Python Forum
Optimize a random walk "animation" in matplotlib
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Optimize a random walk "animation" in matplotlib
#1
Newbie here, learning python.
I am trying to make a very simple code to "animate" a random walk. I use the quotation marks because I don't really know if python (or the way I wrote the code anyway) is the best solution to create an animation.
My objective is to explore different types of random walks by extracting useful visual information besides the usual statistical approach.

My code basically creates two arrays: one with random step lengths and another with random turning angles. From these I create a path (ie list of x, y positions) and then draw the path step by step. I also show the distribution of angles and step lengths.

The first problem I see is that I am very bad using matplotlib (probably this is the most important issue) and I don't know how to optimize the code for speed: the code works and I can see the random walk being developed in the plot, but it is annoyingly slow. I have coded in Pascal many (many!) years ago (Lazarus) and it was SO much faster. Further, it seems to redraw all 3 plots instead of only updating the figure with the random walk itself.

Can you point me what should I start with? Again, I am surely missing lots of optimization from matplotlib alone (or maybe it is not the best choice for my objective?
Here is the code:

# Generates a 2D random walk

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import numpy as np
import math 
from numpy.random import seed
from numpy.random import randint
from numpy.random import randn
import matplotlib.pyplot as plt

# Number of total steps in this walk
number_of_steps = 100

# Time for drawing pause ("animation")
pauseduration = 0.001

# Size of figures for angles and step sizes distribution
sizeFig = 4.5

# Seed
seed(22)

# Mean turning angles
mean = 0
# Standard deviation of the angles
SDev = 1

# Create a vector with random angles
# The angles are drawn from a UNIFORM distribution
# They are integer values within the range 0-360 degrees
angles = randint(0, 360, number_of_steps)
   
# Plot histogram to show distribution of angles
fig = plt.figure(num=1, figsize=(sizeFig,sizeFig))
ax = plt.axes()
ax.set(xlabel="Angle (degrees)", ylabel="Number of cases", title='Angles')
plt.hist(angles, bins=35)

# Now convert angles to radians. This is needed later when
# calculating the new x,y position from angle and step-length
angles = np.radians(angles)

# Create an array with random step sizes
# The step sizes are drawn from a normal distribution 
# First, draw values from standard normal distribution 
# ie mean = 0 and SD = 1
normalized_step_size = randn(number_of_steps)

# Then scale the values to fit this particular normal dist
# with mean = mean and standard deviation = SDev
step_sizes = mean + normalized_step_size * SDev

# Plot histogram to show distribution of step sizes
fig = plt.figure(num=2 ,figsize=(sizeFig,sizeFig))
ax = plt.axes()
ax.set(xlabel="Step size", ylabel="Number of cases", title='Step lengths')
plt.hist(step_sizes, bins=35)


# apparently I could have used directly this:
# normalized_step_size = np.random.normal(mean, SDev, number_of_steps)

# Create a vector of 2 dimensions  
# to store X, Y positions
positions  = np.zeros((2, number_of_steps))

# Starting position
x_start = 0
y_start = 0
positions[0,0] = x_start
positions[1,0] = y_start

# Prepare for plotting
fig = plt.figure(num=3,figsize=(8,8))
ax = plt.axes()
ax.set(xlabel="x (steps)", ylabel="y (steps)", title='A Simple Plot')
ax.set_aspect('equal')

# For each step:
    # move (using an angle and step size from 'angle' and 'steps')
    # draw the current position
    
    
for step in range(1, number_of_steps):
        
    # Calculate x2,y2 from x1,y1 and angle

    # Update x position
    positions[0,step] = positions[0,step-1] + step_sizes[step] * math.cos(angles[step])
    
    # Update y position
    positions[1,step] = positions[1,step-1] + step_sizes[step] * math.sin(angles[step])
    
    x1x2 = np.array([positions[0,step-1],positions[0,step]])
    y1y2 = np.array([positions[1,step-1],positions[1,step]])
    
    ax.set(title='A Simple Plot - #'+str(step))
    plt.plot(x1x2,y1y2)

    # Wait a bit to make it look animated
    plt.pause(pauseduration)
Reply
#2
Matplotlib can be used for building animated plots. I would recommend to use matplotlib.animation for this. There are quite comprehensive examples of how to create animations, e.g. the following one.
Another option for making animations in Python is to use e.g. pygame package.
Reply
#3
(Jul-21-2020, 07:05 AM)scidam Wrote: Matplotlib can be used for building animated plots. I would recommend to use matplotlib.animation for this. There are quite comprehensive examples of how to create animations, e.g. the following one.
Another option for making animations in Python is to use e.g. pygame package.

Wow THANKS!! In their website there is even a 3D random walk animation! Big Grin
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Bug do you have an idea to optimize this code[recursion]]? netanelst 0 1,507 May-19-2022, 06:50 AM
Last Post: netanelst

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020