source: sasview/park_integration/AbstractFitEngine.py @ d831626

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

park integration test_large_model is not working for park

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