source: sasview/src/sas/sascalc/calculator/BaseComponent.py @ 53aa66d

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 53aa66d was 53aa66d, checked in by butler, 8 years ago

This should fix problems Steve King saw in doc building (point 1 and 2
in ticket 318). relates #318

  • Property mode set to 100644
File size: 8.7 KB
Line 
1#!/usr/bin/env python
2
3"""
4Provide base functionality for all model components
5"""
6
7# imports
8import copy
9import numpy
10#TO DO: that about a way to make the parameter
11#is self return if it is fittable or not
12
13class BaseComponent:
14    """
15    Basic model component
16
17    Since version 0.5.0, basic operations are no longer supported.
18    """
19
20    def __init__(self):
21        """ Initialization"""
22
23        ## Name of the model
24        self.name = "BaseComponent"
25
26        ## Parameters to be accessed by client
27        self.params = {}
28        self.details = {}
29        ## Dictionary used to store the dispersity/averaging
30        #  parameters of dispersed/averaged parameters.
31        self.dispersion = {}
32        # string containing information about the model such as the equation
33        #of the given model, exception or possible use
34        self.description = ''
35        #list of parameter that can be fitted
36        self.fixed = []
37        #list of non-fittable parameter
38        self.non_fittable = []
39        ## parameters with orientation
40        self.orientation_params = []
41        ## magnetic parameters
42        self.magnetic_params = []
43        ## store dispersity reference
44        self._persistency_dict = {}
45        ## independent parameter name and unit [string]
46        self.input_name = "Q"
47        self.input_unit = "A^{-1}"
48        ## output name and unit  [string]
49        self.output_name = "Intensity"
50        self.output_unit = "cm^{-1}"
51
52    def __str__(self):
53        """
54        :return: string representatio
55        """
56        return self.name
57
58    def is_fittable(self, par_name):
59        """
60        Check if a given parameter is fittable or not
61
62        :param par_name: the parameter name to check
63
64        """
65        return par_name.lower() in self.fixed
66        #For the future
67        #return self.params[str(par_name)].is_fittable()
68
69    def run(self, x):
70        """
71        run 1d
72        """
73        return NotImplemented
74
75    def runXY(self, x):
76        """
77        run 2d
78        """
79        return NotImplemented
80
81    def calculate_ER(self):
82        """
83        Calculate effective radius
84        """
85        return NotImplemented
86
87    def calculate_VR(self):
88        """
89        Calculate volume fraction ratio
90        """
91        return NotImplemented
92
93    def evalDistribution(self, qdist):
94        """
95        Evaluate a distribution of q-values.
96
97        * For 1D, a numpy array is expected as input: ::
98
99            evalDistribution(q)
100
101          where q is a numpy array.
102
103
104        * For 2D, a list of numpy arrays are expected: [qx_prime,qy_prime],
105          where 1D arrays, ::
106
107              qx_prime = [ qx[0], qx[1], qx[2], ....]
108
109          and ::
110
111              qy_prime = [ qy[0], qy[1], qy[2], ....]
112
113        Then get ::
114
115            q = numpy.sqrt(qx_prime^2+qy_prime^2)
116
117        that is a qr in 1D array; ::
118
119            q = [q[0], q[1], q[2], ....]
120
121        .. note:: Due to 2D speed issue, no anisotropic scattering
122                  is supported for python models, thus C-models should have
123                  their own evalDistribution methods.
124
125        The method is then called the following way: ::
126
127            evalDistribution(q)
128
129        where q is a numpy array.
130
131        :param qdist: ndarray of scalar q-values or list [qx,qy] where qx,qy are 1D ndarrays
132        """
133        if qdist.__class__.__name__ == 'list':
134            # Check whether we have a list of ndarrays [qx,qy]
135            if len(qdist)!=2 or \
136                qdist[0].__class__.__name__ != 'ndarray' or \
137                qdist[1].__class__.__name__ != 'ndarray':
138                msg = "evalDistribution expects a list of 2 ndarrays"
139                raise RuntimeError, msg
140
141            # Extract qx and qy for code clarity
142            qx = qdist[0]
143            qy = qdist[1]
144
145            # calculate q_r component for 2D isotropic
146            q = numpy.sqrt(qx**2+qy**2)
147            # vectorize the model function runXY
148            v_model = numpy.vectorize(self.runXY, otypes=[float])
149            # calculate the scattering
150            iq_array = v_model(q)
151
152            return iq_array
153
154        elif qdist.__class__.__name__ == 'ndarray':
155            # We have a simple 1D distribution of q-values
156            v_model = numpy.vectorize(self.runXY, otypes=[float])
157            iq_array = v_model(qdist)
158            return iq_array
159
160        else:
161            mesg = "evalDistribution is expecting an ndarray of scalar q-values"
162            mesg += " or a list [qx,qy] where qx,qy are 2D ndarrays."
163            raise RuntimeError, mesg
164
165
166
167    def clone(self):
168        """ Returns a new object identical to the current object """
169        obj = copy.deepcopy(self)
170        return self._clone(obj)
171
172    def _clone(self, obj):
173        """
174        Internal utility function to copy the internal
175        data members to a fresh copy.
176        """
177        obj.params     = copy.deepcopy(self.params)
178        obj.details    = copy.deepcopy(self.details)
179        obj.dispersion = copy.deepcopy(self.dispersion)
180        obj._persistency_dict = copy.deepcopy( self._persistency_dict)
181        return obj
182
183    def set_dispersion(self, parameter, dispersion):
184        """
185        model dispersions
186        """
187        ##Not Implemented
188        return None
189
190    def getProfile(self):
191        """
192        Get SLD profile
193
194        : return: (z, beta) where z is a list of depth of the transition points
195                beta is a list of the corresponding SLD values
196        """
197        #Not Implemented
198        return None, None
199
200    def setParam(self, name, value):
201        """
202        Set the value of a model parameter
203
204        :param name: name of the parameter
205        :param value: value of the parameter
206
207        """
208        # Look for dispersion parameters
209        toks = name.split('.')
210        if len(toks)==2:
211            for item in self.dispersion.keys():
212                if item.lower()==toks[0].lower():
213                    for par in self.dispersion[item]:
214                        if par.lower() == toks[1].lower():
215                            self.dispersion[item][par] = value
216                            return
217        else:
218            # Look for standard parameter
219            for item in self.params.keys():
220                if item.lower()==name.lower():
221                    self.params[item] = value
222                    return
223
224        raise ValueError, "Model does not contain parameter %s" % name
225
226    def getParam(self, name):
227        """
228        Set the value of a model parameter
229        :param name: name of the parameter
230
231        """
232        # Look for dispersion parameters
233        toks = name.split('.')
234        if len(toks)==2:
235            for item in self.dispersion.keys():
236                if item.lower()==toks[0].lower():
237                    for par in self.dispersion[item]:
238                        if par.lower() == toks[1].lower():
239                            return self.dispersion[item][par]
240        else:
241            # Look for standard parameter
242            for item in self.params.keys():
243                if item.lower()==name.lower():
244                    return self.params[item]
245
246        raise ValueError, "Model does not contain parameter %s" % name
247
248    def getParamList(self):
249        """
250        Return a list of all available parameters for the model
251        """
252        list = self.params.keys()
253        # WARNING: Extending the list with the dispersion parameters
254        list.extend(self.getDispParamList())
255        return list
256
257    def getDispParamList(self):
258        """
259        Return a list of all available parameters for the model
260        """
261        list = []
262
263        for item in self.dispersion.keys():
264            for p in self.dispersion[item].keys():
265                if p not in ['type']:
266                    list.append('%s.%s' % (item.lower(), p.lower()))
267
268        return list
269
270    # Old-style methods that are no longer used
271    def setParamWithToken(self, name, value, token, member):
272        """
273        set Param With Token
274        """
275        return NotImplemented
276    def getParamWithToken(self, name, token, member):
277        """
278        get Param With Token
279        """
280        return NotImplemented
281
282    def getParamListWithToken(self, token, member):
283        """
284        get Param List With Token
285        """
286        return NotImplemented
287    def __add__(self, other):
288        """
289        add
290        """
291        raise ValueError, "Model operation are no longer supported"
292    def __sub__(self, other):
293        """
294        sub
295        """
296        raise ValueError, "Model operation are no longer supported"
297    def __mul__(self, other):
298        """
299        mul
300        """
301        raise ValueError, "Model operation are no longer supported"
302    def __div__(self, other):
303        """
304        div
305        """
306        raise ValueError, "Model operation are no longer supported"
Note: See TracBrowser for help on using the repository browser.