X-ray emission from radionuclides#
Warning
This module is in beta and its API may change in future releases. It does not yet calculate the full decay chain or account for possible emissions from decay products. The emission from radionuclides which decay straight into stable nuclides should be accurate.
The purpose of this guide is to present an overview of the roentgen.nuclides module which provides access to tables of emission lines from radioactive sources (e.g. Am-241, Ba-133).
Radionuclides are unstable atoms that spontaneously and randomly decay into a different nuclide over time, emitting ionizing radiation in the process.
Those new nuclide may undergo a similar process leading to a chain of decay of different elements.
The radiation emitted may take the form of x-rays or gamma-rays with characteristic energies.
Because these characteristic energies are well-known and sealed sources of radiation are readily available, these sources are frequently used in laboratories to calibrate x-ray and gamma-ray detectors.
This module provides access to data from the Library for gamma and alpha emissions (Lara) provided by the Laboratoire National Henri Becquerel.
The list of available nuclides is available through:
>>> from roentgen.nuclides import nuclides_list
>>> print(nuclides_list)
symbol name mass_number filename half_life
yr
str2 str12 int64 str19 float64
------ ----------- ----------- ------------------- ----------------------
H Hydrogen 3 H-3_@00.lara.txt 12.310822115750247
He Helium 6 He-6_@00.lara.txt 2.5575772555580905e-08
Be Beryllium 7 Be-7_@00.lara.txt 0.1457018277689051
Be Beryllium 10 Be-10_@00.lara.txt 1393008.3403047125
C Carbon 11 C-11_@00.lara.txt 3.871333688239917e-05
N Nitrogen 13 N-13_@00.lara.txt 1.895011027454559e-05
... ... ... ... ...
Am Americium 244 Am-244_@00.lara.txt 0.0011521788729180924
Pu Plutonium 244 Pu-244_@00.lara.txt 81089816.71610008
Cm Curium 245 Cm-245_@00.lara.txt 8248.409257991734
Am Americium 245 Am-245_@00.lara.txt 0.00023385808806753364
Cm Curium 246 Cm-246_@00.lara.txt 4721.525084290313
Cm Curium 248 Cm-248_@00.lara.txt 347935.20419803786
Cf Californium 252 Cf-252_@00.lara.txt 2.646905975105838
To download the entire list nuclides_list.csv or view it online
To access a particular nuclide first initialize it:
>>> from roentgen.nuclides import Nuclide
>>> fe55 = Nuclide('Fe', 55)
>>> print(fe55.lines)
energy intensity origin parent
keV
float64 float64 str7 str7
------- --------- ------- ------
0.6635 0.523 Mn Fe-55
5.88772 8.4 Mn Fe-55
5.89881 16.48 Mn Fe-55
6.513 3.38 Mn Fe-55
125.949 1.3e-07 Mn-55 Fe-55
For nuclides with complicated decay chains this may be too much information. This module therefore provides a convenience function to filter the list. For example, Am-241 has a long decay chain generating 873 different lines some of them very weak. We can there filter the list to only the strongest lines within a particular energy range::
>>> import astropy.units as u
>>> am241 = Nuclide('Am', 241)
>>> strong_lines = am241.get_lines(5 * u.keV, 100 * u.keV, min_intensity=5)
>>> print(strong_lines)
energy intensity origin parent
keV
-------- --------- ------- ------
12.20145 8.04 Pb Tl-209
13.852 13.02 Np Am-241
14.08955 19.0 Fr Ac-225
14.89645 13.6 Ac Ra-225
15.7405 59.7 Pa Np-237
16.1665 40.6 U Pa-233
16.96 18.58 Np Am-241
29.374 14.3 Pa-233 Np-237
40.09 30.0 Ac-225 Ra-225
59.5409 35.92 Np-237 Am-241
72.8049 5.85 Pb Tl-209
74.97 9.84 Pb Tl-209
86.477 12.26 Pa-233 Np-237
94.666 9.1 U Pa-233
98.44 14.6 U Pa-233
The Nuclide class also provides access to some additional information such as the half life
>>> print(am241.half_life)
432.6057748371232 yr
and the url for the data sheet
>>> print(am241.data_sheet)
http://www.lnhb.fr/nuclides/Am-241_tables.pdf
All other metadata is available in meta attribute
>>> print(am241.meta)
{'Nuclide': 'Am-241', 'Element': 'Americium', 'Z': 95.0, 'Daughter(s)': [{'decay_mode': 'alpha', 'element': 'Np', 'mass_number': 237, 'branching_ratio': 100.0}], 'Qalpha': 5637.82, 'Possible parent(s)': '(B-)', 'Half-life (a)': <Quantity 432.6 yr>, 'Half-life (s)': <Quantity 1.3652e+10 s>, 'Decay constant (1/s)': <Quantity 5.077e-11 1 / s>, 'Specific activity (Bq/g)': <Quantity 1.2688e+11 Bq / g>, 'Reference': 'KRI - 2009'}
Ba-133 Example Spectrum#
As an example, let’s consider the nuclide Ba-133. This nuclide decays through electron capture into Cs-133, emitting a number of gamma-rays and x-rays in the process. The strongest emissions are at 31 keV, 81 keV, and 356 keV.
>>> from roentgen.nuclides import Nuclide
>>> ba133 = Nuclide('Ba', 133)
>>> print(ba133)
Nuclide: Ba-133, (Barium) half life=10.538824245189748 yr - (14 lines)
Daughters: [{'decay_mode': 'EC', 'element': 'Cs', 'mass_number': 133, 'branching_ratio': 100.0}]
<QTable length=14>
energy intensity origin parent
keV
float64 float64 str7 str7
-------- --------- ------- ------
4.67355 15.87 Cs-133 Ba-133
30.6254 33.8 Cs-133 Ba-133
30.9731 62.4 Cs-133 Ba-133
35.053 18.24 Cs-133 Ba-133
35.9003 4.45 Cs-133 Ba-133
53.1622 2.14 Cs-133 Ba-133
79.6142 2.63 Cs-133 Ba-133
80.9979 33.31 Cs-133 Ba-133
160.6121 0.638 Cs-133 Ba-133
223.2368 0.45 Cs-133 Ba-133
276.3989 7.13 Cs-133 Ba-133
302.8508 18.31 Cs-133 Ba-133
356.0129 62.05 Cs-133 Ba-133
383.8485 8.94 Cs-133 Ba-133
With this information, it is possible to simulate the emission from a radionuclide as it would be seen by a detector with a finite energy resolution. In the following example, we will simulate the emission from a Ba-133 source as it would be seen by a detector with a 0.5 keV energy resolution up to 80 keV. Given this energy resolution, the individual lines will be broadened and will overlap.
import numpy as np
import astropy.units as u
from astropy.modeling.models import Gaussian1D
from astropy import visualization
from matplotlib import pyplot as plt
from roentgen.nuclides import Nuclide
ba133 = Nuclide('Ba', 133)
lines = ba133.get_lines(1 * u.keV, 100 * u.keV, min_intensity=1)
energy_resolution = 0.5 * u.keV
g0 = Gaussian1D(amplitude=lines[0]['intensity'], mean=lines[0]['energy'], stddev=energy_resolution)
for this_line in lines[1:]:
g0 += Gaussian1D(amplitude=this_line['intensity'], mean=this_line['energy'], stddev=energy_resolution)
energy_ax = np.arange(1, 85, 0.5) * u.keV
with visualization.quantity_support():
fig, ax = plt.subplots()
ax.plot(energy_ax, g0(energy_ax))
ax.set_xlabel(f'Energy')
ax.vlines(lines['energy'], ymin=[0]*len(lines), ymax=lines['intensity'])
plt.show()
(Source code, png, hires.png, pdf)