Changeset 042f065 in sasview


Ignore:
Timestamp:
Apr 11, 2014 3:04:20 PM (10 years ago)
Author:
pkienzle
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:
85f17f6
Parents:
90f49a8
Message:

support stop fit

Location:
src/sans/fit
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/sans/fit/BumpsFitting.py

    r90f49a8 r042f065  
    22BumpsFitting module runs the bumps optimizer. 
    33""" 
    4 import sys 
     4import time 
    55 
    66import numpy 
     
    2525        self.data = data 
    2626        self.param_list = param_list 
    27         self.msg_q = msg_q 
    28         self.curr_thread = curr_thread 
    29         self.handler = handler 
    30         self.fitresult = fitresult 
    31         self.res = [] 
    32         self.func_name = "Functor" 
     27        self.res = None 
    3328        self.theory = None 
    34         self.name = "Fill in proper name!" 
     29 
     30    @property 
     31    def name(self): 
     32        return self.model.name 
    3533 
    3634    @property 
     
    119117        #print "params", params 
    120118        self.res, self.theory = self.data.residuals(self.model.evalDistribution) 
    121  
    122         # TODO: this belongs in monitor not residuals calculation 
    123         if False: # self.fitresult is not None: 
     119        return self.res 
     120 
     121BOUNDS_PENALTY = 1e6 # cost for going out of bounds on unbounded fitters 
     122class MonitoredSasProblem(SasProblem): 
     123    """ 
     124    SAS problem definition for optimizers which do not have monitoring or bounds. 
     125    """ 
     126    def __init__(self, param_list, model=None, data=None, fitresult=None, 
     127                 handler=None, curr_thread=None, msg_q=None, update_rate=1): 
     128        """ 
     129        :param Model: the model wrapper fro sans -model 
     130        :param Data: the data wrapper for sans data 
     131        """ 
     132        SasProblem.__init__(self, param_list, model, data) 
     133        self.msg_q = msg_q 
     134        self.curr_thread = curr_thread 
     135        self.handler = handler 
     136        self.fitresult = fitresult 
     137        #self.last_update = time.time() 
     138        #self.func_name = "Functor" 
     139        #self.name = "Fill in proper name!" 
     140 
     141    def residuals(self, p): 
     142        """ 
     143        Cost function for scipy.optimize.leastsq, which does not have a monitor 
     144        built into the algorithm, and instead relies on a monitor built into 
     145        the cost function. 
     146        """ 
     147        # Note: technically, unbounded fitters and unmonitored fitters are 
     148        self.setp(x) 
     149 
     150        # Compute penalty for being out of bounds which increases the farther 
     151        # you get out of bounds.  This allows derivative following algorithms 
     152        # to point back toward the feasible region. 
     153        penalty = self.bounds_penalty() 
     154        if penalty > 0: 
     155            self.theory = numpy.ones(self.data.num_points) 
     156            self.res = self.theory*(penalty/self.data.num_points) + BOUNDS_PENALTY 
     157            return self.res 
     158 
     159        # If no penalty, then we are not out of bounds and we can use the 
     160        # normal residual calculation 
     161        SasProblem.residuals(self, p) 
     162 
     163        # send update to the application 
     164        if True: 
    124165            #self.fitresult.set_model(model=self.model) 
     166            # copy residuals into fit results 
    125167            self.fitresult.residuals = self.res+0 
    126168            self.fitresult.iterations += 1 
    127169            self.fitresult.theory = self.theory+0 
    128170 
    129             #fitness = self.chisq(params=params) 
    130             fitness = self.chisq() 
    131             self.fitresult.p = params 
    132             self.fitresult.set_fitness(fitness=fitness) 
     171            self.fitresult.p = numpy.array(p) # force copy, and coversion to array 
     172            self.fitresult.set_fitness(fitness=self.chisq()) 
    133173            if self.msg_q is not None: 
    134174                self.msg_q.put(self.fitresult) 
     
    149189 
    150190        return self.res 
    151     __call__ = residuals 
    152  
    153     def _DEAD_check_param_range(self): 
    154         """ 
    155         Check the lower and upper bound of the parameter value 
    156         and set res to the inf if the value is outside of the 
    157         range 
    158         :limitation: the initial values must be within range. 
    159         """ 
    160  
    161         #time.sleep(0.01) 
    162         is_outofbound = False 
    163         # loop through the fit parameters 
    164         model = self.model 
    165         for p in self.param_list: 
    166             value = model.getParam(p) 
    167             low,high = model.details[p][1:3] 
    168             if low is not None and numpy.isfinite(low): 
    169                 if p.value == 0: 
    170                     # This value works on Scipy 
    171                     # Do not change numbers below 
    172                     value = _SMALLVALUE 
    173                 # For leastsq, it needs a bit step back from the boundary 
    174                 val = low - value * _SMALLVALUE 
    175                 if value < val: 
    176                     self.res *= 1e+6 
    177                     is_outofbound = True 
    178                     break 
    179             if high is not None and numpy.isfinite(high): 
    180                 # This value works on Scipy 
    181                 # Do not change numbers below 
    182                 if value == 0: 
    183                     value = _SMALLVALUE 
    184                 # For leastsq, it needs a bit step back from the boundary 
    185                 val = high + value * _SMALLVALUE 
    186                 if value > val: 
    187                     self.res *= 1e+6 
    188                     is_outofbound = True 
    189                     break 
    190  
    191         return is_outofbound 
     191 
     192    def bounds_penalty(self): 
     193        from numpy import sum, where 
     194        p, bounds = self.getp(), self.bounds() 
     195        return (sum(where(p<bounds[:,0], bounds[:,0]-p, 0)**2) 
     196              + sum(where(p>bounds[:,1], bounds[:,1]-p, 0)**2) ) 
    192197 
    193198class BumpsFit(FitEngine): 
     
    223228                ind = fitproblem[0].pars.index(name) 
    224229                model.setParam(name, fitproblem[0].vals[ind]) 
    225         listdata = fitproblem[0].get_data() 
    226         # Concatenate dList set (contains one or more data)before fitting 
    227         data = listdata 
     230        data = fitproblem[0].get_data() 
    228231 
    229232        self.curr_thread = curr_thread 
     
    235238        if handler is not None: 
    236239            handler.set_result(result=result) 
    237         problem = SasProblem(param_list=self.param_list, 
    238                               model=model.model, 
    239                               data=data, 
    240                               handler=handler, 
    241                               fitresult=result, 
    242                               curr_thread=curr_thread, 
    243                               msg_q=msg_q) 
    244         try: 
    245             run_bumps(problem, result, ftol) 
    246             #run_scipy(problem, result, ftol) 
    247         except: 
    248             if hasattr(sys, 'last_type') and sys.last_type == KeyboardInterrupt: 
    249                 if handler is not None: 
    250                     msg = "Fitting: Terminated!!!" 
    251                     handler.stop(msg) 
    252                     raise KeyboardInterrupt, msg 
    253             else: 
    254                 raise 
     240 
     241        if True: # bumps 
     242            def abort_test(): 
     243                try: curr_thread.isquit() 
     244                except KeyboardInterrupt: 
     245                    if handler is not None: 
     246                        handler.stop("Fitting: Terminated!!!") 
     247                    return True 
     248                return False 
     249 
     250            problem = SasProblem(param_list=self.param_list, 
     251                                 model=model.model, 
     252                                 data=data) 
     253            run_bumps(problem, result, ftol, abort_test) 
     254        else: 
     255            problem = SasProblem(param_list=self.param_list, 
     256                                 model=model.model, 
     257                                 data=data, 
     258                                 handler=handler, 
     259                                 fitresult=result, 
     260                                 curr_thread=curr_thread, 
     261                                 msg_q=msg_q) 
     262            run_levenburg_marquardt(problem, result, ftol) 
    255263 
    256264        if handler is not None: 
     
    264272        return [result] 
    265273 
    266 def run_bumps(problem, result, ftol): 
     274def run_bumps(problem, result, ftol, abort_test): 
    267275    fitopts = fitters.FIT_OPTIONS[fitters.FIT_DEFAULT] 
    268276    fitclass = fitopts.fitclass 
     
    270278    options['ftol'] = ftol 
    271279    fitdriver = fitters.FitDriver(fitclass, problem=problem, 
    272                                   abort_test=lambda: False, **options) 
     280                                  abort_test=abort_test, **options) 
    273281    mapper = SerialMapper  
    274282    fitdriver.mapper = mapper.start_mapper(problem, None) 
     
    289297    result.theory = problem.theory 
    290298 
    291 def run_scipy(model, result, ftol): 
     299def run_levenburg_marquardt(model, result, ftol): 
    292300    # This import must be here; otherwise it will be confused when more 
    293301    # than one thread exist. 
  • src/sans/fit/ScipyFitting.py

    r95d58d3 r042f065  
    287287    : param range: min or max value of the bounds 
    288288    """ 
    289     return 0.1 (limit if limit != 0.0 else 1.0) 
     289    return 0.1 * (limit if limit != 0.0 else 1.0) 
    290290 
    291291     
Note: See TracChangeset for help on using the changeset viewer.