Skip to content

Instantly share code, notes, and snippets.

@drammock
Last active April 4, 2016 01:22
Show Gist options
  • Save drammock/f59e40ea27891f1da450 to your computer and use it in GitHub Desktop.
Save drammock/f59e40ea27891f1da450 to your computer and use it in GitHub Desktop.
script to generate proposed new logo for MNE
# -*- coding: utf-8 -*-
"""
===============================================================================
Script 'mne logo'
===============================================================================
This script makes the logo for MNE.
"""
# @author: drmccloy
# Created on Mon Jul 20 11:28:16 2015
# License: BSD (3-clause)
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams
from matplotlib.mlab import bivariate_normal
from matplotlib.path import Path
from matplotlib.text import TextPath
from matplotlib.patches import PathPatch
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.transforms import Bbox
grayscale = False
justify_fudge = 0.97 # to get justification to work properly
center_fudge = np.array([3, 0]) # compensate for font bounding box padding
# font, etc
dpi = 72.
rcp = {'font.sans-serif': ['M+ 1c'], 'font.style': 'normal',
'font.weight': 'black', 'font.variant': 'normal', 'figure.dpi': dpi,
'savefig.dpi': dpi, 'contour.negative_linestyle': 'solid'}
plt.rcdefaults()
rcParams.update(rcp)
# initialize figure (no axes, margins, etc)
fig = plt.figure(1, figsize=(5, 3), frameon=False, dpi=dpi)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
# fake field data
delta = 0.1
x = np.arange(-8.0, 8.0, delta)
y = np.arange(-3.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 8.0, 7.0, -5.0, 0.9, 1.0)
Z2 = bivariate_normal(X, Y, 15.0, 2.5, 2.6, -2.5, 2.5)
Z = Z2 - 0.7 * Z1
# color map: field gradient (yellow-red-transparent-blue-cyan)
yrtbc = {'red': ((0.0, 1.0, 1.0), (0.5, 1.0, 0.0), (1.0, 0.0, 0.0)),
'blue': ((0.0, 0.0, 0.0), (0.5, 0.0, 1.0), (1.0, 1.0, 1.0)),
'green': ((0.0, 1.0, 1.0), (0.5, 0.0, 0.0), (1.0, 1.0, 1.0)),
'alpha': ((0.0, 1.0, 1.0), (0.4, 0.8, 0.8), (0.5, 0.2, 0.2),
(0.6, 0.8, 0.8), (1.0, 1.0, 1.0))}
# color map: field lines (red | blue)
redbl = {'red': ((0., 1., 1.), (0.5, 1., 0.), (1., 0., 0.)),
'blue': ((0., 0., 0.), (0.5, 0., 1.), (1., 1., 1.)),
'green': ((0., 0., 0.), (1., 0., 0.)),
'alpha': ((0., 0.4, 0.4), (1., 0.4, 0.4))}
mne_field_grad_cols = LinearSegmentedColormap('mne_grad', yrtbc)
mne_field_line_cols = LinearSegmentedColormap('mne_line', redbl)
if grayscale:
# convert gradient to grayscale
Zrgba = mne_field_grad_cols((Z - Z.min()) / (Z.max() - Z.min()))
Zrgba[:, :, :3] = (Zrgba[:, :, :3] * np.array([0.299, 0.587, 0.114])
).sum(axis=-1, keepdims=True)
# plot gradient and contour lines
im = plt.imshow(Zrgba, aspect='equal')
cs = plt.contour(Z, 9, colors='k', linewidths=1, alpha=0.2)
else:
# plot gradient and contour lines
im = plt.imshow(Z, cmap=mne_field_grad_cols, aspect='equal')
cs = plt.contour(Z, 9, cmap=mne_field_line_cols, linewidths=1)
plot_dims = np.r_[np.diff(ax.get_xbound()), np.diff(ax.get_ybound())]
# create MNE clipping mask
mne_path = TextPath((0, 0), 'MNE')
dims = mne_path.vertices.max(0) - mne_path.vertices.min(0)
vert = mne_path.vertices - dims / 2.
mult = (plot_dims / dims).min()
mult = [mult, -mult] # y axis is inverted (origin at top left)
offset = plot_dims / 2. - center_fudge
mne_clip = Path(offset + vert * mult, mne_path.codes)
# apply clipping mask to field gradient and lines
im.set_clip_path(mne_clip, transform=im.get_transform())
for coll in cs.collections:
coll.set_clip_path(mne_clip, transform=im.get_transform())
# get final position of clipping mask
mne_corners = mne_clip.get_extents().corners()
# add tagline
rcParams.update({'font.weight': 'light'})
tag_path = TextPath((0, 0), 'MEG + EEG ANALYSIS & VISUALIZATION')
dims = tag_path.vertices.max(0) - tag_path.vertices.min(0)
vert = tag_path.vertices - dims / 2.
mult = justify_fudge * (plot_dims / dims).min()
mult = [mult, -mult] # y axis is inverted
offset = mne_corners[-1] - np.array([mne_clip.get_extents().size[0] / 2.,
-dims[1]])
tag_clip = Path(offset + vert * mult, tag_path.codes)
tag_patch = PathPatch(tag_clip, facecolor='k', edgecolor='none', zorder=10)
ax.add_patch(tag_patch)
yl = ax.get_ylim()
yy = np.max([tag_clip.vertices.max(0)[-1],
tag_clip.vertices.min(0)[-1]])
ax.set_ylim(np.ceil(yy), yl[-1])
# plot actual image extent plus a bit of padding
extent = Bbox(np.c_[ax.get_xlim(), ax.get_ylim()])
extent = extent.transformed(ax.transData + fig.dpi_scale_trans.inverted())
plt.draw()
plt.savefig('mne-logo.svg', bbox_inches=extent.expanded(1.2, 1.))
plt.savefig('mne-logo.png', bbox_inches=extent.expanded(1.2, 1.))
@teonbrooks
Copy link

is this the most up-to-date version of the MNE logo. I tried to run it (I need to make a version with white text and transparent background) but the field lines look different. I also had a font problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment