Shared axis question, with possible answer (long)

Dear John,

Some weeks ago we wrote about the 'sharex' feature. At that occasion, our
talk resulted in two suggestions about the 'freeze' button. Your suggestion was
to give the decision to the user, which should press the X/Y key if desired.
My suggestion was to make in 'automagically', detecting if all X (or Y) are
shared and adapting the zoom rectangle according to this preliminary test.

I made a change in the 'release_zoom' function in the in the 'backend_bases.py'
file. The comments in the 'verbose' fashion to make my suggestion clearer.

    def my_release_zoom(self, event):
        'the release mouse button callback in zoom to rect mode'
        if self._xypress is None: return
        x, y = event.x, event.y

        lastx, lasty, a, ind, lim, trans = self._xypress
        # ignore singular clicks - 5 pixels is a threshold
        if abs(x-lastx)<5 or abs(y-lasty)<5:
            self._xypress = None
            self.release(event)
            self.draw()
            return

        xmin, ymin, xmax, ymax = lim

        # zoom to rect
        lastx, lasty = a.transData.inverse_xy_tup( (lastx, lasty) )
        x, y = a.transData.inverse_xy_tup( (x, y) )
        Xmin,Xmax=a.get_xlim()
        Ymin,Ymax=a.get_ylim()

···

###########################################################################
  # Changes start here ###########################################################################

        def check_shared_x_axes(): # check if all axes have sharedx subplot_structure = self.canvas.figure.gca() # get subplot_structure (rows, cols) N=subplot_structure.rowNum+1 # get subplot rows
            axes_list = self.canvas.figure.get_axes() # get the axes list sharedx_list=list() # create an empty sharedx_list

            if (N>1): # checking is made only if rows>1
                for i in range(N): # check all row subplot axes
                    if axes_list[i]._sharex is None: # check if this an independent X axes
                        axes_reference = axes_list[i] # establish axes_reference
                        sharedx_list.append(axes_list[i]) # append this axes to sharedx_list
                    else: # since this is not an independent X axes sharedx_list.append(axes_list[i]._sharex) # append the _sharex axes to sharedx_list
                if (N==sharedx_list.count(axes_reference)): # check if all axes are included in sharedx_list
                    return True # axes have shared_x
                else:
                    return False # axes don't have shared_x
            else:
                return False # returns False if rows == 1

        def check_shared_y_axes(): # check if all axes have sharedy subplot_structure = self.canvas.figure.gca() # get subplot_structure (rows, cols) M=subplot_structure.rowNum+1 # get subplot rows
            axes_list = self.canvas.figure.get_axes() # get the axes list sharedy_list=list() # create an empty sharedy_list

            if (M>1): # checking is made only if cols>1
                for i in range(M): # check all column subplot axes
                    if axes_list[i]._sharey is None: # check if this an independent Y axes
                        axes_reference = axes_list[i] # establish axes_reference
                        sharedy_list.append(axes_list[i]) # append this axes to sharedy_list
                    else: # since this is not an independent Y axes sharedy_list.append(axes_list[i]._sharey) # append the _sharey axes to sharedy_list
                if (M==sharedy_list.count(axes_reference)): # check if all axes are included in sharedy_list
                    return True # axes have shared_x
                else:
                    return False # axes don't have shared_x
            else:
                return False # returns False if cols == 1

        shared_x_flag = check_shared_x_axes() # create shared_x_flag shared_y_flag = check_shared_y_axes() # create shared_y_flag

        # A particular situation must be checked: "what if both x and y axes ared shared?"
        # In order to avoid disabling the zoom, my decision (arbitrary) was not to 'freeze'
        # any axes. Other possible choice would freeze only Y axes.

        if shared_x_flag and shared_y_flag:
            shared_x_flag = False
            shared_y_flag = False

        # print shared_x_flag, shared_y_flag
                if shared_y_flag: # all Y axis are shared: freeze X axis
            xmin, xmax = a.get_xlim()
        else: # don't freeze X axis,
                                         # zoom acts on both directions if Xmin < Xmax:
                if x<lastx: xmin, xmax = x, lastx
                else: xmin, xmax = lastx, x
                if xmin < Xmin: xmin=Xmin
                if xmax > Xmax: xmax=Xmax
            else:
                if x>lastx: xmin, xmax = x, lastx
                else: xmin, xmax = lastx, x
                if xmin > Xmin: xmin=Xmin
                if xmax < Xmax: xmax=Xmax

        if shared_x_flag: # all X axis are shared: freeze Y axis ymin, ymax = a.get_ylim()
        else: # don't freeze Y axis,
                                         # zoom acts on both directions
            if Ymin < Ymax:
                if y<lasty: ymin, ymax = y, lasty
                else: ymin, ymax = lasty, y
                if ymin < Ymin: ymin=Ymin
                if ymax > Ymax: ymax=Ymax
            else:
                if y>lasty: ymin, ymax = y, lasty
                else: ymin, ymax = lasty, y
                if ymin > Ymin: ymin=Ymin
                if ymax < Ymax: ymax=Ymax

  ##########################################################################
  # Changes finish here ##########################################################################

        if self._button_pressed == 1:
            a.set_xlim((xmin, xmax))
            a.set_ylim((ymin, ymax))
        elif self._button_pressed == 3:
            if a.get_xscale()=='log':
                alpha=log(Xmax/Xmin)/log(xmax/xmin)
                x1=pow(Xmin/xmin,alpha)*Xmin
                x2=pow(Xmax/xmin,alpha)*Xmin
            else:
                alpha=(Xmax-Xmin)/(xmax-xmin)
                x1=alpha*(Xmin-xmin)+Xmin
                x2=alpha*(Xmax-xmin)+Xmin
            if a.get_yscale()=='log':
                alpha=log(Ymax/Ymin)/log(ymax/ymin)
                y1=pow(Ymin/ymin,alpha)*Ymin
                y2=pow(Ymax/ymin,alpha)*Ymin
            else:
                alpha=(Ymax-Ymin)/(ymax-ymin)
                y1=alpha*(Ymin-ymin)+Ymin
                y2=alpha*(Ymax-ymin)+Ymin
            a.set_xlim((x1, x2))
            a.set_ylim((y1, y2))

        if a.get_aspect() == 'equal': a.set_aspect('equal',True)
        self.draw()
        self._xypress = None
        self._button_pressed == None

        self.push_current()
        self.release(event)

Clovis