0

I am using Multicursor to get a cursor on every graph. I want to show the value of the datapoint, which is hit by the cursor, inside a legend during hovering over the graphs, like thisenter image description here

Actually I have thought that this is a standard feature of matplotlib respectively Multicursor, but it seems not. Did someone already something like this or do I have to implement it by my own.

I already found this post matplotlib multiple values under cursor, but this could be just the beginning for the implementation I want.

1 Answers1

1

I have developed a solution.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import MultiCursor
from bisect import bisect_left


fig = plt.figure(figsize=(15, 8))

# create random graph with 60 datapoints, 0 till 59
x = list(range(0,60))

axes_list = [] 

def createRandomGraph(ax,x):
    y = np.random.randint(low=0, high=15, size=60)
    data.append(y)
    ax.plot(x,y, marker='.')


def take_closest(myList, myNumber):
    """
    Assumes myList is sorted. Returns closest value to myNumber.

    If two numbers are equally close, return the smallest number.
    """
    pos = bisect_left(myList, myNumber)
    if pos == 0:
        return myList[0]
    if pos == len(myList):
        return myList[-1]
    before = myList[pos - 1]
    after = myList[pos]
    if after - myNumber < myNumber - before:
       return after, pos
    else:
       return before, pos-1



def show_Legend(event): 
    #get mouse coordinates
    mouseXdata = event.xdata    

    # the value of the closest data point to the current mouse position shall be shown
    closestXValue, posClosestXvalue = take_closest(data[0], mouseXdata)

    i = 1
    for ax in axes_list:
        datalegend = ax.text(1.05, 0.5, data[i][posClosestXvalue],  fontsize=7,
                                      verticalalignment='top', bbox=props, transform=ax.transAxes)               
        ax.draw_artist(datalegend) 

        # this remove is required because otherwise after a resizing of the window there is 
        # an artifact of the last label, which lies behind the new one
        datalegend.remove()
        i +=1

    fig.canvas.update()


# store the x value of the graph in the first element of the list
data = [x]

# properties of the legend labels
props = dict(boxstyle='round', edgecolor='black', facecolor='wheat', alpha=1.5)

for i in range(5):
    if(i>0):        
        # all plots share the same x axes, thus during zooming and panning 
        # we will see always the same x section of each graph
        ax = plt.subplot(5, 1, i+1, sharex=ax)             
    else:
        ax = plt.subplot(5, 1, i+1)        

    axes_list.append(ax)    
    createRandomGraph(ax,x)  

multi = MultiCursor(fig.canvas, axes_list, color='r', lw=1)   

# function show_Legend is called while hovering over the graphs 
fig.canvas.mpl_connect('motion_notify_event', show_Legend)

plt.show()

The output looks like this

enter image description here

Maybe you like it and find it useful