source: sasview/src/sas/models/UnifiedPowerRgModel.py @ 27ab091

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 27ab091 was 79492222, checked in by krzywon, 10 years ago

Changed the file and folder names to remove all SANS references.

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