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.
Files changed (73) hide show
  1. diffpy/__init__.py +15 -0
  2. diffpy/srfit/__init__.py +41 -0
  3. diffpy/srfit/equation/__init__.py +31 -0
  4. diffpy/srfit/equation/builder.py +702 -0
  5. diffpy/srfit/equation/equationmod.py +213 -0
  6. diffpy/srfit/equation/literals/__init__.py +71 -0
  7. diffpy/srfit/equation/literals/abcs.py +81 -0
  8. diffpy/srfit/equation/literals/argument.py +76 -0
  9. diffpy/srfit/equation/literals/literal.py +69 -0
  10. diffpy/srfit/equation/literals/operators.py +380 -0
  11. diffpy/srfit/equation/visitors/__init__.py +94 -0
  12. diffpy/srfit/equation/visitors/argfinder.py +62 -0
  13. diffpy/srfit/equation/visitors/printer.py +120 -0
  14. diffpy/srfit/equation/visitors/swapper.py +142 -0
  15. diffpy/srfit/equation/visitors/validator.py +113 -0
  16. diffpy/srfit/equation/visitors/visitor.py +62 -0
  17. diffpy/srfit/exceptions.py +29 -0
  18. diffpy/srfit/fitbase/__init__.py +53 -0
  19. diffpy/srfit/fitbase/calculator.py +110 -0
  20. diffpy/srfit/fitbase/configurable.py +57 -0
  21. diffpy/srfit/fitbase/constraint.py +117 -0
  22. diffpy/srfit/fitbase/fitcontribution.py +351 -0
  23. diffpy/srfit/fitbase/fithook.py +227 -0
  24. diffpy/srfit/fitbase/fitrecipe.py +826 -0
  25. diffpy/srfit/fitbase/fitresults.py +674 -0
  26. diffpy/srfit/fitbase/parameter.py +314 -0
  27. diffpy/srfit/fitbase/parameterset.py +110 -0
  28. diffpy/srfit/fitbase/profile.py +405 -0
  29. diffpy/srfit/fitbase/profilegenerator.py +168 -0
  30. diffpy/srfit/fitbase/profileparser.py +179 -0
  31. diffpy/srfit/fitbase/recipeorganizer.py +1074 -0
  32. diffpy/srfit/fitbase/restraint.py +117 -0
  33. diffpy/srfit/fitbase/simplerecipe.py +230 -0
  34. diffpy/srfit/fitbase/validatable.py +59 -0
  35. diffpy/srfit/interface/__init__.py +33 -0
  36. diffpy/srfit/interface/interface.py +180 -0
  37. diffpy/srfit/pdf/__init__.py +24 -0
  38. diffpy/srfit/pdf/basepdfgenerator.py +296 -0
  39. diffpy/srfit/pdf/characteristicfunctions.py +432 -0
  40. diffpy/srfit/pdf/debyepdfgenerator.py +115 -0
  41. diffpy/srfit/pdf/pdfcontribution.py +311 -0
  42. diffpy/srfit/pdf/pdfgenerator.py +77 -0
  43. diffpy/srfit/pdf/pdfparser.py +226 -0
  44. diffpy/srfit/sas/__init__.py +30 -0
  45. diffpy/srfit/sas/prcalculator.py +139 -0
  46. diffpy/srfit/sas/sasgenerator.py +70 -0
  47. diffpy/srfit/sas/sasimport.py +66 -0
  48. diffpy/srfit/sas/sasparameter.py +70 -0
  49. diffpy/srfit/sas/sasparser.py +133 -0
  50. diffpy/srfit/sas/sasprofile.py +94 -0
  51. diffpy/srfit/structure/__init__.py +60 -0
  52. diffpy/srfit/structure/basestructureparset.py +62 -0
  53. diffpy/srfit/structure/bvsrestraint.py +101 -0
  54. diffpy/srfit/structure/cctbxparset.py +292 -0
  55. diffpy/srfit/structure/diffpyparset.py +303 -0
  56. diffpy/srfit/structure/objcrystparset.py +1552 -0
  57. diffpy/srfit/structure/sgconstraints.py +761 -0
  58. diffpy/srfit/structure/srrealparset.py +92 -0
  59. diffpy/srfit/util/__init__.py +50 -0
  60. diffpy/srfit/util/argbinders.py +29 -0
  61. diffpy/srfit/util/inpututils.py +50 -0
  62. diffpy/srfit/util/nameutils.py +45 -0
  63. diffpy/srfit/util/observable.py +93 -0
  64. diffpy/srfit/util/tagmanager.py +150 -0
  65. diffpy/srfit/util/weakrefcallable.py +170 -0
  66. diffpy/srfit/version.py +26 -0
  67. diffpy_srfit-3.1.0.dist-info/METADATA +216 -0
  68. diffpy_srfit-3.1.0.dist-info/RECORD +73 -0
  69. diffpy_srfit-3.1.0.dist-info/WHEEL +5 -0
  70. diffpy_srfit-3.1.0.dist-info/licenses/AUTHORS.rst +10 -0
  71. diffpy_srfit-3.1.0.dist-info/licenses/LICENSE.rst +138 -0
  72. diffpy_srfit-3.1.0.dist-info/licenses/LICENSE_DANSE.rst +34 -0
  73. 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