MicroStructPy Logo¶
Python Script¶
The basename for this file is logo.py
.
The file can be run using this command:
microstructpy --demo=logo.py
The full text of the script is:
from __future__ import division
import os
import numpy as np
from matplotlib import collections
from matplotlib import pyplot as plt
from matplotlib.offsetbox import AnnotationBbox
from matplotlib.offsetbox import OffsetImage
import microstructpy as msp
def main(n_seeds, size_rng, pos_rng, k_lw):
bkgrnd_color = 'black'
line_color = (1, 1, 1, 1) # white
dpi = 300
init_size = 2000
logo_size = 1500
favicon_size = 48
logo_basename = 'logo.svg'
favicon_basename = 'favicon.ico'
social_basename = 'social.png'
file_dir = os.path.dirname(os.path.realpath(__file__))
path = os.path.join(file_dir, 'logo')
if not os.path.exists(path):
os.makedirs(path)
print(path)
logo_filename = os.path.join(path, logo_basename)
pad_filename = os.path.join(path, 'pad_' + logo_basename)
favicon_filename = os.path.join(path, favicon_basename)
social_filename = os.path.join(path, social_basename)
# Set Domain
domain = msp.geometry.Circle()
# Set Seed List
np.random.seed(size_rng)
rs = 0.3 * np.random.rand(n_seeds)
factory = msp.seeding.Seed.factory
seeds = msp.seeding.SeedList([factory('circle', r=r) for r in rs])
seeds.position(domain, rng_seed=pos_rng)
# Create the Poly Mesh
pmesh = msp.meshing.PolyMesh.from_seeds(seeds, domain)
# Create and Format the Figure
plt.clf()
plt.close('all')
fig = plt.figure(figsize=(init_size / dpi, init_size / dpi), dpi=dpi)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
fig.add_axes(ax)
# Plot the Domain
domain.plot(ec='none', fc=bkgrnd_color)
# Plot the Facets
facet_colors = []
for neigh_pair in pmesh.facet_neighbors:
if min(neigh_pair) < 0:
facet_colors.append('none')
else:
facet_colors.append(line_color)
lw = k_lw * init_size / 100
pmesh.plot_facets(index_by='facet', colors=facet_colors,
linewidth=lw, capstyle='round')
pts = np.array(pmesh.points)
rs = np.sqrt(np.sum(pts * pts, axis=1))
mask = np.isclose(rs, 1)
edges = []
for facet in pmesh.facets:
if np.sum(mask[facet]) != 1:
continue
edge = np.copy(pts[facet])
if mask[facet[0]]:
u = edge[0] - edge[1]
u *= 1.1
edge[0] = edge[1] + u
else:
u = edge[1] - edge[0]
u *= 1.1
edge[1] = edge[0] + u
edges.append(edge)
pc = collections.LineCollection(edges, color=line_color, linewidth=lw,
capstyle='round')
ax.add_collection(pc)
# Format the Plot and Convert to Image Array
plt.axis('square')
plt.axis(1.01 * np.array([-1, 1, -1, 1]))
fig.canvas.draw()
plt_im = np.array(fig.canvas.get_renderer()._renderer)
mask = plt_im[:, :, 0] > 0.5 * 255
# Create the Logo
logo_im = np.copy(plt_im)
xx, yy = np.meshgrid(*[np.arange(n) for n in logo_im.shape[:2]])
zz = - 0.2 * xx + 0.9 * yy
ss = (zz - zz.min()) / (zz.max() - zz.min())
c1 = [67, 206, 162]
c2 = [24, 90, 157]
logo_im[mask, -1] = 0 # transparent background
# gradient
for i in range(logo_im.shape[-1] - 1):
logo_im[~mask, i] = (1 - ss[~mask]) * c1[i] + ss[~mask] * c2[i]
inds = np.linspace(0, logo_im.shape[0] - 1, logo_size).astype('int')
logo_im = logo_im[inds]
logo_im = logo_im[:, inds]
pad_w = logo_im.shape[0]
pad_h = 0.5 * logo_im.shape[1]
pad_shape = np.array([pad_w, pad_h, logo_im.shape[2]]).astype('int')
logo_pad = np.zeros(pad_shape, dtype=logo_im.dtype)
pad_im = np.concatenate((logo_pad, logo_im, logo_pad), axis=1)
doc_im = np.concatenate((logo_pad, pad_im, logo_pad), axis=1)
plt.imsave(logo_filename, logo_im, dpi=dpi)
plt.imsave(logo_filename.replace('.svg', '.png'), logo_im, dpi=dpi)
plt.imsave(pad_filename, pad_im, dpi=dpi)
plt.imsave(pad_filename.replace('.svg', '.png'), doc_im, dpi=dpi)
# Create the Favicon
fav_im = np.copy(logo_im)
inds = np.linspace(0, fav_im.shape[0] - 1, favicon_size).astype('int')
fav_im = fav_im[inds]
fav_im = fav_im[:, inds]
plt.imsave(favicon_filename, fav_im, dpi=dpi, format='png')
# Create the Social Banner
fig_social, ax_social = plt.subplots()
ax_social.set_xlim(0, 2)
ax_social.set_ylim(0, 1)
ax_social.set_aspect('equal')
ax_social.set_axis_off()
ax_social.get_xaxis().set_visible(False)
ax_social.get_yaxis().set_visible(False)
imagebox = OffsetImage(logo_im, zoom=0.05)
ab = AnnotationBbox(imagebox, (1, 0.7), frameon=False)
ax_social.add_artist(ab)
ax_social.text(1, 0.35, 'MicroStructPy',
fontsize=20,
weight='bold',
horizontalalignment='center',
verticalalignment='center')
ax_social.text(1, 0.23, 'Microstructure Mesh Generation in Python',
fontsize=10,
horizontalalignment='center',
verticalalignment='center')
plt.draw()
plt.savefig(social_filename, bbox_inches='tight')
plt.close('all')
if __name__ == '__main__':
n_seeds = 14
size_rng = 4
pos_rng = 7
k_lw = 1.1
main(n_seeds, size_rng, pos_rng, k_lw)
Domain¶
The domain of the microstructure is a Circle
.
Without arguments, the circle’s center is (0, 0) and side length is 1.
Seeds¶
The seeds are 14 circles with radii uniformly distributed from 0 to 0.3.
Calling the position()
method
positions the points according to random uniform distributions in the domain.
Polygon Mesh¶
A polygon mesh is created from the list of seed points using the
from_seeds()
class method.
The mesh is plotted and saved into a PNG file in the remaining lines of the
script.
Plot Logo¶
The edges in the polygonal mesh are plotted white on a black background. This image is converted into a mask and the white pixels are converted into transparent pixels. The remaining pixels are colored with a linear gradient between two colors. This image is saved in padded and tight versions, as well as a favicon for the HTML documentation. The logo that results is shown in Fig. 23.