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,380 @@
|
|
|
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
|
+
"""Operator classes.
|
|
16
|
+
|
|
17
|
+
Operators are combined with other Literals to create an equation.
|
|
18
|
+
Operators are non-leaf nodes on a Literal tree. These trees can be
|
|
19
|
+
evaluated by the Evaluator visitor, or otherwise inspected.
|
|
20
|
+
|
|
21
|
+
The Operator class contains all the information necessary to be
|
|
22
|
+
identified and evaluated by a Visitor. Thus, a single onOperator method
|
|
23
|
+
exists in the Visitor base class. Other Operators can be derived from
|
|
24
|
+
Operator (see AdditionOperator), but they all identify themselves with
|
|
25
|
+
the Visitor.onOperator method.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"Operator",
|
|
30
|
+
"AdditionOperator",
|
|
31
|
+
"SubtractionOperator",
|
|
32
|
+
"MultiplicationOperator",
|
|
33
|
+
"DivisionOperator",
|
|
34
|
+
"ExponentiationOperator",
|
|
35
|
+
"RemainderOperator",
|
|
36
|
+
"NegationOperator",
|
|
37
|
+
"ConvolutionOperator",
|
|
38
|
+
"SumOperator",
|
|
39
|
+
"UFuncOperator",
|
|
40
|
+
"ArrayOperator",
|
|
41
|
+
"PolyvalOperator",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
import numpy
|
|
45
|
+
|
|
46
|
+
from diffpy.srfit.equation.literals.abcs import OperatorABC
|
|
47
|
+
from diffpy.srfit.equation.literals.literal import Literal
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class Operator(Literal, OperatorABC):
|
|
51
|
+
"""Abstract class for specifying a general operator.
|
|
52
|
+
|
|
53
|
+
This class provides several methods that are common to a derived
|
|
54
|
+
classes for concrete operations.
|
|
55
|
+
|
|
56
|
+
Class Attributes
|
|
57
|
+
----------------
|
|
58
|
+
nin : int, abstract
|
|
59
|
+
Number of input arguments for the operator. Any number of
|
|
60
|
+
arguments is allowed when -1. This attribute must be defined
|
|
61
|
+
in a derived class.
|
|
62
|
+
nout : int, abstract
|
|
63
|
+
Number of outputs returned by the `operation`. This attribute
|
|
64
|
+
must be defined in a derived class.
|
|
65
|
+
operation : callable, abstract
|
|
66
|
+
Function that performs the operation, e.g., `numpy.add`.
|
|
67
|
+
This must be defined in a derived class.
|
|
68
|
+
symbol : str, abstract
|
|
69
|
+
The symbolic representation for the operator such as
|
|
70
|
+
"+" or "sin". This attribute must be defined in a derived
|
|
71
|
+
class.
|
|
72
|
+
|
|
73
|
+
Attributes
|
|
74
|
+
----------
|
|
75
|
+
args : list
|
|
76
|
+
The list of `Literal` arguments. Read-only, use the
|
|
77
|
+
`addLiteral` method to change its content.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
# Private Attributes
|
|
81
|
+
# ------------------
|
|
82
|
+
# _value : float, numpy.ndarray or None
|
|
83
|
+
# The last value of the operator or None.
|
|
84
|
+
|
|
85
|
+
# We must declare the abstract `args` here.
|
|
86
|
+
args = None
|
|
87
|
+
# default for the value
|
|
88
|
+
_value = None
|
|
89
|
+
|
|
90
|
+
def __init__(self, name=None):
|
|
91
|
+
"""Initialize the operator object with the specified name.
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
name : str, optional
|
|
96
|
+
Name for the operator object. When not specified,
|
|
97
|
+
use the class attribute `name`.
|
|
98
|
+
"""
|
|
99
|
+
Literal.__init__(self, name)
|
|
100
|
+
self.args = []
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
def identify(self, visitor):
|
|
104
|
+
"""Identify self to a visitor."""
|
|
105
|
+
return visitor.onOperator(self)
|
|
106
|
+
|
|
107
|
+
def addLiteral(self, literal):
|
|
108
|
+
"""Add a literal to this operator.
|
|
109
|
+
|
|
110
|
+
Note that order of operation matters. The first literal added is
|
|
111
|
+
the leftmost argument. The last is the rightmost.
|
|
112
|
+
|
|
113
|
+
Raises ValueError if the literal causes a self-reference.
|
|
114
|
+
"""
|
|
115
|
+
# Make sure we don't have self-reference
|
|
116
|
+
self._loopCheck(literal)
|
|
117
|
+
self.args.append(literal)
|
|
118
|
+
literal.addObserver(self._flush)
|
|
119
|
+
self._flush(other=(self,))
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
def getValue(self):
|
|
123
|
+
"""Get or evaluate the value of the operator."""
|
|
124
|
+
if self._value is None:
|
|
125
|
+
vals = [arg.value for arg in self.args]
|
|
126
|
+
self._value = self.operation(*vals)
|
|
127
|
+
return self._value
|
|
128
|
+
|
|
129
|
+
value = property(lambda self: self.getValue())
|
|
130
|
+
|
|
131
|
+
def _loopCheck(self, literal):
|
|
132
|
+
"""Check if a literal causes self-reference."""
|
|
133
|
+
if literal is self:
|
|
134
|
+
raise ValueError("'%s' causes self-reference" % literal)
|
|
135
|
+
|
|
136
|
+
# Check to see if I am a dependency of the literal.
|
|
137
|
+
if hasattr(literal, "args"):
|
|
138
|
+
for lit_arg in literal.args:
|
|
139
|
+
self._loopCheck(lit_arg)
|
|
140
|
+
return
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class UnaryOperator(Operator):
|
|
144
|
+
"""Abstract class for an unary operator with one input and one result.
|
|
145
|
+
|
|
146
|
+
This base class defines the `nin` and `nout` attributes. The derived
|
|
147
|
+
concrete operator must provide the remaining abstract attributes
|
|
148
|
+
of the `Operator` class.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
nin = 1
|
|
152
|
+
nout = 1
|
|
153
|
+
pass
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class BinaryOperator(Operator):
|
|
157
|
+
"""Abstract class for a binary operator with two inputs and one result.
|
|
158
|
+
|
|
159
|
+
This base class defines the `nin` and `nout` attributes. The derived
|
|
160
|
+
concrete operator must define the remaining abstract attributes
|
|
161
|
+
of the `Operator` class.
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
nin = 2
|
|
165
|
+
nout = 1
|
|
166
|
+
pass
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class CustomOperator(Operator):
|
|
170
|
+
"""Concrete class for a user-defined Operator.
|
|
171
|
+
|
|
172
|
+
Use the `makeOperator` factory function to create an instance.
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
# declare all abstract attributes from the Operator base.
|
|
176
|
+
nin = None
|
|
177
|
+
nout = None
|
|
178
|
+
operation = None
|
|
179
|
+
symbol = None
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def makeOperator(name, symbol, operation, nin, nout):
|
|
184
|
+
"""Return a new custom operator object.
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
name : str
|
|
189
|
+
Name of the custom operator object.
|
|
190
|
+
symbol : str
|
|
191
|
+
The symbolic representation for the operator such as
|
|
192
|
+
"+" or "sin".
|
|
193
|
+
operation : callable
|
|
194
|
+
Function that performs the operation, e.g., `numpy.add`.
|
|
195
|
+
nin : int
|
|
196
|
+
Number of input arguments for the operator. Any number of
|
|
197
|
+
arguments is allowed when -1.
|
|
198
|
+
nout : in
|
|
199
|
+
Number of outputs returned by the `operation`.
|
|
200
|
+
|
|
201
|
+
Returns
|
|
202
|
+
-------
|
|
203
|
+
CustomOperator
|
|
204
|
+
The new custom operator object.
|
|
205
|
+
"""
|
|
206
|
+
op = CustomOperator(name=name)
|
|
207
|
+
op.symbol = symbol
|
|
208
|
+
op.operation = operation
|
|
209
|
+
op.nin = nin
|
|
210
|
+
op.nout = nout
|
|
211
|
+
return op
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
# Some specified operators
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class AdditionOperator(BinaryOperator):
|
|
218
|
+
"""Addition operator."""
|
|
219
|
+
|
|
220
|
+
name = "add"
|
|
221
|
+
symbol = "+"
|
|
222
|
+
operation = staticmethod(numpy.add)
|
|
223
|
+
pass
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class SubtractionOperator(BinaryOperator):
|
|
227
|
+
"""Subtraction operator."""
|
|
228
|
+
|
|
229
|
+
name = "subtract"
|
|
230
|
+
symbol = "-"
|
|
231
|
+
operation = staticmethod(numpy.subtract)
|
|
232
|
+
pass
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
class MultiplicationOperator(BinaryOperator):
|
|
236
|
+
"""Multiplication operator."""
|
|
237
|
+
|
|
238
|
+
name = "multiply"
|
|
239
|
+
symbol = "*"
|
|
240
|
+
operation = staticmethod(numpy.multiply)
|
|
241
|
+
pass
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
class DivisionOperator(BinaryOperator):
|
|
245
|
+
"""Division operator."""
|
|
246
|
+
|
|
247
|
+
name = "divide"
|
|
248
|
+
symbol = "/"
|
|
249
|
+
operation = staticmethod(numpy.divide)
|
|
250
|
+
pass
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
class ExponentiationOperator(BinaryOperator):
|
|
254
|
+
"""Exponentiation operator."""
|
|
255
|
+
|
|
256
|
+
name = "power"
|
|
257
|
+
symbol = "**"
|
|
258
|
+
operation = staticmethod(numpy.power)
|
|
259
|
+
pass
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
class RemainderOperator(BinaryOperator):
|
|
263
|
+
"""Remainder operator."""
|
|
264
|
+
|
|
265
|
+
name = "mod"
|
|
266
|
+
symbol = "%"
|
|
267
|
+
operation = staticmethod(numpy.mod)
|
|
268
|
+
pass
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
class NegationOperator(UnaryOperator):
|
|
272
|
+
"""Negation operator."""
|
|
273
|
+
|
|
274
|
+
name = "negative"
|
|
275
|
+
symbol = "-"
|
|
276
|
+
operation = staticmethod(numpy.negative)
|
|
277
|
+
pass
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def _conv(v1, v2):
|
|
281
|
+
# Get the full convolution
|
|
282
|
+
c = numpy.convolve(v1, v2, mode="full")
|
|
283
|
+
# Find the centroid of the first signal
|
|
284
|
+
s1 = sum(v1)
|
|
285
|
+
x1 = numpy.arange(len(v1), dtype=float)
|
|
286
|
+
c1idx = numpy.sum(v1 * x1) / s1
|
|
287
|
+
# Find the centroid of the convolution
|
|
288
|
+
xc = numpy.arange(len(c), dtype=float)
|
|
289
|
+
ccidx = numpy.sum(c * xc) / sum(c)
|
|
290
|
+
# Interpolate the convolution such that the centroids line up. This
|
|
291
|
+
# uses linear interpolation.
|
|
292
|
+
shift = ccidx - c1idx
|
|
293
|
+
x1 += shift
|
|
294
|
+
c = numpy.interp(x1, xc, c)
|
|
295
|
+
|
|
296
|
+
# Normalize
|
|
297
|
+
sc = sum(c)
|
|
298
|
+
if sc > 0:
|
|
299
|
+
c *= s1 / sc
|
|
300
|
+
|
|
301
|
+
return c
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class ConvolutionOperator(BinaryOperator):
|
|
305
|
+
"""Convolve two signals.
|
|
306
|
+
|
|
307
|
+
This convolves two signals such that centroid of the first array is
|
|
308
|
+
not altered by the convolution. Furthermore, the integrated
|
|
309
|
+
amplitude of the convolution is scaled to be that of the first
|
|
310
|
+
signal. This is mean to act as a convolution of a signal by a
|
|
311
|
+
probability distribution.
|
|
312
|
+
|
|
313
|
+
Note that this is only possible when the signals are computed over
|
|
314
|
+
the same range.
|
|
315
|
+
"""
|
|
316
|
+
|
|
317
|
+
name = "convolve"
|
|
318
|
+
symbol = "convolve"
|
|
319
|
+
operation = staticmethod(_conv)
|
|
320
|
+
pass
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
class SumOperator(UnaryOperator):
|
|
324
|
+
"""numpy.sum operator."""
|
|
325
|
+
|
|
326
|
+
name = "sum"
|
|
327
|
+
symbol = "sum"
|
|
328
|
+
operation = staticmethod(numpy.sum)
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
class UFuncOperator(Operator):
|
|
332
|
+
"""A operator wrapper around a numpy ufunc.
|
|
333
|
+
|
|
334
|
+
The name and symbol attributes are set equal to the ufunc.__name__
|
|
335
|
+
attribute. nin and nout are also taken from the ufunc.
|
|
336
|
+
"""
|
|
337
|
+
|
|
338
|
+
symbol = None
|
|
339
|
+
nin = None
|
|
340
|
+
nout = None
|
|
341
|
+
operation = None
|
|
342
|
+
|
|
343
|
+
def __init__(self, op):
|
|
344
|
+
"""Initialization.
|
|
345
|
+
|
|
346
|
+
Arguments
|
|
347
|
+
|
|
348
|
+
op -- A numpy ufunc
|
|
349
|
+
"""
|
|
350
|
+
Operator.__init__(self, name=op.__name__)
|
|
351
|
+
self.symbol = op.__name__
|
|
352
|
+
self.nin = op.nin
|
|
353
|
+
self.nout = op.nout
|
|
354
|
+
self.operation = op
|
|
355
|
+
return
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
class ArrayOperator(Operator):
|
|
359
|
+
"""Operator that will take parameters and turn them into an array."""
|
|
360
|
+
|
|
361
|
+
name = "array"
|
|
362
|
+
symbol = "array"
|
|
363
|
+
nin = -1
|
|
364
|
+
nout = 1
|
|
365
|
+
|
|
366
|
+
@staticmethod
|
|
367
|
+
def operation(*args):
|
|
368
|
+
return numpy.array(args)
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class PolyvalOperator(BinaryOperator):
|
|
372
|
+
"""Operator for numpy polyval."""
|
|
373
|
+
|
|
374
|
+
name = "polyval"
|
|
375
|
+
symbol = "polyval"
|
|
376
|
+
operation = staticmethod(numpy.polyval)
|
|
377
|
+
pass
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
# End of file
|
|
@@ -0,0 +1,94 @@
|
|
|
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
|
+
"""Visitors that perform on Literal networks.
|
|
16
|
+
|
|
17
|
+
Visitors are designed to traverse and extract information from Literal
|
|
18
|
+
networks (diffpy.srfit.equation.literals). Visitors are used to
|
|
19
|
+
validate, print and extracting Arguments from Literal networks.
|
|
20
|
+
|
|
21
|
+
The Literal-Visitor relationship is that described by the Visitor
|
|
22
|
+
pattern (
|
|
23
|
+
|
|
24
|
+
http://en.wikipedia.org/wiki/Visitor_pattern).
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from __future__ import print_function
|
|
28
|
+
|
|
29
|
+
from diffpy.srfit.equation.visitors.argfinder import ArgFinder
|
|
30
|
+
from diffpy.srfit.equation.visitors.printer import Printer
|
|
31
|
+
from diffpy.srfit.equation.visitors.swapper import Swapper
|
|
32
|
+
from diffpy.srfit.equation.visitors.validator import Validator
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def getArgs(literal, getconsts=True):
|
|
36
|
+
"""Get the Arguments of a Literal tree.
|
|
37
|
+
|
|
38
|
+
getconsts -- If True (default), then Arguments designated as constant
|
|
39
|
+
are also retrieved.
|
|
40
|
+
|
|
41
|
+
Returns a list of Arguments searched for depth-first.
|
|
42
|
+
"""
|
|
43
|
+
v = ArgFinder(getconsts)
|
|
44
|
+
return literal.identify(v)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def getExpression(literal, eqskip=None):
|
|
48
|
+
"""Get math expression string from the Literal tree object.
|
|
49
|
+
|
|
50
|
+
eqskip -- regular expression pattern for Equation objects that should
|
|
51
|
+
be printed under their own name. Expand all Equation objects
|
|
52
|
+
when None.
|
|
53
|
+
|
|
54
|
+
Return string.
|
|
55
|
+
"""
|
|
56
|
+
v = Printer()
|
|
57
|
+
v.eqskip = eqskip
|
|
58
|
+
rv = literal.identify(v)
|
|
59
|
+
return rv
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def prettyPrint(literal):
|
|
63
|
+
"""Print a Literal tree."""
|
|
64
|
+
print(getExpression(literal))
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def validate(literal):
|
|
69
|
+
"""Validate a Literal tree.
|
|
70
|
+
|
|
71
|
+
Raises ValueError if the tree contains errors.
|
|
72
|
+
"""
|
|
73
|
+
v = Validator()
|
|
74
|
+
errors = literal.identify(v)
|
|
75
|
+
if errors:
|
|
76
|
+
m = "Errors found in Literal tree '%s'\n" % literal
|
|
77
|
+
m += "\n".join(errors)
|
|
78
|
+
raise ValueError(m)
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def swap(literal, oldlit, newlit):
|
|
83
|
+
"""Swap one literal for another in a Literal tree.
|
|
84
|
+
|
|
85
|
+
Corrections are done in-place unless literal is oldlit, in which
|
|
86
|
+
case the return value is newlit.
|
|
87
|
+
|
|
88
|
+
Returns the literal tree with oldlit swapped for newlit.
|
|
89
|
+
"""
|
|
90
|
+
if literal is oldlit:
|
|
91
|
+
return newlit
|
|
92
|
+
v = Swapper(oldlit, newlit)
|
|
93
|
+
literal.identify(v)
|
|
94
|
+
return literal
|
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
"""Visitor for extracting the Argument entries in a Literal tree.
|
|
16
|
+
|
|
17
|
+
ArgFinder extracts all Arguments from a literal true.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
__all__ = ["ArgFinder"]
|
|
21
|
+
|
|
22
|
+
from diffpy.srfit.equation.visitors.visitor import Visitor
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ArgFinder(Visitor):
|
|
26
|
+
"""ArgFinder extracts Arguments from a Literal tree.
|
|
27
|
+
|
|
28
|
+
Attributes
|
|
29
|
+
args -- The list of collected Arguments
|
|
30
|
+
getconsts -- Flag indicating whether to grab constant arguments.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, getconsts=True):
|
|
34
|
+
"""Initialize.
|
|
35
|
+
|
|
36
|
+
Arguments
|
|
37
|
+
getconsts -- Flag indicating whether to parse constant arguments
|
|
38
|
+
(default True).
|
|
39
|
+
"""
|
|
40
|
+
self.args = []
|
|
41
|
+
self.getconsts = getconsts
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
def reset(self):
|
|
45
|
+
"""Reset the argument set."""
|
|
46
|
+
self.args = []
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
def onArgument(self, arg):
|
|
50
|
+
"""Process an Argument node."""
|
|
51
|
+
if self.getconsts or not arg.const:
|
|
52
|
+
self.args.append(arg)
|
|
53
|
+
return self.args
|
|
54
|
+
|
|
55
|
+
def onOperator(self, op):
|
|
56
|
+
"""Process an Operator node."""
|
|
57
|
+
for arg in op.args:
|
|
58
|
+
arg.identify(self)
|
|
59
|
+
return self.args
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# End of file
|
|
@@ -0,0 +1,120 @@
|
|
|
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
|
+
"""Printer visitor for printing the equation represented by a Literal tree.
|
|
16
|
+
|
|
17
|
+
The Printer visitor creates a one-line representation of the Literal
|
|
18
|
+
tree, which is valid as a string equivalent of the equation.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
__all__ = ["Printer"]
|
|
22
|
+
|
|
23
|
+
import re
|
|
24
|
+
|
|
25
|
+
from diffpy.srfit.equation.visitors.visitor import Visitor
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Printer(Visitor):
|
|
29
|
+
"""Printer for printing a Literal tree.
|
|
30
|
+
|
|
31
|
+
Attributes:
|
|
32
|
+
|
|
33
|
+
eqskip -- regular expression pattern for Equation objects that should
|
|
34
|
+
not be expanded, but printed under their own name. Expand
|
|
35
|
+
all equations when None.
|
|
36
|
+
output -- The output generated by the printer.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
# store compiled RE pattern for eqskip or None when none.
|
|
40
|
+
_eqpat = None
|
|
41
|
+
|
|
42
|
+
def __init__(self):
|
|
43
|
+
"""Initialize."""
|
|
44
|
+
self.reset()
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
def reset(self):
|
|
48
|
+
"""Reset the out put string."""
|
|
49
|
+
self.output = ""
|
|
50
|
+
return
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def eqskip(self):
|
|
54
|
+
"""Pattern for equation objects to be skipped.
|
|
55
|
+
|
|
56
|
+
Expand all equations when None.
|
|
57
|
+
"""
|
|
58
|
+
rv = None
|
|
59
|
+
if self._eqpat is not None:
|
|
60
|
+
rv = self._eqpat.pattern
|
|
61
|
+
return rv
|
|
62
|
+
|
|
63
|
+
@eqskip.setter
|
|
64
|
+
def eqskip(self, value):
|
|
65
|
+
if value is None:
|
|
66
|
+
self._eqpat = None
|
|
67
|
+
else:
|
|
68
|
+
self._eqpat = re.compile(value)
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
def onArgument(self, arg):
|
|
72
|
+
"""Process an Argument node.
|
|
73
|
+
|
|
74
|
+
No assumption is made about the argument type.
|
|
75
|
+
"""
|
|
76
|
+
if arg.name is None:
|
|
77
|
+
self.output += str(arg.value)
|
|
78
|
+
else:
|
|
79
|
+
self.output += str(arg.name)
|
|
80
|
+
return self.output
|
|
81
|
+
|
|
82
|
+
def onOperator(self, op):
|
|
83
|
+
"""Process an Operator node."""
|
|
84
|
+
# We have to deal with infix operators
|
|
85
|
+
if op.name != op.symbol and op.nin == 2:
|
|
86
|
+
self._onInfix(op)
|
|
87
|
+
return self.output
|
|
88
|
+
|
|
89
|
+
self.output += str(op.name) + "("
|
|
90
|
+
|
|
91
|
+
for idx, literal in enumerate(op.args):
|
|
92
|
+
if idx != 0:
|
|
93
|
+
self.output += ", "
|
|
94
|
+
literal.identify(self)
|
|
95
|
+
|
|
96
|
+
self.output += ")"
|
|
97
|
+
return self.output
|
|
98
|
+
|
|
99
|
+
def onEquation(self, eq):
|
|
100
|
+
"""Process an Equation node."""
|
|
101
|
+
skipthis = (
|
|
102
|
+
self._eqpat is not None and eq.name and self._eqpat.match(eq.name)
|
|
103
|
+
)
|
|
104
|
+
if skipthis:
|
|
105
|
+
self.onArgument(eq)
|
|
106
|
+
else:
|
|
107
|
+
eq.root.identify(self)
|
|
108
|
+
return self.output
|
|
109
|
+
|
|
110
|
+
def _onInfix(self, op):
|
|
111
|
+
"""Process infix operators."""
|
|
112
|
+
self.output += "("
|
|
113
|
+
op.args[0].identify(self)
|
|
114
|
+
self.output += " %s " % op.symbol
|
|
115
|
+
op.args[1].identify(self)
|
|
116
|
+
self.output += ")"
|
|
117
|
+
return
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
# End of file
|