0

I am currently doing an experiment with perlin noise, but generating this noise uses a series of plotted markers. Like, a bunch of them, and i need to render a lot of graphs, rendering just 20 takes around 15 minutes. Is there any way to speed up my code?

import matplotlib.pyplot as plt
import math, random, noise, time
import numpy as np

def GeneratePlot(x:int,y:int) -> list:
  pnoiseValues = []
  fig, ax = plt.subplots()
  for X in range(x**2):
    plt.gcf().canvas.flush_events()
    marker = str(random.choice(("o", "s")))
    YPOS = y+noise.pnoise2(X*x/x**2/50, y/x**2/50)
    ax.scatter(X, YPOS, marker=marker)
    pnoiseValues.append(YPOS)
  plt.show()
  return np.array(pnoiseValues)

def GetResults(amount:int,  useDelay=True) -> list:
  results = []
  for i in range(amount):
    print(f"Generating Images & Arrays.. (This may take a while depending on the # of points)")
    time.sleep(.100 if useDelay else 0)
    results.append(GeneratePlot(i**2,i//2**2))
  print(results)
  return results;
GetResults(16)

So I haven’t tried anything yet, since i am new to matplotlib

theLawyer
  • 13
  • 5
  • `ax.scatter(...)` is really slow when called to plot each dot separately. You need to give it a complete array of x and another array of y positions. You could create separate arrays for each type of marker. (Also note that `i//2**2` is just `i//4`, maybe you meant `(i//2)**2`?) – JohanC Mar 31 '22 at 06:40
  • Yes, use numpy. Perhaps of assistance if you need Perlin noise: https://stackoverflow.com/questions/42147776/producing-2d-perlin-noise-with-numpy – Jody Klymak Mar 31 '22 at 11:28

1 Answers1

0

Use blit which could speed up the plot largely. In your example you need re-plot figure every time when you get some data, however blit just plot some part of artist in the graph and use the fig from last time plot as background. My suggestion is to ceate a new class which could receive the AXES class for constructor and append new data everytime and replot. Here is a example from my real-time recording application. This is a very simple demo, and did not update the axis. if you want to update the axis at some time, you can do ax.draw_artist(axis). In my i5 8250 cpu, the speed could have ~100 fps. some official document https://matplotlib.org/stable/tutorials/advanced/blitting.html

class DisplayRealTime():
def __init__(self, ax:Axes):
    self.ax = ax
    self.ax.plot(0, 0, animated = True, linewidth = 1)
    self.line = ax.lines
    self.fig = ax.figure
    self.fig.canvas.draw()
    self.fig.canvas.flush_events()
    self.bg = ax.figure.canvas.copy_from_bbox(ax.figure.bbox)

def append(self, data:np.ndarray):   
    self.fig.canvas.restore_region(self.bg)
    self.line[0].set_data(data) 
    for i in self.line:
        self.ax.draw_artist(i) 
    self.fig.canvas.blit(self.fig.bbox)
    self.fig.canvas.flush_events()\nself.bg = self.ax.figure.canvas.copy_from_bbox(self.ax.figure.bbox)


        
    
yuanjie li
  • 11
  • 2