Rebin data and update imshow plot

565 views Asked by At

I have a large data set I want to be able to "zoom" in on.

What I really want is for the data to be rebinned based on the selection and then update the data in the graph. So the graph will show different limits but maintain the same resolution. Currently the imshow isn't getting updated. There must be something I'm missing or don't understand any insight would be appreciated.

Random data working example:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle

class Annotate(object):
  def __init__(self,x,y):
      self.ax = plt.gca()
      self.x = x
      self.y = y
      self.rect = Rectangle((0,0), 0, 0, facecolor='None', edgecolor='red')
      self.im = plt.imshow(np.zeros((150,150)))
      self.x0 = None
      self.y0 = None
      self.x1 = None
      self.y1 = None
      self.ax.add_patch(self.rect)
      self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
      self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
      self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
  def on_press(self, event):
      print ('press')
      self.is_pressed = True
      self.x0 = event.xdata
      self.y0 = event.ydata    
      self.x1 = event.xdata
      self.y1 = event.ydata
      self.rect.set_width(self.x1 - self.x0)
      self.rect.set_height(self.y1 - self.y0)
      self.rect.set_xy((self.x0, self.y0))
      #self.rect.set_linestyle('dashed')
      self.ax.figure.canvas.draw()
  def on_motion(self,event):
      if self.on_press is True:
          return
      self.x1 = event.xdata
      self.y1 = event.ydata
      self.rect.set_width(self.x1 - self.x0)
      self.rect.set_height(self.y1 - self.y0)
      self.rect.set_xy((self.x0, self.y0))
      #self.rect.set_linestyle('dashed')
      if self.is_pressed == True:
          self.ax.figure.canvas.draw()
  def on_release(self, event):
      print ('release')
      self.is_pressed= False
      self.x1 = event.xdata
      self.y1 = event.ydata
      self.rect.set_width(self.x1 - self.x0)
      self.rect.set_height(self.y1 - self.y0)
      self.rect.set_xy((self.x0, self.y0))
      self.rect.set_linestyle('solid')
      update_data(self)
      #self.ax.set_ylim( min(self.y0, self.y1), max(self.y0, self.y1))
      #self.ax.set_xlim( min(self.x0, self.x1), max(self.x0, self.x1))
      self.ax.figure.canvas.draw()
      print (self.x0,self.x1,self.y0,self.y1)
      return [self.x0,self.x1,self.y0,self.y1]


#x = np.random.randint(0,500, size=10000)
x= np.arange(10000)
y = np.random.randint(0,500, size=10000)

Z, xedges, yedges = np.histogram2d(x,y, bins=150)

def update_data(selection):
    ymin= min(selection.y0, selection.y1)
    ymax= max(selection.y0, selection.y1)
    xmin= min(selection.x0, selection.x1)
    xmax= max(selection.x0, selection.x1)
    low_index = np.argmax(selection.x>xmin)
    high_index = np.argmax(selection.y>xmax)
    Z, xedges, yedges = np.histogram2d(x[low_index:high_index],y, bins=150)
    selection.im.set_data(Z)
    selection.im.set_extent([xmin,xmax,ymin,ymax])
    plt.draw()

selection = Annotate(x,y)

selection.im=plt.imshow(Z, interpolation='none', extent=[0,500,0,500])
plt.colorbar()

plt.show()
1

There are 1 answers

5
Ed Smith On BEST ANSWER

You seem to be missing the limits on the y value in the histogram redraw in update_data. The high index and low index are also the wrong way around. The following looks more promising,

    Z, xedges, yedges = np.histogram2d(x[high_index:low_index],y[high_index:low_index], bins=150)

(although I'm not sure it's exactly what you want)

EDIT: The following appears to zoom and redraw.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle

class Annotate(object):
  def __init__(self,x,y):
      self.figure = plt.gcf()
      self.ax = plt.gca()
      self.x = x
      self.y = y
      self.rect = Rectangle((0,0), 0, 0, facecolor='None', edgecolor='red')
      self.im = plt.imshow(np.zeros((150,150)))
      self.x0 = None
      self.y0 = None
      self.x1 = None
      self.y1 = None
      self.is_pressed = False
      self.ax.add_patch(self.rect)
      self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
      self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
      self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
  def on_press(self, event):
      print ('press')
      self.is_pressed = True
      self.x0 = event.xdata
      self.y0 = event.ydata    
      self.x1 = event.xdata
      self.y1 = event.ydata
      self.rect.set_width(self.x1 - self.x0)
      self.rect.set_height(self.y1 - self.y0)
      self.rect.set_xy((self.x0, self.y0))
      #self.rect.set_linestyle('dashed')
      self.ax.figure.canvas.draw()
  def on_motion(self,event):
      if self.is_pressed is False:
          return
      self.x1 = event.xdata
      self.y1 = event.ydata
      #if type(self.x1) is float and type(self.y1) is float:
      self.rect.set_width(self.x1 - self.x0)
      self.rect.set_height(self.y1 - self.y0)
      self.rect.set_xy((self.x0, self.y0))
      #self.rect.set_linestyle('dashed')
      if self.is_pressed == True:
          self.ax.figure.canvas.draw()
  def on_release(self, event):
      print ('release')
      self.is_pressed= False
      self.x1 = event.xdata
      self.y1 = event.ydata
      self.rect.set_width(self.x1 - self.x0)
      self.rect.set_height(self.y1 - self.y0)
      self.rect.set_xy((self.x0, self.y0))
      self.rect.set_linestyle('solid')
      update_data(self)
      #self.ax.set_ylim( min(self.y0, self.y1), max(self.y0, self.y1))
      #self.ax.set_xlim( min(self.x0, self.x1), max(self.x0, self.x1))
      self.ax.figure.canvas.draw()

      print (self.x0,self.x1,self.y0,self.y1)
      return [self.x0,self.x1,self.y0,self.y1]


#x = np.random.randint(0,500, size=10000)
x = np.arange(5000)
y = np.random.randint(0,500, size=5000)

Z, xedges, yedges = np.histogram2d(x, y, bins=150, normed=True)

def update_data(selection):
    ymin= min(selection.y0, selection.y1)
    ymax= max(selection.y0, selection.y1)
    xmin= min(selection.x0, selection.x1)
    xmax= max(selection.x0, selection.x1)
    low_index = np.argmax(selection.x>xmin)
    high_index = np.argmax(selection.y>xmax)
    Z, xedges, yedges = np.histogram2d(x[high_index:low_index],y[high_index:low_index], bins=150, normed=True)

    selection.ax.figure.clf(keep_observers=True)
    selection.ax = selection.ax.figure.add_subplot(111)
    selection.im=plt.imshow(Z, interpolation='none', extent=[xmin, xmax, ymin, ymax])
    plt.colorbar(selection.im)


selection = Annotate(x,y)

selection.im=plt.imshow(Z, interpolation='none', extent=[y.min(), y.max(), y.min(), y.max()])
plt.colorbar(selection.im)

plt.show()