6
6
Yin, L. et al.Thermodynamics of Antisite Defects in Layered NMC Cathodes: Systematic Insights from High-Precision Powder
7
7
Diffraction Analyses Chem. Mater 2020 32 (3), 1002-1010. 10.1021/acs.chemmater.9b03646
8
8
"""
9
+ from __future__ import annotations
9
10
10
11
import os
12
+ from typing import TYPE_CHECKING
13
+
11
14
import numpy as np
12
15
import pandas as pd
13
16
import plotly .express as px
14
- from typing import Callable
15
- from pymatgen .core .periodic_table import Element
16
- from pymatgen .core .structure import Structure
17
+
18
+ if TYPE_CHECKING :
19
+ from pymatgen .core .periodic_table import Element
20
+ from pymatgen .core .structure import Structure
17
21
18
22
# Load in the neutron form factors
19
23
with open (os .path .join (os .path .dirname (__file__ ), "neutron_factors.csv" )) as f :
@@ -25,7 +29,8 @@ class FStarDiagram:
25
29
"""
26
30
Take a list of symmetrized structure objects and use them to generate an f* phase diagram.
27
31
"""
28
- def __init__ (self , structures : list [Structure ], scattering_type : str = 'X-ray' ):
32
+
33
+ def __init__ (self , structures : list [Structure ], scattering_type : str = "X-ray" ):
29
34
"""
30
35
Initialize the f* diagram generator with the list of structures and scattering type.
31
36
@@ -39,26 +44,22 @@ def __init__(self, structures: list[Structure], scattering_type: str='X-ray'):
39
44
# check if the input structures list is valid
40
45
for ind , struct in enumerate (structures ):
41
46
try :
42
- if struct .equivalent_indices == structures [ind - 1 ].equivalent_indices :
47
+ if struct .equivalent_indices == structures [ind - 1 ].equivalent_indices :
43
48
continue
44
49
else :
45
- raise ValueError (
46
- "All structues must only vary in occupancy."
47
- )
50
+ raise ValueError ("All structues must only vary in occupancy." )
48
51
except AttributeError :
49
- raise AttributeError (
50
- "Must use symmeteized structure objects"
51
- )
52
+ raise AttributeError ("Must use symmeteized structure objects" )
52
53
self ._structures = structures
53
54
self ._scatter = scattering_type
54
- self ._scatter_dict = {' X-ray' : self .xray_scatter ,' Neutron' : self .neutron_scatter }
55
+ self ._scatter_dict = {" X-ray" : self .xray_scatter , " Neutron" : self .neutron_scatter }
55
56
self .site_labels = self ._get_site_labels ()
56
57
self .fstar_coords = self ._get_fstar_coords ()
57
58
self .set_plot_list ([self .site_labels [0 ], self .site_labels [1 ], self .site_labels [2 ]])
58
59
self .make_plot ()
59
60
print ("The labels for this structure's unique sites are" )
60
61
print (self .site_labels )
61
-
62
+
62
63
def combine_sites (self , site_lists : list [list [str ]]) -> None :
63
64
"""
64
65
Many structures have more than three sites. If this is the case you may want to
@@ -70,12 +71,11 @@ def combine_sites(self, site_lists: list[list[str]]) -> None:
70
71
for combo in site_lists :
71
72
for site in combo :
72
73
if site not in self .site_labels :
73
- raise ValueError (
74
- "All sites must be in the site_labels list"
75
- )
74
+ raise ValueError ("All sites must be in the site_labels list" )
76
75
self .fstar_coords [str (combo )] = sum ([self .fstar_coords [site ] for site in combo ])
77
76
if str (combo ) not in self .site_labels :
78
77
self .site_labels .append (str (combo ))
78
+
79
79
def set_plot_list (self , site_list : list [str ]) -> None :
80
80
"""
81
81
set the list of sites to plot and the order to plot them in.
@@ -85,19 +85,20 @@ def set_plot_list(self, site_list: list[str]) -> None:
85
85
"""
86
86
for site in site_list :
87
87
if site not in self .site_labels :
88
- raise ValueError (
89
- "All sites must be in the site_labels list"
90
- )
88
+ raise ValueError ("All sites must be in the site_labels list" )
91
89
self .plot_list = site_list
90
+
92
91
def make_plot (self , ** kwargs ):
93
92
"""
94
93
Makes a plotly express scatter_ternary plot useing the fstar_coords dataframe and the
95
94
sites in plot list.
96
95
Args:
97
96
**kwargs: this can be any argument that the scatter_ternary fucntion can use.
98
97
"""
99
- self .plot = px .scatter_ternary (data_frame = self .fstar_coords , a = self .plot_list [0 ], b = self .plot_list [1 ],
100
- c = self .plot_list [2 ], ** kwargs )
98
+ self .plot = px .scatter_ternary (
99
+ data_frame = self .fstar_coords , a = self .plot_list [0 ], b = self .plot_list [1 ], c = self .plot_list [2 ], ** kwargs
100
+ )
101
+
101
102
def _get_site_labels (self ):
102
103
"""
103
104
Generates unique site labels based on composition, order, and symetry equivalence in the structure object.
@@ -132,8 +133,10 @@ def _get_site_labels(self):
132
133
"""
133
134
site_labels = []
134
135
for site in self ._structures [0 ].equivalent_indices :
135
- site_labels .append (str (self ._structures [0 ][site [0 ]].frac_coords ) + \
136
- [str (sp ) for sp , _ in self ._structures [0 ][site [0 ]].species .items ()][0 ])
136
+ site_labels .append (
137
+ str (self ._structures [0 ][site [0 ]].frac_coords )
138
+ + next (str (sp ) for sp , _ in self ._structures [0 ][site [0 ]].species .items ())
139
+ )
137
140
return site_labels
138
141
139
142
def _get_fstar_coords (self ):
@@ -152,31 +155,32 @@ def _get_fstar_coords(self):
152
155
for sp , occ in elements_and_occupancies :
153
156
# ind1 and ind2 are added in case someone wants to make a custom scatter function
154
157
# that uses information in the structure object
155
- f_occ = self ._scatter_dict [self ._scatter ](sp , occ , ind1 , ind2 )
158
+ f_occ = self ._scatter_dict [self ._scatter ](sp , occ , ind1 , ind2 )
156
159
occ_f_list .append (f_occ )
157
160
fstar = np .absolute (mult * sum (occ_f_list ))
158
161
fstar_df .loc [0 ][column [0 ]] = round (float (fstar ), 4 )
159
162
tot = sum (sum (list (fstar_df .values )))
160
163
fstar_df = pd .DataFrame (columns = self .site_labels , data = [fs / tot for fs in list (fstar_df .values )])
161
164
fstar_df_full = pd .concat ([fstar_df_full , fstar_df ], ignore_index = True )
162
165
return fstar_df_full
166
+
163
167
def xray_scatter (self , el : Element , occ : float , i1 : int , i2 : int ) -> float :
164
168
"""
165
169
X-ray scattering function. i2 and i2 are unused.
166
170
"""
167
- f_occ = el .Z * occ
168
- return f_occ
171
+ return el .Z * occ
172
+
169
173
def neutron_scatter (self , el : Element , occ : float , i1 : int , i2 : int ) -> float :
170
174
"""
171
175
Neutron scattering function. i2 and i2 are unused.
172
176
"""
173
- for i , n in enumerate (NEUTRON_SCATTER_DF [' Isotope' ].values ):
177
+ for i , n in enumerate (NEUTRON_SCATTER_DF [" Isotope" ].values ):
174
178
if hasattr (el , "element" ):
175
179
if n == str (el .element ):
176
- f_occ = float (NEUTRON_SCATTER_DF .loc [i ][' Coh b' ]) * occ
180
+ f_occ = float (NEUTRON_SCATTER_DF .loc [i ][" Coh b" ]) * occ
177
181
break
178
182
else :
179
183
if n == str (el ):
180
- f_occ = float (NEUTRON_SCATTER_DF .loc [i ][' Coh b' ]) * occ
184
+ f_occ = float (NEUTRON_SCATTER_DF .loc [i ][" Coh b" ]) * occ
181
185
break
182
- return f_occ
186
+ return f_occ
0 commit comments