source: sasview/sansmodels/src/sans/models/BaseComponent.py @ 1b28ff5

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 1b28ff5 was 318b5bbb, checked in by Jae Cho <jhjcho@…>, 12 years ago

Added polarization and magnetic stuffs

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