source: sasview/park_integration/AbstractFitEngine.py @ c7bc3e7

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 c7bc3e7 was 388309d, checked in by Gervaise Alina <gervyh@…>, 16 years ago

park_integration working better for large model

  • Property mode set to 100644
File size: 10.0 KB
Line 
1
2import park,numpy
3
4class SansParameter(park.Parameter):
5    """
6        SANS model parameters for use in the PARK fitting service.
7        The parameter attribute value is redirected to the underlying
8        parameter value in the SANS model.
9    """
10    def __init__(self, name, model):
11         self._model, self._name = model,name
12         self.set(model.getParam(name))
13         
14    def _getvalue(self): return self._model.getParam(self.name)
15   
16    def _setvalue(self,value): 
17        self._model.setParam(self.name, value)
18       
19    value = property(_getvalue,_setvalue)
20   
21    def _getrange(self):
22        lo,hi = self._model.details[self.name][1:]
23        if lo is None: lo = -numpy.inf
24        if hi is None: hi = numpy.inf
25        return lo,hi
26   
27    def _setrange(self,r):
28        self._model.details[self.name][1:] = r
29    range = property(_getrange,_setrange)
30
31
32class Model(object):
33    """
34        PARK wrapper for SANS models.
35    """
36    def __init__(self, sans_model, **kw):
37        self.model = sans_model
38        self.name=sans_model.name
39        #print "ParkFitting:sans model",self.model
40        self.sansp = sans_model.getParamList()
41        #print "ParkFitting: sans model parameter list",sansp
42        self.parkp = [SansParameter(p,sans_model) for p in self.sansp]
43        #print "ParkFitting: park model parameter ",self.parkp
44        self.parameterset = park.ParameterSet(sans_model.name,pars=self.parkp)
45        self.pars=[]
46     
47    #def __call__(self, x, pars=[]):
48    #    return self.eval(x)   
49    def getParams(self,fitparams):
50        list=[]
51        self.pars=[]
52        self.pars=fitparams
53        for item in fitparams:
54            for element in self.parkp:
55                 if element.name ==str(item):
56                     list.append(element.value)
57        #print "abstractfitengine: getparams",list
58        return list
59   
60    def setParams(self, params):
61        list=[]
62        for item in self.parkp:
63            list.append(item.name)
64        list.sort()
65        for i in range(len(params)):
66            self.parkp[i].value = params[i]
67            print "abstractfitengine: set-params",list[i],params[i]
68           
69            self.model.setParam(list[i],params[i])
70 
71    def eval(self,x):
72       
73        return self.model.runXY(x)
74   
75    #def set(self, **kw):
76        #"""
77            #Set the initial value for a set of parameters.
78            #E.g., model.set(width=3,center=5)
79        #"""
80        #print "Abstractfitting : set called"
81        # This is a convenience funciton for the user.
82        #
83        #for k,v in kw.items():
84        #    self.parameterset[k].set(v)
85   
86class Data(object):
87    """ Wrapper class  for SANS data """
88    def __init__(self,x=None,y=None,dy=None,dx=None,sans_data=None):
89       
90        if  sans_data !=None:
91            self.x= sans_data.x
92            self.y= sans_data.y
93            self.dx= sans_data.dx
94            self.dy= sans_data.dy
95           
96        elif (x!=None and y!=None and dy!=None):
97                self.x=x
98                self.y=y
99                self.dx=dx
100                self.dy=dy
101        else:
102            raise ValueError,\
103            "Data is missing x, y or dy, impossible to compute residuals later on"
104        self.qmin=None
105        self.qmax=None
106       
107    def setFitRange(self,mini=None,maxi=None):
108        """ to set the fit range"""
109        self.qmin=mini
110        self.qmax=maxi
111    def getFitRange(self):
112         return self.qmin, self.qmax
113    def residuals(self, fn):
114        """ @param fn: function that return model value
115            @return residuals
116        """
117        x,y,dy = [numpy.asarray(v) for v in (self.x,self.y,self.dy)]
118        if self.qmin==None and self.qmax==None: 
119            fx =[fn(v) for v in x]
120            return (y - fx)/dy
121        else:
122            idx = (x>=self.qmin) & (x <= self.qmax)
123            fx = [fn(item)for item in x[idx ]]
124            return (y[idx] - fx)/dy[idx]
125         
126           
127         
128    def residuals_deriv(self, model, pars=[]):
129        """
130            @return residuals derivatives .
131            @note: in this case just return empty array
132        """
133        return []
134   
135class sansAssembly:
136    def __init__(self,Model=None , Data=None):
137       self.model = Model
138       self.data  = Data
139       self.res=[]
140    def chisq(self, params):
141        """
142            Calculates chi^2
143            @param params: list of parameter values
144            @return: chi^2
145        """
146        sum = 0
147        for item in self.res:
148            sum += item*item
149        return sum
150    def __call__(self,params):
151        self.model.setParams(params)
152        self.res= self.data.residuals(self.model.eval)
153        return self.res
154   
155class FitEngine:
156    def __init__(self):
157        self.paramList=[]
158    def _concatenateData(self, listdata=[]):
159        """ 
160            _concatenateData method concatenates each fields of all data contains ins listdata.
161            @param listdata: list of data
162           
163            @return Data:
164               
165            @raise: if listdata is empty  will return None
166            @raise: if data in listdata don't contain dy field ,will create an error
167            during fitting
168        """
169        if listdata==[]:
170            raise ValueError, " data list missing"
171        else:
172            xtemp=[]
173            ytemp=[]
174            dytemp=[]
175            self.mini=None
176            self.maxi=None
177               
178            for data in listdata:
179                mini,maxi=data.getFitRange()
180                if self.mini==None and self.maxi==None:
181                    self.mini=mini
182                    self.maxi=maxi
183                else:
184                    if mini < self.mini:
185                        self.mini=mini
186                    if self.maxi < maxi:
187                        self.maxi=maxi
188                       
189                   
190                for i in range(len(data.x)):
191                    xtemp.append(data.x[i])
192                    ytemp.append(data.y[i])
193                    if data.dy is not None and len(data.dy)==len(data.y):   
194                        dytemp.append(data.dy[i])
195                    else:
196                        raise RuntimeError, "Fit._concatenateData: y-errors missing"
197            #return xtemp, ytemp,dytemp
198            data= Data(x=xtemp,y=ytemp,dy=dytemp)
199            data.setFitRange(self.mini, self.maxi)
200            return data
201    def set_model(self,model,name,Uid,pars=[]):
202        if len(pars) >0:
203            self.paramList = []
204            if model==None:
205                raise ValueError, "AbstractFitEngine: Specify parameters to fit"
206            else:
207                model.model.name = name
208                model.name = name
209                self.paramList=pars
210            #A fitArrange is already created but contains dList only at Uid
211            if self.fitArrangeList.has_key(Uid):
212                self.fitArrangeList[Uid].set_model(model)
213            else:
214            #no fitArrange object has been create with this Uid
215                fitproblem = FitArrange()
216                fitproblem.set_model(model)
217                self.fitArrangeList[Uid] = fitproblem
218        else:
219            raise ValueError, "park_integration:missing parameters"
220   
221    def set_data(self,data,Uid,qmin=None,qmax=None):
222        """ Receives plottable, creates a list of data to fit,set data
223            in a FitArrange object and adds that object in a dictionary
224            with key Uid.
225            @param data: data added
226            @param Uid: unique key corresponding to a fitArrange object with data
227            """
228        if qmin !=None and qmax !=None:
229            data.setFitRange(mini=qmin,maxi=qmax)
230        #A fitArrange is already created but contains model only at Uid
231        if self.fitArrangeList.has_key(Uid):
232            self.fitArrangeList[Uid].add_data(data)
233        else:
234        #no fitArrange object has been create with this Uid
235            fitproblem= FitArrange()
236            fitproblem.add_data(data)
237            self.fitArrangeList[Uid]=fitproblem   
238   
239    def get_model(self,Uid):
240        """
241            @param Uid: Uid is key in the dictionary containing the model to return
242            @return  a model at this uid or None if no FitArrange element was created
243            with this Uid
244        """
245        if self.fitArrangeList.has_key(Uid):
246            return self.fitArrangeList[Uid].get_model()
247        else:
248            return None
249   
250    def remove_Fit_Problem(self,Uid):
251        """remove   fitarrange in Uid"""
252        if self.fitArrangeList.has_key(Uid):
253            del self.fitArrangeList[Uid]
254
255   
256class FitArrange:
257    def __init__(self):
258        """
259            Class FitArrange contains a set of data for a given model
260            to perform the Fit.FitArrange must contain exactly one model
261            and at least one data for the fit to be performed.
262            model: the model selected by the user
263            Ldata: a list of data what the user wants to fit
264           
265        """
266        self.model = None
267        self.dList =[]
268       
269    def set_model(self,model):
270        """
271            set_model save a copy of the model
272            @param model: the model being set
273        """
274        self.model = model
275       
276    def add_data(self,data):
277        """
278            add_data fill a self.dList with data to fit
279            @param data: Data to add in the list 
280        """
281        if not data in self.dList:
282            self.dList.append(data)
283           
284    def get_model(self):
285        """ @return: saved model """
286        return self.model   
287     
288    def get_data(self):
289        """ @return:  list of data dList"""
290        return self.dList
291     
292    def remove_data(self,data):
293        """
294            Remove one element from the list
295            @param data: Data to remove from dList
296        """
297        if data in self.dList:
298            self.dList.remove(data)
299   
300
301
302   
Note: See TracBrowser for help on using the repository browser.