Ticket #1099: broadgaussian.py

File broadgaussian.py, 10.9 KB (added by smk78, 6 years ago)

Sum|Multi model created in 4.1.2

Line 
1
2# A sample of an experimental model function for Sum/Multiply(Pmodel1,Pmodel2)
3import os
4import sys
5import copy
6import collections
7
8import numpy
9
10from sas.sascalc.fit.pluginmodel import Model1DPlugin
11from sasmodels.sasview_model import find_model
12
13class Model(Model1DPlugin):
14    name = os.path.splitext(os.path.basename(__file__))[0]
15    is_multiplicity_model = False
16    def __init__(self, multiplicity=1):
17        Model1DPlugin.__init__(self, name='')
18        P1 = find_model('power_law')
19        P2 = find_model('gaussian_peak')
20        p_model1 = P1()
21        p_model2 = P2()
22        ## Setting  model name model description
23        self.description = 'power_law_plus_gaussian_peak'
24        if self.name.rstrip().lstrip() == '':
25            self.name = self._get_name(p_model1.name, p_model2.name)
26        if self.description.rstrip().lstrip() == '':
27            self.description = p_model1.name
28            self.description += p_model2.name
29            self.fill_description(p_model1, p_model2)
30
31        ## Define parameters
32        self.params = collections.OrderedDict()
33
34        ## Parameter details [units, min, max]
35        self.details = {}
36        ## Magnetic Panrameters
37        self.magnetic_params = []
38        # non-fittable parameters
39        self.non_fittable = p_model1.non_fittable
40        self.non_fittable += p_model2.non_fittable
41
42        ##models
43        self.p_model1= p_model1
44        self.p_model2= p_model2
45
46
47        ## dispersion
48        self._set_dispersion()
49        ## Define parameters
50        self._set_params()
51        ## New parameter:scaling_factor
52        self.params['scale_factor'] = 1.0
53
54        ## Parameter details [units, min, max]
55        self._set_details()
56        self.details['scale_factor'] = ['', 0.0, numpy.inf]
57
58
59        #list of parameter that can be fitted
60        self._set_fixed_params()
61
62        ## parameters with orientation
63        self.orientation_params = []
64        for item in self.p_model1.orientation_params:
65            new_item = "p1_" + item
66            if not new_item in self.orientation_params:
67                self.orientation_params.append(new_item)
68
69        for item in self.p_model2.orientation_params:
70            new_item = "p2_" + item
71            if not new_item in self.orientation_params:
72                self.orientation_params.append(new_item)
73        ## magnetic params
74        self.magnetic_params = []
75        for item in self.p_model1.magnetic_params:
76            new_item = "p1_" + item
77            if not new_item in self.magnetic_params:
78                self.magnetic_params.append(new_item)
79
80        for item in self.p_model2.magnetic_params:
81            new_item = "p2_" + item
82            if not new_item in self.magnetic_params:
83                self.magnetic_params.append(new_item)
84        # get multiplicity if model provide it, else 1.
85        try:
86            multiplicity1 = p_model1.multiplicity
87            try:
88                multiplicity2 = p_model2.multiplicity
89            except:
90                multiplicity2 = 1
91        except:
92            multiplicity1 = 1
93            multiplicity2 = 1
94        ## functional multiplicity of the model
95        self.multiplicity1 = multiplicity1
96        self.multiplicity2 = multiplicity2
97        self.multiplicity_info = []
98
99    def _clone(self, obj):
100        import copy
101        obj.params     = copy.deepcopy(self.params)
102        obj.description     = copy.deepcopy(self.description)
103        obj.details    = copy.deepcopy(self.details)
104        obj.dispersion = copy.deepcopy(self.dispersion)
105        obj.p_model1  = self.p_model1.clone()
106        obj.p_model2  = self.p_model2.clone()
107        #obj = copy.deepcopy(self)
108        return obj
109
110    def _get_name(self, name1, name2):
111        p1_name = self._get_upper_name(name1)
112        if not p1_name:
113            p1_name = name1
114        name = p1_name
115        name += "_and_"
116        p2_name = self._get_upper_name(name2)
117        if not p2_name:
118            p2_name = name2
119        name += p2_name
120        return name
121
122    def _get_upper_name(self, name=None):
123        if name == None:
124            return ""
125        upper_name = ""
126        str_name = str(name)
127        for index in range(len(str_name)):
128            if str_name[index].isupper():
129                upper_name += str_name[index]
130        return upper_name
131
132    def _set_dispersion(self):
133        self.dispersion = collections.OrderedDict()
134        ##set dispersion only from p_model
135        for name , value in self.p_model1.dispersion.iteritems():
136            #if name.lower() not in self.p_model1.orientation_params:
137            new_name = "p1_" + name
138            self.dispersion[new_name]= value
139        for name , value in self.p_model2.dispersion.iteritems():
140            #if name.lower() not in self.p_model2.orientation_params:
141            new_name = "p2_" + name
142            self.dispersion[new_name]= value
143
144    def function(self, x=0.0):
145        return 0
146
147    def getProfile(self):
148        try:
149            x,y = self.p_model1.getProfile()
150        except:
151            x = None
152            y = None
153
154        return x, y
155
156    def _set_params(self):
157        for name , value in self.p_model1.params.iteritems():
158            # No 2D-supported
159            #if name not in self.p_model1.orientation_params:
160            new_name = "p1_" + name
161            self.params[new_name]= value
162
163        for name , value in self.p_model2.params.iteritems():
164            # No 2D-supported
165            #if name not in self.p_model2.orientation_params:
166            new_name = "p2_" + name
167            self.params[new_name]= value
168
169        # Set "scale" as initializing
170        self._set_scale_factor()
171
172
173    def _set_details(self):
174        for name ,detail in self.p_model1.details.iteritems():
175            new_name = "p1_" + name
176            #if new_name not in self.orientation_params:
177            self.details[new_name]= detail
178
179        for name ,detail in self.p_model2.details.iteritems():
180            new_name = "p2_" + name
181            #if new_name not in self.orientation_params:
182            self.details[new_name]= detail
183
184    def _set_scale_factor(self):
185        pass
186
187
188    def setParam(self, name, value):
189        # set param to this (p1, p2) model
190        self._setParamHelper(name, value)
191
192        ## setParam to p model
193        model_pre = ''
194        new_name = ''
195        name_split = name.split('_', 1)
196        if len(name_split) == 2:
197            model_pre = name.split('_', 1)[0]
198            new_name = name.split('_', 1)[1]
199        if model_pre == "p1":
200            if new_name in self.p_model1.getParamList():
201                self.p_model1.setParam(new_name, value)
202        elif model_pre == "p2":
203             if new_name in self.p_model2.getParamList():
204                self.p_model2.setParam(new_name, value)
205        elif name == 'scale_factor':
206            self.params['scale_factor'] = value
207        else:
208            raise ValueError, "Model does not contain parameter %s" % name
209
210    def getParam(self, name):
211        # Look for dispersion parameters
212        toks = name.split('.')
213        if len(toks)==2:
214            for item in self.dispersion.keys():
215                # 2D not supported
216                if item.lower()==toks[0].lower():
217                    for par in self.dispersion[item]:
218                        if par.lower() == toks[1].lower():
219                            return self.dispersion[item][par]
220        else:
221            # Look for standard parameter
222            for item in self.params.keys():
223                if item.lower()==name.lower():
224                    return self.params[item]
225        return
226        #raise ValueError, "Model does not contain parameter %s" % name
227
228    def _setParamHelper(self, name, value):
229        # Look for dispersion parameters
230        toks = name.split('.')
231        if len(toks)== 2:
232            for item in self.dispersion.keys():
233                if item.lower()== toks[0].lower():
234                    for par in self.dispersion[item]:
235                        if par.lower() == toks[1].lower():
236                            self.dispersion[item][par] = value
237                            return
238        else:
239            # Look for standard parameter
240            for item in self.params.keys():
241                if item.lower()== name.lower():
242                    self.params[item] = value
243                    return
244
245        raise ValueError, "Model does not contain parameter %s" % name
246
247
248    def _set_fixed_params(self):
249        self.fixed = []
250        for item in self.p_model1.fixed:
251            new_item = "p1" + item
252            self.fixed.append(new_item)
253        for item in self.p_model2.fixed:
254            new_item = "p2" + item
255            self.fixed.append(new_item)
256
257        self.fixed.sort()
258
259
260    def run(self, x = 0.0):
261        self._set_scale_factor()
262        return self.params['scale_factor'] * (self.p_model1.run(x) + self.p_model2.run(x))
263
264    def runXY(self, x = 0.0):
265        self._set_scale_factor()
266        return self.params['scale_factor'] * (self.p_model1.runXY(x) + self.p_model2.runXY(x))
267
268    ## Now (May27,10) directly uses the model eval function
269    ## instead of the for-loop in Base Component.
270    def evalDistribution(self, x = []):
271        self._set_scale_factor()
272        return self.params['scale_factor'] * (self.p_model1.evalDistribution(x) + self.p_model2.evalDistribution(x))
273
274    def set_dispersion(self, parameter, dispersion):
275        value= None
276        new_pre = parameter.split("_", 1)[0]
277        new_parameter = parameter.split("_", 1)[1]
278        try:
279            if new_pre == 'p1' and new_parameter in self.p_model1.dispersion.keys():
280                value= self.p_model1.set_dispersion(new_parameter, dispersion)
281            if new_pre == 'p2' and new_parameter in self.p_model2.dispersion.keys():
282                value= self.p_model2.set_dispersion(new_parameter, dispersion)
283            self._set_dispersion()
284            return value
285        except:
286            raise
287
288    def fill_description(self, p_model1, p_model2):
289        description = ""
290        description += "This model gives the summation or multiplication of"
291        description += "%s and %s. "% ( p_model1.name, p_model2.name )
292        self.description += description
293
294if __name__ == "__main__":
295    m1= Model()
296    #m1.setParam("p1_scale", 25)
297    #m1.setParam("p1_length", 1000)
298    #m1.setParam("p2_scale", 100)
299    #m1.setParam("p2_rg", 100)
300    out1 = m1.runXY(0.01)
301
302    m2= Model()
303    #m2.p_model1.setParam("scale", 25)
304    #m2.p_model1.setParam("length", 1000)
305    #m2.p_model2.setParam("scale", 100)
306    #m2.p_model2.setParam("rg", 100)
307    out2 = m2.p_model1.runXY(0.01) + m2.p_model2.runXY(0.01)
308
309    print "My name is %s."% m1.name
310    print out1, " = ", out2
311    if out1 == out2:
312        print "===> Simple Test: Passed!"
313    else:
314        print "===> Simple Test: Failed!"
315