Index: guitools/PlotPanel.py
===================================================================
--- guitools/PlotPanel.py	(revision 2bf92f2eb410d943f4de97881e7615508e97dcb9)
+++ guitools/PlotPanel.py	(revision 057210c6ea19572fef82f93aab447415c671aaa2)
@@ -10,4 +10,5 @@
 from canvas import FigureCanvas
 #TODO: make the plottables interactive
+from plottables import Graph
 
 def show_tree(obj,d=0):
@@ -46,5 +47,6 @@
         self.SetSizer(sizer)
 
-
+        # Graph object to manage the plottables
+        self.graph = Graph()
         
         self.Bind(wx.EVT_CONTEXT_MENU, self.onContextMenu)
Index: guitools/plottables.py
===================================================================
--- guitools/plottables.py	(revision 2bf92f2eb410d943f4de97881e7615508e97dcb9)
+++ guitools/plottables.py	(revision 057210c6ea19572fef82f93aab447415c671aaa2)
@@ -123,9 +123,9 @@
         """Properties of the y axis.
         """
-        if self.prop["xunit"] and units != self.prop["xunit"]:
+        if self.prop["yunit"] and units != self.prop["yunit"]:
             pass
             #print "Plottable: how do we handle non-commensurate units"
         self.prop["ylabel"] = "%s (%s)"%(name,units)
-        self.prop["xunit"] = units
+        self.prop["yunit"] = units
         
     def title(self,name):
@@ -348,5 +348,63 @@
         """Return the number of colors need to render the object"""
         return 1
-
+    
+    class View:
+        """
+            Representation of the data that might include a transformation
+        """
+        x = None
+        y = None
+        dx = None
+        dy = None
+        
+        def __init__(self, x=None, y=None, dx=None, dy=None):
+            self.x = x
+            self.y = y
+            self.dx = dx
+            self.dy = dy
+            
+        def transform_x(self, func, errfunc, x, dx):
+            """
+                Transforms the x and dx vectors and stores the output.
+                
+                @param func: function to apply to the data
+                @param x: array of x values
+                @param dx: array of error values
+                @param errfunc: function to apply to errors
+            """
+            import copy
+            # Sanity check
+            if dx and not len(x)==len(dx):
+                raise ValueError, "Plottable.View: Given x and dx are not of the same length"
+            
+            self.x  = deepcopy(x)
+            self.dx = deepcopy(dx)
+            
+            for i in range(len(x)):
+                 self.x[i] = func(x[i])
+                 self.dx[i] = errfunc(dx[i])
+                      
+        def transform_y(self, func, errfunc, y, dy):
+            """
+                Transforms the x and dx vectors and stores the output.
+                
+                @param func: function to apply to the data
+                @param y: array of y values
+                @param dy: array of error values
+                @param errfunc: function to apply to errors
+            """
+            import copy
+            # Sanity check
+            if dy and not len(y)==len(dy):
+                raise ValueError, "Plottable.View: Given y and dy are not of the same length"
+            
+            self.y  = deepcopy(y)
+            self.dy = deepcopy(dy)
+            
+            for i in range(len(y)):
+                 self.y[i] = func(y[i])
+                 self.dy[i] = errfunc(dy[i])
+                      
+        
 
 class Data1D(Plottable):
@@ -362,16 +420,26 @@
         The label, if it is different, appears on the status bar.
         """
+        self.name = "data"
         self.x = x
         self.y = y
         self.dx = dx
         self.dy = dy
+        
+        self.view = self.View(self.x, self.y, self.dx, self.dy)
 
     def render(self,plot,**kw):
-        Plottable.render(self,plot)
-        plot.points(self.x,self.y,dx=self.dx,dy=self.dy,**kw)
+        plot.points(self.view.x,self.view.y,dx=self.view.dx,dy=self.view.dy,**kw)
 
     def changed(self):
         return False
 
+    @classmethod
+    def labels(cls, collection):
+        """Build a label mostly unique within a collection"""
+        map = {}
+        for item in collection:
+            #map[item] = label(item, collection)
+            map[item] = r"$\rm{%s}$" % item.name
+        return map
     
 class Theory1D(Plottable):
Index: guitools/test_panel.py
===================================================================
--- guitools/test_panel.py	(revision 057210c6ea19572fef82f93aab447415c671aaa2)
+++ guitools/test_panel.py	(revision 057210c6ea19572fef82f93aab447415c671aaa2)
@@ -0,0 +1,114 @@
+import wx
+from PlotPanel import PlotPanel
+from plottables import Plottable, Graph, Data1D
+import  sys
+import numpy
+import pylab
+
+
+class ViewerFrame(wx.Frame):
+    """
+        Add comment
+    """
+    def __init__(self, parent, id, title):
+        """
+            comment
+            @param parent: parent panel/container
+        """
+        # Initialize the Frame object
+        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(950,850))
+        
+        # Panel for 1D plot
+        self.plotpanel    = PlotPanel(self, -1, style=wx.RAISED_BORDER)
+
+        x  = pylab.arange(0, 25, 1)
+        dx = numpy.zeros(len(x))
+        y  = x/2.0
+        dy = y*0.1
+
+        self.data = Data1D(x=x, y=y, dx=None, dy=dy)
+
+        # Graph        
+        self.graph = Graph()
+        self.graph.xaxis('\\rm{q} ', 'A^{-1}')
+        self.graph.yaxis("\\rm{Intensity} ","cm^{-1}")
+        self.graph.add(self.data)
+        self.graph.render(self.plotpanel)
+
+        # Set up the menu
+        self._setup_menus()
+      
+        # Set up the layout
+        self._setup_layout()
+                
+        # Register the close event so it calls our own method
+        wx.EVT_CLOSE(self, self._onClose)
+        
+       
+    def _setup_layout(self):
+        """
+            Set up the layout
+        """
+        # Status bar
+        self.sb = self.CreateStatusBar()
+        self.SetStatusText("This is a data viewer")
+        
+        # Two columns of panels
+        sizer = wx.GridBagSizer(0,0)
+        
+        sizer.Add(self.plotpanel, (0,0), (1,1),   flag=wx.EXPAND | wx.ALL, border=0)
+        sizer.AddGrowableRow(0)
+        sizer.AddGrowableCol(0)
+   
+        self.SetSizer(sizer)
+        self.Centre()
+        
+        
+                
+    def _setup_menus(self):
+        """
+            Set up the application menus
+        """
+        
+        # Menu
+        menubar = wx.MenuBar()
+        # File menu
+        filemenu = wx.Menu()
+        filemenu.Append(101,'&Quit', 'Exit')
+ 
+        # Add sub menus
+        menubar.Append(filemenu, '&File')
+         
+        self.SetMenuBar(menubar)
+        
+        # Bind handlers
+        wx.EVT_MENU(self, 101, self.Close)
+               
+    def _onClose(self, event):
+        """
+        """
+        wx.Exit()
+        sys.exit()
+                   
+    def Close(self, event=None):
+        """
+            Quit the application
+        """
+        wx.Frame.Close(self)
+        wx.Exit()
+        sys.exit()
+   
+  
+class ViewApp(wx.App):
+    def OnInit(self):
+        frame = ViewerFrame(None, -1, 'testView')    
+        frame.Show(True)
+        self.SetTopWindow(frame)
+        
+        return True
+        
+
+if __name__ == "__main__": 
+    app = ViewApp(0)
+    app.MainLoop()        
+            
