source: sasview/fittingview/src/sans/perspectives/fitting/plugin_models/sum_p1_p2.py @ 33477fd

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

put back this model for now

  • Property mode set to 100644
File size: 15.0 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        name = self._get_upper_name(name1)
133        name += "+"
134        name += self._get_upper_name(name2)
135        return name
136   
137    def _get_upper_name(self, name=None):
138        """
139        Get uppercase string from model name
140        """
141        if name == None:
142            return ""
143        upper_name = ""
144        str_name = str(name)
145        for index in range(len(str_name)):
146            if str_name[index].isupper():
147                upper_name += str_name[index]
148        return upper_name
149       
150    def _set_dispersion(self):
151        """
152           combined the two models dispersions
153           Polydispersion should not be applied to s_model
154        """
155        ##set dispersion only from p_model
156        for name , value in self.p_model1.dispersion.iteritems():
157            #if name.lower() not in self.p_model1.orientation_params:
158            new_name = "p1_" + name
159            self.dispersion[new_name]= value
160        for name , value in self.p_model2.dispersion.iteritems():
161            #if name.lower() not in self.p_model2.orientation_params:
162            new_name = "p2_" + name
163            self.dispersion[new_name]= value
164           
165    def function(self, x=0.0): 
166        """
167        """
168        return 0
169                               
170    def getProfile(self):
171        """
172        Get SLD profile of p_model if exists
173       
174        : return: (r, beta) where r is a list of radius of the transition points
175                beta is a list of the corresponding SLD values
176        : Note: This works only for func_shell# = 2 (exp function)
177                and is not supporting for p2
178        """
179        try:
180            x,y = self.p_model1.getProfile()
181        except:
182            x = None
183            y = None
184           
185        return x, y
186   
187    def _set_params(self):
188        """
189            Concatenate the parameters of the two models to create
190            this model parameters
191        """
192
193        for name , value in self.p_model1.params.iteritems():
194            # No 2D-supported
195            #if name not in self.p_model1.orientation_params:
196            new_name = "p1_" + name
197            self.params[new_name]= value
198           
199        for name , value in self.p_model2.params.iteritems():
200            # No 2D-supported
201            #if name not in self.p_model2.orientation_params:
202            new_name = "p2_" + name
203            self.params[new_name]= value
204               
205        # Set "scale" as initializing
206        self._set_scale_factor()
207     
208           
209    def _set_details(self):
210        """
211            Concatenate details of the two models to create
212            this model details
213        """
214        for name ,detail in self.p_model1.details.iteritems():
215            new_name = "p1_" + name
216            #if new_name not in self.orientation_params:
217            self.details[new_name]= detail
218           
219        for name ,detail in self.p_model2.details.iteritems():
220            new_name = "p2_" + name
221            #if new_name not in self.orientation_params:
222            self.details[new_name]= detail
223   
224    def _set_scale_factor(self):
225        """
226        Not implemented
227        """
228        pass
229       
230               
231    def setParam(self, name, value):
232        """
233        Set the value of a model parameter
234   
235        :param name: name of the parameter
236        :param value: value of the parameter
237        """
238        # set param to p1+p2 model
239        self._setParamHelper(name, value)
240       
241        ## setParam to p model
242        model_pre = name.split('_', 1)[0]
243        new_name = name.split('_', 1)[1]
244        if model_pre == "p1":
245            if new_name in self.p_model1.getParamList():
246                self.p_model1.setParam(new_name, value)
247        elif model_pre == "p2":
248             if new_name in self.p_model2.getParamList():
249                self.p_model2.setParam(new_name, value)
250        elif name.lower() == 'scale_factor':
251            self.params['scale_factor'] = value
252        else:
253            raise ValueError, "Model does not contain parameter %s" % name
254           
255    def getParam(self, name):
256        """
257        Set the value of a model parameter
258
259        :param name: name of the parameter
260       
261        """
262        # Look for dispersion parameters
263        toks = name.split('.')
264        if len(toks)==2:
265            for item in self.dispersion.keys():
266                # 2D not supported
267                if item.lower()==toks[0].lower():# and \
268                            #item.lower() not in self.orientation_params \
269                            #and toks[0].lower() not in self.orientation_params:
270                    for par in self.dispersion[item]:
271                        if par.lower() == toks[1].lower():
272                            return self.dispersion[item][par]
273        else:
274            # Look for standard parameter
275            for item in self.params.keys():
276                if item.lower()==name.lower():#and \
277                            #item.lower() not in self.orientation_params \
278                            #and toks[0].lower() not in self.orientation_params:
279                    return self.params[item]
280        return 
281        #raise ValueError, "Model does not contain parameter %s" % name
282       
283    def _setParamHelper(self, name, value):
284        """
285        Helper function to setparam
286        """
287        # Look for dispersion parameters
288        toks = name.split('.')
289        if len(toks)== 2:
290            for item in self.dispersion.keys():
291                if item.lower()== toks[0].lower():# and \
292                            #item.lower() not in self.orientation_params:
293                    for par in self.dispersion[item]:
294                        if par.lower() == toks[1].lower():#and \
295                                #item.lower() not in self.orientation_params:
296                            self.dispersion[item][par] = value
297                            return
298        else:
299            # Look for standard parameter
300            for item in self.params.keys():
301                if item.lower()== name.lower():#and \
302                            #item.lower() not in self.orientation_params:
303                    self.params[item] = value
304                    return
305           
306        raise ValueError, "Model does not contain parameter %s" % name
307             
308   
309    def _set_fixed_params(self):
310        """
311             fill the self.fixed list with the p_model fixed list
312        """
313        for item in self.p_model1.fixed:
314            new_item = "p1" + item
315            self.fixed.append(new_item)
316        for item in self.p_model2.fixed:
317            new_item = "p2" + item
318            self.fixed.append(new_item)
319
320        self.fixed.sort()
321               
322                   
323    def run(self, x = 0.0):
324        """
325        Evaluate the model
326       
327        :param x: input q-value (float or [float, float] as [r, theta])
328        :return: (scattering function value)
329        """
330        self._set_scale_factor()
331        return self.params['scale_factor'] * \
332                (self.p_model1.run(x) + self.p_model2.run(x))
333   
334    def runXY(self, x = 0.0):
335        """
336        Evaluate the model
337       
338        :param x: input q-value (float or [float, float] as [qx, qy])
339        :return: scattering function value
340        """ 
341        self._set_scale_factor()
342        return self.params['scale_factor'] * \
343                (self.p_model1.runXY(x) + self.p_model2.runXY(x))
344   
345    ## Now (May27,10) directly uses the model eval function
346    ## instead of the for-loop in Base Component.
347    def evalDistribution(self, x = []):
348        """
349        Evaluate the model in cartesian coordinates
350       
351        :param x: input q[], or [qx[], qy[]]
352        :return: scattering function P(q[])
353        """
354        self._set_scale_factor()
355        return self.params['scale_factor'] * \
356                    (self.p_model1.evalDistribution(x) + \
357                                 self.p_model2.evalDistribution(x))
358
359    def set_dispersion(self, parameter, dispersion):
360        """
361        Set the dispersion object for a model parameter
362       
363        :param parameter: name of the parameter [string]
364        :dispersion: dispersion object of type DispersionModel
365        """
366        value= None
367        new_pre = parameter.split("_", 1)[0]
368        new_parameter = parameter.split("_", 1)[1]
369        try:
370            if new_pre == 'p1' and \
371                            new_parameter in self.p_model1.dispersion.keys():
372                value= self.p_model1.set_dispersion(new_parameter, dispersion)
373            if new_pre == 'p2' and \
374                             new_parameter in self.p_model2.dispersion.keys():
375                value= self.p_model2.set_dispersion(new_parameter, dispersion)
376            self._set_dispersion()
377            return value
378        except:
379            raise 
380
381    def fill_description(self, p_model1, p_model2):
382        """
383        Fill the description for P(Q)+P(Q)
384        """
385        description = ""
386        description +="This model gives the summation of  %s and %s.\n"% \
387                                        ( p_model1.name, p_model2.name )
388        self.description += description
389       
390if __name__ == "__main__": 
391    m1= Model() 
392    #m1.setParam("p1_scale", 25) 
393    #m1.setParam("p1_length", 1000)
394    #m1.setParam("p2_scale", 100)
395    #m1.setParam("p2_rg", 100)
396    out1 = m1.runXY(0.01)
397
398    m2= Model()
399    #m2.p_model1.setParam("scale", 25)
400    #m2.p_model1.setParam("length", 1000)
401    #m2.p_model2.setParam("scale", 100)
402    #m2.p_model2.setParam("rg", 100)
403    out2 = m2.p_model1.runXY(0.01) + m2.p_model2.runXY(0.01)
404    print "Testing at Q = 0.01:"
405    print out1, " = ", out2
406    if out1 == out2:
407        print "===> Simple Test: Passed!"
408    else:
409        print "===> Simple Test: Failed!"
Note: See TracBrowser for help on using the repository browser.