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

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 42c974f was 64d3861, checked in by Jessica Tumarkin <jtumarki@…>, 13 years ago
  • Property mode set to 100644
File size: 6.8 KB
RevLine 
[aa36f96]1
2
3
[792db7d5]4"""
[aa36f96]5ParkFitting module contains SansParameter,Model,Data
[b2f25dc5]6FitArrange, ParkFit,Parameter classes.All listed classes work together
7to perform a simple fit with park optimizer.
[792db7d5]8"""
[89f3b66]9#import time
[dfd3577]10import numpy
[b2f25dc5]11#import park
12from park import fit
13from park import fitresult
14from park.assembly import Assembly
15from park.fitmc import FitSimplex
[dfd3577]16import park.fitmc
[b2f25dc5]17from park.fitmc import FitMC
[7d0c1a8]18
[61cb28d]19#from Loader import Load
[b2f25dc5]20from sans.fit.AbstractFitEngine import FitEngine
[d4b0687]21
[fadea71]22
[dfd3577]23
24class MyAssembly(Assembly):
25    def __init__(self, models, curr_thread=None):
26        Assembly.__init__(self, models)
27        self.curr_thread = curr_thread
[bd5ac39]28        self.chisq = None
29        self._cancel = False
[dfd3577]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
[bd5ac39]47        try:
48            self._fitexpression()
49        except NameError:
50            pass
[dfd3577]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   
[4c718654]76class ParkFit(FitEngine):
[7705306]77    """
[aa36f96]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   
[b2f25dc5]94    Add model with a dictionnary of FitArrangeList{} where Uid is a key
95    and model
[aa36f96]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
[792db7d5]103        the user should make sure to call set_param himself.
[aa36f96]104       
[7705306]105    """
[916a15f]106    def __init__(self):
[792db7d5]107        """
[aa36f96]108        Creates a dictionary (self.fitArrangeList={})of FitArrange elements
109        with Uid as keys
[792db7d5]110        """
[b2f25dc5]111        FitEngine.__init__(self)
112        self.fit_arrange_dict = {}
113        self.param_list = []
[37d9521]114       
[dfd3577]115    def create_assembly(self, curr_thread):
[7705306]116        """
[b2f25dc5]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
[792db7d5]121        create an assembly self.problem=  park.Assembly([(parkmodel,parkdata)])
[7705306]122        """
[89f3b66]123        mylist = []
[b2f25dc5]124        #listmodel = []
125        #i = 0
[89f3b66]126        fitproblems = []
[b2f25dc5]127        for fproblem in self.fit_arrange_dict.itervalues():
[89f3b66]128            if fproblem.get_to_fit() == 1:
[a9e04aa]129                fitproblems.append(fproblem)
[89f3b66]130        if len(fitproblems) == 0: 
[a9e04aa]131            raise RuntimeError, "No Assembly scheduled for Park fitting."
132            return
133        for item in fitproblems:
134            parkmodel = item.get_model()
[9e85792]135            for p in parkmodel.parameterset:
[fe886ee]136                ## does not allow status change for constraint parameters
[89f3b66]137                if p.status != 'computed':
[b2f25dc5]138                    if p.get_name()in item.pars:
139                        ## make parameters selected for
140                        #fit will be between boundaries
[89f3b66]141                        p.set(p.range)         
[aed7c57]142                    else:
[89f3b66]143                        p.status = 'fixed'
[b2f25dc5]144            data_list = item.get_data()
145            parkdata = data_list
[89f3b66]146            fitness = (parkmodel, parkdata)
[ca6d914]147            mylist.append(fitness)
[dfd3577]148        self.problem = MyAssembly(models=mylist, curr_thread=curr_thread)
[126a761]149       
[dfd3577]150 
[93de635d]151    def fit(self, q=None, handler=None, curr_thread=None, ftol=1.49012e-8):
[7705306]152        """
[aa36f96]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
[b2f25dc5]155        fit with more than two model associated with their set of data and
156        constraints
[aa36f96]157       
[b2f25dc5]158        :param pars: Dictionary of parameter names for the model and their
159            values.
[aa36f96]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       
[b2f25dc5]163        :note: all parameter are ignored most of the time.Are just there
164            to keep ScipyFit and ParkFit interface the same.
[aa36f96]165           
166        :return: result.fitness Value of the goodness of fit metric
[b2f25dc5]167        :return: result.pvec list of parameter with the best value
168            found during fitting
[aa36f96]169        :return: result.cov Covariance matrix
170       
[7705306]171        """
[dfd3577]172        self.create_assembly(curr_thread=curr_thread)
[cf3b781]173        localfit = FitSimplex()
[93de635d]174        localfit.ftol = ftol
[681f0dc]175       
[916a15f]176        # See `park.fitresult.FitHandler` for details.
[9c648c7]177        fitter = FitMC(localfit=localfit, start_points=1)
[681f0dc]178        if handler == None:
[89f3b66]179            handler = fitresult.ConsoleUpdate(improvement_delta=0.1)
[dfd3577]180        result = fit.fit(self.problem, fitter=fitter, handler=handler)
[8296ff5]181        self.problem.all_results(result)
[89f3b66]182        if result != None:
183            if q != None:
[fd6b789]184                q.put(result)
185                return q
[48882d1]186            return result
[ee5b04c]187        else:
188            raise ValueError, "SVD did not converge"
[aa36f96]189           
Note: See TracBrowser for help on using the repository browser.