Skip to content

Release v0.2.0: docs refresh, viz backend router, vib renderer + cache, telemetry.#15

Merged
NCCU-Schultz-Lab merged 9 commits into
mainfrom
Devs
May 23, 2026
Merged

Release v0.2.0: docs refresh, viz backend router, vib renderer + cache, telemetry.#15
NCCU-Schultz-Lab merged 9 commits into
mainfrom
Devs

Conversation

@NCCU-Schultz-Lab
Copy link
Copy Markdown
Collaborator

[0.2.0] - 2026-05-22

First substantial release after v0.1.0. The codebase moved from a single
monolithic app.py to a modular package, added six PySCF-backed calculation
types end-to-end, introduced a results-persistence layer with history replay,
and shipped a complete visualization stack (3D viewer with selectable backend,
trajectory animation, IR/UV-Vis/PES plots, orbital isosurfaces, vibrational
mode animation with caching). UI runs as a Voilà app suitable for classroom
deployment.

Added

Calculations

  • Geometry optimization (optimizer.py) — ASE-BFGS driver around a custom
    PySCF calculator; per-step trajectory persisted.
  • Vibrational frequency analysis (freq_calc.py) — Hessian via
    pyscf.hessian, ZPVE, thermochemistry (H/S/G at 298 K), IR intensities via
    pyscf.prop.infrared or a numerical-derivative fallback for compatibility
    across PySCF versions.
  • TD-DFT UV-Vis (tddft_calc.py) — excitation energies, oscillator
    strengths, wavelengths; full spectrum plot in the Analysis tab.
  • NMR shielding (nmr_calc.py) — GIAO shielding via pyscf.nmr (core
    preferred over pyscf-properties to dodge a known upstream bug); ¹H/¹³C
    chemical shifts relative to TMS.
  • 1D PES scan (pes_scan.py) — bond / angle / dihedral; energy profile +
    per-step geometry animation.
  • PCM implicit solvent — Water, Ethanol, THF, DMSO, Acetonitrile via a
    single checkbox in the Calculate tab.
  • MP2 post-HF method support.

Analysis & visualization

  • Analysis tab with 8 always-in-DOM panels (Energies, Trajectory,
    Vibrational, IR Spectrum, PES Scan, Isosurface, UV-Vis, NMR) wired through
    a _PANEL_REGISTRY so live runs and history replay share one code path.
  • IR spectrum chart (ir_plot.py) — stick plot + Lorentzian-broadened
    curve; broadening toggle and FWHM slider.
  • UV-Vis spectrum plot — Plotly chart with wavelength/energy axes.
  • Orbital visualization (orbital_visualization.py) — energy-level
    diagram (matplotlib → Plotly HTML) and cube-file isosurface viewer with
    HOMO-1/HOMO/LUMO/LUMO+1 toggle.
  • Trajectory animation — atomic Output-children swap to avoid
    Voilà-deferred-display blank frames; py3Dmol-only render path with
    prev/next arrow navigation.
  • Vibrational mode animation — py3Dmol multi-frame XYZ renderer with
    amplitude scaling, prev/next mode nav, and dropdown skipping near-zero
    modes.
  • 3D visualization backend router (viz_backend_router.py) — pure
    function that picks py3Dmol or plotlymol3d per VizTask based on user
    preference and runtime availability; immutable Decision carries chosen
    backend, fallback, and reason.
  • Lifecycle telemetry_viz_render_event context manager emits
    viz_render_start / viz_render_done / viz_render_error JSONL events
    with backend, task, elapsed_ms, and extras at every render dispatch.
  • Side-by-side Compare tab — pick any two saved calculations and view a
    diff table.

Persistence & logging

  • Results storage (results_storage.py) — every run is saved to a
    timestamped directory containing result.json (schema v2, additive-only),
    pyscf.log, optional trajectory.json / orbitals.npz / thumbnail.png.
  • History tab — browse and replay saved calculations after a kernel
    restart; replay path is identical to live-run analysis activation.
  • Performance log (calc_log.py) — perf_log.jsonl per converged run +
    event_log.jsonl for startup/calc/error events; 7-day auto-prune.
  • Time estimator — 4-strategy priority chain (N_basis-normalised → cross-method
    electron-count) populates "Estimated time" before each run.
  • Benchmark suite (benchmarks.py) — one-click calibration suite to
    populate the time-estimator history with real machine data.
  • Issue tracker (issue_tracker.py) — in-app bug-report UI writing to a
    local issues.db.
  • Persistent user settings (user_settings.py) — stored at
    ~/.quantui/settings.json (override via QUANTUI_SETTINGS_PATH). Schema
    is section-based for additive growth, with atomic writes and graceful
    fallback to defaults on corruption.
  • Vibrational-animation disk cache (vib_cache.py) — per-result-dir
    vib_frames/ of pre-rendered py3Dmol HTML keyed by
    (mode, n_frames, amplitude, renderer, fps). Mode switches on repeat
    visits and history replay are instant.
  • Vib FPS user preferenceviz.vib_framerate_fps exposed as an
    IntSlider in the Status tab (clamped 1–120, default 10); included in the
    vib cache key so changing FPS invalidates cleanly.

UI

  • Modular UI packageapp.py (orchestration) plus app_analysis.py,
    app_builders.py, app_exports.py, app_formatters.py, app_history.py,
    app_runflow.py, app_visualization.py.
  • Seven-tab layout — Calculate, Results, Analysis, History, Compare, Log,
    Status — with a floating Help overlay (not a tab).
  • Light / Dark theme selector — dark by default on startup.
  • Status tab — environment info, performance-history accordion (two-step
    reset), default-3D-backend toggle, vib-FPS slider.
  • Files tab + activity indicator for browsing saved results.
  • Plot export UI — save IR, UV-Vis, PES, orbital diagram plots as HTML.
  • Scroll guard for the run output area to keep long PySCF logs from
    jumping the page.
  • Welcome header, completion banner, structured log header/footer.
  • Compare-tab Copy-path button (replaced a broken Open-folder action).
  • Result directory label + log accordion showing inline pyscf.log.
  • Structure exports — XYZ, MOL/SDF, PDB, plus a standalone runnable .py
    script export.

Tooling & dev

  • Test suite grew from a handful to 1004 passed / 97 skipped (Windows
    quantui-win env baseline; the 97 skips are PySCF-gated Linux-only tests).
  • New analysis-history end-to-end tests for every calc type
    (test_sp_analysis_history.py, test_geo_opt_analysis_history.py,
    test_freq_analysis_history.py, test_tddft_analysis_history.py,
    test_nmr_analysis_history.py, test_pes_scan_analysis_history.py).
  • test_code_quality.py enforces:
    • No include_plotlyjs="cdn" anywhere (fails silently in offline Voilà).
    • No bare except: pass blocks.
  • test_viz_backend_router.py + test_viz_backend_sync.py — full
    task × preference × availability matrix and Calculate/Analysis toggle sync.
  • test_vib_cache.py, test_vib_py3dmol_render.py,
    test_viz_render_telemetry.py — vib animation + telemetry coverage.
  • _layout(...) helper sanitises widgets.Layout kwargs to eliminate a
    4808 → 13 traitlets warning regression.
  • _safe_cb wrapper around every .observe() callback so exceptions surface
    in the Log tab instead of disappearing into the Voilà kernel console.
  • Kernel io_loop is cached at startup; thread-spawned callbacks are queued
    onto the main thread to avoid RuntimeError: no current event loop.
  • Native launchers: launch-native.bat (Windows / WSL) and
    launch-native.command (macOS / Linux) — double-clickable, port 8867,
    stamp-based editable-install skip, browser auto-open. README documents
    pinning each to the Start menu / Dock as a real app.
  • Native JupyterLab launcher (launch-native-jupyter.bat) and Apptainer
    launcher improvements.

Docs

  • .github/copilot-instructions.md — canonical AI-assistant context (now
    the single source of truth for any AI assistant working on this repo).
  • CLAUDE.md — Claude-specific session/workflow context (git-ignored).
  • Site favicons (ICO + SVG) for the GitHub Pages docs site.

Changed

  • Visualization is py3Dmol-first. plotlymol3d remains an optional
    fallback for non-trajectory tasks; trajectory rendering is hard-wired to
    py3Dmol to avoid Plotly/RequireJS flicker.
  • Plotly figures are rendered via plotly.io.to_html(..., include_plotlyjs="require")
    inside widgets.HTML, not display(fig), so threaded renders work and
    offline Voilà loads correctly.
  • pyscf is now an optional extra (pip install quantui[pyscf]); the
    package imports cleanly on Windows with PySCF unavailable.
  • Repo renamed from QuantUI-local to QuantUI.

Fixed

  • Trajectory accordion blank on first expand — switched traj_output
    from Output to VBox and use atomic children-swap so deferred
    widget-display is no longer a blank-frame risk.
  • Vib mode races on rapid switching — render-token guard (_vib_render_token)
    causes stale background renders to bail rather than overwriting newer
    output.
  • Camera state lost on mode switch — JS hook caches the active
    $3Dmol.GLViewer state across atomic HTML swaps; reset only on a
    genuinely new frequency result.
  • PySCF API drift — robust handling for v2 NMR / thermo API and the
    pyscf.prop.infrared rename; both Infrared.kernel() and the older
    IR API are supported.
  • Result-dir name collisions — timestamps now include microseconds; same
    formula + method + basis no longer overwrite each other.
  • IR x-axis — corrected wavenumber axis on the IR Plotly figure.
  • Plotly figures invisible after accordion show — figures are re-rendered
    on accordion expand to handle RequireJS / display-deferral edge cases.

Removed

  • visualization.py (PlotlyMol fallback) — replaced by the router-backed
    visualization_py3dmol.py path.
  • All SLURM-era infrastructure already removed during the downstream port:
    job_manager.py, storage.py, slurm_errors.py, SLURM config templates.

Introduce a pure-function router (quantui.viz_backend_router) that resolves which 3D rendering backend (py3Dmol or plotlymol3d) to use per visualization task based on user preference and runtime availability. Implements VizTask, VizPreference, VizBackend enums, BackendAvailability probe, and an immutable Decision result that includes chosen backend, optional fallback, and a human-readable reason. Encodes a task->(primary,fallback) policy (single-backend tasks ignore preference) and robust fallback logic. Adds exhaustive unit tests (tests/test_viz_backend_router.py) covering the full task × preference × availability matrix, immutability and reason-string requirements.
Introduce a new UserSettings facility to persist user preferences to ~/.quantui/settings.json (overrideable via QUANTUI_SETTINGS_PATH). The settings module provides a small schema (viz section with default_backend), atomic writes, schema-versioning, and robust fallbacks for malformed/missing files. Integrate settings into the app: load settings at startup, snapshot viz backend availability, expose a "Default 3D backend" ToggleButtons control in the Status tab, and persist changes when the user updates the preference. Add comprehensive unit tests covering load/save roundtrips, fallback paths, atomic write semantics, and path-resolution behavior.
Introduce per-task backend routing and sync logic for 3D visualization: resolve_backend/select_backend are used to pick backends per VizTask, and a new _set_viz_preference centralizes preference updates (with optional persistence). Add a sync lock (_viz_sync_in_progress) and an analysis-tab backend toggle + small "Rendering with:" label to keep Calculate/Analysis toggles in parity without observer echo loops. At startup the persisted preference is resolved and widgets are aligned via _initialize_viz_state_from_preference; _rerender_3d_views re-renders visible viewers through the router.

Hard-wire trajectory frame rendering to py3Dmol (update task policy) to avoid Plotly/RequireJS flicker; trajectory rendering now uses router decisions and emits explicit error frames when py3Dmol is unavailable. Implement atomic HTML swaps for frame output to eliminate layout flashes, add prev/next arrow navigation, fix frame_out sizing, and improve py3Dmol/plotlymol fallbacks in trajectory playback.

Refactor show_result_3d to call the router per output/task and track the analysis-displayed molecule so toggling backends can re-render the Analysis viewer. Update viz_backend_router policy (TRAJECTORY_FRAME -> py3Dmol-only) and extend tests: adjust existing router tests and add comprehensive tests (tests/test_viz_backend_sync.py) for toggle parity, sync behaviour, startup preference application, and router-driven rendering.
Replace traj_output Output with a VBox and switch to manipulating children atomically to avoid deferred/asynchronous widget display that left the Trajectory accordion empty. Add a safety-net cache (_last_traj_result) set by trajectory-populators and cleared on context reset so on_traj_expand can recover when a prior auto-render consumed _pending_traj_result. Update on_traj_expand to detect empty children, restore from cache, show a loading placeholder via children, and log recovery/metrics. Update show_opt_trajectory to build Plotly HTML into an Output.outputs entry and set traj_output.children = (energy_holder, panel) to ensure scripts execute and avoid the stale-empty UI. Minor related updates: clear traj_output by resetting children and set _last_traj_result alongside _pending_traj_result in pop_* trajectory helpers.
Introduce a py3Dmol-based vibrational animation path and resilient backend dispatch while keeping plotlymol3d optional. show_vib_animation now builds dropdown options from raw frequencies (skipping near-zero modes), treats vib_data as optional, and caches the Frequency result in _last_vib_freq_result. Added _vib_err for consistent user-facing errors, _render_vib_mode_py3dmol to generate 24-frame sinusoidal multi-frame XYZ payloads and atomically swap HTML into app.vib_output, and _render_vib_mode_plotlymol for the existing plotlymol3d flow. render_vib_mode now dispatches via the viz backend router (py3Dmol preferred, plotlymol3d fallback) and logging events were enriched. on_vib_mode_changed updated to allow py3Dmol rendering when vib_data is None. Added comprehensive tests (tests/test_vib_py3dmol_render.py) covering py3Dmol rendering, frame count, amplitude scaling, error handling, and backend dispatch.
Add a persistent vibrational-animation framerate preference and robust caching/staleness protections.

- Introduce viz.vib_framerate_fps in user settings with validation and sane defaults.
- Add an IntSlider in the Status panel to control and persist the vib FPS.
- Add app._vib_render_token and wire render_token through vib rendering paths so older background renders bail out and cannot overwrite newer outputs.
- Implement atomic output swaps via _swap_vib_output to avoid transient empty states and layout reflow.
- Wire fps into py3Dmol animate interval and include fps in the vib cache key.
- Add quantui.vib_cache module to save/load per-result-directory HTML blobs (index.json + mode_NNN.html), with atomic writes, parameter matching (n_frames, amplitude, renderer, fps), tolerance for floating amplitude, and graceful error handling.
- Update vib render functions to accept fps and render_token, consult user settings when fps is not provided, check cache hits and persist cache on render success.
- Update and add tests: user settings tests for vib framerate, comprehensive vib_cache unit tests, and integration/tests for rendering token staleness and fps behavior.

These changes improve UX by enabling configurable playback speed, eliminating stale-render races on rapid mode switches, and making repeated visits/history playback instant via on-disk caching.
Add prev/next buttons and fixed-size output for vibrational viewer; wire up observers and click handlers in QuantUIApp to enable one-step mode navigation and avoid layout flicker. Introduce a synchronous vib-cache-hit fast path to swap cached py3Dmol HTML without showing a transient "Rendering…" placeholder, and ensure the vib wrapper accepts render_token kwargs to avoid silent thread TypeErrors. Implement camera-persistence JS and a reset hook so interactive camera/view is preserved across mode switches (but reset when a new frequency result loads). Add a _viz_render_event context manager to emit lifecycle telemetry (viz_render_start / viz_render_done / viz_render_error) for render operations and wrap vib/trajectory/structure renders to log backend, task, elapsed time and extras. Harden error handling so telemetry is logged while user-facing errors are shown but worker threads don't crash. Include new unit tests for telemetry and the render_token wrapper, and small adjustments to vib/plotlymol/py3dmol render flows to integrate these features.
Add release artifacts and documentation for v0.2.0: add CHANGELOG.md, bump package version (pyproject.toml and quantui.__version__), and expand README/docs with new features, launch instructions, and updated test baseline. Introduce launch-native.command (macOS launcher) and update .gitattributes to enforce LF for .command files. Enrich .github/copilot-instructions.md with modular UI layout, viz backend router, user settings, vib cache, telemetry, and other developer notes. Update packaging metadata (keywords/classifiers) and site copy (docs/index.html) to reflect the new modular UI and capabilities.
Provide a compatibility shim for enum.StrEnum when running on Python <3.11: import sys and Enum, and define a StrEnum subclass that preserves StrEnum behavior (members compare equal to strings and stringify to their value). This keeps the VizTask enum implementation working on supported Python 3.9/3.10 environments while using the stdlib StrEnum on 3.11+.
@NCCU-Schultz-Lab NCCU-Schultz-Lab merged commit f722fd7 into main May 23, 2026
4 checks passed
@NCCU-Schultz-Lab NCCU-Schultz-Lab deleted the Devs branch May 23, 2026 02:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant