nuclearmasses 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. nuclearmasses-0.0.1/.github/workflows/tests.yml +24 -0
  2. nuclearmasses-0.0.1/.gitignore +21 -0
  3. nuclearmasses-0.0.1/LICENSE +21 -0
  4. nuclearmasses-0.0.1/PKG-INFO +35 -0
  5. nuclearmasses-0.0.1/README.md +4 -0
  6. nuclearmasses-0.0.1/nuclearmasses/__init__.py +0 -0
  7. nuclearmasses-0.0.1/nuclearmasses/ame_mass_file.py +56 -0
  8. nuclearmasses-0.0.1/nuclearmasses/ame_mass_parse.py +55 -0
  9. nuclearmasses-0.0.1/nuclearmasses/ame_reaction_1_file.py +72 -0
  10. nuclearmasses-0.0.1/nuclearmasses/ame_reaction_1_parse.py +61 -0
  11. nuclearmasses-0.0.1/nuclearmasses/ame_reaction_2_file.py +72 -0
  12. nuclearmasses-0.0.1/nuclearmasses/ame_reaction_2_parse.py +64 -0
  13. nuclearmasses-0.0.1/nuclearmasses/data/2003/mass.mas03 +3218 -0
  14. nuclearmasses-0.0.1/nuclearmasses/data/2003/nubtab03.asc +4468 -0
  15. nuclearmasses-0.0.1/nuclearmasses/data/2003/rct1.mas03 +3218 -0
  16. nuclearmasses-0.0.1/nuclearmasses/data/2003/rct2.mas03 +3218 -0
  17. nuclearmasses-0.0.1/nuclearmasses/data/2012/mass.mas12 +3392 -0
  18. nuclearmasses-0.0.1/nuclearmasses/data/2012/nubtab12.asc +5511 -0
  19. nuclearmasses-0.0.1/nuclearmasses/data/2012/rct1.mas12 +3392 -0
  20. nuclearmasses-0.0.1/nuclearmasses/data/2012/rct2.mas12 +3392 -0
  21. nuclearmasses-0.0.1/nuclearmasses/data/2016/mass16.txt +3475 -0
  22. nuclearmasses-0.0.1/nuclearmasses/data/2016/nubase2016.txt +5625 -0
  23. nuclearmasses-0.0.1/nuclearmasses/data/2016/rct1-16.txt +3475 -0
  24. nuclearmasses-0.0.1/nuclearmasses/data/2016/rct2-16.txt +3475 -0
  25. nuclearmasses-0.0.1/nuclearmasses/data/2020/mass.mas20 +3594 -0
  26. nuclearmasses-0.0.1/nuclearmasses/data/2020/nubase_1.mas20 +5869 -0
  27. nuclearmasses-0.0.1/nuclearmasses/data/2020/rct1.mas20 +3593 -0
  28. nuclearmasses-0.0.1/nuclearmasses/data/2020/rct2.mas20 +3660 -0
  29. nuclearmasses-0.0.1/nuclearmasses/mass_table.py +126 -0
  30. nuclearmasses-0.0.1/nuclearmasses/nubase_file.py +85 -0
  31. nuclearmasses-0.0.1/nuclearmasses/nubase_parse.py +137 -0
  32. nuclearmasses-0.0.1/nuclearmasses/parse.py +46 -0
  33. nuclearmasses-0.0.1/nuclearmasses.egg-info/PKG-INFO +35 -0
  34. nuclearmasses-0.0.1/nuclearmasses.egg-info/SOURCES.txt +44 -0
  35. nuclearmasses-0.0.1/nuclearmasses.egg-info/dependency_links.txt +1 -0
  36. nuclearmasses-0.0.1/nuclearmasses.egg-info/requires.txt +5 -0
  37. nuclearmasses-0.0.1/nuclearmasses.egg-info/top_level.txt +1 -0
  38. nuclearmasses-0.0.1/pyproject.toml +64 -0
  39. nuclearmasses-0.0.1/setup.cfg +4 -0
  40. nuclearmasses-0.0.1/tests/__init__.py +0 -0
  41. nuclearmasses-0.0.1/tests/test_ame_mass_parse.py +69 -0
  42. nuclearmasses-0.0.1/tests/test_ame_reaction_1_parse.py +85 -0
  43. nuclearmasses-0.0.1/tests/test_ame_reaction_2_parse.py +85 -0
  44. nuclearmasses-0.0.1/tests/test_mass_table.py +56 -0
  45. nuclearmasses-0.0.1/tests/test_nubase_parse.py +105 -0
  46. nuclearmasses-0.0.1/tests/test_parse.py +34 -0
@@ -0,0 +1,24 @@
1
+ name: Unit Tests
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ python-version: ['3.10', '3.11', '3.12', '3.13']
11
+
12
+ steps:
13
+ - name: Checkout repository
14
+ - uses: actions/checkout@v4
15
+ - name: Set up Python ${{ matrix.python-version }}
16
+ uses: actions/setup-python@v5
17
+ with:
18
+ python-version: ${{ matrix.python-version }}
19
+ - name: Install dependencies
20
+ run: |
21
+ python -m pip install --upgrade pip
22
+ pip install -e .
23
+ - name: Test with pytest
24
+ run: pytest -v
@@ -0,0 +1,21 @@
1
+ # Files and directories created by python
2
+ **/__pycache__/
3
+ **/.pytest_cache
4
+
5
+ # A catch all for virtual env directories
6
+ .venv*/
7
+ venv*/
8
+
9
+ # PyCharm settings directory
10
+ .idea/
11
+
12
+ # Jupyter related files and directories
13
+ *.ipynb
14
+ .ipynb_checkpoints/
15
+
16
+ # Test coverage related files and directories
17
+ .coverage
18
+ coverage_html_report
19
+
20
+ # Package build files and folders
21
+ *.egg-info/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,35 @@
1
+ Metadata-Version: 2.4
2
+ Name: nuclearmasses
3
+ Version: 0.0.1
4
+ Summary: A python package to parse and store the various files published by AME and NUBASE
5
+ Author: Ian Cullen, Soham Pal
6
+ Project-URL: GitHub, https://github.com/php1ic/nuclearmasses
7
+ Keywords: nuclear,physics,decay,AME,NUBASE
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Education
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Topic :: Education
21
+ Classifier: Topic :: Scientific/Engineering
22
+ Classifier: Topic :: Scientific/Engineering :: Physics
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: pandas
27
+ Requires-Dist: pytest
28
+ Provides-Extra: dev
29
+ Requires-Dist: coverage; extra == "dev"
30
+ Dynamic: license-file
31
+
32
+ # Nuclear Masses
33
+
34
+ Python package to parse the various files published by the AME and NUBASE.
35
+
@@ -0,0 +1,4 @@
1
+ # Nuclear Masses
2
+
3
+ Python package to parse the various files published by the AME and NUBASE.
4
+
File without changes
@@ -0,0 +1,56 @@
1
+ """Storage for variable line positions."""
2
+ from nuclearmasses.parse import Parse
3
+
4
+
5
+ class AMEMassFile(Parse):
6
+ """Easy access to where the variables are in the AME mass file."""
7
+
8
+ def __init__(self, year: int):
9
+ """Setup up the values."""
10
+ super().__init__()
11
+ if year < 2020:
12
+ self.HEADER = 39
13
+ self.FOOTER = None
14
+ self.START_A = 16
15
+ self.END_A = 19
16
+ self.START_Z = 11
17
+ self.END_Z = 14
18
+ self.START_ME = 29
19
+ self.END_ME = 41
20
+ self.START_DME = 42
21
+ self.END_DME = 53
22
+ self.START_BE_PER_A = 54
23
+ self.END_BE_PER_A = 64
24
+ self.START_DBE_PER_A = 65
25
+ self.END_DBE_PER_A = 72
26
+ self.START_BETA_DECAY_ENERGY = 76
27
+ self.END_BETA_DECAY_ENERGY = 86
28
+ self.START_DBETA_DECAY_ENERGY = 87
29
+ self.END_DBETA_DECAY_ENERGY = 95
30
+ self.START_MICRO_U = 100
31
+ self.END_MICRO_U = 112
32
+ self.START_MICRO_DU = 113
33
+ self.END_MICRO_DU = 125
34
+ else:
35
+ self.HEADER = 36
36
+ self.FOOTER = None
37
+ self.START_A = 16
38
+ self.END_A = 19
39
+ self.START_Z = 11
40
+ self.END_Z = 14
41
+ self.START_ME = 29
42
+ self.END_ME = 42
43
+ self.START_DME = 43
44
+ self.END_DME = 53
45
+ self.START_BE_PER_A = 56
46
+ self.END_BE_PER_A = 66
47
+ self.START_DBE_PER_A = 69
48
+ self.END_DBE_PER_A = 77
49
+ self.START_BETA_DECAY_ENERGY = 82
50
+ self.END_BETA_DECAY_ENERGY = 93
51
+ self.START_DBETA_DECAY_ENERGY = 95
52
+ self.END_DBETA_DECAY_ENERGY = 104
53
+ self.START_MICRO_U = 110
54
+ self.END_MICRO_U = 120
55
+ self.START_MICRO_DU = 124
56
+ self.END_MICRO_DU = 135
@@ -0,0 +1,55 @@
1
+ """Extract the data from the AME mass file."""
2
+ import logging
3
+ import pathlib
4
+
5
+ import pandas as pd
6
+
7
+ from nuclearmasses.ame_mass_file import AMEMassFile
8
+
9
+
10
+ class AMEMassParser(AMEMassFile):
11
+ """Parse the AME mass file.
12
+
13
+ The format is known but I don't think python can easily parse it.
14
+ """
15
+
16
+ def __init__(self, filename: pathlib.Path, year: int):
17
+ """Set the file to read and table year."""
18
+ self.filename = filename
19
+ self.year = year
20
+ super().__init__(self.year)
21
+ logging.info(f"Reading {self.filename} from {self.year}")
22
+
23
+ def _read_line(self, line: str) -> dict:
24
+ """Read a line from the file."""
25
+ if line.find("#") != -1:
26
+ line = line.replace("#", " ")
27
+
28
+ data = {
29
+ "TableYear": self.year,
30
+ "A": self._read_as_int(line, self.START_A, self.END_A),
31
+ "Z": self._read_as_int(line, self.START_Z, self.END_Z),
32
+ "AMEMassExcess": self._read_as_float(line, self.START_ME, self.END_ME),
33
+ "AMEMassExcessError": self._read_as_float(line, self.START_DME, self.END_DME),
34
+ "BindingEnergyPerA": self._read_as_float(line, self.START_BE_PER_A, self.END_BE_PER_A),
35
+ "BindingEnergyPerAError": self._read_as_float(line, self.START_DBE_PER_A, self.END_DBE_PER_A),
36
+ "BetaDecayEnergy": self._read_as_float(line, self.START_BETA_DECAY_ENERGY, self.END_BETA_DECAY_ENERGY),
37
+ "BetaDecayEnergyError": self._read_as_float(line, self.START_DBETA_DECAY_ENERGY, self.END_DBETA_DECAY_ENERGY),
38
+ "AtomicMass": self._read_as_float(line, self.START_MICRO_U, self.END_MICRO_U),
39
+ "AtomicMassError": self._read_as_float(line, self.START_MICRO_DU, self.END_MICRO_DU),
40
+ }
41
+
42
+ data["N"] = data["A"] - data["Z"]
43
+ data["Symbol"] = self.z_to_symbol[data["Z"]]
44
+
45
+ return data
46
+
47
+ def read_file(self) -> pd.DataFrame:
48
+ """Read the file."""
49
+ with open(self.filename, "r") as f:
50
+ lines = [line.rstrip() for line in f]
51
+
52
+ # Remove the header lines
53
+ lines = lines[self.HEADER: self.FOOTER]
54
+
55
+ return pd.DataFrame([self._read_line(line) for line in lines])
@@ -0,0 +1,72 @@
1
+ """Storage for the variable line positions."""
2
+ from nuclearmasses.parse import Parse
3
+
4
+
5
+ class AMEReactionFileOne(Parse):
6
+ """Easy access to where the variables are in the first AME reaction file."""
7
+
8
+ def __init__(self, year: int):
9
+ """Setup the values that locate the variable."""
10
+ super().__init__()
11
+ if year < 2020:
12
+ self.HEADER = 39
13
+ self.FOOTER = None
14
+ self.START_R1_A = 1
15
+ self.END_R1_A = 4
16
+ self.START_R1_Z = 8
17
+ self.END_R1_Z = 11
18
+ self.START_S2N = 14
19
+ self.END_S2N = 22
20
+ self.START_DS2N = 23
21
+ self.END_DS2N = 30
22
+ self.START_S2P = 32
23
+ self.END_S2P = 40
24
+ self.START_DS2P = 41
25
+ self.END_DS2P = 48
26
+ self.START_QA = 50
27
+ self.END_QA = 58
28
+ self.START_DQA = 59
29
+ self.END_DQA = 66
30
+ self.START_Q2B = 67
31
+ self.END_Q2B = 76
32
+ self.START_DQ2B = 77
33
+ self.END_DQ2B = 84
34
+ self.START_QEP = 85
35
+ self.END_QEP = 94
36
+ self.START_DQEP = 95
37
+ self.END_DQEP = 102
38
+ self.START_QBN = 103
39
+ self.END_QBN = 112
40
+ self.START_DQBN = 113
41
+ self.END_DQBN = 125
42
+ else:
43
+ self.HEADER = 35
44
+ self.FOOTER = None
45
+ self.START_R1_A = 1
46
+ self.END_R1_A = 4
47
+ self.START_R1_Z = 8
48
+ self.END_R1_Z = 11
49
+ self.START_S2N = 14
50
+ self.END_S2N = 24
51
+ self.START_DS2N = 25
52
+ self.END_DS2N = 34
53
+ self.START_S2P = 36
54
+ self.END_S2P = 46
55
+ self.START_DS2P = 47
56
+ self.END_DS2P = 56
57
+ self.START_QA = 58
58
+ self.END_QA = 68
59
+ self.START_DQA = 69
60
+ self.END_DQA = 78
61
+ self.START_Q2B = 79
62
+ self.END_Q2B = 90
63
+ self.START_DQ2B = 91
64
+ self.END_DQ2B = 100
65
+ self.START_QEP = 101
66
+ self.END_QEP = 112
67
+ self.START_DQEP = 113
68
+ self.END_DQEP = 122
69
+ self.START_QBN = 123
70
+ self.END_QBN = 134
71
+ self.START_DQBN = 135
72
+ self.END_DQBN = 144
@@ -0,0 +1,61 @@
1
+ """Extract the data from the first reaction file."""
2
+ import logging
3
+ import pathlib
4
+
5
+ import pandas as pd
6
+
7
+ from nuclearmasses.ame_reaction_1_file import AMEReactionFileOne
8
+
9
+
10
+ class AMEReactionParserOne(AMEReactionFileOne):
11
+ """Parse the first AME reaction file.
12
+
13
+ The format is known but I don't think python can easily parse it.
14
+ """
15
+
16
+ def __init__(self, filename: pathlib.Path, year: int):
17
+ """Set the file to read and table year."""
18
+ self.filename = filename
19
+ self.year = year
20
+ super().__init__(self.year)
21
+ logging.info(f"Reading {self.filename} from {self.year}")
22
+
23
+ def _read_line(self, line: str) -> dict:
24
+ """Read a line from the file."""
25
+ # Don't use a '#' as an experimental marker in this file
26
+ # but still need to remove it
27
+ if line.find("#") != -1:
28
+ line = line.replace("#", " ")
29
+
30
+ data = {
31
+ "TableYear": self.year,
32
+ "A": self._read_as_int(line, self.START_R1_A, self.END_R1_A),
33
+ "Z": self._read_as_int(line, self.START_R1_Z, self.END_R1_Z),
34
+ "TwoNeutronSeparationEnergy": self._read_as_float(line, self.START_S2N, self.END_S2N),
35
+ "TwoNeutronSeparationEnergyError": self._read_as_float(line, self.START_DS2N, self.END_DS2N),
36
+ "TwoProtonSeparationEnergy": self._read_as_float(line, self.START_S2P, self.END_S2P),
37
+ "TwoProtonSeparationEnergyError": self._read_as_float(line, self.START_DS2P, self.END_DS2P),
38
+ "QAlpha": self._read_as_float(line, self.START_QA, self.END_QA),
39
+ "QAlphaError": self._read_as_float(line, self.START_DQA, self.END_DQA),
40
+ "QTwoBeta": self._read_as_float(line, self.START_Q2B, self.END_Q2B),
41
+ "QTwoBetaError": self._read_as_float(line, self.START_DQ2B, self.END_DQ2B),
42
+ "QEpsilon": self._read_as_float(line, self.START_QEP, self.END_QEP),
43
+ "QEpsilonError": self._read_as_float(line, self.START_DQEP, self.END_DQEP),
44
+ "QBetaNeutron": self._read_as_float(line, self.START_QBN, self.END_QBN),
45
+ "QBetaNeutronError": self._read_as_float(line, self.START_DQBN, self.END_DQBN),
46
+ }
47
+
48
+ data["N"] = data["A"] - data["Z"]
49
+ data["Symbol"] = self.z_to_symbol[data["Z"]]
50
+
51
+ return data
52
+
53
+ def read_file(self) -> pd.DataFrame:
54
+ """Read the file."""
55
+ with open(self.filename, "r") as f:
56
+ lines = [line.rstrip() for line in f]
57
+
58
+ # Remove the header lines
59
+ lines = lines[self.HEADER: self.FOOTER]
60
+
61
+ return pd.DataFrame([self._read_line(line) for line in lines])
@@ -0,0 +1,72 @@
1
+ """Storage for the variable line positions."""
2
+ from nuclearmasses.parse import Parse
3
+
4
+
5
+ class AMEReactionFileTwo(Parse):
6
+ """Easy access to where the variables are in the second AME reaction file."""
7
+
8
+ def __init__(self, year: int):
9
+ """Setup the values that locate the variables."""
10
+ super().__init__()
11
+ if year < 2020:
12
+ self.HEADER = 39
13
+ self.FOOTER = None
14
+ self.START_R2_A = 1
15
+ self.END_R2_A = 4
16
+ self.START_R2_Z = 8
17
+ self.END_R2_Z = 11
18
+ self.START_SN = 14
19
+ self.END_SN = 22
20
+ self.START_DSN = 23
21
+ self.END_DSN = 30
22
+ self.START_SP = 32
23
+ self.END_SP = 40
24
+ self.START_DSP = 41
25
+ self.END_DSP = 48
26
+ self.START_Q4B = 49
27
+ self.END_Q4B = 58
28
+ self.START_DQ4B = 59
29
+ self.END_DQ4B = 66
30
+ self.START_QDA = 67
31
+ self.END_QDA = 76
32
+ self.START_DQDA = 77
33
+ self.END_DQDA = 84
34
+ self.START_QPA = 85
35
+ self.END_QPA = 94
36
+ self.START_DQPA = 95
37
+ self.END_DQPA = 102
38
+ self.START_QNA = 103
39
+ self.END_QNA = 112
40
+ self.START_DQNA = 113
41
+ self.END_DQNA = 125
42
+ else:
43
+ self.HEADER = 37
44
+ self.FOOTER = 3645
45
+ self.START_R2_A = 1
46
+ self.END_R2_A = 4
47
+ self.START_R2_Z = 8
48
+ self.END_R2_Z = 11
49
+ self.START_SN = 14
50
+ self.END_SN = 24
51
+ self.START_DSN = 25
52
+ self.END_DSN = 34
53
+ self.START_SP = 36
54
+ self.END_SP = 46
55
+ self.START_DSP = 47
56
+ self.END_DSP = 56
57
+ self.START_Q4B = 57
58
+ self.END_Q4B = 68
59
+ self.START_DQ4B = 69
60
+ self.END_DQ4B = 78
61
+ self.START_QDA = 79
62
+ self.END_QDA = 90
63
+ self.START_DQDA = 91
64
+ self.END_DQDA = 100
65
+ self.START_QPA = 101
66
+ self.END_QPA = 112
67
+ self.START_DQPA = 113
68
+ self.END_DQPA = 122
69
+ self.START_QNA = 123
70
+ self.END_QNA = 134
71
+ self.START_DQNA = 135
72
+ self.END_DQNA = 144
@@ -0,0 +1,64 @@
1
+ """Extract the date from the second reaction file."""
2
+ import logging
3
+ import pathlib
4
+
5
+ import pandas as pd
6
+
7
+ from nuclearmasses.ame_reaction_2_file import AMEReactionFileTwo
8
+
9
+
10
+ class AMEReactionParserTwo(AMEReactionFileTwo):
11
+ """Parse the second AME reaction file.
12
+
13
+ The format is known but I don't think python can easily parse it.
14
+ """
15
+
16
+ def __init__(self, filename: pathlib.Path, year: int):
17
+ """Set the file to read and table year."""
18
+ self.filename = filename
19
+ self.year = year
20
+ super().__init__(self.year)
21
+ logging.info(f"Reading {self.filename} from {self.year}")
22
+
23
+ def _read_line(self, line: str) -> dict:
24
+ """Read a line from the file."""
25
+ # Don't use a '#' as an experimental marker in this file
26
+ # but still need to remove it
27
+ if line.find("#") != -1:
28
+ line = line.replace("#", " ")
29
+
30
+ data = {
31
+ "TableYear": self.year,
32
+ "A": self._read_as_int(line, self.START_R2_A, self.END_R2_A),
33
+ "Z": self._read_as_int(line, self.START_R2_Z, self.END_R2_Z),
34
+ "OneNeutronSeparationEnergy": self._read_as_float(line, self.START_SN, self.END_SN),
35
+ "OneNeutronSeparationEnergyError": self._read_as_float(line, self.START_DSN, self.END_DSN),
36
+ "OneProtonSeparationEnergy": self._read_as_float(line, self.START_SP, self.END_SP),
37
+ "OneProtonSeparationEnergyError": self._read_as_float(line, self.START_DSP, self.END_DSP),
38
+ "QFourBeta": self._read_as_float(line, self.START_Q4B, self.END_Q4B),
39
+ "QFourBetaError": self._read_as_float(line, self.START_DQ4B, self.END_DQ4B),
40
+ "QDeuteronAlpha": self._read_as_float(line, self.START_QDA, self.END_QDA),
41
+ "QDeuteronAlphaError": self._read_as_float(line, self.START_DQDA, self.END_DQDA),
42
+ "QProtonAlpha": self._read_as_float(line, self.START_QPA, self.END_QPA),
43
+ "QProtonAlphaError": self._read_as_float(line, self.START_DQPA, self.END_DQPA),
44
+ "QNeutronAlpha": self._read_as_float(line, self.START_QNA, self.END_QNA),
45
+ "QNeutronAlphaError": self._read_as_float(line, self.START_DQNA, self.END_DQNA),
46
+ }
47
+
48
+ data["N"] = data["A"] - data["Z"]
49
+ data["Symbol"] = self.z_to_symbol[data["Z"]]
50
+
51
+ return data
52
+
53
+ def read_file(self) -> pd.DataFrame:
54
+ """Read the file."""
55
+ with open(self.filename, "r") as f:
56
+ lines = [line.rstrip() for line in f]
57
+
58
+ # Remove the header lines and the footer for the 2020 table
59
+ lines = lines[self.HEADER: self.FOOTER]
60
+
61
+ # The 2020 rct2 file has additional lines feeds not present in any other file
62
+ the_lines = [line for line in lines if line[:1] != "1"]
63
+
64
+ return pd.DataFrame([self._read_line(line) for line in the_lines])