0

I have a simple sine wave plot and a program (with a few modes) to pick the peaks of the sine wave line. I have another mode to delete peaks I've picked/plotted in case a mistake was made. However I'm having some trouble with separating which artist is to be deleted.

I would like to be able to label the sine wave line and the picked points so I can later remove the peak points I picked/plotted and keep the sine wave on the figure. I made this code below. Sorry it may look over complicated, I'm just trying to keep the layout/features of my program.

#! /usr/bin/python

import sys
import matplotlib.pyplot as plt
import numpy as np


class MyClick(object):
    def __init__(self):
        # initialize mode
        self._mode = 1 

        self.peak = []

    def press(self, event):
        """record last key pressed"""
        sys.stdout.flush()
        if event.key == '1':   
            self._mode = 1 
            print('Peak Mode')

        elif event.key == '4':
            self._mode = 4
            print('Delete Mode')

    def pick(self,event):
        mouseevent = event.mouseevent
        artist = event.artist
        x, y = np.array(artist.get_xdata()), np.array(artist.get_ydata())#used numpy array for argsort feature
        ind = event.ind

        #remove = [artist for artist in self.peak if artist.get_xy ]

        if self._mode == 1:
            # peak
            peakind = y[ind].argsort()[-1:] #argsort to find peak
            self.peak.append(zip(x[ind[peakind]], y[ind[peakind]])) #save peak
            ax.plot(x[ind[peakind]],y[ind[peakind]],'ro',picker=5)
            print('peak: ', zip(x[ind[peakind]], y[ind[peakind]]))
            pass

        elif self._mode == 4:
            # delete
            #for artist in remove:
            artist.remove()

        fig.canvas.draw()

if __name__ == "__main__":
    fig = plt.figure()
    ax = plt.axes()

    ax.set_xlim(0, 1.5)
    ax.set_ylim(-1.5, 1.5)

    #pickable_artists = []

    x=np.arange(0,2,0.01)
    y=np.sin(2*np.pi*x)
    plt.plot(x, y, picker=5)

    browser = MyClick()
    cid = fig.canvas.mpl_connect('pick_event', browser.pick)
    cid = fig.canvas.mpl_connect('key_press_event', browser.press)

    plt.show()

I've been trying to follow things from this post matplotlib: clearing the scatter data before redrawing but I seem to be doing something wrong. Any help would be greatly appreciated! Thanks in advance!

Community
  • 1
  • 1

1 Answers1

1

After a few hours of toying and searching I came up with a solution. Basically I stored each peak selected and plotted into a list. Then compared the list to the current artist. I'm sorry if thats a horrible explanation, but I've included the new code below. Thanks for matplotlib: clearing the scatter data before redrawing and Matplotlib - How to remove a specific line or curve for the inspiration and help.

#! /usr/bin/python
import sys
import matplotlib.pyplot as plt
import numpy as np


class MyClick(object):
    def __init__(self):
        # initialize mode
        self._mode = 1 

        self.peak = []
        self.pk = [] # new - list where to store artists/pts already picked

    def press(self, event):
        """record last key pressed"""
        sys.stdout.flush()
        if event.key == '1':   
            self._mode = 1 
            print('Peak Mode')

        elif event.key == '4':
            self._mode = 4
            print('Delete Mode')

    def pick(self,event):
        mouseevent = event.mouseevent
        artist = event.artist
        x, y = np.array(artist.get_xdata()), np.array(artist.get_ydata()) #used numpy array for argsort feature
        ind = event.ind

        #remove = [artist for artist in self.peak if artist.contains()]


        if self._mode == 1:
            # peak
            peakind = y[ind].argsort()[-1:] #argsort to find peak
            self.peak.append(zip(x[ind[peakind]], y[ind[peakind]])) #save peak
            pt, = ax.plot(x[ind[peakind]],y[ind[peakind]],'ro',picker=5) #new
            self.pk.append(pt)  #new - store into a list
            print('peak: ', zip(x[ind[peakind]], y[ind[peakind]]))
            pass

        elif self._mode == 4:
            # delete
            for i in self.pk:   # this loop can probably be done in 1 line
                for j in ind:
                    if i == artist: #see if point in list matches current point
                        i.remove()  #remove the point

        fig.canvas.draw()

if __name__ == "__main__":
    fig = plt.figure()
    ax = plt.axes()

    ax.set_xlim(0, 1.5)
    ax.set_ylim(-1.5, 1.5)

    #pickable_artists = []

    x=np.arange(0,2,0.01)
    y=np.sin(2*np.pi*x)
    plt.plot(x, y, picker=5)

    browser = MyClick()
    cid = fig.canvas.mpl_connect('pick_event', browser.pick)
    cid = fig.canvas.mpl_connect('key_press_event', browser.press)

    plt.show()

Hope this helps anyone in the future!

Community
  • 1
  • 1