Changeset a3f8d58 in sasview for DataLoader


Ignore:
Timestamp:
Jul 18, 2009 4:40:57 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:
72c7d31
Parents:
ba95543
Message:

dataloader: converted smearing to C and allowed for partial Q range

Location:
DataLoader
Files:
4 added
4 edited

Legend:

Unmodified
Added
Removed
  • DataLoader/.pydevproject

    r11a0319 ra3f8d58  
    55<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH"> 
    66<path>/DataLoader/src</path> 
     7<path>/DataLoader/extensions</path> 
    78</pydev_pathproperty> 
    89<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.5</pydev_property> 
     10<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property> 
    911</pydev_project> 
  • DataLoader/qsmearing.py

    rc7ac15e ra3f8d58  
    66See the license text in license.txt 
    77 
    8 copyright 2008, University of Tennessee 
     8copyright 2009, University of Tennessee 
    99""" 
    1010 
    11  
     11import DataLoader.extensions.smearer as smearer 
    1212import numpy 
    1313import math 
     
    7171                _found_resolution = False 
    7272                break 
    73     #print "_found_slit",_found_slit  
    74     #print "data1D.dx[0]",data1D.dx[0],data1D.dxl[0]        
    7573    # If we found slit smearing data, return a slit smearer 
    7674    if _found_slit == True: 
     
    8583        self.nbins = 0 
    8684        self._weights = None 
     85        ## Internal flag to keep track of C++ smearer initialization 
     86        self._init_complete = False 
     87        self._smearer = None 
     88         
     89    def __deepcopy__(self, memo={}): 
     90        """ 
     91            Return a valid copy of self. 
     92            Avoid copying the _smearer C object and force a matrix recompute 
     93            when the copy is used.   
     94        """ 
     95        result = _BaseSmearer() 
     96        result.nbins = self.nbins 
     97        return result 
     98 
    8799         
    88100    def _compute_matrix(self): return NotImplemented 
    89101 
    90     def __call__(self, iq): 
    91         """ 
    92             Return the smeared I(q) value at the given q. 
    93             The smeared I(q) is computed using a predetermined  
    94             smearing matrix for a particular binning. 
    95          
    96             @param q: I(q) array 
    97             @return: smeared I(q) 
    98         """ 
     102    def __call__(self, iq_in, first_bin=0, last_bin=None): 
     103        """ 
     104            Perform smearing 
     105        """ 
     106        # If this is the first time we call for smearing, 
     107        # initialize the C++ smearer object first 
     108        if not self._init_complete: 
     109            self._initialize_smearer() 
     110              
     111        # Get the max value for the last bin 
     112        if last_bin is None or last_bin>=len(iq_in): 
     113            last_bin = len(iq_in)-1 
     114        # Check that the first bin is positive 
     115        if first_bin<0: 
     116            first_bin = 0 
     117             
    99118        # Sanity check 
    100         if len(iq) != self.nbins: 
    101             raise RuntimeError, "Invalid I(q) vector: inconsistent array length %s <> %s" % (len(iq), self.nbins) 
    102          
    103         if self._weights == None: 
    104             self._compute_matrix() 
    105              
    106         iq_smeared = numpy.zeros(self.nbins) 
    107         # Loop over q-values 
    108         idwb=[] 
    109          
    110         for q_i in range(self.nbins): 
    111             sum = 0.0 
    112             counts = 0.0   
    113  
    114             for i in range(self.nbins): 
    115                 if iq[i]==0 or self._weights[q_i][i]==0: 
    116                     continue 
    117                 else: 
    118                     sum += iq[i] * self._weights[q_i][i]  
    119                     counts += self._weights[q_i][i] 
    120                     #print "i,iq[i],self._weights[q_i][i] ",i,iq[i],self._weights[q_i][i] 
    121             if counts == 0: 
    122                 iq_smeared[q_i] = 0 
    123             else: 
    124                 iq_smeared[q_i] = sum/counts  
    125             #print "q_i,iq_smeared[q_i]",q_i,iq[i],iq_smeared[q_i] 
    126             #print "iq[i],iq_smeared[q_i],sum,counts,self.nbins",iq[i], iq_smeared[q_i],sum,counts,self.nbins 
    127         return iq_smeared     
     119        if len(iq_in) != self.nbins: 
     120            raise RuntimeError, "Invalid I(q) vector: inconsistent array length %d != %s" % (len(iq_in), str(self.nbins)) 
     121              
     122        # Storage for smeared I(q)    
     123        iq_out = numpy.zeros(self.nbins) 
     124        smearer.smear(self._smearer, iq_in, iq_out, first_bin, last_bin) 
     125        return iq_out 
    128126     
    129127class _SlitSmearer(_BaseSmearer): 
     
    142140            @param max: Q_max [A-1] 
    143141        """ 
     142        _BaseSmearer.__init__(self) 
    144143        ## Slit width in Q units 
    145144        self.width  = width 
     
    157156        self._weights = None 
    158157         
    159     def _compute_matrix(self): 
    160         """ 
    161             Compute the smearing matrix for the current I(q) array 
    162         """ 
    163         weights = numpy.zeros([self.nbins, self.nbins]) 
    164          
    165         # Loop over all q-values 
    166         for i in range(self.nbins): 
    167             q = self.min + i*(self.max-self.min)/float(self.nbins-1.0) 
    168              
    169             # For each q-value, compute the weight of each other q-bin 
    170             # in the I(q) array 
    171             npts_h = self.npts if self.height>0 else 1  
    172             npts_w = self.npts if self.width>0 else 1  
    173              
    174             # If both height and width are great than zero, 
    175             # modify the number of points in each direction so  
    176             # that the total number of points is still what  
    177             # the user would expect (downgrade resolution) 
    178             if npts_h>1 and npts_w>1: 
    179                 npts_h = int(math.ceil(math.sqrt(self.npts))) 
    180                 npts_w = npts_h 
    181                  
    182             for k in range(npts_h): 
    183                 if npts_h==1: 
    184                     shift_h = 0 
    185                 else: 
    186                     shift_h = self.height/(float(npts_h-1.0)) * k 
    187                 for j in range(npts_w): 
    188                     if npts_w==1: 
    189                         shift_w = 0 
    190                     else: 
    191                         shift_w = self.width/(float(npts_w-1.0)) * j 
    192                     q_shifted = math.sqrt( ((q-shift_w)*(q-shift_w) + shift_h*shift_h) ) 
    193                     q_i = int(math.floor( (q_shifted-self.min)/((self.max-self.min)/(self.nbins -1.0)) )) 
    194                      
    195                     # Skip the entries outside our I(q) range 
    196                     #TODO: be careful with edge effect 
    197                     if q_i<self.nbins: 
    198                         weights[i][q_i] = weights[i][q_i]+1.0 
    199  
    200         self._weights = weights 
    201         return self._weights 
     158    def _initialize_smearer(self): 
     159        """ 
     160            Initialize the C++ smearer object. 
     161            This method HAS to be called before smearing 
     162        """ 
     163        self._smearer = smearer.new_slit_smearer(self.width, self.height, self.min, self.max, self.nbins) 
     164        self._init_complete = True 
     165 
    202166 
    203167class SlitSmearer(_SlitSmearer): 
     
    255219            @param max: Q_max [A-1] 
    256220        """ 
     221        _BaseSmearer.__init__(self) 
    257222        ## Standard deviation in Q [A-1] 
    258223        self.width  = width 
     
    266231        self._weights = None 
    267232         
    268     def _compute_matrix(self): 
    269         """ 
    270             Compute the smearing matrix for the current I(q) array 
    271         """ 
    272         weights = numpy.zeros([self.nbins, self.nbins]) 
    273          
    274         # Loop over all q-values 
    275         step = (self.max-self.min)/float(self.nbins-1.0) 
    276         for i in range(self.nbins): 
    277             q = self.min + i*step 
    278             q_min = q - 0.5*step 
    279             q_max = q + 0.5*step 
    280             for j in range(self.nbins): 
    281                 q_j = self.min + j*step 
    282                  
    283                 # Compute the fraction of the Gaussian contributing 
    284                 # to the q bin between q_min and q_max 
    285                 #value =  math.exp(-math.pow((q_max-q_j),2)/(2*math.pow(self.width[j],2) )) 
    286                 #value +=  math.exp(-math.pow((q_max-q_j),2)/(2*math.pow(self.width[j],2) ))  
    287                 value =  scipy.special.erf( (q_max-q_j)/(math.sqrt(2.0)*self.width[j]) )  
    288                 value -=scipy.special.erf( (q_min-q_j)/(math.sqrt(2.0)*self.width[j]) )  
    289                 weights[i][j] += value 
    290                                  
    291         self._weights = weights 
    292         return self._weights 
     233    def _initialize_smearer(self): 
     234        """ 
     235            Initialize the C++ smearer object. 
     236            This method HAS to be called before smearing 
     237        """ 
     238        self._smearer = smearer.new_q_smearer(numpy.asarray(self.width), self.min, self.max, self.nbins) 
     239        self._init_complete = True 
    293240         
    294241class QSmearer(_QSmearer): 
  • DataLoader/setup.py

    r07f8d9a ra3f8d58  
    22     Installation script for SANS DataLoader 
    33""" 
    4 import os 
     4import os, sys 
    55 
    66# Then build and install the modules 
    77from distutils.core import setup, Extension 
    88from distutils.sysconfig import get_python_lib 
    9  
     9numpy_incl_path = os.path.join(sys.prefix, "Lib", "site-packages", "numpy", "core", "include", "numpy") 
    1010 
    1111setup( 
     
    1414    description = "Python module for loading", 
    1515    author = "University of Tennessee", 
    16     #author_email = "", 
    1716    url = "http://danse.chem.utk.edu", 
    1817     
    19     # Use the pure python modules 
    20     package_dir = {"DataLoader":"."}, 
     18    package_dir = {"DataLoader":".", 
     19                   "DataLoader.extensions":"extensions"}, 
    2120     
    22     packages = ["DataLoader","DataLoader.readers"], 
    23     data_files=[(os.path.join(get_python_lib(),"DataLoader","readers"), ["readers/defaults.xml"])] 
    24     ) 
     21    data_files=[(os.path.join(get_python_lib(),"DataLoader","readers"), ["readers/defaults.xml"])], 
     22    packages = ["DataLoader","DataLoader.readers","DataLoader.extensions"], 
     23     
     24    ext_modules = [ Extension("DataLoader.extensions.smearer", 
     25     sources = [ 
     26        "extensions/smearer_module.cpp", 
     27        "extensions/smearer.cpp", 
     28            ], 
     29         include_dirs=["extensions", numpy_incl_path] 
     30      
     31      
     32     )]) 
    2533         
  • DataLoader/test/utest_smearing.py

    r4fe4394 ra3f8d58  
    5656        answer = [ 9.666,  9.056,  8.329,  7.494,  6.642,  5.721,  4.774,  3.824,  2.871, 2.   ] 
    5757        for i in range(len(input)): 
    58             self.assertAlmostEqual(answer[i], output[i], 5) 
     58            self.assertAlmostEqual(answer[i], output[i], 2) 
    5959         
    6060    def test_q(self): 
     
    6868        output = s(input) 
    6969        for i in range(len(input)): 
    70             self.assertEquals(input[i], output[i]) 
     70            self.assertAlmostEquals(input[i], output[i], 5) 
    7171 
    7272    def test_q2(self): 
Note: See TracChangeset for help on using the changeset viewer.