Repository navigation
Interactive Web Viewer
The cmat_webviewer.py server and companion cmat_webviewer.html client provide an ultra-responsive, browser-based GUI for exploring 2D matrices in the .cmat format and conducting nuclear physics data analysis.
While the viewer functions as a high-performance visualizer for arbitrary 2D .cmat datasets, it features dedicated subroutines tailored for
ROOT support: This viewer can also display TH1/TH2 histograms from local ROOT files (
./pycmat file.root) and stream live histograms from ROOTTHttpServer/ c4Root (--live-server,--live). See ROOT Files & Live Histograms.
Run the server script from your terminal, pointing to one or more .cmat files:
# Open a single matrix
python cmat_webviewer.py /path/to/matrix.cmat
# Open multiple matrices
python cmat_webviewer.py run01.cmat run02.cmat run03.cmat
# Load all matrices in a folder
python cmat_webviewer.py ./data/*.cmatThe server binds to http://0.0.0.0:8080 (or the configured host/port) and automatically launches your default web browser.
When running inside WSL on Windows, launching native GUI applications via X11 can cause window-grab issues and slow rendering. cmat_webviewer leverages your host Windows browser directly for full hardware-accelerated WebGL/Canvas rendering.
Browser launching from WSL works out of the box: the viewer detects WSL automatically and opens the page with your default Windows browser (cmd.exe /c start fallback), so no configuration is required.
Optionally, install wslu for native WSL→Windows integration:
sudo apt update && sudo apt install wsluThe viewer picks up wslview automatically when present and uses it as the preferred launcher.
When analyzing data stored on a remote Linux workstation or cluster via SSH:
The viewer prints the server's network address in the terminal upon startup (e.g. http://192.168.1.50:8080). Modern terminals (VS Code, Windows Terminal, iTerm2, GNOME Terminal) allow you to Ctrl+Click (or Cmd+Click on macOS) the URL to open the remote session in your local browser immediately.
When running inside an SSH session (detected via $SSH_CLIENT / $SSH_TTY), cmat_webviewer.py automatically suppresses launching headless or remote X11 browsers, keeping the SSH connection fast and lightweight.
If the remote machine is behind a firewall or lacks direct port exposure:
# Forward remote port 8080 to your local machine:
ssh -L 8080:localhost:8080 user@remote-server
# Run the viewer on the remote machine:
python3 cmat_webviewer.py matrix.cmatThen open http://localhost:8080 in your local browser.
- Renders matrices up to
$6144 \times 6144$ channels effortlessly by fetching only as many data points as screen pixels available. - 2D Max-Pooling: When zoomed out over large channel ranges, downsampling uses maximum-intensity pooling rather than naive averaging or nearest-neighbor interpolation. This ensures sharp, narrow gamma photopeaks never disappear at full zoom.
- Direct scale options: Logarithmic, Linear, and Power (
$\sqrt{N}$ ) scaling with real-time colormap mapping (Turbo, Viridis, Plasma, Inferno, Hot, Jet, Gray).
- Det 1 (X Projection): Slices the 2D matrix along the visible Y-window, showing total or gated counts vs. Det 1 energy.
- Det 2 (Y Projection): Slices the 2D matrix along the visible X-window, showing total or gated counts vs. Det 2 energy.
- Synchronized crosshair cursors: Moving the mouse in the 2D matrix updates highlighted crosshairs and channel/energy readouts simultaneously across both 1D panels.
- Stepped staircase rendering with dynamic Y-axis auto-scaling, calibrated keV readouts, and ASCII
.datexport.
- Press
M(or click theMenutoggle) to collapse the left control panel, maximizing matrix visualization space. - An interactive vertical divider bar allows click-and-drag resizing between the 2D matrix canvas and the 1D projection histograms (double-click the divider to reset to equal width).
Keyboard arrow keys automatically route actions based on which panel is under cursor focus:
-
1D Spectrum Focus:
-
←/→pans channels horizontally (Shiftfor 2× speed). -
↑/↓pans and magnifies the vertical counts scale.
-
-
2D Matrix Focus:
-
←/→/↓/↑sets Left, Right, Down, and Up limit markers at the crosshair. -
Shift + Arrowspans the 2D view.
-
Open multiple matrices simultaneously to perform comparative spectroscopy:
-
Instant Switching: Cycle between loaded matrices using the header dropdown or the
[and]bracket keys. -
Analysis State Locking: Switching matrices preserves:
- Viewport coordinates and zoom ranges
- Active coincidence gates (
$W$ ) and background subtractions ($X$ ), which are instantly re-evaluated against the new matrix - Active 1D single-peak and multiplet fits (automatically refitted with updated areas and FWHMs)
- Active 2D coincidence peak fits (refitted at identical coincidence coordinates)
- Visual contrast settings (
$V_{\max}$ ,$V_{\min}$ , colormap, scale mode)
Click 📂 Browse Server Matrices... in the header (or press Ctrl + O) to open the server-side file browser modal. You can navigate the remote directory structure, view file sizes and timestamps, filter files by keyword, and load .cmat matrices directly without typing paths.
Click Print PDF on the 2D matrix footer or either 1D projection header:
- Outputs standalone, vector PDFs rendered with classic publication typography (Times New Roman).
- Embeds energy-calibrated axes, stepped histogram paths, all active continuous fit curves, background baselines, labeled centroid pointers, 2D FWHM confidence ellipses, and unobtrusive 3-line fit summary labels.
For irregular or curve-shaped features on the 2D coincidence matrix (e.g. bananas, Doppler-shifted diagonal ridges, or non-rectangular regions of interest), cmat_webviewer provides interactive polygonal ROI drawing with area-normalized background subtraction and terminal reporting:
-
Draw Peak Banana (W): Move the cursor over the 2D matrix and press
ato start drawing and add the first Peak ROI vertex (rendered in gold#ffd600); each furtherapress adds a vertex at the cursor position. The polygon auto-closes (the last vertex connects back to the first) — pressEnterto apply the ROI. Mouse click-drag zoom/pan keeps working while drawing. -
Draw Background Banana (B): Press
bwith the cursor over the 2D matrix to add Background ROI vertices (rendered in magenta#ff4081) the same way; pressEnterto apply. Over a 1D spectrum,bstill sets the background region for fits. -
Area-Normalized Subtraction:
- Exact discrete pixel containment (
$N_{\text{px}}$ ) and continuous geometric Shoelace area ($A\ \text{ch}^2$ ) are calculated for both polygons. - Scale factor: $\text{Scale} = \text{Area}{\text{peak}} / \text{Area}{\text{bg}}$.
- Net Area Counts:
$$\text{Net Counts} = C_{\text{peak}} - \text{Scale} \times C_{\text{bg}} \quad \pm \quad \sqrt{C_{\text{peak}} + \text{Scale}^2 \times C_{\text{bg}}}$$
- Exact discrete pixel containment (
-
Real-Time Readout & Diagnostics:
- A persistent top badge overlay on the 2D matrix and the sidebar card display live vertex counts, surface area (
$\text{ch}^2$ ), discrete pixel count, raw counts, scale factor, and net background-subtracted counts. - A formatted diagnostic summary is automatically printed to the terminal console whenever a banana ROI is closed or when switching between matrices:
================================================================================ [2D Banana ROI Analysis] GeE-symm.cmat (4096 x 4096) -------------------------------------------------------------------------------- • Peak Banana (W): 1,250 px (area: 1250.0 ch², 5 vertices) | Counts: 345,210 cts • Bg Banana (B): 2,500 px (area: 2500.0 ch², 4 vertices) | Counts: 110,400 cts (Scale factor: 0.5000) -------------------------------------------------------------------------------- => Net Area Counts: 290,010.0 ± 608.2 cts ================================================================================
- A persistent top badge overlay on the 2D matrix and the sidebar card display live vertex counts, surface area (
-
Clear Banana ROIs: Press
Z(or click Clear Bananas) to remove both peak and background polygons and reset the display. -
Banana Save Files (
.ban): Bananas are saved to the server working directory only on demand: click Save Banana in the sidebar or presswwith the cursor over the 2D matrix. Files are namedp<E1>-<E2>.ban(peak) /b<E1>-<E2>.ban(background), whereE1/E2are the calibrated x/y centroid coordinates of the polygon as integers (channels if uncalibrated). Each file lists onex yvertex pair per line in matrix channel coordinates. To keep peak/background pairs associated, a background file reuses the coordinates of the most recently saved peak: the first background saved after a peak becomesb<E1>-<E2>.ban, and each additional one gets an incrementing index (b<E1>-<E2>_2.ban,_3.ban, …) until a new peak is saved. If no peak has been saved yet, the background file uses its own centroid coordinates. -
Manual Save / Load: The sidebar Save Banana button saves the drawn polygon(s) as
.banfile(s) with the same format and naming as the automatic save, in the server working directory. The Load Banana button opens a server-side file browser (starting in the server working directory) to pick a.banfile from the server filesystem: the type is auto-recognized from the header (Peak/Background) and the polygon is loaded and applied immediately. -
Result Logging: When fit results logging is enabled (
fit_log on [filename]in the terminal, or the sidebar toggle), the gross peak area and the net background-subtracted area (± error) of every applied banana are appended to the results.txtfile. -
Matrix Cycling: Banana ROIs are re-applied automatically when the active matrix is switched (
[/]or the matrix dropdown): the diagnostic summary is re-printed for the new matrix and the on-screen badge/sidebar readout is refreshed. If the new matrix has different dimensions, the bananas are cleared with a notification.
Press P while focusing the 2D matrix (or click Find 2D Peaks [P] in the 2D matrix footer or Sidebar Section 4.3):
-
4-Stage Hybrid Search Engine:
-
Projection Seeding: Performs multi-scale CWT peak search on both Det 1 and Det 2 projections to generate candidate coordinate pairs
$(x_i, y_j)$ . -
Local Gamba 4-Component Decomposition: Fits each candidate subregion to separate true coincidence volume (
$p|p^t$ ) from vertical ridges ($p|bg$ ), horizontal ridges ($bg|p$ ), and continuum ($bg|bg$ ). -
Compton Scattering Ridge & Cross-Talk Rejection: Automatically rejects 1D single-gamma Compton cross-ridges (where
$\Pi = n_{p|p}^t / n_{p|p}^m \le \text{threshold}$ ) and detector cross-talk diagonal artifacts ($\rho_{xy} \approx -1$ ). -
Non-Maximum Suppression (NMS) & Levenberg-Marquardt Fit: Eliminates redundant split fits and refines coincidence centroids, widths (
$\text{FWHM}_X, \text{FWHM}_Y$ ), and net volume.
-
Projection Seeding: Performs multi-scale CWT peak search on both Det 1 and Det 2 projections to generate candidate coordinate pairs
-
Configurable Sensitivity: Adjust Min Peak SNR (1.5–20.0) and Min Gamba
$\Pi$ Ratio (0.01–0.90) sliders in Sidebar Section 4.3 to tune sensitivity for weak transitions vs. noisy matrices. -
Collision-Free, Zoom-Adaptive 2D Labels:
- At wide zoom levels, clean crosshair markers and FWHM ellipses are shown to keep the view uncluttered.
- As you zoom into coincidence regions, text labels (
$E_X \times E_Y$ , net counts) smoothly appear using dynamic bounding box collision avoidance. - Hovering any peak marker instantly brings its full energy label and summary badge to the foreground.
-
Automated Logging: When
📝 Log Fits: ONis enabled, all detected 2D coincidence fits are automatically saved tofit_results_<timestamp>.txt. -
Terminal Report: A structured summary table with energies, net volume, Gamba areas, FWHMs,
$\chi^2$ , and peak-to-background ratios is printed directly to the terminal.
- Toggleable via the
📝 Log Fits: ON/OFFUI button in the viewer header, the--fit-logstartup flag, or thefit_log [on|off]macro command. - Each 1D photopeak or 2D coincidence fit (both manual
Ctrl+Click/Vand automaticPin 2D /Hin 1D) is cleanly appended as a single fixed-width, right-aligned row intofit_results_<timestamp>.txtin the server directory. - Accommodates 10+ digit area counts and error bars with perfect column alignment:
-
1D Fits:
Energy(err),Net_Area(err),FWHM(err),Chi2,Peak_to_BG -
2D Fits:
Energy1(err),Energy2(err),Net_Area(err),Gamba_Area(err),FWHM1(err),FWHM2(err),Chi2,Peak_to_BG
-
1D Fits:
Click 🔬 Isotope Identification in the header to launch the standalone nuclear structure search window (/ensdf_popup.html):
-
Server File Browser (
📂 Browse...): Interactively search and select anyfit_results_*.txtlog file on the server. -
Top 5 Candidate Isotopes: For each 2D coincidence fit, displays the top physical cascade matches with colored badges (
Direct Cascade (Prompt Coincidence),Sequential Cascade,Same Level Scheme) and expandable sub-tables. -
Global Parsimony & Mass-Clustering: Automatically clusters isotopes by dominant reaction/decay mass (
$\bar{A}$ ) and finds the minimal set of isotopes explaining all 1D and 2D features. - See ENSDF Isotope Identification for full theory and algorithms.
Each 1D projection header has its own ⏱️ Half-Life Fit button. The button is explicitly linked to its histogram, so it does not depend on which panel the pointer happens to be over:
- Det 1 / X: opens the lifetime popup with the current X histogram.
- Det 2 / Y: opens the lifetime popup with the current Y histogram.
The popup requests a same-origin snapshot of the exact currently displayed 1D bins. In Synced with 2D Window Zoom mode, only the visible X/Y range is transferred; in Full 0..4095 Range mode, the complete current projection is transferred. Gated/coincidence-cut counts and calibration metadata are preserved.
Use 📥 Pull from WebViewer whenever the matrix, visible region, gates, or projection has changed. It requests a fresh snapshot rather than reusing the spectrum loaded when the popup was first opened.
The Half-Life plot provides mouse-wheel Y zoom, Shift + wheel X zoom, drag-to-zoom, middle-button pan, and double-click reset. Fit bounds stay synchronized to the visible X range. Enable ⇄ Mirror Spectrum for reversed time spectra before fitting. Press L/l to toggle the popup display between linear and logarithmic Y scales.
The lifetime fit is nonnegative (t₁/₂ ≥ 0). Background is free by default and initialized from the late-time tail of the current fit range; it can be fixed manually or explored with the background scan.
python-cmat © 2026. Released under the MIT License. Return to GitHub Repository
Interactive 2D & 3D Matrix Analysis & Spectroscopy
- Home
- Interactive Web Viewer
- 3D Matrix Analysis & Web Viewer
- Keyboard Shortcuts & Controls
- ROOT Files & Live Histograms
- ENSDF Isotope Identification
- Spectroscopy Commands & Macros
- Configuration Guide
- Python API & CLI Tools