Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate multiple plots by clicking a single plot for more information using clickable python events

I am in the process of developing an application which can generate a 2nd plot by clicking data point in the 1st plot. I am using events to accomplish this.

Question:

  1. How to generate a 3rd plot by clicking a 2nd plot data point? Is it possible to accomplish to this?
  2. How to generate a simpler 3 layer synthetic data?

Code I have so far:

"""
compute the mean and stddev of 100 data sets and plot mean vs stddev.
When you click on one of the mu, sigma points, plot the raw data from
the dataset that generated the mean and stddev
"""
import numpy as np
import matplotlib.pyplot as plt

X = np.random.rand(100, 1000)
xs = np.mean(X, axis=1)
ys = np.std(X, axis=1)

fig = plt.figure()
ax = fig.add_subplot(211)
bx = fig.add_subplot(212)

# ax.set_title('click on point to plot time series')
# bx.set_title('click on point to plot time series')


line, = ax.plot(xs, ys, 'bs', picker=5)  # 5 points tolerance
line1, = bx.plot(xs, ys, 'bo', picker=5)  # 5 points tolerance

def onpick(event):

    if event.artist!=line: return True

    N = len(event.ind)
    if not N: return True


    figi = plt.figure()
    for subplotnum, dataind in enumerate(event.ind):

        ax = figi.add_subplot(N,1,subplotnum+1)
        ax.plot(X[dataind])
        ax.text(0.05, 0.9, 'mu=%1.3f\nsigma=%1.3f'%(xs[dataind], ys[dataind]),
                transform=ax.transAxes, va='top')
        ax.set_ylim(-0.5, 1.5)

        bx = figi.add_subplot(N,1,subplotnum+1)
        bx.plot(X[dataind])
        bx.text(0.05, 0.9, 'mu=%1.3f\nsigma=%1.3f'%(xs[dataind], ys[dataind]),
                transform=ax.transAxes, va='top')
        bx.set_ylim(-0.5, 1.5)

    figi.show()
    return True

fig.canvas.mpl_connect('pick_event', onpick)

plt.show()

1st plot

By clicking data points on the first plot, 2nd plot will be generated.

2nd plot

Now expectations are to generate a 3rd plot clicking the 2nd plot data point.

I have researched on this, but I am not successful :-( :-(

If my approach is wrong, please do suggest the any other alternative.

like image 690
Sandy Avatar asked Mar 13 '16 13:03

Sandy


People also ask

How do I plot multiple plots in one python?

Call matplotlib. pyplot. plot(x, y) with x and y set to arrays of data points to construct a plot. Calling this function multiple times on the same figure creates multiple plots in the same graph.


1 Answers

synthetic 3 level data

import matplotlib.pyplot as plt
import numpy as np
# data source
data_bucket = {}

# l1: randn
# l2: sum(l1)
# l3: sum(l2)


# generate some 3 layer synthetic data
N = 1000
l1_count = 50
l2_count = 50
l3_count = 2
x = np.arange(N)
for j in range(l3_count):
    l3 = []
    for k in range(l2_count):
        l2 = []
        for m in range(l1_count):
            l1 = data_bucket[(j, k, m)] = np.random.randn(N)
            l2.append(np.sum(l1))
        l2 = data_bucket[(j, k)] = np.asarray(l2)
        l3.append(np.sum(l2))
    data_bucket[(j, )] = np.asarary(l3)

The picker function

# only hase to close over the data
def picker(event):
    print(event.artist.get_gid())
    print(event.ind)
    # some function to generate next data key from gid + index
    k = event.artist.get_gid() + tuple(event.ind)
    try:
        next_data = data_bucket[k]
    except KeyError:
        print("no generations of data left")
        return
    # make the previous generation of plot
    fig, ax = plt.subplots()
    # can use the key here to dispatch to different plotting functions
    ax.plot(next_data, gid=k, picker=5, ls='-')
    fig.canvas.mpl_connect('pick_event', picker)

Initial plot

fig, ax = plt.subplots()

for k in range(l3_count):
    k = (k, )
    ax.plot(data_bucket[k], gid=k, picker=5, ls='', marker='o')
fig.canvas.mpl_connect('pick_event', picker)

The tricky part of this managing the mapping between the data in the 'current' figure and the next layer of data. All mpl artists have a gid attribute which can be used to uniquely identify them so here I use that + the index to generate keys into a dictionary which are tuples of integers of varying length. This was just the first thing that popped into my head when trying to make synthetic 3-layer data. In principle any keying system that uses the gid of the picked artist + the index in that line -> next layer of data will work.

You can then use the same picker function for all of your figures and it only needs to close over the data source. All of this could (should?) be rolled up into a single class.

like image 181
tacaswell Avatar answered Oct 04 '22 01:10

tacaswell