source: sasview/sansmodels/src/igor_wrapper/test/Averager2D.py @ 27976fd0

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 27976fd0 was ae3ce4e, checked in by Mathieu Doucet <doucetm@…>, 17 years ago

Moving sansmodels to trunk

  • Property mode set to 100644
File size: 10.3 KB
Line 
1"""
2    Class to average an oriented model
3    Options:
4        - flat average in one or both coordinates (specified)
5        - given distribution in one or both coordinates (specified)
6       
7    Uses DisperseModel to allow for polydispersity
8"""
9
10from sans.models.BaseComponent import BaseComponent
11import copy, os, math
12   
13class Averager2D(BaseComponent):
14   
15
16    def __init__(self):
17        BaseComponent.__init__(self)
18        self.params = {}
19        self.model      = None
20        self.dispersed  = None
21        self.phi_file   = None
22        self.theta_file = None
23        self.phi_name   = None
24        self.theta_name = None
25        self.phi_on     = False
26        self.theta_on   = False
27       
28        self.phi_data   = None
29        self.theta_data = None
30        self.dispersion = []
31        self.runXY      = self.run_oriented
32        self.run        = self.run_oriented
33        self.disp_model_run = None
34        self.details    = None
35
36    def __str__(self):
37        info  = "%s (%s)\n" % (self.name, self.model.__class__.__name__)
38        info += "Pars: %s\n" % self.model.params
39        info += "Disp: %s\n" % self.dispersion
40        info += "Disp: %s\n" % self.dispersed.params
41        return info
42
43    def clone(self):
44        obj            = Averager2D()
45        obj.params     = copy.deepcopy(self.params)
46        obj.details    = copy.deepcopy(self.details)
47        obj.model      = self.model.clone()
48        obj.phi_file   = copy.deepcopy(self.phi_file)
49        obj.theta_file = copy.deepcopy(self.theta_file)
50        obj.phi_name   = copy.deepcopy(self.phi_name)
51        obj.theta_name = copy.deepcopy(self.theta_name)
52        obj.name       = copy.deepcopy(self.name)
53        obj.phi_on = self.phi_on
54        obj.theta_on = self.theta_on
55        obj.dispersion = copy.deepcopy(self.dispersion)
56        obj.update_functor()
57        return obj   
58
59    def set_model(self, model):
60        self.name = model.name
61        self.model = model
62        self.params = model.params
63        self.details = model.details
64        retval = self._find_angles()
65        self.update_functor()
66        self.disp_model_run = self.model.runXY
67        return retval
68       
69    def setParam(self, name, value):
70        # Keep a local copy for badly implemented code
71        # that access params directly
72        #TODO: fix that!
73        if name.lower() in self.params:
74            self.params[name.lower()] = value
75        return self.model.setParam(name, value)
76       
77    def getParam(self, name):
78        return self.model.getParam(name)
79
80    def _find_angles(self):
81        """
82            Find which model parameters represent
83            theta and phi
84            @return: True if at least one angle was found
85        """
86        self.theta_name = None
87        self.phi_name   = None
88        for item in self.model.params:
89            if item.lower().count("theta")>0:
90                self.theta_name = item
91            elif item.lower().count("phi")>0:
92                self.phi_name = item
93               
94        if self.theta_name == None and self.phi_name == None:
95            return False
96        return True
97       
98    def setPhiFile(self, path):
99        """
100            Check the validity of a path and store it
101            @param path: file path
102            @return: True if all OK, False if can't be set
103        """
104       
105        # If it's the same file, do nothing
106        if self.phi_file == path:
107            return True
108       
109        if path==None or self.phi_name == None:
110            self.phi_file = None
111            self.phi_data = None
112            self.phi_on   = False
113            self.update_functor()
114        elif os.path.isfile(path):
115            self.phi_file = path
116            #self.phi_data = self.read_file(path)
117            self.phi_on = True
118            self.update_functor()
119        else:
120            raise ValueError, "%s is not a file" % path
121       
122        if self.phi_name == None:
123            return False
124        else:
125            return True
126
127    def read_file(self, path):
128        input_f = open(path, 'r')
129        buff = input_f.read()
130        lines = buff.split('\n')
131       
132        angles = []
133       
134        for line in lines:
135            toks = line.split()
136            if len(toks)==2:
137                try:
138                    angle = float(toks[0])
139                    weight = float(toks[1])
140                except:
141                    # Skip non-data lines
142                    pass
143                angles.append([angle, weight])
144        return angles
145               
146
147    def setThetaFile(self, path):
148        """
149            Check the validity of a path and store it
150            @param path: file path
151            @return: True if all OK, False if can't be set
152        """
153       
154        # If it's the same file, do nothing
155        if self.theta_file == path:
156            return True
157       
158        if path==None or self.theta_name == None:
159            self.theta_file = None
160            self.theta_data = None
161            self.theta_on   = False
162            self.update_functor()
163        elif os.path.isfile(path):
164            self.theta_file = path
165            #self.theta_data = self.read_file(path)
166            self.theta_on = True
167            self.update_functor()
168        else:
169            raise ValueError, "%s is not a file" % path
170
171        if self.theta_name == None:
172            return False
173        else:
174            return True
175
176    def update_functor(self):
177        # Protect against empty model
178        if self.model==None:
179            return
180       
181        self.set_dispersity(self.dispersion)
182        #phi_points = [[self.model.getParam(self.phi_name), 1.0]]
183        #theta_points = [[self.model.getParam(self.theta_name), 1.0]]
184       
185       # Initialize theta points to visit
186        if self.theta_on:
187            # Check whether we have the data
188            if not self.theta_file == None and self.theta_data == None:
189                self.theta_data = self.read_file(self.theta_file)
190            elif not self.model == None:
191                self.theta_data = [[self.model.getParam(self.phi_name), 1.0]]
192            else:
193                self.theta_data = []
194           
195        # Initialize phi points to visit
196        if self.phi_on:
197            # Check whether we have the data
198            if not self.phi_file == None and self.phi_data == None:
199                self.phi_data = self.read_file(self.phi_file)
200            elif not self.model == None:
201                self.phi_data = [[self.model.getParam(self.theta_name), 1.0]]
202            else:
203                self.phi_data = []
204               
205        if self.phi_on and self.theta_on:
206            self.runXY = self.run_theta_phi
207        elif not self.phi_on and self.theta_on:
208            self.runXY = self.run_theta
209        elif not self.theta_on and self.phi_on:
210            self.runXY = self.run_phi
211        else:
212            self.runXY = self.run_oriented
213               
214    def get_dispersity(self):
215        return self.dispersion
216   
217    def set_dispersity(self, disp):
218        from sans.models.DisperseModel import DisperseModel
219       
220        if len(disp) == 0 and len(self.dispersion) == 0:
221            self.disp_model_run = self.model.runXY
222            return False
223       
224        self.dispersion = disp
225        if len(self.dispersion)==0:
226            self.disp_model_run = self.model.runXY
227            self.dispersed = None
228           
229            return True
230       
231       
232        name_list = []
233        val_list  = []
234        npts = 0
235        for item in disp:
236            name_list.append(item[0])
237            val_list.append(item[1])
238            # For now, us largest
239            if item[2]>npts:
240                npts = item[2]
241           
242        self.dispersed = DisperseModel(self.model, name_list, val_list)
243        self.dispersed.setParam('n_pts', npts)
244        self.disp_model_run = self.dispersed.runXY
245       
246        return True
247               
248    def run_oriented(self, x=0):
249        return self.disp_model_run(x)
250   
251    def run_phi(self, x=0):
252        sum  = 0
253        norm = 0
254        background = 0
255       
256        # If we have a background, perform the average
257        # only with bck=0 and add it at the end
258        if "background" in self.model.getParamList():
259            background = self.model.getParam('background')
260            self.model.setParam('background', 0.0)
261
262        for ph_i in self.phi_data:
263            self.model.setParam(self.phi_name, ph_i[0])
264            sum += self.disp_model_run(x) * ph_i[1]
265            norm += ph_i[1]
266               
267        # Restore original background value
268        if "background" in self.model.getParamList():
269            self.model.setParam('background', background)
270
271        return sum / norm + background
272   
273    def run_theta(self, x=0):
274        sum  = 0
275        norm = 0
276        background = 0
277       
278        # If we have a background, perform the average
279        # only with bck=0 and add it at the end
280        if "background" in self.model.getParamList():
281            background = self.model.getParam('background')
282            self.model.setParam('background', 0.0)
283           
284        for th_i in self.theta_data:
285            self.model.setParam(self.theta_name, th_i[0])
286            sum += self.disp_model_run(x) * math.sin(th_i[0]) * th_i[1]
287            norm += th_i[1]
288               
289        # Restore original background value
290        if "background" in self.model.getParamList():
291            self.model.setParam('background', background)
292
293        return sum / norm + background
294   
295    def run_theta_phi(self, x=0):
296        sum  = 0
297        norm = 0
298        background = 0
299       
300        # If we have a background, perform the average
301        # only with bck=0 and add it at the end
302        if "background" in self.model.getParamList():
303            background = self.model.getParam('background')
304            self.model.setParam('background', 0.0)
305
306        for th_i in self.theta_data:
307            self.model.setParam(self.theta_name, th_i[0])
308           
309            for ph_i in self.phi_data:
310                self.model.setParam(self.phi_name, ph_i[0])
311                sum += self.disp_model_run(x) * math.sin(th_i[0]) * ph_i[1] * th_i[1]
312                norm += ph_i[1] * th_i[1]
313       
314        # Restore original background value
315        if "background" in self.model.getParamList():
316            self.model.setParam('background', background)
317       
318        return sum / norm + background       
319
320   
Note: See TracBrowser for help on using the repository browser.