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

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 a2cb1f9 was 35aface, checked in by Jae Cho <jhjcho@…>, 14 years ago

addede new models and attr. non_fittable

  • Property mode set to 100644
File size: 7.9 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        ## store dispersity reference
42        self._persistency_dict = {}
43           
44    def __str__(self):
45        """
46        :return: string representatio
47
48        """
49        return self.name
50   
51    def is_fittable(self, par_name):
52        """
53        Check if a given parameter is fittable or not
54       
55        :param par_name: the parameter name to check
56       
57        """
58        return par_name.lower() in self.fixed
59        #For the future
60        #return self.params[str(par_name)].is_fittable()
61   
62    def run(self, x): return NotImplemented
63    def runXY(self, x): return NotImplemented 
64    def calculate_ER(self): return NotImplemented 
65    def evalDistribution(self, qdist):
66        """
67        Evaluate a distribution of q-values.
68       
69        * For 1D, a numpy array is expected as input:
70       
71            evalDistribution(q)
72           
73        where q is a numpy array.
74       
75       
76        * For 2D, a list of numpy arrays are expected: [qx_prime,qy_prime],
77          where 1D arrays,
78       
79        qx_prime = [ qx[0], qx[1], qx[2], ....]
80        and
81        qy_prime = [ qy[0], qy[1], qy[2], ....]
82       
83        Then get
84        q = numpy.sqrt(qx_prime^2+qy_prime^2)
85       
86        that is a qr in 1D array;
87        q = [q[0], q[1], q[2], ....]
88       
89        :Note: Due to 2D speed issue, no anisotropic scattering
90            is supported for python models, thus C-models should have
91             their own evalDistribution methods.
92       
93        The method is then called the following way:
94       
95        evalDistribution(q)
96        where q is a numpy array.
97       
98        :param qdist: ndarray of scalar q-values or list [qx,qy]
99                    where qx,qy are 1D ndarrays
100       
101        """
102        if qdist.__class__.__name__ == 'list':
103            # Check whether we have a list of ndarrays [qx,qy]
104            if len(qdist)!=2 or \
105                qdist[0].__class__.__name__ != 'ndarray' or \
106                qdist[1].__class__.__name__ != 'ndarray':
107                    raise RuntimeError, "evalDistribution expects a list of 2 ndarrays"
108               
109            # Extract qx and qy for code clarity
110            qx = qdist[0]
111            qy = qdist[1]
112           
113            # calculate q_r component for 2D isotropic
114            q = numpy.sqrt(qx**2+qy**2)
115            # vectorize the model function runXY
116            v_model = numpy.vectorize(self.runXY,otypes=[float])
117            # calculate the scattering
118            iq_array = v_model(q)
119
120            return iq_array
121               
122        elif qdist.__class__.__name__ == 'ndarray':
123                # We have a simple 1D distribution of q-values
124                v_model = numpy.vectorize(self.runXY,otypes=[float])
125                iq_array = v_model(qdist)
126
127                return iq_array
128           
129        else:
130            mesg = "evalDistribution is expecting an ndarray of scalar q-values"
131            mesg += " or a list [qx,qy] where qx,qy are 2D ndarrays."
132            raise RuntimeError, mesg
133       
134   
135   
136    def clone(self):
137        """ Returns a new object identical to the current object """
138        obj = copy.deepcopy(self)
139        return self._clone(obj)
140   
141    def _clone(self, obj):
142        """
143        Internal utility function to copy the internal
144        data members to a fresh copy.
145        """
146        obj.params     = copy.deepcopy(self.params)
147        obj.details    = copy.deepcopy(self.details)
148        obj.dispersion = copy.deepcopy(self.dispersion)
149        obj._persistency_dict = copy.deepcopy( self._persistency_dict)
150        return obj
151
152    def setParam(self, name, value):
153        """
154        Set the value of a model parameter
155   
156        :param name: name of the parameter
157        :param value: value of the parameter
158       
159        """
160        # Look for dispersion parameters
161        toks = name.split('.')
162        if len(toks)==2:
163            for item in self.dispersion.keys():
164                if item.lower()==toks[0].lower():
165                    for par in self.dispersion[item]:
166                        if par.lower() == toks[1].lower():
167                            self.dispersion[item][par] = value
168                            return
169        else:
170            # Look for standard parameter
171            for item in self.params.keys():
172                if item.lower()==name.lower():
173                    self.params[item] = value
174                    return
175           
176        raise ValueError, "Model does not contain parameter %s" % name
177       
178    def getParam(self, name):
179        """
180        Set the value of a model parameter
181
182        :param name: name of the parameter
183       
184        """
185        # Look for dispersion parameters
186        toks = name.split('.')
187        if len(toks)==2:
188            for item in self.dispersion.keys():
189                if item.lower()==toks[0].lower():
190                    for par in self.dispersion[item]:
191                        if par.lower() == toks[1].lower():
192                            return self.dispersion[item][par]
193        else:
194            # Look for standard parameter
195            for item in self.params.keys():
196                if item.lower()==name.lower():
197                    return self.params[item]
198           
199        raise ValueError, "Model does not contain parameter %s" % name
200     
201    def getParamList(self):
202        """
203        Return a list of all available parameters for the model
204        """ 
205        list = self.params.keys()
206        # WARNING: Extending the list with the dispersion parameters
207        list.extend(self.getDispParamList())
208        return list
209   
210    def getDispParamList(self):
211        """
212        Return a list of all available parameters for the model
213        """ 
214        list = []
215       
216        for item in self.dispersion.keys():
217            for p in self.dispersion[item].keys():
218                if p not in ['type']:
219                    list.append('%s.%s' % (item.lower(), p.lower()))
220                   
221        return list
222   
223    # Old-style methods that are no longer used
224    def setParamWithToken(self, name, value, token, member): return NotImplemented
225    def getParamWithToken(self, name, token, member): return NotImplemented
226    def getParamListWithToken(self, token, member): return NotImplemented
227    def __add__(self, other): raise ValueError, "Model operation are no longer supported"
228    def __sub__(self, other): raise ValueError, "Model operation are no longer supported"
229    def __mul__(self, other): raise ValueError, "Model operation are no longer supported"
230    def __div__(self, other): raise ValueError, "Model operation are no longer supported"
231       
Note: See TracBrowser for help on using the repository browser.