Index: run.py
===================================================================
--- run.py	(revision f94a935e45e0206bda8929f0e74ea1ab98e9c18f)
+++ run.py	(revision f36e01fa1b9b521d3f7496b637e33bed18626df2)
@@ -51,5 +51,4 @@
 def import_package(modname, path):
     """Import a package into a particular point in the python namespace"""
-    #logger.debug("Dynamicly importing: %s", path)
     mod = imp.load_source(modname, abspath(joinpath(path, '__init__.py')))
     sys.modules[modname] = mod
Index: src/sas/sascalc/dataloader/manipulations.py
===================================================================
--- src/sas/sascalc/dataloader/manipulations.py	(revision b290a9ed6c2a596ca4ab749a77e177563f10f071)
+++ src/sas/sascalc/dataloader/manipulations.py	(revision 7432acb919f4013119ca918a73350297e0d4c93f)
@@ -1,27 +1,18 @@
-from __future__ import division
 """
 Data manipulations for 2D data sets.
 Using the meta data information, various types of averaging
 are performed in Q-space
-
-To test this module use:
-```
-cd test
-PYTHONPATH=../src/ python2  -m sasdataloader.test.utest_averaging DataInfoTests.test_sectorphi_quarter
-```
 """
 #####################################################################
-# This software was developed by the University of Tennessee as part of the
-# Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-# project funded by the US National Science Foundation.
-# See the license text in license.txt
-# copyright 2008, University of Tennessee
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#See the license text in license.txt
+#copyright 2008, University of Tennessee
 ######################################################################
 
-
-# TODO: copy the meta data from the 2D object to the resulting 1D object
+#TODO: copy the meta data from the 2D object to the resulting 1D object
 import math
-import numpy as np
-import sys
+import numpy
 
 #from data_info import plottable_2D
@@ -79,4 +70,302 @@
     return phi_out
 
+
+def reader2D_converter(data2d=None):
+    """
+    convert old 2d format opened by IhorReader or danse_reader
+    to new Data2D format
+
+    :param data2d: 2d array of Data2D object
+    :return: 1d arrays of Data2D object
+
+    """
+    if data2d.data is None or data2d.x_bins is None or data2d.y_bins is None:
+        raise ValueError, "Can't convert this data: data=None..."
+    new_x = numpy.tile(data2d.x_bins, (len(data2d.y_bins), 1))
+    new_y = numpy.tile(data2d.y_bins, (len(data2d.x_bins), 1))
+    new_y = new_y.swapaxes(0, 1)
+
+    new_data = data2d.data.flatten()
+    qx_data = new_x.flatten()
+    qy_data = new_y.flatten()
+    q_data = numpy.sqrt(qx_data * qx_data + qy_data * qy_data)
+    if data2d.err_data is None or numpy.any(data2d.err_data <= 0):
+        new_err_data = numpy.sqrt(numpy.abs(new_data))
+    else:
+        new_err_data = data2d.err_data.flatten()
+    mask = numpy.ones(len(new_data), dtype=bool)
+
+    #TODO: make sense of the following two lines...
+    #from sas.sascalc.dataloader.data_info import Data2D
+    #output = Data2D()
+    output = data2d
+    output.data = new_data
+    output.err_data = new_err_data
+    output.qx_data = qx_data
+    output.qy_data = qy_data
+    output.q_data = q_data
+    output.mask = mask
+
+    return output
+
+
+class _Slab(object):
+    """
+    Compute average I(Q) for a region of interest
+    """
+    def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0,
+                 y_max=0.0, bin_width=0.001):
+        # Minimum Qx value [A-1]
+        self.x_min = x_min
+        # Maximum Qx value [A-1]
+        self.x_max = x_max
+        # Minimum Qy value [A-1]
+        self.y_min = y_min
+        # Maximum Qy value [A-1]
+        self.y_max = y_max
+        # Bin width (step size) [A-1]
+        self.bin_width = bin_width
+        # If True, I(|Q|) will be return, otherwise,
+        # negative q-values are allowed
+        self.fold = False
+
+    def __call__(self, data2D):
+        return NotImplemented
+
+    def _avg(self, data2D, maj):
+        """
+        Compute average I(Q_maj) for a region of interest.
+        The major axis is defined as the axis of Q_maj.
+        The minor axis is the axis that we average over.
+
+        :param data2D: Data2D object
+        :param maj_min: min value on the major axis
+        :return: Data1D object
+        """
+        if len(data2D.detector) > 1:
+            msg = "_Slab._avg: invalid number of "
+            msg += " detectors: %g" % len(data2D.detector)
+            raise RuntimeError, msg
+
+        # Get data
+        data = data2D.data[numpy.isfinite(data2D.data)]
+        err_data = data2D.err_data[numpy.isfinite(data2D.data)]
+        qx_data = data2D.qx_data[numpy.isfinite(data2D.data)]
+        qy_data = data2D.qy_data[numpy.isfinite(data2D.data)]
+
+        # Build array of Q intervals
+        if maj == 'x':
+            if self.fold:
+                x_min = 0
+            else:
+                x_min = self.x_min
+            nbins = int(math.ceil((self.x_max - x_min) / self.bin_width))
+        elif maj == 'y':
+            if self.fold:
+                y_min = 0
+            else:
+                y_min = self.y_min
+            nbins = int(math.ceil((self.y_max - y_min) / self.bin_width))
+        else:
+            raise RuntimeError, "_Slab._avg: unrecognized axis %s" % str(maj)
+
+        x = numpy.zeros(nbins)
+        y = numpy.zeros(nbins)
+        err_y = numpy.zeros(nbins)
+        y_counts = numpy.zeros(nbins)
+
+        # Average pixelsize in q space
+        for npts in range(len(data)):
+            # default frac
+            frac_x = 0
+            frac_y = 0
+            # get ROI
+            if self.x_min <= qx_data[npts] and self.x_max > qx_data[npts]:
+                frac_x = 1
+            if self.y_min <= qy_data[npts] and self.y_max > qy_data[npts]:
+                frac_y = 1
+            frac = frac_x * frac_y
+
+            if frac == 0:
+                continue
+            # binning: find axis of q
+            if maj == 'x':
+                q_value = qx_data[npts]
+                min_value = x_min
+            if maj == 'y':
+                q_value = qy_data[npts]
+                min_value = y_min
+            if self.fold and q_value < 0:
+                q_value = -q_value
+            # bin
+            i_q = int(math.ceil((q_value - min_value) / self.bin_width)) - 1
+
+            # skip outside of max bins
+            if i_q < 0 or i_q >= nbins:
+                continue
+
+            #TODO: find better definition of x[i_q] based on q_data
+            # min_value + (i_q + 1) * self.bin_width / 2.0
+            x[i_q] += frac * q_value
+            y[i_q] += frac * data[npts]
+
+            if err_data is None or err_data[npts] == 0.0:
+                if data[npts] < 0:
+                    data[npts] = -data[npts]
+                err_y[i_q] += frac * frac * data[npts]
+            else:
+                err_y[i_q] += frac * frac * err_data[npts] * err_data[npts]
+            y_counts[i_q] += frac
+
+        # Average the sums
+        for n in range(nbins):
+            err_y[n] = math.sqrt(err_y[n])
+
+        err_y = err_y / y_counts
+        y = y / y_counts
+        x = x / y_counts
+        idx = (numpy.isfinite(y) & numpy.isfinite(x))
+
+        if not idx.any():
+            msg = "Average Error: No points inside ROI to average..."
+            raise ValueError, msg
+        return Data1D(x=x[idx], y=y[idx], dy=err_y[idx])
+
+
+class SlabY(_Slab):
+    """
+    Compute average I(Qy) for a region of interest
+    """
+    def __call__(self, data2D):
+        """
+        Compute average I(Qy) for a region of interest
+
+        :param data2D: Data2D object
+        :return: Data1D object
+        """
+        return self._avg(data2D, 'y')
+
+
+class SlabX(_Slab):
+    """
+    Compute average I(Qx) for a region of interest
+    """
+    def __call__(self, data2D):
+        """
+        Compute average I(Qx) for a region of interest
+        :param data2D: Data2D object
+        :return: Data1D object
+        """
+        return self._avg(data2D, 'x')
+
+
+class Boxsum(object):
+    """
+    Perform the sum of counts in a 2D region of interest.
+    """
+    def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0):
+        # Minimum Qx value [A-1]
+        self.x_min = x_min
+        # Maximum Qx value [A-1]
+        self.x_max = x_max
+        # Minimum Qy value [A-1]
+        self.y_min = y_min
+        # Maximum Qy value [A-1]
+        self.y_max = y_max
+
+    def __call__(self, data2D):
+        """
+        Perform the sum in the region of interest
+
+        :param data2D: Data2D object
+        :return: number of counts, error on number of counts,
+            number of points summed
+        """
+        y, err_y, y_counts = self._sum(data2D)
+
+        # Average the sums
+        counts = 0 if y_counts == 0 else y
+        error = 0 if y_counts == 0 else math.sqrt(err_y)
+
+        # Added y_counts to return, SMK & PDB, 04/03/2013
+        return counts, error, y_counts
+
+    def _sum(self, data2D):
+        """
+        Perform the sum in the region of interest
+
+        :param data2D: Data2D object
+        :return: number of counts,
+            error on number of counts, number of entries summed
+        """
+        if len(data2D.detector) > 1:
+            msg = "Circular averaging: invalid number "
+            msg += "of detectors: %g" % len(data2D.detector)
+            raise RuntimeError, msg
+        # Get data
+        data = data2D.data[numpy.isfinite(data2D.data)]
+        err_data = data2D.err_data[numpy.isfinite(data2D.data)]
+        qx_data = data2D.qx_data[numpy.isfinite(data2D.data)]
+        qy_data = data2D.qy_data[numpy.isfinite(data2D.data)]
+
+        y = 0.0
+        err_y = 0.0
+        y_counts = 0.0
+
+        # Average pixelsize in q space
+        for npts in range(len(data)):
+            # default frac
+            frac_x = 0
+            frac_y = 0
+
+            # get min and max at each points
+            qx = qx_data[npts]
+            qy = qy_data[npts]
+
+            # get the ROI
+            if self.x_min <= qx and self.x_max > qx:
+                frac_x = 1
+            if self.y_min <= qy and self.y_max > qy:
+                frac_y = 1
+            #Find the fraction along each directions
+            frac = frac_x * frac_y
+            if frac == 0:
+                continue
+            y += frac * data[npts]
+            if err_data is None or err_data[npts] == 0.0:
+                if data[npts] < 0:
+                    data[npts] = -data[npts]
+                err_y += frac * frac * data[npts]
+            else:
+                err_y += frac * frac * err_data[npts] * err_data[npts]
+            y_counts += frac
+        return y, err_y, y_counts
+
+
+class Boxavg(Boxsum):
+    """
+    Perform the average of counts in a 2D region of interest.
+    """
+    def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0):
+        super(Boxavg, self).__init__(x_min=x_min, x_max=x_max,
+                                     y_min=y_min, y_max=y_max)
+
+    def __call__(self, data2D):
+        """
+        Perform the sum in the region of interest
+
+        :param data2D: Data2D object
+        :return: average counts, error on average counts
+
+        """
+        y, err_y, y_counts = self._sum(data2D)
+
+        # Average the sums
+        counts = 0 if y_counts == 0 else y / y_counts
+        error = 0 if y_counts == 0 else math.sqrt(err_y) / y_counts
+
+        return counts, error
+
+
 def get_pixel_fraction_square(x, xmin, xmax):
     """
@@ -101,27 +390,260 @@
         return 1.0
 
-def get_intercept(q, q_0, q_1):
-    """
-    Returns the fraction of the side at which the
-    q-value intercept the pixel, None otherwise.
-    The values returned is the fraction ON THE SIDE
-    OF THE LOWEST Q. ::
-
-            A           B
-        +-----------+--------+    <--- pixel size
-        0                    1
-        Q_0 -------- Q ----- Q_1   <--- equivalent Q range
-        if Q_1 > Q_0, A is returned
-        if Q_1 < Q_0, B is returned
-        if Q is outside the range of [Q_0, Q_1], None is returned
-
-    """
-    if q_1 > q_0:
-        if q > q_0 and q <= q_1:
-            return (q - q_0) / (q_1 - q_0)
-    else:
-        if q > q_1 and q <= q_0:
-            return (q - q_1) / (q_0 - q_1)
-    return None
+
+class CircularAverage(object):
+    """
+    Perform circular averaging on 2D data
+
+    The data returned is the distribution of counts
+    as a function of Q
+    """
+    def __init__(self, r_min=0.0, r_max=0.0, bin_width=0.0005):
+        # Minimum radius included in the average [A-1]
+        self.r_min = r_min
+        # Maximum radius included in the average [A-1]
+        self.r_max = r_max
+        # Bin width (step size) [A-1]
+        self.bin_width = bin_width
+
+    def __call__(self, data2D, ismask=False):
+        """
+        Perform circular averaging on the data
+
+        :param data2D: Data2D object
+        :return: Data1D object
+        """
+        # Get data W/ finite values
+        data = data2D.data[numpy.isfinite(data2D.data)]
+        q_data = data2D.q_data[numpy.isfinite(data2D.data)]
+        err_data = data2D.err_data[numpy.isfinite(data2D.data)]
+        mask_data = data2D.mask[numpy.isfinite(data2D.data)]
+
+        dq_data = None
+
+        # Get the dq for resolution averaging
+        if data2D.dqx_data is not None and data2D.dqy_data is not None:
+            # The pinholes and det. pix contribution present
+            # in both direction of the 2D which must be subtracted when
+            # converting to 1D: dq_overlap should calculated ideally at
+            # q = 0. Note This method works on only pinhole geometry.
+            # Extrapolate dqx(r) and dqy(phi) at q = 0, and take an average.
+            z_max = max(data2D.q_data)
+            z_min = min(data2D.q_data)
+            x_max = data2D.dqx_data[data2D.q_data[z_max]]
+            x_min = data2D.dqx_data[data2D.q_data[z_min]]
+            y_max = data2D.dqy_data[data2D.q_data[z_max]]
+            y_min = data2D.dqy_data[data2D.q_data[z_min]]
+            # Find qdx at q = 0
+            dq_overlap_x = (x_min * z_max - x_max * z_min) / (z_max - z_min)
+            # when extrapolation goes wrong
+            if dq_overlap_x > min(data2D.dqx_data):
+                dq_overlap_x = min(data2D.dqx_data)
+            dq_overlap_x *= dq_overlap_x
+            # Find qdx at q = 0
+            dq_overlap_y = (y_min * z_max - y_max * z_min) / (z_max - z_min)
+            # when extrapolation goes wrong
+            if dq_overlap_y > min(data2D.dqy_data):
+                dq_overlap_y = min(data2D.dqy_data)
+            # get dq at q=0.
+            dq_overlap_y *= dq_overlap_y
+
+            dq_overlap = numpy.sqrt((dq_overlap_x + dq_overlap_y) / 2.0)
+            # Final protection of dq
+            if dq_overlap < 0:
+                dq_overlap = y_min
+            dqx_data = data2D.dqx_data[numpy.isfinite(data2D.data)]
+            dqy_data = data2D.dqy_data[numpy.isfinite(data2D.data)] - dq_overlap
+            # def; dqx_data = dq_r dqy_data = dq_phi
+            # Convert dq 2D to 1D here
+            dqx = dqx_data * dqx_data
+            dqy = dqy_data * dqy_data
+            dq_data = numpy.add(dqx, dqy)
+            dq_data = numpy.sqrt(dq_data)
+
+        #q_data_max = numpy.max(q_data)
+        if len(data2D.q_data) is None:
+            msg = "Circular averaging: invalid q_data: %g" % data2D.q_data
+            raise RuntimeError, msg
+
+        # Build array of Q intervals
+        nbins = int(math.ceil((self.r_max - self.r_min) / self.bin_width))
+
+        x = numpy.zeros(nbins)
+        y = numpy.zeros(nbins)
+        err_y = numpy.zeros(nbins)
+        err_x = numpy.zeros(nbins)
+        y_counts = numpy.zeros(nbins)
+
+        for npt in range(len(data)):
+
+            if ismask and not mask_data[npt]:
+                continue
+
+            frac = 0
+
+            # q-value at the pixel (j,i)
+            q_value = q_data[npt]
+            data_n = data[npt]
+
+            ## No need to calculate the frac when all data are within range
+            if self.r_min >= self.r_max:
+                raise ValueError, "Limit Error: min > max"
+
+            if self.r_min <= q_value and q_value <= self.r_max:
+                frac = 1
+            if frac == 0:
+                continue
+            i_q = int(math.floor((q_value - self.r_min) / self.bin_width))
+
+            # Take care of the edge case at phi = 2pi.
+            if i_q == nbins:
+                i_q = nbins - 1
+            y[i_q] += frac * data_n
+            # Take dqs from data to get the q_average
+            x[i_q] += frac * q_value
+            if err_data is None or err_data[npt] == 0.0:
+                if data_n < 0:
+                    data_n = -data_n
+                err_y[i_q] += frac * frac * data_n
+            else:
+                err_y[i_q] += frac * frac * err_data[npt] * err_data[npt]
+            if dq_data is not None:
+                # To be consistent with dq calculation in 1d reduction,
+                # we need just the averages (not quadratures) because
+                # it should not depend on the number of the q points
+                # in the qr bins.
+                err_x[i_q] += frac * dq_data[npt]
+            else:
+                err_x = None
+            y_counts[i_q] += frac
+
+        # Average the sums
+        for n in range(nbins):
+            if err_y[n] < 0:
+                err_y[n] = -err_y[n]
+            err_y[n] = math.sqrt(err_y[n])
+            #if err_x is not None:
+            #    err_x[n] = math.sqrt(err_x[n])
+
+        err_y = err_y / y_counts
+        err_y[err_y == 0] = numpy.average(err_y)
+        y = y / y_counts
+        x = x / y_counts
+        idx = (numpy.isfinite(y)) & (numpy.isfinite(x))
+
+        if err_x is not None:
+            d_x = err_x[idx] / y_counts[idx]
+        else:
+            d_x = None
+
+        if not idx.any():
+            msg = "Average Error: No points inside ROI to average..."
+            raise ValueError, msg
+
+        return Data1D(x=x[idx], y=y[idx], dy=err_y[idx], dx=d_x)
+
+
+class Ring(object):
+    """
+    Defines a ring on a 2D data set.
+    The ring is defined by r_min, r_max, and
+    the position of the center of the ring.
+
+    The data returned is the distribution of counts
+    around the ring as a function of phi.
+
+    Phi_min and phi_max should be defined between 0 and 2*pi
+    in anti-clockwise starting from the x- axis on the left-hand side
+    """
+    #Todo: remove center.
+    def __init__(self, r_min=0, r_max=0, center_x=0, center_y=0, nbins=36):
+        # Minimum radius
+        self.r_min = r_min
+        # Maximum radius
+        self.r_max = r_max
+        # Center of the ring in x
+        self.center_x = center_x
+        # Center of the ring in y
+        self.center_y = center_y
+        # Number of angular bins
+        self.nbins_phi = nbins
+
+
+    def __call__(self, data2D):
+        """
+        Apply the ring to the data set.
+        Returns the angular distribution for a given q range
+
+        :param data2D: Data2D object
+
+        :return: Data1D object
+        """
+        if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]:
+            raise RuntimeError, "Ring averaging only take plottable_2D objects"
+
+        Pi = math.pi
+
+        # Get data
+        data = data2D.data[numpy.isfinite(data2D.data)]
+        q_data = data2D.q_data[numpy.isfinite(data2D.data)]
+        err_data = data2D.err_data[numpy.isfinite(data2D.data)]
+        qx_data = data2D.qx_data[numpy.isfinite(data2D.data)]
+        qy_data = data2D.qy_data[numpy.isfinite(data2D.data)]
+
+        # Set space for 1d outputs
+        phi_bins = numpy.zeros(self.nbins_phi)
+        phi_counts = numpy.zeros(self.nbins_phi)
+        phi_values = numpy.zeros(self.nbins_phi)
+        phi_err = numpy.zeros(self.nbins_phi)
+
+        # Shift to apply to calculated phi values in order
+        # to center first bin at zero
+        phi_shift = Pi / self.nbins_phi
+
+        for npt in range(len(data)):
+            frac = 0
+            # q-value at the point (npt)
+            q_value = q_data[npt]
+            data_n = data[npt]
+
+            # phi-value at the point (npt)
+            phi_value = math.atan2(qy_data[npt], qx_data[npt]) + Pi
+
+            if self.r_min <= q_value and q_value <= self.r_max:
+                frac = 1
+            if frac == 0:
+                continue
+            # binning
+            i_phi = int(math.floor((self.nbins_phi) * \
+                                   (phi_value + phi_shift) / (2 * Pi)))
+
+            # Take care of the edge case at phi = 2pi.
+            if i_phi >= self.nbins_phi:
+                i_phi = 0
+            phi_bins[i_phi] += frac * data[npt]
+
+            if err_data is None or err_data[npt] == 0.0:
+                if data_n < 0:
+                    data_n = -data_n
+                phi_err[i_phi] += frac * frac * math.fabs(data_n)
+            else:
+                phi_err[i_phi] += frac * frac * err_data[npt] * err_data[npt]
+            phi_counts[i_phi] += frac
+
+        for i in range(self.nbins_phi):
+            phi_bins[i] = phi_bins[i] / phi_counts[i]
+            phi_err[i] = math.sqrt(phi_err[i]) / phi_counts[i]
+            phi_values[i] = 2.0 * math.pi / self.nbins_phi * (1.0 * i)
+
+        idx = (numpy.isfinite(phi_bins))
+
+        if not idx.any():
+            msg = "Average Error: No points inside ROI to average..."
+            raise ValueError, msg
+        #elif len(phi_bins[idx])!= self.nbins_phi:
+        #    print "resulted",self.nbins_phi- len(phi_bins[idx])
+        #,"empty bin(s) due to tight binning..."
+        return Data1D(x=phi_values[idx], y=phi_bins[idx], dy=phi_err[idx])
+
 
 def get_pixel_fraction(qmax, q_00, q_01, q_10, q_11):
@@ -188,604 +710,29 @@
     return frac_max
 
-def get_dq_data(data2D):
-    '''
-    Get the dq for resolution averaging
-    The pinholes and det. pix contribution present
-    in both direction of the 2D which must be subtracted when
-    converting to 1D: dq_overlap should calculated ideally at
-    q = 0. Note This method works on only pinhole geometry.
-    Extrapolate dqx(r) and dqy(phi) at q = 0, and take an average.
-    '''
-    z_max = max(data2D.q_data)
-    z_min = min(data2D.q_data)
-    x_max = data2D.dqx_data[data2D.q_data[z_max]]
-    x_min = data2D.dqx_data[data2D.q_data[z_min]]
-    y_max = data2D.dqy_data[data2D.q_data[z_max]]
-    y_min = data2D.dqy_data[data2D.q_data[z_min]]
-    # Find qdx at q = 0
-    dq_overlap_x = (x_min * z_max - x_max * z_min) / (z_max - z_min)
-    # when extrapolation goes wrong
-    if dq_overlap_x > min(data2D.dqx_data):
-        dq_overlap_x = min(data2D.dqx_data)
-    dq_overlap_x *= dq_overlap_x
-    # Find qdx at q = 0
-    dq_overlap_y = (y_min * z_max - y_max * z_min) / (z_max - z_min)
-    # when extrapolation goes wrong
-    if dq_overlap_y > min(data2D.dqy_data):
-        dq_overlap_y = min(data2D.dqy_data)
-    # get dq at q=0.
-    dq_overlap_y *= dq_overlap_y
-
-    dq_overlap = np.sqrt((dq_overlap_x + dq_overlap_y) / 2.0)
-    # Final protection of dq
-    if dq_overlap < 0:
-        dq_overlap = y_min
-    dqx_data = data2D.dqx_data[np.isfinite(data2D.data)]
-    dqy_data = data2D.dqy_data[np.isfinite(
-        data2D.data)] - dq_overlap
-    # def; dqx_data = dq_r dqy_data = dq_phi
-    # Convert dq 2D to 1D here
-    dq_data = np.sqrt(dqx_data**2 + dqx_data**2)
-    return dq_data
-
-################################################################################
-
-def reader2D_converter(data2d=None):
-    """
-    convert old 2d format opened by IhorReader or danse_reader
-    to new Data2D format
-    This is mainly used by the Readers
-
-    :param data2d: 2d array of Data2D object
-    :return: 1d arrays of Data2D object
-
-    """
-    if data2d.data is None or data2d.x_bins is None or data2d.y_bins is None:
-        raise ValueError("Can't convert this data: data=None...")
-    new_x = np.tile(data2d.x_bins, (len(data2d.y_bins), 1))
-    new_y = np.tile(data2d.y_bins, (len(data2d.x_bins), 1))
-    new_y = new_y.swapaxes(0, 1)
-
-    new_data = data2d.data.flatten()
-    qx_data = new_x.flatten()
-    qy_data = new_y.flatten()
-    q_data = np.sqrt(qx_data * qx_data + qy_data * qy_data)
-    if data2d.err_data is None or np.any(data2d.err_data <= 0):
-        new_err_data = np.sqrt(np.abs(new_data))
+
+def get_intercept(q, q_0, q_1):
+    """
+    Returns the fraction of the side at which the
+    q-value intercept the pixel, None otherwise.
+    The values returned is the fraction ON THE SIDE
+    OF THE LOWEST Q. ::
+
+            A           B
+        +-----------+--------+    <--- pixel size
+        0                    1
+        Q_0 -------- Q ----- Q_1   <--- equivalent Q range
+        if Q_1 > Q_0, A is returned
+        if Q_1 < Q_0, B is returned
+        if Q is outside the range of [Q_0, Q_1], None is returned
+
+    """
+    if q_1 > q_0:
+        if q > q_0 and q <= q_1:
+            return (q - q_0) / (q_1 - q_0)
     else:
-        new_err_data = data2d.err_data.flatten()
-    mask = np.ones(len(new_data), dtype=bool)
-
-    # TODO: make sense of the following two lines...
-    #from sas.sascalc.dataloader.data_info import Data2D
-    #output = Data2D()
-    output = data2d
-    output.data = new_data
-    output.err_data = new_err_data
-    output.qx_data = qx_data
-    output.qy_data = qy_data
-    output.q_data = q_data
-    output.mask = mask
-
-    return output
-
-################################################################################
-
-class Binning(object):
-    '''
-    This class just creates a binning object
-    either linear or log
-    '''
-
-    def __init__(self, min_value, max_value, n_bins, base=None):
-        '''
-        if base is None: Linear binning
-        '''
-        self.min = min_value if min_value > 0 else 0.0001
-        self.max = max_value
-        self.n_bins = n_bins
-        self.base = base
-
-    def get_bin_index(self, value):
-        '''
-        The general formula logarithm binning is:
-        bin = floor(N * (log(x) - log(min)) / (log(max) - log(min)))
-        '''
-        if self.base:
-            temp_x = self.n_bins * (math.log(value, self.base) - math.log(self.min, self.base))
-            temp_y = math.log(self.max, self.base) - math.log(self.min, self.base)
-        else:
-            temp_x = self.n_bins * (value - self.min)
-            temp_y = self.max - self.min
-        # Bin index calulation
-        return int(math.floor(temp_x / temp_y))
-
-
-################################################################################
-
-class _Slab(object):
-    """
-    Compute average I(Q) for a region of interest
-    """
-
-    def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0,
-                 y_max=0.0, bin_width=0.001):
-        # Minimum Qx value [A-1]
-        self.x_min = x_min
-        # Maximum Qx value [A-1]
-        self.x_max = x_max
-        # Minimum Qy value [A-1]
-        self.y_min = y_min
-        # Maximum Qy value [A-1]
-        self.y_max = y_max
-        # Bin width (step size) [A-1]
-        self.bin_width = bin_width
-        # If True, I(|Q|) will be return, otherwise,
-        # negative q-values are allowed
-        self.fold = False
-
-    def __call__(self, data2D):
-        return NotImplemented
-
-    def _avg(self, data2D, maj):
-        """
-        Compute average I(Q_maj) for a region of interest.
-        The major axis is defined as the axis of Q_maj.
-        The minor axis is the axis that we average over.
-
-        :param data2D: Data2D object
-        :param maj_min: min value on the major axis
-        :return: Data1D object
-        """
-        if len(data2D.detector) > 1:
-            msg = "_Slab._avg: invalid number of "
-            msg += " detectors: %g" % len(data2D.detector)
-            raise RuntimeError(msg)
-
-        # Get data
-        data = data2D.data[np.isfinite(data2D.data)]
-        err_data = data2D.err_data[np.isfinite(data2D.data)]
-        qx_data = data2D.qx_data[np.isfinite(data2D.data)]
-        qy_data = data2D.qy_data[np.isfinite(data2D.data)]
-
-        # Build array of Q intervals
-        if maj == 'x':
-            if self.fold:
-                x_min = 0
-            else:
-                x_min = self.x_min
-            nbins = int(math.ceil((self.x_max - x_min) / self.bin_width))
-        elif maj == 'y':
-            if self.fold:
-                y_min = 0
-            else:
-                y_min = self.y_min
-            nbins = int(math.ceil((self.y_max - y_min) / self.bin_width))
-        else:
-            raise RuntimeError("_Slab._avg: unrecognized axis %s" % str(maj))
-
-        x = np.zeros(nbins)
-        y = np.zeros(nbins)
-        err_y = np.zeros(nbins)
-        y_counts = np.zeros(nbins)
-
-        # Average pixelsize in q space
-        for npts in range(len(data)):
-            # default frac
-            frac_x = 0
-            frac_y = 0
-            # get ROI
-            if self.x_min <= qx_data[npts] and self.x_max > qx_data[npts]:
-                frac_x = 1
-            if self.y_min <= qy_data[npts] and self.y_max > qy_data[npts]:
-                frac_y = 1
-            frac = frac_x * frac_y
-
-            if frac == 0:
-                continue
-            # binning: find axis of q
-            if maj == 'x':
-                q_value = qx_data[npts]
-                min_value = x_min
-            if maj == 'y':
-                q_value = qy_data[npts]
-                min_value = y_min
-            if self.fold and q_value < 0:
-                q_value = -q_value
-            # bin
-            i_q = int(math.ceil((q_value - min_value) / self.bin_width)) - 1
-
-            # skip outside of max bins
-            if i_q < 0 or i_q >= nbins:
-                continue
-
-            # TODO: find better definition of x[i_q] based on q_data
-            # min_value + (i_q + 1) * self.bin_width / 2.0
-            x[i_q] += frac * q_value
-            y[i_q] += frac * data[npts]
-
-            if err_data is None or err_data[npts] == 0.0:
-                if data[npts] < 0:
-                    data[npts] = -data[npts]
-                err_y[i_q] += frac * frac * data[npts]
-            else:
-                err_y[i_q] += frac * frac * err_data[npts] * err_data[npts]
-            y_counts[i_q] += frac
-
-        # Average the sums
-        for n in range(nbins):
-            err_y[n] = math.sqrt(err_y[n])
-
-        err_y = err_y / y_counts
-        y = y / y_counts
-        x = x / y_counts
-        idx = (np.isfinite(y) & np.isfinite(x))
-
-        if not idx.any():
-            msg = "Average Error: No points inside ROI to average..."
-            raise ValueError(msg)
-        return Data1D(x=x[idx], y=y[idx], dy=err_y[idx])
-
-
-class SlabY(_Slab):
-    """
-    Compute average I(Qy) for a region of interest
-    """
-
-    def __call__(self, data2D):
-        """
-        Compute average I(Qy) for a region of interest
-
-        :param data2D: Data2D object
-        :return: Data1D object
-        """
-        return self._avg(data2D, 'y')
-
-
-class SlabX(_Slab):
-    """
-    Compute average I(Qx) for a region of interest
-    """
-
-    def __call__(self, data2D):
-        """
-        Compute average I(Qx) for a region of interest
-        :param data2D: Data2D object
-        :return: Data1D object
-        """
-        return self._avg(data2D, 'x')
-
-################################################################################
-
-class Boxsum(object):
-    """
-    Perform the sum of counts in a 2D region of interest.
-    """
-
-    def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0):
-        # Minimum Qx value [A-1]
-        self.x_min = x_min
-        # Maximum Qx value [A-1]
-        self.x_max = x_max
-        # Minimum Qy value [A-1]
-        self.y_min = y_min
-        # Maximum Qy value [A-1]
-        self.y_max = y_max
-
-    def __call__(self, data2D):
-        """
-        Perform the sum in the region of interest
-
-        :param data2D: Data2D object
-        :return: number of counts, error on number of counts,
-            number of points summed
-        """
-        y, err_y, y_counts = self._sum(data2D)
-
-        # Average the sums
-        counts = 0 if y_counts == 0 else y
-        error = 0 if y_counts == 0 else math.sqrt(err_y)
-
-        # Added y_counts to return, SMK & PDB, 04/03/2013
-        return counts, error, y_counts
-
-    def _sum(self, data2D):
-        """
-        Perform the sum in the region of interest
-
-        :param data2D: Data2D object
-        :return: number of counts,
-            error on number of counts, number of entries summed
-        """
-        if len(data2D.detector) > 1:
-            msg = "Circular averaging: invalid number "
-            msg += "of detectors: %g" % len(data2D.detector)
-            raise RuntimeError(msg)
-        # Get data
-        data = data2D.data[np.isfinite(data2D.data)]
-        err_data = data2D.err_data[np.isfinite(data2D.data)]
-        qx_data = data2D.qx_data[np.isfinite(data2D.data)]
-        qy_data = data2D.qy_data[np.isfinite(data2D.data)]
-
-        y = 0.0
-        err_y = 0.0
-        y_counts = 0.0
-
-        # Average pixelsize in q space
-        for npts in range(len(data)):
-            # default frac
-            frac_x = 0
-            frac_y = 0
-
-            # get min and max at each points
-            qx = qx_data[npts]
-            qy = qy_data[npts]
-
-            # get the ROI
-            if self.x_min <= qx and self.x_max > qx:
-                frac_x = 1
-            if self.y_min <= qy and self.y_max > qy:
-                frac_y = 1
-            # Find the fraction along each directions
-            frac = frac_x * frac_y
-            if frac == 0:
-                continue
-            y += frac * data[npts]
-            if err_data is None or err_data[npts] == 0.0:
-                if data[npts] < 0:
-                    data[npts] = -data[npts]
-                err_y += frac * frac * data[npts]
-            else:
-                err_y += frac * frac * err_data[npts] * err_data[npts]
-            y_counts += frac
-        return y, err_y, y_counts
-
-
-class Boxavg(Boxsum):
-    """
-    Perform the average of counts in a 2D region of interest.
-    """
-
-    def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0):
-        super(Boxavg, self).__init__(x_min=x_min, x_max=x_max,
-                                     y_min=y_min, y_max=y_max)
-
-    def __call__(self, data2D):
-        """
-        Perform the sum in the region of interest
-
-        :param data2D: Data2D object
-        :return: average counts, error on average counts
-
-        """
-        y, err_y, y_counts = self._sum(data2D)
-
-        # Average the sums
-        counts = 0 if y_counts == 0 else y / y_counts
-        error = 0 if y_counts == 0 else math.sqrt(err_y) / y_counts
-
-        return counts, error
-
-################################################################################
-
-class CircularAverage(object):
-    """
-    Perform circular averaging on 2D data
-
-    The data returned is the distribution of counts
-    as a function of Q
-    """
-
-    def __init__(self, r_min=0.0, r_max=0.0, bin_width=0.0005):
-        # Minimum radius included in the average [A-1]
-        self.r_min = r_min
-        # Maximum radius included in the average [A-1]
-        self.r_max = r_max
-        # Bin width (step size) [A-1]
-        self.bin_width = bin_width
-
-    def __call__(self, data2D, ismask=False):
-        """
-        Perform circular averaging on the data
-
-        :param data2D: Data2D object
-        :return: Data1D object
-        """
-        # Get data W/ finite values
-        data = data2D.data[np.isfinite(data2D.data)]
-        q_data = data2D.q_data[np.isfinite(data2D.data)]
-        err_data = data2D.err_data[np.isfinite(data2D.data)]
-        mask_data = data2D.mask[np.isfinite(data2D.data)]
-
-        dq_data = None
-        if data2D.dqx_data is not None and data2D.dqy_data is not None:
-            dq_data = get_dq_data(data2D)
-
-        if len(q_data) == 0:
-            msg = "Circular averaging: invalid q_data: %g" % data2D.q_data
-            raise RuntimeError(msg)
-
-        # Build array of Q intervals
-        nbins = int(math.ceil((self.r_max - self.r_min) / self.bin_width))
-
-        x = np.zeros(nbins)
-        y = np.zeros(nbins)
-        err_y = np.zeros(nbins)
-        err_x = np.zeros(nbins)
-        y_counts = np.zeros(nbins)
-
-        for npt in range(len(data)):
-
-            if ismask and not mask_data[npt]:
-                continue
-
-            frac = 0
-
-            # q-value at the pixel (j,i)
-            q_value = q_data[npt]
-            data_n = data[npt]
-
-            # No need to calculate the frac when all data are within range
-            if self.r_min >= self.r_max:
-                raise ValueError("Limit Error: min > max")
-
-            if self.r_min <= q_value and q_value <= self.r_max:
-                frac = 1
-            if frac == 0:
-                continue
-            i_q = int(math.floor((q_value - self.r_min) / self.bin_width))
-
-            # Take care of the edge case at phi = 2pi.
-            if i_q == nbins:
-                i_q = nbins - 1
-            y[i_q] += frac * data_n
-            # Take dqs from data to get the q_average
-            x[i_q] += frac * q_value
-            if err_data is None or err_data[npt] == 0.0:
-                if data_n < 0:
-                    data_n = -data_n
-                err_y[i_q] += frac * frac * data_n
-            else:
-                err_y[i_q] += frac * frac * err_data[npt] * err_data[npt]
-            if dq_data is not None:
-                # To be consistent with dq calculation in 1d reduction,
-                # we need just the averages (not quadratures) because
-                # it should not depend on the number of the q points
-                # in the qr bins.
-                err_x[i_q] += frac * dq_data[npt]
-            else:
-                err_x = None
-            y_counts[i_q] += frac
-
-        # Average the sums
-        for n in range(nbins):
-            if err_y[n] < 0:
-                err_y[n] = -err_y[n]
-            err_y[n] = math.sqrt(err_y[n])
-            # if err_x is not None:
-            #    err_x[n] = math.sqrt(err_x[n])
-
-        err_y = err_y / y_counts
-        err_y[err_y == 0] = np.average(err_y)
-        y = y / y_counts
-        x = x / y_counts
-        idx = (np.isfinite(y)) & (np.isfinite(x))
-
-        if err_x is not None:
-            d_x = err_x[idx] / y_counts[idx]
-        else:
-            d_x = None
-
-        if not idx.any():
-            msg = "Average Error: No points inside ROI to average..."
-            raise ValueError(msg)
-
-        return Data1D(x=x[idx], y=y[idx], dy=err_y[idx], dx=d_x)
-
-################################################################################
-
-class Ring(object):
-    """
-    Defines a ring on a 2D data set.
-    The ring is defined by r_min, r_max, and
-    the position of the center of the ring.
-
-    The data returned is the distribution of counts
-    around the ring as a function of phi.
-
-    Phi_min and phi_max should be defined between 0 and 2*pi
-    in anti-clockwise starting from the x- axis on the left-hand side
-    """
-    # Todo: remove center.
-
-    def __init__(self, r_min=0, r_max=0, center_x=0, center_y=0, nbins=36):
-        # Minimum radius
-        self.r_min = r_min
-        # Maximum radius
-        self.r_max = r_max
-        # Center of the ring in x
-        self.center_x = center_x
-        # Center of the ring in y
-        self.center_y = center_y
-        # Number of angular bins
-        self.nbins_phi = nbins
-
-    def __call__(self, data2D):
-        """
-        Apply the ring to the data set.
-        Returns the angular distribution for a given q range
-
-        :param data2D: Data2D object
-
-        :return: Data1D object
-        """
-        if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]:
-            raise RuntimeError("Ring averaging only take plottable_2D objects")
-
-        Pi = math.pi
-
-        # Get data
-        data = data2D.data[np.isfinite(data2D.data)]
-        q_data = data2D.q_data[np.isfinite(data2D.data)]
-        err_data = data2D.err_data[np.isfinite(data2D.data)]
-        qx_data = data2D.qx_data[np.isfinite(data2D.data)]
-        qy_data = data2D.qy_data[np.isfinite(data2D.data)]
-
-        # Set space for 1d outputs
-        phi_bins = np.zeros(self.nbins_phi)
-        phi_counts = np.zeros(self.nbins_phi)
-        phi_values = np.zeros(self.nbins_phi)
-        phi_err = np.zeros(self.nbins_phi)
-
-        # Shift to apply to calculated phi values in order
-        # to center first bin at zero
-        phi_shift = Pi / self.nbins_phi
-
-        for npt in range(len(data)):
-            frac = 0
-            # q-value at the point (npt)
-            q_value = q_data[npt]
-            data_n = data[npt]
-
-            # phi-value at the point (npt)
-            phi_value = math.atan2(qy_data[npt], qx_data[npt]) + Pi
-
-            if self.r_min <= q_value and q_value <= self.r_max:
-                frac = 1
-            if frac == 0:
-                continue
-            # binning
-            i_phi = int(math.floor((self.nbins_phi) *
-                                   (phi_value + phi_shift) / (2 * Pi)))
-
-            # Take care of the edge case at phi = 2pi.
-            if i_phi >= self.nbins_phi:
-                i_phi = 0
-            phi_bins[i_phi] += frac * data[npt]
-
-            if err_data is None or err_data[npt] == 0.0:
-                if data_n < 0:
-                    data_n = -data_n
-                phi_err[i_phi] += frac * frac * math.fabs(data_n)
-            else:
-                phi_err[i_phi] += frac * frac * err_data[npt] * err_data[npt]
-            phi_counts[i_phi] += frac
-
-        for i in range(self.nbins_phi):
-            phi_bins[i] = phi_bins[i] / phi_counts[i]
-            phi_err[i] = math.sqrt(phi_err[i]) / phi_counts[i]
-            phi_values[i] = 2.0 * math.pi / self.nbins_phi * (1.0 * i)
-
-        idx = (np.isfinite(phi_bins))
-
-        if not idx.any():
-            msg = "Average Error: No points inside ROI to average..."
-            raise ValueError(msg)
-        # elif len(phi_bins[idx])!= self.nbins_phi:
-        #    print "resulted",self.nbins_phi- len(phi_bins[idx])
-        #,"empty bin(s) due to tight binning..."
-        return Data1D(x=phi_values[idx], y=phi_bins[idx], dy=phi_err[idx])
-
-################################################################################
+        if q > q_1 and q <= q_0:
+            return (q - q_1) / (q_0 - q_1)
+    return None
+
 
 class _Sector(object):
@@ -801,6 +748,5 @@
     starting from the x- axis on the left-hand side
     """
-
-    def __init__(self, r_min, r_max, phi_min=0, phi_max=2 * math.pi, nbins=20, base = None):
+    def __init__(self, r_min, r_max, phi_min=0, phi_max=2 * math.pi, nbins=20):
         self.r_min = r_min
         self.r_max = r_max
@@ -808,5 +754,4 @@
         self.phi_max = phi_max
         self.nbins = nbins
-        self.base = base
 
     def _agv(self, data2D, run='phi'):
@@ -820,23 +765,60 @@
         """
         if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]:
-            raise RuntimeError("Ring averaging only take plottable_2D objects")
+            raise RuntimeError, "Ring averaging only take plottable_2D objects"
+        Pi = math.pi
 
         # Get the all data & info
-        data = data2D.data[np.isfinite(data2D.data)]
-        q_data = data2D.q_data[np.isfinite(data2D.data)]
-        err_data = data2D.err_data[np.isfinite(data2D.data)]
-        qx_data = data2D.qx_data[np.isfinite(data2D.data)]
-        qy_data = data2D.qy_data[np.isfinite(data2D.data)]
-
+        data = data2D.data[numpy.isfinite(data2D.data)]
+        q_data = data2D.q_data[numpy.isfinite(data2D.data)]
+        err_data = data2D.err_data[numpy.isfinite(data2D.data)]
+        qx_data = data2D.qx_data[numpy.isfinite(data2D.data)]
+        qy_data = data2D.qy_data[numpy.isfinite(data2D.data)]
         dq_data = None
+
+        # Get the dq for resolution averaging
         if data2D.dqx_data is not None and data2D.dqy_data is not None:
-            dq_data = get_dq_data(data2D)
-
-        # set space for 1d outputs
-        x = np.zeros(self.nbins)
-        y = np.zeros(self.nbins)
-        y_err = np.zeros(self.nbins)
-        x_err = np.zeros(self.nbins)
-        y_counts = np.zeros(self.nbins) # Cycle counts (for the mean)
+            # The pinholes and det. pix contribution present
+            # in both direction of the 2D which must be subtracted when
+            # converting to 1D: dq_overlap should calculated ideally at
+            # q = 0.
+            # Extrapolate dqy(perp) at q = 0
+            z_max = max(data2D.q_data)
+            z_min = min(data2D.q_data)
+            x_max = data2D.dqx_data[data2D.q_data[z_max]]
+            x_min = data2D.dqx_data[data2D.q_data[z_min]]
+            y_max = data2D.dqy_data[data2D.q_data[z_max]]
+            y_min = data2D.dqy_data[data2D.q_data[z_min]]
+            # Find qdx at q = 0
+            dq_overlap_x = (x_min * z_max - x_max * z_min) / (z_max - z_min)
+            # when extrapolation goes wrong
+            if dq_overlap_x > min(data2D.dqx_data):
+                dq_overlap_x = min(data2D.dqx_data)
+            dq_overlap_x *= dq_overlap_x
+            # Find qdx at q = 0
+            dq_overlap_y = (y_min * z_max - y_max * z_min) / (z_max - z_min)
+            # when extrapolation goes wrong
+            if dq_overlap_y > min(data2D.dqy_data):
+                dq_overlap_y = min(data2D.dqy_data)
+            # get dq at q=0.
+            dq_overlap_y *= dq_overlap_y
+
+            dq_overlap = numpy.sqrt((dq_overlap_x + dq_overlap_y) / 2.0)
+            if dq_overlap < 0:
+                dq_overlap = y_min
+            dqx_data = data2D.dqx_data[numpy.isfinite(data2D.data)]
+            dqy_data = data2D.dqy_data[numpy.isfinite(data2D.data)] - dq_overlap
+            # def; dqx_data = dq_r dqy_data = dq_phi
+            # Convert dq 2D to 1D here
+            dqx = dqx_data * dqx_data
+            dqy = dqy_data * dqy_data
+            dq_data = numpy.add(dqx, dqy)
+            dq_data = numpy.sqrt(dq_data)
+
+        #set space for 1d outputs
+        x = numpy.zeros(self.nbins)
+        y = numpy.zeros(self.nbins)
+        y_err = numpy.zeros(self.nbins)
+        x_err = numpy.zeros(self.nbins)
+        y_counts = numpy.zeros(self.nbins)
 
         # Get the min and max into the region: 0 <= phi < 2Pi
@@ -844,11 +826,6 @@
         phi_max = flip_phi(self.phi_max)
 
-        #  binning object
-        if run.lower() == 'phi':
-            binning = Binning(self.phi_min, self.phi_max, self.nbins, self.base)
-        else:
-            binning = Binning(self.r_min, self.r_max, self.nbins, self.base)
-
         for n in range(len(data)):
+            frac = 0
 
             # q-value at the pixel (j,i)
@@ -860,42 +837,47 @@
 
             # phi-value of the pixel (j,i)
-            phi_value = math.atan2(qy_data[n], qx_data[n]) + math.pi
-
-            # No need to calculate: data outside of the radius
-            if self.r_min > q_value or q_value > self.r_max:
+            phi_value = math.atan2(qy_data[n], qx_data[n]) + Pi
+
+            ## No need to calculate the frac when all data are within range
+            if self.r_min <= q_value and q_value <= self.r_max:
+                frac = 1
+            if frac == 0:
                 continue
-
-            # In case of two ROIs (symmetric major and minor regions)(for 'q2')
+            #In case of two ROIs (symmetric major and minor regions)(for 'q2')
             if run.lower() == 'q2':
-                # For minor sector wing
+                ## For minor sector wing
                 # Calculate the minor wing phis
-                phi_min_minor = flip_phi(phi_min - math.pi)
-                phi_max_minor = flip_phi(phi_max - math.pi)
+                phi_min_minor = flip_phi(phi_min - Pi)
+                phi_max_minor = flip_phi(phi_max - Pi)
                 # Check if phis of the minor ring is within 0 to 2pi
                 if phi_min_minor > phi_max_minor:
-                    is_in = (phi_value > phi_min_minor or
-                             phi_value < phi_max_minor)
+                    is_in = (phi_value > phi_min_minor or \
+                              phi_value < phi_max_minor)
                 else:
-                    is_in = (phi_value > phi_min_minor and
-                             phi_value < phi_max_minor)
-
-            # For all cases(i.e.,for 'q', 'q2', and 'phi')
-            # Find pixels within ROI
+                    is_in = (phi_value > phi_min_minor and \
+                              phi_value < phi_max_minor)
+
+            #For all cases(i.e.,for 'q', 'q2', and 'phi')
+            #Find pixels within ROI
             if phi_min > phi_max:
-                is_in = is_in or (phi_value > phi_min or
-                                  phi_value < phi_max)
+                is_in = is_in or (phi_value > phi_min or \
+                                   phi_value < phi_max)
             else:
-                is_in = is_in or (phi_value >= phi_min and
-                                  phi_value < phi_max)
-
-            # data oustide of the phi range
+                is_in = is_in or (phi_value >= phi_min  and \
+                                    phi_value < phi_max)
+
             if not is_in:
+                frac = 0
+            if frac == 0:
                 continue
-
-            # Get the binning index
+            # Check which type of averaging we need
             if run.lower() == 'phi':
-                i_bin = binning.get_bin_index(phi_value)
+                temp_x = (self.nbins) * (phi_value - self.phi_min)
+                temp_y = (self.phi_max - self.phi_min)
+                i_bin = int(math.floor(temp_x / temp_y))
             else:
-                i_bin = binning.get_bin_index(q_value)
+                temp_x = (self.nbins) * (q_value - self.r_min)
+                temp_y = (self.r_max - self.r_min)
+                i_bin = int(math.floor(temp_x / temp_y))
 
             # Take care of the edge case at phi = 2pi.
@@ -903,13 +885,13 @@
                 i_bin = self.nbins - 1
 
-            # Get the total y
-            y[i_bin] += data_n
-            x[i_bin] += q_value
+            ## Get the total y
+            y[i_bin] += frac * data_n
+            x[i_bin] += frac * q_value
             if err_data[n] is None or err_data[n] == 0.0:
                 if data_n < 0:
                     data_n = -data_n
-                y_err[i_bin] += data_n
+                y_err[i_bin] += frac * frac * data_n
             else:
-                y_err[i_bin] += err_data[n]**2
+                y_err[i_bin] += frac * frac * err_data[n] * err_data[n]
 
             if dq_data is not None:
@@ -918,8 +900,8 @@
                 # it should not depend on the number of the q points
                 # in the qr bins.
-                x_err[i_bin] += dq_data[n]
+                x_err[i_bin] += frac * dq_data[n]
             else:
                 x_err = None
-            y_counts[i_bin] += 1
+            y_counts[i_bin] += frac
 
         # Organize the results
@@ -941,6 +923,6 @@
                 #x[i] = math.sqrt((r_inner * r_inner + r_outer * r_outer) / 2)
                 x[i] = x[i] / y_counts[i]
-        y_err[y_err == 0] = np.average(y_err)
-        idx = (np.isfinite(y) & np.isfinite(y_err))
+        y_err[y_err == 0] = numpy.average(y_err)
+        idx = (numpy.isfinite(y) & numpy.isfinite(y_err))
         if x_err is not None:
             d_x = x_err[idx] / y_counts[idx]
@@ -949,6 +931,6 @@
         if not idx.any():
             msg = "Average Error: No points inside sector of ROI to average..."
-            raise ValueError(msg)
-        # elif len(y[idx])!= self.nbins:
+            raise ValueError, msg
+        #elif len(y[idx])!= self.nbins:
         #    print "resulted",self.nbins- len(y[idx]),
         #"empty bin(s) due to tight binning..."
@@ -964,5 +946,4 @@
     The number of bin in phi also has to be defined.
     """
-
     def __call__(self, data2D):
         """
@@ -984,5 +965,4 @@
     The number of bin in Q also has to be defined.
     """
-
     def __call__(self, data2D):
         """
@@ -995,5 +975,4 @@
         return self._agv(data2D, 'q2')
 
-################################################################################
 
 class Ringcut(object):
@@ -1008,5 +987,4 @@
     in anti-clockwise starting from the x- axis on the left-hand side
     """
-
     def __init__(self, r_min=0, r_max=0, center_x=0, center_y=0):
         # Minimum radius
@@ -1029,10 +1007,10 @@
         """
         if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]:
-            raise RuntimeError("Ring cut only take plottable_2D objects")
+            raise RuntimeError, "Ring cut only take plottable_2D objects"
 
         # Get data
         qx_data = data2D.qx_data
         qy_data = data2D.qy_data
-        q_data = np.sqrt(qx_data * qx_data + qy_data * qy_data)
+        q_data = numpy.sqrt(qx_data * qx_data + qy_data * qy_data)
 
         # check whether or not the data point is inside ROI
@@ -1040,5 +1018,4 @@
         return out
 
-################################################################################
 
 class Boxcut(object):
@@ -1046,5 +1023,4 @@
     Find a rectangular 2D region of interest.
     """
-
     def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0):
         # Minimum Qx value [A-1]
@@ -1079,5 +1055,5 @@
         """
         if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]:
-            raise RuntimeError("Boxcut take only plottable_2D objects")
+            raise RuntimeError, "Boxcut take only plottable_2D objects"
         # Get qx_ and qy_data
         qx_data = data2D.qx_data
@@ -1090,5 +1066,4 @@
         return outx & outy
 
-################################################################################
 
 class Sectorcut(object):
@@ -1102,5 +1077,4 @@
     and (phi_max-phi_min) should not be larger than pi
     """
-
     def __init__(self, phi_min=0, phi_max=math.pi):
         self.phi_min = phi_min
@@ -1132,5 +1106,5 @@
         """
         if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]:
-            raise RuntimeError("Sectorcut take only plottable_2D objects")
+            raise RuntimeError, "Sectorcut take only plottable_2D objects"
         Pi = math.pi
         # Get data
@@ -1139,5 +1113,5 @@
 
         # get phi from data
-        phi_data = np.arctan2(qy_data, qx_data)
+        phi_data = numpy.arctan2(qy_data, qx_data)
 
         # Get the min and max into the region: -pi <= phi < Pi
@@ -1146,9 +1120,7 @@
         # check for major sector
         if phi_min_major > phi_max_major:
-            out_major = (phi_min_major <= phi_data) + \
-                (phi_max_major > phi_data)
+            out_major = (phi_min_major <= phi_data) + (phi_max_major > phi_data)
         else:
-            out_major = (phi_min_major <= phi_data) & (
-                phi_max_major > phi_data)
+            out_major = (phi_min_major <= phi_data) & (phi_max_major > phi_data)
 
         # minor sector
@@ -1160,8 +1132,8 @@
         if phi_min_minor > phi_max_minor:
             out_minor = (phi_min_minor <= phi_data) + \
-                (phi_max_minor >= phi_data)
+                            (phi_max_minor >= phi_data)
         else:
             out_minor = (phi_min_minor <= phi_data) & \
-                (phi_max_minor >= phi_data)
+                            (phi_max_minor >= phi_data)
         out = out_major + out_minor
 
Index: test/sasdataloader/test/utest_averaging.py
===================================================================
--- test/sasdataloader/test/utest_averaging.py	(revision fa4af7651800e56c3e125ac82e9b2bd0a75ca5ba)
+++ test/sasdataloader/test/utest_averaging.py	(revision 9a5097cd1c76689d1f997b85ba43d12a95d8f243)
@@ -1,17 +1,11 @@
 
+import unittest
 import math
-import os
-import unittest
+
+from sas.sascalc.dataloader.loader import  Loader
+from sas.sascalc.dataloader.manipulations import Ring, CircularAverage, SectorPhi, get_q,reader2D_converter
 
 import numpy as np
-
 import sas.sascalc.dataloader.data_info as data_info
-from sas.sascalc.dataloader.loader import Loader
-from sas.sascalc.dataloader.manipulations import (Boxavg, Boxsum,
-                                                  CircularAverage, Ring,
-                                                  SectorPhi, SectorQ, SlabX,
-                                                  SlabY, get_q,
-                                                  reader2D_converter)
-
 
 class Averaging(unittest.TestCase):
@@ -19,5 +13,4 @@
         Test averaging manipulations on a flat distribution
     """
-
     def setUp(self):
         """
@@ -25,70 +18,70 @@
             should return the predefined height of the distribution (1.0).
         """
-        x_0 = np.ones([100, 100])
-        dx_0 = np.ones([100, 100])
-
+        x_0  = np.ones([100,100])
+        dx_0 = np.ones([100,100])
+        
         self.data = data_info.Data2D(data=x_0, err_data=dx_0)
         detector = data_info.Detector()
-        detector.distance = 1000.0  # mm
-        detector.pixel_size.x = 1.0  # mm
-        detector.pixel_size.y = 1.0  # mm
-
+        detector.distance = 1000.0  #mm
+        detector.pixel_size.x = 1.0 #mm
+        detector.pixel_size.y = 1.0 #mm
+        
         # center in pixel position = (len(x_0)-1)/2
-        detector.beam_center.x = (len(x_0) - 1) / 2  # pixel number
-        detector.beam_center.y = (len(x_0) - 1) / 2  # pixel number
+        detector.beam_center.x = (len(x_0)-1)/2 #pixel number
+        detector.beam_center.y = (len(x_0)-1)/2 #pixel number
         self.data.detector.append(detector)
-
+        
         source = data_info.Source()
-        source.wavelength = 10.0  # A
+        source.wavelength = 10.0 #A
         self.data.source = source
-
-        # get_q(dx, dy, det_dist, wavelength) where units are mm,mm,mm,and A
-        # respectively.
+        
+        # get_q(dx, dy, det_dist, wavelength) where units are mm,mm,mm,and A respectively.
         self.qmin = get_q(1.0, 1.0, detector.distance, source.wavelength)
 
         self.qmax = get_q(49.5, 49.5, detector.distance, source.wavelength)
-
+        
         self.qstep = len(x_0)
-        x = np.linspace(start=-1 * self.qmax,
-                        stop=self.qmax,
-                        num=self.qstep,
-                        endpoint=True)
-        y = np.linspace(start=-1 * self.qmax,
-                        stop=self.qmax,
-                        num=self.qstep,
-                        endpoint=True)
-        self.data.x_bins = x
-        self.data.y_bins = y
+        x=  np.linspace(start= -1*self.qmax,
+                               stop= self.qmax,
+                               num= self.qstep,
+                               endpoint=True )  
+        y = np.linspace(start= -1*self.qmax,
+                               stop= self.qmax,
+                               num= self.qstep,
+                               endpoint=True )
+        self.data.x_bins=x
+        self.data.y_bins=y
         self.data = reader2D_converter(self.data)
-
+            
     def test_ring_flat_distribution(self):
         """
             Test ring averaging
         """
-        r = Ring(r_min=2 * self.qmin, r_max=5 * self.qmin,
-                 center_x=self.data.detector[0].beam_center.x,
+        r = Ring(r_min=2*self.qmin, r_max=5*self.qmin, 
+                 center_x=self.data.detector[0].beam_center.x, 
                  center_y=self.data.detector[0].beam_center.y)
         r.nbins_phi = 20
-
+        
         o = r(self.data)
         for i in range(20):
             self.assertEqual(o.y[i], 1.0)
-
+            
     def test_sectorphi_full(self):
         """
             Test sector averaging
         """
-        r = SectorPhi(r_min=self.qmin, r_max=3 * self.qmin,
-                      phi_min=0, phi_max=math.pi * 2.0)
+        r = SectorPhi(r_min=self.qmin, r_max=3*self.qmin, 
+                      phi_min=0, phi_max=math.pi*2.0)
         r.nbins_phi = 20
         o = r(self.data)
         for i in range(7):
             self.assertEqual(o.y[i], 1.0)
-
+            
+            
     def test_sectorphi_partial(self):
         """
         """
         phi_max = math.pi * 1.5
-        r = SectorPhi(r_min=self.qmin, r_max=3 * self.qmin,
+        r = SectorPhi(r_min=self.qmin, r_max=3*self.qmin, 
                       phi_min=0, phi_max=phi_max)
         self.assertEqual(r.phi_max, phi_max)
@@ -98,52 +91,47 @@
         for i in range(17):
             self.assertEqual(o.y[i], 1.0)
-
-
-class DataInfoTests(unittest.TestCase):
-
+            
+            
+
+class data_info_tests(unittest.TestCase):
+    
     def setUp(self):
-        filepath = os.path.join(os.path.dirname(
-            os.path.realpath(__file__)), 'MAR07232_rest.ASC')
-        self.data = Loader().load(filepath)
-
+        self.data = Loader().load('MAR07232_rest.ASC')
+        
     def test_ring(self):
         """
             Test ring averaging
         """
-        r = Ring(r_min=.005, r_max=.01,
-                 center_x=self.data.detector[0].beam_center.x,
+        r = Ring(r_min=.005, r_max=.01, 
+                 center_x=self.data.detector[0].beam_center.x, 
                  center_y=self.data.detector[0].beam_center.y,
-                 nbins=20)
+                 nbins = 20)
         ##r.nbins_phi = 20
-
-        o = r(self.data)
-        filepath = os.path.join(os.path.dirname(
-            os.path.realpath(__file__)), 'ring_testdata.txt')
-        answer = Loader().load(filepath)
-
+        
+        o = r(self.data)
+        answer = Loader().load('ring_testdata.txt')
+        
         for i in range(r.nbins_phi - 1):
             self.assertAlmostEqual(o.x[i + 1], answer.x[i], 4)
             self.assertAlmostEqual(o.y[i + 1], answer.y[i], 4)
             self.assertAlmostEqual(o.dy[i + 1], answer.dy[i], 4)
-
+            
     def test_circularavg(self):
         """
-        Test circular averaging
-        The test data was not generated by IGOR.
-        """
-        r = CircularAverage(r_min=.00, r_max=.025,
-                            bin_width=0.0003)
-        r.nbins_phi = 20
-
-        o = r(self.data)
-
-        filepath = os.path.join(os.path.dirname(
-            os.path.realpath(__file__)), 'avg_testdata.txt')
-        answer = Loader().load(filepath)
+            Test circular averaging
+            The test data was not generated by IGOR.
+        """
+        r = CircularAverage(r_min=.00, r_max=.025, 
+                 bin_width=0.0003)
+        r.nbins_phi = 20
+        
+        o = r(self.data)
+
+        answer = Loader().load('avg_testdata.txt')
         for i in range(r.nbins_phi):
             self.assertAlmostEqual(o.x[i], answer.x[i], 4)
             self.assertAlmostEqual(o.y[i], answer.y[i], 4)
             self.assertAlmostEqual(o.dy[i], answer.dy[i], 4)
-
+            
     def test_box(self):
         """
@@ -151,16 +139,17 @@
             The test data was not generated by IGOR.
         """
-
+        from sas.sascalc.dataloader.manipulations import Boxsum, Boxavg
+        
         r = Boxsum(x_min=.01, x_max=.015, y_min=0.01, y_max=0.015)
         s, ds, npoints = r(self.data)
         self.assertAlmostEqual(s, 34.278990899999997, 4)
         self.assertAlmostEqual(ds, 7.8007981835194293, 4)
-        self.assertAlmostEqual(npoints, 324.0000, 4)
-
+        self.assertAlmostEqual(npoints, 324.0000, 4)        
+    
         r = Boxavg(x_min=.01, x_max=.015, y_min=0.01, y_max=0.015)
         s, ds = r(self.data)
         self.assertAlmostEqual(s, 0.10579935462962962, 4)
         self.assertAlmostEqual(ds, 0.024076537603455028, 4)
-
+            
     def test_slabX(self):
         """
@@ -168,18 +157,16 @@
             The test data was not generated by IGOR.
         """
-
-        r = SlabX(x_min=-.01, x_max=.01, y_min=-0.0002,
-                  y_max=0.0002, bin_width=0.0004)
+        from sas.sascalc.dataloader.manipulations import SlabX
+        
+        r = SlabX(x_min=-.01, x_max=.01, y_min=-0.0002, y_max=0.0002, bin_width=0.0004)
         r.fold = False
         o = r(self.data)
 
-        filepath = os.path.join(os.path.dirname(
-            os.path.realpath(__file__)), 'slabx_testdata.txt')
-        answer = Loader().load(filepath)
-        for i in range(len(o.x)):
-            self.assertAlmostEqual(o.x[i], answer.x[i], 4)
-            self.assertAlmostEqual(o.y[i], answer.y[i], 4)
-            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4)
-
+        answer = Loader().load('slabx_testdata.txt')
+        for i in range(len(o.x)):
+            self.assertAlmostEqual(o.x[i], answer.x[i], 4)
+            self.assertAlmostEqual(o.y[i], answer.y[i], 4)
+            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4)
+            
     def test_slabY(self):
         """
@@ -187,18 +174,16 @@
             The test data was not generated by IGOR.
         """
-
-        r = SlabY(x_min=.005, x_max=.01, y_min=-
-                  0.01, y_max=0.01, bin_width=0.0004)
+        from sas.sascalc.dataloader.manipulations import SlabY
+        
+        r = SlabY(x_min=.005, x_max=.01, y_min=-0.01, y_max=0.01, bin_width=0.0004)
         r.fold = False
         o = r(self.data)
 
-        filepath = os.path.join(os.path.dirname(
-            os.path.realpath(__file__)), 'slaby_testdata.txt')
-        answer = Loader().load(filepath)
-        for i in range(len(o.x)):
-            self.assertAlmostEqual(o.x[i], answer.x[i], 4)
-            self.assertAlmostEqual(o.y[i], answer.y[i], 4)
-            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4)
-
+        answer = Loader().load('slaby_testdata.txt')
+        for i in range(len(o.x)):
+            self.assertAlmostEqual(o.x[i], answer.x[i], 4)
+            self.assertAlmostEqual(o.y[i], answer.y[i], 4)
+            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4)
+            
     def test_sectorphi_full(self):
         """
@@ -208,9 +193,11 @@
             The test data was not generated by IGOR.
         """
-
+        from sas.sascalc.dataloader.manipulations import SectorPhi
+        import math
+        
         nbins = 19
         phi_min = math.pi / (nbins + 1)
         phi_max = math.pi * 2 - phi_min
-
+        
         r = SectorPhi(r_min=.005,
                       r_max=.01,
@@ -220,12 +207,10 @@
         o = r(self.data)
 
-        filepath = os.path.join(os.path.dirname(
-            os.path.realpath(__file__)), 'ring_testdata.txt')
-        answer = Loader().load(filepath)
-        for i in range(len(o.x)):
-            self.assertAlmostEqual(o.x[i], answer.x[i], 4)
-            self.assertAlmostEqual(o.y[i], answer.y[i], 4)
-            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4)
-
+        answer = Loader().load('ring_testdata.txt')
+        for i in range(len(o.x)):
+            self.assertAlmostEqual(o.x[i], answer.x[i], 4)
+            self.assertAlmostEqual(o.y[i], answer.y[i], 4)
+            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4)
+            
     def test_sectorphi_quarter(self):
         """
@@ -233,17 +218,17 @@
             The test data was not generated by IGOR.
         """
-
-        r = SectorPhi(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi / 2.0)
-        r.nbins_phi = 20
-        o = r(self.data)
-
-        filepath = os.path.join(os.path.dirname(
-            os.path.realpath(__file__)), 'sectorphi_testdata.txt')
-        answer = Loader().load(filepath)
-        for i in range(len(o.x)):
-            self.assertAlmostEqual(o.x[i], answer.x[i], 4)
-            self.assertAlmostEqual(o.y[i], answer.y[i], 4)
-            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4)
-
+        from sas.sascalc.dataloader.manipulations import SectorPhi
+        import math
+        
+        r = SectorPhi(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi/2.0)
+        r.nbins_phi = 20
+        o = r(self.data)
+
+        answer = Loader().load('sectorphi_testdata.txt')
+        for i in range(len(o.x)):
+            self.assertAlmostEqual(o.x[i], answer.x[i], 4)
+            self.assertAlmostEqual(o.y[i], answer.y[i], 4)
+            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4)
+            
     def test_sectorq_full(self):
         """
@@ -251,17 +236,17 @@
             The test data was not generated by IGOR.
         """
-
-        r = SectorQ(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi / 2.0)
-        r.nbins_phi = 20
-        o = r(self.data)
-
-        filepath = os.path.join(os.path.dirname(
-            os.path.realpath(__file__)), 'sectorq_testdata.txt')
-        answer = Loader().load(filepath)
-        for i in range(len(o.x)):
-            self.assertAlmostEqual(o.x[i], answer.x[i], 4)
-            self.assertAlmostEqual(o.y[i], answer.y[i], 4)
-            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4)
-
+        from sas.sascalc.dataloader.manipulations import SectorQ
+        import math
+        
+        r = SectorQ(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi/2.0)
+        r.nbins_phi = 20
+        o = r(self.data)
+
+        answer = Loader().load('sectorq_testdata.txt')
+        for i in range(len(o.x)):
+            self.assertAlmostEqual(o.x[i], answer.x[i], 4)
+            self.assertAlmostEqual(o.y[i], answer.y[i], 4)
+            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4)
+            
 
 if __name__ == '__main__':
Index: test/sasguiframe/test/utest_manipulations.py
===================================================================
--- test/sasguiframe/test/utest_manipulations.py	(revision 959eb0181ad06828a748f04512f953aad5b31659)
+++ test/sasguiframe/test/utest_manipulations.py	(revision 959eb0181ad06828a748f04512f953aad5b31659)
@@ -2,23 +2,21 @@
     Unit tests for data manipulations
 """
-# TODO: what happens if you add a Data1D to a Data2D?
-
+#TODO: what happens if you add a Data1D to a Data2D?
+
+import unittest
 import math
+import numpy as np
+from sas.sascalc.dataloader.loader import  Loader
+from sas.sasgui.guiframe.dataFitting import Data1D, Data2D
+from sas.sasgui.guiframe.dataFitting import Data1D as Theory1D
+ 
 import os.path
-import unittest
-
-import numpy as np
-
-from sas.sascalc.dataloader.loader import Loader
-from sas.sasgui.guiframe.dataFitting import Data1D
-from sas.sasgui.guiframe.dataFitting import Data2D
-
-
-class DataInfoTests(unittest.TestCase):
-
+
+class data_info_tests(unittest.TestCase):
+    
     def setUp(self):
         data = Loader().load("cansas1d.xml")
         self.data = data[0]
-
+        
     def test_clone1D(self):
         """
@@ -26,27 +24,24 @@
         """
         clone = self.data.clone_without_data()
-
+        
         for i in range(len(self.data.detector)):
-            self.assertEqual(
-                self.data.detector[i].distance, clone.detector[i].distance)
-
-
-class Theory1DTests(unittest.TestCase):
-
+            self.assertEqual(self.data.detector[i].distance, clone.detector[i].distance)
+            
+class theory1d_tests(unittest.TestCase):
+    
     def setUp(self):
         data = Loader().load("cansas1d.xml")
         self.data = data[0]
-
+        
     def test_clone_theory1D(self):
         """
             Test basic cloning
         """
-        theory = Data1D(x=[], y=[], dy=None)
+        theory = Theory1D(x=[], y=[], dy=None)
         theory.clone_without_data(clone=self.data)
         theory.copy_from_datainfo(data1d=self.data)
         for i in range(len(self.data.detector)):
-            self.assertEqual(
-                self.data.detector[i].distance, theory.detector[i].distance)
-
+            self.assertEqual(self.data.detector[i].distance, theory.detector[i].distance)
+            
         for i in range(len(self.data.x)):
             self.assertEqual(self.data.x[i], theory.x[i])
@@ -54,22 +49,22 @@
             self.assertEqual(self.data.dy[i], theory.dy[i])
 
-
-class ManipTests(unittest.TestCase):
-
+class manip_tests(unittest.TestCase):
+    
     def setUp(self):
         # Create two data sets to play with
         x_0 = np.ones(5)
         for i in range(5):
-            x_0[i] = x_0[i] * (i + 1.0)
-
-        y_0 = 2.0 * np.ones(5)
-        dy_0 = 0.5 * np.ones(5)
+            x_0[i] = x_0[i]*(i+1.0)
+            
+        y_0 = 2.0*np.ones(5)
+        dy_0 = 0.5*np.ones(5)
         self.data = Data1D(x_0, y_0, dy=dy_0)
-
+        
         x = self.data.x
         y = np.ones(5)
         dy = np.ones(5)
         self.data2 = Data1D(x, y, dy=dy)
-
+        
+        
     def test_load(self):
         """
@@ -78,102 +73,99 @@
         # There should be 5 entries in the file
         self.assertEqual(len(self.data.x), 5)
-
+        
         for i in range(5):
             # The x values should be from 1 to 5
-            self.assertEqual(self.data.x[i], float(i + 1))
-
+            self.assertEqual(self.data.x[i], float(i+1))
+        
             # All y-error values should be 0.5
-            self.assertEqual(self.data.dy[i], 0.5)
-
+            self.assertEqual(self.data.dy[i], 0.5)    
+            
             # All y values should be 2.0
-            self.assertEqual(self.data.y[i], 2.0)
-
+            self.assertEqual(self.data.y[i], 2.0)    
+        
     def test_add(self):
-        result = self.data2 + self.data
+        result = self.data2+self.data
         for i in range(5):
             self.assertEqual(result.y[i], 3.0)
-            self.assertEqual(result.dy[i], math.sqrt(0.5**2 + 1.0))
-
+            self.assertEqual(result.dy[i], math.sqrt(0.5**2+1.0))
+        
     def test_sub(self):
-        result = self.data2 - self.data
+        result = self.data2-self.data
         for i in range(5):
             self.assertEqual(result.y[i], -1.0)
-            self.assertEqual(result.dy[i], math.sqrt(0.5**2 + 1.0))
-
+            self.assertEqual(result.dy[i], math.sqrt(0.5**2+1.0))
+        
     def test_mul(self):
-        result = self.data2 * self.data
+        result = self.data2*self.data
         for i in range(5):
             self.assertEqual(result.y[i], 2.0)
-            self.assertEqual(result.dy[i], math.sqrt(
-                (0.5 * 1.0)**2 + (1.0 * 2.0)**2))
-
+            self.assertEqual(result.dy[i], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2))
+        
     def test_div(self):
-        result = self.data2 / self.data
+        result = self.data2/self.data
         for i in range(5):
             self.assertEqual(result.y[i], 0.5)
-            self.assertEqual(result.dy[i], math.sqrt(
-                (1.0 / 2.0)**2 + (0.5 * 1.0 / 4.0)**2))
-
+            self.assertEqual(result.dy[i], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2))
+        
     def test_radd(self):
-        result = self.data + 3.0
+        result = self.data+3.0
         for i in range(5):
             self.assertEqual(result.y[i], 5.0)
             self.assertEqual(result.dy[i], 0.5)
-
-        result = 3.0 + self.data
+            
+        result = 3.0+self.data
         for i in range(5):
             self.assertEqual(result.y[i], 5.0)
             self.assertEqual(result.dy[i], 0.5)
-
+            
     def test_rsub(self):
-        result = self.data - 3.0
+        result = self.data-3.0
         for i in range(5):
             self.assertEqual(result.y[i], -1.0)
             self.assertEqual(result.dy[i], 0.5)
-
-        result = 3.0 - self.data
+            
+        result = 3.0-self.data
         for i in range(5):
             self.assertEqual(result.y[i], 1.0)
             self.assertEqual(result.dy[i], 0.5)
-
+            
     def test_rmul(self):
-        result = self.data * 3.0
+        result = self.data*3.0
         for i in range(5):
             self.assertEqual(result.y[i], 6.0)
             self.assertEqual(result.dy[i], 1.5)
-
-        result = 3.0 * self.data
+            
+        result = 3.0*self.data
         for i in range(5):
             self.assertEqual(result.y[i], 6.0)
             self.assertEqual(result.dy[i], 1.5)
-
+            
     def test_rdiv(self):
-        result = self.data / 4.0
+        result = self.data/4.0
         for i in range(5):
             self.assertEqual(result.y[i], 0.5)
             self.assertEqual(result.dy[i], 0.125)
-
-        result = 6.0 / self.data
+            
+        result = 6.0/self.data
         for i in range(5):
             self.assertEqual(result.y[i], 3.0)
-            self.assertEqual(result.dy[i], 6.0 * 0.5 / 4.0)
-
-
-class Manin2DTests(unittest.TestCase):
-
+            self.assertEqual(result.dy[i], 6.0*0.5/4.0)
+            
+class manip_2D(unittest.TestCase):
+    
     def setUp(self):
         # Create two data sets to play with
-        x_0 = 2.0 * np.ones(25)
-        dx_0 = 0.5 * np.ones(25)
+        x_0 = 2.0*np.ones(25)
+        dx_0 = 0.5*np.ones(25)
         qx_0 = np.arange(25)
         qy_0 = np.arange(25)
         mask_0 = np.zeros(25)
-        dqx_0 = np.arange(25) / 100
-        dqy_0 = np.arange(25) / 100
+        dqx_0 = np.arange(25)/100
+        dqy_0 = np.arange(25)/100
         q_0 = np.sqrt(qx_0 * qx_0 + qy_0 * qy_0)
-        self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0,
-                           qy_data=qy_0, q_data=q_0, mask=mask_0,
+        self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0, 
+                           qy_data=qy_0, q_data=q_0, mask=mask_0, 
                            dqx_data=dqx_0, dqy_data=dqy_0)
-
+        
         y = np.ones(25)
         dy = np.ones(25)
@@ -182,7 +174,8 @@
         mask = np.zeros(25)
         q = np.sqrt(qx * qx + qy * qy)
-        self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy,
+        self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy, 
                             q_data=q, mask=mask)
-
+        
+        
     def test_load(self):
         """
@@ -191,99 +184,96 @@
         # There should be 5 entries in the file
         self.assertEqual(np.size(self.data.data), 25)
-
+        
         for i in range(25):
             # All y-error values should be 0.5
-            self.assertEqual(self.data.err_data[i], 0.5)
-
+            self.assertEqual(self.data.err_data[i], 0.5)    
+            
             # All y values should be 2.0
-            self.assertEqual(self.data.data[i], 2.0)
-
+            self.assertEqual(self.data.data[i], 2.0)    
+        
     def test_add(self):
-        result = self.data2 + self.data
+        result = self.data2+self.data
         for i in range(25):
             self.assertEqual(result.data[i], 3.0)
-            self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0))
-
+            self.assertEqual(result.err_data[i], math.sqrt(0.5**2+1.0))
+        
     def test_sub(self):
-        result = self.data2 - self.data
+        result = self.data2-self.data
+        for i in range(25):
+                self.assertEqual(result.data[i], -1.0)
+                self.assertEqual(result.err_data[i], math.sqrt(0.5**2+1.0))
+        
+    def test_mul(self):
+        result = self.data2*self.data
+        for i in range(25):
+            self.assertEqual(result.data[i], 2.0)
+            self.assertEqual(result.err_data[i], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2))
+        
+    def test_div(self):
+        result = self.data2/self.data
+        for i in range(25):
+            self.assertEqual(result.data[i], 0.5)
+            self.assertEqual(result.err_data[i], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2))
+        
+    def test_radd(self):
+        result = self.data+3.0
+        for i in range(25):
+            self.assertEqual(result.data[i], 5.0)
+            self.assertEqual(result.err_data[i], 0.5)
+   
+        result = 3.0+self.data
+        for i in range(25):
+            self.assertEqual(result.data[i], 5.0)
+            self.assertEqual(result.err_data[i], 0.5)
+            
+    def test_rsub(self):
+        result = self.data-3.0
         for i in range(25):
             self.assertEqual(result.data[i], -1.0)
-            self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0))
-
-    def test_mul(self):
-        result = self.data2 * self.data
-        for i in range(25):
-            self.assertEqual(result.data[i], 2.0)
-            self.assertEqual(result.err_data[i], math.sqrt(
-                (0.5 * 1.0)**2 + (1.0 * 2.0)**2))
-
-    def test_div(self):
-        result = self.data2 / self.data
-        for i in range(25):
-            self.assertEqual(result.data[i], 0.5)
-            self.assertEqual(result.err_data[i], math.sqrt(
-                (1.0 / 2.0)**2 + (0.5 * 1.0 / 4.0)**2))
-
-    def test_radd(self):
-        result = self.data + 3.0
-        for i in range(25):
-            self.assertEqual(result.data[i], 5.0)
-            self.assertEqual(result.err_data[i], 0.5)
-
-        result = 3.0 + self.data
-        for i in range(25):
-            self.assertEqual(result.data[i], 5.0)
-            self.assertEqual(result.err_data[i], 0.5)
-
-    def test_rsub(self):
-        result = self.data - 3.0
-        for i in range(25):
-            self.assertEqual(result.data[i], -1.0)
-            self.assertEqual(result.err_data[i], 0.5)
-
-        result = 3.0 - self.data
+            self.assertEqual(result.err_data[i], 0.5)
+    
+        result = 3.0-self.data
         for i in range(25):
             self.assertEqual(result.data[i], 1.0)
             self.assertEqual(result.err_data[i], 0.5)
-
+            
     def test_rmul(self):
-        result = self.data * 3.0
+        result = self.data*3.0
         for i in range(25):
             self.assertEqual(result.data[i], 6.0)
             self.assertEqual(result.err_data[i], 1.5)
-
-        result = 3.0 * self.data
+ 
+        result = 3.0*self.data
         for i in range(25):
             self.assertEqual(result.data[i], 6.0)
             self.assertEqual(result.err_data[i], 1.5)
-
+            
     def test_rdiv(self):
-        result = self.data / 4.0
+        result = self.data/4.0
         for i in range(25):
             self.assertEqual(result.data[i], 0.5)
             self.assertEqual(result.err_data[i], 0.125)
 
-        result = 6.0 / self.data
+        result = 6.0/self.data
         for i in range(25):
             self.assertEqual(result.data[i], 3.0)
-            self.assertEqual(result.err_data[i], 6.0 * 0.5 / 4.0)
-
-
-class ExtraManip2DTests(unittest.TestCase):
-
+            self.assertEqual(result.err_data[i], 6.0*0.5/4.0)
+    
+class extra_manip_2D(unittest.TestCase):
+    
     def setUp(self):
         # Create two data sets to play with
-        x_0 = 2.0 * np.ones(25)
-        dx_0 = 0.5 * np.ones(25)
+        x_0 = 2.0*np.ones(25)
+        dx_0 = 0.5*np.ones(25)
         qx_0 = np.arange(25)
         qy_0 = np.arange(25)
         mask_0 = np.zeros(25)
-        dqx_0 = np.arange(25) / 100
-        dqy_0 = np.arange(25) / 100
+        dqx_0 = np.arange(25)/100
+        dqy_0 = np.arange(25)/100
         q_0 = np.sqrt(qx_0 * qx_0 + qy_0 * qy_0)
-        self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0,
-                           qy_data=qy_0, q_data=q_0, mask=mask_0,
+        self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0, 
+                           qy_data=qy_0, q_data=q_0, mask=mask_0, 
                            dqx_data=dqx_0, dqy_data=dqy_0)
-
+        
         y = np.ones(25)
         dy = np.ones(25)
@@ -292,7 +282,8 @@
         mask = np.zeros(25)
         q = np.sqrt(qx * qx + qy * qy)
-        self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy,
+        self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy, 
                             q_data=q, mask=mask)
-
+        
+        
     def test_load(self):
         """
@@ -301,83 +292,81 @@
         # There should be 5 entries in the file
         self.assertEqual(np.size(self.data.data), 25)
-
+        
         for i in range(25):
             # All y-error values should be 0.5
-            self.assertEqual(self.data.err_data[i], 0.5)
-
+            self.assertEqual(self.data.err_data[i], 0.5)    
+            
             # All y values should be 2.0
-            self.assertEqual(self.data.data[i], 2.0)
-
+            self.assertEqual(self.data.data[i], 2.0)    
+        
     def test_add(self):
-        result = self.data2 + self.data
+        result = self.data2+self.data
         for i in range(25):
             self.assertEqual(result.data[i], 3.0)
-            self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0))
-
+            self.assertEqual(result.err_data[i], math.sqrt(0.5**2+1.0))
+        
     def test_sub(self):
-        result = self.data2 - self.data
+        result = self.data2-self.data
+        for i in range(25):
+                self.assertEqual(result.data[i], -1.0)
+                self.assertEqual(result.err_data[i], math.sqrt(0.5**2+1.0))
+        
+    def test_mul(self):
+        result = self.data2*self.data
+        for i in range(25):
+            self.assertEqual(result.data[i], 2.0)
+            self.assertEqual(result.err_data[i], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2))
+        
+    def test_div(self):
+        result = self.data2/self.data
+        for i in range(25):
+            self.assertEqual(result.data[i], 0.5)
+            self.assertEqual(result.err_data[i], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2))
+        
+    def test_radd(self):
+        result = self.data+3.0
+        for i in range(25):
+            self.assertEqual(result.data[i], 5.0)
+            self.assertEqual(result.err_data[i], 0.5)
+   
+        result = 3.0+self.data
+        for i in range(25):
+            self.assertEqual(result.data[i], 5.0)
+            self.assertEqual(result.err_data[i], 0.5)
+            
+    def test_rsub(self):
+        result = self.data-3.0
         for i in range(25):
             self.assertEqual(result.data[i], -1.0)
-            self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0))
-
-    def test_mul(self):
-        result = self.data2 * self.data
-        for i in range(25):
-            self.assertEqual(result.data[i], 2.0)
-            self.assertEqual(result.err_data[i], math.sqrt(
-                (0.5 * 1.0)**2 + (1.0 * 2.0)**2))
-
-    def test_div(self):
-        result = self.data2 / self.data
-        for i in range(25):
-            self.assertEqual(result.data[i], 0.5)
-            self.assertEqual(result.err_data[i], math.sqrt(
-                (1.0 / 2.0)**2 + (0.5 * 1.0 / 4.0)**2))
-
-    def test_radd(self):
-        result = self.data + 3.0
-        for i in range(25):
-            self.assertEqual(result.data[i], 5.0)
-            self.assertEqual(result.err_data[i], 0.5)
-
-        result = 3.0 + self.data
-        for i in range(25):
-            self.assertEqual(result.data[i], 5.0)
-            self.assertEqual(result.err_data[i], 0.5)
-
-    def test_rsub(self):
-        result = self.data - 3.0
-        for i in range(25):
-            self.assertEqual(result.data[i], -1.0)
-            self.assertEqual(result.err_data[i], 0.5)
-
-        result = 3.0 - self.data
+            self.assertEqual(result.err_data[i], 0.5)
+    
+        result = 3.0-self.data
         for i in range(25):
             self.assertEqual(result.data[i], 1.0)
             self.assertEqual(result.err_data[i], 0.5)
-
+            
     def test_rmul(self):
-        result = self.data * 3.0
+        result = self.data*3.0
         for i in range(25):
             self.assertEqual(result.data[i], 6.0)
             self.assertEqual(result.err_data[i], 1.5)
-
-        result = 3.0 * self.data
+ 
+        result = 3.0*self.data
         for i in range(25):
             self.assertEqual(result.data[i], 6.0)
             self.assertEqual(result.err_data[i], 1.5)
-
+            
     def test_rdiv(self):
-        result = self.data / 4.0
+        result = self.data/4.0
         for i in range(25):
             self.assertEqual(result.data[i], 0.5)
             self.assertEqual(result.err_data[i], 0.125)
 
-        result = 6.0 / self.data
+        result = 6.0/self.data
         for i in range(25):
             self.assertEqual(result.data[i], 3.0)
-            self.assertEqual(result.err_data[i], 6.0 * 0.5 / 4.0)
-
+            self.assertEqual(result.err_data[i], 6.0*0.5/4.0)
 
 if __name__ == '__main__':
     unittest.main()
+   
