source: sasview/sansmodels/src/sans/models/BaseComponent.py @ 7e4a6ff

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 7e4a6ff was 2f1a0dc, checked in by Jae Cho <jhjcho@…>, 14 years ago

2d input for eval is now qr instead of list (qx,qr), this way we can use numpy.vertorize and it is much faster; So we don't support anisotropic 2D for python models.

  • Property mode set to 100644
File size: 7.9 KB
RevLine 
[ae3ce4e]1#!/usr/bin/env python
[ae60f86]2"""
3    Provide base functionality for all model components
[ae3ce4e]4"""
5
6# imports   
7import copy
[83a25da]8import numpy
[988130c6]9#TO DO: that about a way to make the parameter
10#is self return if it is fittable or not 
[836fe6e]11
[ae3ce4e]12class BaseComponent:
[ae60f86]13    """
14        Basic model component
[ae3ce4e]15       
[ae60f86]16        Since version 0.5.0, basic operations are no longer supported.
[ae3ce4e]17    """
18
19    def __init__(self):
20        """ Initialization"""
21       
22        ## Name of the model
23        self.name   = "BaseComponent"
24       
25        ## Parameters to be accessed by client
26        self.params = {}
[3db3895]27        self.details = {}
[d30fdde]28        ## Dictionary used to store the dispersity/averaging
29        #  parameters of dispersed/averaged parameters.
30        self.dispersion = {}
[5f89fb8]31        # string containing information about the model such as the equation
32        #of the given model, exception or possible use
33        self.description=''
[c9636f7]34        #list of parameter that can be fitted
[988130c6]35        self.fixed= []
[25a608f5]36        ## parameters with orientation
37        self.orientation_params =[]
[c3e4a7fa]38        ## store dispersity reference
39        self._persistency_dict = {}
[ae3ce4e]40           
41    def __str__(self):
[ae60f86]42        """
[ae3ce4e]43            @return: string representation
44        """
45        return self.name
46   
[988130c6]47    def is_fittable(self, par_name):
[c9636f7]48        """
49            Check if a given parameter is fittable or not
50            @param par_name: the parameter name to check
51        """
52        return par_name.lower() in self.fixed
[988130c6]53        #For the future
[836fe6e]54        #return self.params[str(par_name)].is_fittable()
[988130c6]55   
[ae60f86]56    def run(self, x): return NotImplemented
57    def runXY(self, x): return NotImplemented 
[f9bf661]58    def calculate_ER(self): return NotImplemented 
[83a25da]59    def evalDistribution(self, qdist):
60        """
61            Evaluate a distribution of q-values.
62           
[ecc58e72]63            * For 1D, a numpy array is expected as input:
[83a25da]64           
[ecc58e72]65                evalDistribution(q)
66               
67            where q is a numpy array.
68           
69           
[3080527]70            * For 2D, a list of numpy arrays are expected: [qx_prime,qy_prime],
71            where 1D arrays,
[ecc58e72]72           
[3080527]73            qx_prime = [ qx[0], qx[1], qx[2], ....]
74            and
75            qy_prime = [ qy[0], qy[1], qy[2], ....]
[ecc58e72]76           
[2f1a0dc]77            Then get
78            q = numpy.sqrt(qx_prime^2+qy_prime^2)
79           
80            that is a qr in 1D array;
81            q = [q[0], q[1], q[2], ....]
82            Note: Due to 2D speed issue, no anisotropic scattering is supported for python models,
83            thus C-models should have their own evalDistribution methods.
84           
[ecc58e72]85            The method is then called the following way:
86           
[2f1a0dc]87            evalDistribution(q)
88            where q is a numpy array.
[ecc58e72]89           
[3080527]90            @param qdist: ndarray of scalar q-values or list [qx,qy] where qx,qy are 1D ndarrays
[83a25da]91        """
[ecc58e72]92        if qdist.__class__.__name__ == 'list':
93            # Check whether we have a list of ndarrays [qx,qy]
94            if len(qdist)!=2 or \
95                qdist[0].__class__.__name__ != 'ndarray' or \
96                qdist[1].__class__.__name__ != 'ndarray':
97                    raise RuntimeError, "evalDistribution expects a list of 2 ndarrays"
98               
99            # Extract qx and qy for code clarity
100            qx = qdist[0]
101            qy = qdist[1]
102           
[2f1a0dc]103            # calculate q_r component for 2D isotropic
104            q = numpy.sqrt(qx**2+qy**2)
105            # vectorize the model function runXY
106            v_model = numpy.vectorize(self.runXY,otypes=[float])
107            # calculate the scattering
108            iq_array = v_model(q)
109
[ecc58e72]110            return iq_array
111               
112        elif qdist.__class__.__name__ == 'ndarray':
113                # We have a simple 1D distribution of q-values
[2f1a0dc]114                v_model = numpy.vectorize(self.runXY,otypes=[float])
115                iq_array = v_model(qdist)
116
[ecc58e72]117                return iq_array
[83a25da]118           
[ecc58e72]119        else:
120            mesg = "evalDistribution is expecting an ndarray of scalar q-values"
121            mesg += " or a list [qx,qy] where qx,qy are 2D ndarrays."
122            raise RuntimeError, mesg
[2f1a0dc]123       
124   
[83a25da]125   
[ae3ce4e]126    def clone(self):
127        """ Returns a new object identical to the current object """
128        obj = copy.deepcopy(self)
[8809e48]129        return self._clone(obj)
130   
131    def _clone(self, obj):
132        """
133            Internal utility function to copy the internal
134            data members to a fresh copy.
135        """
[ae60f86]136        obj.params     = copy.deepcopy(self.params)
137        obj.details    = copy.deepcopy(self.details)
138        obj.dispersion = copy.deepcopy(self.dispersion)
[138c139]139        obj._persistency_dict = copy.deepcopy( self._persistency_dict)
[ae3ce4e]140        return obj
141
142    def setParam(self, name, value):
[ae60f86]143        """
144            Set the value of a model parameter
[ae3ce4e]145       
146            @param name: name of the parameter
147            @param value: value of the parameter
148        """
[ae60f86]149        # Look for dispersion parameters
150        toks = name.split('.')
151        if len(toks)==2:
152            for item in self.dispersion.keys():
153                if item.lower()==toks[0].lower():
154                    for par in self.dispersion[item]:
155                        if par.lower() == toks[1].lower():
156                            self.dispersion[item][par] = value
157                            return
158        else:
159            # Look for standard parameter
160            for item in self.params.keys():
161                if item.lower()==name.lower():
162                    self.params[item] = value
163                    return
164           
165        raise ValueError, "Model does not contain parameter %s" % name
[ae3ce4e]166       
[ae60f86]167    def getParam(self, name):
168        """
169            Set the value of a model parameter
170
[ae3ce4e]171            @param name: name of the parameter
172        """
[ae60f86]173        # Look for dispersion parameters
[ae3ce4e]174        toks = name.split('.')
[ae60f86]175        if len(toks)==2:
176            for item in self.dispersion.keys():
177                if item.lower()==toks[0].lower():
178                    for par in self.dispersion[item]:
179                        if par.lower() == toks[1].lower():
180                            return self.dispersion[item][par]
181        else:
182            # Look for standard parameter
183            for item in self.params.keys():
184                if item.lower()==name.lower():
185                    return self.params[item]
186           
187        raise ValueError, "Model does not contain parameter %s" % name
188     
[ae3ce4e]189    def getParamList(self):
190        """
[ae60f86]191            Return a list of all available parameters for the model
192        """ 
193        list = self.params.keys()
194        # WARNING: Extending the list with the dispersion parameters
195        list.extend(self.getDispParamList())
196        return list
197   
198    def getDispParamList(self):
199        """
200            Return a list of all available parameters for the model
201        """ 
202        list = []
203       
204        for item in self.dispersion.keys():
205            for p in self.dispersion[item].keys():
206                if p not in ['type']:
207                    list.append('%s.%s' % (item.lower(), p.lower()))
208                   
209        return list
210   
211    # Old-style methods that are no longer used
212    def setParamWithToken(self, name, value, token, member): return NotImplemented
213    def getParamWithToken(self, name, token, member): return NotImplemented
214    def getParamListWithToken(self, token, member): return NotImplemented
215    def __add__(self, other): raise ValueError, "Model operation are no longer supported"
216    def __sub__(self, other): raise ValueError, "Model operation are no longer supported"
217    def __mul__(self, other): raise ValueError, "Model operation are no longer supported"
218    def __div__(self, other): raise ValueError, "Model operation are no longer supported"
219       
Note: See TracBrowser for help on using the repository browser.