diff -urN matplotlib/examples/two_scales.py matplotlib-twin/examples/two_scales.py
--- matplotlib/examples/two_scales.py	2004-12-09 17:00:38.000000000 +0100
+++ matplotlib-twin/examples/two_scales.py	2005-01-23 19:15:04.000000000 +0100
@@ -22,16 +22,14 @@
 t = arange(0.0, 10.0, 0.01)
 s1 = exp(t)
 plot(t, s1, 'b-')
-ax1.yaxis.tick_left()
+xlabel('time (s)')
+ylabel('exp')
 
 
 # turn off the 2nd axes rectangle with frameon kwarg
-ax2 = subplot(111, frameon=False) 
+ax2 = twin() 
 s2 = sin(2*pi*t)
 plot(t, s2, 'r.')
-ax2.yaxis.tick_right()
-
-
-xlabel('time (s)')
+ylabel('sin')
 
 show()
diff -urN matplotlib/lib/matplotlib/axes.py matplotlib-twin/lib/matplotlib/axes.py
--- matplotlib/lib/matplotlib/axes.py	2004-12-30 18:50:53.000000000 +0100
+++ matplotlib-twin/lib/matplotlib/axes.py	2005-01-23 19:44:47.000000000 +0100
@@ -285,7 +285,14 @@
                 remaining=remaining[2:]
             #yield self._plot_2_args(remaining[:2])
             #remaining=args[2:]
-        
+
+BinOpType=type(zero())
+def makeValue(v):
+    if type(v) == BinOpType:
+        return v
+    else:
+        return Value(v)
+
 
 
 class Axes(Artist):
@@ -305,7 +312,7 @@
                  axisbg = None, # defaults to rc axes.facecolor
                  frameon = True):
         Artist.__init__(self)
-        self._position = [Value(val) for val in rect]
+        self._position = map(makeValue, rect)
         self.set_figure(fig)
 
         if axisbg is None: axisbg = rcParams['axes.facecolor']
@@ -3574,3 +3581,45 @@
         SubplotBase.__init__(self, *args)        
         PolarAxes.__init__(self, fig, [self.figLeft, self.figBottom, self.figW, self.figH], **kwargs)
 
+class TwinAxes(Axes):
+    """
+    Create an Axes instance that shares the X axis with another:
+
+      TwinAxes(existing_axes)
+    """
+    def __init__(self, axes):
+        Axes.__init__(self, axes.figure, axes._position, frameon=False)
+        
+        self._xscale=axes._xscale
+        self.fmt_xdata=axes.fmt_xdata
+
+        vl_left=axes.viewLim.ll().x()
+        vl_right=axes.viewLim.ur().x()
+        vl_bottom=self.viewLim.ll().y()
+        vl_top=self.viewLim.ur().y()
+        self.viewLim=Bbox(Point(vl_left,vl_bottom),Point(vl_right, vl_top))
+
+        dl_left=axes.dataLim.ll().x()
+        dl_right=axes.dataLim.ur().x()
+        dl_bottom=self.dataLim.ll().y()
+        dl_top=self.dataLim.ur().y()
+        self.dataLim=Bbox(Point(dl_left,dl_bottom),Point(dl_right, dl_top))
+
+        try:
+            self.transData = blend_xy_sep_transform(axes.transData, self.transData)
+        except RuntimeError:
+            raise RuntimeError, "TwinAxes only works with cartesian axes"
+
+        self.xaxis=axes.xaxis
+        
+        self.yaxis.tick_right()
+        self.yaxis.set_label_position('right')
+        axes.yaxis.tick_left()
+
+    def set_figure(self, fig):
+        if self.figure is None:
+            Axes.set_figure(self, fig)
+            return None
+        if fig is not self.figure:
+            raise RuntimeError, "TwinAxes can only be added to the same figure"
+
diff -urN matplotlib/lib/matplotlib/axis.py matplotlib-twin/lib/matplotlib/axis.py
--- matplotlib/lib/matplotlib/axis.py	2004-12-30 04:52:57.000000000 +0100
+++ matplotlib-twin/lib/matplotlib/axis.py	2005-01-23 19:45:07.000000000 +0100
@@ -473,6 +473,7 @@
         if not self.get_visible(): return 
         renderer.open_group(__name__)
         ticklabelBoxes = []
+        ticklabelBoxes2 = []
         
         majorTicks = self.get_major_ticks()
         majorLocs = self._majorLocator()
@@ -491,8 +492,12 @@
             tick.set_label1(label)
             tick.set_label2(label)            
             tick.draw(renderer)
-            extent = tick.label1.get_window_extent(renderer) 
-            ticklabelBoxes.append(extent)
+            if tick.label1On:
+                extent = tick.label1.get_window_extent(renderer) 
+                ticklabelBoxes.append(extent)
+            if tick.label2On:
+                extent = tick.label2.get_window_extent(renderer) 
+                ticklabelBoxes2.append(extent)
 
         minorTicks = self.get_minor_ticks()
         minorLocs = self._minorLocator()
@@ -508,8 +513,12 @@
             tick.set_label(label)
 
             tick.draw(renderer)  
-            extent = tick.label1.get_window_extent(renderer) 
-            ticklabelBoxes.append(extent)
+            if tick.label1On:
+                extent = tick.label1.get_window_extent(renderer) 
+                ticklabelBoxes.append(extent)
+            if tick.label2On:
+                extent = tick.label2.get_window_extent(renderer) 
+                ticklabelBoxes2.append(extent)
 
 
 
@@ -519,7 +528,7 @@
         # the actual bbox
 
 
-        self._update_label_postion(ticklabelBoxes)
+        self._update_label_postion(ticklabelBoxes, ticklabelBoxes2)
 
         self.label.draw(renderer)  # memory leak here, vertical text
 
@@ -750,25 +759,54 @@
                                                      identity_transform() ))
 
         self._set_artist_props(label)
+        self.label_position='bottom'
         return label
 
+    def get_label_position(self):
+        """
+Return the label position (top or bottom)
+        """
+        return self.label_position
 
-    def _update_label_postion(self, bboxes):
+    def set_label_position(self, position):
+        """
+Set the label position (top or bottom)
+
+ACCEPTS: [ 'top' | 'bottom' ]
+        """
+        assert position == 'top' or position == 'bottom'
+        if position == 'top':
+            self.label.set_verticalalignment('bottom')
+        else:
+            self.label.set_verticalalignment('top')
+        self.label_position=position
+
+    def _update_label_postion(self, bboxes, bboxes2):
         """
         Update the label position based on the sequence of bounding
         boxes of all the ticklabels 
         """
 
         x,y = self.label.get_position()
-        if not len(bboxes):
-            bottom = self.axes.bbox.ymin()
+        if self.label_position == 'bottom':
+            if not len(bboxes):
+                bottom = self.axes.bbox.ymin()
+            else:
+
+                bbox = bbox_all(bboxes)
+                bottom = bbox.ymin()
+            
+            self.label.set_position( (x, bottom-self.LABELPAD*self.figure.dpi.get()/72.0))
+
         else:
+            if not len(bboxes2):
+                top = self.axes.bbox.ymax()
+            else:
 
-            bbox = bbox_all(bboxes)
-            bottom = bbox.ymin()
+                bbox = bbox_all(bboxes2)
+                top = bbox.ymax()
             
-        self.label.set_position( (x, bottom-self.LABELPAD*self.figure.dpi.get()/72.0))
-        
+            self.label.set_position( (x, top+self.LABELPAD*self.figure.dpi.get()/72.0))
 
     def tick_top(self):
         'use ticks only on top'
@@ -822,24 +860,54 @@
                                                      self.axes.transAxes) )
 
         self._set_artist_props(label)
+        self.label_position='left'
         return label
 
-    def _update_label_postion(self, bboxes):
+    def get_label_position(self):
+        """
+Return the label position (left or right)
+        """
+        return self.label_position
+
+    def set_label_position(self, position):
+        """
+Set the label position (left or right)
+
+ACCEPTS: [ 'left' | 'right' ]
+        """
+        assert position == 'left' or position == 'right'
+        if position == 'right':
+            self.label.set_horizontalalignment('left')
+        else:
+            self.label.set_horizontalalignment('right')
+        self.label_position=position
+
+    def _update_label_postion(self, bboxes, bboxes2):
         """
         Update the label position based on the sequence of bounding
-        boxes overlaps of all the ticklabels that overlap the current
-        ticklabel.  overlaps are the bounding boxes of the ticklabels
+        boxes of all the ticklabels 
         """
 
         x,y = self.label.get_position()
-        if not len(bboxes):
-            left = self.axes.bbox.xmin()
-        else:
-            bbox = bbox_all(bboxes)
-            left = bbox.xmin()
-        self.label.set_position((left - self.figure.dpi.get()*self.LABELPAD/72.0,y))
+        if self.label_position == 'left':
+            if not len(bboxes):
+                left = self.axes.bbox.xmin()
+            else:
+
+                bbox = bbox_all(bboxes)
+                left = bbox.xmin()
+            
+            self.label.set_position( (left-self.LABELPAD*self.figure.dpi.get()/72.0, y))
 
+        else:
+            if not len(bboxes2):
+                right = self.axes.bbox.xmax()
+            else:
 
+                bbox = bbox_all(bboxes2)
+                right = bbox.xmax()
+            
+            self.label.set_position( (right+self.LABELPAD*self.figure.dpi.get()/72.0, y))
 
     def tick_right(self):
         'use ticks only on right'
diff -urN matplotlib/lib/matplotlib/pylab.py matplotlib-twin/lib/matplotlib/pylab.py
--- matplotlib/lib/matplotlib/pylab.py	2005-01-23 19:46:00.000000000 +0100
+++ matplotlib-twin/lib/matplotlib/pylab.py	2005-01-14 00:03:36.000000000 +0100
@@ -191,7 +191,7 @@
 import _pylab_helpers
 import mlab  #so I can override hist, psd, etc...
 
-from axes import Axes, PolarAxes
+from axes import Axes, PolarAxes, TwinAxes
 from backends import new_figure_manager, error_msg, \
      draw_if_interactive, show
 
@@ -1160,6 +1160,16 @@
     return a
 
 
+def twin(axes=None):
+    if axes is None:
+        axes=gca()
+
+    tw=TwinAxes(axes)
+    gcf().add_axes(tw)
+    draw_if_interactive()
+    return tw
+
+
 def title(s, *args, **kwargs):
     """
     Set the title of the current axis to s
