diffpy.srfit 3.1.0__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.
- diffpy/__init__.py +15 -0
- diffpy/srfit/__init__.py +41 -0
- diffpy/srfit/equation/__init__.py +31 -0
- diffpy/srfit/equation/builder.py +702 -0
- diffpy/srfit/equation/equationmod.py +213 -0
- diffpy/srfit/equation/literals/__init__.py +71 -0
- diffpy/srfit/equation/literals/abcs.py +81 -0
- diffpy/srfit/equation/literals/argument.py +76 -0
- diffpy/srfit/equation/literals/literal.py +69 -0
- diffpy/srfit/equation/literals/operators.py +380 -0
- diffpy/srfit/equation/visitors/__init__.py +94 -0
- diffpy/srfit/equation/visitors/argfinder.py +62 -0
- diffpy/srfit/equation/visitors/printer.py +120 -0
- diffpy/srfit/equation/visitors/swapper.py +142 -0
- diffpy/srfit/equation/visitors/validator.py +113 -0
- diffpy/srfit/equation/visitors/visitor.py +62 -0
- diffpy/srfit/exceptions.py +29 -0
- diffpy/srfit/fitbase/__init__.py +53 -0
- diffpy/srfit/fitbase/calculator.py +110 -0
- diffpy/srfit/fitbase/configurable.py +57 -0
- diffpy/srfit/fitbase/constraint.py +117 -0
- diffpy/srfit/fitbase/fitcontribution.py +351 -0
- diffpy/srfit/fitbase/fithook.py +227 -0
- diffpy/srfit/fitbase/fitrecipe.py +826 -0
- diffpy/srfit/fitbase/fitresults.py +674 -0
- diffpy/srfit/fitbase/parameter.py +314 -0
- diffpy/srfit/fitbase/parameterset.py +110 -0
- diffpy/srfit/fitbase/profile.py +405 -0
- diffpy/srfit/fitbase/profilegenerator.py +168 -0
- diffpy/srfit/fitbase/profileparser.py +179 -0
- diffpy/srfit/fitbase/recipeorganizer.py +1074 -0
- diffpy/srfit/fitbase/restraint.py +117 -0
- diffpy/srfit/fitbase/simplerecipe.py +230 -0
- diffpy/srfit/fitbase/validatable.py +59 -0
- diffpy/srfit/interface/__init__.py +33 -0
- diffpy/srfit/interface/interface.py +180 -0
- diffpy/srfit/pdf/__init__.py +24 -0
- diffpy/srfit/pdf/basepdfgenerator.py +296 -0
- diffpy/srfit/pdf/characteristicfunctions.py +432 -0
- diffpy/srfit/pdf/debyepdfgenerator.py +115 -0
- diffpy/srfit/pdf/pdfcontribution.py +311 -0
- diffpy/srfit/pdf/pdfgenerator.py +77 -0
- diffpy/srfit/pdf/pdfparser.py +226 -0
- diffpy/srfit/sas/__init__.py +30 -0
- diffpy/srfit/sas/prcalculator.py +139 -0
- diffpy/srfit/sas/sasgenerator.py +70 -0
- diffpy/srfit/sas/sasimport.py +66 -0
- diffpy/srfit/sas/sasparameter.py +70 -0
- diffpy/srfit/sas/sasparser.py +133 -0
- diffpy/srfit/sas/sasprofile.py +94 -0
- diffpy/srfit/structure/__init__.py +60 -0
- diffpy/srfit/structure/basestructureparset.py +62 -0
- diffpy/srfit/structure/bvsrestraint.py +101 -0
- diffpy/srfit/structure/cctbxparset.py +292 -0
- diffpy/srfit/structure/diffpyparset.py +303 -0
- diffpy/srfit/structure/objcrystparset.py +1552 -0
- diffpy/srfit/structure/sgconstraints.py +761 -0
- diffpy/srfit/structure/srrealparset.py +92 -0
- diffpy/srfit/util/__init__.py +50 -0
- diffpy/srfit/util/argbinders.py +29 -0
- diffpy/srfit/util/inpututils.py +50 -0
- diffpy/srfit/util/nameutils.py +45 -0
- diffpy/srfit/util/observable.py +93 -0
- diffpy/srfit/util/tagmanager.py +150 -0
- diffpy/srfit/util/weakrefcallable.py +170 -0
- diffpy/srfit/version.py +26 -0
- diffpy_srfit-3.1.0.dist-info/METADATA +216 -0
- diffpy_srfit-3.1.0.dist-info/RECORD +73 -0
- diffpy_srfit-3.1.0.dist-info/WHEEL +5 -0
- diffpy_srfit-3.1.0.dist-info/licenses/AUTHORS.rst +10 -0
- diffpy_srfit-3.1.0.dist-info/licenses/LICENSE.rst +138 -0
- diffpy_srfit-3.1.0.dist-info/licenses/LICENSE_DANSE.rst +34 -0
- diffpy_srfit-3.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
##############################################################################
|
|
3
|
+
#
|
|
4
|
+
# diffpy.srfit by DANSE Diffraction group
|
|
5
|
+
# Simon J. L. Billinge
|
|
6
|
+
# (c) 2008 The Trustees of Columbia University
|
|
7
|
+
# in the City of New York. All rights reserved.
|
|
8
|
+
#
|
|
9
|
+
# File coded by: Chris Farrow
|
|
10
|
+
#
|
|
11
|
+
# See AUTHORS.txt for a list of people who contributed.
|
|
12
|
+
# See LICENSE_DANSE.txt for license information.
|
|
13
|
+
#
|
|
14
|
+
##############################################################################
|
|
15
|
+
"""PDF profile generator base class.
|
|
16
|
+
|
|
17
|
+
The BasePDFGenerator class interfaces with SrReal PDF calculators and is
|
|
18
|
+
used as a base for the PDFGenerator and DebyePDFGenerator classes.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
__all__ = ["BasePDFGenerator"]
|
|
22
|
+
|
|
23
|
+
import numpy
|
|
24
|
+
|
|
25
|
+
from diffpy.srfit.exceptions import SrFitError
|
|
26
|
+
from diffpy.srfit.fitbase import ProfileGenerator
|
|
27
|
+
from diffpy.srfit.fitbase.parameter import ParameterAdapter
|
|
28
|
+
from diffpy.srfit.structure import struToParameterSet
|
|
29
|
+
|
|
30
|
+
# FIXME - Parameter creation will have to be smarter once deeper calculator
|
|
31
|
+
# configuration is enabled.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class BasePDFGenerator(ProfileGenerator):
|
|
35
|
+
"""Base class for calculating PDF profiles using SrReal.
|
|
36
|
+
|
|
37
|
+
This works with diffpy.structure.Structure, pyobjcryst.crystal.Crystal and
|
|
38
|
+
pyobjcryst.molecule.Molecule instances. Note that the managed Parameters
|
|
39
|
+
are not created until the structure is added.
|
|
40
|
+
|
|
41
|
+
Attributes:
|
|
42
|
+
_calc -- PDFCalculator or DebyePDFCalculator instance for calculating
|
|
43
|
+
the PDF.
|
|
44
|
+
_phase -- The structure ParameterSet used to calculate the profile.
|
|
45
|
+
stru -- The structure objected adapted by _phase.
|
|
46
|
+
_lastr -- The last value of r over which the PDF was calculated. This is
|
|
47
|
+
used to configure the calculator when r changes.
|
|
48
|
+
_pool -- A multiprocessing.Pool for managing parallel computation.
|
|
49
|
+
|
|
50
|
+
Managed Parameters:
|
|
51
|
+
scale -- Scale factor
|
|
52
|
+
delta1 -- Linear peak broadening term
|
|
53
|
+
delta2 -- Quadratic peak broadening term
|
|
54
|
+
qbroad -- Resolution peak broadening term
|
|
55
|
+
qdamp -- Resolution peak dampening term
|
|
56
|
+
|
|
57
|
+
Managed ParameterSets:
|
|
58
|
+
The structure ParameterSet (SrRealParSet instance) used to calculate the
|
|
59
|
+
profile is named by the user.
|
|
60
|
+
|
|
61
|
+
Usable Metadata:
|
|
62
|
+
stype -- The scattering type "X" for x-ray, "N" for neutron (see
|
|
63
|
+
'setScatteringType').
|
|
64
|
+
qmax -- The maximum scattering vector used to generate the PDF (see
|
|
65
|
+
setQmax).
|
|
66
|
+
qmin -- The minimum scattering vector used to generate the PDF (see
|
|
67
|
+
setQmin).
|
|
68
|
+
scale -- See Managed Parameters.
|
|
69
|
+
delta1 -- See Managed Parameters.
|
|
70
|
+
delta2 -- See Managed Parameters.
|
|
71
|
+
qbroad -- See Managed Parameters.
|
|
72
|
+
qdamp -- See Managed Parameters.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self, name="pdf"):
|
|
76
|
+
"""Initialize the generator."""
|
|
77
|
+
ProfileGenerator.__init__(self, name)
|
|
78
|
+
|
|
79
|
+
self._phase = None
|
|
80
|
+
self.stru = None
|
|
81
|
+
self.meta = {}
|
|
82
|
+
self._lastr = numpy.empty(0)
|
|
83
|
+
self._calc = None
|
|
84
|
+
|
|
85
|
+
self._pool = None
|
|
86
|
+
|
|
87
|
+
return
|
|
88
|
+
|
|
89
|
+
_parnames = ["delta1", "delta2", "qbroad", "scale", "qdamp"]
|
|
90
|
+
|
|
91
|
+
def _setCalculator(self, calc):
|
|
92
|
+
"""Set the SrReal calculator instance.
|
|
93
|
+
|
|
94
|
+
Setting the calculator creates Parameters from the variable
|
|
95
|
+
attributes of the SrReal calculator.
|
|
96
|
+
"""
|
|
97
|
+
self._calc = calc
|
|
98
|
+
for pname in self.__class__._parnames:
|
|
99
|
+
self.addParameter(ParameterAdapter(pname, self._calc, attr=pname))
|
|
100
|
+
self.processMetaData()
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
def parallel(self, ncpu, mapfunc=None):
|
|
104
|
+
"""Run calculation in parallel.
|
|
105
|
+
|
|
106
|
+
ncpu -- Number of parallel processes. Revert to serial mode when 1.
|
|
107
|
+
mapfunc -- A mapping function to use. If this is None (default),
|
|
108
|
+
multiprocessing.Pool.imap_unordered will be used.
|
|
109
|
+
|
|
110
|
+
No return value.
|
|
111
|
+
"""
|
|
112
|
+
from diffpy.srreal.parallel import createParallelCalculator
|
|
113
|
+
|
|
114
|
+
calc_serial = self._calc
|
|
115
|
+
if hasattr(calc_serial, "pqobj"):
|
|
116
|
+
calc_serial = calc_serial.pqobj
|
|
117
|
+
# revert to serial calculator for ncpu <= 1
|
|
118
|
+
if ncpu <= 1:
|
|
119
|
+
self._calc = calc_serial
|
|
120
|
+
self._pool = None
|
|
121
|
+
return
|
|
122
|
+
# Why don't we let the user shoot his foot or test on single CPU?
|
|
123
|
+
# ncpu = min(ncpu, multiprocessing.cpu_count())
|
|
124
|
+
if mapfunc is None:
|
|
125
|
+
import multiprocessing
|
|
126
|
+
|
|
127
|
+
self._pool = multiprocessing.Pool(ncpu)
|
|
128
|
+
mapfunc = self._pool.imap_unordered
|
|
129
|
+
|
|
130
|
+
self._calc = createParallelCalculator(calc_serial, ncpu, mapfunc)
|
|
131
|
+
return
|
|
132
|
+
|
|
133
|
+
def processMetaData(self):
|
|
134
|
+
"""Process the metadata once it gets set."""
|
|
135
|
+
ProfileGenerator.processMetaData(self)
|
|
136
|
+
|
|
137
|
+
stype = self.meta.get("stype")
|
|
138
|
+
if stype is not None:
|
|
139
|
+
self.setScatteringType(stype)
|
|
140
|
+
|
|
141
|
+
qmax = self.meta.get("qmax")
|
|
142
|
+
if qmax is not None:
|
|
143
|
+
self.setQmax(qmax)
|
|
144
|
+
|
|
145
|
+
qmin = self.meta.get("qmin")
|
|
146
|
+
if qmin is not None:
|
|
147
|
+
self.setQmin(qmin)
|
|
148
|
+
|
|
149
|
+
for name in self.__class__._parnames:
|
|
150
|
+
val = self.meta.get(name)
|
|
151
|
+
if val is not None:
|
|
152
|
+
par = self.get(name)
|
|
153
|
+
par.setValue(val)
|
|
154
|
+
|
|
155
|
+
return
|
|
156
|
+
|
|
157
|
+
def setScatteringType(self, stype="X"):
|
|
158
|
+
"""Set the scattering type.
|
|
159
|
+
|
|
160
|
+
stype -- "X" for x-ray, "N" for neutron, "E" for electrons,
|
|
161
|
+
or any registered type from diffpy.srreal from
|
|
162
|
+
ScatteringFactorTable.getRegisteredTypes().
|
|
163
|
+
|
|
164
|
+
Raises ValueError for unknown scattering type.
|
|
165
|
+
"""
|
|
166
|
+
self._calc.setScatteringFactorTableByType(stype)
|
|
167
|
+
# update the meta dictionary only if there was no exception
|
|
168
|
+
self.meta["stype"] = self.getScatteringType()
|
|
169
|
+
return
|
|
170
|
+
|
|
171
|
+
def getScatteringType(self):
|
|
172
|
+
"""Get the scattering type.
|
|
173
|
+
|
|
174
|
+
See 'setScatteringType'.
|
|
175
|
+
"""
|
|
176
|
+
return self._calc.getRadiationType()
|
|
177
|
+
|
|
178
|
+
def setQmax(self, qmax):
|
|
179
|
+
"""Set the qmax value."""
|
|
180
|
+
self._calc.qmax = qmax
|
|
181
|
+
self.meta["qmax"] = self.getQmax()
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
def getQmax(self):
|
|
185
|
+
"""Get the qmax value."""
|
|
186
|
+
return self._calc.qmax
|
|
187
|
+
|
|
188
|
+
def setQmin(self, qmin):
|
|
189
|
+
"""Set the qmin value."""
|
|
190
|
+
self._calc.qmin = qmin
|
|
191
|
+
self.meta["qmin"] = self.getQmin()
|
|
192
|
+
return
|
|
193
|
+
|
|
194
|
+
def getQmin(self):
|
|
195
|
+
"""Get the qmin value."""
|
|
196
|
+
return self._calc.qmin
|
|
197
|
+
|
|
198
|
+
def setStructure(self, stru, name="phase", periodic=True):
|
|
199
|
+
"""Set the structure that will be used to calculate the PDF.
|
|
200
|
+
|
|
201
|
+
This creates a DiffpyStructureParSet, ObjCrystCrystalParSet or
|
|
202
|
+
ObjCrystMoleculeParSet that adapts stru to a ParameterSet interface.
|
|
203
|
+
See those classes (located in diffpy.srfit.structure) for how they are
|
|
204
|
+
used. The resulting ParameterSet will be managed by this generator.
|
|
205
|
+
|
|
206
|
+
stru -- diffpy.structure.Structure, pyobjcryst.crystal.Crystal or
|
|
207
|
+
pyobjcryst.molecule.Molecule instance. Default None.
|
|
208
|
+
name -- A name to give to the managed ParameterSet that adapts stru
|
|
209
|
+
(default "phase").
|
|
210
|
+
periodic -- The structure should be treated as periodic (default
|
|
211
|
+
True). Note that some structures do not support
|
|
212
|
+
periodicity, in which case this will have no effect on the
|
|
213
|
+
PDF calculation.
|
|
214
|
+
"""
|
|
215
|
+
|
|
216
|
+
# Create the ParameterSet
|
|
217
|
+
parset = struToParameterSet(name, stru)
|
|
218
|
+
|
|
219
|
+
# Set the phase
|
|
220
|
+
self.setPhase(parset, periodic)
|
|
221
|
+
return
|
|
222
|
+
|
|
223
|
+
def setPhase(self, parset, periodic=True):
|
|
224
|
+
"""Set the phase that will be used to calculate the PDF.
|
|
225
|
+
|
|
226
|
+
Set the phase directly with a DiffpyStructureParSet,
|
|
227
|
+
ObjCrystCrystalParSet or ObjCrystMoleculeParSet that adapts a structure
|
|
228
|
+
object (from diffpy or pyobjcryst). The passed ParameterSet will be
|
|
229
|
+
managed by this generator.
|
|
230
|
+
|
|
231
|
+
parset -- A SrRealParSet that holds the structural information.
|
|
232
|
+
This can be used to share the phase between multiple
|
|
233
|
+
BasePDFGenerators, and have the changes in one reflect in
|
|
234
|
+
another.
|
|
235
|
+
periodic -- The structure should be treated as periodic (default True).
|
|
236
|
+
Note that some structures do not support periodicity, in
|
|
237
|
+
which case this will be ignored.
|
|
238
|
+
"""
|
|
239
|
+
# Store the ParameterSet for easy access
|
|
240
|
+
self._phase = parset
|
|
241
|
+
self.stru = self._phase.stru
|
|
242
|
+
|
|
243
|
+
# Put this ParameterSet in the ProfileGenerator.
|
|
244
|
+
self.addParameterSet(parset)
|
|
245
|
+
|
|
246
|
+
# Set periodicity
|
|
247
|
+
self._phase.useSymmetry(periodic)
|
|
248
|
+
return
|
|
249
|
+
|
|
250
|
+
def _prepare(self, r):
|
|
251
|
+
"""Prepare the calculator when a new r-value is passed."""
|
|
252
|
+
self._lastr = r.copy()
|
|
253
|
+
lo, hi = r.min(), r.max()
|
|
254
|
+
ndiv = max(len(r) - 1, 1)
|
|
255
|
+
self._calc.rstep = (hi - lo) / ndiv
|
|
256
|
+
self._calc.rmin = lo
|
|
257
|
+
self._calc.rmax = hi + 0.5 * self._calc.rstep
|
|
258
|
+
return
|
|
259
|
+
|
|
260
|
+
def _validate(self):
|
|
261
|
+
"""Validate my state.
|
|
262
|
+
|
|
263
|
+
This validates that the phase is not None. This performs
|
|
264
|
+
ProfileGenerator validations.
|
|
265
|
+
|
|
266
|
+
Raises SrFitError if validation fails.
|
|
267
|
+
"""
|
|
268
|
+
if self._calc is None:
|
|
269
|
+
raise SrFitError("_calc is None")
|
|
270
|
+
if self._phase is None:
|
|
271
|
+
raise SrFitError("_phase is None")
|
|
272
|
+
ProfileGenerator._validate(self)
|
|
273
|
+
return
|
|
274
|
+
|
|
275
|
+
def __call__(self, r):
|
|
276
|
+
"""Calculate the PDF.
|
|
277
|
+
|
|
278
|
+
This ProfileGenerator will be used in a fit equation that will
|
|
279
|
+
be optimized to fit some data. By the time this function is
|
|
280
|
+
evaluated, the crystal has been updated by the optimizer via the
|
|
281
|
+
ObjCrystParSet created in setCrystal. Thus, we need only call
|
|
282
|
+
pdf with the internal structure object.
|
|
283
|
+
"""
|
|
284
|
+
if not numpy.array_equal(r, self._lastr):
|
|
285
|
+
self._prepare(r)
|
|
286
|
+
|
|
287
|
+
rcalc, y = self._calc(self._phase._getSrRealStructure())
|
|
288
|
+
|
|
289
|
+
if numpy.isnan(y).any():
|
|
290
|
+
y = numpy.zeros_like(r)
|
|
291
|
+
else:
|
|
292
|
+
y = numpy.interp(r, rcalc, y)
|
|
293
|
+
return y
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
# End class BasePDFGenerator
|