Search code examples
pythonmatplotlibinteractivearrow-keys

Changing r values for cobweb diagrams in Python


Relatively new to Matplotlib. I plotted a cobweb diagram and is now hoping to change the r values via arrow keys as the program is running. Tried to use "import keyboard" along with a "running loop" but it doesn't seem to work. Can someone please explain?

import matplotlib.pyplot as plt
import keyboard
from scipy import linspace

r = 3.35
x0 = 0.3
running = True


def cobweb(f, x0):
    t = linspace(0, 1, 100)
    l = plt.plot(t, f(t))
    plt.plot(t, t)

    x, y = x0, f(x0)
    for _ in range(100):
        fy = f(y)
        plt.plot([x, y], [y, y], 'b', linewidth=1)
        plt.plot([y, y], [y, fy], 'b', linewidth=1)
        x, y = y, fy

    plt.xlabel("X n")
    plt.ylabel("X n+1")
    plt.show()
    plt.close()


while running:
    cobweb(lambda x: r * x * (1 - x), x0)
    if keyboard.is_pressed('up'):
        r += 0.1
    if keyboard.is_pressed('down'):
        r -= 0.1
    cobweb(lambda x: r * x * (1 - x), x0)

Solution

  • You need to turn on the interactive mode with plt.ion() and replace plt.show() with fig.canvas.draw(). Check the following code:

    import matplotlib.pyplot as plt
    import keyboard
    # from scipy import linspace
    from numpy import linspace
    import time
    
    r = 3.35
    x0 = 0.3
    running = True
    
    
    def cobweb(f, x0):
        ax.cla()
        t = linspace(0, 1, 100)
        l = plt.plot(t, f(t))
        plt.plot(t, t)
    
        x, y = x0, f(x0)
        for _ in range(100):
            fy = f(y)
            plt.plot([x, y], [y, y], 'b', linewidth=1)
            plt.plot([y, y], [y, fy], 'b', linewidth=1)
            x, y = y, fy
    
        plt.xlabel("X n")
        plt.ylabel("X n+1")
        fig.canvas.draw()
        time.sleep(0.01)
    
    plt.ion()
    fig, ax = plt.subplots()
    
    while running:
        if keyboard.is_pressed('up'):
            r += 0.1
        if keyboard.is_pressed('down'):
            r -= 0.1
        cobweb(lambda x: r*x*(1 - x), x0)
    

    By pressing or , you will get plots like these:

    enter image description here enter image description here

    Note: if you use linspace by scipy, you get this warning:

    DeprecationWarning: scipy.linspace is deprecated and will be removed in SciPy 2.0.0, use numpy.linspace instead
    

    It is wise to replace it with

    from numpy import linspace
    

    as I done in the above code. The functionality of your code won't change