@@ -586,7 +586,8 @@ def contains_element_type(self, category: str) -> bool:
586
586
587
587
return any (getattr (el , f"is_{ category } " ) for el in self .elements )
588
588
589
- def _parse_formula (self , formula : str , strict : bool = True ) -> dict [str , float ]:
589
+ @staticmethod
590
+ def _parse_formula (formula : str , strict : bool = True ) -> dict [str , float ]:
590
591
"""
591
592
Args:
592
593
formula (str): A string formula, e.g. Fe2O3, Li3Fe2(PO4)3.
@@ -678,22 +679,64 @@ def from_dict(cls, dct: dict) -> Self:
678
679
return cls (dct )
679
680
680
681
@classmethod
681
- def from_weight_dict (cls , weight_dict : dict [SpeciesLike , float ]) -> Self :
682
+ def from_weight_dict (cls , weight_dict : dict [SpeciesLike , float ], strict : bool = True , ** kwargs ) -> Self :
682
683
"""Create a Composition based on a dict of atomic fractions calculated
683
684
from a dict of weight fractions. Allows for quick creation of the class
684
685
from weight-based notations commonly used in the industry, such as
685
686
Ti6V4Al and Ni60Ti40.
686
687
687
688
Args:
688
689
weight_dict (dict): {symbol: weight_fraction} dict.
690
+ strict (bool): Only allow valid Elements and Species in the Composition. Defaults to True.
691
+ **kwargs: Additional kwargs supported by the dict() constructor.
689
692
690
693
Returns:
691
- Composition
694
+ Composition in molar fractions.
695
+
696
+ Examples:
697
+ >>> Composition.from_weights({"Fe": 0.5, "Ni": 0.5})
698
+ Composition('Fe0.512434 Ni0.487566')
699
+ >>> Composition.from_weights({"Ti": 60, "Ni": 40})
700
+ Composition('Ti0.647796 Ni0.352204')
692
701
"""
693
702
weight_sum = sum (val / Element (el ).atomic_mass for el , val in weight_dict .items ())
694
703
comp_dict = {el : val / Element (el ).atomic_mass / weight_sum for el , val in weight_dict .items ()}
695
704
696
- return cls (comp_dict )
705
+ return cls (comp_dict , strict = strict , ** kwargs )
706
+
707
+ @classmethod
708
+ def from_weights (cls , * args , strict : bool = True , ** kwargs ) -> Self :
709
+ """Create a Composition from a weight-based formula.
710
+
711
+ Args:
712
+ *args: Any number of 2-tuples as key-value pairs.
713
+ strict (bool): Only allow valid Elements and Species in the Composition. Defaults to False.
714
+ allow_negative (bool): Whether to allow negative compositions. Defaults to False.
715
+ **kwargs: Additional kwargs supported by the dict() constructor.
716
+
717
+ Returns:
718
+ Composition in molar fractions.
719
+
720
+ Examples:
721
+ >>> Composition.from_weights("Fe50Ti50")
722
+ Composition('Fe0.461538 Ti0.538462')
723
+ >>> Composition.from_weights({"Fe": 0.5, "Ni": 0.5})
724
+ Composition('Fe0.512434 Ni0.487566')
725
+ """
726
+ if len (args ) == 1 and isinstance (args [0 ], str ):
727
+ elem_map : dict [str , float ] = cls ._parse_formula (args [0 ])
728
+ elif len (args ) == 1 and isinstance (args [0 ], type (cls )):
729
+ elem_map = args [0 ] # type: ignore[assignment]
730
+ elif len (args ) == 1 and isinstance (args [0 ], float ) and math .isnan (args [0 ]):
731
+ raise ValueError ("float('NaN') is not a valid Composition, did you mean 'NaN'?" )
732
+ else :
733
+ elem_map = dict (* args , ** kwargs ) # type: ignore[assignment]
734
+
735
+ for val in elem_map .values ():
736
+ if val < - cls .amount_tolerance :
737
+ raise ValueError ("Weights in Composition cannot be negative!" )
738
+
739
+ return cls .from_weight_dict (elem_map , strict = strict )
697
740
698
741
def get_el_amt_dict (self ) -> dict [str , float ]:
699
742
"""
0 commit comments