Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

matplotlib interactive graphing (manually drawing lines on a graph)

I have succesfully plotted a set of date sequenced data (X axis is date) using matplotlib. However, I want to be able to manually draw lines from one (date1, y1) to another (date2, y2) on the plotted graph.

I can't seem to find any examples that show how to do this - or indeed if it is even posible.

To summarize, this is what I want to do:

  1. Draw a set of lines on the plotted graph
  2. Save the manually drawn line data to file
  3. Load the manually drawn line data from file (to recreate the graph)
  4. Ideally, I would like to store 'meta data' about the drawn lines (e.g. color, line-width etc)

Can someone post a skeleton snippet (preferably with links to further info), to show how I may get started with implementing this (the main requirements being the ability to manually draw lines on a graph and then to save/load the lines into a plot).

Note: By 'manually', I mean to be able to draw the lines by clicking on a point, and then clicking on another point in the plotted graph. to draw a line between the two points (or simply clicking on a point and dragging and releasing the mouse at another point on the plotted graph)

[[Update]]

dawe, thanks very much for the snippet you provided. This allows me to do what I am trying to do - however, as soon as the line is drawn on the canvas (after the second mouse click), the GUI crashes and I get this warning message on the console:

/usr/local/lib/python2.6/dist-packages/matplotlib/backend_bases.py:2192: DeprecationWarning: Using default event loop until function specific to this GUI is implemented
  warnings.warn(str,DeprecationWarning)

Do you know what is causing this warning and the abrupt program termination?

Also, is it possible to draw more than one line on the graph? (I'm guessing this will involve writing some kind of event handler that will instantiate a linedrawer variable). At the moment , I get the chance to draw only one line before the 'app' abruptly terminates.

like image 266
Homunculus Reticulli Avatar asked Feb 03 '12 23:02

Homunculus Reticulli


1 Answers

I would write something like this:

import matplotlib.pyplot as plt
class LineDrawer(object):
    lines = []
    def draw_line(self):
        ax = plt.gca()
        xy = plt.ginput(2)

        x = [p[0] for p in xy]
        y = [p[1] for p in xy]
        line = plt.plot(x,y)
        ax.figure.canvas.draw()

        self.lines.append(line)

Using ginput() you can avoid more complicated event handling. The way it 'works' is you plot something:

plt.plot([1,2,3,4,5])
ld = LineDrawer()
ld.draw_line() # here you click on the plot

For saving/loading the line data to a file you can easily implement a method using pickle or shelve. You can also pass the necessary metadata by the method draw_line()

like image 156
dawe Avatar answered Sep 25 '22 08:09

dawe