Silent Sniper
Silent Sniper

Reputation: 15

Python plots graph into button instead of figure

I'm a total beginner to python (started some days ago).
This little program is supposed to draw sinus waves, and the buttons at the bottom should increase / decrease the frequency of the plotted sinus. But my program plots the sinus into the button, for whatever reason. Where is the mistake? I've tried so much already... Thanks in advance ❤

import numpy as np
import matplotlib.pyplot as plt  
from matplotlib.widgets import Button

class Function:      
def __init__(self, amplitude, frequency): 
    self.amplitude = amplitude  
    self.frequency = frequency  
    self.time = np.arange(0.0, 1.0, 0.001) 
    self.signal= amplitude*np.sin(2*np.pi*frequency*self.time)           

def status(self):        
    print("The frequency is: ", self.frequency)        
    print("The amplitude is: ", self.amplitude)                    

def setFrequency(self, frequency):        
    self.frequency = frequency                    

def setAmplitue(self, amplitude):        
    self.amplitude = amplitude            

def show(self):        
    plt.plot(self.time, self.signal, linewidth = 2)        
    plt.ylabel("Sinus") 
    plt.xlabel("x")      
    pass

func = Function(1, 20)
func.show()

def IncreaseFrequency(event):
    global func
    if (func.frequency < 100):
        func.setFrequency(func.frequency + 10)   
    else:
        func.setFrequency(10)
    func.show()
    plt.draw()
    pass

def LowerFrequency(event):
    global func
    if (func.frequency > 10):
        func.setFrequency(func.frequency - 10)
    else:
        func.setFrequency(100) 
    func.show()
    plt.draw()
    pass

buttonIncrSize = plt.axes([0.7, 0.01, 0.1, 0.05])
buttonLowerSize = plt.axes([0.81, 0.01, 0.1, 0.05])
buttonIncrFreq = Button(buttonIncrSize, 'Next')
buttonLowerFreq = Button(buttonLowerSize, 'Previous')
buttonIncrFreq.on_clicked(IncreaseFrequency)
buttonLowerFreq.on_clicked(LowerFrequency)

plt.show()

Upvotes: 0

Views: 424

Answers (1)

python_ged
python_ged

Reputation: 610

First what looks kind of weird is that after lowering or increasing your frequency, you never update the self.signal, which should change if your frequency changes.

Secondly, from what I could see on this link, plt.plot returns an Line2D object which you can use to set the y data on your plot using line2D.set_ydata(new_ydata).

After changing the y data, just update the plot using plt.draw() and that should work.

EDIT: Indeed I didn't have access to my PC but ran this now and didn't work. After some search:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import matplotlib


class Function:
    def __init__(self, amplitude, frequency):
        self.amplitude = amplitude
        self.frequency = frequency
        self.time = np.arange(0.0, 1.0, 0.001)
        self.signal = amplitude * np.sin(2 * np.pi * frequency * self.time)

    def status(self):
        print("The frequency is: ", self.frequency)
        print("The amplitude is: ", self.amplitude)

    def setFrequency(self, frequency):
        self.frequency = frequency
        self.signal = self.amplitude * np.sin(2 * np.pi * frequency * self.time)

    def setAmplitude(self, amplitude):
        self.amplitude = amplitude
        self.signal = self.amplitude * np.sin(2 * np.pi * frequency * self.time)

    def show(self):
        plt.cla()
        plt.plot(self.time,self.signal,lw=2)
        plt.draw()
        plt.ylabel("Sinus")
        plt.xlabel("x")


def IncreaseFrequency(event):
    global func
    if (func.frequency < 100):
        func.setFrequency(func.frequency + 10)
    else:
        func.setFrequency(10)
    func.show()


def LowerFrequency(event):
    global func
    if (func.frequency > 10):
        func.setFrequency(func.frequency - 10)
    else:
        func.setFrequency(100)
    func.show()


fig, ax = plt.subplots()
func = Function(1, 20)
func.show()
buttonIncrSize = plt.axes([0.7, 0.01, 0.1, 0.05])
buttonLowerSize = plt.axes([0.81, 0.01, 0.1, 0.05])
buttonIncrFreq = Button(buttonIncrSize, 'Next')
buttonLowerFreq = Button(buttonLowerSize, 'Previous')
buttonIncrFreq.on_clicked(IncreaseFrequency)
buttonLowerFreq.on_clicked(LowerFrequency)
plt.sca(fig.axes[0])
plt.show()
 

Main change being the plt.sca(fig.axes[0]) which allows to select the current axis for plt. When you run plt.axes() it sets the current axes of plt to the button, hence subsequently plotting your graph in that button. Also added plt.cla() which clears the current plotting area.

Upvotes: 2

Related Questions