Ignore:
Timestamp:
Jul 18, 2009 4:45:23 PM (15 years ago)
Author:
Mathieu Doucet <doucetm@…>
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:
2b687dc
Parents:
a3f8d58
Message:

park_integration: modified residuals to allow for partial q range when using smeared data

File:
1 edited

Legend:

Unmodified
Added
Removed
  • park_integration/AbstractFitEngine.py

    r058b2d7 r72c7d31  
    1  
     1import logging, sys 
    22import park,numpy,math, copy 
    33 
     
    205205        # Initialize from Data1D object 
    206206        self.data=sans_data1d 
    207         self.x= numpy.array(sans_data1d.x) 
    208         self.y= numpy.array(sans_data1d.y) 
    209         self.dx= numpy.array(sans_data1d.dx) 
    210         self.dy= numpy.array(sans_data1d.dy) 
    211            
    212          
    213         if self.dy ==None or len(self.dy)==0: 
    214             self.res_dy= numpy.zeros(len(self.y)) 
    215         else: 
    216             self.res_dy= copy.deepcopy(self.dy) 
    217         self.res_dy= numpy.asarray(self.res_dy) 
    218          
    219         self.res_dy[self.res_dy==0]=1 
     207        self.x= sans_data1d.x 
     208        self.y= sans_data1d.y 
     209        self.dx= sans_data1d.dx 
     210        self.dy= sans_data1d.dy 
     211         
    220212        ## Min Q-value 
    221213        #Skip the Q=0 point, especially when y(q=0)=None at x[0]. 
     
    227219        self.qmax= max (self.data.x) 
    228220         
    229          
     221        # Range used for input to smearing 
     222        self._qmin_unsmeared = self.qmin 
     223        self._qmax_unsmeared = self.qmax 
     224        
     225        
    230226    def setFitRange(self,qmin=None,qmax=None): 
    231227        """ to set the fit range""" 
     
    239235        if qmax !=None: 
    240236            self.qmax = qmax 
    241         
     237             
     238        # Range used for input to smearing 
     239        self._qmin_unsmeared = self.qmin 
     240        self._qmax_unsmeared = self.qmax     
     241         
     242        # Determine the range needed in unsmeared-Q to cover 
     243        # the smeared Q range 
     244        #TODO: use the smearing matrix to determine which  
     245        # bin range to use 
     246        if self.smearer.__class__.__name__ == 'SlitSmearer': 
     247            self._qmin_unsmeared = min(self.data.x) 
     248            self._qmax_unsmeared = max(self.data.x) 
     249        elif self.smearer.__class__.__name__ == 'QSmearer': 
     250            # Take 3 sigmas as the offset between smeared and unsmeared space 
     251            try: 
     252                offset = 3.0*max(self.smearer.width) 
     253                self._qmin_unsmeared = max([min(self.data.x), self.qmin-offset]) 
     254                self._qmax_unsmeared = min([max(self.data.x), self.qmax+offset]) 
     255            except: 
     256                logging.error("FitData1D.setFitRange: %s" % sys.exc_value) 
     257         
    242258         
    243259    def getFitRange(self): 
     
    246262        """ 
    247263        return self.qmin, self.qmax 
     264         
     265    def residuals(self, fn): 
     266        """  
     267            Compute residuals. 
     268             
     269            If self.smearer has been set, use if to smear 
     270            the data before computing chi squared. 
     271             
     272            @param fn: function that return model value 
     273            @return residuals 
     274        """ 
     275        x,y = [numpy.asarray(v) for v in (self.x,self.y)] 
     276        if self.dy ==None or self.dy==[]: 
     277            dy= numpy.zeros(len(y))   
     278        else: 
     279            dy= numpy.asarray(self.dy) 
    248280      
    249       
    250     def residuals(self, fn): 
    251         """ 
    252         Compute residuals. 
    253          
    254         If self.smearer has been set, use if to smear the data before computing chi squared. 
    255          
    256         @param fn: function that return model value @return residuals """ 
    257         # Get the indices of the selected range 
    258         idx = (self.x>=self.qmin) & (self.x <= self.qmax) 
    259          
     281        # For fitting purposes, replace zero errors by 1 
     282        #TODO: check validity for the rare case where only 
     283        # a few points have zero errors  
     284        dy[dy==0]=1 
     285         
     286        # Identify the bin range for the unsmeared and smeared spaces 
     287        idx = (x>=self.qmin) & (x <= self.qmax) 
     288        idx_unsmeared = (x>=self._qmin_unsmeared) & (x <= self._qmax_unsmeared) 
     289   
    260290        # Compute theory data f(x) 
    261         newy = numpy.zeros(len(self.x)) 
    262         newfx= numpy.zeros(len(self.x)) 
    263         newdy= numpy.zeros(len(self.x)) 
    264         
    265         for i_x in range(len(self.x)): 
     291        fx= numpy.zeros(len(x)) 
     292     
     293        _first_bin = None 
     294        _last_bin  = None 
     295        for i_x in range(len(x)): 
    266296            try: 
    267                 # Skip the selection here since we want all the contribution from the theory bins #if self.qmin <=x[i_x] and x[i_x]<=self.qmax: 
    268                 value       = fn(self.x[i_x]) 
    269                 newfx[i_x]  = value 
    270                 newy[i_x]   = self.y[i_x] 
    271                 newdy[i_x]  = self.res_dy[i_x] 
    272                  
     297                if idx_unsmeared[i_x]==True: 
     298                    # Identify first and last bin 
     299                    #TODO: refactor this to pass q-values to the smearer 
     300                    # and let it figure out which bin range to use 
     301                    if _first_bin is None: 
     302                        _first_bin = i_x 
     303                    else: 
     304                        _last_bin  = i_x 
     305                     
     306                    value = fn(x[i_x]) 
     307                    fx[i_x] = value 
    273308            except: 
    274309                ## skip error for model.run(x) 
    275310                pass 
    276         
     311                  
    277312        ## Smear theory data 
    278313        if self.smearer is not None: 
    279              
    280             newfx = self.smearer(newfx) 
    281        
     314            fx = self.smearer(fx, _first_bin, _last_bin) 
     315        
    282316        ## Sanity check 
    283         if numpy.size(newdy)!= numpy.size(newfx): 
    284             raise RuntimeError, "FitData1D: invalid error array" 
    285          
    286         # Sum over the selected range 
    287         return (newy[idx]- newfx[idx])/newdy[idx] 
    288          
     317        if numpy.size(dy)!= numpy.size(fx): 
     318            raise RuntimeError, "FitData1D: invalid error array %d <> %d" % (numpy.size(dy), numpy.size(fx)) 
    289319 
     320        return (y[idx]-fx[idx])/dy[idx] 
     321      
     322   
     323         
    290324    def residuals_deriv(self, model, pars=[]): 
    291325        """  
Note: See TracChangeset for help on using the changeset viewer.