1

I am trying to produce an interactive graph in python's matplotlib. I have two sets of data, one is drawn as scatter plot and other is line plot. My minimal code is as follows.

import numpy as np
import matplotlib.pyplot as plt

model = np.array([(0.310, -0.687), (0.407, -0.355), (0.455, -0.142), (0.504, 0.061), (0.552, 0.238), 
                  (0.601,  0.380), (0.698,  0.549), (0.746,  0.581), (0.795, 0.587), (0.859, 0.567), 
                  (0.956,  0.511), (1.053,  0.473), (1.150,  0.489), (1.199, 0.523), (1.296, 0.640), 
                  (1.393,  0.812), (1.490,  0.981), (1.587,  1.189), (1.684, 1.386), (1.781, 1.572), 
                  (1.878, 1.766)])

obser = np.array([(0.212, -0.114), (0.199, 0.017), (0.259, 0.020), (0.199, 0.076), (0.297, 0.082), 
                  (0.735, 0.085), (0.641, 0.104), (0.791, 0.104), (0.681, 0.109), (0.606, 0.132), 
                  (0.262, 0.135), (0.813, 0.137), (0.334, 0.157), (0.565, 0.165), (0.647, 0.170), 
                  (0.876, 0.174), (0.746, 0.186), (0.509, 0.197), (0.398, 0.203), (0.693, 0.207), 
                  (0.829, 0.215), (0.299, 0.226), (0.585, 0.228), (0.549, 0.242), (0.430, 0.242), 
                  (0.637, 0.253), (0.511, 0.257), (0.918, 0.268), (0.813, 0.269), (0.746, 0.271), 
                  (0.336, 0.288), (0.449, 0.297), (0.398, 0.299), (0.783, 0.306), (0.578, 0.312), 
                  (0.871, 0.330), (0.515, 0.345), (0.468, 0.353), (0.818, 0.380), (0.936, 0.391), 
                  (0.889, 0.416), (0.876, 0.503), (1.027, 0.522), (1.040, 0.601), (0.965, 0.656), 
                  (1.130, 0.796), (1.224, 0.845), (1.261, 0.964), (1.378, 1.149)])

fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(9,6))
fig.subplots_adjust(wspace=0.5, hspace=0)

model2 = model - (0.37, 0.32)

ax1.invert_yaxis()
ax1.set_xlabel("BmV")
ax1.set_ylabel("UmB")
ax1.scatter(obser[:, 0], obser[:, 1], s=2, c="black")
ax1.plot(model[:, 0], model[:, 1], linewidth=1, c="red")
ax1.text(0.7, 0.96, 'Before', verticalalignment='top', horizontalalignment='left', 
    transform = ax1.transAxes, color = 'black', fontsize=12)

ax2.invert_yaxis()
ax2.set_xlabel("BmV")
ax2.set_ylabel("UmB")
ax2.scatter(obser[:, 0], obser[:, 1], s=2, c="black")
ax2.plot(model2[:, 0], model2[:, 1], linewidth=1, c="red")
ax2.text(0.8, 0.96, 'After', verticalalignment='top', horizontalalignment='left', 
    transform = ax2.transAxes, color = 'black', fontsize=12)

plt.show()

I want to drag and move the red line plot with mouse from "before" location to "after" location.

How can we do that?

Before and After case

3
  • Two examples from the matplotlib documentation. Commented Oct 17, 2019 at 12:15
  • I know these examples, you can only drag and move JUST ONE POINT at a time. I want to drag & move whole line at once, not points of it. Commented Oct 18, 2019 at 13:28
  • Yeah, sorry I don't have time to provide a full answer here. The point is, once you understood how those examples work, it will be easy to move just anything you want. Commented Oct 18, 2019 at 13:31

1 Answer 1

3

Here is my working example.

import numpy as np
import matplotlib.pyplot as plt

class MoveGraphLine(object):
    def __init__(self, ax, graf, obj, eubv):
        self.ax = ax
        self.figcanvas = self.ax.figure.canvas
        self.graf = graf
        self.obj = obj
        self.kayma = 0.0
        self.ebv, self.eub = eubv
        self.moved = None
        self.point = None
        self.pressed = False
        self.start = False

        self.figcanvas.mpl_connect('button_press_event', self.mouse_press)
        self.figcanvas.mpl_connect('button_release_event', self.mouse_release)
        self.figcanvas.mpl_connect('motion_notify_event', self.mouse_move)

    def mouse_release(self, event):
        if self.ax.get_navigate_mode()!= None: return
        if not event.inaxes: return
        if event.inaxes != self.ax: return
        if self.pressed: 
            self.pressed = False
            self.start = False
            self.point = None
            self.ebv -= self.kayma
            self.obj = self.moved
            return

    def mouse_press(self, event):
        if self.ax.get_navigate_mode()!= None: return
        if not event.inaxes: return
        if event.inaxes != self.ax: return
        if self.start: return
        self.point = event.xdata
        self.pressed = True

    def mouse_move(self, event):
        if self.ax.get_navigate_mode()!= None: return
        if not event.inaxes: return
        if event.inaxes != self.ax: return
        if not self.pressed: return
        self.start = True

        self.kayma = self.point - event.xdata
        keub = 0.72 * self.kayma + 0.025 * self.kayma**2
        self.moved = self.obj - [self.kayma, keub]
        mvdx, mvdy = self.moved[:, 0], self.moved[:, 1]

        self.graf.remove()
        self.graf, = self.ax.plot(mvdx, mvdy, linewidth=1.1, c="b")

        self.figcanvas.draw()


model = np.array([(0.310, -0.687), (0.407, -0.355), (0.455, -0.142), (0.504, 0.061), (0.552, 0.238), 
                  (0.601,  0.380), (0.698,  0.549), (0.746,  0.581), (0.795, 0.587), (0.859, 0.567), 
                  (0.956,  0.511), (1.053,  0.473), (1.150,  0.489), (1.199, 0.523), (1.296, 0.640), 
                  (1.393,  0.812), (1.490,  0.981), (1.587,  1.189), (1.684, 1.386), (1.781, 1.572), 
                  (1.878, 1.766)])

obser = np.array([(0.212, -0.114), (0.199, 0.017), (0.259, 0.020), (0.199, 0.076), (0.297, 0.082), 
                  (0.735, 0.085), (0.641, 0.104), (0.791, 0.104), (0.681, 0.109), (0.606, 0.132), 
                  (0.262, 0.135), (0.813, 0.137), (0.334, 0.157), (0.565, 0.165), (0.647, 0.170), 
                  (0.876, 0.174), (0.746, 0.186), (0.509, 0.197), (0.398, 0.203), (0.693, 0.207), 
                  (0.829, 0.215), (0.299, 0.226), (0.585, 0.228), (0.549, 0.242), (0.430, 0.242), 
                  (0.637, 0.253), (0.511, 0.257), (0.918, 0.268), (0.813, 0.269), (0.746, 0.271), 
                  (0.336, 0.288), (0.449, 0.297), (0.398, 0.299), (0.783, 0.306), (0.578, 0.312), 
                  (0.871, 0.330), (0.515, 0.345), (0.468, 0.353), (0.818, 0.380), (0.936, 0.391), 
                  (0.889, 0.416), (0.876, 0.503), (1.027, 0.522), (1.040, 0.601), (0.965, 0.656), 
                  (1.130, 0.796), (1.224, 0.845), (1.261, 0.964), (1.378, 1.149)])


obv, oub =obser[:, 0], obser[:, 1]

fig, ax1 = plt.subplots(nrows=1, ncols=1, figsize=(5.31,6.79))
fig.subplots_adjust(left=0.14, bottom=0.08, right=0.95, top=0.97, wspace=0, hspace=0)

shift = (model.mean(axis=0) - obser.mean(axis=0))
sebv = shift[0]
seub = 0.72 * sebv + 0.025 * sebv**2

ax1.invert_yaxis()
ax1.set_xlabel("BmV")
ax1.set_ylabel("UmB")
ax1.set_ylim(2, -1)
ax1.set_xlim(-0.5, 2)
ax1.scatter(obv, oub, s=2, c="k")
gmdl, = ax1.plot(model[:, 0], model[:, 1], linewidth=1.1, c="b")

moveline = MoveGraphLine(ax1, gmdl, model, (sebv, seub))

plt.show()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.