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

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

more completion of custom model edit

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