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,311 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
##############################################################################
|
|
3
|
+
#
|
|
4
|
+
# diffpy.srfit by DANSE Diffraction group
|
|
5
|
+
# Simon J. L. Billinge
|
|
6
|
+
# (c) 2010 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
|
+
"""PDFContribution class.
|
|
16
|
+
|
|
17
|
+
This is a custom FitContribution that simplifies the creation of PDF
|
|
18
|
+
fits.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
__all__ = ["PDFContribution"]
|
|
22
|
+
|
|
23
|
+
from diffpy.srfit.fitbase import FitContribution, Profile
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class PDFContribution(FitContribution):
|
|
27
|
+
"""PDFContribution class.
|
|
28
|
+
|
|
29
|
+
PDFContribution is a FitContribution that is customized for PDF fits. Data
|
|
30
|
+
and phases can be added directly to the PDFContribution. Setup of
|
|
31
|
+
constraints and restraints requires direct interaction with the generator
|
|
32
|
+
attributes (see setPhase).
|
|
33
|
+
|
|
34
|
+
Attributes
|
|
35
|
+
name -- A name for this FitContribution.
|
|
36
|
+
profile -- A Profile that holds the measured (and calculated)
|
|
37
|
+
signal.
|
|
38
|
+
_meta -- Metadata dictionary. This is specific to this object,
|
|
39
|
+
and not shared with the profile. This is used to record
|
|
40
|
+
configuration options, like qmax.
|
|
41
|
+
_calculators -- A managed dictionary of Calculators, indexed by name.
|
|
42
|
+
_constraints -- A set of constrained Parameters. Constraints can be
|
|
43
|
+
added using the 'constrain' methods.
|
|
44
|
+
_generators -- A managed dictionary of ProfileGenerators.
|
|
45
|
+
_parameters -- A managed OrderedDict of parameters.
|
|
46
|
+
_restraints -- A set of Restraints. Restraints can be added using the
|
|
47
|
+
'restrain' or 'confine' methods.
|
|
48
|
+
_parsets -- A managed dictionary of ParameterSets.
|
|
49
|
+
_eqfactory -- A diffpy.srfit.equation.builder.EquationFactory
|
|
50
|
+
instance that is used to create constraints and
|
|
51
|
+
restraints from string
|
|
52
|
+
_eq -- The FitContribution equation that will be optimized.
|
|
53
|
+
_reseq -- The residual equation.
|
|
54
|
+
_xname -- Name of the x-variable
|
|
55
|
+
_yname -- Name of the y-variable
|
|
56
|
+
_dyname -- Name of the dy-variable
|
|
57
|
+
|
|
58
|
+
Managed Parameters:
|
|
59
|
+
scale -- Scale factor
|
|
60
|
+
qbroad -- Resolution peak broadening term
|
|
61
|
+
qdamp -- Resolution peak dampening term
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
def __init__(self, name):
|
|
65
|
+
"""Create the PDFContribution.
|
|
66
|
+
|
|
67
|
+
name -- The name of the contribution.
|
|
68
|
+
"""
|
|
69
|
+
FitContribution.__init__(self, name)
|
|
70
|
+
self._meta = {}
|
|
71
|
+
# Add the profile
|
|
72
|
+
profile = Profile()
|
|
73
|
+
self.setProfile(profile, xname="r")
|
|
74
|
+
|
|
75
|
+
# Need a parameter for the overall scale, in the case that this is a
|
|
76
|
+
# multi-phase fit.
|
|
77
|
+
self.newParameter("scale", 1.0)
|
|
78
|
+
# Profile-related parameters that will be shared between the generators
|
|
79
|
+
self.newParameter("qdamp", 0)
|
|
80
|
+
self.newParameter("qbroad", 0)
|
|
81
|
+
return
|
|
82
|
+
|
|
83
|
+
# Data methods
|
|
84
|
+
|
|
85
|
+
def loadData(self, data):
|
|
86
|
+
"""Load the data in various formats.
|
|
87
|
+
|
|
88
|
+
This uses the PDFParser to load the data and then passes it to the
|
|
89
|
+
built-in profile with loadParsedData.
|
|
90
|
+
|
|
91
|
+
data -- An open file-like object, name of a file that contains data
|
|
92
|
+
or a string containing the data.
|
|
93
|
+
"""
|
|
94
|
+
# Get the data into a string
|
|
95
|
+
from diffpy.srfit.util.inpututils import inputToString
|
|
96
|
+
|
|
97
|
+
datstr = inputToString(data)
|
|
98
|
+
|
|
99
|
+
# Load data with a PDFParser
|
|
100
|
+
from diffpy.srfit.pdf.pdfparser import PDFParser
|
|
101
|
+
|
|
102
|
+
parser = PDFParser()
|
|
103
|
+
parser.parseString(datstr)
|
|
104
|
+
|
|
105
|
+
# Pass it to the profile
|
|
106
|
+
self.profile.loadParsedData(parser)
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
def setCalculationRange(self, xmin=None, xmax=None, dx=None):
|
|
110
|
+
"""Set epsilon-inclusive calculation range.
|
|
111
|
+
|
|
112
|
+
Adhere to the observed ``xobs`` points when ``dx`` is the same
|
|
113
|
+
as in the data. ``xmin`` and ``xmax`` are clipped at the bounds
|
|
114
|
+
of the observed data.
|
|
115
|
+
|
|
116
|
+
Parameters
|
|
117
|
+
----------
|
|
118
|
+
|
|
119
|
+
xmin : float or "obs", optional
|
|
120
|
+
The minimum value of the independent variable. Keep the
|
|
121
|
+
current minimum when not specified. If specified as "obs"
|
|
122
|
+
reset to the minimum observed value.
|
|
123
|
+
xmax : float or "obs", optional
|
|
124
|
+
The maximum value of the independent variable. Keep the
|
|
125
|
+
current maximum when not specified. If specified as "obs"
|
|
126
|
+
reset to the maximum observed value.
|
|
127
|
+
dx : float or "obs", optional
|
|
128
|
+
The sample spacing in the independent variable. When different
|
|
129
|
+
from the data, resample the ``x`` as anchored at ``xmin``.
|
|
130
|
+
|
|
131
|
+
Note that xmin is always inclusive (unless clipped). xmax is inclusive
|
|
132
|
+
if it is within the bounds of the observed data.
|
|
133
|
+
|
|
134
|
+
Raises
|
|
135
|
+
------
|
|
136
|
+
AttributeError
|
|
137
|
+
If there is no observed data.
|
|
138
|
+
ValueError
|
|
139
|
+
When xmin > xmax or if dx <= 0. Also if dx > xmax - xmin.
|
|
140
|
+
"""
|
|
141
|
+
return self.profile.setCalculationRange(xmin, xmax, dx)
|
|
142
|
+
|
|
143
|
+
def savetxt(self, fname, **kwargs):
|
|
144
|
+
"""Call numpy.savetxt with x, ycalc, y, dy.
|
|
145
|
+
|
|
146
|
+
This calls on the built-in Profile.
|
|
147
|
+
|
|
148
|
+
Arguments are passed to numpy.savetxt.
|
|
149
|
+
"""
|
|
150
|
+
return self.profile.savetxt(fname, **kwargs)
|
|
151
|
+
|
|
152
|
+
# Phase methods
|
|
153
|
+
|
|
154
|
+
def addStructure(self, name, stru, periodic=True):
|
|
155
|
+
"""Add a phase that goes into the PDF calculation.
|
|
156
|
+
|
|
157
|
+
name -- A name to give the generator that will manage the PDF
|
|
158
|
+
calculation from the passed structure. The adapted
|
|
159
|
+
structure will be accessible via the name "phase" as an
|
|
160
|
+
attribute of the generator, e.g.
|
|
161
|
+
contribution.name.phase, where 'contribution' is this
|
|
162
|
+
contribution and 'name' is passed name.
|
|
163
|
+
(default), then the name will be set as "phase".
|
|
164
|
+
stru -- diffpy.structure.Structure, pyobjcryst.crystal.Crystal or
|
|
165
|
+
pyobjcryst.molecule.Molecule instance. Default None.
|
|
166
|
+
periodic -- The structure should be treated as periodic. If this is
|
|
167
|
+
True (default), then a PDFGenerator will be used to
|
|
168
|
+
calculate the PDF from the phase. Otherwise, a
|
|
169
|
+
DebyePDFGenerator will be used. Note that some structures
|
|
170
|
+
do not support periodicity, in which case this may be
|
|
171
|
+
ignored.
|
|
172
|
+
|
|
173
|
+
Returns the new phase (ParameterSet appropriate for what was passed in
|
|
174
|
+
stru.)
|
|
175
|
+
"""
|
|
176
|
+
# Based on periodic, create the proper generator.
|
|
177
|
+
if periodic:
|
|
178
|
+
from diffpy.srfit.pdf.pdfgenerator import PDFGenerator
|
|
179
|
+
|
|
180
|
+
gen = PDFGenerator(name)
|
|
181
|
+
else:
|
|
182
|
+
from diffpy.srfit.pdf.debyepdfgenerator import DebyePDFGenerator
|
|
183
|
+
|
|
184
|
+
gen = DebyePDFGenerator(name)
|
|
185
|
+
|
|
186
|
+
# Set up the generator
|
|
187
|
+
gen.setStructure(stru, "phase", periodic)
|
|
188
|
+
self._setupGenerator(gen)
|
|
189
|
+
|
|
190
|
+
return gen.phase
|
|
191
|
+
|
|
192
|
+
def addPhase(self, name, parset, periodic=True):
|
|
193
|
+
"""Add a phase that goes into the PDF calculation.
|
|
194
|
+
|
|
195
|
+
name -- A name to give the generator that will manage the PDF
|
|
196
|
+
calculation from the passed parameter phase. The parset
|
|
197
|
+
will be accessible via the name "phase" as an attribute
|
|
198
|
+
of the generator, e.g., contribution.name.phase, where
|
|
199
|
+
'contribution' is this contribution and 'name' is passed
|
|
200
|
+
name.
|
|
201
|
+
parset -- A SrRealParSet that holds the structural information.
|
|
202
|
+
This can be used to share the phase between multiple
|
|
203
|
+
BasePDFGenerators, and have the changes in one reflect in
|
|
204
|
+
another.
|
|
205
|
+
periodic -- The structure should be treated as periodic. If this is
|
|
206
|
+
True (default), then a PDFGenerator will be used to
|
|
207
|
+
calculate the PDF from the phase. Otherwise, a
|
|
208
|
+
DebyePDFGenerator will be used. Note that some structures
|
|
209
|
+
do not support periodicity, in which case this may be
|
|
210
|
+
ignored.
|
|
211
|
+
|
|
212
|
+
Returns the new phase (ParameterSet appropriate for what was passed in
|
|
213
|
+
stru.)
|
|
214
|
+
"""
|
|
215
|
+
# Based on periodic, create the proper generator.
|
|
216
|
+
if periodic:
|
|
217
|
+
from diffpy.srfit.pdf.pdfgenerator import PDFGenerator
|
|
218
|
+
|
|
219
|
+
gen = PDFGenerator(name)
|
|
220
|
+
else:
|
|
221
|
+
from diffpy.srfit.pdf.debyepdfgenerator import DebyePDFGenerator
|
|
222
|
+
|
|
223
|
+
gen = DebyePDFGenerator(name)
|
|
224
|
+
|
|
225
|
+
# Set up the generator
|
|
226
|
+
gen.setPhase(parset, periodic)
|
|
227
|
+
self._setupGenerator(gen)
|
|
228
|
+
|
|
229
|
+
return gen.phase
|
|
230
|
+
|
|
231
|
+
def _setupGenerator(self, gen):
|
|
232
|
+
"""Setup a generator.
|
|
233
|
+
|
|
234
|
+
The generator must already have a managed SrRealParSet, added
|
|
235
|
+
with setStructure or setPhase.
|
|
236
|
+
"""
|
|
237
|
+
# Add the generator to this FitContribution
|
|
238
|
+
self.addProfileGenerator(gen)
|
|
239
|
+
|
|
240
|
+
# Set the proper equation for the fit, depending on the number of
|
|
241
|
+
# phases we have.
|
|
242
|
+
gnames = self._generators.keys()
|
|
243
|
+
eqstr = " + ".join(gnames)
|
|
244
|
+
eqstr = "scale * (%s)" % eqstr
|
|
245
|
+
self.setEquation(eqstr)
|
|
246
|
+
|
|
247
|
+
# Update with our metadata
|
|
248
|
+
gen.meta.update(self._meta)
|
|
249
|
+
gen.processMetaData()
|
|
250
|
+
|
|
251
|
+
# Constrain the shared parameters
|
|
252
|
+
self.constrain(gen.qdamp, self.qdamp)
|
|
253
|
+
self.constrain(gen.qbroad, self.qbroad)
|
|
254
|
+
return
|
|
255
|
+
|
|
256
|
+
# Calculation setup methods
|
|
257
|
+
|
|
258
|
+
def _getMetaValue(self, kwd):
|
|
259
|
+
"""Get metadata according to object hierarchy."""
|
|
260
|
+
# Check self, then generators then profile
|
|
261
|
+
if kwd in self._meta:
|
|
262
|
+
return self._meta[kwd]
|
|
263
|
+
for gen in self._generators.values():
|
|
264
|
+
if kwd in gen.meta:
|
|
265
|
+
return gen.meta[kwd]
|
|
266
|
+
val = self.profile.meta.get(kwd)
|
|
267
|
+
return val
|
|
268
|
+
|
|
269
|
+
def setScatteringType(self, type="X"):
|
|
270
|
+
"""Set the scattering type.
|
|
271
|
+
|
|
272
|
+
type -- "X" for x-ray or "N" for neutron
|
|
273
|
+
|
|
274
|
+
Raises ValueError if type is not "X" or "N"
|
|
275
|
+
"""
|
|
276
|
+
self._meta["stype"] = type
|
|
277
|
+
for gen in self._generators.values():
|
|
278
|
+
gen.setScatteringType(type)
|
|
279
|
+
return
|
|
280
|
+
|
|
281
|
+
def getScatteringType(self):
|
|
282
|
+
"""Get the scattering type.
|
|
283
|
+
|
|
284
|
+
See 'setScatteringType'.
|
|
285
|
+
"""
|
|
286
|
+
return self._getMetaValue("stype")
|
|
287
|
+
|
|
288
|
+
def setQmax(self, qmax):
|
|
289
|
+
"""Set the qmax value."""
|
|
290
|
+
self._meta["qmax"] = qmax
|
|
291
|
+
for gen in self._generators.values():
|
|
292
|
+
gen.setQmax(qmax)
|
|
293
|
+
return
|
|
294
|
+
|
|
295
|
+
def getQmax(self):
|
|
296
|
+
"""Get the qmax value."""
|
|
297
|
+
return self._getMetaValue("qmax")
|
|
298
|
+
|
|
299
|
+
def setQmin(self, qmin):
|
|
300
|
+
"""Set the qmin value."""
|
|
301
|
+
self._meta["qmin"] = qmin
|
|
302
|
+
for gen in self._generators.values():
|
|
303
|
+
gen.setQmin(qmin)
|
|
304
|
+
return
|
|
305
|
+
|
|
306
|
+
def getQmin(self):
|
|
307
|
+
"""Get the qmin value."""
|
|
308
|
+
return self._getMetaValue("qmin")
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
# End of file
|
|
@@ -0,0 +1,77 @@
|
|
|
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.
|
|
16
|
+
|
|
17
|
+
The PDFGenerator class can take a diffpy.structure,
|
|
18
|
+
pyobjcryst.crystal.Crystal or pyobjcryst.molecule.Molecule object and
|
|
19
|
+
calculate the crystal PDF from it. The passed structure object is
|
|
20
|
+
wrapped in a StructureParameter set, which makes its attributes
|
|
21
|
+
refinable. See the class definition for more details and the examples
|
|
22
|
+
for its use.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
__all__ = ["PDFGenerator"]
|
|
26
|
+
|
|
27
|
+
from diffpy.srfit.pdf.basepdfgenerator import BasePDFGenerator
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class PDFGenerator(BasePDFGenerator):
|
|
31
|
+
"""A class for calculating the PDF from a single crystal structure.
|
|
32
|
+
|
|
33
|
+
This works with diffpy.structure.Structure, pyobjcryst.crystal.Crystal and
|
|
34
|
+
pyobjcryst.molecule.Molecule instances. Note that the managed Parameters
|
|
35
|
+
are not created until the structure is added.
|
|
36
|
+
|
|
37
|
+
Attributes:
|
|
38
|
+
_calc -- PDFCalculator instance for calculating the PDF
|
|
39
|
+
_phase -- The structure ParameterSet used to calculate the profile.
|
|
40
|
+
_lastr -- The last value of r over which the PDF was calculated. This is
|
|
41
|
+
used to configure the calculator when r changes.
|
|
42
|
+
|
|
43
|
+
Managed Parameters:
|
|
44
|
+
scale -- Scale factor
|
|
45
|
+
delta1 -- Linear peak broadening term
|
|
46
|
+
delta2 -- Quadratic peak broadening term
|
|
47
|
+
qbroad -- Resolution peak broadening term
|
|
48
|
+
qdamp -- Resolution peak dampening term
|
|
49
|
+
|
|
50
|
+
Managed ParameterSets:
|
|
51
|
+
The structure ParameterSet (SrRealStructure instance) used to calculate the
|
|
52
|
+
profile is named by the user.
|
|
53
|
+
|
|
54
|
+
Usable Metadata:
|
|
55
|
+
stype -- The scattering type "X" for x-ray, "N" for neutron (see
|
|
56
|
+
'setScatteringType').
|
|
57
|
+
qmax -- The maximum scattering vector used to generate the PDF (see
|
|
58
|
+
setQmax).
|
|
59
|
+
qmin -- The minimum scattering vector used to generate the PDF (see
|
|
60
|
+
setQmin).
|
|
61
|
+
scale -- See Managed Parameters.
|
|
62
|
+
delta1 -- See Managed Parameters.
|
|
63
|
+
delta2 -- See Managed Parameters.
|
|
64
|
+
qbroad -- See Managed Parameters.
|
|
65
|
+
qdamp -- See Managed Parameters.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def __init__(self, name="pdf"):
|
|
69
|
+
"""Initialize the generator."""
|
|
70
|
+
from diffpy.srreal.pdfcalculator import PDFCalculator
|
|
71
|
+
|
|
72
|
+
BasePDFGenerator.__init__(self, name)
|
|
73
|
+
self._setCalculator(PDFCalculator())
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# End class PDFGenerator
|
|
@@ -0,0 +1,226 @@
|
|
|
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
|
+
"""This module contains parsers for PDF data.
|
|
16
|
+
|
|
17
|
+
PDFParser is suitable for parsing data generated from PDFGetN and
|
|
18
|
+
PDFGetX.
|
|
19
|
+
|
|
20
|
+
See the class documentation for more information.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
__all__ = ["PDFParser"]
|
|
24
|
+
|
|
25
|
+
import re
|
|
26
|
+
|
|
27
|
+
import numpy
|
|
28
|
+
|
|
29
|
+
from diffpy.srfit.exceptions import ParseError
|
|
30
|
+
from diffpy.srfit.fitbase.profileparser import ProfileParser
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class PDFParser(ProfileParser):
|
|
34
|
+
"""Class for holding a diffraction pattern.
|
|
35
|
+
|
|
36
|
+
Attributes
|
|
37
|
+
|
|
38
|
+
_format -- Name of the data format that this parses (string, default
|
|
39
|
+
""). The format string is a unique identifier for the data
|
|
40
|
+
format handled by the parser.
|
|
41
|
+
_banks -- The data from each bank. Each bank contains a
|
|
42
|
+
(x, y, dx, dy) tuple:
|
|
43
|
+
x -- A numpy array containing the independent
|
|
44
|
+
variable read from the file.
|
|
45
|
+
y -- A numpy array containing the profile
|
|
46
|
+
from the file.
|
|
47
|
+
dx -- A numpy array containing the uncertainty in x
|
|
48
|
+
read from the file. This is 0 if the
|
|
49
|
+
uncertainty cannot be read.
|
|
50
|
+
dy -- A numpy array containing the uncertainty read
|
|
51
|
+
from the file. This is 0 if the uncertainty
|
|
52
|
+
cannot be read.
|
|
53
|
+
_x -- Independent variable from the chosen bank
|
|
54
|
+
_y -- Profile from the chosen bank
|
|
55
|
+
_dx -- Uncertainty in independent variable from the chosen bank
|
|
56
|
+
_dy -- Uncertainty in profile from the chosen bank
|
|
57
|
+
_meta -- A dictionary containing metadata read from the file.
|
|
58
|
+
|
|
59
|
+
General Metadata
|
|
60
|
+
|
|
61
|
+
filename -- The name of the file from which data was parsed. This key
|
|
62
|
+
will not exist if data was not read from file.
|
|
63
|
+
nbanks -- The number of banks parsed.
|
|
64
|
+
bank -- The chosen bank number.
|
|
65
|
+
|
|
66
|
+
Metadata - These may appear in the metadata dictionary
|
|
67
|
+
|
|
68
|
+
stype -- The scattering type ("X", "N")
|
|
69
|
+
qmin -- Minimum scattering vector (float)
|
|
70
|
+
qmax -- Maximum scattering vector (float)
|
|
71
|
+
qdamp -- Resolution damping factor (float)
|
|
72
|
+
qbroad -- Resolution broadening factor (float)
|
|
73
|
+
spdiameter -- Nanoparticle diameter (float)
|
|
74
|
+
scale -- Data scale (float)
|
|
75
|
+
temperature -- Temperature (float)
|
|
76
|
+
doping -- Doping (float)
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
_format = "PDF"
|
|
80
|
+
|
|
81
|
+
def parseString(self, patstring):
|
|
82
|
+
"""Parse a string and set the _x, _y, _dx, _dy and _meta variables.
|
|
83
|
+
|
|
84
|
+
When _dx or _dy cannot be obtained in the data format it is set to 0.
|
|
85
|
+
|
|
86
|
+
This wipes out the currently loaded data and selected bank number.
|
|
87
|
+
|
|
88
|
+
Arguments
|
|
89
|
+
patstring -- A string containing the pattern
|
|
90
|
+
|
|
91
|
+
Raises ParseError if the string cannot be parsed
|
|
92
|
+
"""
|
|
93
|
+
# useful regex patterns:
|
|
94
|
+
rx = {"f": r"[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?"}
|
|
95
|
+
# find where does the data start
|
|
96
|
+
res = re.search(r"^#+ start data\s*(?:#.*\s+)*", patstring, re.M)
|
|
97
|
+
# start_data is position where the first data line starts
|
|
98
|
+
if res:
|
|
99
|
+
start_data = res.end()
|
|
100
|
+
else:
|
|
101
|
+
# find line that starts with a floating point number
|
|
102
|
+
regexp = r"^\s*%(f)s" % rx
|
|
103
|
+
res = re.search(regexp, patstring, re.M)
|
|
104
|
+
if res:
|
|
105
|
+
start_data = res.start()
|
|
106
|
+
else:
|
|
107
|
+
start_data = 0
|
|
108
|
+
header = patstring[:start_data]
|
|
109
|
+
databody = patstring[start_data:].strip()
|
|
110
|
+
|
|
111
|
+
# find where the metadata starts
|
|
112
|
+
metadata = ""
|
|
113
|
+
res = re.search(r"^#+\ +metadata\b\n", header, re.M)
|
|
114
|
+
if res:
|
|
115
|
+
metadata = header[res.end() :]
|
|
116
|
+
header = header[: res.start()]
|
|
117
|
+
|
|
118
|
+
# parse header
|
|
119
|
+
meta = self._meta
|
|
120
|
+
# stype
|
|
121
|
+
if re.search("(x-?ray|PDFgetX)", header, re.I):
|
|
122
|
+
meta["stype"] = "X"
|
|
123
|
+
elif re.search("(neutron|PDFgetN)", header, re.I):
|
|
124
|
+
meta["stype"] = "N"
|
|
125
|
+
# qmin
|
|
126
|
+
regexp = r"\bqmin *= *(%(f)s)\b" % rx
|
|
127
|
+
res = re.search(regexp, header, re.I)
|
|
128
|
+
if res:
|
|
129
|
+
meta["qmin"] = float(res.groups()[0])
|
|
130
|
+
# qmax
|
|
131
|
+
regexp = r"\bqmax *= *(%(f)s)\b" % rx
|
|
132
|
+
res = re.search(regexp, header, re.I)
|
|
133
|
+
if res:
|
|
134
|
+
meta["qmax"] = float(res.groups()[0])
|
|
135
|
+
# qdamp
|
|
136
|
+
regexp = r"\b(?:qdamp|qsig) *= *(%(f)s)\b" % rx
|
|
137
|
+
res = re.search(regexp, header, re.I)
|
|
138
|
+
if res:
|
|
139
|
+
meta["qdamp"] = float(res.groups()[0])
|
|
140
|
+
# qbroad
|
|
141
|
+
regexp = r"\b(?:qbroad|qalp) *= *(%(f)s)\b" % rx
|
|
142
|
+
res = re.search(regexp, header, re.I)
|
|
143
|
+
if res:
|
|
144
|
+
meta["qbroad"] = float(res.groups()[0])
|
|
145
|
+
# spdiameter
|
|
146
|
+
regexp = r"\bspdiameter *= *(%(f)s)\b" % rx
|
|
147
|
+
res = re.search(regexp, header, re.I)
|
|
148
|
+
if res:
|
|
149
|
+
meta["spdiameter"] = float(res.groups()[0])
|
|
150
|
+
# dscale
|
|
151
|
+
regexp = r"\bdscale *= *(%(f)s)\b" % rx
|
|
152
|
+
res = re.search(regexp, header, re.I)
|
|
153
|
+
if res:
|
|
154
|
+
meta["scale"] = float(res.groups()[0])
|
|
155
|
+
# temperature
|
|
156
|
+
regexp = r"\b(?:temp|temperature|T)\ *=\ *(%(f)s)\b" % rx
|
|
157
|
+
res = re.search(regexp, header)
|
|
158
|
+
if res:
|
|
159
|
+
meta["temperature"] = float(res.groups()[0])
|
|
160
|
+
# doping
|
|
161
|
+
regexp = r"\b(?:x|doping)\ *=\ *(%(f)s)\b" % rx
|
|
162
|
+
res = re.search(regexp, header)
|
|
163
|
+
if res:
|
|
164
|
+
meta["doping"] = float(res.groups()[0])
|
|
165
|
+
|
|
166
|
+
# parsing general metadata
|
|
167
|
+
if metadata:
|
|
168
|
+
regexp = r"\b(\w+)\ *=\ *(%(f)s)\b" % rx
|
|
169
|
+
while True:
|
|
170
|
+
res = re.search(regexp, metadata, re.M)
|
|
171
|
+
if res:
|
|
172
|
+
meta[res.groups()[0]] = float(res.groups()[1])
|
|
173
|
+
metadata = metadata[res.end() :]
|
|
174
|
+
else:
|
|
175
|
+
break
|
|
176
|
+
|
|
177
|
+
# read actual data - robs, Gobs, drobs, dGobs
|
|
178
|
+
inf_or_nan = re.compile("(?i)^[+-]?(NaN|Inf)\\b")
|
|
179
|
+
has_drobs = True
|
|
180
|
+
has_dGobs = True
|
|
181
|
+
# raise ParseError if something goes wrong
|
|
182
|
+
robs = []
|
|
183
|
+
Gobs = []
|
|
184
|
+
drobs = []
|
|
185
|
+
dGobs = []
|
|
186
|
+
try:
|
|
187
|
+
for line in databody.split("\n"):
|
|
188
|
+
v = line.split()
|
|
189
|
+
# there should be at least 2 value in the line
|
|
190
|
+
robs.append(float(v[0]))
|
|
191
|
+
Gobs.append(float(v[1]))
|
|
192
|
+
# drobs is valid if all values are defined and positive
|
|
193
|
+
has_drobs = (
|
|
194
|
+
has_drobs and len(v) > 2 and not inf_or_nan.match(v[2])
|
|
195
|
+
)
|
|
196
|
+
if has_drobs:
|
|
197
|
+
v2 = float(v[2])
|
|
198
|
+
has_drobs = v2 > 0.0
|
|
199
|
+
drobs.append(v2)
|
|
200
|
+
# dGobs is valid if all values are defined and positive
|
|
201
|
+
has_dGobs = (
|
|
202
|
+
has_dGobs and len(v) > 3 and not inf_or_nan.match(v[3])
|
|
203
|
+
)
|
|
204
|
+
if has_dGobs:
|
|
205
|
+
v3 = float(v[3])
|
|
206
|
+
has_dGobs = v3 > 0.0
|
|
207
|
+
dGobs.append(v3)
|
|
208
|
+
except (ValueError, IndexError) as err:
|
|
209
|
+
raise ParseError(err)
|
|
210
|
+
if has_drobs:
|
|
211
|
+
drobs = numpy.asarray(drobs)
|
|
212
|
+
else:
|
|
213
|
+
drobs = None
|
|
214
|
+
if has_dGobs:
|
|
215
|
+
dGobs = numpy.asarray(dGobs)
|
|
216
|
+
else:
|
|
217
|
+
dGobs = None
|
|
218
|
+
|
|
219
|
+
robs = numpy.asarray(robs)
|
|
220
|
+
Gobs = numpy.asarray(Gobs)
|
|
221
|
+
|
|
222
|
+
self._banks.append([robs, Gobs, drobs, dGobs])
|
|
223
|
+
return
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
# End of PDFParser
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
"""SAS calculation tools."""
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"SASGenerator",
|
|
19
|
+
"SASParser",
|
|
20
|
+
"SASProfile",
|
|
21
|
+
"PrCalculator",
|
|
22
|
+
"CFCalculator",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
from .prcalculator import CFCalculator, PrCalculator
|
|
26
|
+
from .sasgenerator import SASGenerator
|
|
27
|
+
from .sasparser import SASParser
|
|
28
|
+
from .sasprofile import SASProfile
|
|
29
|
+
|
|
30
|
+
# End of file
|