Changeset 2e83ff3 in sasview


Ignore:
Timestamp:
Sep 22, 2008 3:53:09 PM (16 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:
1374174f
Parents:
55fd102
Message:

Added sector average (phi and q)

Location:
DataLoader
Files:
4 added
2 edited

Legend:

Unmodified
Added
Removed
  • DataLoader/manipulations.py

    r70975f3 r2e83ff3  
    1515""" 
    1616#TODO: copy the meta data from the 2D object to the resulting 1D object 
    17 #TODO: Don't assume square pixels 
    1817 
    1918from data_info import plottable_2D, Data1D 
     
    222221            raise RuntimeError, "Circular averaging: invalid number of detectors: %g" % len(data2D.detector) 
    223222         
    224         pixel_width = data2D.detector[0].pixel_size.x 
     223        pixel_width_x = data2D.detector[0].pixel_size.x 
     224        pixel_width_y = data2D.detector[0].pixel_size.y 
    225225        det_dist    = data2D.detector[0].distance 
    226226        wavelength  = data2D.source.wavelength 
    227         center_x    = data2D.detector[0].beam_center.x/pixel_width 
    228         center_y    = data2D.detector[0].beam_center.y/pixel_width 
     227        center_x    = data2D.detector[0].beam_center.x/pixel_width_x 
     228        center_y    = data2D.detector[0].beam_center.y/pixel_width_y 
    229229                 
    230230        y  = 0.0 
     
    232232        y_counts = 0.0 
    233233                 
    234         for i in range(len(data2D.data)): 
     234        for i in range(numpy.size(data2D.data,1)): 
    235235            # Min and max x-value for the pixel 
    236             minx = pixel_width*(i - center_x) 
    237             maxx = pixel_width*(i+1.0 - center_x) 
     236            minx = pixel_width_x*(i - center_x) 
     237            maxx = pixel_width_x*(i+1.0 - center_x) 
    238238             
    239239            qxmin = get_q(minx, 0.0, det_dist, wavelength) 
     
    245245            frac_x = frac_max - frac_min 
    246246             
    247             for j in range(len(data2D.data)): 
     247            for j in range(numpy.size(data2D.data,0)): 
    248248                # Min and max y-value for the pixel 
    249                 miny = pixel_width*(j - center_y) 
    250                 maxy = pixel_width*(j+1.0 - center_y) 
     249                miny = pixel_width_y*(j - center_y) 
     250                maxy = pixel_width_y*(j+1.0 - center_y) 
    251251 
    252252                qymin = get_q(0.0, miny, det_dist, wavelength) 
     
    339339            raise RuntimeError, "Circular averaging: invalid number of detectors: %g" % len(data2D.detector) 
    340340         
    341         pixel_width = data2D.detector[0].pixel_size.x 
     341        pixel_width_x = data2D.detector[0].pixel_size.x 
     342        pixel_width_y = data2D.detector[0].pixel_size.y 
    342343        det_dist    = data2D.detector[0].distance 
    343344        wavelength  = data2D.source.wavelength 
    344         center_x    = data2D.detector[0].beam_center.x/pixel_width 
    345         center_y    = data2D.detector[0].beam_center.y/pixel_width 
     345        center_x    = data2D.detector[0].beam_center.x/pixel_width_x 
     346        center_y    = data2D.detector[0].beam_center.y/pixel_width_y 
    346347         
    347348        # Find out the maximum Q range 
    348         xwidth = numpy.size(data2D.data,1)*pixel_width 
     349        xwidth = numpy.size(data2D.data,1)*pixel_width_x 
    349350        dx_max = xwidth - data2D.detector[0].beam_center.x 
    350351        if xwidth-dx_max>dx_max: 
    351352            dx_max = xwidth-dx_max 
    352353             
    353         ywidth = numpy.size(data2D.data,0)*pixel_width 
     354        ywidth = numpy.size(data2D.data,0)*pixel_width_y 
    354355        dy_max = ywidth - data2D.detector[0].beam_center.y 
    355356        if ywidth-dy_max>dy_max: 
     
    367368        y_counts = numpy.zeros(nbins) 
    368369         
    369         for i in range(len(data2D.data)): 
    370             dx = pixel_width*(i+0.5 - center_x) 
     370        for i in range(numpy.size(data2D.data,1)): 
     371            dx = pixel_width_x*(i+0.5 - center_x) 
    371372             
    372373            # Min and max x-value for the pixel 
    373             minx = pixel_width*(i - center_x) 
    374             maxx = pixel_width*(i+1.0 - center_x) 
    375              
    376             for j in range(len(data2D.data)): 
    377                 dy = pixel_width*(j+0.5 - center_y) 
     374            minx = pixel_width_x*(i - center_x) 
     375            maxx = pixel_width_x*(i+1.0 - center_x) 
     376             
     377            for j in range(numpy.size(data2D.data,0)): 
     378                dy = pixel_width_y*(j+0.5 - center_y) 
    378379             
    379380                q_value = get_q(dx, dy, det_dist, wavelength) 
    380381             
    381382                # Min and max y-value for the pixel 
    382                 miny = pixel_width*(j - center_y) 
    383                 maxy = pixel_width*(j+1.0 - center_y) 
     383                miny = pixel_width_y*(j - center_y) 
     384                maxy = pixel_width_y*(j+1.0 - center_y) 
    384385                 
    385386                # Calculate the q-value for each corner 
     
    463464        if len(data2D.detector) != 1: 
    464465            raise RuntimeError, "Ring averaging: invalid number of detectors: %g" % len(data2D.detector) 
    465         pixel_width = data2D.detector[0].pixel_size.x 
     466        pixel_width_x = data2D.detector[0].pixel_size.x 
     467        pixel_width_y = data2D.detector[0].pixel_size.y 
    466468        det_dist = data2D.detector[0].distance 
    467469        wavelength = data2D.source.wavelength 
    468         center_x = self.center_x/pixel_width 
    469         center_y = self.center_y/pixel_width 
     470        #center_x = self.center_x/pixel_width_x 
     471        #center_y = self.center_y/pixel_width_y 
     472        center_x    = data2D.detector[0].beam_center.x/pixel_width_x 
     473        center_y    = data2D.detector[0].beam_center.y/pixel_width_y 
     474         
    470475         
    471476        phi_bins   = numpy.zeros(self.nbins_phi) 
     
    474479        phi_err    = numpy.zeros(self.nbins_phi) 
    475480         
    476         for i in range(len(data)): 
    477             dx = pixel_width*(i+0.5 - center_x) 
     481        for i in range(numpy.size(data,1)): 
     482            dx = pixel_width_x*(i+0.5 - center_x) 
    478483             
    479484            # Min and max x-value for the pixel 
    480             minx = pixel_width*(i - center_x) 
    481             maxx = pixel_width*(i+1.0 - center_x) 
    482              
    483             for j in range(len(data)): 
    484                 dy = pixel_width*(j+0.5 - center_y) 
     485            minx = pixel_width_x*(i - center_x) 
     486            maxx = pixel_width_x*(i+1.0 - center_x) 
     487             
     488            for j in range(numpy.size(data,0)): 
     489                dy = pixel_width_y*(j+0.5 - center_y) 
    485490             
    486491                q_value = get_q(dx, dy, det_dist, wavelength) 
    487492             
    488493                # Min and max y-value for the pixel 
    489                 miny = pixel_width*(j - center_y) 
    490                 maxy = pixel_width*(j+1.0 - center_y) 
     494                miny = pixel_width_y*(j - center_y) 
     495                maxy = pixel_width_y*(j+1.0 - center_y) 
    491496                 
    492497                # Calculate the q-value for each corner 
     
    512517                frac = frac_max - frac_min 
    513518 
    514                 i_phi = int(math.ceil(self.nbins_phi*(math.atan2(dy, dx)+math.pi)/(2.0*math.pi)) - 1) 
     519                i_phi = int(math.ceil(self.nbins_phi*(math.atan2(dy, dx)+math.pi)/(2.0*math.pi))) - 1 
    515520             
    516521                phi_bins[i_phi] += frac * data[j][i] 
     
    629634     
    630635 
    631 class Sector: 
     636class _Sector: 
    632637    """ 
    633638        Defines a sector region on a 2D data set. 
    634639        The sector is defined by r_min, r_max, phi_min, phi_max, 
    635640        and the position of the center of the ring.  
    636     """ 
    637     pass 
     641         
     642        Phi is defined between 0 and 2pi 
     643    """ 
     644    def __init__(self, r_min, r_max, phi_min, phi_max): 
     645        self.r_min = r_min 
     646        self.r_max = r_max 
     647        self.phi_min = phi_min 
     648        self.phi_max = phi_max 
     649        self.nbins = 20 
     650         
     651    def _agv(self, data2D, run='phi'): 
     652        """ 
     653            Perform sector averaging. 
     654             
     655            @param data2D: Data2D object 
     656            @param run:  define the varying parameter ('phi' or 'q') 
     657            @return: Data1D object 
     658        """ 
     659        if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 
     660            raise RuntimeError, "Ring averaging only take plottable_2D objects" 
     661         
     662        data = data2D.data 
     663        qmin = self.r_min 
     664        qmax = self.r_max 
     665         
     666        if len(data2D.detector) != 1: 
     667            raise RuntimeError, "Ring averaging: invalid number of detectors: %g" % len(data2D.detector) 
     668        pixel_width_x = data2D.detector[0].pixel_size.x 
     669        pixel_width_y = data2D.detector[0].pixel_size.y 
     670        det_dist      = data2D.detector[0].distance 
     671        wavelength    = data2D.source.wavelength 
     672        center_x      = data2D.detector[0].beam_center.x/pixel_width_x 
     673        center_y      = data2D.detector[0].beam_center.y/pixel_width_y 
     674         
     675        y        = numpy.zeros(self.nbins) 
     676        y_counts = numpy.zeros(self.nbins) 
     677        x        = numpy.zeros(self.nbins) 
     678        y_err    = numpy.zeros(self.nbins) 
     679         
     680        for i in range(numpy.size(data,1)): 
     681            dx = pixel_width_x*(i+0.5 - center_x) 
     682             
     683            # Min and max x-value for the pixel 
     684            minx = pixel_width_x*(i - center_x) 
     685            maxx = pixel_width_x*(i+1.0 - center_x) 
     686             
     687            for j in range(numpy.size(data,0)): 
     688                dy = pixel_width_y*(j+0.5 - center_y) 
     689             
     690                q_value = get_q(dx, dy, det_dist, wavelength) 
     691 
     692                # Min and max y-value for the pixel 
     693                miny = pixel_width_y*(j - center_y) 
     694                maxy = pixel_width_y*(j+1.0 - center_y) 
     695                 
     696                # Calculate the q-value for each corner 
     697                # q_[x min or max][y min or max] 
     698                q_00 = get_q(minx, miny, det_dist, wavelength) 
     699                q_01 = get_q(minx, maxy, det_dist, wavelength) 
     700                q_10 = get_q(maxx, miny, det_dist, wavelength) 
     701                q_11 = get_q(maxx, maxy, det_dist, wavelength) 
     702                 
     703                # Look for intercept between each side of the pixel 
     704                # and the constant-q ring for qmax 
     705                frac_max = get_pixel_fraction(qmax, q_00, q_01, q_10, q_11) 
     706                 
     707                # Look for intercept between each side of the pixel 
     708                # and the constant-q ring for qmin 
     709                frac_min = get_pixel_fraction(qmin, q_00, q_01, q_10, q_11) 
     710                 
     711                # We are interested in the region between qmin and qmax 
     712                # therefore the fraction of the surface of the pixel 
     713                # that we will use to calculate the number of counts to  
     714                # include is given by: 
     715                 
     716                frac = frac_max - frac_min 
     717 
     718                # Compute phi and check whether it's within the limits 
     719                phi_value = math.atan2(dy, dx)+math.pi 
     720                if phi_value<self.phi_min or phi_value>self.phi_max: 
     721                    continue 
     722                                                     
     723                # Check which type of averaging we need 
     724                if run.lower()=='phi':  
     725                    i_bin = int(math.ceil(self.nbins*(phi_value-self.phi_min)/(self.phi_max-self.phi_min))) - 1 
     726                else: 
     727                    # If we don't need this pixel, skip the rest of the work 
     728                    #TODO: an improvement here would be to compute the average 
     729                    # Q for the pixel from the part that is covered by 
     730                    # the ring defined by q_min/q_max rather than the complete 
     731                    # pixel  
     732                    if q_value<self.r_min or q_value>self.r_max: 
     733                        continue 
     734                    i_bin = int(math.ceil(self.nbins*(q_value-self.r_min)/(self.r_max-self.r_min))) - 1 
     735             
     736                try: 
     737                    y[i_bin] += frac * data[j][i] 
     738                except: 
     739                    import sys 
     740                    print sys.exc_value 
     741                    print i_bin, frac 
     742                 
     743                if data2D.err_data == None or data2D.err_data[j][i]==0.0: 
     744                    y_err[i_bin] += frac * frac * math.fabs(data2D.data[j][i]) 
     745                else: 
     746                    y_err[i_bin] += frac * frac * data2D.err_data[j][i] * data2D.err_data[j][i] 
     747                y_counts[i_bin] += frac 
     748         
     749        for i in range(self.nbins): 
     750            y[i] = y[i] / y_counts[i] 
     751            y_err[i] = math.sqrt(y_err[i]) / y_counts[i] 
     752            # Check which type of averaging we need 
     753            if run.lower()=='phi': 
     754                x[i] = (self.phi_max-self.phi_min)/self.nbins*(1.0*i + 0.5)+self.phi_min 
     755            else: 
     756                x[i] = (self.r_max-self.r_min)/self.nbins*(1.0*i + 0.5)+self.r_min 
     757             
     758        return Data1D(x=x, y=y, dy=y_err) 
     759         
     760         
     761class SectorPhi(_Sector): 
     762    """ 
     763        Sector average as a function of phi. 
     764        I(phi) is return and the data is averaged over Q. 
     765         
     766        A sector is defined by r_min, r_max, phi_min, phi_max. 
     767        The number of bin in phi also has to be defined. 
     768    """ 
     769    def __call__(self, data2D): 
     770        """ 
     771            Perform sector average and return I(phi). 
     772             
     773            @param data2D: Data2D object 
     774            @return: Data1D object 
     775        """ 
     776        return self._agv(data2D, 'phi') 
     777 
     778class SectorQ(_Sector): 
     779    """ 
     780        Sector average as a function of Q. 
     781        I(Q) is return and the data is averaged over phi. 
     782         
     783        A sector is defined by r_min, r_max, phi_min, phi_max. 
     784        The number of bin in Q also has to be defined. 
     785    """ 
     786    def __call__(self, data2D): 
     787        """ 
     788            Perform sector average and return I(Q). 
     789             
     790            @param data2D: Data2D object 
     791            @return: Data1D object 
     792        """ 
     793        return self._agv(data2D, 'q') 
    638794 
    639795if __name__ == "__main__":  
     
    646802 
    647803     
    648     #r = Boxsum(x_min=.2, x_max=.4, y_min=0.2, y_max=0.4) 
    649     r = SlabX(x_min=-.01, x_max=.01, y_min=-0.0002, y_max=0.0002, bin_width=0.0004) 
    650     r.fold = False 
     804    r = SectorQ(r_min=.005, r_max=.01, phi_min=0.0, phi_max=math.pi/2.0) 
    651805    o = r(d) 
    652806     
    653     #s = SlabY(x_min=-.01, x_max=.01, y_min=-0.0002, y_max=0.0002, bin_width=0.0004) 
    654     #s.fold = False 
    655     #p = s(d) 
     807    s = Ring(r_min=.005, r_max=.01)  
     808    p = s(d) 
    656809     
    657810    for i in range(len(o.x)): 
  • DataLoader/test/utest_averaging.py

    rf8d0ee7 r2e83ff3  
    6161        self.assertAlmostEqual(ds, 0.011979881083557541, 4) 
    6262             
     63    def test_slabX(self): 
     64        """ 
     65            Test slab in X 
     66            The test data was not generated by IGOR. 
     67        """ 
     68        from DataLoader.manipulations import SlabX 
     69         
     70        r = SlabX(x_min=-.01, x_max=.01, y_min=-0.0002, y_max=0.0002, bin_width=0.0004) 
     71        r.fold = False 
     72        o = r(self.data) 
     73     
     74        answer = Loader().load('slabx_testdata.txt') 
     75        for i in range(len(o.x)): 
     76            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     77            self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
     78            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
     79             
     80    def test_slabY(self): 
     81        """ 
     82            Test slab in Y 
     83            The test data was not generated by IGOR. 
     84        """ 
     85        from DataLoader.manipulations import SlabY 
     86         
     87        r = SlabY(x_min=.005, x_max=.01, y_min=-0.01, y_max=0.01, bin_width=0.0004) 
     88        r.fold = False 
     89        o = r(self.data) 
     90     
     91        answer = Loader().load('slaby_testdata.txt') 
     92        for i in range(len(o.x)): 
     93            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     94            self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
     95            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
     96             
     97    def test_sectorphi_full(self): 
     98        """ 
     99            Test sector averaging I(phi) 
     100            When considering the whole azimuthal range (2pi),  
     101            the answer should be the same as ring averaging. 
     102            The test data was not generated by IGOR. 
     103        """ 
     104        from DataLoader.manipulations import SectorPhi 
     105        import math 
     106         
     107        r = SectorPhi(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi*2.0) 
     108        r.nbins_phi = 20 
     109        o = r(self.data) 
     110     
     111        answer = Loader().load('ring_testdata.txt') 
     112        for i in range(len(o.x)): 
     113            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     114            self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
     115            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
     116             
     117    def test_sectorphi_quarter(self): 
     118        """ 
     119            Test sector averaging I(phi) 
     120            The test data was not generated by IGOR. 
     121        """ 
     122        from DataLoader.manipulations import SectorPhi 
     123        import math 
     124         
     125        r = SectorPhi(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi/2.0) 
     126        r.nbins_phi = 20 
     127        o = r(self.data) 
     128     
     129        answer = Loader().load('sectorphi_testdata.txt') 
     130        for i in range(len(o.x)): 
     131            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     132            self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
     133            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
     134             
     135    def test_sectorq_full(self): 
     136        """ 
     137            Test sector averaging I(q) 
     138            The test data was not generated by IGOR. 
     139        """ 
     140        from DataLoader.manipulations import SectorQ 
     141        import math 
     142         
     143        r = SectorQ(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi/2.0) 
     144        r.nbins_phi = 20 
     145        o = r(self.data) 
     146     
     147        answer = Loader().load('sectorq_testdata.txt') 
     148        for i in range(len(o.x)): 
     149            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     150            self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
     151            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
     152             
    63153 
    64154if __name__ == '__main__': 
Note: See TracChangeset for help on using the changeset viewer.