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,142 @@
|
|
|
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
|
+
"""Swapper for replacing a Literal in an equation with another Literals."""
|
|
16
|
+
|
|
17
|
+
__all__ = ["Swapper"]
|
|
18
|
+
|
|
19
|
+
from diffpy.srfit.equation.visitors.visitor import Visitor
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Swapper(Visitor):
|
|
23
|
+
"""Swapper for swapping out one literal for another in a literal tree.
|
|
24
|
+
|
|
25
|
+
Note that this cannot swap out a root node of a literal tree. This case
|
|
26
|
+
must be tested for explicitly.
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
newlit -- The literal to be placed into the literal tree.
|
|
30
|
+
oldlit -- The literal to be replaced.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, oldlit, newlit):
|
|
34
|
+
"""Initialize.
|
|
35
|
+
|
|
36
|
+
oldlit -- The literal to be replaced.
|
|
37
|
+
newlit -- The literal to be placed into the literal tree. See the
|
|
38
|
+
class for how the replacement takes place.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
self.newlit = newlit
|
|
42
|
+
self.oldlit = oldlit
|
|
43
|
+
|
|
44
|
+
self._swap = False
|
|
45
|
+
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
def onArgument(self, arg):
|
|
49
|
+
"""Process an Argument node.
|
|
50
|
+
|
|
51
|
+
Tell the parent to swap the old Argument with the replacement
|
|
52
|
+
Literal.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
if arg is self.oldlit:
|
|
56
|
+
self._swap = True
|
|
57
|
+
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
def onOperator(self, op):
|
|
61
|
+
"""Process an Operator node.
|
|
62
|
+
|
|
63
|
+
Tell the parent to swap the old Operator with the replacement
|
|
64
|
+
Literal.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
# Check to see if we need to swap out this Operator. If so, then we
|
|
68
|
+
# don't need to traverse into its arguments.
|
|
69
|
+
if op is self.oldlit:
|
|
70
|
+
self._swap = True
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
# Now traverse into the arguments.
|
|
74
|
+
for literal in op.args:
|
|
75
|
+
literal.identify(self)
|
|
76
|
+
|
|
77
|
+
# If we've been told to swap out a literal, then we must do it in-place
|
|
78
|
+
# because the order of op.args matters.
|
|
79
|
+
if self._swap:
|
|
80
|
+
|
|
81
|
+
oldlit = self.oldlit
|
|
82
|
+
newlit = self.newlit
|
|
83
|
+
|
|
84
|
+
while oldlit in op.args:
|
|
85
|
+
|
|
86
|
+
# Record the index
|
|
87
|
+
idx = op.args.index(oldlit)
|
|
88
|
+
# Remove the literal
|
|
89
|
+
del op.args[idx]
|
|
90
|
+
# Remove op as an observer. A KeyError will be raised if we
|
|
91
|
+
# attempt to remove the same observer more than once, which
|
|
92
|
+
# might happen if the oldlit appears multiple times in op.args.
|
|
93
|
+
try:
|
|
94
|
+
oldlit.removeObserver(op._flush)
|
|
95
|
+
except KeyError:
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
# Validate the new literal. If it fails, we need to restore the
|
|
99
|
+
# old one
|
|
100
|
+
try:
|
|
101
|
+
op._loopCheck(newlit)
|
|
102
|
+
except ValueError:
|
|
103
|
+
# Restore the old literal
|
|
104
|
+
op.args.insert(idx, oldlit)
|
|
105
|
+
oldlit.addObserver(op._flush)
|
|
106
|
+
raise
|
|
107
|
+
|
|
108
|
+
# If we got here, then go on with replacing the literal
|
|
109
|
+
op.args.insert(idx, newlit)
|
|
110
|
+
newlit.addObserver(op._flush)
|
|
111
|
+
op._flush(other=())
|
|
112
|
+
|
|
113
|
+
self._swap = False
|
|
114
|
+
|
|
115
|
+
return
|
|
116
|
+
|
|
117
|
+
def onEquation(self, eq):
|
|
118
|
+
"""Process an Equation node.
|
|
119
|
+
|
|
120
|
+
This looks at the equation itself as well as the root.
|
|
121
|
+
"""
|
|
122
|
+
if eq is self.oldlit:
|
|
123
|
+
self._swap = True
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
# If the newlit is the root, then swap that out and move on.
|
|
127
|
+
if eq.root is self.oldlit:
|
|
128
|
+
eq.setRoot(self.newlit)
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
# Now move into the equation. We have to do a _loopCheck to make sure
|
|
132
|
+
# that we won't have any loops in the equation.
|
|
133
|
+
eq._loopCheck(self.newlit)
|
|
134
|
+
eq.root.identify(self)
|
|
135
|
+
|
|
136
|
+
# Reset the root in case anything changed underneath.
|
|
137
|
+
eq.setRoot(eq.root)
|
|
138
|
+
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# End of file
|
|
@@ -0,0 +1,113 @@
|
|
|
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
|
+
"""Validator visitor for validating a tree of Literals.
|
|
16
|
+
|
|
17
|
+
The Validator walks an equation tree composed of Literals and checks the
|
|
18
|
+
validity of each equation as much as possible without evaluating it. It
|
|
19
|
+
collects errors in a list.
|
|
20
|
+
|
|
21
|
+
The Validator checks that the input count of each Operator is equal to
|
|
22
|
+
the output count of its arguments. It also checks that each object has
|
|
23
|
+
the proper interface.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
__all__ = ["Validator"]
|
|
27
|
+
|
|
28
|
+
from diffpy.srfit.equation.literals.abcs import ArgumentABC, OperatorABC
|
|
29
|
+
from diffpy.srfit.equation.visitors.visitor import Visitor
|
|
30
|
+
|
|
31
|
+
msg = "'%s' does not have the interface required by '%s'"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Validator(Visitor):
|
|
35
|
+
"""Validator error for checking validity of an equation tree.
|
|
36
|
+
|
|
37
|
+
Attributes:
|
|
38
|
+
errors -- List of strings describing errors.
|
|
39
|
+
_nin -- Variable for counting the number input arguments for an
|
|
40
|
+
operator.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self):
|
|
44
|
+
"""Initialize."""
|
|
45
|
+
self.reset()
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
def reset(self):
|
|
49
|
+
"""Click the clicker and reset non-public data."""
|
|
50
|
+
self.errors = []
|
|
51
|
+
self._nin = 0
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
def onArgument(self, arg):
|
|
55
|
+
"""Process an Argument node.
|
|
56
|
+
|
|
57
|
+
The Argument must be an instance of ArgumentABC from
|
|
58
|
+
diffpy.srfit.equation.literals.abcs
|
|
59
|
+
"""
|
|
60
|
+
if not isinstance(arg, ArgumentABC):
|
|
61
|
+
m = msg % (arg, ArgumentABC.__name__)
|
|
62
|
+
self.errors.append(m)
|
|
63
|
+
self._nin = 1
|
|
64
|
+
return self.errors
|
|
65
|
+
|
|
66
|
+
def onOperator(self, op):
|
|
67
|
+
"""Process an Operator node.
|
|
68
|
+
|
|
69
|
+
The Operator must be an instance of OperatorABC from
|
|
70
|
+
diffpy.srfit.equation.literals.abcs
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
if not isinstance(op, OperatorABC):
|
|
74
|
+
m = msg % (op, OperatorABC.__name__)
|
|
75
|
+
self.errors.append(m)
|
|
76
|
+
|
|
77
|
+
# Can only process single-valued functions
|
|
78
|
+
if op.nout != 1:
|
|
79
|
+
m = "'%s' is not single-valued (nout != 1)" % op
|
|
80
|
+
self.errors.append(m)
|
|
81
|
+
# Check name
|
|
82
|
+
if op.name is None:
|
|
83
|
+
m = "'%s' does not have a name" % op
|
|
84
|
+
self.errors.append(m)
|
|
85
|
+
# Check symbol
|
|
86
|
+
if op.symbol is None:
|
|
87
|
+
m = "'%s' does not have a symbol" % op
|
|
88
|
+
self.errors.append(m)
|
|
89
|
+
# Check operation without evaluating it
|
|
90
|
+
if op.operation is None:
|
|
91
|
+
m = "'%s' does not define and operation" % op
|
|
92
|
+
self.errors.append(m)
|
|
93
|
+
|
|
94
|
+
localnin = 0
|
|
95
|
+
for literal in op.args:
|
|
96
|
+
literal.identify(self)
|
|
97
|
+
# Count the nout of the arguments.
|
|
98
|
+
localnin += self._nin
|
|
99
|
+
|
|
100
|
+
# Check the input/output balance
|
|
101
|
+
if op.nin >= 0 and localnin != op.nin:
|
|
102
|
+
m = "'%s' requires %i inputs but receives %i" % (
|
|
103
|
+
op,
|
|
104
|
+
op.nin,
|
|
105
|
+
localnin,
|
|
106
|
+
)
|
|
107
|
+
self.errors.append(m)
|
|
108
|
+
|
|
109
|
+
self._nin = op.nout
|
|
110
|
+
return self.errors
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# End of file
|
|
@@ -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
|
+
"""Base visitor class.
|
|
16
|
+
|
|
17
|
+
Visitors work with Literal trees to perform a specified action. They are
|
|
18
|
+
designed according to the visitor pattern (
|
|
19
|
+
http://en.wikipedia.org/wiki/Visitor_pattern).
|
|
20
|
+
|
|
21
|
+
Visitors work with the following Literal classes
|
|
22
|
+
(diffpy.srfit.equation.literals):
|
|
23
|
+
Argument
|
|
24
|
+
Operator
|
|
25
|
+
|
|
26
|
+
See the Visitor class for the required methods that each Visitor must overload.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
__all__ = ["Visitor"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Visitor(object):
|
|
33
|
+
"""Abstract class for all visitors to a Literal tree.
|
|
34
|
+
|
|
35
|
+
See implemented visitors for examples of use.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def onArgument(self, arg):
|
|
39
|
+
"""Process an Argument node."""
|
|
40
|
+
return self._abstract("onArgument")
|
|
41
|
+
|
|
42
|
+
def onOperator(self, op):
|
|
43
|
+
"""Process an Operator node."""
|
|
44
|
+
return self._abstract("onOperator")
|
|
45
|
+
|
|
46
|
+
def onEquation(self, eq):
|
|
47
|
+
"""Process an Equation node.
|
|
48
|
+
|
|
49
|
+
Equations are specialized Operators. They don't need to be
|
|
50
|
+
specifically supported by a Visitor.
|
|
51
|
+
"""
|
|
52
|
+
return self.onOperator(eq)
|
|
53
|
+
|
|
54
|
+
# throw an exception
|
|
55
|
+
def _abstract(self, method):
|
|
56
|
+
raise NotImplementedError(
|
|
57
|
+
"class '%s' should override method '%s'"
|
|
58
|
+
% (self.__class__.__name__, method)
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# End of file
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
##############################################################################
|
|
3
|
+
#
|
|
4
|
+
# diffpy.srfit Complex Modeling Initiative
|
|
5
|
+
# (c) 2016 Brookhaven Science Associates,
|
|
6
|
+
# Brookhaven National Laboratory.
|
|
7
|
+
# All rights reserved.
|
|
8
|
+
#
|
|
9
|
+
# File coded by: Pavol Juhas
|
|
10
|
+
#
|
|
11
|
+
# See AUTHORS.txt for a list of people who contributed.
|
|
12
|
+
# See LICENSE.txt for license information.
|
|
13
|
+
#
|
|
14
|
+
##############################################################################
|
|
15
|
+
"""
|
|
16
|
+
Exceptions used for SrFit - specific errors.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SrFitError(Exception):
|
|
21
|
+
"""Generic error in SrFit expressions or recipe."""
|
|
22
|
+
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ParseError(Exception):
|
|
27
|
+
"""Exception used by ProfileParsers."""
|
|
28
|
+
|
|
29
|
+
pass
|
|
@@ -0,0 +1,53 @@
|
|
|
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
|
+
"""The base fitting classes for diffpy.srfit.
|
|
16
|
+
|
|
17
|
+
This package contains modules and subpackages that are used to define a
|
|
18
|
+
fit problem in SrFit. Unaltered, these classes will help set up a fit
|
|
19
|
+
problem that can be optimized within a fitting framework or with a
|
|
20
|
+
standalone optimizer. They provide the basic framework for defining a
|
|
21
|
+
forward calculator, and from that defining a fit problem with data,
|
|
22
|
+
constraints and restraints. The classes involved in this collaboration
|
|
23
|
+
can be tied to a fitting framework at various levels through
|
|
24
|
+
inheritance. One can create a fitting problem using the FitContribution,
|
|
25
|
+
Profile and FitRecipe classes.
|
|
26
|
+
|
|
27
|
+
Various code and design taken from Paul Kienzle's PARK package.
|
|
28
|
+
http://www.reflectometry.org/danse/park.html
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"Calculator",
|
|
33
|
+
"FitContribution",
|
|
34
|
+
"FitHook",
|
|
35
|
+
"FitRecipe",
|
|
36
|
+
"FitResults",
|
|
37
|
+
"initializeRecipe",
|
|
38
|
+
"PlotFitHook",
|
|
39
|
+
"Profile",
|
|
40
|
+
"ProfileGenerator",
|
|
41
|
+
"SimpleRecipe",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
from diffpy.srfit.fitbase.calculator import Calculator
|
|
45
|
+
from diffpy.srfit.fitbase.fitcontribution import FitContribution
|
|
46
|
+
from diffpy.srfit.fitbase.fithook import FitHook, PlotFitHook
|
|
47
|
+
from diffpy.srfit.fitbase.fitrecipe import FitRecipe
|
|
48
|
+
from diffpy.srfit.fitbase.fitresults import FitResults, initializeRecipe
|
|
49
|
+
from diffpy.srfit.fitbase.profile import Profile
|
|
50
|
+
from diffpy.srfit.fitbase.profilegenerator import ProfileGenerator
|
|
51
|
+
from diffpy.srfit.fitbase.simplerecipe import SimpleRecipe
|
|
52
|
+
|
|
53
|
+
# End of file
|
|
@@ -0,0 +1,110 @@
|
|
|
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
|
+
"""The Calculator for Parameter-aware functions.
|
|
16
|
+
|
|
17
|
+
Calculator is a functor class for producing a signal from embedded
|
|
18
|
+
Parameters. Calculators can store Parameters and ParameterSets,
|
|
19
|
+
Constraints and Restraints. Also, the __call__ function can be
|
|
20
|
+
overloaded to accept external arguments. Calculators are used to wrap
|
|
21
|
+
registered functions so that the function's Parameters are contained in
|
|
22
|
+
an object specific to the function. A custom Calculator can be added to
|
|
23
|
+
another RecipeOrganizer with the 'registerCalculator' method.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
__all__ = ["Calculator"]
|
|
27
|
+
|
|
28
|
+
from diffpy.srfit.equation.literals.operators import Operator
|
|
29
|
+
from diffpy.srfit.fitbase.parameterset import ParameterSet
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Calculator(Operator, ParameterSet):
|
|
33
|
+
"""Base class for calculators.
|
|
34
|
+
|
|
35
|
+
A Calculator organizes Parameters and has a __call__ method that can
|
|
36
|
+
calculate a generic signal.
|
|
37
|
+
|
|
38
|
+
Attributes
|
|
39
|
+
name -- A name for this organizer.
|
|
40
|
+
meta -- A dictionary of metadata needed by the calculator.
|
|
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
|
+
_parameters -- A managed OrderedDict of contained Parameters.
|
|
45
|
+
_parsets -- A managed dictionary of ParameterSets.
|
|
46
|
+
_restraints -- A set of Restraints. Restraints can be added using the
|
|
47
|
+
'restrain' or 'confine' methods.
|
|
48
|
+
_eqfactory -- A diffpy.srfit.equation.builder.EquationFactory
|
|
49
|
+
instance that is used create Equations from string.
|
|
50
|
+
|
|
51
|
+
Operator Attributes
|
|
52
|
+
args -- List of Literal arguments
|
|
53
|
+
nin -- Number of inputs (<1 means this is variable)
|
|
54
|
+
nout -- Number of outputs (1)
|
|
55
|
+
operation -- Function that performs the operation, self.__call__
|
|
56
|
+
symbol -- Same as name
|
|
57
|
+
_value -- The value of the Operator.
|
|
58
|
+
value -- Property for 'getValue'.
|
|
59
|
+
|
|
60
|
+
Properties
|
|
61
|
+
names -- Variable names (read only). See getNames.
|
|
62
|
+
values -- Variable values (read only). See getValues.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
# define abstract attributes from the Operator base.
|
|
66
|
+
|
|
67
|
+
nin = -1
|
|
68
|
+
nout = 1
|
|
69
|
+
|
|
70
|
+
def __init__(self, name):
|
|
71
|
+
ParameterSet.__init__(self, name)
|
|
72
|
+
self.meta = {}
|
|
73
|
+
|
|
74
|
+
# Initialize Operator attributes
|
|
75
|
+
Operator.__init__(self, name)
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def symbol(self):
|
|
80
|
+
return self.name
|
|
81
|
+
|
|
82
|
+
# Overload me!
|
|
83
|
+
def __call__(self, *args):
|
|
84
|
+
"""Calculate something.
|
|
85
|
+
|
|
86
|
+
This method must be overloaded. When overloading, you should
|
|
87
|
+
specify the arguments explicitly, otherwise the parameters must
|
|
88
|
+
be specified when adding the Calculator to a RecipeOrganizer.
|
|
89
|
+
"""
|
|
90
|
+
return 0
|
|
91
|
+
|
|
92
|
+
def operation(self, *args):
|
|
93
|
+
self._value = self.__call__(*args)
|
|
94
|
+
return self._value
|
|
95
|
+
|
|
96
|
+
def _validate(self):
|
|
97
|
+
"""Validate my state.
|
|
98
|
+
|
|
99
|
+
This performs ParameterSet validations. This does not validate
|
|
100
|
+
the operation, since this could be costly. The operation should
|
|
101
|
+
be validated with a containing equation.
|
|
102
|
+
|
|
103
|
+
Raises AttributeError if validation fails.
|
|
104
|
+
"""
|
|
105
|
+
ParameterSet._validate(self)
|
|
106
|
+
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# End class Calculator
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
"""Configurable class.
|
|
16
|
+
|
|
17
|
+
A Configurable has state of which a FitRecipe must be aware.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
__all__ = ["Configurable"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Configurable(object):
|
|
24
|
+
"""Configurable class.
|
|
25
|
+
|
|
26
|
+
A Configurable has state of which a FitRecipe must be aware.
|
|
27
|
+
|
|
28
|
+
Attributes
|
|
29
|
+
_configobjs -- Set of Configureables in a hierarchy or instances.
|
|
30
|
+
Messages get passed up the hierarchy to a FitReciple
|
|
31
|
+
via these objects.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self):
|
|
35
|
+
self._configobjs = set()
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
def _updateConfiguration(self):
|
|
39
|
+
"""Notify Configurables in hierarchy of configuration change."""
|
|
40
|
+
for obj in self._configobjs:
|
|
41
|
+
obj._updateConfiguration()
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
def _storeConfigurable(self, obj):
|
|
45
|
+
"""Store a Configurable.
|
|
46
|
+
|
|
47
|
+
The passed obj is only stored if it is a a Configurable,
|
|
48
|
+
otherwise this method quietly exits.
|
|
49
|
+
"""
|
|
50
|
+
if isinstance(obj, Configurable):
|
|
51
|
+
self._configobjs.add(obj)
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# End class Configurable
|
|
56
|
+
|
|
57
|
+
# End of file
|
|
@@ -0,0 +1,117 @@
|
|
|
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
|
+
"""Constraint class.
|
|
16
|
+
|
|
17
|
+
Constraints are used by a FitRecipe (and other RecipeOrganizers) to
|
|
18
|
+
organize constraint equations. They store a Parameter object and an
|
|
19
|
+
Equation object that is used to compute its value. The
|
|
20
|
+
Constraint.constrain method is used to create this association.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
__all__ = ["Constraint"]
|
|
24
|
+
|
|
25
|
+
from diffpy.srfit.exceptions import SrFitError
|
|
26
|
+
from diffpy.srfit.fitbase.validatable import Validatable
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Constraint(Validatable):
|
|
30
|
+
"""Constraint class.
|
|
31
|
+
|
|
32
|
+
Constraints are designed to be stored in only one place. (The holder of the
|
|
33
|
+
constraint owns it).
|
|
34
|
+
|
|
35
|
+
Attributes
|
|
36
|
+
par -- A Parameter that is the subject of the constraint.
|
|
37
|
+
eq -- An equation whose evaluation is used to set the value of the
|
|
38
|
+
constraint.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self):
|
|
42
|
+
"""Initialization."""
|
|
43
|
+
self.par = None
|
|
44
|
+
self.eq = None
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
def constrain(self, par, eq):
|
|
48
|
+
"""Constrain a Parameter according to an Equation.
|
|
49
|
+
|
|
50
|
+
The parameter will be set constant once it is constrained. This
|
|
51
|
+
will keep it from being constrained multiple times.
|
|
52
|
+
|
|
53
|
+
Raises a ValueError if par is const.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
if par.const:
|
|
57
|
+
raise ValueError("The parameter '%s' is constant" % par)
|
|
58
|
+
|
|
59
|
+
if par.constrained:
|
|
60
|
+
raise ValueError("The parameter '%s' is already constrained" % par)
|
|
61
|
+
|
|
62
|
+
par.constrained = True
|
|
63
|
+
|
|
64
|
+
self.par = par
|
|
65
|
+
self.eq = eq
|
|
66
|
+
self.update()
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
def unconstrain(self):
|
|
70
|
+
"""Clear the constraint."""
|
|
71
|
+
self.par.constrained = False
|
|
72
|
+
self.par = None
|
|
73
|
+
self.eq = None
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
def update(self):
|
|
77
|
+
"""Update the parameter according to the equation."""
|
|
78
|
+
# This will be evaluated quickly thanks to the Equation class.
|
|
79
|
+
val = self.eq()
|
|
80
|
+
# This will only change the Parameter if val is different from the
|
|
81
|
+
# currently stored value.
|
|
82
|
+
self.par.setValue(val)
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
def _validate(self):
|
|
86
|
+
"""Validate my state.
|
|
87
|
+
|
|
88
|
+
This validates that par is not None. This validates eq.
|
|
89
|
+
|
|
90
|
+
Raises SrFitError if validation fails.
|
|
91
|
+
"""
|
|
92
|
+
if self.par is None:
|
|
93
|
+
raise SrFitError("par is None")
|
|
94
|
+
if self.eq is None:
|
|
95
|
+
raise SrFitError("eq is None")
|
|
96
|
+
self.par._validate()
|
|
97
|
+
from diffpy.srfit.equation.visitors import validate
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
validate(self.eq)
|
|
101
|
+
except ValueError as e:
|
|
102
|
+
raise SrFitError(e)
|
|
103
|
+
|
|
104
|
+
# Try to get the value of eq.
|
|
105
|
+
try:
|
|
106
|
+
val = self.eq()
|
|
107
|
+
self.par.setValue(val)
|
|
108
|
+
except TypeError:
|
|
109
|
+
raise SrFitError("eq cannot be evaluated")
|
|
110
|
+
finally:
|
|
111
|
+
if val is None:
|
|
112
|
+
raise SrFitError("eq evaluates to None")
|
|
113
|
+
|
|
114
|
+
return
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# End of file
|