source: sasview/sansmodels/src/sans/models/ReflectivityIIModel.py @ 96656e3

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

update models due to changes of template

  • Property mode set to 100644
File size: 12.4 KB
Line 
1   
2from sans.models.BaseComponent import BaseComponent
3from sans.models.ReflAdvModel import ReflAdvModel
4from copy import deepcopy
5from math import floor
6from scipy.special import erf
7func_list = {'Erf(|nu|*z)':0, 'RPower(z^|nu|)':1, 'LPower(z^|nu|)':2, \
8                     'RExp(-|nu|*z)':3, 'LExp(-|nu|*z)':4}
9max_nshells = 10
10class ReflectivityIIModel(BaseComponent):
11    """
12    This multi-model is based on Parratt formalism and provides the capability
13    of changing the number of layers between 0 and 10.
14    """
15    def __init__(self, multfactor=1):
16        BaseComponent.__init__(self)
17        """
18        :param multfactor: number of layers in the model,
19        assumes 0<= n_layers <=10.
20        """
21
22        ## Setting  model name model description
23        self.description=""
24        model = ReflAdvModel()
25        self.model = model
26        self.name = "ReflectivityIIModel"
27        self.description=model.description
28        self.n_layers = multfactor
29        ## Define parameters
30        self.params = {}
31       
32        ## Parameter details [units, min, max]
33        self.details = {}
34       
35        # non-fittable parameters
36        self.non_fittable = model.non_fittable
37       
38        # list of function in order of the function number
39        self.fun_list = self._get_func_list()
40        ## dispersion
41        self._set_dispersion()
42        ## Define parameters
43        self._set_params()
44       
45        ## Parameter details [units, min, max]
46        self._set_details()
47       
48        #list of parameter that can be fitted
49        self._set_fixed_params() 
50        self.model.params['n_layers'] = self.n_layers
51       
52        ## functional multiplicity info of the model
53        # [int(maximum no. of functionality),"str(Titl),
54        # [str(name of function0),...], [str(x-asix name of sld),...]]
55        self.multiplicity_info = [max_nshells,"No. of Layers:",[],['Depth']]
56       
57   
58    def _clone(self, obj):
59        """
60        Internal utility function to copy the internal
61        data members to a fresh copy.
62        """
63        obj.params     = deepcopy(self.params)
64        obj.non_fittable     = deepcopy(self.non_fittable)
65        obj.description     = deepcopy(self.description)
66        obj.details    = deepcopy(self.details)
67        obj.dispersion = deepcopy(self.dispersion)
68        obj.model  = self.model.clone()
69
70        return obj
71   
72   
73    def _set_dispersion(self):
74        """
75        model dispersions
76        """ 
77        ##set dispersion from model
78        self.dispersion = {}
79                   
80
81    def _set_params(self):
82        """
83        Concatenate the parameters of the model to create
84        this model parameters
85        """
86        # rearrange the parameters for the given # of shells
87        for name , value in self.model.params.iteritems():
88            n = 0
89            pos = len(name.split('_'))-1
90            first_name = name.split('_')[0]
91            last_name = name.split('_')[pos]
92            if first_name == 'npts':
93                self.params[name]=value
94                continue
95            elif first_name == 'sldIM':
96                continue
97            elif first_name == 'func':
98                n= -1
99                while n<self.n_layers:
100                    n += 1
101                    if last_name == 'inter%s' % str(n): 
102                        self.params[name]=value
103                        continue
104           
105                #continue
106            elif last_name[0:5] == 'inter':
107                n= -1
108                while n<self.n_layers:
109                    n += 1
110                    if last_name == 'inter%s' % str(n):
111                        self.params[name]= value
112                        continue
113            elif last_name[0:4] == 'flat':
114                while n<self.n_layers:
115                    n += 1
116                    if last_name == 'flat%s' % str(n):
117                        self.params[name]= value
118                        continue
119            elif name == 'n_layers':
120                continue
121            else:
122                self.params[name]= value
123 
124        self.model.params['n_layers'] = self.n_layers   
125 
126        # set constrained values for the original model params
127        self._set_xtra_model_param()       
128
129    def _set_details(self):
130        """
131        Concatenate details of the original model to create
132        this model details
133        """
134        for name ,detail in self.model.details.iteritems():
135            if name in self.params.iterkeys():
136                self.details[name]= detail
137           
138   
139    def _set_xtra_model_param(self):
140        """
141        Set params of original model that are hidden from this model
142        """
143        # look for the model parameters that are not in param list
144        for key in self.model.params.iterkeys():
145            if key not in self.params.keys():
146                if  key.split('_')[0] == 'thick':
147                    self.model.setParam(key, 0)
148                    continue
149                if  key.split('_')[0] == 'func': 
150                        self.model.setParam(key, 0)
151                        continue
152
153                for nshell in range(self.n_layers,max_nshells):
154                    if key.split('_')[1] == 'flat%s' % str(nshell+1):
155                        try:
156                            if key.split('_')[0] == 'sld':
157                                value = self.model.params['sld_medium']
158                            elif key.split('_')[0] == 'sldIM':
159                                value = self.model.params['sldIM_medium']
160                            self.model.setParam(key, value)
161                        except: pass
162   
163    def _get_func_list(self):
164        """
165        Get the list of functions in each layer (shell)
166        """
167        #func_list = {}
168        return func_list
169       
170    def getProfile(self):
171        """
172        Get SLD profile
173       
174        : return: (z, beta) where z is a list of depth of the transition points
175                beta is a list of the corresponding SLD values
176        """
177        # max_pts for each layers
178        n_sub = self.params['npts_inter']
179        z = []
180        beta = []
181        sub_range = floor(n_sub/2.0)
182        z.append(0)
183        beta.append(self.params['sld_bottom0']) 
184       
185        z0 = 0.0
186        dz = 0.0
187        # for layers from the top
188        for n_lyr in range(1,self.n_layers+2):
189            i = n_lyr
190            # j=0 for interface, j=1 for flat layer
191            for j in range(0,2):
192                # interation for sub-layers
193                for n_s in range(0,n_sub):
194                    # for flat layer
195                    if j==1:
196                        if i==self.n_layers+1:
197                            break
198                        # shift half sub thickness for the first point
199                        z0 -= dz/2.0
200                        z.append(z0)
201                        sld_i = self.params['sld_flat%s'% str(i)]
202                        beta.append(sld_i)
203                        dz = self.params['thick_flat%s'% str(i)]
204                        z0 += dz
205                    else:
206                        dz = self.params['thick_inter%s'% str(i-1)]/n_sub
207                        nu = self.params['nu_inter%s'% str(i-1)]
208                        if n_s == 0:
209                            # shift half sub thickness for the point
210                            z0 += dz/2.0
211                        # decide which sld is which, sld_r or sld_l
212                        if i == 1:
213                            sld_l = self.params['sld_bottom0']
214                        else:
215                            sld_l = self.params['sld_flat%s'% str(i-1)]
216                        if i == self.n_layers+1:
217                            sld_r = self.params['sld_medium']
218                        else:
219                            sld_r = self.params['sld_flat%s'% str(i)]
220                        if sld_r == sld_l:
221                            sld_i = sld_r
222                        else:
223                            func_idx = self.params['func_inter%s'% str(i-1)]
224                            # calculate the sld
225                            sld_i = self._get_sld(func_idx, n_sub, n_s+0.5, nu,
226                                              sld_l, sld_r)
227                    # append to the list
228                    z.append(z0)
229                    beta.append(sld_i)
230                    if j==1: break
231                    else: z0 += dz
232        # put substrate and superstrate profile
233        z.append(z0)
234        beta.append(self.params['sld_medium']) 
235        z_ext = z0/5.0
236       
237        # put the extra points for the substrate
238        # and superstrate
239        z.append(z0+z_ext)
240        beta.append(self.params['sld_medium']) 
241        z.insert(0,-z_ext)
242        beta.insert(0,self.params['sld_bottom0']) 
243        # rearrange the profile for NR sld profile style
244        z = [z0 - x for x in z]
245        z.reverse()
246        beta.reverse() 
247        return z, beta
248   
249    def _get_sld(self, func_idx, n_sub, n_s, nu, sld_l, sld_r):
250        """
251        Get the function asked to build sld profile
252        : param func_idx: func type number
253        : param n_sub: total number of sub_layer
254        : param n_s: index of sub_layer
255        : param nu: coefficient of the function
256        : param sld_l: sld on the left side
257        : param sld_r: sld on the right side
258        : return: sld value, float
259        """
260        from sans.models.SLDCalFunc import SLDCalFunc
261        # sld_cal init
262        sld_cal = SLDCalFunc()
263        # set params
264        sld_cal.setParam('fun_type',func_idx)
265        sld_cal.setParam('npts_inter',n_sub)
266        sld_cal.setParam('shell_num',n_s)
267        sld_cal.setParam('nu_inter',nu)
268        sld_cal.setParam('sld_left',sld_l)
269        sld_cal.setParam('sld_right',sld_r)
270        # return sld value
271        return sld_cal.run()
272   
273    def setParam(self, name, value):
274        """
275        Set the value of a model parameter
276   
277        : param name: name of the parameter
278        : param value: value of the parameter
279        """
280        # set param to new model
281        self._setParamHelper( name, value)
282       
283        ## setParam to model
284        if name=='sld_medium':
285            # the sld_*** model.params not in params must set
286            # to value of sld_solv
287            for key in self.model.params.iterkeys():
288                if key not in self.params.keys()and key.split('_')[0] == 'sld':
289                        self.model.setParam(key, value)   
290       
291        self.model.setParam( name, value)
292
293    def _setParamHelper(self, name, value):
294        """
295        Helper function to setParam
296        """
297
298        # Look for standard parameter
299        for item in self.params.keys():
300            if item.lower()==name.lower():
301                self.params[item] = value
302                return
303       
304        raise ValueError, "Model does not contain parameter %s" % name
305             
306   
307    def _set_fixed_params(self):
308        """
309        Fill the self.fixed list with the model fixed list
310        """
311        pass         
312
313    def run(self, x = 0.0):
314        """
315        Evaluate the model
316       
317        :param x: input q, or [q,phi]
318       
319        :return: scattering function P(q)
320       
321        """
322
323        return self.model.run(x)
324
325    def runXY(self, x = 0.0):
326        """
327        Evaluate the model
328       
329        : param x: input q-value (float or [float, float] as [qx, qy])
330        : return: scattering function value
331        """ 
332
333        return self.model.runXY(x)
334   
335    ## Now (May27,10) directly uses the model eval function
336    ## instead of the for-loop in Base Component.
337    def evalDistribution(self, x = []):
338        """
339        Evaluate the model in cartesian coordinates
340       
341        : param x: input q[], or [qx[], qy[]]
342        : return: scattering function P(q[])
343        """
344        # set effective radius and scaling factor before run
345        return self.model.evalDistribution(x)
346    def calculate_ER(self):
347        """
348        """
349        return self.model.calculate_ER()
350    def set_dispersion(self, parameter, dispersion):
351        """
352        Set the dispersion object for a model parameter
353       
354        : param parameter: name of the parameter [string]
355        :dispersion: dispersion object of type DispersionModel
356        """
357        pass
Note: See TracBrowser for help on using the repository browser.