Repository navigation
ENSDF Isotope Identification
python-cmat includes a dedicated, fully offline nuclear structure search and automated isotope identification engine powered by the complete Evaluated Nuclear Structure Data File (ENSDF) database.
The system connects the experimental photopeak and coincidence fit results generated during 1D and 2D spectroscopy to known nuclear level schemes, decay modes, and transition cascades across all 300+ mass chains (
-
100% Offline Local SQLite Database (
ensdf.db):- Indexed SQLite database holding over 3,400 nuclides, 18,000 datasets, 175,000 nuclear levels, and 330,000 evaluated
$\gamma$ -ray transitions. - Sub-millisecond indexed lookups by energy range, mass number
$A$ , element$Z$ , dataset type (Decay, Adopted, Reaction), and parent half-life$T_{1/2}$ .
- Indexed SQLite database holding over 3,400 nuclides, 18,000 datasets, 175,000 nuclear levels, and 330,000 evaluated
-
Physical 2D Coincidence Cascade Matching:
- Classifies 2D
$\gamma$ -$\gamma$ coincidence pairs into physical topologies:-
Direct Prompt Cascades (
$L_A \xrightarrow{\gamma_1} L_B \xrightarrow{\gamma_2} L_C$ ): Receives the highest confidence weight ($10\times$ boost). -
Sequential Cascades: Multi-step cascades separated by intermediate transitions, scaled inversely with intermediate energy gap
$\Delta E_{\text{gap}}$ . -
High Excitation Energy Damping: Penalizes coincidences originating from high excitation/resonance states (
$E_{\text{exc}} \gg 3000\text{ keV}$ ).
-
Direct Prompt Cascades (
- Classifies 2D
-
Global Parsimony & Mass-Clustering Optimization:
-
2D Anchoring: High-confidence 2D coincidences establish dominant reaction/decay products and calculate the dominant mass center
$\bar{A}$ . -
Mass Proximity Constraint: Prefers candidates with mass close to the dominant experiment cluster (
$\Delta A \le 6-8$ mass units), damping distant isolated masses. -
Parsimonious Minimal Isotope Set Cover: Solves for the smallest set of distinct #1 isotopes (
$S = {^{51}\text{Cr}, ^{52}\text{Cr}, ^{48}\text{Ti}, ^{55}\text{V}}$ ) that collectively explains all 1D photopeaks and 2D coincidences.
-
2D Anchoring: High-confidence 2D coincidences establish dominant reaction/decay products and calculate the dominant mass center
-
Standalone Web Pop-up & Server File Browser:
- Opens as an independent pop-up tool from both the 2D (
cmat_webviewer) and 3D (cmat3d_webviewer) web interfaces. - Built-in interactive server filesystem browser (
📂 Browse...) with breadcrumbs, directory navigation, and fit log search. - Expandable Top 5 Candidate Isotopes breakdown for each 2D coincidence fit.
- Opens as an independent pop-up tool from both the 2D (
The Gaussian probability of energy agreement given user tolerance
-
Direct Cascade (
$|E(f_1) - E(i_2)| < 2.5\text{ keV}$ or$|E(f_2) - E(i_1)| < 2.5\text{ keV}$ ):$$W_{\text{topo}} = 10.0, \quad \Delta E_{\text{gap}} = 0\text{ keV}$$ -
Sequential Cascade (
$E(f_1) > E(i_2)$ or $E(f_2) > E(i_1)$):$$W_{\text{topo}} = \frac{4.0}{1.0 + \Delta E_{\text{gap}} / 600\text{ keV}}$$ -
Branching / Common Feeding:
$$W_{\text{topo}} = \frac{1.2}{1.0 + \Delta E_{\text{gap}} / 1200\text{ keV}}$$
Transitions originating from low-lying states (
Given the dominant mass center
If a candidate isotope
The identification pop-up (ensdf_popup.html) can be launched directly from the top navigation bar of both cmat_webviewer and cmat3d_webviewer via the 🔬 Isotope Identification button or at URL /ensdf_popup.html.
-
Server File Browser (
📂 Browse...): Interactively navigate server directories, search for log files (fit_results_*.txt), and inspect file size/modification dates. -
2D Coincidence Results Table: Shows the primary #1 match with colored cascade badges (
Direct Cascade (Prompt Coincidence),Sequential Cascade,Same Level Scheme), excitation levels, and energy differences. -
Expandable Top 5 Candidates: Clicking
▼ Top N Candidateson any row expands an inner sub-table detailing the top 5 candidate isotopes with confidence scores. -
1D Photopeaks Table: Displays net area, assigned candidate isotope, parent
$T_{1/2}$ , dataset source, ENSDF transition energy, and energy difference. -
Constraint Filters:
- Mass range:
$A_{\text{min}} \le A \le A_{\text{max}}$ - Specific elements: e.g.
Cr Ti V Fe Ni - Parent half-life: Minimum and maximum parent
$T_{1/2}$ (e.g.1m,1h,1d,1y) - Dataset type:
All,Decay Schemes Only,Adopted Levels Only,Reactions / In-Beam - Energy search tolerance:
$\pm\text{keV}$ (default:$1.5\text{ keV}$ )
- Mass range:
- Export: Export identified 1D and 2D results as clean tab-separated text files.
ensdf_search.py can be used directly from the command line for automated scripting and terminal inspection.
# Automatically identify all 1D photopeaks and 2D coincidences in a log file
python3 ensdf_search.py fit_results_20260922_155405.txt
# Specify energy tolerance and list top 5 candidate isotopes
python3 ensdf_search.py fit_results_20260922_155405.txt --tol 1.5 --top 5
# Apply mass and half-life constraints
python3 ensdf_search.py fit_results_20260922_155405.txt --a-min 48 --a-max 56 --min-t12 1m# Search for coincidence pair E1=1434.2 keV, E2=935.3 keV
python3 ensdf_search.py -c 1434.2 935.3 --tol 1.5 --top 5# Search for single photopeak E=1480.3 keV
python3 ensdf_search.py -g 1480.3 --tol 1.5python3 ensdf_search.py --statusTo build or update the local database from a raw ENSDF mass directory (e.g. ensdf_260901/):
python3 ensdf_search.py --build-db /path/to/ensdf_directory/In fusion–evaporation and transfer experiments the candidate isotope space can be
constrained by declaring the likely reaction channels. This replaces the inferred
mass-clustering prior with a declared reaction prior: in-channel candidates are
scaled by their channel weight, off-channel ones are demoted (score × 0.05) but
never hidden (unless --strict).
# Example: 100Mo(18O,xn) with a 181Ta stopper — stopper cascades rank correctly
python3 ensdf_search.py fit_results.txt --reaction "100Mo(18O,16O)102Mo; 181Ta(18O,xn); 181Ta"
# Include decay-chain daughters (2 generations) and hard-whitelist mode
python3 ensdf_search.py fit_results.txt --reaction "100Mo(18O,16O)102Mo" --decay-depth 2 --strict
# Channels from a file (one channel/isotope per line, or a 'Z A [weight]' table)
python3 ensdf_search.py fit_results.txt --channels channels.txt --decay-onlySpec syntax (also used in the web pop-up "⚗️ Reaction Definition" card):
-
target(beam,ejectile)residue— residue optional; verified/completed by A/Z conservation (e.g.100Mo(18O,16O)→ 102Mo) -
target(beam,xn)— wildcard multiplicity, expands to n…4n - standalone isotopes (
181Ta) for stopper/coulomb-excitation contributions - optional weight:
w=0.5;#lines are comments - weights are relative cross-section proxies; daughters inherit the parent weight damped by 0.9 per decay generation
Coulomb excitation of beam-line materials happens in essentially every run — independent of the beam+target reaction. The identification therefore carries a built-in coulex prior: candidates that are naturally-abundant (≥ 0.5%) stable isotopes of the common auxiliary materials (181Ta stopper, 197Au backing, nat Ti/C/Fe/Mg, 27Al, 16O oxide layers, 19F/Teflon, plastics) are exempt from the dominant-mass-clustering factor when they lie outside the ±8 mass-cluster window, and instead carry a coulex prior weight (score × 1.3). Inside the cluster nothing changes, so line-dense stable isotopes cannot steal in-cluster matches, and the dominant mass keeps reflecting the reaction products.
- In an unconstrained run this fixes the classic failure mode: the strong 181Ta stopper lines are attributed to 181Ta (badge ⚡ coulex · 181Ta) instead of being pulled into a line-dense isotope near the dominant mass.
- With declared channels (soft mode, non-strict), off-channel coulex-likely
candidates get a milder penalty (×0.4 instead of ×0.05) — no need to remember
to declare the Ta stopper.
--strictis unaffected. - Coulex-attributed candidates are highlighted with a ⚡ badge in the pop-up
(and
⚡coulex(...)markers in the CLI report); the pop-up summary lists them under "⚡ coulex".
Tunables: COULEX_MASS_FACTOR, COULEX_PRIOR_FACTOR,
COULEX_OFFCHANNEL_COULEX_FACTOR, COULEX_WINDOW, COULEX_MIN_ABUNDANCE.
You can also use the ENSDFSearchEngine directly in Python scripts or Jupyter notebooks:
from ensdf_search import ENSDFSearchEngine
engine = ENSDFSearchEngine()
# 1. Search 2D coincidence pair
cands_2d = engine.search_2d(
energy1=1434.15,
energy2=935.26,
tol1=1.5,
tol2=1.5,
limit=5,
unique_nuclides=True
)
for c in cands_2d:
print(f"{c['nuclide']}: Score={c['score']}, {c['cascade_type']}, Levels: {c['level1_init']}->{c['level1_final']}")
# 2. Identify entire fit results log file with global parsimony
report = engine.identify_fit_results_file("fit_results_20260922_155405.txt", tol=1.5)
print(f"Dominant Mass: A ≈ {report['dominant_mass']}")
print(f"Minimal Isotope Set: {report['parsimonious_isotopes']}")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