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

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 285c3bb was 279e371, checked in by Mathieu Doucet <doucetm@…>, 13 years ago

Fixing code style problems

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