source: sasview/sansmodels/src/sans/models/UnifiedPowerRgModel.py @ 0d86fecb

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