source: sasview/fittingview/src/sans/perspectives/fitting/plugin_models/sum_Ap1_1_Ap2.py @ 045be84d

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 045be84d 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.4 KB
Line 
1# A sample of an experimental model function for Sum(APmodel1,(1-A)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 model is DIFFERENT from the Easy Custom Sum(p1 + p2)
31## by definition of the scale factor *****************************************
32#
33#     Custom model = scale_factor * P1 + (1 - scale_factor) * P2
34#
35## User can REPLACE model names below arrowed two lines (twice per line)
36from sans.models.CylinderModel import CylinderModel as P1          #<========
37from sans.models.PolymerExclVolume import PolymerExclVolume as P2  #<========
38
39#####DO NOT CHANGE ANYTHING BELOW THIS LINE
40#####---------------------------------------------------------------------------
41class Model(Model1DPlugin):
42    """
43    Use for A*p1(Q)+(1-A)*p2(Q);
44    Note: P(Q) refers to 'form factor' model.
45    """
46    name = "" 
47    def __init__(self):
48        Model1DPlugin.__init__(self, name=self.name)
49        """
50        :param p_model1: a form factor, P(Q)
51        :param p_model2: another form factor, P(Q)
52        """
53        p_model1 = P1()
54        p_model2 = P2()
55        ## Setting  model name model description
56        self.description = ""
57        self.fill_description(p_model1, p_model2)
58        # Set the name same as the file name
59        self.name = self.get_fname()     ##DO NOT CHANGE THIS LINE!!!
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'] = 0.5
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 = "A*"
133        p1_name = self._get_upper_name(name1)
134        if not p1_name:
135            p1_name = name1
136        name += p1_name
137        name += "+(1-A)*"
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'] * self.p_model1.run(x) + \
339                (1 - self.params['scale_factor']) * 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'] * self.p_model1.runXY(x) + \
350                (1 - self.params['scale_factor']) * 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'] * self.p_model1.evalDistribution(x) + \
363                (1 - self.params['scale_factor']) * self.p_model2.evalDistribution(x))
364
365    def set_dispersion(self, parameter, dispersion):
366        """
367        Set the dispersion object for a model parameter
368       
369        :param parameter: name of the parameter [string]
370        :dispersion: dispersion object of type DispersionModel
371        """
372        value= None
373        new_pre = parameter.split("_", 1)[0]
374        new_parameter = parameter.split("_", 1)[1]
375        try:
376            if new_pre == 'p1' and \
377                            new_parameter in self.p_model1.dispersion.keys():
378                value= self.p_model1.set_dispersion(new_parameter, dispersion)
379            if new_pre == 'p2' and \
380                             new_parameter in self.p_model2.dispersion.keys():
381                value= self.p_model2.set_dispersion(new_parameter, dispersion)
382            self._set_dispersion()
383            return value
384        except:
385            raise 
386
387    def fill_description(self, p_model1, p_model2):
388        """
389        Fill the description for P(Q)+P(Q)
390        """
391        description = ""
392        description +="This model gives the summation of (A*%s) and ((1-A)*%s).\n"% \
393                                        ( p_model1.name, p_model2.name )
394        self.description += description
395   
396    ## DO NOT MODIFY THE FOLLOWING LINES!!!!!!!!!!!!!!!!       
397    def get_fname(self):
398        """
399        Get the model name same as the file name
400        """
401        path = sys._getframe().f_code.co_filename
402        basename  = os.path.basename(path)
403        name, _ = os.path.splitext(basename)
404        return name
405           
406### FOR TEST               
407if __name__ == "__main__": 
408    m1= Model() 
409    out1 = m1.runXY(0.01)
410    m2= Model()
411    out2 = 0.5 * m2.p_model1.runXY(0.01) + 0.5 * m2.p_model2.runXY(0.01)
412    print "Testing at Q = 0.01:"
413    print out1, " = ", out2
414    if out1 == out2:
415        print "===> Simple Test: Passed!"
416    else:
417        print "===> Simple Test: Failed!"
Note: See TracBrowser for help on using the repository browser.