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