Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues with decorated function arguments used for conditionals, and non-looping gifs #3

Closed
davidwych opened this issue Apr 22, 2020 · 5 comments

Comments

@davidwych
Copy link

In trying to plot an audio signal stored in the array piano as a function of time t, in increments of 1000 elements, with various parts of the signal highlighted as the animation goes on with axvspan, I created the function:

image

@gif.frame
def plot_progression(T):
    #f, ax = plt.subplots(figsize=(6,4), dpi=100)
    plt.plot(t[:(T+1)*1000], piano[0][:(T+1)*1000], c="k", alpha=0.7)
    plt.xlabel("Time (seconds)")
    plt.ylabel("Amplitude (?)")
    plt.xlim([0,20])
    plt.ylim([-0.4, 0.4])
    if 1.8 < t[T] < 4.5:
        plt.axvspan(1.8, t[T], facecolor="Red", ls="--", lw=2.0, label=r"$C_{3}$", alpha=0.2)
    elif t[T] > 4.5:
        plt.axvspan(1.8, 4.5, facecolor="Red", ls="--", lw=2.0, label=r"$C_{3}$", alpha=0.2)
        plt.legend(fontsize="small")
    elif 5.5 < t[T] < 7.8:
        plt.axvspan(5.5, t[T], facecolor="Orange", ls="--", lw=2.0, label=r"$E_{3}$", alpha=0.2)
    elif t[T] > 7.8:
        plt.axvspan(5.5, 7.8, facecolor="Orange", ls="--", lw=2.0, label=r"$E_{3}$", alpha=0.2)
    elif 8.9 < t[T] < 11.2:
        plt.axvspan(8.9, t[T], facecolor="Green", ls="--", lw=2.0, label=r"$G_{3}$", alpha=0.2)
    elif t[T] > 11.2:
        plt.axvspan(8.9, 11.2, facecolor="Green", ls="--", lw=2.0, label=r"$G_{3}$", alpha=0.2)
    elif 12.2 < t[T] < 15.3:
        plt.axvspan(12.2, t[T], facecolor="Purple", ls="--", lw=2.0, label=r"$C_{maj}$", alpha=0.2)
    elif t[T] > 15.3:
        plt.axvspan(12.2, 15.3, facecolor="Purple", ls="--", lw=2.0, label=r"$C_{maj}$", alpha=0.2)

with the gif creation loop:

frames = []
for T in range(382):
    frame = plot_progression(T)
    frames.append(frame)
    del frame
    
gif.save(frames, "./audio_progression.gif", duration=45.4)

Problem is, none of the conditionals ever get triggered. All I get is the audio signal, no vspans or inclusion of the legend elements:

audio_progression


Also, is there any way to have the gif not loop? I know in gif.py the setting have loop=0 what do we set that to to get it to not loop? Can this be added as an argument to gif.save()?

@maxhumber
Copy link
Owner

Hey @davidwych! Thanks for the issue and suggestion.

I can look at adding the non-loop parameter 👍 Can I ask why you want it? I've never had a scenario when I didn't want something to loop.

As for the other issue. Could you drop in your data, so I can poke at it?

@davidwych
Copy link
Author

davidwych commented Apr 22, 2020

@maxhumber

(1) The non-loop functionality would be useful for "one-time use" animations (e.g. in my case I'm creating this gif for a slide in a presentation, so I really just need the animation to run through once and then stay in the form it's in at the last frame for the remaining time I'm presenting the slide).

(2) Here's the piano data:
piano.npy.zip

to load it:

piano = np.load("piano.npy")
t = np.linspace(0, len(piano)/22050, len(piano))

n.b. in the code above: replace piano[0] with just piano

@maxhumber
Copy link
Owner

Okay, figured out your first thing!

Seems like you need to adjust your ifs. Basically, you need two for every note. One to track the note, and another to keep the color turned on.

See this reproducible example:

import gif
from matplotlib import pyplot as plt

x = list(range(100))
y = [10] * len(x)

@gif.frame
def plot(i):
    plt.plot(x[:i], y[:i])
    plt.xlim([0, max(x)])
    plt.ylim([0, max(y) * 2])
    # track the RED note
    if x[i] > 50 and x[i] < 70:
        plt.axvspan(50, x[i-1], facecolor="Red", ls="--", lw=2.0, alpha=0.2)
    # track the BLUE note
    if x[i] > 80 and x[i] < 90:
        plt.axvspan(80, x[i-1], facecolor="Blue", ls="--", lw=2.0, alpha=0.2)
    # make sure the RED stays on
    if x[i] >= 70:
        plt.axvspan(50, 70, facecolor="Red", ls="--", lw=2.0, alpha=0.2)
    # make sure the BLUE stays on
    if x[i] >= 90:
        plt.axvspan(80, 90, facecolor="Blue", ls="--", lw=2.0, alpha=0.2)

frames = []
for i in range(len(x)):
    frame = plot(i)
    frames.append(frame)

gif.save(frames, 'piano.gif', duration=30)

Output:

piano

@maxhumber
Copy link
Owner

As for the non-looping. Let me meditate on it... for now... just skip the slide a millisecond before it finishes 🤣

@davidwych
Copy link
Author

Thanks so much! Sorry if this wasn't really an "issue" so much as me not knowing how conditionals work... :|

I thought maybe it had something to do with how arguments are handled by the decorator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants