Created
February 24, 2020 16:43
-
-
Save joferkington/d3076ad449cfdfa2d073eda5a89f914a to your computer and use it in GitHub Desktop.
Some auto-generated mold-like art in matplotlib.
This file contains hidden or 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
""" | |
Silly auto-generated art. Meant to look like some sort of mold spores. | |
Deliberately slow to render -- meant to look good at high-res. | |
""" | |
import numpy as np | |
import matplotlib.pyplot as plt | |
import matplotlib.colors as mcolors | |
from matplotlib.collections import LineCollection | |
def main(): | |
spore = MoldSpore() | |
fig, ax = plt.subplots(figsize=(6,12)) | |
pos = 20 * np.random.random((10, 2)) | |
pos[1,:] *= 0.7 | |
for x, y in pos: | |
spore.plot(ax, center=(x, y)) | |
ax.axis('off') | |
fig.patch.set(facecolor='0.3') | |
ax.set(aspect=1.0) | |
ax.autoscale() | |
fig.tight_layout() | |
plt.show() | |
class MoldSpore(object): | |
def __init__(self, fringe_color='white', linewidth=0.01, jitter=0.005, | |
center_light='#2C9E0D', center_dark='#073303', | |
random_seed=None): | |
self.fringe_color = fringe_color | |
self.lw = linewidth | |
self.jitter = jitter | |
self.center_light = center_light | |
self.center_dark = center_dark | |
if random_seed is None: | |
random_seed = np.random.RandomState() | |
elif isinstance(random_seed, int): | |
random_seed = np.random.RandomState(random_seed) | |
self.random = random_seed | |
def plot(self, ax, nlines=2000, center=(0,0), radius=None): | |
if radius is None: | |
radius = 1.5 * self.random.random_sample() + 0.5 | |
mwidth = radius * (0.4 * self.random.random_sample() + 0.3) | |
fringe = LineCollection(list(self.lines(nlines, center, radius)), | |
color=self.fringe_color, lw=self.lw) | |
green, fringes = self.mound(center, mwidth, nlines) | |
ax.add_collection(fringe) | |
ax.add_collection(fringes) | |
ax.add_collection(green) | |
def filament(self, center, angle, radius, inner_radius=0): | |
npoints = int((radius - inner_radius) * 500.0) | |
x0, y0 = center | |
width = radius - inner_radius | |
r = np.linspace(inner_radius, radius, npoints) / radius | |
dx = width * np.ones(npoints) * np.cos(np.radians(angle)) / npoints | |
dy = width * np.ones(npoints) * np.sin(np.radians(angle)) / npoints | |
dx += self.random.normal(0, self.jitter, npoints) * 1 * r**2.5 | |
dy += self.random.normal(0, self.jitter, npoints) * 1 * r**2.5 | |
dx[0] += inner_radius * np.cos(np.radians(angle)) | |
dy[0] += inner_radius * np.sin(np.radians(angle)) | |
dx = dx.cumsum() | |
dy = dy.cumsum() | |
return zip(x0 + dx, y0 + dy) | |
def lines(self, num, center=(0, 0), outer=1.0, inner=0): | |
for angle in np.linspace(0, 360, num): | |
yield self.filament(center, angle, outer, inner) | |
def mound(self, center, radius, num): | |
symmetry = self.random.randint(1, 4) | |
start = self.random.random_sample() * 2 * np.pi | |
colors = [self.center_light, self.center_dark] | |
cmap = mcolors.LinearSegmentedColormap.from_list('', colors) | |
n = int(np.ceil(float(num) / (symmetry * 2))) | |
vals = self.random.normal(0, 3, n).cumsum() | |
vals = np.r_[vals, vals[::-1]] | |
vals = np.concatenate(symmetry * [vals]) | |
theta = np.linspace(start, start + 2 * np.pi, vals.size) | |
rvals = (vals - vals.min()) / vals.ptp() | |
r = radius * (np.ones(vals.size) + 0.05 * rvals) | |
fwidth = 0.3 * radius | |
x0, y0 = center | |
rays = [] | |
fringes = [] | |
for rad, angle in zip(r, theta): | |
x = rad * np.cos(angle) | |
y = rad * np.sin(angle) | |
rays.append([(x0, y0), (x + x0, y + y0)]) | |
fil = self.filament(center, np.degrees(angle), rad + fwidth, rad) | |
fringes.append(fil) | |
ccol = LineCollection(rays, array=vals, cmap=cmap, linewidths=5*self.lw, | |
zorder=4) | |
fcol = LineCollection(fringes, linewidths=self.lw, | |
color=self.fringe_color) | |
return ccol, fcol | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment