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

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 cb4ef58 was cb4ef58, checked in by Paul Kienzle <pkienzle@…>, 4 years ago

remove references to internal _model_info attribute from sasview

  • Property mode set to 100644
File size: 8.8 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        self.is_multiplicity_model = False
53        self.is_structure_factor = False
54        self.is_form_factor = False
55
56    def __str__(self):
57        """
58        :return: string representatio
59        """
60        return self.name
61
62    def is_fittable(self, par_name):
63        """
64        Check if a given parameter is fittable or not
65
66        :param par_name: the parameter name to check
67
68        """
69        return par_name.lower() in self.fixed
70        #For the future
71        #return self.params[str(par_name)].is_fittable()
72
73    def run(self, x):
74        """
75        run 1d
76        """
77        return NotImplemented
78
79    def runXY(self, x):
80        """
81        run 2d
82        """
83        return NotImplemented
84
85    def calculate_ER(self):
86        """
87        Calculate effective radius
88        """
89        return NotImplemented
90
91    def calculate_VR(self):
92        """
93        Calculate volume fraction ratio
94        """
95        return NotImplemented
96
97    def evalDistribution(self, qdist):
98        """
99        Evaluate a distribution of q-values.
100
101        * For 1D, a numpy array is expected as input: ::
102
103            evalDistribution(q)
104
105          where q is a numpy array.
106
107
108        * For 2D, a list of numpy arrays are expected: [qx_prime,qy_prime],
109          where 1D arrays, ::
110
111              qx_prime = [ qx[0], qx[1], qx[2], ....]
112
113          and ::
114
115              qy_prime = [ qy[0], qy[1], qy[2], ....]
116
117        Then get ::
118
119            q = numpy.sqrt(qx_prime^2+qy_prime^2)
120
121        that is a qr in 1D array; ::
122
123            q = [q[0], q[1], q[2], ....]
124
125        .. note:: Due to 2D speed issue, no anisotropic scattering
126                  is supported for python models, thus C-models should have
127                  their own evalDistribution methods.
128
129        The method is then called the following way: ::
130
131            evalDistribution(q)
132
133        where q is a numpy array.
134
135        :param qdist: ndarray of scalar q-values or list [qx,qy] where qx,qy are 1D ndarrays
136        """
137        if qdist.__class__.__name__ == 'list':
138            # Check whether we have a list of ndarrays [qx,qy]
139            if len(qdist)!=2 or \
140                qdist[0].__class__.__name__ != 'ndarray' or \
141                qdist[1].__class__.__name__ != 'ndarray':
142                msg = "evalDistribution expects a list of 2 ndarrays"
143                raise RuntimeError, msg
144
145            # Extract qx and qy for code clarity
146            qx = qdist[0]
147            qy = qdist[1]
148
149            # calculate q_r component for 2D isotropic
150            q = numpy.sqrt(qx**2+qy**2)
151            # vectorize the model function runXY
152            v_model = numpy.vectorize(self.runXY, otypes=[float])
153            # calculate the scattering
154            iq_array = v_model(q)
155
156            return iq_array
157
158        elif qdist.__class__.__name__ == 'ndarray':
159            # We have a simple 1D distribution of q-values
160            v_model = numpy.vectorize(self.runXY, otypes=[float])
161            iq_array = v_model(qdist)
162            return iq_array
163
164        else:
165            mesg = "evalDistribution is expecting an ndarray of scalar q-values"
166            mesg += " or a list [qx,qy] where qx,qy are 2D ndarrays."
167            raise RuntimeError, mesg
168
169
170
171    def clone(self):
172        """ Returns a new object identical to the current object """
173        obj = copy.deepcopy(self)
174        return self._clone(obj)
175
176    def _clone(self, obj):
177        """
178        Internal utility function to copy the internal
179        data members to a fresh copy.
180        """
181        obj.params     = copy.deepcopy(self.params)
182        obj.details    = copy.deepcopy(self.details)
183        obj.dispersion = copy.deepcopy(self.dispersion)
184        obj._persistency_dict = copy.deepcopy( self._persistency_dict)
185        return obj
186
187    def set_dispersion(self, parameter, dispersion):
188        """
189        model dispersions
190        """
191        ##Not Implemented
192        return None
193
194    def getProfile(self):
195        """
196        Get SLD profile
197
198        : return: (z, beta) where z is a list of depth of the transition points
199                beta is a list of the corresponding SLD values
200        """
201        #Not Implemented
202        return None, None
203
204    def setParam(self, name, value):
205        """
206        Set the value of a model parameter
207
208        :param name: name of the parameter
209        :param value: value of the parameter
210
211        """
212        # Look for dispersion parameters
213        toks = name.split('.')
214        if len(toks)==2:
215            for item in self.dispersion.keys():
216                if item.lower()==toks[0].lower():
217                    for par in self.dispersion[item]:
218                        if par.lower() == toks[1].lower():
219                            self.dispersion[item][par] = value
220                            return
221        else:
222            # Look for standard parameter
223            for item in self.params.keys():
224                if item.lower()==name.lower():
225                    self.params[item] = value
226                    return
227
228        raise ValueError, "Model does not contain parameter %s" % name
229
230    def getParam(self, name):
231        """
232        Set the value of a model parameter
233        :param name: name of the parameter
234
235        """
236        # Look for dispersion parameters
237        toks = name.split('.')
238        if len(toks)==2:
239            for item in self.dispersion.keys():
240                if item.lower()==toks[0].lower():
241                    for par in self.dispersion[item]:
242                        if par.lower() == toks[1].lower():
243                            return self.dispersion[item][par]
244        else:
245            # Look for standard parameter
246            for item in self.params.keys():
247                if item.lower()==name.lower():
248                    return self.params[item]
249
250        raise ValueError, "Model does not contain parameter %s" % name
251
252    def getParamList(self):
253        """
254        Return a list of all available parameters for the model
255        """
256        list = self.params.keys()
257        # WARNING: Extending the list with the dispersion parameters
258        list.extend(self.getDispParamList())
259        return list
260
261    def getDispParamList(self):
262        """
263        Return a list of all available parameters for the model
264        """
265        list = []
266
267        for item in self.dispersion.keys():
268            for p in self.dispersion[item].keys():
269                if p not in ['type']:
270                    list.append('%s.%s' % (item.lower(), p.lower()))
271
272        return list
273
274    # Old-style methods that are no longer used
275    def setParamWithToken(self, name, value, token, member):
276        """
277        set Param With Token
278        """
279        return NotImplemented
280    def getParamWithToken(self, name, token, member):
281        """
282        get Param With Token
283        """
284        return NotImplemented
285
286    def getParamListWithToken(self, token, member):
287        """
288        get Param List With Token
289        """
290        return NotImplemented
291    def __add__(self, other):
292        """
293        add
294        """
295        raise ValueError, "Model operation are no longer supported"
296    def __sub__(self, other):
297        """
298        sub
299        """
300        raise ValueError, "Model operation are no longer supported"
301    def __mul__(self, other):
302        """
303        mul
304        """
305        raise ValueError, "Model operation are no longer supported"
306    def __div__(self, other):
307        """
308        div
309        """
310        raise ValueError, "Model operation are no longer supported"
Note: See TracBrowser for help on using the repository browser.