0

I am playing with the code in this tutorial of the Barnsley fern, and I would like the fern to be plotted slowly (not at once). Python is not comfortable, yet, and I see that the function plt.pause() may do the trick in some other answers; however, I don't know how to combine plt.pause() with plt.scatter() to obtain an animated gif effect. Would I have to incorporate plt.scatter within the for loop, for example?

# importing necessary modules 
import matplotlib.pyplot as plt 
from random import randint 

# initializing the list 
x = [] 
y = [] 

# setting first element to 0 
x.append(0) 
y.append(0) 

current = 0

for i in range(1, 50000): 

    # generates a random integer between 1 and 100 
    z = randint(1, 100) 

    # the x and y coordinates of the equations 
    # are appended in the lists respectively. 

    # for the probability 0.01 
    if z == 1: 
        a = 0; b = 0; c = 0; d = 0.16; e = 0; f = 0
        x.append(0) 
        y.append(d*(y[current])) 

    # for the probability 0.85     
    if z>= 2 and z<= 86: 
        a = 0.85; b = 0.04; c = -0.04; d = 0.85; e = 0; f = 1.6
        x.append(a*(x[current]) + b*(y[current])) 
        y.append(c*(x[current]) + d*(y[current])+f) 

    # for the probability 0.07     
    if z>= 87 and z<= 93: 
        a = 0.2; b = -0.26; c = 0.23; d = 0.22; e = 0; f = 1.6
        x.append(a*(x[current]) + b*(y[current])) 
        y.append(c*(x[current]) + d*(y[current])+f) 

    # for the probability 0.07     
    if z>= 94 and z<= 100: 
        a = -0.15; b = 0.28; c = 0.26; d = 0.24; e = 0; f = 0.44
        x.append(a*(x[current]) + b*(y[current])) 
        y.append(c*(x[current]) + d*(y[current])+f) 

    current = current + 1

plt.figure(figsize=(10,10))

plt.scatter(x, y, s = 0.2, edgecolor ='green') 

This is the desired effect:

enter image description here

Antoni Parellada
  • 4,253
  • 6
  • 49
  • 114

1 Answers1

1

I suggest you to use FuncAnimation from matplotlib.animation:

You can just a point in each frame. You just have to set axes limits to avoid figure to move:

fig, ax = plt.subplots(figsize=(10, 10))
ax.set_xlim(min(x), max(x))
ax.set_ylim(min(y), max(y))

def animation(i):
    ax.scatter(x[i], y[i], s=0.2, edgecolor='green')


ani = FuncAnimation(fig, animation, frames=len(x))

plt.show()

EDIT In case you want more points to be drawn at the same time e.g. 15:

fig, ax = plt.subplots(figsize=(10, 10))
ax.set_xlim(min(x), max(x))
ax.set_ylim(min(y), max(y))

nb_points = 15
# calculate number of frames needed:
# one more frame if remainder is not 0
nb_frames = len(x) // nb_points + (len(x) % nb_points != 0)


def animation(i):
    i_from = i * nb_points
    # are we on the last frame?
    if i_from + nb_points > len(x) - 1:
        i_to = len(x) - 1
    else:
        i_to = i_from + nb_points
    ax.scatter(x[i_from:i_to], y[i_from:i_to], s=0.2, edgecolor='green')


ani = FuncAnimation(fig, animation, frames=nb_frames)

plt.show()
david
  • 1,302
  • 1
  • 10
  • 21
  • I'm sure I'm missing out on something, but it only shows one single figure with the first batch of points. – Antoni Parellada May 10 '20 at 15:06
  • I do have a correct visual ouput... have you tried with fewer steps? any console output ? – david May 10 '20 at 15:15
  • I am using Jupyter NB with inline output of the plot. Would you mind pasting the exact entire code you ran? Thank you! – Antoni Parellada May 10 '20 at 16:01
  • 1
    I see it in real time, but I do not use Jupyter to do so. I guess you could try [https://stackoverflow.com/questions/43445103/inline-animations-in-jupyter#43447370](https://stackoverflow.com/questions/43445103/inline-animations-in-jupyter#43447370). – david May 10 '20 at 17:22