Changeset f867cd9 in sasview for DataLoader


Ignore:
Timestamp:
Dec 17, 2010 5:26:52 PM (14 years ago)
Author:
Jae Cho <jhjcho@…>
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:
7342634
Parents:
0d8c8d7
Message:

fixed the edge problem in Q(pinhole) smearer

Location:
DataLoader
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • DataLoader/extensions/smearer.cpp

    r65883cf rf867cd9  
    211211 
    212212                        // Compute the fraction of the Gaussian contributing 
    213                         // to the q bin between q_min and q_max 
    214                         double value =  erf( (q_max-q_j)/(sqrt(2.0)*width[j]) ); 
    215                 value -= erf( (q_min-q_j)/(sqrt(2.0)*width[j]) ); 
     213                        // to the q_j bin between q_jmin and q_jmax 
     214                        double value =  erf( (q_jmax-q)/(sqrt(2.0)*width[i]) ); 
     215                value -= erf( (q_jmin-q)/(sqrt(2.0)*width[i]) ); 
    216216                (*weights)[i*nbins+j] += value; 
    217217                } 
     
    273273 
    274274                for(int i=first_bin; i<=last_bin; i++){ 
     275                        // Skip if weight is less than 1e-04(this value is much smaller than 
     276                        // the weight at the 3*sigma distance 
     277                        // Will speed up a little bit... 
     278                        if ((*weights)[q_i*nbins+i] < 1.0e-004){ 
     279                                continue; 
     280                        } 
    275281                        sum += iq_in[i] * (*weights)[q_i*nbins+i]; 
    276282                        counts += (*weights)[q_i*nbins+i]; 
     
    279285                // Normalize counts 
    280286                iq_out[q_i] = (counts>0.0) ? sum/counts : 0; 
     287                //printf("\n iii=%g,%g ",iq_out[q_i], q_i); 
    281288        } 
    282289} 
  • DataLoader/qsmearing.py

    ra7a5886 rf867cd9  
    88###################################################################### 
    99import numpy 
    10 #import math 
     10import math 
    1111import logging 
    1212import sys 
     
    1414from DataLoader.smearing_2d import Smearer2D 
    1515 
    16 def smear_selection(data1D): 
     16def smear_selection(data1D, model = None): 
    1717    """ 
    1818    Creates the right type of smearer according  
     
    3030     
    3131    :param data1D: Data1D object 
     32    :param model: sans.model instance 
    3233    """ 
    3334    # Sanity check. If we are not dealing with a SANS Data1D 
     
    5556    # If we found resolution smearing data, return a QSmearer 
    5657    if _found_resolution == True: 
    57         return QSmearer(data1D) 
     58        return QSmearer(data1D, model) 
    5859 
    5960    # Look for slit smearing data 
     
    8687    def __init__(self): 
    8788        self.nbins = 0 
     89        self.nbins_low = 0 
     90        self.nbins_high = 0 
    8891        self._weights = None 
    8992        ## Internal flag to keep track of C++ smearer initialization 
    9093        self._init_complete = False 
    9194        self._smearer = None 
     95        self.model = None 
    9296         
    9397    def __deepcopy__(self, memo={}): 
     
    121125        if q_max == None: 
    122126            q_max = self.max 
     127 
    123128        _qmin_unsmeared, _qmax_unsmeared = self.get_unsmeared_range(q_min, 
    124129                                                                     q_max) 
     
    126131        _last_bin  = None 
    127132 
    128         step = (self.max - self.min) / (self.nbins - 1.0) 
     133        #step = (self.max - self.min) / (self.nbins - 1.0) 
     134        # Find the first and last bin number in all extrapolated and real data 
    129135        try: 
    130136            for i in range(self.nbins): 
     
    140146            msg += " error getting range\n  %s" % sys.exc_value 
    141147            raise RuntimeError, msg 
    142                 
     148    
     149        #  Find the first and last bin number only in the real data 
     150        _first_bin, _last_bin = self._get_unextrapolated_bin( \ 
     151                                        _first_bin, _last_bin) 
     152 
    143153        return _first_bin, _last_bin 
    144154 
    145     def __call__(self, iq_in, first_bin=0, last_bin=None): 
     155    def __call__(self, iq_in, first_bin = 0, last_bin = None): 
    146156        """ 
    147157        Perform smearing 
     
    151161        if not self._init_complete: 
    152162            self._initialize_smearer() 
    153               
    154         # Get the max value for the last bin 
     163 
    155164        if last_bin is None or last_bin >= len(iq_in): 
    156165            last_bin = len(iq_in) - 1 
     
    159168            first_bin = 0 
    160169             
     170        # With a model given, compute I for the extrapolated points and append 
     171        # to the iq_in 
     172        #iq_in_temp = iq_in 
     173        if self.model != None: 
     174            temp_first, temp_last = self._get_extrapolated_bin( \ 
     175                                                        first_bin, last_bin) 
     176            iq_in_low = self.model.evalDistribution( \ 
     177                                            self.qvalues[0:self.nbins_low]) 
     178            iq_in_high = self.model.evalDistribution( \ 
     179                                            self.qvalues[(len(self.qvalues) - \ 
     180                                            self.nbins_high - 1): -1]) 
     181            if self.nbins_low > 0:                              
     182                iq_in_temp = numpy.append(iq_in_low, iq_in) 
     183            if self.nbins_high > 0: 
     184                iq_in_temp = numpy.append(iq_in_temp, iq_in_high) 
     185        else: 
     186            temp_first = first_bin 
     187            temp_last = last_bin 
     188            iq_in_temp = iq_in 
    161189        # Sanity check 
    162         if len(iq_in) != self.nbins: 
     190        if len(iq_in_temp) != self.nbins: 
    163191            msg = "Invalid I(q) vector: inconsistent array " 
    164             msg += " length %d != %s" % (len(iq_in), str(self.nbins)) 
     192            msg += " length %d != %s" % (len(iq_in_temp), str(self.nbins)) 
    165193            raise RuntimeError, msg 
    166               
     194 
    167195        # Storage for smeared I(q)    
    168196        iq_out = numpy.zeros(self.nbins) 
    169         smear_output = smearer.smear(self._smearer, iq_in, iq_out, 
    170                                       first_bin, last_bin) 
     197 
     198        smear_output = smearer.smear(self._smearer, iq_in_temp, iq_out, 
     199                                      #0, self.nbins - 1) 
     200                                      temp_first, temp_last) 
     201                                      #first_bin, last_bin) 
    171202        if smear_output < 0: 
    172203            msg = "_BaseSmearer: could not smear, code = %g" % smear_output 
    173204            raise RuntimeError, msg 
    174         return iq_out 
     205         
     206         
     207        temp_first += self.nbins_low 
     208        temp_last = self.nbins - (self.nbins_high + 1) 
     209 
     210        return iq_out[temp_first: (temp_last + 1)] 
    175211     
    176212    def _initialize_smearer(self): 
     
    179215        return NotImplemented 
    180216     
     217    def set_model(self, model): 
     218        """ 
     219        Set model 
     220        """ 
     221        if model != None: 
     222            self.model = model 
     223             
     224     
     225    def _get_unextrapolated_bin(self, first_bin = 0, last_bin = 0): 
     226        """ 
     227        Get unextrapolated first bin and the last bin 
     228         
     229        : param first_bin: extrapolated first_bin 
     230        : param last_bin: extrapolated last_bin 
     231         
     232        : return fist_bin, last_bin: unextrapolated first and last bin 
     233        """ 
     234        #  For first bin 
     235        if first_bin <= self.nbins_low: 
     236            first_bin = 0 
     237        else: 
     238            first_bin = first_bin - self.nbins_low 
     239        # For last bin 
     240        if last_bin >= (self.nbins - self.nbins_high): 
     241            last_bin  = self.nbins - (self.nbins_high + self.nbins_low + 1) 
     242        elif last_bin >= self.nbins_low: 
     243            last_bin = last_bin - self.nbins_low 
     244        else: 
     245            last_bin = 0 
     246        return first_bin, last_bin 
     247     
     248    def _get_extrapolated_bin(self, first_bin = 0, last_bin = 0): 
     249        """ 
     250        Get extrapolated first bin and the last bin 
     251         
     252        : param first_bin: unextrapolated first_bin 
     253        : param last_bin: unextrapolated last_bin 
     254         
     255        : return first_bin, last_bin: extrapolated first and last bin 
     256        """ 
     257        #  For the first bin 
     258        if first_bin > 0: 
     259            # In the case that doesn't need lower q extrapolation data  
     260            first_bin +=  self.nbins_low 
     261        else: 
     262            # In the case that needs low extrapolation data 
     263            first_bin = 0 
     264        # For last bin 
     265        if last_bin >= self.nbins - (self.nbins_high + self.nbins_low + 1): 
     266            # In the case that needs higher q extrapolation data  
     267            last_bin = self.nbins - 1 
     268        else: 
     269            # In the case that doesn't need higher q extrapolation data  
     270             last_bin += self.nbins_low 
     271 
     272        return first_bin, last_bin 
     273         
    181274class _SlitSmearer(_BaseSmearer): 
    182275    """ 
     
    253346        ## Slit width 
    254347        self.width = 0 
     348        self.nbins_low = 0 
     349        self.nbins_high = 0 
    255350        if data1D.dxw is not None and len(data1D.dxw) == len(data1D.x): 
    256351            self.width = data1D.dxw[0] 
     
    342437    Adaptor for Gaussian Q smearing class and SANS data 
    343438    """ 
    344     def __init__(self, data1D): 
     439    def __init__(self, data1D, model = None): 
    345440        """ 
    346441        Assumption: equally spaced bins of increasing q-values. 
     
    350445        # Initialization from parent class 
    351446        super(QSmearer, self).__init__() 
    352          
     447        data1d_x = [] 
     448        self.nbins_low = 0 
     449        self.nbins_high = 0 
     450        self.model = model 
    353451        ## Resolution 
    354         self.width = numpy.zeros(len(data1D.x)) 
     452        #self.width = numpy.zeros(len(data1D.x)) 
    355453        if data1D.dx is not None and len(data1D.dx) == len(data1D.x): 
    356454            self.width = data1D.dx 
    357455         
     456        if self.model == None: 
     457            data1d_x = data1D.x 
     458        else: 
     459            self.nbins_low, self.nbins_high, self.width, data1d_x = \ 
     460                                get_qextrapolate(self.width, data1D.x) 
     461 
    358462        ## Number of Q bins 
    359         self.nbins = len(data1D.x) 
     463        self.nbins = len(data1d_x) 
    360464        ## Minimum Q  
    361         self.min = min(data1D.x) 
     465        self.min = min(data1d_x) 
    362466        ## Maximum 
    363         self.max = max(data1D.x) 
     467        self.max = max(data1d_x) 
    364468        ## Q-values 
    365         self.qvalues = data1D.x 
    366  
    367  
     469        self.qvalues = data1d_x 
     470 
     471         
     472def get_qextrapolate(width, data_x): 
     473    """ 
     474    Make fake data_x points extrapolated outside of the data_x points 
     475     
     476    : param width: array of std of q resolution 
     477    : param Data1D.x: Data1D.x array 
     478     
     479    : return new_width, data_x_ext: extrapolated width array and x array 
     480     
     481    : assumption1: data_x is ordered from lower q to higher q 
     482    : assumption2: len(data) = len(width) 
     483    : assumption3: the distance between the data points is more compact  
     484            than the size of width  
     485    : Todo1: Make sure that the assumptions are correct for Data1D 
     486    : Todo2: This fixes the edge problem in Qsmearer but still needs to make  
     487            smearer interface  
     488    """ 
     489    # Length of the width 
     490    length = len(width) 
     491    max_width = max(width) 
     492    # Find bin sizes 
     493    bin_size_low = math.fabs(data_x[1] - data_x[0]) 
     494    bin_size_high = math.fabs(data_x[length -1] - data_x[length -2]) 
     495    # Number of q points required below the 1st data point in order to extend 
     496    # them 3 times of the width (std) 
     497    nbins_low = math.ceil(3 * max_width / bin_size_low) 
     498    # Number of q points required above the last data point 
     499    nbins_high = math.ceil(3 * max_width / (bin_size_high)) 
     500    # Make null q points         
     501    extra_low = numpy.zeros(nbins_low) 
     502    extra_high = numpy.zeros(nbins_high) 
     503    # Give extrapolated values 
     504    ind = 0 
     505    qvalue = data_x[0] - bin_size_low 
     506    while(ind < nbins_low): 
     507        extra_low[nbins_low - (ind + 1)] = qvalue 
     508        qvalue -= bin_size_low 
     509        ind += 1 
     510    # Remove the points <= 0 
     511    extra_low = extra_low[extra_low > 0] 
     512    nbins_low = len(extra_low) 
     513    # Reset ind for another extrapolation 
     514    ind = 0 
     515    qvalue = data_x[length -1] + bin_size_high 
     516    while(ind < nbins_high): 
     517        extra_high[ind] = qvalue 
     518        qvalue += bin_size_high 
     519        ind += 1 
     520    # Make a new qx array 
     521    data_x_ext = numpy.append(extra_low, data_x) 
     522    data_x_ext = numpy.append(data_x_ext, extra_high) 
     523    # Redefine extra_low and high based on corrected nbins   
     524    # And note that it is not necessary for extra_width to be a non-zero       
     525    extra_low = numpy.zeros(nbins_low) 
     526    extra_high = numpy.zeros(nbins_high)  
     527    # Make new width array 
     528    new_width = numpy.append(extra_low, width) 
     529    new_width = numpy.append(new_width, extra_high) 
     530 
     531    return  nbins_low, nbins_high, new_width, data_x_ext 
     532     
    368533if __name__ == '__main__': 
    369534    x = 0.001 * numpy.arange(1, 11) 
  • DataLoader/test/utest_smearing.py

    r5859862 rf867cd9  
    8989                  5.00093415,   4.01898292,   3.15008701,   2.55214921] 
    9090        for i in range(len(input)): 
    91             self.assertAlmostEqual(answer[i], output[i], 5) 
     91            self.assertAlmostEqual(answer[i], output[i], 4) 
    9292       
    9393 
Note: See TracChangeset for help on using the changeset viewer.