source: sasview/sansmodels/src/sans/models/OnionExpShellModel.py @ 2d9c4039

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 2d9c4039 was 4b3d25b, checked in by Jae Cho <jhjcho@…>, 14 years ago

new model and some bug fixes

  • Property mode set to 100644
File size: 10.5 KB
Line 
1   
2from sans.models.BaseComponent import BaseComponent
3from sans.models.OnionModel import OnionModel
4import copy
5max_nshells = 10
6class OnionExpShellModel(BaseComponent):
7    """
8    This multi-model is based on CoreMultiShellModel with exponential
9    func shells and provides the capability
10    of changing the number of shells between 1 and 10.
11    """
12    def __init__(self, n_shells=1):
13        BaseComponent.__init__(self)
14        """
15        :param n_shells: number of shells in the model,
16        assumes 1<= n_shells <=10.
17        """
18
19        ## Setting  model name model description
20        self.description=""
21        model = OnionModel()
22        self.model = model
23        self.name = "OnionExpShellModel"
24        self.description=model.description
25        self.n_shells = n_shells
26        ## Define parameters
27        self.params = {}
28
29        ## Parameter details [units, min, max]
30        self.details = {}
31       
32        ## dispersion
33        self._set_dispersion()
34        ## Define parameters
35        self._set_params()
36       
37        ## Parameter details [units, min, max]
38        self._set_details()
39       
40        #list of parameter that can be fitted
41        self._set_fixed_params() 
42        self.model.params['n_shells'] = self.n_shells
43        ## functional multiplicity info of the model
44        # [int(maximum no. of functionality),"str(Titl),
45        # [str(name of function0),...], [str(x-asix name of sld),...]]
46        self.multiplicity_info = [max_nshells,"No. of Shells:",[],['Radius']]
47
48        ## parameters with orientation: can be removed since there is
49        # no orientational params
50        for item in self.model.orientation_params:
51            self.orientation_params.append(item)
52        self.getProfile()       
53    def _clone(self, obj):
54        """
55        Internal utility function to copy the internal
56        data members to a fresh copy.
57        """
58        obj.params     = copy.deepcopy(self.params)
59        obj.description     = copy.deepcopy(self.description)
60        obj.details    = copy.deepcopy(self.details)
61        obj.dispersion = copy.deepcopy(self.dispersion)
62        obj.model  = self.model.clone()
63
64        return obj
65   
66   
67    def _set_dispersion(self):
68        """
69        model dispersions
70        """ 
71        ##set dispersion from model
72        for name , value in self.model.dispersion.iteritems():   
73             
74            nshell = 0
75            if name.split('_')[0] == 'thick':
76                while nshell<self.n_shells:
77                    nshell += 1
78                    if name.split('_')[1] == 'shell%s' % str(nshell):
79                        self.dispersion[name]= value
80                    else: 
81                        continue
82            else:
83                self.dispersion[name]= value
84                   
85
86    def _set_params(self):
87        """
88        Concatenate the parameters of the model to create
89        this model parameters
90        """
91        # rearrange the parameters for the given # of shells
92        for name , value in self.model.params.iteritems():
93            nshell = 0
94            pos = len(name.split('_'))-1
95            if name.split('_')[0] == 'func':
96                continue
97            elif name.split('_')[pos][0:5] == 'shell':
98                    while nshell<self.n_shells:
99                        nshell += 1
100                        if name.split('_')[pos] == 'shell%s' % str(nshell):
101                            self.params[name]= value
102                            continue
103            else:
104                self.params[name]= value
105               
106        self.model.params['n_shells'] = self.n_shells   
107
108        # set constrained values for the original model params
109        self._set_xtra_model_param()       
110 
111    def _set_details(self):
112        """
113        Concatenate details of the original model to create
114        this model details
115        """
116        for name ,detail in self.model.details.iteritems():
117            if name in self.params.iterkeys():
118                self.details[name]= detail
119           
120   
121    def _set_xtra_model_param(self):
122        """
123        Set params of original model that are hidden from this model
124        """
125        # look for the model parameters that are not in param list
126        for key in self.model.params.iterkeys():
127            if key not in self.params.keys():
128                if  key.split('_')[0] == 'thick':
129                    self.model.setParam(key, 0)
130                    continue
131                if  key.split('_')[0] == 'A':
132                    self.model.setParam(key, 0)
133                    continue
134                if  key.split('_')[0] == 'func':
135                    self.model.setParam(key, 2)
136                    continue
137                for nshell in range(self.n_shells,max_nshells):
138                    if key.split('_')[1] == 'sld_in_shell%s' % str(nshell+1):
139                        try:
140                            value = self.model.params['sld_solv']
141                            self.model.setParam(key, value)
142                        except: pass
143    def getProfile(self):
144        """
145        Get SLD profile
146       
147        : return: (r, beta) where r is a list of radius of the transition
148                points and  beta is a list of the corresponding SLD values
149        """
150        # max_pts for each shells
151        max_pts = 10
152        r = []
153        beta = []
154        # for core at r=0
155        r.append(0)
156        beta.append(self.params['sld_core0'])
157        # for core at r=rad_core
158        r.append(self.params['rad_core0'])
159        beta.append(self.params['sld_core0'])
160       
161        # for shells
162        for n in range(1,self.n_shells+1):
163            # Left side of each shells
164            r0 = r[len(r)-1]           
165            r.append(r0)
166            beta.append(self.params['sld_in_shell%s'% str(n)])
167           
168            A = self.params['A_shell%s'% str(n)]
169            from math import fabs
170            if fabs(A) <1.0e-16:
171                # Right side of each shells
172                r0 += self.params['thick_shell%s'% str(n)]
173                r.append(r0)
174                beta.append(self.params['sld_in_shell%s'% str(n)])
175            else:
176                from math import exp
177                rn = r0
178                for n_sub in range(0,max_pts):
179                    # Right side of each sub_shells
180                    rn += self.params['thick_shell%s'% str(n)]/10.0
181                    r.append(rn)
182                    slope = (self.params['sld_out_shell%s'% str(n)] \
183                                    -self.params['sld_in_shell%s'% str(n)]) \
184                                     /(exp(self.params['A_shell%s'% str(n)])-1)
185                    const = (self.params['sld_in_shell%s'% str(n)]-slope)
186                    beta_n = slope*exp((self.params['A_shell%s'% str(n)]* \
187                        (rn-r0)/self.params['thick_shell%s'% str(n)])) + const
188                    beta.append(beta_n)
189           
190        # for solvent
191        r0 = r[len(r)-1]           
192        r.append(r0)
193        beta.append(self.params['sld_solv'])
194        r_solv = 5*r0/4
195        r.append(r_solv)
196        beta.append(self.params['sld_solv'])
197       
198        return r, beta
199   
200    def setParam(self, name, value):
201        """
202        Set the value of a model parameter
203   
204        : param name: name of the parameter
205        : param value: value of the parameter
206        """
207        # set param to new model
208        self._setParamHelper( name, value)
209       
210        ## setParam to model
211        if name=='sld_solv':
212            # the sld_*** model.params not in params must set to value
213            # of sld_solv
214            for key in self.model.params.iterkeys():
215                if key not in self.params.keys()and key.split('_')[0] == 'sld':
216                        self.model.setParam(key, value)
217        self.model.setParam( name, value)
218       
219    def _setParamHelper(self, name, value):
220        """
221        Helper function to setParam
222        """
223        #look for dispersion parameters
224        toks = name.split('.')
225        if len(toks)==2:
226            for item in self.dispersion.keys():
227                if item.lower()==toks[0].lower():
228                    for par in self.dispersion[item]:
229                        if par.lower() == toks[1].lower():
230                            self.dispersion[item][par] = value
231                            return
232        # Look for standard parameter
233        for item in self.params.keys():
234            if item.lower()==name.lower():
235                self.params[item] = value
236                return
237       
238        raise ValueError, "Model does not contain parameter %s" % name
239             
240   
241    def _set_fixed_params(self):
242        """
243        Fill the self.fixed list with the model fixed list
244        """
245        for item in self.model.fixed:
246            if item.split('.')[0] in self.params.keys(): 
247                self.fixed.append(item)
248
249        self.fixed.sort()
250        pass         
251               
252    def run(self, x = 0.0):
253        """
254        Evaluate the model
255       
256        : param x: input q-value (float or [float, float] as [r, theta])
257        : return: (I value)
258        """
259
260        return self.model.run(x)
261
262    def runXY(self, x = 0.0):
263        """
264        Evaluate the model
265       
266        : param x: input q-value (float or [float, float] as [qx, qy])
267        : return: I value
268        """ 
269
270        return self.model.runXY(x)
271   
272    ## Now (May27,10) directly uses the model eval function
273    ## instead of the for-loop in Base Component.
274    def evalDistribution(self, x = []):
275        """
276        Evaluate the model in cartesian coordinates
277       
278        : param x: input q[], or [qx[], qy[]]
279        : return: scattering function P(q[])
280        """
281        # set effective radius and scaling factor before run
282        return self.model.evalDistribution(x)
283
284    def set_dispersion(self, parameter, dispersion):
285        """
286        Set the dispersion object for a model parameter
287       
288        : param parameter: name of the parameter [string]
289        :dispersion: dispersion object of type DispersionModel
290        """
291        value= None
292        try:
293            if parameter in self.model.dispersion.keys():
294                value= self.model.set_dispersion(parameter, dispersion)
295            self._set_dispersion()
296            return value
297        except:
298            raise 
Note: See TracBrowser for help on using the repository browser.