From 8e4703e7eaeb2b2ca376268527dd4e57e45cc0fc Mon Sep 17 00:00:00 2001 From: Paul Kienzle Date: Tue, 23 Dec 2025 18:45:54 -0500 Subject: [PATCH 1/2] Use NUBASE2020 for half-life data --- ChangeLog.rst | 8 + doc/sphinx/guide/data_sources.rst | 15 +- explore/nubase.py | 335 +++++++++++++++++++++++ periodictable/activation.py | 438 ++++++++++++++++++++++++++++-- test/test_activation.py | 26 +- 5 files changed, 787 insertions(+), 35 deletions(-) create mode 100644 explore/nubase.py diff --git a/ChangeLog.rst b/ChangeLog.rst index 5285d43..ff7e060 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -23,6 +23,14 @@ Known issues Change history ============== +2026-01-xx R2.1.0 +----------------- + +Modified: + +* Use NUBASE2020 for half-life values in activation. The following change by 20% or more: + 32Si, 38Clm, 41Ca, 79Se, 97Tc, 108Ag, 121Snm, 126Sn, 135Cs, 157Tb, 177Lum + 2024-12-19 R2.0.2 ----------------- diff --git a/doc/sphinx/guide/data_sources.rst b/doc/sphinx/guide/data_sources.rst index d15e1e6..1dae28f 100644 --- a/doc/sphinx/guide/data_sources.rst +++ b/doc/sphinx/guide/data_sources.rst @@ -5,7 +5,7 @@ Data Sources ************ Physical constants - `NIST Physics Laboratory - Constants, units and uncertainty `_ + `NIST Physics Laboratory - Constants, units and uncertainty `_ Isotope mass `IAEA Atomic Mass Data Center AME2020 `_ @@ -17,7 +17,7 @@ Atomic density *ILL Neutron Data Booklet* Covalent Radii - Cordero, et al., Dalton Trans., 2008, 2832-2838, `doi:10.1039/801115j `_ + Cordero, et al., Dalton Trans., 2008, 2832-2838, `doi:10.1039/801115j `_ Magnetic form factors Brown. P. J., In *International Tables for Crystallography, Volume C*, Wilson. A. J. C (ed), section 4.4.5 @@ -26,15 +26,22 @@ Neutron scattering factors `Atomic Institute for Austrian Universities `_ X-ray scattering factors - `Center for X-Ray Optics `_ + `Center for X-Ray Optics `_ Neutron activation - `IAEA (1987) Handbook on Nuclear Activation Data. TR 273 (International Atomic Energy Agency, Vienna, Austria, 1987). `_ + `IAEA (1987) Handbook on Nuclear Activation Data. TR 273 (International Atomic Energy Agency, Vienna, Austria, 1987). `_ Shleien, B., Slaback, L.A., Birky, B.K., (1998). *Handbook of health physics and radiological health*. Williams & Wilkins, Baltimore. +Isotope half-life + `NUBASE2020 `_ + + Kondev, F.G.; Wang, M.; Huang, W.J.; Naimi, S. and Audi, G. (2021). + *The NUBASE2020 evaluation of nuclear physics properties.* + Chin. Phys. C45, 030001. + `doi:10.1088/1674-1137/abddae `_ Crystal structure Ashcroft and Mermin diff --git a/explore/nubase.py b/explore/nubase.py new file mode 100644 index 0000000..1534202 --- /dev/null +++ b/explore/nubase.py @@ -0,0 +1,335 @@ +from typing import Dict, Tuple + +# Time units from shortest to longest +# Year-based units use YEAR_SECONDS conversion +YEAR_SECONDS = 31556926 # Exactly 365.2422 days +TIME_UNITS = { + 'ys': 1e-24, # yoctosecond + 'zs': 1e-21, # zeptosecond + 'as': 1e-18, # attosecond + 'fs': 1e-15, # femtosecond + 'ps': 1e-12, # picosecond + 'ns': 1e-9, # nanosecond + 'us': 1e-6, # microsecond + 'ms': 1e-3, # millisecond + 's': 1, # second + 'm': 60, # minute + 'h': 3600, # hour + 'd': 3600*24, # day + 'y': YEAR_SECONDS, # year + 'ky': 1e3 * YEAR_SECONDS, # kiloyear + 'My': 1e6 * YEAR_SECONDS, # megayear + 'Gy': 1e9 * YEAR_SECONDS, # gigayear + 'Ty': 1e12 * YEAR_SECONDS, # terayear + 'Py': 1e15 * YEAR_SECONDS, # petayear + 'Ey': 1e18 * YEAR_SECONDS, # exayear + 'Zy': 1e15 * YEAR_SECONDS, # zettayear + 'Yy': 1e21 * YEAR_SECONDS, # yottayear +} + +class NUBASEParser: + def __init__(self, filename: str): + self.filename = filename + + def parse_half_life(self, hl_str: str, unit_str: str, unc_str: str) -> float: + """Convert NUBASE half-life notation to seconds.""" + hl_str = hl_str.strip() + # Handle special cases + if hl_str == 'stbl': + return float('inf'), 0 + if hl_str == 'p-unst': + return float('inf'), 0 + if not hl_str: + return float('nan'), float('nan') + + # handle >val ~': + hl_str = hl_str[1:] + if hl_str[-1] == '#': + hl_str = hl_str[:-1] + + # Parse numeric value + try: + value = float(hl_str) + except ValueError: + raise ValueError(f"Invalid half-life value: {orig}") + + try: + unc = float(unc_str) + except ValueError: + unc = 0 + # msg = f"Invalid half-life uncertainty: {orig} ± {unc_str}" + # print(msg) + # raise ValueError(msg) + + # Handle unit conversion + unit = unit_str.strip() + factor = TIME_UNITS[unit] + return value * factor, unc * factor + + def parse_decay_modes(self, decay_str: str) -> Dict[str, Dict[str, Tuple[float, float]]]: + """Parse decay modes and branching ratios from column 120-209.""" + modes = {} + + # Split into individual mode entries + parts = decay_str.split(';') + + for part in parts: + part = part.strip() + if not part: + continue + + part = part.replace('#', '') + # Split mode from percentage + if part[-1] == '?': + # "mode ?" => (0 +/- 0) [unobserved but theoretically possible] + key = part.split(' ')[0] + modes[key] = 0., 0. + elif '<' in part: + # "mode (0 +/- value/100) + key, valstr = part.split('<') + valstr = valstr.split(' ')[0] # "mode' in part: + # "mode>value" => (value/100 +/- value/100) + key, valstr = part.split('>') + valstr = valstr.split(' ')[0] # "mode>value unc" + val = float(valstr)*0.01 + modes[key] = val, val + else: + # "mode=value" => (value/100 +/- 0) + # "mode=value unc" => (value/100 +/- unc/100) after correcting for digits after decimal + part = part.split('[')[0] # ignore e.g., IT=100[gs=100,m=0] + part = part.replace('~', '=') # treat A~val as if it were A=val + key, valstr = part.split('=') + val, unc = valstr.split(' ') if ' ' in valstr else (valstr, '0') + if '+' in unc: # value +unc-unc + plus, minus = unc[1:].split('-') + unc = plus if float(plus) > float(minus) else minus + unc_exp = len(val.split('.')[1]) if '.' in val else 0 + modes[key] = (float(val)*0.01, float(unc)*10**(-unc_exp-2)) + + # TODO: perhaps delete IS "mode": stable isotope natural abundance + return modes + + def parse_line(self, line: str) -> Dict[str, any]: + """Parse a single line from the NUBASE file.""" + def to_float(s): + s = s.strip() + if s == 'non-exist': + return float('nan') + return float(s.replace('#', '')) if s else float('nan') + + # Extract fixed-width columns + A = int(line[0:3].strip()) # Mass Number + Z_str = line[4:8].strip() # Atomic Number with isomer flag + Z = int(Z_str[:-1]) # Remove isomer flag + isomer_flag = int(Z_str[-1]) # Store isomer flag + element = line[11:16].strip() # Element symbol + isomer = line[16:17] # Isomer letter + mass_excess = to_float(line[18:31]) # Mass Excess in keV + mass_uncertainty = to_float(line[31:42]) + exc_energy = to_float(line[42:54].strip()) + exc_uncertainty = to_float(line[54:65].strip()) + orig = line[65:67].strip() # Origin of Excitation Energy + isomer_unc = line[67:68].strip() # Isomer ordering uncertainty + isomer_inv = line[68:69].strip() # Reversed ordering indicator + half_life = line[69:78].strip() # Half-life value + unit = line[78:80].strip() # Half-life unit + hl_uncertainty = line[81:88].strip() # Half-life uncertainty + spin_parity = line[88:102].strip() # Spin and Parity + ensdf_year = line[102:104].strip() # ENSDF update year + discovery_year = line[114:118].strip() # Year of Discovery + decay_modes = line[119:209].strip() # Decay Modes + + # Process parsed data + isomer_state = { + 'uncertain_ordering': isomer_unc == '*', + 'reversed_ordering': isomer_inv == '&' + } + + spin_parity_info = { + 'direct_measurement': '*' in spin_parity, + 'systematic_value': '#' in spin_parity, + 'value': spin_parity.replace('*', '').replace('#', '') + } + + half_life_s, err = self.parse_half_life(half_life, unit, hl_uncertainty) + decay_info = self.parse_decay_modes(decay_modes) + + return { + 'A': A, + 'Z': Z, + 'isomer_flag': isomer_flag, + 'isomer': isomer, + 'element': element, + 'mass_excess_keV': mass_excess, + 'mass_uncertainty_keV': mass_uncertainty, + 'excitation_energy_keV': exc_energy, + 'excitation_uncertainty_keV': exc_uncertainty, + 'origin': orig, + 'isomer_state': isomer_state, + 'spin_parity': spin_parity_info, + 'ensdf_year': ensdf_year, + 'discovery_year': discovery_year, + 'half_life': ' '.join((half_life, unit)), + 'half_life_uncertainty': hl_uncertainty, + 'half_life_s': half_life_s, + 'half_life_s_err': err, + 'decay_modes_str': decay_modes, + 'decay_modes': decay_info, + } + + def parse_file(self) -> Dict[Tuple[int, int], Dict[str, any]]: + """Parse the entire NUBASE file and return a dictionary of isotopes.""" + isotopes = {} + + with open(self.filename, 'r') as file: + # Skip header lines (lines starting with '#') + for line in file: + if not line.startswith('#'): + try: + isotope_data = self.parse_line(line) + key = (isotope_data['Z'], isotope_data['A'], isotope_data['isomer_flag']) + isotopes[key] = isotope_data + except Exception as e: + print(f"Error parsing line: {str(e)}\n {line.strip()}") + raise + + return isotopes + +def main(show_table=False): + import sys + from pathlib import Path + import re + from collections import defaultdict, Counter + from math import log10 + + import numpy as np + from periodictable import elements + #from uncertainties import ufloat as U + + decay_modes = Counter() + checked = {} + nubase_path = Path(__file__).parent / "nubase_4.mas20.txt" + nubase_url = "https://www.anl.gov/phy/reference/nubase-2020-nubase4mas20" + if not nubase_path.exists(): + print(f"Missing {nubase_path}. Fetch it from:\n {nubase_url}") + sys.exit(1) + + isotopes = NUBASEParser(nubase_path).parse_file() + #for k, v in isotopes.items(): + # print(f"{k}: {v['element']:>5s}{v['isomer']}: {v['half_life']:>10s} ({v['half_life_s']:10.3e} s) {v['decay_modes']}") + + if show_table: + print("# Halflife from NUBASE2020 in seconds") + print("# F.G. Kondev, M. Wang, W.J. Huang, S. Naimi, and G. Audi, Chin. Phys. C45, 030001 (2021)") + print("# isomer: (halflife, uncertainty, formatted)") + print("nubase2020_halflife = {") + + for el in elements: + for iso_num in el.isotopes: + iso = el[iso_num] + act_list = getattr(iso, 'neutron_activation', ()) + #print(iso.__dict__) + for act in act_list: + if act.daughter in checked: + continue + checked[act.daughter] = True + match = re.match(r'^([A-Z][a-z]*)-(\d+)(.*)', act.daughter) + d_symbol, d_isotope, d_isomer = match.group(1), match.group(2), match.group(3) + code = 2 if d_isomer.startswith('m2') else 1 if d_isomer.startswith('m') else 0 + code_override = { + "Pb-204m": 2, + "Ir-194m": 2, + "Ta-182m+": 2, + "Lu-177m*": 3, # 177Lup in NUBASE + "Eu-152m2+": 5, # 152Eur in NUBASE + "Sb-122m+": 3, # 122Sbp in NUBASE + "Ag-110m*": 2, + "Pd-109m+": 2, + "Pd-107m+": 2, + "Kr-83m": 2, + "Ge-73m": 2, + "Sc-46m+": 2, + } + code = code_override.get(act.daughter, code) + d_el = getattr(elements, d_symbol) + v = isotopes.get((d_el.number, int(d_isotope), code), None) + if v is None: + print(f"{act.daughter} {act.Thalf_str} missing from nubase") + continue + + # While debugging the code_override above I suppressed the known differences + known_diff = ( + # 20% or more + 'Lu-177m*', 'Tb-157', 'Cs-135', 'Sn-126', 'Sn-121m', + 'Ag-108m*', 'Tc-97', 'Se-79', 'Ca-41', 'Cl-38m+', 'Si-32', + # 10%-20% + 'Be-10', 'Rb-88', 'Mo-93', 'Cd-113', 'Sn-119m', 'Te-121', + 'Lu-176', 'Os-191m+', 'Pb-205', 'Bi-210ms', + ) + #if act.daughter in known_diff: continue + + nub_s, nub_ds, act_s = v['half_life_s'], v['half_life_s_err'], act.Thalf_hrs*3600.0 + + # Te-123 is listed as stable in NUBASE2020 + if not np.isfinite(nub_s): + # print(f"{act.isotope} => {act.daughter}: T1/2 = {act.Thalf_str} != stbl") + continue + + # # Ignore long and short half lives (in seconds) + # if not (600 <= nub_s <= 10*365*24*3600): + # continue + decay_modes.update(v['decay_modes'].keys()) + + if show_table: # print new table of half-lives + digits = int(log10(nub_s)) - int(log10(nub_ds)) + 1 + print(f" \"{act.daughter}\": ({nub_s:.{digits}e}, {nub_ds:.1e}, \"{v['half_life']}\"),") # {U(nub_s, nub_ds):.2uS} + continue + + # Note: IS is isotopic abundance for stable and long-lived isotopes + # Note: 2B+ from Gd152 has 0 probability + #if any(mode not in {'B-', 'IT', 'B+', 'EC', 'A', 'IS', '2B+'} for mode in v['decay_modes'].keys()): + # print(f"** rare {d_symbol}{d_isotope}{v['isomer']} => {act.reaction}", v['decay_modes']) + + diff = abs(nub_s - act_s)/nub_s # relative diff between nubase and activation calculator + target = nub_ds/nub_s # relative uncertainty in nub_s + target = 0.005 # 0.5% + target = 0.05 # 5% + target = 0.2 # 20% + if diff > target: + #print(act.daughter, d_symbol, d_isotope, d_isomer, code) + #print(f"{act.isotope}=>{act.daughter}: T1/2 = {act.Thalf_str} ({act.Thalf_hrs*3600.:.3e} s)") + #print(f" {v['element']}{v['isomer']}[{v['isomer_flag']}]: {v['half_life']:>10s} ({v['half_life_s']:10.3e} s) {v['decay_modes']}") + print(f"{act.isotope:6} => {act.daughter:<9}: {int(diff*100):3d}% ΔT½ ({act.Thalf_str} != {v['half_life']} ± {nub_ds/nub_s*100:.1f}%)") + + if show_table: + print("}") + return + + print(f"There are {len(isotopes)} halflives in NUBASE of which {len(checked)} are used in the activation calculator.") + print(f"Decay modes used in activation isotopes:", decay_modes) + + joined = {key[:2]:value for key, value in isotopes.items()} + masses = {(el.number, iso): el[iso] for el in elements for iso in el.isotopes} + print(f"There are {len(joined)} isotopes in NUBASE and {len(masses)} isotopes in periodictable") + if all(m in joined for m in masses.keys()): + print(f"All isotopes from periodictable are in nubase") + if 0 and any(m not in masses for m in joined.keys()): + result = defaultdict(list) + for key, value in joined.keys(): + result[key].append(value) + for el in elements: + print(f"{el}:", " ".join(f"{iso}" if iso in el.isotopes else f"*{iso}" for iso in result[el.number])) + + # Note: decay energy is the difference in excess energy + + +if __name__ == "__main__": + # Tell activation.py to use activation.dat for halflife values + import periodictable.activation + periodictable.activation.use_nubase2020_halflife = False + main(show_table=False) # Show differences from activation.dat values + #main(show_table=True) # Show halflife table to include in activation.py \ No newline at end of file diff --git a/periodictable/activation.py b/periodictable/activation.py index 54f696d..a3658de 100644 --- a/periodictable/activation.py +++ b/periodictable/activation.py @@ -86,21 +86,21 @@ ----------------- activity (uCi) ------------------ isotope product reaction half-life 0 hrs 1 hrs 24 hrs 360 hrs -------- --------- -------- ---------- ------------ ------------ ------------ ------------ - Co-59 Co-60 act 5.272 y 0.0004959 0.0004959 0.0004958 0.0004933 - Co-59 Co-60m+ act 10.5 m 1.664 0.03169 --- --- + Co-59 Co-60 act 5.272 y 0.0004957 0.0004957 0.0004955 0.000493 + Co-59 Co-60m+ act 10.5 m 1.664 0.03129 --- --- -------- --------- -------- ---------- ------------ ------------ ------------ ------------ - total 1.664 0.0322 0.0005084 0.0005049 + total 1.664 0.03181 0.0005079 0.0005045 -------- --------- -------- ---------- ------------ ------------ ------------ ------------ >>> print("%.3f"%sample.decay_time(0.001)) # number of hours to reach 1 nCi - 2.053 + 2.046 The default rest times used above show the sample activity at the end of neutron activation and after 1 hour, 1 day, and 15 days. The neutron activation table, *activation.dat*,\ [#Shleien1998]_ contains details about the individual isotopes, with interaction cross sections taken -from from IAEA-273\ [#IAEA1987]_. +from from IAEA-273\ [#IAEA1987]_, and half-lives from NUBASE2020\ [#Kondev2021]_ Activation can be run from the command line using:: @@ -117,6 +117,10 @@ TR 273 (International Atomic Energy Agency, Vienna, Austria, 1987). http://cds.cern.ch/record/111089/files/IAEA-TR-273.pdf +.. [#Kondev2021] F.G. Kondev, M. Wang, W.J. Huang, S. Naimi, and G. Audi, 2021. + Chin. Phys. C45, 030001. DOI:10.1088/1674-1137/abddae + Data retrieved from https://www.anl.gov/phy/reference/nubase-2020-nubase4mas20 + Code original developed for spreadsheet by Les Slaback of NIST. """ @@ -892,7 +896,6 @@ def init(table, reload=False): """ Add neutron activation levels to each isotope. """ - from math import floor # TODO: importlib.reload does not work for iso.neutron_activation attribute if 'neutron_activation' not in table.properties: table.properties.append('neutron_activation') @@ -949,17 +952,7 @@ def init(table, reload=False): # Note: spreadsheet is not converting half-life to hours in cell AW1462 (186-W => 188-W) kw['Thalf_hrs'] = float(kw['_Thalf']) * UNITS_TO_HOURS[kw['_Thalf_unit']] #print(f"T1/2 {kw['Thalf_hrs']} +/- {kw['Thalf_hrs_unc']}") - # Recreate Thalf_parent by fetching from the new Thalf_hrs - # e.g., =IF(OR(AR1408="2n",AR1408="b"),IF(AR1407="b",AW1406,AW1407),"") - # This requires that the parent is directly before the 'b' or 'nb' - # with its activation list already entered into the isotope. - # Note: 150-Nd has 'act' followed by two consecutive 'b' entries. - if kw['reaction'] in ('b', '2n'): - parent = act[-2] if act[-1].reaction == 'b' else act[-1] - kw['Thalf_parent'] = parent.Thalf_hrs - else: - #assert kw['Thalf_parent'] == 0 - kw['Thalf_parent'] = None + # Half-lives use My, Gy, Ty, Py value, units = float(kw['_Thalf']), kw['_Thalf_unit'] if units == 'y': @@ -976,6 +969,33 @@ def init(table, reload=False): # print(f"{kw['_index']}: old {kw['Thalf_str']} != {formatted} new") kw['Thalf_str'] = formatted + # Override half-lives using NUBASE2020. + # Note: to use the original values, import periodictable.activation and set + # use_nubase2020_halflife = False before accessing any activation data. + if use_nubase2020_halflife: + daughter = kw['daughter'] + # NUBASE2020 lists 123Te as stable, so drop it from the reaction table + if daughter == "Te-123": + continue + Thalf_hrs = nubase2020_halflife[daughter][0] / 3600.0 + # Show change for a specific element or isotope + #if daughter.startswith('Co'): + # print(f"{daughter}: {kw['Thalf_hrs']} => {Thalf_hrs}") + kw['Thalf_hrs'] = Thalf_hrs + kw['Thalf_str'] = nubase2020_halflife[daughter][2] + + # Recreate Thalf_parent by fetching from the new Thalf_hrs + # e.g., =IF(OR(AR1408="2n",AR1408="b"),IF(AR1407="b",AW1406,AW1407),"") + # This requires that the parent is directly before the 'b' or 'nb' + # with its activation list already entered into the isotope. + # Note: 150-Nd has 'act' followed by two consecutive 'b' entries. + if kw['reaction'] in ('b', '2n'): + parent = act[-2] if act[-1].reaction == 'b' else act[-1] + kw['Thalf_parent'] = parent.Thalf_hrs + else: + #assert kw['Thalf_parent'] == 0 + kw['Thalf_parent'] = None + # Strip columns whose names start with underscore kw = dict((k, v) for k, v in kw.items() if not k.startswith('_')) @@ -992,6 +1012,390 @@ def init(table, reload=False): for (Z, A), daughters in activations.items(): table[Z][A].neutron_activation = tuple(daughters) +# Halflife from NUBASE2020 in seconds +# F.G. Kondev, M. Wang, W.J. Huang, S. Naimi, and G. Audi, Chin. Phys. C45, 030001 (2021) +# isomer: (halflife, uncertainty, formatted) +use_nubase2020_halflife = True # Set this to False before accessing activation data +nubase2020_halflife = { + "H-3": (3.8878e+08, 6.3e+05, "12.32 y"), + "Li-8": (8.3870e-01, 3.0e-04, "838.7 ms"), + "Be-10": (4.377e+13, 3.8e+11, "1.387 My"), + "He-6": (8.0692e-01, 2.4e-04, "806.92 ms"), + "B-12": (2.0200e-02, 2.0e-05, "20.20 ms"), + "C-11": (1.2204e+03, 3.2e-01, "20.3402 m"), + "C-14": (1.7987e+11, 9.5e+08, "5.70 ky"), + "N-16": (7.13e+00, 2.0e-02, "7.13 s"), + "O-15": (1.2227e+02, 4.3e-02, "122.266 s"), + "N-17": (4.173e+00, 4.0e-03, "4.173 s"), + "O-19": (2.6470e+01, 6.0e-03, "26.470 s"), + "F-20": (1.1006e+01, 8.0e-03, "11.0062 s"), + "F-18": (6.5840e+03, 4.8e-01, "109.734 m"), + "Ne-23": (3.715e+01, 3.0e-02, "37.15 s"), + "Na-24m+": (2.0180e-02, 1.0e-04, "20.18 ms"), + "Na-24": (5.38416e+04, 5.4e+00, "14.9560 h"), + "Na-22": (8.2108e+07, 1.9e+04, "2.6019 y"), + "Na-25": (5.91e+01, 6.0e-01, "59.1 s"), + "Mg-27": (5.661e+02, 1.6e+00, "9.435 m"), + "Mg-28": (7.5294e+04, 3.2e+01, "20.915 h"), + "Al-28": (1.347e+02, 3.0e-01, "2.245 m"), + "Al-29": (3.936e+02, 3.6e+00, "6.56 m"), + "Si-31": (9.430e+03, 1.2e+01, "157.16 m"), + "Si-32": (4.95e+09, 2.2e+08, "157 y"), + "P-32": (1.23284e+06, 6.0e+02, "14.269 d"), + "P-33": (2.1902e+06, 9.5e+03, "25.35 d"), + "S-35": (7.5488e+06, 3.5e+03, "87.37 d"), + "P-34": (1.243e+01, 1.0e-01, "12.43 s"), + "S-37": (3.030e+02, 1.2e+00, "5.05 m"), + "Cl-36": (9.508e+12, 4.7e+10, "301.3 ky"), + "Cl-38m+": (7.150e-01, 3.0e-03, "715 ms"), + "Cl-38": (2.2338e+03, 8.4e-01, "37.230 m"), + "Ar-37": (3.0250e+06, 1.6e+03, "35.011 d"), + "Ar-39": (8.46e+09, 2.5e+08, "268 y"), + "Ar-41": (6.5766e+03, 2.4e+00, "109.61 m"), + "Ar-42": (1.038e+09, 3.5e+07, "32.9 y"), + "K-40": (3.9383e+16, 9.5e+13, "1.248 Gy"), + "K-42": (4.4478e+04, 2.5e+01, "12.355 h"), + "Ca-41": (3.137e+12, 4.7e+10, "99.4 ky"), + "K-43": (8.028e+04, 3.6e+02, "22.3 h"), + "Ca-45": (1.40495e+07, 7.8e+03, "162.61 d"), + "Ca-47*": (3.9191e+05, 2.6e+02, "4.536 d"), + "Ca-49t": (5.231e+02, 3.6e-01, "8.718 m"), + "Sc-49": (3.4308e+03, 7.8e+00, "57.18 m"), + "Sc-46m+": (1.875e+01, 4.0e-02, "18.75 s"), + "Sc-46": (7.2366e+06, 1.2e+03, "83.757 d"), + "Sc-47": (2.89371e+05, 5.2e+01, "3.3492 d"), + "Ti-45": (1.1088e+04, 3.0e+01, "184.8 m"), + "Sc-48": (1.5721e+05, 3.2e+02, "43.67 h"), + "Ti-51": (3.456e+02, 6.0e-01, "5.76 m"), + "V-52": (2.246e+02, 3.0e-01, "3.743 m"), + "Cr-51": (2.393410e+06, 9.5e+01, "27.7015 d"), + "Cr-49": (2.5380e+03, 6.0e+00, "42.3 m"), + "V-53": (9.26e+01, 8.4e-01, "1.543 m"), + "Cr-55": (2.098e+02, 1.8e-01, "3.497 m"), + "Mn-56": (9.2840e+03, 3.6e-01, "2.5789 h"), + "Mn-54": (2.69638e+07, 2.8e+03, "312.081 d"), + "Fe-55": (8.6977e+07, 1.3e+04, "2.7562 y"), + "Fe-53": (5.106e+02, 1.2e+00, "8.51 m"), + "Fe-59": (3.8448e+06, 1.0e+03, "44.500 d"), + "Co-60m+": (6.280e+02, 3.6e-01, "10.467 m"), + "Co-61": (5.936e+03, 1.8e+01, "1.649 h"), + "Co-60": (1.66349e+08, 1.9e+04, "5.2714 y"), + "Co-58": (6.1209e+06, 1.7e+03, "70.844 d"), + "Ni-57": (1.2816e+05, 2.2e+02, "35.60 h"), + "Ni-59": (2.56e+12, 1.6e+11, "81 ky"), + "Co-58m+": (3.1871e+04, 8.3e+01, "8.853 h"), + "Ni-63": (3.194e+09, 4.7e+07, "101.2 y"), + "Ni-65": (9.0630e+03, 1.8e+00, "2.5175 h"), + "Cu-62": (5.803e+02, 4.8e-01, "9.672 m"), + "Cu-64": (4.57214e+04, 4.7e+00, "12.7004 h"), + "Cu-66": (3.072e+02, 8.4e-01, "5.120 m"), + "Cu-67": (2.2259e+05, 4.3e+02, "61.83 h"), + "Ni-66s": (1.966e+05, 1.1e+03, "54.6 h"), + "Zn-65": (2.10764e+07, 3.5e+03, "243.94 d"), + "Zn-69ms": (4.9489e+04, 4.0e+01, "13.747 h"), + "Zn-69": (3.384e+03, 5.4e+01, "56.4 m"), + "Zn-71m": (1.4933e+04, 4.3e+01, "4.148 h"), + "Zn-71": (1.440e+02, 3.0e+00, "2.40 m"), + "Ga-70": (1.2684e+03, 3.0e+00, "21.14 m"), + "Ga-72m+": (3.968e-02, 1.3e-04, "39.68 ms"), + "Ga-72": (5.0490e+04, 3.6e+01, "14.025 h"), + "Ga-73": (1.750e+04, 1.1e+02, "4.86 h"), + "Ge-69": (1.4058e+05, 3.6e+02, "39.05 h"), + "Ge-71m+": (2.041e-02, 1.8e-04, "20.41 ms"), + "Ge-71": (9.876e+05, 2.6e+03, "11.43 d"), + "Ge-73m": (4.99e-01, 1.1e-02, "499 ms"), + "Ge-75m+": (4.77e+01, 5.0e-01, "47.7 s"), + "Ge-75": (4.9668e+03, 2.4e+00, "82.78 m"), + "Zn-71ms": (1.4933e+04, 4.3e+01, "4.148 h"), + "Ge-77m+": (5.37e+01, 6.0e-01, "53.7 s"), + "Ge-77": (4.0360e+04, 1.1e+01, "11.211 h"), + "Ge-78s": (5.280e+03, 6.0e+01, "88.0 m"), + "As-74": (1.5353e+06, 1.7e+03, "17.77 d"), + "As-76": (9.446e+04, 3.3e+02, "1.0933 d"), + "As-77": (1.3964e+05, 1.8e+02, "38.79 h"), + "Se-75": (1.03490e+07, 2.6e+03, "119.78 d"), + "Se-77m": (1.736e+01, 5.0e-02, "17.36 s"), + "Se-79m+": (2.340e+02, 1.1e+00, "3.900 m"), + "Se-79": (1.032e+13, 8.8e+11, "327 ky"), + "Se-79m": (2.340e+02, 1.1e+00, "3.900 m"), + "Se-81m*": (3.4368e+03, 1.2e+00, "57.28 m"), + "Se-81": (1.1070e+03, 7.2e+00, "18.45 m"), + "Se-83m+": (7.01e+01, 4.0e-01, "70.1 s"), + "Se-83t": (1.3350e+03, 2.4e+00, "22.25 m"), + "Br-83": (8.546e+03, 1.4e+01, "2.374 h"), + "Br-80m*": (1.59138e+04, 2.9e+00, "4.4205 h"), + "Br-80": (1.0608e+03, 1.2e+00, "17.68 m"), + "Br-82m+": (3.678e+02, 3.0e+00, "6.13 m"), + "Br-82": (1.27015e+05, 2.5e+01, "35.282 h"), + "Kr-79m+": (5.00e+01, 3.0e+00, "50 s"), + "Kr-79": (1.2614e+05, 3.6e+02, "35.04 h"), + "Kr-81m+": (1.310e+01, 3.0e-02, "13.10 s"), + "Kr-81": (7.23e+12, 3.5e+11, "229 ky"), + "Kr-83m": (6.588e+03, 4.7e+01, "1.830 h"), + "Kr-85m+": (1.6128e+04, 2.9e+01, "4.480 h"), + "Kr-85": (3.3854e+08, 2.2e+05, "10.728 y"), + "Kr-87": (4.578e+03, 3.0e+01, "76.3 m"), + "Kr-88": (1.0170e+04, 6.8e+01, "2.825 h"), + "Rb-84": (2.8356e+06, 6.0e+03, "32.82 d"), + "Rb-86m+": (6.10e+01, 1.8e-01, "1.017 m"), + "Rb-86": (1.61093e+06, 6.9e+02, "18.645 d"), + "Rb-88": (1.0668e+03, 1.8e+00, "17.78 m"), + "Rb-89*": (9.192e+02, 6.0e+00, "15.32 m"), + "Sr-85m+": (4.0578e+03, 2.4e+00, "67.63 m"), + "Sr-85": (5.60269e+06, 5.2e+02, "64.846 d"), + "Sr-87m": (1.0098e+04, 3.2e+01, "2.805 h"), + "Sr-89": (4.3686e+06, 2.2e+03, "50.563 d"), + "Sr-90": (9.1231e+08, 9.5e+05, "28.91 y"), + "Y-88": (9.2127e+06, 2.1e+03, "106.629 d"), + "Y-89m": (1.5663e+01, 5.0e-03, "15.663 s"), + "Y-90m+": (1.1614e+04, 4.0e+01, "3.226 h"), + "Y-90": (2.3058e+05, 1.8e+02, "64.05 h"), + "Y-91": (5.0553e+06, 5.2e+03, "58.51 d"), + "Zr-89": (2.82096e+05, 8.3e+01, "78.360 h"), + "Zr-93": (5.08e+13, 1.6e+12, "1.61 My"), + "Sr-90s": (9.1231e+08, 9.5e+05, "28.91 y"), + "Zr-95s": (5.53236e+06, 5.2e+02, "64.032 d"), + "Zr-97s": (6.0296e+04, 2.9e+01, "16.749 h"), + "Nb-92mt": (8.740e+05, 1.1e+03, "10.116 d"), + "Nb-92": (1.095e+15, 7.6e+13, "34.7 My"), + "Nb-94m+": (3.758e+02, 2.4e-01, "6.263 m"), + "Nb-94": (6.44e+11, 1.3e+10, "20.4 ky"), + "Nb-93m": (5.087e+08, 3.8e+06, "16.12 y"), + "Mo-93m+": (2.466e+04, 2.5e+02, "6.85 h"), + "Mo-93": (1.26e+11, 2.5e+10, "4.0 ky"), + "Nb-95": (3.02322e+06, 5.2e+02, "34.991 d"), + "Nb-96": (8.406e+04, 1.8e+02, "23.35 h"), + "Mo-99st": (2.37355e+05, 1.8e+01, "65.932 h"), + "Tc-99": (6.662e+12, 3.8e+10, "211.1 ky"), + "Zr-95": (5.53236e+06, 5.2e+02, "64.032 d"), + "Mo-101s": (8.766e+02, 1.8e+00, "14.61 m"), + "Tc-99m+": (2.16238e+04, 7.2e-01, "6.0066 h"), + "Ru-97t": (2.4512e+05, 1.2e+02, "2.8370 d"), + "Tc-97": (1.329e+14, 5.0e+12, "4.21 My"), + "Ru-103": (3.39077e+06, 6.9e+02, "39.245 d"), + "Ru-105t": (1.5980e+04, 4.0e+01, "4.439 h"), + "Rh-105": (1.27228e+05, 6.8e+01, "35.341 h"), + "Rh-103m": (3.3668e+03, 5.4e-01, "56.114 m"), + "Rh-104m": (2.604e+02, 1.8e+00, "4.34 m"), + "Rh-104": (4.23e+01, 4.0e-01, "42.3 s"), + "Pd-103": (1.4680e+06, 1.6e+03, "16.991 d"), + "Pd-107m+": (2.13e+01, 5.0e-01, "21.3 s"), + "Pd-107": (2.051e+14, 9.5e+12, "6.5 My"), + "Pd-109m+": (2.822e+02, 5.4e-01, "4.703 m"), + "Pd-109": (4.892e+04, 4.3e+02, "13.59 h"), + "Pd-111m*": (2.0027e+04, 4.7e+01, "5.563 h"), + "Pd-111t": (1.4136e+03, 5.4e+00, "23.56 m"), + "Ag-111": (6.4221e+05, 8.6e+02, "7.433 d"), + "Ag-106ms": (7.154e+05, 1.7e+03, "8.28 d"), + "Ag-108m*": (1.385e+10, 2.8e+08, "439 y"), + "Ag-108": (1.429e+02, 6.6e-01, "2.382 m"), + "Ag-110m*": (2.15882e+07, 2.1e+03, "249.863 d"), + "Ag-110": (2.46e+01, 1.1e-01, "24.56 s"), + "Cd-107": (2.3400e+04, 7.2e+01, "6.50 h"), + "Ag-106": (1.4376e+03, 2.4e+00, "23.96 m"), + "Cd-109": (3.9856e+07, 4.3e+04, "461.3 d"), + "Cd-111m": (2.9100e+03, 5.4e+00, "48.50 m"), + "Cd-113m": (4.383e+08, 3.5e+06, "13.89 y"), + "Cd-113": (2.537e+23, 1.6e+21, "8.04 Py"), + "Cd-115ms": (3.850e+06, 2.1e+04, "44.56 d"), + "Cd-115s": (1.9246e+05, 1.8e+02, "53.46 h"), + "Cd-117ms": (1.2388e+04, 3.2e+01, "3.441 h"), + "Cd-117s": (9.011e+03, 1.8e+01, "2.503 h"), + "In-114m2+": (4.310e-02, 6.0e-04, "43.1 ms"), + "In-114m1*": (4.27766e+06, 8.6e+02, "49.51 d"), + "In-114": (7.190e+01, 1.0e-01, "71.9 s"), + "In-116m2+": (2.18e+00, 4.0e-02, "2.18 s"), + "In-116m1": (3.257e+03, 1.0e+01, "54.29 m"), + "In-116": (1.410e+01, 3.0e-02, "14.10 s"), + "In-115m": (1.6150e+04, 1.4e+01, "4.486 h"), + "Sn-113m+": (1.284e+03, 2.4e+01, "21.4 m"), + "Sn-113": (9.9429e+06, 3.5e+03, "115.08 d"), + "Sn-117m": (1.2043e+06, 2.1e+03, "13.939 d"), + "Sn-119m": (2.5324e+07, 6.0e+04, "293.1 d"), + "Sn-121m": (1.385e+09, 1.6e+07, "43.9 y"), + "Sn-121": (9.731e+04, 1.4e+02, "27.03 h"), + "Sn-123m": (2.4036e+03, 6.0e-01, "40.06 m"), + "Sn-123": (1.1163e+07, 3.5e+04, "129.2 d"), + "Sn-125t": (8.324e+05, 1.3e+03, "9.634 d"), + "Sn-125m": (5.86e+02, 1.5e+01, "9.77 m"), + "Sb-125": (8.7021e+07, 3.5e+04, "2.7576 y"), + "Sn-126": (7.26e+12, 4.4e+11, "230 ky"), + "Sb-122m+": (2.515e+02, 1.8e-01, "4.191 m"), + "Sb-122": (2.35336e+05, 1.7e+01, "2.7238 d"), + "Sb-124m2*": (1.212e+03, 1.2e+01, "20.2 m"), + "Sb-124m1+": (9.30e+01, 5.0e+00, "93 s"), + "Sb-124": (5.2013e+06, 2.6e+03, "60.20 d"), + "Te-121m*": (1.4230e+07, 4.3e+04, "164.7 d"), + "Te-121": (1.6684e+06, 6.0e+03, "19.31 d"), + "Te-123m*": (1.02989e+07, 8.6e+03, "119.2 d"), + "Te-125m": (4.959e+06, 1.3e+04, "57.40 d"), + "Te-127m*": (9.167e+06, 6.0e+04, "106.1 d"), + "Te-127": (3.366e+04, 2.5e+02, "9.35 h"), + "Te-129ms": (2.9030e+06, 8.6e+03, "33.6 d"), + "Te-129t": (4.176e+03, 1.8e+01, "69.6 m"), + "I-129": (5.093e+14, 3.8e+12, "16.14 My"), + "Te-131m": (1.1693e+05, 4.0e+02, "32.48 h"), + "Te-132": (2.768e+05, 1.1e+03, "3.204 d"), + "Te-131t": (1.5000e+03, 6.0e+00, "25.0 m"), + "I-131": (6.93351e+05, 5.2e+01, "8.0249 d"), + "I-126": (1.1172e+06, 4.3e+03, "12.93 d"), + "I-128": (1.4994e+03, 1.2e+00, "24.99 m"), + "Xe-125m+": (5.69e+01, 9.0e-01, "56.9 s"), + "Xe-125t": (6.073e+04, 2.9e+02, "16.87 h"), + "I-125": (5.13147e+06, 6.9e+02, "59.392 d"), + "Xe-127m+": (6.92e+01, 9.0e-01, "69.2 s"), + "Xe-127": (3.13995e+06, 2.6e+02, "36.342 d"), + "Xe-129m": (7.672e+05, 1.7e+03, "8.88 d"), + "Xe-131m": (1.0323e+06, 1.0e+03, "11.948 d"), + "Xe-133m+": (1.899e+05, 1.1e+03, "2.198 d"), + "Xe-133": (4.53375e+05, 4.3e+01, "5.2474 d"), + "Xe-135m+": (9.174e+02, 3.0e+00, "15.29 m"), + "Xe-135": (3.2904e+04, 7.2e+01, "9.14 h"), + "Xe-137t": (2.291e+02, 7.8e-01, "3.818 m"), + "Cs-137s": (9.480e+08, 1.3e+06, "30.04 y"), + "Cs-134m+": (1.04832e+04, 7.2e+00, "2.912 h"), + "Cs-134": (6.5165e+07, 1.3e+04, "2.0650 y"), + "Cs-135": (4.20e+13, 6.0e+12, "1.33 My"), + "I-130": (4.4496e+04, 3.6e+01, "12.36 h"), + "Ba-131m+": (8.556e+02, 5.4e+00, "14.26 m"), + "Ba-131s": (9.9533e+05, 8.6e+02, "11.52 d"), + "Ba-133m+": (1.4004e+05, 2.2e+02, "38.90 h"), + "Ba-133": (3.32544e+08, 5.0e+04, "10.5379 y"), + "Cs-132": (5.5987e+05, 5.2e+02, "6.480 d"), + "Ba-135m": (1.01196e+05, 7.2e+01, "28.11 h"), + "Ba-136m": (3.084e-01, 1.9e-03, "308.4 ms"), + "Ba-137m": (1.5312e+02, 6.0e-02, "2.552 m"), + "Cs-136": (1.1241e+06, 4.3e+03, "13.01 d"), + "Cs-137": (9.480e+08, 1.3e+06, "30.04 y"), + "Ba-139": (4.9758e+03, 5.4e+00, "82.93 m"), + "Ba-140": (1.10189e+06, 1.8e+02, "12.7534 d"), + "La-140": (1.45040e+05, 1.4e+01, "40.289 h"), + "La-141*": (1.411e+04, 1.1e+02, "3.92 h"), + "Ce-137m*": (1.238e+05, 1.1e+03, "34.4 h"), + "Ce-137t": (3.24e+04, 1.1e+03, "9.0 h"), + "La-137": (1.89e+12, 6.3e+11, "60 ky"), + "Ce-139m+": (5.76e+01, 3.2e-01, "57.58 s"), + "Ce-139": (1.18923e+07, 1.7e+03, "137.642 d"), + "Ce-141": (2.80843e+06, 8.6e+02, "32.505 d"), + "Ce-143t": (1.18940e+05, 2.2e+01, "33.039 h"), + "Pr-143": (1.1724e+06, 1.7e+03, "13.57 d"), + "Ce-144s": (2.46142e+07, 2.2e+03, "284.886 d"), + "Pr-142m+": (8.76e+02, 3.0e+01, "14.6 m"), + "Pr-142": (6.883e+04, 1.4e+02, "19.12 h"), + "Nd-147t": (9.4867e+05, 8.6e+02, "10.98 d"), + "Pm-147": (8.27864e+07, 6.3e+03, "2.6234 y"), + "Nd-149t": (6.2208e+03, 3.6e+00, "1.728 h"), + "Pm-149": (1.9109e+05, 1.8e+02, "53.08 h"), + "Nd-151t": (7.464e+02, 4.2e+00, "12.44 m"), + "Pm-151": (1.0224e+05, 1.4e+02, "28.40 h"), + "Sm-151": (2.985e+09, 1.9e+07, "94.6 y"), + "Sm-145t": (2.938e+07, 2.6e+05, "340 d"), + "Pm-145": (5.59e+08, 1.3e+07, "17.7 y"), + "Sm-153": (1.666246e+05, 8.3e+00, "46.2846 h"), + "Sm-155": (1.3308e+03, 3.6e+00, "22.18 m"), + "Eu-152m2+": (5.748e+03, 2.4e+01, "95.8 m"), + "Eu-152m1": (3.35218e+04, 4.7e+00, "9.3116 h"), + "Gd-152": (3.41e+21, 2.5e+20, "108 Ty"), + "Eu-152t": (4.2655e+08, 1.9e+05, "13.517 y"), + "Eu-154": (2.71137e+08, 9.5e+04, "8.592 y"), + "Eu-155": (1.4964e+08, 2.5e+05, "4.742 y"), + "Gd-153": (2.0788e+07, 6.0e+04, "240.6 d"), + "Gd-159": (6.6524e+04, 1.4e+01, "18.479 h"), + "Gd-161t": (2.188e+02, 1.8e-01, "3.646 m"), + "Tb-161": (6.0031e+05, 4.3e+02, "6.948 d"), + "Tb-160": (6.247e+06, 1.7e+04, "72.3 d"), + "Dy-157t": (2.930e+04, 1.4e+02, "8.14 h"), + "Tb-157": (2.24e+09, 2.2e+08, "71 y"), + "Dy-159": (1.2476e+07, 1.7e+04, "144.4 d"), + "Dy-165m": (7.54e+01, 3.6e-01, "1.257 m"), + "Dy-165": (8.395e+03, 1.4e+01, "2.332 h"), + "Dy-166": (2.9376e+05, 3.6e+02, "81.6 h"), + "Ho-166m": (3.574e+10, 1.2e+08, "1.1326 ky"), + "Ho-166": (9.6523e+04, 2.5e+01, "26.812 h"), + "Er-163t": (4.500e+03, 2.4e+01, "75.0 m"), + "Ho-163": (1.4422e+11, 7.9e+08, "4.570 ky"), + "Er-165": (3.730e+04, 1.4e+02, "10.36 h"), + "Er-167m": (2.269e+00, 6.0e-03, "2.269 s"), + "Er-169": (8.115e+05, 1.6e+03, "9.392 d"), + "Er-171t": (2.70576e+04, 7.2e+00, "7.516 h"), + "Tm-171": (6.059e+07, 3.2e+05, "1.92 y"), + "Er-172*": (1.775e+05, 1.8e+03, "49.3 h"), + "Tm-170": (1.1111e+07, 2.6e+04, "128.6 d"), + "Yb-169m+": (4.60e+01, 2.0e+00, "46 s"), + "Yb-169": (2.76601e+06, 4.3e+02, "32.014 d"), + "Yb-175m+": (6.820e-02, 3.0e-04, "68.2 ms"), + "Yb-175": (3.61584e+05, 8.6e+01, "4.185 d"), + "Yb-177m+": (6.41e+00, 2.0e-02, "6.41 s"), + "Yb-177t": (6.880e+03, 1.1e+01, "1.911 h"), + "Lu-177": (5.74068e+05, 7.8e+01, "6.6443 d"), + "Lu-176m": (1.3190e+04, 6.8e+01, "3.664 h"), + "Lu-176": (1.1679e+18, 5.4e+15, "37.01 Gy"), + "Lu-177m*": (1.3859e+07, 2.6e+04, "160.4 d"), + "Hf-175": (6.104e+06, 1.6e+04, "70.65 d"), + "Hf-178m": (4.0e+00, 2.0e-01, "4.0 s"), + "Hf-179m2": (2.160e+06, 1.5e+04, "25.00 d"), + "Hf-179m1": (1.867e+01, 4.0e-02, "18.67 s"), + "Hf-180m": (1.9908e+04, 7.2e+01, "5.53 h"), + "Hf-181": (3.6625e+06, 5.2e+03, "42.39 d"), + "Hf-182s": (2.809e+14, 2.8e+12, "8.90 My"), + "Ta-182m+": (9.504e+02, 6.0e+00, "15.84 m"), + "Ta-182": (9.914e+06, 1.0e+04, "114.74 d"), + "Ta-183": (4.406e+05, 8.6e+03, "5.1 d"), + "Lu-178": (1.704e+03, 1.2e+01, "28.4 m"), + "W-181": (1.04506e+07, 1.6e+03, "120.956 d"), + "W-185m+": (9.58e+01, 2.4e-01, "1.597 m"), + "W-185": (6.489e+06, 2.6e+04, "75.1 d"), + "W-187": (8.5712e+04, 9.0e+01, "23.809 h"), + "W-188": (6.0281e+06, 4.3e+03, "69.77 d"), + "Re-184ms": (1.460e+07, 6.9e+05, "169 d"), + "Re-184": (3.059e+06, 6.0e+04, "35.4 d"), + "Re-186": (3.21278e+05, 4.3e+01, "3.7185 d"), + "Re-188m+": (1.1154e+03, 2.4e+00, "18.59 m"), + "Re-188": (6.1218e+04, 1.1e+01, "17.005 h"), + "Os-185": (8.0309e+06, 7.8e+03, "92.95 d"), + "Os-189m": (2.092e+04, 3.6e+02, "5.81 h"), + "Os-190m": (5.916e+02, 1.8e+00, "9.86 m"), + "Os-191m+": (4.716e+04, 1.8e+02, "13.10 h"), + "Os-191": (1.2951e+06, 1.7e+03, "14.99 d"), + "Os-193": (1.07388e+05, 6.5e+01, "29.830 h"), + "Os-194s": (1.893e+08, 6.3e+06, "6.0 y"), + "Ir-192m2*": (7.61e+09, 2.8e+08, "241 y"), + "Ir-192m1+": (8.70e+01, 3.0e+00, "1.45 m"), + "Ir-192": (6.3780e+06, 1.2e+03, "73.820 d"), + "Ir-193m": (9.098e+05, 3.5e+03, "10.53 d"), + "Ir-194m": (1.477e+07, 9.5e+05, "171 d"), + "Ir-194": (6.966e+04, 2.5e+02, "19.35 h"), + "Pt-191": (2.445e+05, 1.7e+03, "2.83 d"), + "Pt-193m": (3.741e+05, 2.6e+03, "4.33 d"), + "Pt-193": (1.58e+09, 1.9e+08, "50 y"), + "Pt-195m": (3.4646e+05, 4.3e+02, "4.010 d"), + "Pt-197m+": (5.725e+03, 1.1e+01, "95.41 m"), + "Pt-197": (7.16094e+04, 6.8e+00, "19.8915 h"), + "Pt-199m+": (1.35e+01, 1.6e-01, "13.48 s"), + "Pt-199t": (1.848e+03, 1.3e+01, "30.80 m"), + "Au-199": (2.7121e+05, 6.0e+02, "3.139 d"), + "Pt-200s": (4.54e+04, 1.1e+03, "12.6 h"), + "Au-196": (5.3266e+05, 9.5e+02, "6.165 d"), + "Au-197m": (7.73e+00, 6.0e-02, "7.73 s"), + "Au-198": (2.32817e+05, 1.2e+01, "2.69464 d"), + "Hg-197m*": (8.575e+04, 1.4e+02, "23.82 h"), + "Hg-197": (2.3375e+05, 2.5e+02, "64.93 h"), + "Hg-199m": (2.5602e+03, 5.4e+00, "42.67 m"), + "Hg-203": (4.02710e+06, 8.6e+02, "46.610 d"), + "Hg-205": (3.084e+02, 5.4e+00, "5.14 m"), + "Tl-202": (1.0636e+06, 6.9e+03, "12.31 d"), + "Tl-204": (1.1938e+08, 3.8e+05, "3.783 y"), + "Tl-206": (2.521e+02, 6.6e-01, "4.202 m"), + "Pb-203": (1.86926e+05, 5.4e+01, "51.924 h"), + "Pb-204m": (4.0158e+03, 6.0e+00, "66.93 m"), + "Pb-205": (5.36e+14, 2.8e+13, "17.0 My"), + "Pb-209": (1.1646e+04, 1.8e+01, "3.235 h"), + "Bi-210ms": (9.59e+13, 1.9e+12, "3.04 My"), + "Bi-210t": (4.3304e+05, 4.3e+02, "5.012 d"), + "Po-210": (1.195569e+07, 1.7e+02, "138.376 d"), + "Bi-211": (1.284e+02, 1.2e+00, "2.14 m"), +} + def demo(): # pragma: nocover import sys import argparse diff --git a/test/test_activation.py b/test/test_activation.py index 7e2bba6..5218387 100644 --- a/test/test_activation.py +++ b/test/test_activation.py @@ -64,27 +64,25 @@ def _get_Au_activity(fluence=1e5): # "Co-60": [1.55042700053951E-01, 1.55040373560730E-01, 1.54986873850802E-01], # "Co-61": [1.36469792582999E-09, 8.96670432174800E-10, 5.71936948464344E-14], # } - # Results from R2.0.0-pre - results = { - "Co-60m+": [5.08746786932552e+03, 9.69014499692868e+01, 2.64477047705988e-38], - "Co-61": [7.30866736559643e-09, 4.80170831653643e-09, 3.05646958051663e-13], - "Co-60": [1.55056574647797e-01, 1.55054247452235e-01, 1.55000731593431e-01], - "Co-61": [1.36478223029061e-09, 8.96645839472098e-10, 5.70749106813738e-14], - } + # Results from R2.1.0-pre, with halflife updated to NUBASE2020 + results = [ + ("Co-60m+", [5.08870610591228E+03, 9.57100873523175E+01, 1.95440969864725E-38]), + ("Co-61", [7.29613649387052E-09, 4.79211894136011E-09, 3.03056972241711E-13]), + ("Co-60", [1.54971558843742E-01, 1.54969234199432E-01, 1.54915777003567E-01]), + ("Co-61", [1.36558180150732E-09, 8.96917213990930E-10, 5.67216754320407E-14]), + ] #print(list(sample.activity.keys())) #print(" ".join(k for k in dir(list(sample.activity.keys())[0]) if k[0] != '_')) #print(list(sample.activity.keys())[0].__dict__) - for product, activity in sample.activity.items(): + for k, (product, activity) in enumerate(sample.activity.items()): #print(product) #print(dir(product)) # Uncomment to show new table values - activity_str = ",\t".join(f"{Ia:.14E}" for Ia in activity) - #print(f' "{product.daughter}":\t[{activity_str}],') - assert product.daughter in results, f"Missing {product.daughter}" - # TODO: include duplicate decay paths in test, or identical daughters + #activity_str = ",\t".join(f"{Ia:.14E}" for Ia in activity) + #print(f' ("{product.daughter}", [{activity_str}]),') + assert product.daughter == results[k][0], f"Expected {product.daughter} but got {results[k][0]}" # Test that results haven't changed since last update - if product.daughter != "Co-61": - assert np.allclose(results[product.daughter], activity, atol=0, rtol=1e-12) + assert np.allclose(results[k][1], activity, atol=0, rtol=1e-12) # 129-I has a long half-life (16 My) so any combination of exposure # fluence and mass that causes significant activation will yield a product From 286e8c1e99008936858a158cb4d872359b53a79e Mon Sep 17 00:00:00 2001 From: Paul Kienzle Date: Tue, 23 Dec 2025 18:54:12 -0500 Subject: [PATCH 2/2] Fix doctest to use updated halflife string --- periodictable/activation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/periodictable/activation.py b/periodictable/activation.py index a3658de..656165c 100644 --- a/periodictable/activation.py +++ b/periodictable/activation.py @@ -86,8 +86,8 @@ ----------------- activity (uCi) ------------------ isotope product reaction half-life 0 hrs 1 hrs 24 hrs 360 hrs -------- --------- -------- ---------- ------------ ------------ ------------ ------------ - Co-59 Co-60 act 5.272 y 0.0004957 0.0004957 0.0004955 0.000493 - Co-59 Co-60m+ act 10.5 m 1.664 0.03129 --- --- + Co-59 Co-60 act 5.2714 y 0.0004957 0.0004957 0.0004955 0.000493 + Co-59 Co-60m+ act 10.467 m 1.664 0.03129 --- --- -------- --------- -------- ---------- ------------ ------------ ------------ ------------ total 1.664 0.03181 0.0005079 0.0005045 -------- --------- -------- ---------- ------------ ------------ ------------ ------------