source: sasview/sansmodels/src/sans/models/SphereExpShellModel.py @ db08737

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 db08737 was a1b2471, checked in by Jae Cho <jhjcho@…>, 14 years ago

added sld plot for onion model and etc…

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