source: sasview/fittingview/src/sans/perspectives/fitting/plugin_models/sum_p1_p2.py @ 316e231

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 316e231 was 316e231, checked in by Jae Cho <jhjcho@…>, 12 years ago

set all the custom model names same as its filename

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