matplotlib - How to move a graph in a stack plot with the mouse in python -


problem

i want move single graph in stack plot mouse , update plot instantly. values shouldn't change in plot (graphical), list values should updated, can print them in file.

question

is possible implement in python matplotlib or recommend me else? implementation need in python. matplotlib recommended me, if it's not possible package or there better 1 please leave comment. when have code example feel free share it.

example

the x-axis represent time (from today future) , y-axis anmount of resources. isn't possible move graph past (left) when value cut of != 0. can move graph future (right), nothing get's cut. example can't move "o" left, can move "r" , "y" (only 1 time) left.

in example used lists 6 entries, imagine long enought.

values:

x-ax = [0, 1, 2, 3, 4, 5] y-ax = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]     r = [0, 1, 2, 1, 1, 1]    y = [0, 2, 1, 2, 1, 0]    o = [5, 2, 1, 1, 1, 1]  after moving y 1 right    r = [0, 1, 2, 1, 1, 1]    y = [0, 0, 2, 1, 2, 1]    o = [5, 2, 1, 1, 1, 1] 

example plot - move 1 graph

what have

i define figure , add subplot, use stackplot function plot data.

fig = plt.figure() ax1 = fig.add_subplot(111) stackplots = ax1.stackplot(x-ax, r, y, o) 

thanks "importanceofbeingernest"! added 3 events , connected them

cid_press = fig.canvas.mpl_connect('button_press_event', on_press) cid_release = fig.canvas.mpl_connect('button_release_event', on_release) cid_move = fig.canvas.mpl_connect('motion_notify_event', motion_notify)  def on_press(event): if(event.button == 1):     stack_p in stackplots:         contains, attrd = stack_p.contains(event)         if contains:             selected_stack = stack_p             break     if not contains:         return      # can change color, how can move it?     selected_stack .set_facecolors('black')     plt.draw()      print("clicked on", attrd, selected_stack)       #print('you pressed', event.button, event.xdata, event.ydata)  def on_release(event):     if (event.button == 1):         print('you released', event.button, event.xdata, event.ydata)  def motion_notify(event):     if (event.button == 1):         return         print('you moved', event.button, event.xdata, event.ydata) 

when click on graph changes it's color black. know i've got right one, want move it. "stackplot" method returns list of "polycollection". think should redo whole plot, need find out "polycollection" correspond array (r, y, o)...

thanks help!

i think problem needs separated 2 main parts. since moving 1 stack of stackplot not graphical movement, requires draw new stackplot changed data, 1 (a) first find way calculate new data , (b) provide way plot redone new data.

(a) move row along columns in data

we need way move 1 row inside array left or right, such output array may have 1 column more on side towards movement performed. done in following way:

import numpy np  class moveable():     def __init__(self, x,y):         self.x = x         self.y = y      def move(self, row, by):         if >0:             in range(by):                 self.moveright(row)                 self.sanitize()         else:             in range(-int(by)):                 self.moveleft(row)                 self.sanitize()      def moveright(self,row):         x = np.zeros(len(self.x)+1)         x[:len(self.x)] = self.x[:]         x[-1] = self.x[-1]+1         y = np.zeros((self.y.shape[0], len(self.x)+1))         y[:, :len(self.x)] = self.y[:,:]         y[row,0] = 0         y[row,1:] = self.y[row,:]         self.x=x         self.y=y      def moveleft(self,row):         x = np.zeros(len(self.x)+1)         x[1:len(self.x)+1] = self.x[:]         x[0] = self.x[0]-1         y = np.zeros((self.y.shape[0], len(self.x)+1))         y[:, 1:len(self.x)+1] = self.y[:,:]         y[row,-1] = 0         y[row,:-1] = self.y[row,:]         self.x=x         self.y=y      def sanitize(self):         if (self.y[:,0] == 0.).all():             self.x = self.x[1:]             self.y = self.y[:,1:]         if (self.y[:,-1] == 0.).all():             self.x = self.x[:-1]             self.y = self.y[:,:-1] 

the usage e.g. be

x = [0, 1, 2, 3, 4, 5]  r = [0, 1, 2, 1, 1, 1] y = [0, 2, 1, 2, 1, 0] o = [5, 2, 1, 1, 1, 1]  m= moveable(np.array(x), np.array([r, y, o])) m.move(row=2, by=1) print(m.x)  # prints [ 1.  2.  3.  4.  5.  6.] print(m.y)  # [[ 1.  2.  1.  1.  1.  0.]             #  [ 2.  1.  2.  1.  0.  0.]             #  [ 5.  2.  1.  1.  1.  1.]] # note 0 not part of x array more,  # have 6 new column on right side of matrix 

(b) new stackplot when mouse dragged

now can use above update axes new stackplot once mouse selects stack , moved amount left or right.

import matplotlib.pyplot plt  class stackmover():     def __init__(self, ax, x,y, **kw):         self.m = moveable(np.array(x), np.array(y))         self.xp = none         self.ax = ax         self.kw = kw         self.stackplot = self.ax.stackplot(self.m.x, self.m.y, **self.kw)         self.c1 = self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)         self.c2 = self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)      def on_press(self,event):         self.xp = none         if(event.button != 1): return         self.row = 0         stack_p in self.stackplot:             contains, attrd = stack_p.contains(event)             if contains:                 break             self.row += 1         if not contains:             return         self.xp = event.xdata       def on_release(self,event):         if(event.button != 1): return         if self.xp != none:             = int(event.xdata - self.xp)             self.m.move(self.row, by)             self.ax.clear()             self.stackplot = self.ax.stackplot(self.m.x, self.m.y, **self.kw)         self.ax.figure.canvas.draw_idle()         self.xp = none   x = [0, 1, 2, 3, 4, 5]  r = [0, 1, 2, 1, 1, 1] y = [0, 2, 1, 2, 1, 0] o = [5, 2, 1, 1, 1, 1]  fig, ax = plt.subplots() stackplots = stackmover(ax, x, [r, y, o])  plt.show() 

the result may this

enter image description here

i have neglected motion_notify_event here, need start , end point of mouse drag obtain stack update.


Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -