Changeset 1cff677 in sasview for park_integration/src/sans/fit


Ignore:
Timestamp:
Oct 4, 2011 8:03:59 PM (13 years ago)
Author:
Gervaise Alina <gervyh@…>
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
706667b
Parents:
34a60dd
Message:

working on get thing data and model from result of fit

Location:
park_integration/src/sans/fit
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • park_integration/src/sans/fit/AbstractFitEngine.py

    r41517a6 r1cff677  
    1717    parameter value in the SANS model. 
    1818    """ 
    19     def __init__(self, name, model): 
     19    def __init__(self, name, model, data): 
    2020        """ 
    2121        :param name: the name of the model parameter 
     
    2525        park.Parameter.__init__(self, name) 
    2626        self._model, self._name = model, name 
     27        self.data = data 
     28        self.model = model 
    2729        #set the value for the parameter of the given name 
    2830        self.set(model.getParam(name)) 
     
    8587    PARK wrapper for SANS models. 
    8688    """ 
    87     def __init__(self, sans_model, **kw): 
     89    def __init__(self, sans_model, sans_data=None, **kw): 
    8890        """ 
    8991        :param sans_model: the sans model to wrap using park interface 
     
    9395        self.model = sans_model 
    9496        self.name = sans_model.name 
     97        self.data = sans_data 
    9598        #list of parameters names 
    9699        self.sansp = sans_model.getParamList() 
    97100        #list of park parameter 
    98         self.parkp = [SansParameter(p, sans_model) for p in self.sansp] 
     101        self.parkp = [SansParameter(p, sans_model, sans_data) for p in self.sansp] 
    99102        #list of parameterset  
    100103        self.parameterset = park.ParameterSet(sans_model.name, pars=self.parkp) 
     
    540543        self.fit_arrange_dict = {} 
    541544   
    542     def set_model(self, model, id, pars=[], constraints=[]): 
     545    def set_model(self, model,  id,  pars=[], constraints=[], data=None): 
    543546        """ 
    544547        set a model on a given  in the fit engine. 
     
    566569        new_model = model 
    567570        if not issubclass(model.__class__, Model): 
    568             new_model = Model(model) 
     571            new_model = Model(model, data) 
    569572         
    570573        if len(constraints) > 0: 
  • park_integration/src/sans/fit/ParkFitting.py

    r64d3861 r1cff677  
    1212from park import fit 
    1313from park import fitresult 
     14from  park.fitresult import FitParameter 
     15import park.simplex 
    1416from park.assembly import Assembly 
     17from park.assembly import Part 
    1518from park.fitmc import FitSimplex  
    1619import park.fitmc 
    1720from park.fitmc import FitMC 
    18  
     21from park.fit import Fitter 
     22from park.formatnum import format_uncertainty 
    1923#from Loader import Load 
    2024from sans.fit.AbstractFitEngine import FitEngine 
    21  
    22  
    23  
     25   
     26class SansFitSimplex(FitSimplex): 
     27    """ 
     28    Local minimizer using Nelder-Mead simplex algorithm. 
     29 
     30    Simplex is robust and derivative free, though not very efficient. 
     31 
     32    This class wraps the bounds contrained Nelder-Mead simplex 
     33    implementation for `park.simplex.simplex`. 
     34    """ 
     35    radius = 0.05 
     36    """Size of the initial simplex; this is a portion between 0 and 1""" 
     37    xtol = 1 
     38    #xtol = 1e-4 
     39    """Stop when simplex vertices are within xtol of each other""" 
     40    ftol = 1e-4 
     41    """Stop when vertex values are within ftol of each other""" 
     42    maxiter = None 
     43    """Maximum number of iterations before fit terminates""" 
     44    def fit(self, fitness, x0): 
     45        """Run the fit""" 
     46        self.cancel = False 
     47        pars = fitness.fit_parameters() 
     48        bounds = numpy.array([p.range for p in pars]).T 
     49        result = park.simplex.simplex(fitness, x0, bounds=bounds, 
     50                                 radius=self.radius, xtol=self.xtol, 
     51                                 ftol=self.ftol, maxiter=self.maxiter, 
     52                                 abort_test=self._iscancelled) 
     53        #print "calls:",result.calls 
     54        #print "simplex returned",result.x,result.fx 
     55        # Need to make our own copy of the fit results so that the 
     56        # values don't get stomped on by the next fit iteration. 
     57        fitpars = [SansFitParameter(pars[i].name,pars[i].range,v, pars[i].model, pars[i].data) 
     58                   for i,v in enumerate(result.x)] 
     59        res = fitresult.FitResult(fitpars, result.calls, result.fx) 
     60        # Compute the parameter uncertainties from the jacobian 
     61        res.calc_cov(fitness) 
     62        return res 
     63       
     64class SansFitter(Fitter): 
     65    """ 
     66    """ 
     67    def fit(self, fitness, handler): 
     68        """ 
     69        Global optimizer. 
     70 
     71        This function should return immediately 
     72        """ 
     73        # Determine initial value and bounds 
     74        pars = fitness.fit_parameters() 
     75        bounds = numpy.array([p.range for p in pars]).T 
     76        x0 = [p.value for p in pars] 
     77 
     78        # Initialize the monitor and results. 
     79        # Need to make our own copy of the fit results so that the 
     80        # values don't get stomped on by the next fit iteration. 
     81        handler.done = False 
     82        self.handler = handler 
     83        fitpars = [SansFitParameter(pars[i].name, pars[i].range, v, 
     84                                     pars[i].model, pars[i].data) 
     85                   for i,v in enumerate(x0)] 
     86        handler.result = fitresult.FitResult(fitpars, 0, numpy.NaN) 
     87 
     88        # Run the fit (fit should perform _progress and _improvement updates) 
     89        # This function may return before the fit is complete. 
     90        self._fit(fitness, x0, bounds) 
     91         
     92class SansFitMC(SansFitter): 
     93    """ 
     94    Monte Carlo optimizer. 
     95 
     96    This implements `park.fit.Fitter`. 
     97    """ 
     98    localfit = SansFitSimplex() 
     99    start_points = 10 
     100 
     101    def _fit(self, objective, x0, bounds): 
     102        """ 
     103        Run a monte carlo fit. 
     104 
     105        This procedure maps a local optimizer across a set of initial points. 
     106        """ 
     107        park.fitmc.fitmc(objective, x0, bounds, self.localfit, 
     108              self.start_points, self.handler) 
     109 
     110         
     111class SansPart(Part): 
     112    """ 
     113    Part of a fitting assembly.  Part holds the model itself and 
     114    associated data.  The part can be initialized with a fitness 
     115    object or with a pair (model,data) for the default fitness function. 
     116 
     117    fitness (Fitness) 
     118        object implementing the `park.assembly.Fitness` interface.  In 
     119        particular, fitness should provide a parameterset attribute 
     120        containing a ParameterSet and a residuals method returning a vector 
     121        of residuals. 
     122    weight (dimensionless) 
     123        weight for the model.  See comments in assembly.py for details. 
     124    isfitted (boolean) 
     125        True if the model residuals should be included in the fit. 
     126        The model parameters may still be used in parameter 
     127        expressions, but there will be no comparison to the data. 
     128    residuals (vector) 
     129        Residuals for the model if they have been calculated, or None 
     130    degrees_of_freedom 
     131        Number of residuals minus number of fitted parameters. 
     132        Degrees of freedom for individual models does not make 
     133        sense in the presence of expressions combining models, 
     134        particularly in the case where a model has many parameters 
     135        but no data or many computed parameters.  The degrees of 
     136        freedom for the model is set to be at least one. 
     137    chisq 
     138        sum(residuals**2); use chisq/degrees_of_freedom to 
     139        get the reduced chisq value. 
     140 
     141        Get/set the weight on the given model. 
     142 
     143        assembly.weight(3) returns the weight on model 3 (0-origin) 
     144        assembly.weight(3,0.5) sets the weight on model 3 (0-origin) 
     145    """ 
     146 
     147    def __init__(self, fitness, weight=1., isfitted=True): 
     148        Part.__init__(self, fitness=fitness, weight=weight, 
     149                       isfitted=isfitted) 
     150        
     151        self.model, self.data = fitness[0], fitness[1] 
     152 
     153class SansFitParameter(FitParameter): 
     154    """ 
     155    Fit result for an individual parameter. 
     156    """ 
     157    def __init__(self, name, range, value, model, data): 
     158        FitParameter.__init__(self, name, range, value) 
     159        self.model = model 
     160        self.data = data 
     161         
     162    def summarize(self): 
     163        """ 
     164        Return parameter range string. 
     165 
     166        E.g.,  "       Gold .....|.... 5.2043 in [2,7]" 
     167        """ 
     168        bar = ['.']*10 
     169        lo,hi = self.range 
     170        if numpy.isfinite(lo)and numpy.isfinite(hi): 
     171            portion = (self.value-lo)/(hi-lo) 
     172            if portion < 0: portion = 0. 
     173            elif portion >= 1: portion = 0.99999999 
     174            barpos = int(math.floor(portion*len(bar))) 
     175            bar[barpos] = '|' 
     176        bar = "".join(bar) 
     177        lostr = "[%g"%lo if numpy.isfinite(lo) else "(-inf" 
     178        histr = "%g]"%hi if numpy.isfinite(hi) else "inf)" 
     179        valstr = format_uncertainty(self.value, self.stderr) 
     180        model_name = str(None) 
     181        if self.model is not None: 
     182            model_name = self.model.name 
     183        data_name = str(None) 
     184        if self.data is not None: 
     185            data_name = self.data.name 
     186             
     187        return "%25s %s %s in %s,%s, %s, %s"  % (self.name,bar,valstr,lostr,histr,  
     188                                                 model_name, data_name) 
     189    def __repr__(self): 
     190        #return "FitParameter('%s')"%self.name 
     191        return str(self.__class__) 
     192     
    24193class MyAssembly(Assembly): 
    25194    def __init__(self, models, curr_thread=None): 
     
    29198        self._cancel = False 
    30199         
     200    def fit_parameters(self): 
     201        """ 
     202        Return an alphabetical list of the fitting parameters. 
     203 
     204        This function is called once at the beginning of a fit, 
     205        and serves as a convenient place to precalculate what 
     206        can be precalculated such as the set of fitting parameters 
     207        and the parameter expressions evaluator. 
     208        """ 
     209        self.parameterset.setprefix() 
     210        self._fitparameters = self.parameterset.fitted 
     211        self._restraints = self.parameterset.restrained 
     212        pars = self.parameterset.flatten() 
     213        context = self.parameterset.gather_context() 
     214        self._fitexpression = park.expression.build_eval(pars,context) 
     215        #print "constraints",self._fitexpression.__doc__ 
     216 
     217        self._fitparameters.sort(lambda a,b: cmp(a.path,b.path)) 
     218        # Convert to fitparameter a object 
     219         
     220        fitpars = [SansFitParameter(p.path,p.range,p.value, p.model, p.data) 
     221                   for p in self._fitparameters] 
     222        #print "fitpars", fitpars 
     223        return fitpars 
     224     
     225    def all_results(self, result): 
     226        """ 
     227        Extend result from the fit with the calculated parameters. 
     228        """ 
     229        calcpars = [SansFitParameter(p.path,p.range,p.value, p.model, p.data) 
     230                    for p in self.parameterset.computed] 
     231        #print "all_results", calcpars 
     232        result.parameters += calcpars 
     233 
    31234    def eval(self): 
    32235        """ 
     
    171374        """ 
    172375        self.create_assembly(curr_thread=curr_thread) 
    173         localfit = FitSimplex() 
     376        localfit = SansFitSimplex() 
    174377        localfit.ftol = ftol 
    175378         
    176379        # See `park.fitresult.FitHandler` for details. 
    177         fitter = FitMC(localfit=localfit, start_points=1) 
     380        fitter = SansFitMC(localfit=localfit, start_points=1) 
    178381        if handler == None: 
    179382            handler = fitresult.ConsoleUpdate(improvement_delta=0.1) 
    180383        result = fit.fit(self.problem, fitter=fitter, handler=handler) 
    181384        self.problem.all_results(result) 
     385         
     386        #print "park------", self.problem.parts 
     387    
    182388        if result != None: 
    183389            if q != None: 
Note: See TracChangeset for help on using the changeset viewer.