11
11
import warnings
12
12
from functools import total_ordering
13
13
from itertools import combinations_with_replacement , product
14
+ from math import isnan
14
15
from typing import TYPE_CHECKING , Union , cast
15
16
16
17
from monty .fractions import gcd , gcd_float
@@ -122,17 +123,19 @@ def __init__(self, *args, strict: bool = False, **kwargs) -> None:
122
123
if len (args ) == 1 and isinstance (args [0 ], Composition ):
123
124
elem_map = args [0 ]
124
125
elif len (args ) == 1 and isinstance (args [0 ], str ):
125
- elem_map = self ._parse_formula (args [0 ]) # type: ignore
126
+ elem_map = self ._parse_formula (args [0 ]) # type: ignore[assignment]
127
+ elif len (args ) == 1 and isinstance (args [0 ], float ) and isnan (args [0 ]):
128
+ raise ValueError ("float('NaN') is not a valid Composition, did you mean str('NaN')?" )
126
129
else :
127
130
elem_map = dict (* args , ** kwargs ) # type: ignore
128
131
elem_amt = {}
129
- self ._natoms = 0
132
+ self ._n_atoms = 0
130
133
for key , val in elem_map .items ():
131
134
if val < - Composition .amount_tolerance and not self .allow_negative :
132
135
raise ValueError ("Amounts in Composition cannot be negative!" )
133
136
if abs (val ) >= Composition .amount_tolerance :
134
137
elem_amt [get_el_sp (key )] = val
135
- self ._natoms += abs (val )
138
+ self ._n_atoms += abs (val )
136
139
self ._data = elem_amt
137
140
if strict and not self .valid :
138
141
raise ValueError (f"Composition is not valid, contains: { ', ' .join (map (str , self .elements ))} " )
@@ -201,8 +204,8 @@ def __add__(self, other: object) -> Composition:
201
204
202
205
new_el_map : dict [SpeciesLike , float ] = collections .defaultdict (float )
203
206
new_el_map .update (self )
204
- for k , v in other .items ():
205
- new_el_map [get_el_sp (k )] += v
207
+ for key , val in other .items ():
208
+ new_el_map [get_el_sp (key )] += val
206
209
return Composition (new_el_map , allow_negative = self .allow_negative )
207
210
208
211
def __sub__ (self , other : object ) -> Composition :
@@ -219,8 +222,8 @@ def __sub__(self, other: object) -> Composition:
219
222
220
223
new_el_map : dict [SpeciesLike , float ] = collections .defaultdict (float )
221
224
new_el_map .update (self )
222
- for k , v in other .items ():
223
- new_el_map [get_el_sp (k )] -= v
225
+ for key , val in other .items ():
226
+ new_el_map [get_el_sp (key )] -= val
224
227
return Composition (new_el_map , allow_negative = self .allow_negative )
225
228
226
229
def __mul__ (self , other : object ) -> Composition :
@@ -323,7 +326,7 @@ def fractional_composition(self) -> Composition:
323
326
1.
324
327
E.g. "Fe2 O3".fractional_composition = "Fe0.4 O0.6".
325
328
"""
326
- return self / self ._natoms
329
+ return self / self ._n_atoms
327
330
328
331
@property
329
332
def reduced_composition (self ) -> Composition :
@@ -362,7 +365,7 @@ def get_reduced_formula_and_factor(self, iupac_ordering: bool = False) -> tuple[
362
365
all_int = all (abs (x - round (x )) < Composition .amount_tolerance for x in self .values ())
363
366
if not all_int :
364
367
return self .formula .replace (" " , "" ), 1
365
- d = {k : int (round (v )) for k , v in self .get_el_amt_dict ().items ()}
368
+ d = {key : int (round (val )) for key , val in self .get_el_amt_dict ().items ()}
366
369
formula , factor = reduce_formula (d , iupac_ordering = iupac_ordering )
367
370
368
371
if formula in Composition .special_formulas :
@@ -395,7 +398,7 @@ def get_integer_formula_and_factor(
395
398
el_amt = self .get_el_amt_dict ()
396
399
gcd = gcd_float (list (el_amt .values ()), 1 / max_denominator )
397
400
398
- dct = {k : round (v / gcd ) for k , v in el_amt .items ()}
401
+ dct = {key : round (val / gcd ) for key , val in el_amt .items ()}
399
402
formula , factor = reduce_formula (dct , iupac_ordering = iupac_ordering )
400
403
if formula in Composition .special_formulas :
401
404
formula = Composition .special_formulas [formula ]
@@ -439,7 +442,7 @@ def elements(self) -> list[Element | Species | DummySpecies]:
439
442
return list (self )
440
443
441
444
def __str__ (self ) -> str :
442
- return " " .join (f"{ k } { formula_double_format (v , ignore_ones = False )} " for k , v in self .as_dict ().items ())
445
+ return " " .join (f"{ key } { formula_double_format (val , ignore_ones = False )} " for key , val in self .as_dict ().items ())
443
446
444
447
def to_pretty_string (self ) -> str :
445
448
"""
@@ -453,7 +456,7 @@ def num_atoms(self) -> float:
453
456
"""Total number of atoms in Composition. For negative amounts, sum
454
457
of absolute values.
455
458
"""
456
- return self ._natoms
459
+ return self ._n_atoms
457
460
458
461
@property
459
462
def weight (self ) -> float :
@@ -469,7 +472,7 @@ def get_atomic_fraction(self, el: SpeciesLike) -> float:
469
472
Returns:
470
473
Atomic fraction for element el in Composition
471
474
"""
472
- return abs (self [el ]) / self ._natoms
475
+ return abs (self [el ]) / self ._n_atoms
473
476
474
477
def get_wt_fraction (self , el : SpeciesLike ) -> float :
475
478
"""Calculate weight fraction of an Element or Species.
@@ -605,7 +608,7 @@ def valid(self) -> bool:
605
608
return not any (isinstance (el , DummySpecies ) for el in self .elements )
606
609
607
610
def __repr__ (self ) -> str :
608
- formula = " " .join (f"{ k } { ':' if hasattr (k , 'oxi_state' ) else '' } { v :g} " for k , v in self .items ())
611
+ formula = " " .join (f"{ key } { ':' if hasattr (key , 'oxi_state' ) else '' } { val :g} " for key , val in self .items ())
609
612
cls_name = type (self ).__name__
610
613
return f"{ cls_name } ({ formula !r} )"
611
614
@@ -1250,20 +1253,20 @@ def __init__(self, *args, **kwargs) -> None:
1250
1253
**kwargs: any valid dict init arguments.
1251
1254
"""
1252
1255
dct = dict (* args , ** kwargs )
1253
- super ().__init__ ((get_el_sp (k ), v ) for k , v in dct .items ())
1256
+ super ().__init__ ((get_el_sp (key ), val ) for key , val in dct .items ())
1254
1257
if len (dct ) != len (self ):
1255
1258
raise ValueError ("Duplicate potential specified" )
1256
1259
1257
1260
def __mul__ (self , other : object ) -> ChemicalPotential :
1258
1261
if isinstance (other , (int , float )):
1259
- return ChemicalPotential ({k : v * other for k , v in self .items ()})
1262
+ return ChemicalPotential ({key : val * other for key , val in self .items ()})
1260
1263
return NotImplemented
1261
1264
1262
1265
__rmul__ = __mul__
1263
1266
1264
1267
def __truediv__ (self , other : object ) -> ChemicalPotential :
1265
1268
if isinstance (other , (int , float )):
1266
- return ChemicalPotential ({k : v / other for k , v in self .items ()})
1269
+ return ChemicalPotential ({key : val / other for key , val in self .items ()})
1267
1270
return NotImplemented
1268
1271
1269
1272
__div__ = __truediv__
@@ -1290,7 +1293,7 @@ def get_energy(self, composition: Composition, strict: bool = True) -> float:
1290
1293
if strict and set (composition ) > set (self ):
1291
1294
s = set (composition ) - set (self )
1292
1295
raise ValueError (f"Potentials not specified for { s } " )
1293
- return sum (self .get (k , 0 ) * v for k , v in composition .items ())
1296
+ return sum (self .get (key , 0 ) * val for key , val in composition .items ())
1294
1297
1295
1298
def __repr__ (self ) -> str :
1296
1299
return f"ChemPots: { super ()!r} "
0 commit comments