source: sasview/fittingview/src/sans/perspectives/fitting/plugin_models/sum_p1_p2.py @ 4310dbb

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 4310dbb was 2b4c8ca, checked in by Jae Cho <jhjcho@…>, 13 years ago

a little correction for naming the sum model especially when one of the models has all lower case name

  • Property mode set to 100644
File size: 15.1 KB
Line 
1# A sample of an experimental model function for Sum(Pmodel1,Pmodel2)
2import copy
3from sans.models.pluginmodel import Model1DPlugin
4
5"""
6## *****************************************************************************
7Please select the 'Compile' from the menubar after the modification and saving.
8Note that we recommend to save the file as a different file name.
9Otherwise, it could be removed in the future on re-installation of the SansView.
10## *****************************************************************************
11"""
12
13# Available model names for this sum model
14"""
15BCCrystalModel, BEPolyelectrolyte, BarBellModel, BinaryHSModel, BroadPeakModel,
16CSParallelepipedModel, CappedCylinderModel, CoreShellCylinderModel,
17CoreShellEllipsoidModel, CoreShellModel, CorrLengthModel, CylinderModel,
18DABModel, DebyeModel, EllipsoidModel, EllipticalCylinderModel, FCCrystalModel,
19FlexCylEllipXModel, FlexibleCylinderModel, FractalCoreShellModel, FractalModel,
20FuzzySphereModel, GaussLorentzGelModel, GuinierModel, GuinierPorodModel,
21HardsphereStructure, HayterMSAStructure, HollowCylinderModel, LamellarFFHGModel,
22LamellarModel, LamellarPCrystalModel, LamellarPSHGModel, LamellarPSModel,
23LineModel, LorentzModel, MultiShellModel, ParallelepipedModel, PeakGaussModel,
24PeakLorentzModel, PearlNecklaceModel, Poly_GaussCoil, PolymerExclVolume,
25PorodModel, PowerLawAbsModel, SCCrystalModel, SphereModel, SquareWellStructure,
26StackedDisksModel, StickyHSStructure, TeubnerStreyModel, TriaxialEllipsoidModel,
27TwoLorentzianModel, TwoPowerLawModel, VesicleModel
28"""
29## This is same as the Easy Custom Sum(p1 + p2)
30#
31#     Custom model = scale_factor * (P1 + P2)
32#
33## User can REPLACE model names below two arrowed lines (two names per line)
34from sans.models.CylinderModel import CylinderModel as P1          #<========
35from sans.models.PolymerExclVolume import PolymerExclVolume as P2  #<========
36
37#####DO NOT CHANGE ANYTHING BELOW THIS LINE
38#####---------------------------------------------------------------------------
39class Model(Model1DPlugin):
40    """
41    Use for p1(Q)+p2(Q);
42    Note: P(Q) refers to 'form factor' model.
43    """
44    name = ""
45    def __init__(self):
46        Model1DPlugin.__init__(self, name='')
47        """
48        :param p_model1: a form factor, P(Q)
49        :param p_model2: another form factor, P(Q)
50        """
51        p_model1 = P1()
52        p_model2 = P2()
53        ## Setting  model name model description
54        self.description=""
55        self.name = self._get_name(p_model1.name, p_model2.name)
56        self.description = p_model1.name+"\n"
57        self.description += p_model2.name+"\n"
58        self.fill_description(p_model1, p_model2)
59
60        ## Define parameters
61        self.params = {}
62
63        ## Parameter details [units, min, max]
64        self.details = {}
65       
66        # non-fittable parameters
67        self.non_fittable = p_model1.non_fittable 
68        self.non_fittable += p_model2.non_fittable 
69           
70        ##models
71        self.p_model1= p_model1
72        self.p_model2= p_model2
73       
74       
75        ## dispersion
76        self._set_dispersion()
77        ## Define parameters
78        self._set_params()
79        ## New parameter:Scaling factor
80        self.params['scale_factor'] = 1
81       
82        ## Parameter details [units, min, max]
83        self._set_details()
84        self.details['scale_factor'] = ['',  None, None]
85
86       
87        #list of parameter that can be fitted
88        self._set_fixed_params() 
89        ## parameters with orientation
90        for item in self.p_model1.orientation_params:
91            new_item = "p1_" + item
92            if not new_item in self.orientation_params:
93                self.orientation_params.append(new_item)
94           
95        for item in self.p_model2.orientation_params:
96            new_item = "p2_" + item
97            if not new_item in self.orientation_params:
98                self.orientation_params.append(new_item)
99        # get multiplicity if model provide it, else 1.
100        try:
101            multiplicity1 = p_model1.multiplicity
102            try:
103                multiplicity2 = p_model2.multiplicity
104            except:
105                multiplicity2 = 1
106        except:
107            multiplicity1 = 1
108            multiplicity2 = 1
109        ## functional multiplicity of the model
110        self.multiplicity1 = multiplicity1 
111        self.multiplicity2 = multiplicity2   
112        self.multiplicity_info = []   
113       
114    def _clone(self, obj):
115        """
116            Internal utility function to copy the internal
117            data members to a fresh copy.
118        """
119        obj.params     = copy.deepcopy(self.params)
120        obj.description     = copy.deepcopy(self.description)
121        obj.details    = copy.deepcopy(self.details)
122        obj.dispersion = copy.deepcopy(self.dispersion)
123        obj.p_model1  = self.p_model1.clone()
124        obj.p_model2  = self.p_model2.clone()
125        #obj = copy.deepcopy(self)
126        return obj
127   
128    def _get_name(self, name1, name2):
129        """
130        Get combined name from two model names
131        """
132        p1_name = self._get_upper_name(name1)
133        if not p1_name:
134            p1_name = name1
135        name = p1_name
136        name += "+"
137        p2_name = self._get_upper_name(name2)
138        if not p2_name:
139            p2_name = name2
140        name += p2_name
141        return name
142   
143    def _get_upper_name(self, name=None):
144        """
145        Get uppercase string from model name
146        """
147        if name == None:
148            return ""
149        upper_name = ""
150        str_name = str(name)
151        for index in range(len(str_name)):
152            if str_name[index].isupper():
153                upper_name += str_name[index]
154        return upper_name
155       
156    def _set_dispersion(self):
157        """
158           combined the two models dispersions
159           Polydispersion should not be applied to s_model
160        """
161        ##set dispersion only from p_model
162        for name , value in self.p_model1.dispersion.iteritems():
163            #if name.lower() not in self.p_model1.orientation_params:
164            new_name = "p1_" + name
165            self.dispersion[new_name]= value
166        for name , value in self.p_model2.dispersion.iteritems():
167            #if name.lower() not in self.p_model2.orientation_params:
168            new_name = "p2_" + name
169            self.dispersion[new_name]= value
170           
171    def function(self, x=0.0): 
172        """
173        """
174        return 0
175                               
176    def getProfile(self):
177        """
178        Get SLD profile of p_model if exists
179       
180        : return: (r, beta) where r is a list of radius of the transition points
181                beta is a list of the corresponding SLD values
182        : Note: This works only for func_shell# = 2 (exp function)
183                and is not supporting for p2
184        """
185        try:
186            x,y = self.p_model1.getProfile()
187        except:
188            x = None
189            y = None
190           
191        return x, y
192   
193    def _set_params(self):
194        """
195            Concatenate the parameters of the two models to create
196            this model parameters
197        """
198
199        for name , value in self.p_model1.params.iteritems():
200            # No 2D-supported
201            #if name not in self.p_model1.orientation_params:
202            new_name = "p1_" + name
203            self.params[new_name]= value
204           
205        for name , value in self.p_model2.params.iteritems():
206            # No 2D-supported
207            #if name not in self.p_model2.orientation_params:
208            new_name = "p2_" + name
209            self.params[new_name]= value
210               
211        # Set "scale" as initializing
212        self._set_scale_factor()
213     
214           
215    def _set_details(self):
216        """
217            Concatenate details of the two models to create
218            this model details
219        """
220        for name ,detail in self.p_model1.details.iteritems():
221            new_name = "p1_" + name
222            #if new_name not in self.orientation_params:
223            self.details[new_name]= detail
224           
225        for name ,detail in self.p_model2.details.iteritems():
226            new_name = "p2_" + name
227            #if new_name not in self.orientation_params:
228            self.details[new_name]= detail
229   
230    def _set_scale_factor(self):
231        """
232        Not implemented
233        """
234        pass
235       
236               
237    def setParam(self, name, value):
238        """
239        Set the value of a model parameter
240   
241        :param name: name of the parameter
242        :param value: value of the parameter
243        """
244        # set param to p1+p2 model
245        self._setParamHelper(name, value)
246       
247        ## setParam to p model
248        model_pre = name.split('_', 1)[0]
249        new_name = name.split('_', 1)[1]
250        if model_pre == "p1":
251            if new_name in self.p_model1.getParamList():
252                self.p_model1.setParam(new_name, value)
253        elif model_pre == "p2":
254             if new_name in self.p_model2.getParamList():
255                self.p_model2.setParam(new_name, value)
256        elif name.lower() == 'scale_factor':
257            self.params['scale_factor'] = value
258        else:
259            raise ValueError, "Model does not contain parameter %s" % name
260           
261    def getParam(self, name):
262        """
263        Set the value of a model parameter
264
265        :param name: name of the parameter
266       
267        """
268        # Look for dispersion parameters
269        toks = name.split('.')
270        if len(toks)==2:
271            for item in self.dispersion.keys():
272                # 2D not supported
273                if item.lower()==toks[0].lower():# and \
274                            #item.lower() not in self.orientation_params \
275                            #and toks[0].lower() not in self.orientation_params:
276                    for par in self.dispersion[item]:
277                        if par.lower() == toks[1].lower():
278                            return self.dispersion[item][par]
279        else:
280            # Look for standard parameter
281            for item in self.params.keys():
282                if item.lower()==name.lower():#and \
283                            #item.lower() not in self.orientation_params \
284                            #and toks[0].lower() not in self.orientation_params:
285                    return self.params[item]
286        return 
287        #raise ValueError, "Model does not contain parameter %s" % name
288       
289    def _setParamHelper(self, name, value):
290        """
291        Helper function to setparam
292        """
293        # Look for dispersion parameters
294        toks = name.split('.')
295        if len(toks)== 2:
296            for item in self.dispersion.keys():
297                if item.lower()== toks[0].lower():# and \
298                            #item.lower() not in self.orientation_params:
299                    for par in self.dispersion[item]:
300                        if par.lower() == toks[1].lower():#and \
301                                #item.lower() not in self.orientation_params:
302                            self.dispersion[item][par] = value
303                            return
304        else:
305            # Look for standard parameter
306            for item in self.params.keys():
307                if item.lower()== name.lower():#and \
308                            #item.lower() not in self.orientation_params:
309                    self.params[item] = value
310                    return
311           
312        raise ValueError, "Model does not contain parameter %s" % name
313             
314   
315    def _set_fixed_params(self):
316        """
317             fill the self.fixed list with the p_model fixed list
318        """
319        for item in self.p_model1.fixed:
320            new_item = "p1" + item
321            self.fixed.append(new_item)
322        for item in self.p_model2.fixed:
323            new_item = "p2" + item
324            self.fixed.append(new_item)
325
326        self.fixed.sort()
327               
328                   
329    def run(self, x = 0.0):
330        """
331        Evaluate the model
332       
333        :param x: input q-value (float or [float, float] as [r, theta])
334        :return: (scattering function value)
335        """
336        self._set_scale_factor()
337        return self.params['scale_factor'] * \
338                (self.p_model1.run(x) + self.p_model2.run(x))
339   
340    def runXY(self, x = 0.0):
341        """
342        Evaluate the model
343       
344        :param x: input q-value (float or [float, float] as [qx, qy])
345        :return: scattering function value
346        """ 
347        self._set_scale_factor()
348        return self.params['scale_factor'] * \
349                (self.p_model1.runXY(x) + self.p_model2.runXY(x))
350   
351    ## Now (May27,10) directly uses the model eval function
352    ## instead of the for-loop in Base Component.
353    def evalDistribution(self, x = []):
354        """
355        Evaluate the model in cartesian coordinates
356       
357        :param x: input q[], or [qx[], qy[]]
358        :return: scattering function P(q[])
359        """
360        self._set_scale_factor()
361        return self.params['scale_factor'] * \
362                    (self.p_model1.evalDistribution(x) + \
363                                 self.p_model2.evalDistribution(x))
364
365    def set_dispersion(self, parameter, dispersion):
366        """
367        Set the dispersion object for a model parameter
368       
369        :param parameter: name of the parameter [string]
370        :dispersion: dispersion object of type DispersionModel
371        """
372        value= None
373        new_pre = parameter.split("_", 1)[0]
374        new_parameter = parameter.split("_", 1)[1]
375        try:
376            if new_pre == 'p1' and \
377                            new_parameter in self.p_model1.dispersion.keys():
378                value= self.p_model1.set_dispersion(new_parameter, dispersion)
379            if new_pre == 'p2' and \
380                             new_parameter in self.p_model2.dispersion.keys():
381                value= self.p_model2.set_dispersion(new_parameter, dispersion)
382            self._set_dispersion()
383            return value
384        except:
385            raise 
386
387    def fill_description(self, p_model1, p_model2):
388        """
389        Fill the description for P(Q)+P(Q)
390        """
391        description = ""
392        description +="This model gives the summation of  %s and %s.\n"% \
393                                        ( p_model1.name, p_model2.name )
394        self.description += description
395       
396if __name__ == "__main__": 
397    m1= Model() 
398    #m1.setParam("p1_scale", 25) 
399    #m1.setParam("p1_length", 1000)
400    #m1.setParam("p2_scale", 100)
401    #m1.setParam("p2_rg", 100)
402    out1 = m1.runXY(0.01)
403
404    m2= Model()
405    #m2.p_model1.setParam("scale", 25)
406    #m2.p_model1.setParam("length", 1000)
407    #m2.p_model2.setParam("scale", 100)
408    #m2.p_model2.setParam("rg", 100)
409    out2 = m2.p_model1.runXY(0.01) + m2.p_model2.runXY(0.01)
410    print "Testing at Q = 0.01:"
411    print out1, " = ", out2
412    if out1 == out2:
413        print "===> Simple Test: Passed!"
414    else:
415        print "===> Simple Test: Failed!"
Note: See TracBrowser for help on using the repository browser.