source: sasview/sansview/plugins/sum_p1_p2.py @ 1ae05b6

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 1ae05b6 was 1ae05b6, checked in by Jae Cho <jhjcho@…>, 13 years ago

Added a user function sum(sphere+cylinder) so that a user can modify to add two models (1d only)

  • Property mode set to 100644
File size: 12.5 KB
Line 
1
2import copy
3from sans.models.pluginmodel import Model1DPlugin
4from sans.models.SphereModel import SphereModel as P1
5from sans.models.CylinderModel import CylinderModel as P2
6#from sans.models.SphericalSLDModel import SphericalSLDModel as P1
7
8class Model(Model1DPlugin):
9    """
10    Use for p1(Q)+p2(Q);
11    Note: P(Q) refers to 'form factor' model.
12    """
13    name = ""
14    P_MODEL1=P1
15    P_MODEL2=P2
16   
17    def __init__(self):
18        Model1DPlugin.__init__(self, name='')
19        """
20        :param p_model1: a form factor, P(Q)
21        :param p_model2: another form factor, P(Q)
22        """
23        ##models
24        #self.p_model1 = self.P_MODEL1(2) # for multifunctional model
25        self.p_model1 = self.P_MODEL1()
26        self.p_model2 = self.P_MODEL2()
27
28        ## Setting  model name model description
29        self.description=""
30        self.name = "Sphere(P1)"  +"+"+ "Cylinder(P2)"
31        self.description = self.p_model1.name+"\n"
32        self.description += self.p_model2.name+"\n"
33        self.fill_description(self.p_model1, self.p_model2)
34
35        ## Define parameters
36        self.params = {}
37
38        ## Parameter details [units, min, max]
39        self.details = {}
40       
41       
42        # non-fittable parameters
43        self.non_fittable = self.p_model1.non_fittable 
44        self.non_fittable += self.p_model2.non_fittable 
45           
46       
47        ## dispersion
48        self._set_dispersion()
49        ## Define parameters
50        self._set_params()
51        ## New parameter:Scaling factor
52        self.params['scale_factor'] = 1
53       
54        ## Parameter details [units, min, max]
55        self._set_details()
56        self.details['scale_factor'] = ['',     None, None]
57
58       
59        #list of parameter that can be fitted
60        self._set_fixed_params() 
61        ## parameters with orientation
62        for item in self.p_model1.orientation_params:
63            new_item = "p1_" + item
64            if not new_item in self.orientation_params:
65                self.orientation_params.append(new_item)
66           
67        for item in self.p_model2.orientation_params:
68            new_item = "p2_" + item
69            if not new_item in self.orientation_params:
70                self.orientation_params.append(new_item)
71        # get multiplicity if model provide it, else 1.
72        try:
73            multiplicity1 = self.p_model1.multiplicity
74            try:
75                multiplicity2 = self.p_model2.multiplicity
76            except:
77                multiplicity2 = 1
78        except:
79            multiplicity1 = 1
80            multiplicity2 = 1
81        ## functional multiplicity of the model
82        self.multiplicity1 = multiplicity1 
83        self.multiplicity2 = multiplicity2       
84       
85    def _clone(self, obj):
86        """
87            Internal utility function to copy the internal
88            data members to a fresh copy.
89        """
90        obj.params     = copy.deepcopy(self.params)
91        obj.description     = copy.deepcopy(self.description)
92        obj.details    = copy.deepcopy(self.details)
93        obj.dispersion = copy.deepcopy(self.dispersion)
94        obj.p_model1  = self.p_model1.clone()
95        obj.p_model2  = self.p_model2.clone()
96        #obj = copy.deepcopy(self)
97        return obj
98   
99   
100    def _set_dispersion(self):
101        """
102           combined the two models dispersions
103           Polydispersion should not be applied to s_model
104        """
105        ##set dispersion only from p_model
106        for name , value in self.p_model1.dispersion.iteritems():
107            if name.lower() not in self.p_model1.orientation_params:
108                new_name = "p1_" + name
109                self.dispersion[new_name]= value
110        for name , value in self.p_model2.dispersion.iteritems():
111            if name.lower() not in self.p_model2.orientation_params:
112                new_name = "p2_" + name
113                self.dispersion[new_name]= value
114           
115    def function(self, x=0.0): 
116        """
117        """
118        return 0
119                               
120    def getProfile(self):
121        """
122        Get SLD profile of p_model if exists
123       
124        : return: (r, beta) where r is a list of radius of the transition points
125                beta is a list of the corresponding SLD values
126        : Note: This works only for func_shell# = 2 (exp function)
127                and is not supporting for p2
128        """
129        try:
130            x,y = self.p_model1.getProfile()
131        except:
132            x = None
133            y = None
134           
135        return x, y
136   
137    def _set_params(self):
138        """
139            Concatenate the parameters of the two models to create
140            this model parameters
141        """
142
143        for name , value in self.p_model1.params.iteritems():
144            # No 2D-supported
145            if name not in self.p_model1.orientation_params:
146                new_name = "p1_" + name
147                self.params[new_name]= value
148           
149        for name , value in self.p_model2.params.iteritems():
150            # No 2D-supported
151            if name not in self.p_model2.orientation_params:
152                new_name = "p2_" + name
153                self.params[new_name]= value
154               
155        # Set "scale" as initializing
156        self._set_scale_factor()
157     
158           
159    def _set_details(self):
160        """
161            Concatenate details of the two models to create
162            this model details
163        """
164        for name ,detail in self.p_model1.details.iteritems():
165            new_name = "p1_" + name
166            if new_name not in self.orientation_params:
167                self.details[new_name]= detail
168           
169        for name ,detail in self.p_model2.details.iteritems():
170            new_name = "p2_" + name
171            if new_name not in self.orientation_params:
172                self.details[new_name]= detail
173   
174    def _set_scale_factor(self):
175        """
176        Not implemented
177        """
178        pass
179       
180               
181    def setParam(self, name, value):
182        """
183        Set the value of a model parameter
184   
185        :param name: name of the parameter
186        :param value: value of the parameter
187        """
188        # set param to p1+p2 model
189        self._setParamHelper(name, value)
190       
191        ## setParam to p model
192        model_pre = name.split('_', 1)[0]
193        new_name = name.split('_', 1)[1]
194        if model_pre == "p1":
195            if new_name in self.p_model1.getParamList():
196                self.p_model1.setParam(new_name, value)
197        elif model_pre == "p2":
198             if new_name in self.p_model2.getParamList():
199                self.p_model2.setParam(new_name, value)
200        elif name.lower() == 'scale_factor':
201            self.params['scale_factor'] = value
202        else:
203            raise ValueError, "Model does not contain parameter %s" % name
204           
205    def getParam(self, name):
206        """
207        Set the value of a model parameter
208
209        :param name: name of the parameter
210       
211        """
212        # Look for dispersion parameters
213        toks = name.split('.')
214        if len(toks)==2:
215            for item in self.dispersion.keys():
216                # 2D not supported
217                if item.lower()==toks[0].lower() and \
218                            item.lower() not in self.orientation_params \
219                            and toks[0].lower() not in self.orientation_params:
220                    for par in self.dispersion[item]:
221                        if par.lower() == toks[1].lower():
222                            return self.dispersion[item][par]
223        else:
224            # Look for standard parameter
225            for item in self.params.keys():
226                if item.lower()==name.lower()and \
227                            item.lower() not in self.orientation_params \
228                            and toks[0].lower() not in self.orientation_params:
229                    return self.params[item]
230        return 
231        #raise ValueError, "Model does not contain parameter %s" % name
232       
233    def _setParamHelper(self, name, value):
234        """
235        Helper function to setparam
236        """
237        # Look for dispersion parameters
238        toks = name.split('.')
239        if len(toks)== 2:
240            for item in self.dispersion.keys():
241                if item.lower()== toks[0].lower() and \
242                            item.lower() not in self.orientation_params:
243                    for par in self.dispersion[item]:
244                        if par.lower() == toks[1].lower()and \
245                                item.lower() not in self.orientation_params:
246                            self.dispersion[item][par] = value
247                            return
248        else:
249            # Look for standard parameter
250            for item in self.params.keys():
251                if item.lower()== name.lower()and \
252                            item.lower() not in self.orientation_params:
253                    self.params[item] = value
254                    return
255           
256        raise ValueError, "Model does not contain parameter %s" % name
257             
258   
259    def _set_fixed_params(self):
260        """
261             fill the self.fixed list with the p_model fixed list
262        """
263        for item in self.p_model1.fixed:
264            new_item = "p1" + item
265            self.fixed.append(new_item)
266        for item in self.p_model2.fixed:
267            new_item = "p2" + item
268            self.fixed.append(new_item)
269
270        self.fixed.sort()
271               
272                   
273    def run(self, x = 0.0):
274        """
275        Evaluate the model
276       
277        :param x: input q-value (float or [float, float] as [r, theta])
278        :return: (scattering function value)
279        """
280        self._set_scale_factor()
281        return self.params['scale_factor'] * \
282                (self.p_model1.run(x) + self.p_model2.run(x))
283   
284    def runXY(self, x = 0.0):
285        """
286        Evaluate the model
287       
288        :param x: input q-value (float or [float, float] as [qx, qy])
289        :return: scattering function value
290        """ 
291        self._set_scale_factor()
292        return self.params['scale_factor'] * \
293                (self.p_model1.runXY(x) + self.p_model2.runXY(x))
294   
295    ## Now (May27,10) directly uses the model eval function
296    ## instead of the for-loop in Base Component.
297    def evalDistribution(self, x = []):
298        """
299        Evaluate the model in cartesian coordinates
300       
301        :param x: input q[], or [qx[], qy[]]
302        :return: scattering function P(q[])
303        """
304        self._set_scale_factor()
305        return self.params['scale_factor'] * \
306                    (self.p_model1.evalDistribution(x) + \
307                                 self.p_model2.evalDistribution(x))
308
309    def set_dispersion(self, parameter, dispersion):
310        """
311        Set the dispersion object for a model parameter
312       
313        :param parameter: name of the parameter [string]
314        :dispersion: dispersion object of type DispersionModel
315        """
316        value= None
317        new_pre = parameter.split("_", 1)[0]
318        new_parameter = parameter.split("_", 1)[1]
319        try:
320            if new_pre == 'p1' and \
321                            new_parameter in self.p_model1.dispersion.keys():
322                value= self.p_model1.set_dispersion(new_parameter, dispersion)
323            if new_pre == 'p2' and \
324                             new_parameter in self.p_model2.dispersion.keys():
325                value= self.p_model2.set_dispersion(new_parameter, dispersion)
326            self._set_dispersion()
327            return value
328        except:
329            raise 
330
331    def fill_description(self, p_model1, p_model2):
332        """
333        Fill the description for P(Q)+P(Q)
334        """
335        description = ""
336        description +="This model gives the summation of  %s and %s.\n"% \
337                                        ( p_model1.name, p_model2.name )
338        self.description += description
339       
340if __name__ == "__main__": 
341    m1= Model() 
342    m1.setParam("p1_scale", 25) 
343    m1.setParam("p1_long_c", 1000)
344    m1.setParam("p2_scale", 100) 
345    m1.setParam("p2_rg", 100) 
346    out1 = m1.runXY(0.01)
347
348    m2= Model()
349    m2.p_model1.setParam("scale", 25) 
350    m2.p_model1.setParam("long_c", 1000) 
351    m2.p_model2.setParam("scale", 100)
352    m2.p_model2.setParam("rg", 100)
353    out2 = m2.p_model1.runXY(0.01) + m2.p_model2.runXY(0.01)
354    print out1, " = ", out2
355
356   
Note: See TracBrowser for help on using the repository browser.