Ticket #1184: lamellar_plus_gaussian_peak_410.py

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

Plugin created in 4.1.0

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('lamellar')
19        P2 = find_model('gaussian_peak')
20        p_model1 = P1()
21        p_model2 = P2()
22        ## Setting  model name model description
23        self.description = 'lamellar+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        obj.params     = copy.deepcopy(self.params)
101        obj.description     = copy.deepcopy(self.description)
102        obj.details    = copy.deepcopy(self.details)
103        obj.dispersion = copy.deepcopy(self.dispersion)
104        obj.p_model1  = self.p_model1.clone()
105        obj.p_model2  = self.p_model2.clone()
106        #obj = copy.deepcopy(self)
107        return obj
108
109    def _get_name(self, name1, name2):
110        p1_name = self._get_upper_name(name1)
111        if not p1_name:
112            p1_name = name1
113        name = p1_name
114        name += "_and_"
115        p2_name = self._get_upper_name(name2)
116        if not p2_name:
117            p2_name = name2
118        name += p2_name
119        return name
120
121    def _get_upper_name(self, name=None):
122        if name == None:
123            return ""
124        upper_name = ""
125        str_name = str(name)
126        for index in range(len(str_name)):
127            if str_name[index].isupper():
128                upper_name += str_name[index]
129        return upper_name
130
131    def _set_dispersion(self):
132        self.dispersion = collections.OrderedDict()
133        ##set dispersion only from p_model
134        for name , value in self.p_model1.dispersion.iteritems():
135            #if name.lower() not in self.p_model1.orientation_params:
136            new_name = "p1_" + name
137            self.dispersion[new_name]= value
138        for name , value in self.p_model2.dispersion.iteritems():
139            #if name.lower() not in self.p_model2.orientation_params:
140            new_name = "p2_" + name
141            self.dispersion[new_name]= value
142
143    def function(self, x=0.0):
144        return 0
145
146    def getProfile(self):
147        try:
148            x,y = self.p_model1.getProfile()
149        except:
150            x = None
151            y = None
152
153        return x, y
154
155    def _set_params(self):
156        for name , value in self.p_model1.params.iteritems():
157            # No 2D-supported
158            #if name not in self.p_model1.orientation_params:
159            new_name = "p1_" + name
160            self.params[new_name]= value
161
162        for name , value in self.p_model2.params.iteritems():
163            # No 2D-supported
164            #if name not in self.p_model2.orientation_params:
165            new_name = "p2_" + name
166            self.params[new_name]= value
167
168        # Set "scale" as initializing
169        self._set_scale_factor()
170
171
172    def _set_details(self):
173        for name ,detail in self.p_model1.details.iteritems():
174            new_name = "p1_" + name
175            #if new_name not in self.orientation_params:
176            self.details[new_name]= detail
177
178        for name ,detail in self.p_model2.details.iteritems():
179            new_name = "p2_" + name
180            #if new_name not in self.orientation_params:
181            self.details[new_name]= detail
182
183    def _set_scale_factor(self):
184        pass
185
186
187    def setParam(self, name, value):
188        # set param to this (p1, p2) model
189        self._setParamHelper(name, value)
190
191        ## setParam to p model
192        model_pre = ''
193        new_name = ''
194        name_split = name.split('_', 1)
195        if len(name_split) == 2:
196            model_pre = name.split('_', 1)[0]
197            new_name = name.split('_', 1)[1]
198        if model_pre == "p1":
199            if new_name in self.p_model1.getParamList():
200                self.p_model1.setParam(new_name, value)
201        elif model_pre == "p2":
202             if new_name in self.p_model2.getParamList():
203                self.p_model2.setParam(new_name, value)
204        elif name == 'scale_factor':
205            self.params['scale_factor'] = value
206        else:
207            raise ValueError, "Model does not contain parameter %s" % name
208
209    def getParam(self, name):
210        # Look for dispersion parameters
211        toks = name.split('.')
212        if len(toks)==2:
213            for item in self.dispersion.keys():
214                # 2D not supported
215                if item.lower()==toks[0].lower():
216                    for par in self.dispersion[item]:
217                        if par.lower() == toks[1].lower():
218                            return self.dispersion[item][par]
219        else:
220            # Look for standard parameter
221            for item in self.params.keys():
222                if item.lower()==name.lower():
223                    return self.params[item]
224        return
225        #raise ValueError, "Model does not contain parameter %s" % name
226
227    def _setParamHelper(self, name, value):
228        # Look for dispersion parameters
229        toks = name.split('.')
230        if len(toks)== 2:
231            for item in self.dispersion.keys():
232                if item.lower()== toks[0].lower():
233                    for par in self.dispersion[item]:
234                        if par.lower() == toks[1].lower():
235                            self.dispersion[item][par] = value
236                            return
237        else:
238            # Look for standard parameter
239            for item in self.params.keys():
240                if item.lower()== name.lower():
241                    self.params[item] = value
242                    return
243
244        raise ValueError, "Model does not contain parameter %s" % name
245
246
247    def _set_fixed_params(self):
248        self.fixed = []
249        for item in self.p_model1.fixed:
250            new_item = "p1" + item
251            self.fixed.append(new_item)
252        for item in self.p_model2.fixed:
253            new_item = "p2" + item
254            self.fixed.append(new_item)
255
256        self.fixed.sort()
257
258
259    def run(self, x = 0.0):
260        self._set_scale_factor()
261        return self.params['scale_factor'] * (self.p_model1.run(x) + self.p_model2.run(x))
262
263    def runXY(self, x = 0.0):
264        self._set_scale_factor()
265        return self.params['scale_factor'] * (self.p_model1.runXY(x) + self.p_model2.runXY(x))
266
267    ## Now (May27,10) directly uses the model eval function
268    ## instead of the for-loop in Base Component.
269    def evalDistribution(self, x = []):
270        self._set_scale_factor()
271        return self.params['scale_factor'] * (self.p_model1.evalDistribution(x) + self.p_model2.evalDistribution(x))
272
273    def set_dispersion(self, parameter, dispersion):
274        value= None
275        new_pre = parameter.split("_", 1)[0]
276        new_parameter = parameter.split("_", 1)[1]
277        try:
278            if new_pre == 'p1' and new_parameter in self.p_model1.dispersion.keys():
279                value= self.p_model1.set_dispersion(new_parameter, dispersion)
280            if new_pre == 'p2' and new_parameter in self.p_model2.dispersion.keys():
281                value= self.p_model2.set_dispersion(new_parameter, dispersion)
282            self._set_dispersion()
283            return value
284        except:
285            raise
286
287    def fill_description(self, p_model1, p_model2):
288        description = ""
289        description += "This model gives the summation or multiplication of"
290        description += "%s and %s. "% ( p_model1.name, p_model2.name )
291        self.description += description
292
293if __name__ == "__main__":
294    m1= Model()
295    #m1.setParam("p1_scale", 25)
296    #m1.setParam("p1_length", 1000)
297    #m1.setParam("p2_scale", 100)
298    #m1.setParam("p2_rg", 100)
299    out1 = m1.runXY(0.01)
300
301    m2= Model()
302    #m2.p_model1.setParam("scale", 25)
303    #m2.p_model1.setParam("length", 1000)
304    #m2.p_model2.setParam("scale", 100)
305    #m2.p_model2.setParam("rg", 100)
306    out2 = m2.p_model1.runXY(0.01) + m2.p_model2.runXY(0.01)
307
308    print "My name is %s."% m1.name
309    print out1, " = ", out2
310    if out1 == out2:
311        print "===> Simple Test: Passed!"
312    else:
313        print "===> Simple Test: Failed!"
314