Instantly share code, notes, and snippets.

# endolith/cyclic_noise.py

Last active February 16, 2023 15:31
Cyclic noise from filtering white noise in Python

[This is a mess. TODO: Turn it into a `def cyclic_noise` function.]

This generates cyclic/repeating/perfect loop noise by low-pass filtering white noise in a cyclic way. Useful for "random" but looping animations, etc.:

This one loops in both space and time, for instance:

Simplex noise typically has a more trapezoidal value distribution:

lmas/opensimplex#18 (comment)

which could be emulated by stretching the sample values.

Other examples:

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 import numpy as np import matplotlib.pyplot as plt from scipy.ndimage import gaussian_filter rng = np.random.default_rng() # shape = (1024, ) # shape = (512, 512) shape = (128, 128, 128) white = rng.normal(size=shape) if len(shape) == 1: fig, ax = plt.subplots(3, 1, sharex='col', num='LPF noise comparison', figsize=(9, 6)) else: fig, ax = plt.subplots(1, 3, num='LPF noise comparison', figsize=(9, 6)) if white.ndim == 1: # Plot the curve ax.plot(white) elif white.ndim == 2: # Plot a heatmap ax.imshow(white, cmap='gray') elif white.ndim == 3: # Plot a heatmap of the first slice ax.imshow(white, cmap='gray') ax.set_title('White noise') filtered = gaussian_filter(white, 7, mode='wrap') del white # Plot it tiled next to itself tiled = np.hstack((filtered, filtered)) if tiled.ndim == 1: ax.plot(tiled) elif tiled.ndim == 2: ax.imshow(tiled, cmap='gray') elif tiled.ndim == 3: ax.imshow(tiled, cmap='gray') ax.set_title('Filtered, tiled') del tiled vmin = filtered.min() vmax = filtered.max() if filtered.ndim == 3: for n, slice in enumerate(filtered): plt.imsave(f'slice {n:03d}.png', filtered[n], vmin=vmin, vmax=vmax, cmap='gray')

### endolith commented Oct 17, 2022

```import numpy as np
from scipy.ndimage import gaussian_filter

def cyclic_noise(shape, sigma=7, rng)=None:
"""
shape stuff copy

sigmascalar or sequence of scalars

Standard deviation for Gaussian kernel. The standard deviations of the Gaussian filter are given for each axis as a sequence, or as a single number, in which case it is equal for all axes.

copy rng stuff from scipy functions
"""
white = rng.normal(size=shape)
filtered = gaussian_filter(white, sigma, mode='wrap')
return filtered```