Skip to content

Commit 660ba7a

Browse files
Fix Ion formula parsing bug; add more special formulas (#3942)
* fix Ion parsing bug introduced by commit b4a70ee * Ion: special handling of CH4, NH4, N3-, SCN-, formate, oxalate * pre-commit auto-fixes * Element / Species - add n_electrons * Revert "Element / Species - add n_electrons" This reverts commit 97ea180. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 720fdf8 commit 660ba7a

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

src/pymatgen/core/ion.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,10 @@ def get_reduced_formula_and_factor(
173173
el_amt_dict = {k: int(round(v)) for k, v in comp.get_el_amt_dict().items()}
174174
formula, factor = reduce_formula(el_amt_dict, iupac_ordering=iupac_ordering)
175175

176-
if (self.composition.get("H") and self.composition.get("O")) is not None:
176+
# This line checks specifically that the contains an equal amount of O and H. When that is the case,
177+
# they should be displayed as "OH" rather than "HO".
178+
if self.composition.get("H") == self.composition.get("O"):
177179
formula = formula.replace("HO", "OH")
178-
179180
if nH2O > 0:
180181
formula += f".{nH2O}H2O"
181182

@@ -187,6 +188,13 @@ def get_reduced_formula_and_factor(
187188
elif formula == "H2CO":
188189
formula = "CH3COOH"
189190
factor /= 2
191+
# phosphoric acid system
192+
elif formula == "PH3O4":
193+
formula = "H3PO4"
194+
elif formula == "PHO4":
195+
formula = "HPO4"
196+
elif formula == "P(HO2)2":
197+
formula = "H2PO4"
190198
# acetate
191199
elif formula == "H3(CO)2":
192200
formula = "CH3COO"
@@ -205,6 +213,29 @@ def get_reduced_formula_and_factor(
205213
elif formula == "O" and factor % 3 == 0:
206214
formula = "O3"
207215
factor /= 3
216+
# ammonia
217+
elif formula == "H4N":
218+
formula = "NH4"
219+
elif formula == "H3N":
220+
formula = "NH3"
221+
# methane
222+
elif formula == "H4C":
223+
formula = "CH4"
224+
# thiocyanate
225+
elif formula == "CSN":
226+
formula = "SCN"
227+
# triiodide, nitride, an phosphide
228+
elif formula in ["I", "N", "P"] and self.charge == -1:
229+
formula += "3"
230+
factor /= 3
231+
# formate # codespell:ignore
232+
elif formula == "HCOO":
233+
formula = "HCO2"
234+
# oxalate
235+
elif formula == "CO2":
236+
formula = "C2O4"
237+
factor *= 2
238+
# diatomic gases
208239
elif formula in {"O", "N", "F", "Cl", "H"} and factor % 2 == 0:
209240
formula += "2"
210241
factor /= 2

tests/core/test_ion.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def test_charge_from_formula(self):
4646
assert Ion.from_formula("SO42-").charge == -1
4747
assert Ion.from_formula("SO4--").charge == -2
4848
assert Ion.from_formula("SO4[--]").charge == -2
49+
assert Ion.from_formula("N3-").charge == -1
4950

5051
assert Ion.from_formula("Na[+-+]").charge == 1
5152

@@ -59,19 +60,25 @@ def test_special_formulas(self):
5960
("O3", "O3(aq)"),
6061
("O2", "O2(aq)"),
6162
("N2", "N2(aq)"),
63+
("NaOH", "NaOH(aq)"),
6264
("H4O4", "H2O2(aq)"),
6365
("OH-", "OH[-1]"),
66+
("H2PO4-", "H2PO4[-1]"),
6467
("CH3COO-", "CH3COO[-1]"),
6568
("CH3COOH", "CH3COOH(aq)"),
6669
("CH3OH", "CH3OH(aq)"),
6770
("H4CO", "CH3OH(aq)"),
71+
("CH4", "CH4(aq)"),
72+
("NH4+", "NH4[+1]"),
73+
("NH3", "NH3(aq)"),
74+
("N3-", "N3[-1]"),
75+
("HCOO-", "HCO2[-1]"),
6876
("C2H6O", "C2H5OH(aq)"),
6977
("C3H8O", "C3H7OH(aq)"),
7078
("C4H10O", "C4H9OH(aq)"),
7179
("Fe(OH)4+", "Fe(OH)4[+1]"),
7280
("Zr(OH)4", "Zr(OH)4(aq)"),
7381
]
74-
7582
for tup in special_formulas:
7683
assert Ion.from_formula(tup[0]).reduced_formula == tup[1]
7784

0 commit comments

Comments
 (0)