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,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