source: sasview/sansmodels/src/sans/models/UnifiedPowerRgModel.py @ 2e862a0

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 2e862a0 was 29100cb, checked in by Jae Cho <jhjcho@…>, 14 years ago

last scattering model added

  • Property mode set to 100644
File size: 8.3 KB
Line 
1   
2from sans.models.BaseComponent import BaseComponent
3from math import pow,exp, sqrt
4from scipy.special import erf
5max_level_n = 7
6class UnifiedPowerRgModel(BaseComponent):
7    """
8    This model is based on Exponential/Power-law fit method developed
9    by G. Beaucage
10    """
11    def __init__(self, multfactor=1):
12        BaseComponent.__init__(self)
13        """
14        :param multfactor: number of levels in the model, assumes 0<= level# <=5.
15        """
16
17        ## Setting  model name model description
18        self.name = "UnifiedPowerRg"
19        self.description="""Multiple Levels of Unified Exponential/Power-law Method.
20        Up to Level 6 is provided.
21        Note; the additional Level 0 is an inverse linear function,
22        i.e., y = scale/x + background.
23        The Level N is defined as
24        y = background + scale * Sum(1..N)[G_i*exp(-x^2*Rg_i^2/3)
25        + B_i/x^(power_i)*(erf(x*Rg_i/sqrt(6))^(3*power_i))].
26        Ref:
27        G. Beaucage (1995).  J. Appl. Cryst., vol. 28, p717-728.
28        G. Beaucage (1996).  J. Appl. Cryst., vol. 29, p134-146.
29        """
30        self.level_num = multfactor
31        ## Define parameters
32        self.params = {}
33
34        ## Parameter details [units, min, max]
35        self.details = {}
36       
37        # non-fittable parameters
38        self.non_fittable = []
39
40        # list of function in order of the function number
41        self.fun_list = self._get_func_list()
42        ## dispersion
43        self._set_dispersion()
44        ## Define parameters
45        self._set_params()
46       
47        ## Parameter details [units, min, max]
48        self._set_details()
49       
50        #list of parameter that can be fitted
51        self._set_fixed_params() 
52       
53        ## functional multiplicity of the model
54        self.multiplicity_info = [max_level_n,"Level No.:",[],[]]
55   
56    def _unifiedpowerrg(self,x):
57        """
58        Scattering function
59       
60        :param x: q value(s)
61        :return answer: output of the function
62        """
63        # common parameters for the model functions
64        bkg = self.params['background'] 
65        scale = self.params['scale']
66        l_num = self.level_num
67        # set default output
68        answer = 0.0
69        # Set constant on lebel zero (special case)
70        if l_num == 0:
71            answer = scale / x + bkg
72            return answer
73        # rearrange the parameters for the given label no.
74        for ind in range(1,l_num+1):
75            # get exp term
76            exp_now = exp(-pow(x*self.params['Rg%s'% ind],2)/3.0)
77            # get erf term
78            erf_now = erf(x*self.params['Rg%s'% ind]/sqrt(6.0))
79            # get power term
80            pow_now = pow((erf_now*erf_now*erf_now/x),self.params['power%s'% ind])
81            # get next exp term only if it exists
82            try:
83                exp_next = exp(-pow(x*self.params['Rg%s'% (ind+1)],2)/3.0)
84            except:
85                exp_next = 1.0
86            # get to the calculation
87            answer += self.params['G%s'% ind]*exp_now + self.params['B%s'% ind]* \
88                            exp_next * pow_now
89        # take care of the singular point
90        if x == 0.0:
91            answer = 0.0
92            for ind in range(1,l_num+1):
93                answer += self.params['G%s'% ind]
94        # get scaled
95        answer *= scale
96        # add background
97        answer += bkg
98        return answer
99       
100    def _set_dispersion(self):
101        """
102        model dispersions
103        """ 
104        ##set dispersion from model
105        self.dispersion = {}
106                   
107
108    def _set_params(self):
109        """
110        Concatenate the parameters of the model to create
111        this model parameters
112        """
113        # common parameters for the model functions
114        self.params['background'] = 0.0
115        self.params['scale'] = 1.0
116        l_num = self.level_num
117        # rearrange the parameters for the given label no.
118        for ind in range(0,l_num+1):
119            if ind == 0:
120                continue
121            # multiple factor for higher labels
122            mult = 1.0
123            mul_pow = 1.0
124            if ind != l_num:
125                mult = 10.0 * 4.0/3.0
126                mul_pow = 2.0
127            # Set reasonably define default values that consistent
128            # w/NIST for label #1
129            self.params['G%s'% ind] = 0.3*mult*pow(10, \
130                            (l_num+1 - float('%s'% ind)))
131            self.params['Rg%s'% ind] = 21.0/mult*pow(10, \
132                              (l_num - float('%s'% ind)))
133            self.params['B%s'% ind] = 6e-03/mult*pow(10, \
134                           -(l_num+1 - float('%s'% ind)))
135            self.params['power%s'% ind] = 2.0 * mul_pow
136           
137
138    def _set_details(self):
139        """
140        Concatenate details of the original model to create
141        this model details
142        """
143        # common parameters for the model functions
144        self.details['background'] = ['[1/cm]', None, None]
145        self.details['scale'] = ['', None, None]
146        # rearrange the parameters for the given label no.
147        for ind in range(0,self.level_num+1):
148            if ind == 0:
149                continue
150            self.details['G%s'% ind] = ['[1/(cm.sr)]', None, None]
151            self.details['Rg%s'% ind] = ['[A]', None, None]
152            self.details['B%s'% ind] = ['[1/(cm.sr)]', None, None]
153            self.details['power%s'% ind] = ['', None, None]
154
155   
156    def _get_func_list(self):
157        """
158        Get the list of functions in each cases
159        """
160        func_list = {}
161        return func_list
162       
163    def getProfile(self):
164        """
165        Get SLD profile
166       
167        : return: None, No SLD profile supporting for this model
168        """
169        return None
170       
171    def setParam(self, name, value):
172        """
173        Set the value of a model parameter
174   
175        : param name: name of the parameter
176        : param value: value of the parameter
177        """
178        # set param to new model
179        self._setParamHelper(name, value)
180
181    def _setParamHelper(self, name, value):
182        """
183        Helper function to setParam
184        """
185
186        # Look for standard parameter
187        for item in self.params.keys():
188            if item.lower()==name.lower():
189                self.params[item] = value
190                return
191       
192        raise ValueError, "Model does not contain parameter %s" % name
193             
194   
195    def _set_fixed_params(self):
196        """
197        Fill the self.fixed list with the model fixed list
198        """
199        pass         
200
201               
202    def run(self, x = 0.0):
203        """
204        Evaluate the model
205       
206        : param x: input q-value (float or [float, float] as [r, theta])
207        : return: (DAB value)
208        """
209        if x.__class__.__name__ == 'list':
210            # Take absolute value of Q, since this model is really meant to
211            # be defined in 1D for a given length of Q
212            #qx = math.fabs(x[0]*math.cos(x[1]))
213            #qy = math.fabs(x[0]*math.sin(x[1]))
214            return self._unifiedpowerrg(x)
215        elif x.__class__.__name__ == 'tuple':
216            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
217        else:
218            return self._unifiedpowerrg(x)
219
220
221        return self._unifiedpowerrg(x)
222
223    def runXY(self, x = 0.0):
224        """
225        Evaluate the model
226       
227        : param x: input q-value (float or [float, float] as [qx, qy])
228        : return: DAB value
229        """ 
230        if x.__class__.__name__ == 'list':
231            q = math.sqrt(x[0]**2 + x[1]**2)
232            return self._unifiedpowerrg(x)
233        elif x.__class__.__name__ == 'tuple':
234            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
235        else:
236            return self._unifiedpowerrg(x)
237
238    def calculate_ER(self):
239        """
240        """
241        # Not implemented!!!
242        pass
243   
244    def set_dispersion(self, parameter, dispersion):
245        """
246        Set the dispersion object for a model parameter
247       
248        : param parameter: name of the parameter [string]
249        :dispersion: dispersion object of type DispersionModel
250        """
251        pass
Note: See TracBrowser for help on using the repository browser.