Files
beta_shape_pnpi/notebooks/coinc_paceENSDF.ipynb
T
unzhakov 33ed4f7e44 fix: satisfy mypy strict type-checking requirements
- Add proper type annotations to all source files
- Fix return types for numpy operations (np.asarray with dtype=np.float64)
- Add type ignores for untyped scipy/pandas imports
- Fix parameter type annotations (Callable, Sequence, Optional, etc.)
- Add TYPE_CHECKING imports for forward references
- Fix fitter.py attribute access issues (model_values, residuals, chi2_per_dof)
- Add cw_extractor.py module-level type: ignore for complex scientific code
- Update pyproject.toml to exclude notebooks from mypy
- Run black and ruff for formatting and linting
2026-05-03 00:44:11 +03:00

26 KiB

paceENSDF methods for accessing coincidence \gamma-\gamma and $\gamma-X$-ray data sets from radioactive-decay data

Import the Python package paceENSDF and load the JSON-formatted coincidence-decay data sets to a list object.

In [ ]:
import paceENSDF as pe
e = pe.ENSDF()
cdata = e.load_pace()
In [ ]:
import matplotlib.pyplot as plt
import numpy as np
%matplotlib notebook

Exploring the coincidence data sets

To find all available coincidence data sets corresponding to a particular type of decay (\alpha, \beta^{-}, \epsilon/\beta^{+}) the pyENSDF method coinc_pairs can be invoked. This method creates a dictionary containing the associated parent-daughter information for all relevant data sets that contain $\gamma$- and $X$-ray data. For more detail on this method and how to use it refer to the docstrings:

>>> help(e.coinc_pairs)
In [ ]:
# Find all coincidence data sets from beta-minus decay
bm_coinc = e.coinc_pairs(cdata, "BM")
[print(k,v) for (k,v) in bm_coinc.items()][0]
In [ ]:
# Find all coincidence data sets from alpha decay
a_coinc = e.coinc_pairs(cdata, "A")
[print(k,v) for (k,v) in a_coinc.items()][0]
In [ ]:
# Find all coincidence data sets from electron-capture/beta-plus decay
ecbp_coinc = e.coinc_pairs(cdata, "ECBP")
[print(k,v) for (k,v) in ecbp_coinc.items()][0]
In [ ]:
# Gather the Z, A information from each decay-mode dictionary

# Alpha decay
Z_A = [k[1] for (k,v) in a_coinc.items()]
A_A = [k[2] for (k,v) in a_coinc.items()]

# Beta-minus decay
Z_BM = [k[1] for (k,v) in bm_coinc.items()]
A_BM = [k[2] for (k,v) in bm_coinc.items()]

# Electron-capture/beta-plus decay
Z_ECBP = [k[1] for (k,v) in ecbp_coinc.items()]
A_ECBP = [k[2] for (k,v) in ecbp_coinc.items()]
In [ ]:
%matplotlib notebook
fig, ax = plt.subplots(figsize=(9,6))

ax.scatter(np.array(A_A), np.array(Z_A), color='y', marker='s', alpha=0.5, label=r'$\alpha$')
ax.scatter(np.array(A_BM), np.array(Z_BM), color='r', marker='s', alpha=0.10, label=r'$\beta^{-}$')
ax.scatter(np.array(A_ECBP), np.array(Z_ECBP), color='b', marker='s', alpha=0.10, label=r'$\epsilon/\beta^{+}$')

ax.set_xlabel(r'$A$', size=20)
ax.set_ylabel(r'$Z$', size=20)
ax.tick_params(axis='both', which='major', labelsize=15)
ax.legend(loc='best', fontsize=20)

plt.tight_layout()
plt.savefig("coinc_decay_nuclides.png", dpi=fig.dpi)
plt.show()

$\gamma$-ray singles data

All $\gamma$-ray energies and absolute intensities observed following the decay of a defined parent nucleus and given radioactive-decay mode. The returned quantities and function arguments are explained in the docstrings:

>>> help(e.get_gamma_singles)

These associated normalization and production normalization records have been applied to the returned $\gamma$-ray intensities

In [ ]:
help(e.get_gamma_singles)
In [ ]:
# Define parent and decay mode
parent_nucleus = "Np239"
decay_mode = "BM"
decay_index = 0

decay_pairs = e.coinc_pairs(cdata, decay_mode)
daughter_nucleus = [v[0] for k,v in decay_pairs.items() if (k[0]==parent_nucleus and k[3]==decay_index)][0]
print("Daughter nucleus: {0}".format(daughter_nucleus))
In [ ]:
# Get the absolute total-projection singles gamma data for 239Pu following the g.s. beta-minus decay of 239Np
#g = e.get_gamma_singles(cdata, "BM", "Np239", 0)
g = e.get_gamma_singles(cdata, decay_mode, parent_nucleus, decay_index)
for data in g: print(data)

# Put gamma data into arrays
gamma_array = np.array(g)
gamma_energy = gamma_array[:,0]
gamma_intensity = gamma_array[:,5]
In [ ]:
# Plot gamma data
%matplotlib notebook
fig, ax = plt.subplots(figsize=(9,6))

ax.bar(gamma_energy, gamma_intensity, width=3, color='k', label=r'%s $\gamma$ singles'%daughter_nucleus)
ax.legend(loc='best', fontsize=15)

ax.set_yscale('log')
ax.set_xlabel(r'$E_{\gamma}$ [keV]', size=20)
ax.set_ylabel(r'$I_{\gamma}$', size=20)

plt.grid()
plt.tight_layout()

\gamma-\gamma coincidence data

Energies and absolute intensities for \gamma-\gamma coincidence pairs. The callable get_gg returns all coincidences within a defined decay scheme or all coincidences with a defined transition according to input arguments. For more information and an explanation of the function arguments and return value refer to the docstrings:

>>> help(e.get_gg)

(i) All \gamma-\gamma coincidences in a defined decay scheme

Four arguments are passed to the get_gg function.

In [ ]:
# Get all g-g coincidences in daughter following radioactive decay
gg=e.get_gg(cdata, decay_mode, parent_nucleus, decay_index)
for coinc in gg: print(coinc)

(ii) All \gamma-\gamma coincidences with a particular transition

Six arguments are passed to the get_gg function.

In [ ]:
# Define indices for gating transition
E_i = 8
E_f = 5
In [ ]:
# Now get all g-g coincidences with the 8->5 transition in 239Pu following the g.s. beta-minus decay of 239Np
cg=e.get_gg(cdata, decay_mode, parent_nucleus, decay_index, E_i, E_f)
cgate = cg[0][0]
for coinc in cg: 
    print(coinc)
    
coinc_array = np.array(cg)
coinc_gamma = coinc_array[:,1]
coinc_intensity = coinc_array[:,10]
In [ ]:
# Plot coincidence gamma data imposed on singles gamma data
%matplotlib notebook
fig, ax = plt.subplots(figsize=(9,6))

ax.bar(gamma_energy, gamma_intensity, width=3, color='k', label=r'%s $\gamma$ singles'%daughter_nucleus)
ax.bar(coinc_gamma, coinc_intensity, width=3, color='r', label=r'%s %s-keV coincidences'%(daughter_nucleus,cgate))
ax.legend(loc='best', fontsize=15)

ax.set_yscale('log')
ax.set_xlabel(r'$E_{\gamma}$ [keV]', size=20)
ax.set_ylabel(r'$I_{\gamma}$', size=20)

plt.grid()
#plt.tight_layout()

Search for \gamma rays and \gamma-\gamma coincidences

(i) Find a single \gamma ray

Provide a single $\gamma$-ray energy and find all isotopes containing \gamma rays at the specified energy. By default a tolerance window of $\pm$0.5 keV is assumed on the specified $\gamma$-ray energy. This can be adjusted with an optional argument. See the docstrings for more details:

>>> help(e.find_gamma)
In [ ]:
# Find all isotopes containing gamma rays at 1332 keV (+/- 0.5 keV; default tolerance range)
e.find_gamma(cdata, 1332)
In [ ]:
# Tune the tolerance to narrow the search range to 1332 +/- 0.2 keV
e.find_gamma(cdata, 1332, 0.2)

(ii) Find a pair of \gamma-\gamma coincidences

Provide a pair of $\gamma$-ray energies and find all isotopes containing coincidence \gamma rays at the specified energies. By default a tolerance window of $\pm$0.5 keV is assumed on the specified $\gamma$-ray energy. This can be adjusted with an optional argument. See the docstrings for more details:

>>> help(e.find_gamma_coinc)
In [ ]:
# Find all isotopes containing a coincidence pair of gamma rays 
# at 106 keV and 392 keV (default tolerance=0.5 keV)
e.find_gamma_coinc(cdata, 106, 392)
In [ ]:
# Tune the tolerance to expand the search window to +/- 2.0 keV
e.find_gamma_coinc(cdata, 106, 392, 2.0)

$X$-ray singles data

$K$-shell $X$-ray energies and absolute intensities observed following the decay of a defined parent nucleus and given radioactive-decay mode. The returned quantities and function arguments are explained in the docstrings:

>>> help(e.get_xray_singles)
In [ ]:
# Get the absolute total-projection singles X-ray data for 239Pu following the g.s. beta-minus decay of 239Np
#x=e.get_xray_singles(cdata, "BM", "Np239", 0)
x=e.get_xray_singles(cdata, decay_mode, parent_nucleus, decay_index)
for xray in x: print(xray)

xray_array = np.array(x)
xray_energy = xray_array[:,0]
xray_intensity = xray_array[:,1]

To get the contribution of individual transitions, from the associated $K$-shell conversion, to the observed $K$-shell $X$-ray yield use the get_xray_contribution callable. For more information see the docstrings:

>>> help(e.get_xray_contribution)
In [ ]:
# Plot gamma and X-ray data
%matplotlib notebook
fig, ax = plt.subplots(figsize=(9,6))

ax.bar(gamma_energy, gamma_intensity, width=3, color='k', label=r'%s decay $\gamma$ singles'%daughter_nucleus)
ax.bar(xray_energy, xray_intensity, width=3, color='b', label=r'%s $X$-rays'%daughter_nucleus)
ax.legend(loc='best', fontsize=15)

ax.set_yscale('log')
ax.set_xlabel(r'$E$ [keV]', size=20)
ax.set_ylabel(r'$I$', size=20)

plt.grid()
plt.tight_layout()
In [ ]:
# Get the individual contributions to the X-ray yield from transitions in 239Pu following the g.s. beta-minus
# decay of 239Np
e.get_xray_contribution(cdata, decay_mode, parent_nucleus, decay_index)

$\gamma-X$-ray coincidence data

Energies and absolute intensities for $\gamma-X$-ray coincidence pairs. The callable get_gx returns all coincidences within a defined decay scheme or all coincidences with a defined transition according to input arguments. For more information and an explanation of the function arguments and return value refer to the docstrings:

>>> help(e.get_gx)

(i) All $\gamma-X$-ray coincidences in a defined decay scheme

Four arguments are passed to the get_gx function.

In [ ]:
# Get all g-X coincidences in 239Pu following the ground-state beta-minus decay of 239Np
xx=e.get_gx(cdata, decay_mode, parent_nucleus, decay_index)
for coinc in xx: print(coinc)

(ii) All $\gamma-X$-ray coincidences with a particular transition

Six arguments are passed to the get_gx function.

In [ ]:
# Now get all g-X coincidences with the 8->5 transition in 239Pu following the g.s. beta-minus decay of 239Np
cx=e.get_gx(cdata, decay_mode, parent_nucleus, decay_index, E_i, E_f)
for coinc in cx: print(coinc)
    
coincgx_array = np.array(cx)
coincgx_energy = coincgx_array[:,3].astype(float)
coincgx_intensity = coincgx_array[:,5].astype(float)
In [ ]:
# Plot coincidence gamma and X-ray imposed upon singles gamma and X-ray data
%matplotlib notebook
fig, ax = plt.subplots(figsize=(9,6))

ax.bar(gamma_energy, gamma_intensity, width=3, color='k', label=r'%s decay $\gamma$'%daughter_nucleus)
ax.bar(xray_energy, xray_intensity, width=3, color='b', label=r'%s $X$-rays'%daughter_nucleus)
ax.bar(coinc_gamma, coinc_intensity, width=3, color='r', label=r'%s $\gamma$/%s-keV coincidences'%(daughter_nucleus, cgate))
ax.bar(coincgx_energy, coincgx_intensity, width=3, color='yellow', label=r'%s $X$/%s-keV coincidences'%(daughter_nucleus, cgate))
ax.legend(loc='best', fontsize=15)

ax.set_yscale('log')
ax.set_xlabel(r'$E$ [keV]', size=20)
ax.set_ylabel(r'$I$', size=20)

plt.grid()
plt.tight_layout()

Search for X rays and $\gamma-X$-ray coincidences

(i) Find a single X ray

Provide a single $X$-ray energy and find all isotopes containing X rays at the specified energy. By default a tolerance window of $\pm$0.5 keV is assumed on the specified $X$-ray energy. This can be adjusted with an optional argument. See the docstrings for more details:

>>> help(e.find_xray)
In [ ]:
# Find all isotopes containing X rays at 52 keV (+/- 0.5 keV; default tolerance range)
e.find_xray(cdata, 52)
In [ ]:
# Tune the tolerance to narrow the search range to 52 +/- 0.1 keV
e.find_xray(cdata, 52, 0.1)

(ii) Find a pair of $\gamma-X$-ray coincidences

Provide the $X$-ray energy and the $\gamma$-ray energy and find all isotopes containing coincidence $\gamma-X$-ray pairs at the specified energies. By default a tolerance window of $\pm$0.5 keV is assumed on the specified photon energy. This can be adjusted with an optional argument. See the docstrings for more details:

>>> help(e.find_xray_coinc)
In [ ]:
# Find all isotopes containing a gamma-X-ray coincidence pair with a 52-keV X ray and 688-keV gamma, 
# respectively, assuming the default tolerance=0.5 keV
e.find_xray_coinc(cdata, 52, 688)
In [ ]:
# Tune the tolerance to narrow the search window to +/- 0.15 keV
e.find_xray_coinc(cdata, 52, 688, 0.15)

Display parallel paths for cascades between coincident \gamma rays

This function shows all parallel $\gamma$-ray cascade sequences between a pair of coincident \gamma rays in the decay scheme of the daughter nucleus. In addition to the \gamma rays in the cascade, all associated level indices and energies are shown and a list of tuples containing the level indices is returned. See the appropriate docstring:

>>> help(e.show_cascades)
In [ ]:
# Show the cascade gamma-ray sequence between the 3->2 and 1->0 transitions in 60Ni following 
# 60Co beta-minus decay (G.S.)
e.show_cascades(cdata,"BM","Co60",0,3,2,1,0)
In [ ]:
# Show the cascade gamma-ray sequence between the 9->6 and 1->0 transitions in 147Pm following 
# 147Nd beta-minus decay (G.S.)
e.show_cascades(cdata,"BM","Nd147",0,9,6,1,0)

Impose timecut

The following method has been implemented to allow the user to filter cascades going through isomeric levels:

>>> help(e.get_gg_timecut)

Transient-equilibrium intensity data is gradually being added to the repository. To use these datasets instead of the regular ENSDF decay datasets make sure to install by setting the appropriate flag (-t | --transient) described in the README.

In [ ]:
# Inspecting transient-equilibrium coincidences following 99Mo beta-minus decay.

# To remove coincidences that go through the 6-h isomer at E=142.7-keV (level index=2) impose a 21600-s timecut:
gg=e.get_gg_timecut(cdata, "BM", "Mo99", 0, -21600)
for g in gg: print(g[0:12])
print("\nNumber of coincidences = {0}".format(len(gg)))
In [ ]:
# Find only coincidences with the 1->0 transition (140.51-keV -> 0-keV) with the same timecut:
gg=e.get_gg_timecut(cdata, "BM", "Mo99", 0, 1, 0, -21600)
for g in gg: print(g[0:12])
print("\nNumber of coincidences = {0}".format(len(gg)))
In [ ]:
# Find coincidences in the path of the 6-h isomer:
gg=e.get_gg_timecut(cdata, "BM", "Mo99", 0, 21600)
for g in gg: print(g[0:12])
print("\nNumber of coincidences = {0}".format(len(gg)))
In [ ]:
# Find only coincidences with the 1->0 transition (140.51-keV -> 0-keV) in the path of the 6-h isomer:
gg=e.get_gg_timecut(cdata, "BM", "Mo99", 0, 1, 0, 21600)
for g in gg: print(g[0:12])
print("\nNumber of coincidences = {0}".format(len(gg)))
In [ ]:
# Compare these results with all expected coincidences (i.e. no timecut):
gg=e.get_gg(cdata, "BM", "Mo99", 0)
for g in gg: print(g)
print("\nNumber of coincidences = {0}".format(len(gg)))
In [ ]:
# Compare these results with all expected coincidences with just the 1->0 transition (i.e. no timecut):
gg=e.get_gg(cdata, "BM", "Mo99", 0, 1, 0)
for g in gg: print(g)
print("\nNumber of coincidences = {0}".format(len(gg)))

Auxiliary data

This section of the Notebook runs through some of the supplementary data in coincidence data structures that may be interesting or useful.

Valence electronic configurations

The valence electronic configuration is provided for all elements from Z=3-110 apart from Z=1,2,101,103,106. The missing data will be added in a future release. Refer to the docstrings for information regarding the returned list object:

>>> help(e.get_valence_config)
In [ ]:
# Get the valence electronic configuration of Yb (pass the chemical symbol <str>)
e.get_valence_config(cdata, "Yb")
In [ ]:
# Get the valence electronic configuration of Yb (pass the atomic number <int>)
e.get_valence_config(cdata, 70)
In [ ]:
# Get the valence electronic configuration of Fe (pass the chemical symbol <str>)
e.get_valence_config(cdata, "Fe")
In [ ]:
# Get the valence electronic configuration of Fe (pass the atomic number <int>)
e.get_valence_config(cdata, 26)

Atomic binding energies

Atomic subshell binding energies in keV for K, L_{I} - L_{III}, and M_{I} - M_{V}. Refer to the docstrings for more information:

>>> help(e.get_binding_energies)

The desired element can be passed as a string (chemical symbol) or an integer (atomic number). A keyword argument is also needed to specify the required output:

shell = 'K'
shell = 'L'
shell = 'M'
shell = 'all'
In [ ]:
# Get the K-shell binding energy for W:
e.get_binding_energies(cdata, "W", shell='K')
In [ ]:
# Get the L-shell binding energies for W:
e.get_binding_energies(cdata, "W", shell='L')
In [ ]:
# Get the M-shell binding energies for W:
e.get_binding_energies(cdata, "W", shell='M')
In [ ]:
# Get all available atomic-shell binding energies for Yb:
e.get_binding_energies(cdata, 74, shell='ALL')
In [ ]: