ChessAnalysisPipeline 0.0.2__py3-none-any.whl → 0.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ChessAnalysisPipeline might be problematic. Click here for more details.
- CHAP/__init__.py +3 -0
- CHAP/common/__init__.py +19 -0
- CHAP/common/models/__init__.py +2 -0
- CHAP/common/models/integration.py +515 -0
- CHAP/common/models/map.py +535 -0
- CHAP/common/processor.py +644 -0
- CHAP/common/reader.py +119 -0
- CHAP/common/utils/__init__.py +37 -0
- CHAP/common/utils/fit.py +2613 -0
- CHAP/common/utils/general.py +1225 -0
- CHAP/common/utils/material.py +231 -0
- CHAP/common/utils/scanparsers.py +785 -0
- CHAP/common/writer.py +96 -0
- CHAP/edd/__init__.py +7 -0
- CHAP/edd/models.py +215 -0
- CHAP/edd/processor.py +321 -0
- CHAP/edd/reader.py +5 -0
- CHAP/edd/writer.py +5 -0
- CHAP/inference/__init__.py +3 -0
- CHAP/inference/processor.py +68 -0
- CHAP/inference/reader.py +5 -0
- CHAP/inference/writer.py +5 -0
- CHAP/pipeline.py +1 -1
- CHAP/processor.py +11 -818
- CHAP/reader.py +18 -113
- CHAP/saxswaxs/__init__.py +6 -0
- CHAP/saxswaxs/processor.py +5 -0
- CHAP/saxswaxs/reader.py +5 -0
- CHAP/saxswaxs/writer.py +5 -0
- CHAP/sin2psi/__init__.py +7 -0
- CHAP/sin2psi/processor.py +5 -0
- CHAP/sin2psi/reader.py +5 -0
- CHAP/sin2psi/writer.py +5 -0
- CHAP/tomo/__init__.py +5 -0
- CHAP/tomo/models.py +125 -0
- CHAP/tomo/processor.py +2009 -0
- CHAP/tomo/reader.py +5 -0
- CHAP/tomo/writer.py +5 -0
- CHAP/writer.py +17 -167
- {ChessAnalysisPipeline-0.0.2.dist-info → ChessAnalysisPipeline-0.0.4.dist-info}/METADATA +1 -1
- ChessAnalysisPipeline-0.0.4.dist-info/RECORD +50 -0
- CHAP/async.py +0 -56
- ChessAnalysisPipeline-0.0.2.dist-info/RECORD +0 -17
- {ChessAnalysisPipeline-0.0.2.dist-info → ChessAnalysisPipeline-0.0.4.dist-info}/LICENSE +0 -0
- {ChessAnalysisPipeline-0.0.2.dist-info → ChessAnalysisPipeline-0.0.4.dist-info}/WHEEL +0 -0
- {ChessAnalysisPipeline-0.0.2.dist-info → ChessAnalysisPipeline-0.0.4.dist-info}/entry_points.txt +0 -0
- {ChessAnalysisPipeline-0.0.2.dist-info → ChessAnalysisPipeline-0.0.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# -*- coding: utf-8 -*-
|
|
4
|
+
"""
|
|
5
|
+
Created on Fri May 27 12:21:25 2022
|
|
6
|
+
|
|
7
|
+
@author: rv43
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import numpy as np
|
|
14
|
+
try:
|
|
15
|
+
import xrayutilities as xu
|
|
16
|
+
have_xu = True
|
|
17
|
+
except:
|
|
18
|
+
have_xu = False
|
|
19
|
+
pass
|
|
20
|
+
try:
|
|
21
|
+
from hexrd import material
|
|
22
|
+
have_hexrd = True
|
|
23
|
+
except:
|
|
24
|
+
have_hexrd = False
|
|
25
|
+
pass
|
|
26
|
+
if have_hexrd:
|
|
27
|
+
try:
|
|
28
|
+
from hexrd.valunits import valWUnit
|
|
29
|
+
except:
|
|
30
|
+
have_hexrd = False
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
powder_intensity_cutoff = 1.e-8
|
|
34
|
+
|
|
35
|
+
class Material:
|
|
36
|
+
"""Base class for materials in an sin2psi or EDD analysis.
|
|
37
|
+
Right now it assumes a single material
|
|
38
|
+
extend its ability to do differently when test data is available
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, material_name=None, material_file=None, sgnum=None,
|
|
42
|
+
lattice_parameters_angstroms=None, atoms=None, pos=None, enrgy=None):
|
|
43
|
+
self._enrgy = enrgy
|
|
44
|
+
self._materials = []
|
|
45
|
+
self._ds_min = []
|
|
46
|
+
self._ds_unique = None
|
|
47
|
+
self._hkls_unique = None
|
|
48
|
+
if material_name is not None:
|
|
49
|
+
self.add_material(material_name, material_file, sgnum, lattice_parameters_angstroms,
|
|
50
|
+
atoms, pos)
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
#FIX passing arguments to a property isn't correct?
|
|
54
|
+
def lattice_parameters(self, index=0):
|
|
55
|
+
"""Convert from internal nm units to angstrom
|
|
56
|
+
"""
|
|
57
|
+
matl = self._materials[index]
|
|
58
|
+
if isinstance(matl, xu.materials.material.Crystal):
|
|
59
|
+
return [matl.a, matl.b, matl.c]
|
|
60
|
+
elif isinstance(matl, material.Material):
|
|
61
|
+
return [l.getVal("angstrom") for l in self._materials[index].latticeParameters[0:3]]
|
|
62
|
+
else:
|
|
63
|
+
raise ValueError('Illegal material class type')
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def ds_unique(self, tth_tol=None, tth_max=None, round_sig=8):
|
|
68
|
+
if self._ds_unique is None:
|
|
69
|
+
self.get_unique_ds(tth_tol, tth_max, round_sig)
|
|
70
|
+
return self._ds_unique
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def hkls_unique(self, tth_tol=None, tth_max=None, round_sig=8):
|
|
74
|
+
if self._hkls_unique is None:
|
|
75
|
+
self.get_unique_ds(tth_tol, tth_max, round_sig)
|
|
76
|
+
return self._hkls_unique
|
|
77
|
+
|
|
78
|
+
def add_material(self, material_name, material_file=None, sgnum=None,
|
|
79
|
+
lattice_parameters_angstroms=None, atoms=None, pos=None, dmin_angstroms=0.6):
|
|
80
|
+
# At this point only for a single material
|
|
81
|
+
# Unique energies works for more, but fitting with different materials is not implemented
|
|
82
|
+
if len(self._materials) == 1:
|
|
83
|
+
exit('Multiple materials not implemented yet')
|
|
84
|
+
self._ds_min.append(dmin_angstroms)
|
|
85
|
+
self._materials.append(Material.make_material(material_name, material_file, sgnum,
|
|
86
|
+
lattice_parameters_angstroms, atoms, pos, dmin_angstroms))
|
|
87
|
+
|
|
88
|
+
def get_unique_ds(self, tth_tol=None, tth_max=None, round_sig=8):
|
|
89
|
+
"""Get the list of unique lattice spacings from material HKLs
|
|
90
|
+
|
|
91
|
+
Parameters
|
|
92
|
+
----------
|
|
93
|
+
tth_tol : two theta tolerance (in degrees)
|
|
94
|
+
tth_max : maximum two theta value (in degrees)
|
|
95
|
+
round_sig : significant digits, passed to round() function
|
|
96
|
+
|
|
97
|
+
Returns
|
|
98
|
+
-------
|
|
99
|
+
hkls : list of hkl's corresponding to the unique lattice spacings
|
|
100
|
+
ds : list of the unique lattice spacings
|
|
101
|
+
"""
|
|
102
|
+
hkls = np.empty((0,3))
|
|
103
|
+
ds = np.empty((0))
|
|
104
|
+
ids = np.empty((0))
|
|
105
|
+
for i,m in enumerate(self._materials):
|
|
106
|
+
material_class_valid = False
|
|
107
|
+
if have_xu:
|
|
108
|
+
if isinstance(m, xu.materials.material.Crystal):
|
|
109
|
+
powder = xu.simpack.PowderDiffraction(m, en=self._enrgy)
|
|
110
|
+
hklsi = [hkl for hkl in powder.data if powder.data[hkl]['active']]
|
|
111
|
+
dsi = [m.planeDistance(hkl) for hkl in powder.data if powder.data[hkl]['active']]
|
|
112
|
+
mask = [True if d > self._ds_min[i] else False for d in dsi]
|
|
113
|
+
hkls = np.vstack((hkls, np.array(hklsi)[mask,:]))
|
|
114
|
+
dsi = np.array(dsi)[mask]
|
|
115
|
+
material_class_valid = True
|
|
116
|
+
if have_hexrd:
|
|
117
|
+
if isinstance(m, material.Material):
|
|
118
|
+
pd = m.planeData
|
|
119
|
+
if tth_tol is not None:
|
|
120
|
+
pd.tThWidth = np.radians(tth_tol)
|
|
121
|
+
if tth_max is not None:
|
|
122
|
+
pd.exclusions = None
|
|
123
|
+
pd.tThMax = np.radians(tth_max)
|
|
124
|
+
hkls = np.vstack((hkls, pd.hkls.T))
|
|
125
|
+
dsi = pd.getPlaneSpacings()
|
|
126
|
+
material_class_valid = True
|
|
127
|
+
if not material_class_valid:
|
|
128
|
+
raise ValueError('Illegal material class type')
|
|
129
|
+
ds = np.hstack((ds, dsi))
|
|
130
|
+
ids = np.hstack((ids, i*np.ones(len(dsi))))
|
|
131
|
+
|
|
132
|
+
# Sort lattice spacings in reverse order (use -)
|
|
133
|
+
ds_unique, ids_unique, _ = np.unique(-ds.round(round_sig), return_index=True,
|
|
134
|
+
return_counts=True)
|
|
135
|
+
ds_unique = np.abs(ds_unique)
|
|
136
|
+
|
|
137
|
+
# Limit the list to unique lattice spacings
|
|
138
|
+
self._hkls_unique = hkls[ids_unique,:].astype(int)
|
|
139
|
+
self._ds_unique = ds[ids_unique]
|
|
140
|
+
hkl_list = np.vstack((np.arange(self._ds_unique.shape[0]), ids[ids_unique],
|
|
141
|
+
self._hkls_unique.T, self._ds_unique)).T
|
|
142
|
+
logging.info("Unique d's:")
|
|
143
|
+
for hkl in hkl_list:
|
|
144
|
+
logging.info(f'{hkl[0]:4.0f} {hkl[1]:.0f} {hkl[2]:.0f} {hkl[3]:.0f} {hkl[4]:.0f} '+
|
|
145
|
+
f'{hkl[5]:.6f}')
|
|
146
|
+
|
|
147
|
+
return self._hkls_unique, self._ds_unique
|
|
148
|
+
|
|
149
|
+
@staticmethod
|
|
150
|
+
def make_material(material_name, material_file=None, sgnum=None,
|
|
151
|
+
lattice_parameters_angstroms=None, atoms=None, pos=None, dmin_angstroms=0.6):
|
|
152
|
+
""" Use HeXRD to get material properties when a materials file is provided
|
|
153
|
+
Use xrayutilities otherwise
|
|
154
|
+
"""
|
|
155
|
+
if not isinstance(material_name, str):
|
|
156
|
+
raise ValueError(f'Illegal material_name: {material_name} {type(material_name)}')
|
|
157
|
+
if lattice_parameters_angstroms is not None:
|
|
158
|
+
if material_file is not None:
|
|
159
|
+
logging.warning('Overwrite lattice_parameters of material_file with input values '+
|
|
160
|
+
f'({lattice_parameters_angstroms})')
|
|
161
|
+
if isinstance(lattice_parameters_angstroms, (int, float)):
|
|
162
|
+
lattice_parameters = [lattice_parameters_angstroms]
|
|
163
|
+
elif isinstance(lattice_parameters_angstroms, (tuple, list, np.ndarray)):
|
|
164
|
+
lattice_parameters = list(lattice_parameters_angstroms)
|
|
165
|
+
else:
|
|
166
|
+
raise ValueError(f'Illegal lattice_parameters_angstroms: '+
|
|
167
|
+
f'{lattice_parameters_angstroms} {type(lattice_parameters_angstroms)}')
|
|
168
|
+
if material_file is None:
|
|
169
|
+
if not isinstance(sgnum, int):
|
|
170
|
+
raise ValueError(f'Illegal sgnum: {sgnum} {type(sgnum)}')
|
|
171
|
+
if sgnum is None or lattice_parameters_angstroms is None or pos is None:
|
|
172
|
+
raise ValueError('Valid inputs for sgnum and lattice_parameters_angstroms and '+
|
|
173
|
+
'pos are required if materials file is not specified')
|
|
174
|
+
if isinstance(pos, str):
|
|
175
|
+
pos = [pos]
|
|
176
|
+
use_xu = True
|
|
177
|
+
if (np.array(pos).ndim == 1 and isinstance(pos[0], (int, float)) and
|
|
178
|
+
np.array(pos).size == 3):
|
|
179
|
+
if have_hexrd:
|
|
180
|
+
pos = np.array([pos])
|
|
181
|
+
use_xu = False
|
|
182
|
+
elif (np.array(pos).ndim == 2 and np.array(pos).shape[0] > 0 and
|
|
183
|
+
np.array(pos).shape[1] == 3):
|
|
184
|
+
if have_hexrd:
|
|
185
|
+
pos = np.array(pos)
|
|
186
|
+
use_xu = False
|
|
187
|
+
elif not (np.array(pos).ndim == 1 and isinstance(pos[0], str) and
|
|
188
|
+
np.array(pos).size > 0 and have_xu):
|
|
189
|
+
raise ValueError(f'Illegal pos (have_xu = {have_xu}): {pos} {type(pos)}')
|
|
190
|
+
if use_xu:
|
|
191
|
+
if atoms is None:
|
|
192
|
+
atoms = [material_name]
|
|
193
|
+
matl = xu.materials.Crystal(material_name, xu.materials.SGLattice(sgnum,
|
|
194
|
+
*lattice_parameters, atoms=atoms, pos=[p for p in np.array(pos)]))
|
|
195
|
+
else:
|
|
196
|
+
matl = material.Material(material_name)
|
|
197
|
+
matl.sgnum = sgnum
|
|
198
|
+
matl.atominfo = np.vstack((pos.T, np.ones(pos.shape[0]))).T
|
|
199
|
+
matl.latticeParameters = lattice_parameters
|
|
200
|
+
matl.dmin = valWUnit('lp', 'length', dmin_angstroms, 'angstrom')
|
|
201
|
+
exclusions = matl.planeData.get_exclusions()
|
|
202
|
+
powder_intensity = matl.planeData.powder_intensity
|
|
203
|
+
exclusions = [True if exclusion or i >= len(powder_intensity) or
|
|
204
|
+
powder_intensity[i] < powder_intensity_cutoff else False
|
|
205
|
+
for i, exclusion in enumerate(exclusions)]
|
|
206
|
+
matl.planeData.set_exclusions(exclusions)
|
|
207
|
+
logging.debug(f'powder_intensity = {matl.planeData.powder_intensity}')
|
|
208
|
+
logging.debug(f'exclusions = {matl.planeData.exclusions}')
|
|
209
|
+
else:
|
|
210
|
+
if not have_hexrd:
|
|
211
|
+
raise ValueError('Illegal inputs: must provide detailed material info when '+
|
|
212
|
+
'hexrd package is unavailable')
|
|
213
|
+
if sgnum is not None:
|
|
214
|
+
logging.warning('Ignore sgnum input when material_file is specified')
|
|
215
|
+
if not (os.path.splitext(material_file)[1] in ('.h5', '.hdf5', '.xtal', '.cif')):
|
|
216
|
+
raise ValueError(f'Illegal material file {material_file}')
|
|
217
|
+
matl = material.Material(material_name, material_file,
|
|
218
|
+
dmin=valWUnit('lp', 'length', dmin_angstroms, 'angstrom'))
|
|
219
|
+
if lattice_parameters_angstroms is not None:
|
|
220
|
+
matl.latticeParameters = lattice_parameters
|
|
221
|
+
exclusions = matl.planeData.get_exclusions()
|
|
222
|
+
powder_intensity = matl.planeData.powder_intensity
|
|
223
|
+
exclusions = [True if exclusion or i >= len(powder_intensity) or
|
|
224
|
+
powder_intensity[i] < powder_intensity_cutoff else False
|
|
225
|
+
for i, exclusion in enumerate(exclusions)]
|
|
226
|
+
matl.planeData.set_exclusions(exclusions)
|
|
227
|
+
logging.debug(f'powder_intensity = {matl.planeData.powder_intensity}')
|
|
228
|
+
logging.debug(f'exclusions = {matl.planeData.exclusions}')
|
|
229
|
+
|
|
230
|
+
return matl
|
|
231
|
+
|