Coverage for /builds/ase/ase/ase/data/isotopes.py: 77.27%
22 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
1# fmt: off
3"""Isotope data extracted from NIST public website.
5Source data has been compiled by NIST:
7 https://www.nist.gov/pml/atomic-weights-and-isotopic-compositions-relative-atomic-masses
9The atomic weights data were published in:
11 J. Meija et al, Atomic weights of the elements 2013,
12 Pure and Applied Chemistry 88, 265-291 (2016).
13 https://doi.org/10.1515/pac-2015-0305
14 http://www.ciaaw.org/atomic-weights.htm
16Isotopic compositions data were published in:
18 Michael Berglund and Michael E. Wieser,
19 Isotopic compositions of the elements 2009 (IUPAC Technical Report)
20 Pure Appl. Chem., 2011, Vol. 83, No. 2, pp. 397-410
21 https://doi.org/10.1351/PAC-REP-10-06-02
23The relative atomic masses of the isotopes data were published in:
25 M. Wang, G. Audi, A.H. Wapstra, F.G. Kondev, M. MacCormick, X. Xu,
26 and B. Pfeiffer, The AME2012 Atomic Mass Evaluation,
27 Chinese Phys. C 36 1603
28 https://doi.org/10.1088/1674-1137/36/12/003
29 http://amdc.impcas.ac.cn/evaluation/data2012/ame.html
30"""
31from urllib import request
34def download_isotope_data():
35 """Download isotope data from NIST public website.
37 Relative atomic masses of individual isotopes their abundance
38 (mole fraction) are compiled into a dictionary. Individual items can be
39 indexed by the atomic number and mass number, e.g. titanium-48:
41 >>> from ase.data.isotopes import download_isotope_data
42 >>> isotopes = download_isotope_data()
43 >>> isotopes[22][48]['mass']
44 47.94794198
45 >>> isotopes[22][48]['composition']
46 0.7372
47 """
49 url = 'http://physics.nist.gov/cgi-bin/Compositions/stand_alone.pl' \
50 '?ele=&ascii=ascii&isotype=all'
52 with request.urlopen(url) as fd:
53 txt = fd.read()
55 raw_data = txt.decode().splitlines()
57 return parse_isotope_data(raw_data)
60def parse_isotope_data(raw_data):
61 # In the list of raw data, a string containing only a series of underscores
62 # preceeds the data for each element. So by getting the indexes of these
63 # strings, we are recording where in the data each element starts
64 indexes = [idx for (idx, line) in enumerate(raw_data) if "_____" in line]
66 isotopes = {}
67 for idx1, idx2 in zip(indexes, indexes[1:]):
68 atomic_number = int(raw_data[idx1 + 1].split()[0])
69 isotopes[atomic_number] = dct = {}
70 for isotope_idx in range(idx1 + 1, idx2):
71 mass_number = int(raw_data[isotope_idx][8:12])
72 # drop uncertainty
73 mass = float(raw_data[isotope_idx][13:31].split('(')[0])
74 try:
75 composition = float(raw_data[isotope_idx][32:46].split('(')[0])
76 except ValueError:
77 composition = 0.0
78 dct[mass_number] = {'mass': mass, 'composition': composition}
80 return isotopes