Skip to content

Commit 19c024c

Browse files
author
soham
committed
Added read_fwf based implementation for AME.
1 parent ae7a0e9 commit 19c024c

File tree

3 files changed

+407
-0
lines changed

3 files changed

+407
-0
lines changed

src/pynch/ame.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import numpy as np
2+
import pandas as pd
3+
4+
from nuclearmasses.ame_formats import AME_MASS_FORMAT, AME_RCT1_FORMAT, AME_RCT2_FORMAT
5+
from nuclearmasses.parser import ELEMENTS, FWFParser
6+
7+
AME_YEARS = [1993, 1995, 2003, 2012, 2016, 2020]
8+
9+
10+
class AMEMassParser(FWFParser):
11+
"""Parses AME mass files."""
12+
13+
def __init__(self, year: int):
14+
if year not in AME_YEARS:
15+
raise ValueError(f"You must choose a year from {AME_YEARS}.")
16+
self.year = year
17+
18+
def _colspecs(self) -> dict[str, tuple[int, int]]:
19+
if self.year == 2020:
20+
return AME_MASS_FORMAT["2020"]
21+
if 2003 <= self.year <= 2016:
22+
return AME_MASS_FORMAT["2003"]
23+
if self.year <= 1995:
24+
return AME_MASS_FORMAT["1993"]
25+
26+
def _filespecs(self) -> dict[str, int]:
27+
if self.year == 2020:
28+
return {"header": 35, "footer": 0}
29+
if 2003 <= self.year <= 2016:
30+
return {"header": 38, "footer": 0}
31+
if self.year <= 1995:
32+
return {"header": 39, "footer": 0}
33+
34+
def _sanitize_data(self, df: pd.DataFrame) -> pd.DataFrame:
35+
to_float = [
36+
col for col in df.columns if col not in ["Z", "A", "BetaDecayChannel"]
37+
]
38+
for col in to_float:
39+
if "Error" not in col:
40+
df[col + "Extrapolated"] = df[col].str.endswith("#")
41+
df = df.replace("#", ".0", regex=True)
42+
df = df.replace("*", np.nan)
43+
df["AtomicMass"] = df["AtomicMass"].replace(" ", "", regex=True)
44+
df[to_float] = df[to_float].apply(pd.to_numeric)
45+
if self.year <= 1995:
46+
df["BindingEnergyPerNucleon"] = df["BindingEnergy"] / df["A"]
47+
df["BindingEnergyPerNucleonError"] = df["BindingEnergyError"] / df["A"]
48+
49+
df["N"] = df["A"] - df["Z"]
50+
df["Element"] = [ELEMENTS[z] for z in df["Z"]]
51+
df["TableYear"] = self.year
52+
53+
return df
54+
55+
56+
class AMEReactionParser(FWFParser):
57+
"""Parses AME reaction files."""
58+
59+
def __init__(self, year: int, rct: int):
60+
if year not in AME_YEARS:
61+
raise ValueError(f"You must choose a year from {AME_YEARS}.")
62+
self.year = year
63+
if rct != 1 and rct != 2:
64+
raise ValueError("rct must be either 1 or 2.")
65+
self.rct = rct
66+
self.rct_format = AME_RCT1_FORMAT if self.rct == 1 else AME_RCT2_FORMAT
67+
68+
def _colspecs(self) -> dict[str, tuple[int, int]]:
69+
if self.year == 2020:
70+
return self.rct_format["2020"]
71+
if self.year < 2020:
72+
return self.rct_format["1993"]
73+
74+
def _filespecs(self) -> dict[str, int]:
75+
if self.year == 2020:
76+
header = 35 if self.rct == 1 else 37
77+
footer = 0 if self.rct == 1 else 15
78+
return {"header": header, "footer": footer}
79+
if self.year < 2020:
80+
return {"header": 39, "footer": 0}
81+
82+
def _sanitize_data(self, df: pd.DataFrame) -> pd.DataFrame:
83+
to_float = [col for col in df.columns if col not in ["Z", "A"]]
84+
for col in to_float:
85+
if "Error" not in col:
86+
df[col + "Extrapolated"] = df[col].str.endswith("#")
87+
df = df.replace("#", ".0", regex=True)
88+
df = df.replace("*", np.nan)
89+
df[to_float] = df[to_float].apply(pd.to_numeric)
90+
91+
df["N"] = df["A"] - df["Z"]
92+
df["Element"] = [ELEMENTS[z] for z in df["Z"]]
93+
df["TableYear"] = self.year
94+
95+
return df

src/pynch/ame_formats.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
AME_MASS_FORMAT = {
2+
"2020": {
3+
"Z": (9, 14),
4+
"A": (14, 19),
5+
"MassExcess": (28, 42),
6+
"MassExcessError": (42, 54),
7+
"BindingEnergyPerNucleon": (54, 67),
8+
"BindingEnergyPerNucleonError": (68, 78),
9+
"BetaDecayChannel": (78, 81),
10+
"BetaDecayEnergy": (81, 94),
11+
"BetaDecayEnergyError": (94, 105),
12+
"AtomicMass": (106, 123),
13+
"AtomicMassError": (123, -1),
14+
},
15+
"2003": {
16+
"Z": (9, 14),
17+
"A": (14, 19),
18+
"MassExcess": (29, 41),
19+
"MassExcessError": (42, 53),
20+
"BindingEnergyPerNucleon": (54, 64),
21+
"BindingEnergyPerNucleonError": (65, 72),
22+
"BetaDecayChannel": (72, 76),
23+
"BetaDecayEnergy": (76, 86),
24+
"BetaDecayEnergyError": (87, 95),
25+
"AtomicMass": (96, 112),
26+
"AtomicMassError": (113, -1),
27+
},
28+
"1993": {
29+
"Z": (10, 14),
30+
"A": (14, 19),
31+
"MassExcess": (29, 39),
32+
"MassExcessError": (40, 48),
33+
"BindingEnergy": (48, 60),
34+
"BindingEnergyError": (60, 69),
35+
"BetaDecayChannel": (72, 75),
36+
"BetaDecayEnergy": (75, 85),
37+
"BetaDecayEnergyError": (86, 94),
38+
"AtomicMass": (97, 110),
39+
"AtomicMassError": (111, -1),
40+
},
41+
}
42+
43+
AME_RCT1_FORMAT = {
44+
"2020": {
45+
"Z": (8, 11),
46+
"A": (1, 4),
47+
"TwoNeutronSeparationEnergy": (14, 24),
48+
"TwoNeutronSeparationEnergyError": (25, 34),
49+
"TwoProtonSeparationEnergy": (36, 46),
50+
"TwoProtonSeparationEnergyError": (47, 56),
51+
"QAlpha": (58, 68),
52+
"QAlphaError": (69, 78),
53+
"QTwoBeta": (79, 90),
54+
"QTwoBetaError": (91, 100),
55+
"QEpsilon": (101, 112),
56+
"QEpsilonError": (113, 122),
57+
"QBetaNeutron": (123, 134),
58+
"QBetaNeutronError": (135, -1),
59+
},
60+
"1993": {
61+
"Z": (8, 11),
62+
"A": (1, 4),
63+
"TwoNeutronSeparationEnergy": (14, 22),
64+
"TwoNeutronSeparationEnergyError": (22, 30),
65+
"TwoProtonSeparationEnergy": (32, 40),
66+
"TwoProtonSeparationEnergyError": (41, 48),
67+
"QAlpha": (49, 58),
68+
"QAlphaError": (59, 66),
69+
"QTwoBeta": (67, 76),
70+
"QTwoBetaError": (77, 84),
71+
"QEpsilon": (85, 94),
72+
"QEpsilonError": (95, 102),
73+
"QBetaNeutron": (103, 112),
74+
"QBetaNeutronError": (113, -1),
75+
},
76+
}
77+
78+
AME_RCT2_FORMAT = {
79+
"2020": {
80+
"Z": (8, 11),
81+
"A": (1, 4),
82+
"OneNeutronSeparationEnergy": (14, 24),
83+
"OneNeutronSeparationEnergyError": (25, 34),
84+
"OneProtonSeparationEnergy": (36, 46),
85+
"OneProtonSeparationEnergyError": (47, 56),
86+
"QFourBeta": (57, 68),
87+
"QFourBetaError": (69, 78),
88+
"QDeuteronAlpha": (79, 90),
89+
"QDeuteronAlphaError": (91, 100),
90+
"QProtonAlpha": (101, 112),
91+
"QProtonAlphaError": (113, 122),
92+
"QNeutronAlpha": (123, 134),
93+
"QNeutronAlphaError": (135, -1),
94+
},
95+
"1993": {
96+
"Z": (8, 11),
97+
"A": (1, 4),
98+
"OneNeutronSeparationEnergy": (14, 22),
99+
"OneNeutronSeparationEnergyError": (23, 30),
100+
"OneProtonSeparationEnergy": (32, 40),
101+
"OneProtonSeparationEnergyError": (41, 48),
102+
"QFourBeta": (49, 58),
103+
"QFourBetaError": (59, 66),
104+
"QDeuteronAlpha": (67, 76),
105+
"QDeuteronAlphaError": (77, 84),
106+
"QProtonAlpha": (85, 94),
107+
"QProtonAlphaError": (95, 102),
108+
"QNeutronAlpha": (103, 112),
109+
"QNeutronAlphaError": (113, -1),
110+
},
111+
}

0 commit comments

Comments
 (0)