source: sasview/sansmodels/src/sans/models/FractalCoreShellModel.py @ f80236f

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

replaced math.pow to numpy.power since math.pow is not working with list of x values(remember we use the list in fitting for speed)

  • Property mode set to 100644
File size: 8.4 KB
RevLine 
[8f20419d]1   
2from sans.models.BaseComponent import BaseComponent
3from sans.models.CoreShellModel import CoreShellModel
4from scipy.special import gammaln
[18695bf]5from math import exp, sin, atan
6from numpy import power
[8f20419d]7from copy import deepcopy
8
9class FractalCoreShellModel(BaseComponent):
10    """
11    Class that evaluates a FractalCoreShellModel
12    List of default parameters:
13    volfraction     = 0.05
14    radius          = 20.0 [A]
15    thickness       = 5.0 [A]
16    frac_dim        = 2.0
17    cor_length      = 100 [A]
18    core_sld        = 3.5e-006 [1/A^(2)]
19    shell_sld       = 1.0e-006 [1/A^(2)]
20    solvent_sld     = 6.35e-006 [1/A^(2)]
21    background      = 0.0 [1/cm]
22    """
23    def __init__(self):
24        BaseComponent.__init__(self)
25
26        ## Setting  model name model description
27        model = CoreShellModel()
28        self.description=model
29       
30        self.model = model
31        self.name = "FractalCoreShell"
32        self.description="""Scattering  from a fractal structure
33        with a primary building block of a spherical particle
34        with particle with a core-shell structure.
35        Note: Setting the (core) radius polydispersion with a Schulz
36        distribution is equivalent to the FractalPolyCore function
37        in NIST/Igor Package.
38        List of parameters:
39        volfraction: volume fraction of building block spheres
40        radius: radius of building block
41        thickness: shell thickness
42        frac_dim:  fractal dimension
43        cor_length: correlation length of fractal-like aggregates
44        core_sld: SLD of building block
45        shell_sld: SLD of shell
46        solvent_sld: SLD of matrix or solution
47        background: flat background"""
48       
49        ## Define parameters
50        self.params = {}
51
52        ## Parameter details [units, min, max]
53        self.details = {}
54       
55        # non-fittable parameters
56        self.non_fittable = model.non_fittable
57       
58        ## dispersion
59        self._set_dispersion()
60        ## Define parameters
61        self._set_params()
62       
63        ## Parameter details [units, min, max]
64        self._set_details()
65
66        ## parameters with orientation: can be removed since there is no orientational params
67        for item in self.model.orientation_params:
68            self.orientation_params.append(item)
69               
70    def _fractalcore(self,x):
71        """
72        Define model function
73       
74        return S(q): Fractal Structure
75        """
76        # set local variables
77        Df = self.params['frac_dim']
78        corr = self.params['cor_length']
79        r0 = self.params['radius']
80        #calculate S(q)
81        sq = Df*exp(gammaln(Df-1.0))*sin((Df-1.0)*atan(x*corr))
[18695bf]82        sq /= power((x*r0),Df) * power((1.0 + 1.0/(x*corr*x*corr)),((Df-1)/2))
[8f20419d]83        sq += 1.0
84        return sq
85
86    def _clone(self, obj):
87        """
88        Internal utility function to copy the internal
89        data members to a fresh copy.
90        """
91        obj.params     = deepcopy(self.params)
92        obj.description     = deepcopy(self.description)
93        obj.details    = deepcopy(self.details)
94        obj.dispersion = deepcopy(self.dispersion)
95        obj.model  = self.model.clone()
96
97        return obj
98   
99    def _set_dispersion(self):
100        """
101        model dispersions
102        """ 
103        ##set dispersion from model
104        for name , value in self.model.dispersion.iteritems():     
105            self.dispersion[name]= value
106                             
107    def _set_params(self):
108        """
109        Concatenate the parameters of the model to create
110        this model parameters
111        """
112        # rearrange the parameters for the given # of shells
113        for name , value in self.model.params.iteritems():
114            if name == 'scale':
115                value = 0.05   
116            elif name == 'radius':
117                value = 20.0
118            elif name == 'thickness':
119                value = 5.0
120            elif name == 'core_sld':
121                value = 3.5e-06
122            elif name == 'shell_sld':
123                value = 1.0e-06
124            elif name == 'solvent_sld':
125                value = 6.35e-06
126            elif name == 'background':
127                value = 0.0
128            self.model.params[name]= value
129            if name  == 'scale':
130                name = 'volfraction'
131            self.params[name]= value
132        self.params['frac_dim'] = 2.0
133        self.params['cor_length'] = 100.0 
134 
135    def _set_details(self):
136        """
137        Concatenate details of the original model to create
138        this model details
139        """
140        for name ,detail in self.model.details.iteritems():
141            if name in self.params.iterkeys():
142                if name == 'scale':
143                    name = 'volfraction'
144                self.details[name]= detail
145        self.details['frac_dim']   = ['', None, None]
146        self.details['cor_length'] = ['[A]', None, None] 
147
148
149    def setParam(self, name, value):
150        """
151        Set the value of a model parameter
152   
153        : param name: name of the parameter
154        : param value: value of the parameter
155        """
156        # set param to new model
157        self._setParamHelper(name, value)
158
159        if name == 'volfraction':
160            name = 'scale'
161        # model.setParam except the two names below
162        if name != 'frac_dim' and name != 'cor_length':
163            # background is always 0.0 in the coreshellmodel
164            if name == 'background':
165                value = 0.0
166            self.model.setParam(name, value)
167
168    def _setParamHelper(self, name, value):
169        """
170        Helper function to setParam
171        """
172        #look for dispersion parameters
173        toks = name.split('.')
174        if len(toks)==2:
175            for item in self.dispersion.keys():
176                if item.lower()==toks[0].lower():
177                    for par in self.dispersion[item]:
178                        if par.lower() == toks[1].lower():
179                            self.dispersion[item][par] = value
180                            return
181        # Look for standard parameter
182        for item in self.params.keys():
183            if item.lower()==name.lower():
184                self.params[item] = value
185                return
186       
187        raise ValueError, "Model does not contain parameter %s" % name
188             
189     
190               
191    def run(self, x = 0.0):
192        """
193        Evaluate the model
194       
195        : param x: input q-value (float or [float, float] as [r, theta])
196        : return: (DAB value)
197        """
198        if x.__class__.__name__ == 'list':
199            # Take absolute value of Q, since this model is really meant to
200            # be defined in 1D for a given length of Q
201            #qx = math.fabs(x[0]*math.cos(x[1]))
202            #qy = math.fabs(x[0]*math.sin(x[1]))
203            return self.params['background']+self._fractalcore(x[0])*self.model.run(x)
204        elif x.__class__.__name__ == 'tuple':
205            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
206        else:
207            return self.params['background']+self._fractalcore(x)*self.model.run(x)
208
209
210        return self.params['background']+self._fractalcore(x)*self.model.run(x)
211
212    def runXY(self, x = 0.0):
213        """
214        Evaluate the model
215       
216        : param x: input q-value (float or [float, float] as [qx, qy])
217        : return: DAB value
218        """ 
219        if x.__class__.__name__ == 'list':
220            q = math.sqrt(x[0]**2 + x[1]**2)
221            return self.params['background']+self._fractalcore(q)*self.model.runXY(x)
222        elif x.__class__.__name__ == 'tuple':
223            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
224        else:
225            return self.params['background']+self._fractalcore(x)*self.model.runXY(x)
226
227
228    def set_dispersion(self, parameter, dispersion):
229        """
230        Set the dispersion object for a model parameter
231       
232        : param parameter: name of the parameter [string]
233        :dispersion: dispersion object of type DispersionModel
234        """
235        value= None
236        try:
237            if parameter in self.model.dispersion.keys():
238                value= self.model.set_dispersion(parameter, dispersion)
239            self._set_dispersion()
240            return value
241        except:
242            raise 
Note: See TracBrowser for help on using the repository browser.