source: sasview/src/sas/models/CoreMultiShellModel.py @ e0c16ce

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 e0c16ce was e0c16ce, checked in by butler, 9 years ago

Fix sphinx compile issues (and a bunch of pyling white spaces) in
CoreMultiShellModel?

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