RIPL-3¶
RIPL-3 is the IAEA’s Reference Input Parameter Library — the input side of nuclear reaction modelling: discrete levels, masses, resonance spacings, level densities, gamma strength, optical potentials, fission barriers. Cite it as R. Capote et al., Nucl. Data Sheets 110 (2009) 3107; the discrete-levels segment used here is the 2021 cut.
Unlike the other two backends, RIPL-3 is static — no API, no releases to track — so the whole library is mirrored into the repository and parsed from disk.
The mirror¶
python tools/fetch_ripl3.py --record # first population: download + hash
python tools/fetch_ripl3.py --verify # offline integrity check
python tools/fetch_ripl3.py --refresh levels # re-pull one segment
The mirror lives at data/ripl3/<segment>/ (~1.2 GB extracted, excluded from
wheels and sdists); data/ripl3/MANIFEST.json records a sha256 for every
extracted file. Downloads resume; archives are transient under
data/ripl3/_archives/ (gitignored). A wheel install has no mirror — point
$RIPL_PATH at one instead.
One index link is dead upstream: masses/gs-deformations-exp.dat 404s (as of
2026-07) and is deliberately absent; theoretical deformations are still in
mass-frdm95.dat.
Units¶
RIPL files are in MeV; everything here converts to keV at parse time so
levels line up with the ENSDF backends. Exceptions keep their natural unit and
say so in the name (gamma_width_mev_milli, bn_mev, barrier heights in MeV).
nook.sources.ripl3.RIPL3_UNITS is the full mapping, and
RIPL3_EVALUATIONS the attribution. One normalisation to know about: the EGSM
level-density file ships D0 in keV while bfm/ctm/hfm ship eV — all four are
served as spacing_kev.
Levels¶
RIPL levels derive from ENSDF, repackaged per element with two extras worth
having: the evaluator’s completeness cutoff Nmax (how far the scheme can be
trusted to be complete) and a numeric spin for every level, flagged when it
was estimated rather than measured.
import nook
scheme = nook.level_scheme("24Mg", source="ripl3") # a normal LevelScheme
block = nook.Ripl3Source().levels("24Mg") # raw counts + cutoffs
nook.Ripl3Source().fetch("24Mg", up_to_nmax=True) # truncate at Nmax
up_to_nmax is RIPL’s own judgement; scheme.complete_up_to() is our
heuristic. Comparing the two is the point of nook.compare.
The other segments¶
All through Ripl3Source (each returns frozen dataclasses; --json on the
CLI):
src = nook.Ripl3Source()
src.masses("24Mg") # Audi + FRDM95 + HFB-14 mass excesses, β2, abundance
src.mass_table() # the same for every nuclide, keyed (z, a)
src.ground_state("24Mg") # projected onto the shared GroundState model
src.matter_density("208Pb") # HFB-14 radial matter density
src.resonances("27Al", wave=0) # D0, S0, Γγ for the *target* nuclide
src.resonance_table(wave=0) # every target's parameters, keyed (z, a)
src.gdr("181Ta") # GDR Lorentzians, experimental fits then theory
src.gsf("56Fe") # HFB+QRPA E1 strength table
src.fission_barriers("238U") # empirical (or model="hfb")
src.optical_potentials(nuclide="56Fe", projectile="n", energy_mev=14.0)
src.deformations("12C") # coupled-channel deformation parameters
src.level_density_params("57Fe") # analytic models: egsm, bfm, ctm, hfm
src.hfb_density("57Fe") # ρ(E, J, π) table with .rho() lookup
src.levels_param() # constant-temperature fit table, every nuclide
src.sn_table() # S(n) from every levels header, keyed (z, a)
Most of these have a figure in the gallery: GDR fits, strength functions, level densities against the discrete staircase, matter densities, fission barriers, mass-model residual and deformation charts, and resonance systematics — all drawn from the mirror, no external data needed.
Two conventions that look like bugs but are not:
Density and resonance-derived quantities are keyed by the compound nucleus. The level-density row for the n+56Fe system is
57Fe, not56Fe. Resonances are the exception — they’re filed under the target.Optical potentials are records, not potentials. The archive’s energy-dependent coefficient tables are parsed in full, but nothing here evaluates V(r); that’s a reaction code’s job.
Comparison¶
Where sources overlap, nook.compare matches them: greedy one-to-one
nearest-neighbour for levels (within max(tolerance, 3σ)), keyed evaluations
for masses.
result = nook.compare.levels("24Mg", sources=("file", "ripl3"))
result.rms_delta_kev, result.jpi_agreement_fraction
result.only_a, result.only_b # levels one source dropped
result.cutoff_a, result.cutoff_b # heuristic complete_up_to vs RIPL's Nmax
nook.compare.masses("180Ta") # ame-livechart / ripl-exp / frdm95 / hfb14
Because RIPL levels derive from ENSDF and the two parsing chains share no
code, a low-lying comparison doubles as an end-to-end test — that’s
tests/test_compare.py::test_compare_24mg_ripl_vs_ensdf_adopted_matches_low_lying.
plot_level_comparison draws the same object — matched levels joined across
the gutter, both completeness cutoffs as hairlines
(figure):

CLI¶
nook levels 24Mg --source ripl3 --nmax
nook ripl masses 24Mg
nook ripl resonances 27Al --wave 0
nook ripl gdr 181Ta
nook ripl fission 238U --model hfb
nook compare 24Mg --what levels --below 8000
nook compare 180Ta --what masses --no-livechart