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

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

fixing pylint warnings

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