source: sasview/park_integration/src/sans/fit/ParkFitting.py @ d81008e

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 d81008e was 64d3861, checked in by Jessica Tumarkin <jtumarki@…>, 13 years ago
  • Property mode set to 100644
File size: 6.8 KB
Line 
1
2
3
4"""
5ParkFitting module contains SansParameter,Model,Data
6FitArrange, ParkFit,Parameter classes.All listed classes work together
7to perform a simple fit with park optimizer.
8"""
9#import time
10import numpy
11#import park
12from park import fit
13from park import fitresult
14from park.assembly import Assembly
15from park.fitmc import FitSimplex
16import park.fitmc
17from park.fitmc import FitMC
18
19#from Loader import Load
20from sans.fit.AbstractFitEngine import FitEngine
21
22
23
24class MyAssembly(Assembly):
25    def __init__(self, models, curr_thread=None):
26        Assembly.__init__(self, models)
27        self.curr_thread = curr_thread
28        self.chisq = None
29        self._cancel = False
30       
31    def eval(self):
32        """
33        Recalculate the theory functions, and from them, the
34        residuals and chisq.
35
36        :note: Call this after the parameters have been updated.
37        """
38        # Handle abort from a separate thread.
39        self._cancel = False
40        if self.curr_thread != None:
41            try:
42                self.curr_thread.isquit()
43            except:
44                self._cancel = True
45
46        # Evaluate the computed parameters
47        try:
48            self._fitexpression()
49        except NameError:
50            pass
51
52        # Check that the resulting parameters are in a feasible region.
53        if not self.isfeasible(): return numpy.inf
54
55        resid = []
56        k = len(self._fitparameters)
57        for m in self.parts:
58            # In order to support abort, need to be able to propagate an
59            # external abort signal from self.abort() into an abort signal
60            # for the particular model.  Can't see a way to do this which
61            # doesn't involve setting a state variable.
62            self._current_model = m
63            if self._cancel: return numpy.inf
64            if m.isfitted and m.weight != 0:
65                m.residuals = m.fitness.residuals()
66                N = len(m.residuals)
67                m.degrees_of_freedom = N-k if N>k else 1
68                m.chisq = numpy.sum(m.residuals**2)
69                resid.append(m.weight*m.residuals)
70        self.residuals = numpy.hstack(resid)
71        N = len(self.residuals)
72        self.degrees_of_freedom = N-k if N>k else 1
73        self.chisq = numpy.sum(self.residuals**2)
74        return self.chisq
75   
76class ParkFit(FitEngine):
77    """
78    ParkFit performs the Fit.This class can be used as follow:
79    #Do the fit Park
80    create an engine: engine = ParkFit()
81    Use data must be of type plottable
82    Use a sans model
83   
84    Add data with a dictionnary of FitArrangeList where Uid is a key and data
85    is saved in FitArrange object.
86    engine.set_data(data,Uid)
87   
88    Set model parameter "M1"= model.name add {model.parameter.name:value}.
89   
90    :note: Set_param() if used must always preceded set_model()
91         for the fit to be performed.
92    engine.set_param( model,"M1", {'A':2,'B':4})
93   
94    Add model with a dictionnary of FitArrangeList{} where Uid is a key
95    and model
96    is save in FitArrange object.
97    engine.set_model(model,Uid)
98   
99    engine.fit return chisqr,[model.parameter 1,2,..],[[err1....][..err2...]]
100    chisqr1, out1, cov1=engine.fit({model.parameter.name:value},qmin,qmax)
101   
102    :note: {model.parameter.name:value} is ignored in fit function since
103        the user should make sure to call set_param himself.
104       
105    """
106    def __init__(self):
107        """
108        Creates a dictionary (self.fitArrangeList={})of FitArrange elements
109        with Uid as keys
110        """
111        FitEngine.__init__(self)
112        self.fit_arrange_dict = {}
113        self.param_list = []
114       
115    def create_assembly(self, curr_thread):
116        """
117        Extract sansmodel and sansdata from
118        self.FitArrangelist ={Uid:FitArrange}
119        Create parkmodel and park data ,form a list couple of parkmodel
120        and parkdata
121        create an assembly self.problem=  park.Assembly([(parkmodel,parkdata)])
122        """
123        mylist = []
124        #listmodel = []
125        #i = 0
126        fitproblems = []
127        for fproblem in self.fit_arrange_dict.itervalues():
128            if fproblem.get_to_fit() == 1:
129                fitproblems.append(fproblem)
130        if len(fitproblems) == 0: 
131            raise RuntimeError, "No Assembly scheduled for Park fitting."
132            return
133        for item in fitproblems:
134            parkmodel = item.get_model()
135            for p in parkmodel.parameterset:
136                ## does not allow status change for constraint parameters
137                if p.status != 'computed':
138                    if p.get_name()in item.pars:
139                        ## make parameters selected for
140                        #fit will be between boundaries
141                        p.set(p.range)         
142                    else:
143                        p.status = 'fixed'
144            data_list = item.get_data()
145            parkdata = data_list
146            fitness = (parkmodel, parkdata)
147            mylist.append(fitness)
148        self.problem = MyAssembly(models=mylist, curr_thread=curr_thread)
149       
150 
151    def fit(self, q=None, handler=None, curr_thread=None, ftol=1.49012e-8):
152        """
153        Performs fit with park.fit module.It can  perform fit with one model
154        and a set of data, more than two fit of  one model and sets of data or
155        fit with more than two model associated with their set of data and
156        constraints
157       
158        :param pars: Dictionary of parameter names for the model and their
159            values.
160        :param qmin: The minimum value of data's range to be fit
161        :param qmax: The maximum value of data's range to be fit
162       
163        :note: all parameter are ignored most of the time.Are just there
164            to keep ScipyFit and ParkFit interface the same.
165           
166        :return: result.fitness Value of the goodness of fit metric
167        :return: result.pvec list of parameter with the best value
168            found during fitting
169        :return: result.cov Covariance matrix
170       
171        """
172        self.create_assembly(curr_thread=curr_thread)
173        localfit = FitSimplex()
174        localfit.ftol = ftol
175       
176        # See `park.fitresult.FitHandler` for details.
177        fitter = FitMC(localfit=localfit, start_points=1)
178        if handler == None:
179            handler = fitresult.ConsoleUpdate(improvement_delta=0.1)
180        result = fit.fit(self.problem, fitter=fitter, handler=handler)
181        self.problem.all_results(result)
182        if result != None:
183            if q != None:
184                q.put(result)
185                return q
186            return result
187        else:
188            raise ValueError, "SVD did not converge"
189           
Note: See TracBrowser for help on using the repository browser.