Index: guiframe/local_perspectives/plotting/Plotter2D.py
===================================================================
--- guiframe/local_perspectives/plotting/Plotter2D.py	(revision ef0c1700493953c0ec4b1091779caf8c5177bf15)
+++ guiframe/local_perspectives/plotting/Plotter2D.py	(revision 38224f10e4ed8289b03ee51a242f885249dc2c12)
@@ -203,4 +203,7 @@
         wx.EVT_MENU(self, id, self.onSectorPhi) 
       
+        id = wx.NewId()
+        slicerpop.Append(id, '&Box averaging')
+        wx.EVT_MENU(self, id, self.onBoxavg) 
         
         id = wx.NewId()
@@ -367,5 +370,16 @@
         wx.PostEvent(self.parent, InternalEvent(slicer= AnnulusInteractor))
         
-       
+    def onBoxavg(self,event):
+        from boxSlicer import BoxInteractor
+        self.onClearSlicer(event)
+        wx.PostEvent(self.parent, InternalEvent(slicer= BoxInteractor))
+        print "onboxavg",self.slicer
+        if self.slicer !=None:
+            from SlicerParameters import SlicerParameterPanel
+            dialog = SlicerParameterPanel(self.parent, -1, "Slicer Parameters")
+            dialog.set_slicer(self.slicer.__class__.__name__,
+                            self.slicer.get_params())
+            if dialog.ShowModal() == wx.ID_OK:
+                dialog.Destroy() 
     def onClearSlicer(self, event):
         """
Index: guiframe/local_perspectives/plotting/boxDialog.py
===================================================================
--- guiframe/local_perspectives/plotting/boxDialog.py	(revision 38224f10e4ed8289b03ee51a242f885249dc2c12)
+++ guiframe/local_perspectives/plotting/boxDialog.py	(revision 38224f10e4ed8289b03ee51a242f885249dc2c12)
@@ -0,0 +1,138 @@
+"""
+    Panel class to show the slicer parameters 
+"""
+
+import wx
+import wx.lib.newevent
+from copy import deepcopy
+
+(SlicerEvent, EVT_SLICER)   = wx.lib.newevent.NewEvent()
+(SlicerParameterEvent, EVT_SLICER_PARS)   = wx.lib.newevent.NewEvent()
+
+
+def format_number(value, high=False):
+    """
+        Return a float in a standardized, human-readable formatted string 
+    """
+    try: 
+        value = float(value)
+    except:
+        return "NaN"
+    
+    if high:
+        return "%-6.4g" % value
+    else:
+        return "%-5.3g" % value
+
+class SlicerParameterPanel(wx.Dialog):
+    #TODO: show units
+    #TODO: order parameters properly
+    
+    def __init__(self, parent, *args, **kwargs):
+        wx.Dialog.__init__(self, parent, *args, **kwargs)
+        self.params = {}
+        self.parent = parent
+        self.type = None
+        self.listeners = []
+        self.parameters = []
+        self.bck = wx.GridBagSizer(5,5)
+        self.SetSizer(self.bck)
+               
+        title = wx.StaticText(self, -1, "Right-click on 2D plot for slicer options", style=wx.ALIGN_LEFT)
+        self.bck.Add(title, (0,0), (1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
+        
+        # Bindings
+        self.parent.Bind(EVT_SLICER, self.onEVT_SLICER)
+        self.parent.Bind(EVT_SLICER_PARS, self.onParamChange)
+
+    def onEVT_SLICER(self, event):
+        """
+            Process EVT_SLICER events
+            When the slicer changes, update the panel
+            
+            @param event: EVT_SLICER event
+        """
+        event.Skip()
+        if event.obj_class==None:
+            self.set_slicer(None, None)
+        else:
+            self.set_slicer(event.type, event.params)
+        
+    def set_slicer(self, type, params):
+        """
+            Rebuild the panel
+        """
+        self.bck.Clear(True)  
+        self.type = type  
+        
+        if type==None:
+            title = wx.StaticText(self, -1, "Right-click on 2D plot for slicer options", style=wx.ALIGN_LEFT)
+            self.bck.Add(title, (0,0), (1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
+
+        else:
+            title = wx.StaticText(self, -1, "Slicer Parameters", style=wx.ALIGN_LEFT)
+            self.bck.Add(title, (0,0), (1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
+            ix = 0
+            iy = 0
+            self.parameters = []
+            #params = slicer.get_params()
+            keys = params.keys()
+            keys.sort()
+            
+            for item in keys:
+                iy += 1
+                ix = 0
+                text = wx.StaticText(self, -1, item, style=wx.ALIGN_LEFT)
+                #self.bck.Add(text, (iy,ix), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
+                self.bck.Add(text, (iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+                ctl = wx.TextCtrl(self, -1, size=(80,20), style=wx.TE_PROCESS_ENTER)
+                
+                ctl.SetToolTipString("Modify the value of %s to change the 2D slicer" % item)
+                
+                ix = 1
+                ctl.SetValue(format_number(str(params[item])))
+                self.Bind(wx.EVT_TEXT_ENTER, self.onTextEnter)
+                ctl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
+                self.parameters.append([item, ctl])
+                #self.bck.Add(ctl, (iy,ix), flag=wx.TOP|wx.BOTTOM, border = 0)
+                self.bck.Add(ctl, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+                
+                ix =3
+                self.bck.Add((20,20), (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+            iy +=1
+            ix = 1
+            self.bck.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        self.bck.Layout()
+        self.bck.Fit(self)
+        self.parent.GetSizer().Layout()
+
+    def onParamChange(self, evt):
+        evt.Skip()
+        if evt.type == "UPDATE":
+            for item in self.parameters:              
+                if item[0] in evt.params:
+                    item[1].SetValue("%-5.3g" %evt.params[item[0]])
+                    item[1].Refresh()
+        
+    def onTextEnter(self, evt): 
+        """
+            Parameters have changed
+        """ 
+        params = {}
+        has_error = False
+        for item in self.parameters:
+            try:
+                params[item[0]] = float(item[1].GetValue())
+                item[1].SetBackgroundColour(
+                        wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
+                item[1].Refresh()
+            except:
+                has_error = True
+                item[1].SetBackgroundColour("pink")
+                item[1].Refresh()
+
+        if has_error==False:
+            # Post parameter event
+            event = SlicerParameterEvent(type=self.type, params=params)
+            wx.PostEvent(self.parent, event)
+        
Index: guiframe/local_perspectives/plotting/boxSlicer.py
===================================================================
--- guiframe/local_perspectives/plotting/boxSlicer.py	(revision 2d107b883288e417fcd3b30f942cda5fd43b54c7)
+++ guiframe/local_perspectives/plotting/boxSlicer.py	(revision 38224f10e4ed8289b03ee51a242f885249dc2c12)
@@ -8,18 +8,18 @@
 
 # Debug printout
-from config import printEVT
+#from config import printEVT
 from BaseInteractor import _BaseInteractor
 from copy import deepcopy
 import math
 
-from Plotter1D import AddPlotEvent
+#from Plotter1D import AddPlotEvent
 import SlicerParameters
 import wx
 
-class AnnulusInteractor(_BaseInteractor):
+class BoxInteractor(_BaseInteractor):
     """
          Select an annulus through a 2D plot
     """
-    def __init__(self,base,axes,color='black', zorder=3, x_min=0.025, x_max=0.025, y_min=0.025, y_max=0.025):
+    def __init__(self,base,axes,color='black', zorder=3, x_min=0.0025, x_max=0.0025, y_min=0.0025, y_max=0.0025):
         
         _BaseInteractor.__init__(self, base, axes, color=color)
@@ -28,11 +28,12 @@
         self.qmax = self.base.qmax
         self.connect = self.base.connect
-        self.xmin=xmin
-        self.ymin=ymin
-        self.xmax=xmax
-        self.ymax=ymax
+        self.xmin=x_min
+        self.ymin=y_min
+        self.xmax=x_max
+        self.ymax=y_max
         ## Number of points on the plot
         self.nbins = 20
-        
+        self.count=0
+        self.error=0
         #self.theta3= 2*self.theta2 -self.theta1
         # Inner circle
@@ -59,6 +60,6 @@
         
                       
-        #self.update()
-        self._post_data()
+        self.update()
+        #self._post_data()
         
         # Bind to slice parameter events
@@ -67,5 +68,5 @@
 
     def _onEVT_SLICER_PARS(self, event):
-        printEVT("AnnulusSlicer._onEVT_SLICER_PARS")
+        #printEVT("AnnulusSlicer._onEVT_SLICER_PARS")
         event.Skip()
         if event.type == self.__class__.__name__:
@@ -93,6 +94,8 @@
     def clear(self):
         self.clear_markers()
-        self.outer_circle.clear()
-        self.inner_circle.clear()
+        self.left_line.clear()
+        self.right_line.clear()
+        self.top_line.clear()
+        self.bottom_line.clear()
         #self.base.connect.disconnect()
         self.base.parent.Unbind(SlicerParameters.EVT_SLICER_PARS)
@@ -103,4 +106,8 @@
         resetting the widgets.
         """
+        self.left_line.update()
+        self.right_line.update()
+        self.top_line.update()
+        self.bottom_line.update()
         if self.left_line.has_move:
             print "left has moved"
@@ -135,46 +142,5 @@
             self.right_line.update(ymin= self.bottom_line.y ,ymax= self.top_line.y)
             
-    def get_data(self, image, x, y):
-        """ 
-            Return a 1D vector corresponding to the slice
-            @param image: data matrix
-            @param x: x matrix
-            @param y: y matrix
-        """
-        # If we have no data, just return
-        if image == None:
-            return        
-        
-        nbins = self.nbins
-        
-        data_x = nbins*[0]
-        data_y = nbins*[0]
-        counts = nbins*[0]
-        length = len(image)
-        print "length x , y , image", len(x), len(y), length
-        
-        for i_x in range(length):
-            for i_y in range(length):
-                        
-                q = math.sqrt(x[i_x]*x[i_x] + y[i_y]*y[i_y])
-                if (q>self.inner_circle._inner_mouse_x \
-                    and q<self.outer_circle._inner_mouse_x) \
-                    or (q<self.inner_circle._inner_mouse_x \
-                    and q>self.outer_circle._inner_mouse_x):
-                            
-                    i_bin = int(math.ceil(nbins*(math.atan2(y[i_y], x[i_x])+math.pi)/(2.0*math.pi)) - 1)
-                    
-                    
-                    #data_y[i_bin] += math.exp(image[i_x][i_y])
-                    data_y[i_bin] += image[i_y][i_x]
-                    counts[i_bin] += 1.0
-                    
-        for i in range(nbins):
-            data_x[i] = (1.0*i+0.5)*2.0*math.pi/nbins
-            if counts[i]>0:
-                data_y[i] = data_y[i]/counts[i]
-        
-        return data_x, data_y
-
+    
     def save(self, ev):
         """
@@ -188,29 +154,16 @@
     def _post_data(self):
         # Compute data
-        data = self.base.get_corrected_data()
-        # If we have no data, just return
-        if data == None:
-            return
-
-        data_x, data_y = self.get_data(data, self.base.x, self.base.y)
-        
-        name = "Ring"
-        if hasattr(self.base, "name"):
-            name += " %s" % self.base.name
-        
-        wx.PostEvent(self.base.parent, AddPlotEvent(name=name,
-                                               x = data_x,
-                                               y = data_y,
-                                               qmin = self.inner_circle._inner_mouse_x,
-                                               qmax = self.outer_circle._inner_mouse_x,
-                                               yscale = 'log',
-                                               variable = 'ANGLE',
-                                               ylabel = "\\rm{Intensity} ",
-                                               yunits = "cm^{-1}",
-                                               xlabel = "\\rm{\phi}",
-                                               xunits = "rad",
-                                               parent = self.base.__class__.__name__))
-                                               
-        
+        data = self.base.data2D
+        from DataLoader.manipulations import  Boxavg
+        radius = math.sqrt(math.pow(self.qmax,2)+math.pow(self.qmax,2))
+        x_min= self.left_line.x 
+        x_max= self.right_line.x 
+        y_min= self.bottom_line.y
+        y_max= self.top_line.y
+        box =  Boxavg (x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max)
+       
+        self.count, self.error= box(self.base.data2D)
+                      
+                                       
     def moveend(self, ev):
         self.base.thaw_axes()
@@ -242,20 +195,25 @@
     def get_params(self):
         params = {}
-        #params["main_phi"] = self.right_line.get_radius()
-        #params["left_phi"] = self.left_line.get_radius()
-        
-        params["nbins"] = self.nbins
+        params["x_min"] = self.left_line.x 
+        params["x_max"] = self.right_line.x 
+        params["y_min"] = self.bottom_line.y
+        params["y_max"] = self.top_line.y
+        params["count"] = self.count
+        params["error"] = self.error
         return params
     
     def set_params(self, params):
         
-        main = params["main_phi"] 
-        left = params["left_phi"] 
+        x_min = params["x_min"] 
+        x_max = params["x_max"] 
+        y_min = params["y_min"]
+        y_max = params["y_max"] 
        
-        self.nbins = int(params["nbins"])
-        #self.main_line.set_cursor(inner, self.inner_circle._inner_mouse_y)
-        #self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y)
+        
+        self.left_line.update(ymin= y_min ,ymax= y_max)
+        self.right_line.update(ymin= y_min ,ymax= y_max)
+        self.top_line.update( xmin= x_min ,xmax= xmax)
+        self.bottom_line.update(xmin= xmin ,xmax= xmax)
         self._post_data()
-        
     def freeze_axes(self):
         self.base.freeze_axes()
