source: sasview/sansmodels/src/sans/models/BaseComponent.py @ 8665e11

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 8665e11 was 7fdb332, checked in by Jae Cho <jhjcho@…>, 12 years ago

pylint cleanups

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