source: sasview/src/sas/models/BaseComponent.py @ 4ee041f

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 4ee041f was 79492222, checked in by krzywon, 10 years ago

Changed the file and folder names to remove all SANS references.

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