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

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 543d1bd was 0e62f0f, checked in by Jae Cho <jhjcho@…>, 13 years ago

Added comments

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