Ticket #820: fractal_times_core_shell_elypse.py

File fractal_times_core_shell_elypse.py, 11.0 KB (added by pkienzle, 7 years ago)

custom model to store in the plugins directory

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('fractal')
19        P2 = find_model('core_shell_ellipsoid')
20        p_model1 = P1()
21        p_model2 = P2()
22        ## Setting  model name model description
23        self.description = 'fractal *core_shell_ellipsoid'
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['BackGround'] = 0.0
53
54        ## Parameter details [units, min, max]
55        self._set_details()
56        self.details['BackGround'] = ['', 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_BackGround()
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_BackGround(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        #print("==> %s = %s.%s = %g", name, model_pre, new_name, value)
199        if model_pre == "p1":
200            if new_name in self.p_model1.getParamList():
201                self.p_model1.setParam(new_name, value)
202        #        print("p1")
203        elif model_pre == "p2":
204             if new_name in self.p_model2.getParamList():
205                self.p_model2.setParam(new_name, value)
206        #        print("p2")
207        elif name == 'BackGround':
208            self.params['BackGround'] = value
209        else:
210            raise ValueError, "Model does not contain parameter %s" % name
211
212    def getParam(self, name):
213        # Look for dispersion parameters
214        toks = name.split('.')
215        if len(toks)==2:
216            for item in self.dispersion.keys():
217                # 2D not supported
218                if item.lower()==toks[0].lower():
219                    for par in self.dispersion[item]:
220                        if par.lower() == toks[1].lower():
221                            return self.dispersion[item][par]
222        else:
223            # Look for standard parameter
224            for item in self.params.keys():
225                if item.lower()==name.lower():
226                    return self.params[item]
227        return
228        #raise ValueError, "Model does not contain parameter %s" % name
229
230    def _setParamHelper(self, name, value):
231        # Look for dispersion parameters
232        toks = name.split('.')
233        if len(toks)== 2:
234            for item in self.dispersion.keys():
235                if item.lower()== toks[0].lower():
236                    for par in self.dispersion[item]:
237                        if par.lower() == toks[1].lower():
238                            self.dispersion[item][par] = value
239                            return
240        else:
241            # Look for standard parameter
242            for item in self.params.keys():
243                if item.lower()== name.lower():
244                    self.params[item] = value
245                    return
246
247        raise ValueError, "Model does not contain parameter %s" % name
248
249
250    def _set_fixed_params(self):
251        self.fixed = []
252        for item in self.p_model1.fixed:
253            new_item = "p1" + item
254            self.fixed.append(new_item)
255        for item in self.p_model2.fixed:
256            new_item = "p2" + item
257            self.fixed.append(new_item)
258
259        self.fixed.sort()
260
261
262    def run(self, x = 0.0):
263        self._set_BackGround()
264        return self.params['BackGround'] + (self.p_model1.run(x)  * self.p_model2.run(x))
265
266    def runXY(self, x = 0.0):
267        self._set_BackGround()
268        return self.params['BackGround'] + (self.p_model1.runXY(x)  * self.p_model2.runXY(x))
269
270    ## Now (May27,10) directly uses the model eval function
271    ## instead of the for-loop in Base Component.
272    def evalDistribution(self, x = []):
273        self._set_BackGround()
274        return self.params['BackGround'] + (self.p_model1.evalDistribution(x)  * self.p_model2.evalDistribution(x))
275
276    def set_dispersion(self, parameter, dispersion):
277        value= None
278        new_pre = parameter.split("_", 1)[0]
279        new_parameter = parameter.split("_", 1)[1]
280        try:
281            if new_pre == 'p1' and new_parameter in self.p_model1.dispersion.keys():
282                value= self.p_model1.set_dispersion(new_parameter, dispersion)
283            if new_pre == 'p2' and new_parameter in self.p_model2.dispersion.keys():
284                value= self.p_model2.set_dispersion(new_parameter, dispersion)
285            self._set_dispersion()
286            return value
287        except:
288            raise
289
290    def fill_description(self, p_model1, p_model2):
291        description = ""
292        description += "This model gives the summation or multiplication of"
293        description += "%s and %s. "% ( p_model1.name, p_model2.name )
294        self.description += description
295
296if __name__ == "__main__":
297    m1= Model()
298    #m1.setParam("p1_scale", 25)
299    #m1.setParam("p1_length", 1000)
300    #m1.setParam("p2_scale", 100)
301    #m1.setParam("p2_rg", 100)
302    out1 = m1.runXY(0.01)
303
304    m2= Model()
305    #m2.p_model1.setParam("scale", 25)
306    #m2.p_model1.setParam("length", 1000)
307    #m2.p_model2.setParam("scale", 100)
308    #m2.p_model2.setParam("rg", 100)
309    out2 = m2.p_model1.runXY(0.01)  * m2.p_model2.runXY(0.01)
310
311    print "My name is %s."% m1.name
312    print out1, " = ", out2
313    if out1 == out2:
314        print "===> Simple Test: Passed!"
315    else:
316        print "===> Simple Test: Failed!"
317