source: sasview/park_integration/ParkFitting.py @ 94b44293

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

changed done on AbstractFit? engine scipyfit parkfit

  • Property mode set to 100644
File size: 6.9 KB
Line 
1"""
2    @organization: ParkFitting module contains SansParameter,Model,Data
3    FitArrange, ParkFit,Parameter classes.All listed classes work together to perform a
4    simple fit with park optimizer.
5"""
6import time
7import numpy
8
9import park
10from park import fit,fitresult
11from park import assembly
12from park.fitmc import FitSimplex, FitMC
13
14from sans.guitools.plottables import Data1D
15from Loader import Load
16from AbstractFitEngine import FitEngine, Parameter, FitArrange
17class SansParameter(park.Parameter):
18    """
19        SANS model parameters for use in the PARK fitting service.
20        The parameter attribute value is redirected to the underlying
21        parameter value in the SANS model.
22    """
23    def __init__(self, name, model):
24         self._model, self._name = model,name
25         self.set(model.getParam(name))
26         
27    def _getvalue(self): return self._model.getParam(self.name)
28   
29    def _setvalue(self,value): 
30        self._model.setParam(self.name, value)
31       
32    value = property(_getvalue,_setvalue)
33   
34    def _getrange(self):
35        lo,hi = self._model.details[self.name][1:]
36        if lo is None: lo = -numpy.inf
37        if hi is None: hi = numpy.inf
38        return lo,hi
39   
40    def _setrange(self,r):
41        self._model.details[self.name][1:] = r
42    range = property(_getrange,_setrange)
43
44
45class Model(object):
46    """
47        PARK wrapper for SANS models.
48    """
49    def __init__(self, sans_model):
50        self.model = sans_model
51        sansp = sans_model.getParamList()
52        parkp = [SansParameter(p,sans_model) for p in sansp]
53        self.parameterset = park.ParameterSet(sans_model.name,pars=parkp)
54       
55    def eval(self,x):
56        return self.model.run(x)
57   
58class Data(object):
59    """ Wrapper class  for SANS data """
60    def __init__(self,x=None,y=None,dy=None,dx=None,sans_data=None):
61        if not sans_data==None:
62            self.x= sans_data.x
63            self.y= sans_data.y
64            self.dx= sans_data.dx
65            self.dy= sans_data.dy
66        else:
67            if x!=None and y!=None and dy!=None:
68                self.x=x
69                self.y=y
70                self.dx=dx
71                self.dy=dy
72            else:
73                raise ValueError,\
74                "Data is missing x, y or dy, impossible to compute residuals later on"
75        self.qmin=None
76        self.qmax=None
77       
78    def setFitRange(self,mini=None,maxi=None):
79        """ to set the fit range"""
80        self.qmin=mini
81        self.qmax=maxi
82       
83    def residuals(self, fn):
84        """ @param fn: function that return model value
85            @return residuals
86        """
87        x,y,dy = [numpy.asarray(v) for v in (self.x,self.y,self.dy)]
88        if self.qmin==None and self.qmax==None: 
89            self.fx = fn(x)
90            return (y - fn(x))/dy
91       
92        else:
93            self.fx = fn(x[idx])
94            idx = x>=self.qmin & x <= self.qmax
95            return (y[idx] - fn(x[idx]))/dy[idx]
96           
97         
98    def residuals_deriv(self, model, pars=[]):
99        """
100            @return residuals derivatives .
101            @note: in this case just return empty array
102        """
103        return []
104
105           
106class ParkFit(FitEngine):
107    """
108        ParkFit performs the Fit.This class can be used as follow:
109        #Do the fit Park
110        create an engine: engine = ParkFit()
111        Use data must be of type plottable
112        Use a sans model
113       
114        Add data with a dictionnary of FitArrangeList where Uid is a key and data
115        is saved in FitArrange object.
116        engine.set_data(data,Uid)
117       
118        Set model parameter "M1"= model.name add {model.parameter.name:value}.
119        @note: Set_param() if used must always preceded set_model()
120             for the fit to be performed.
121        engine.set_param( model,"M1", {'A':2,'B':4})
122       
123        Add model with a dictionnary of FitArrangeList{} where Uid is a key and model
124        is save in FitArrange object.
125        engine.set_model(model,Uid)
126       
127        engine.fit return chisqr,[model.parameter 1,2,..],[[err1....][..err2...]]
128        chisqr1, out1, cov1=engine.fit({model.parameter.name:value},qmin,qmax)
129        @note: {model.parameter.name:value} is ignored in fit function since
130        the user should make sure to call set_param himself.
131    """
132    def __init__(self,data=[]):
133        """
134            Creates a dictionary (self.fitArrangeList={})of FitArrange elements
135            with Uid as keys
136        """
137        self.fitArrangeList={}
138       
139    def createProblem(self):
140        """
141        Extract sansmodel and sansdata from self.FitArrangelist ={Uid:FitArrange}
142        Create parkmodel and park data ,form a list couple of parkmodel and parkdata
143        create an assembly self.problem=  park.Assembly([(parkmodel,parkdata)])
144        """
145        mylist=[]
146        listmodel=[]
147        for k,value in self.fitArrangeList.iteritems():
148            sansmodel=value.get_model()
149            #wrap sans model
150            parkmodel = Model(sansmodel)
151            for p in parkmodel.parameterset:
152                if p.isfixed():
153                    p.set([-numpy.inf,numpy.inf])
154               
155            Ldata=value.get_data()
156            x,y,dy=self._concatenateData(Ldata)
157            #wrap sansdata
158            parkdata=Data(x,y,dy,None)
159            couple=(parkmodel,parkdata)
160            mylist.append(couple)
161       
162        self.problem =  park.Assembly(mylist)
163       
164   
165    def fit(self, qmin=None, qmax=None):
166        """
167            Performs fit with park.fit module.It can  perform fit with one model
168            and a set of data, more than two fit of  one model and sets of data or
169            fit with more than two model associated with their set of data and constraints
170           
171           
172            @param pars: Dictionary of parameter names for the model and their values.
173            @param qmin: The minimum value of data's range to be fit
174            @param qmax: The maximum value of data's range to be fit
175            @note:all parameter are ignored most of the time.Are just there to keep ScipyFit
176            and ParkFit interface the same.
177            @return result.fitness: Value of the goodness of fit metric
178            @return result.pvec: list of parameter with the best value found during fitting
179            @return result.cov: Covariance matrix
180        """
181
182       
183        self.createProblem()
184        pars=self.problem.fit_parameters()
185        self.problem.eval()
186   
187        localfit = FitSimplex()
188        localfit.ftol = 1e-8
189        fitter = FitMC(localfit=localfit)
190
191        result = fit.fit(self.problem,
192                         fitter=fitter,
193                         handler= fitresult.ConsoleUpdate(improvement_delta=0.1))
194        print "result",result
195        return result.fitness,result.pvec,result.cov
196   
197   
Note: See TracBrowser for help on using the repository browser.