beamerlines/efishtitle.py

198 lines
6.6 KiB
Python

import numpy as np
import matplotlib.pyplot as plt
from thunderfish.efield import efish_monopoles, epotential_meshgrid, squareroot_transform
from thunderfish.fishshapes import plot_fish
def aspect_ratio(ax):
"""Aspect ratio of axes.
From `plottools.axes`.
Parameters
----------
ax: matplotlib axes
Axes of which aspect ratio is computed.
Returns
-------
aspect: float
Aspect ratio (height in inches relative to width).
"""
figw, figh = ax.get_figure().get_size_inches()
_, _, w, h = ax.get_position().bounds
return (figh * h) / (figw * w)
def lighter(color, lightness):
""" Make a color lighter.
Adapted from `plottools.colors`.
Parameters
----------
color: matplotlib color spec
A matplotlib color (hex string, name color string, rgb tuple).
lightness: float
The smaller the lightness, the lighter the returned color.
A lightness of 0 returns white.
A lightness of 1 leaves the color untouched.
A lightness of 2 returns black.
Returns
-------
color: string
The lighter color as a hexadecimal RGB string (e.g. '#rrggbb').
"""
try:
from matplotlib.colors import colorConverter as cc
except ImportError:
import matplotlib.colors as cc
try:
from matplotlib.colors import to_hex
except ImportError:
from matplotlib.colors import rgb2hex as to_hex
if lightness > 2:
lightness = 2
if lightness > 1:
return darker(color, 2.0-lightness)
if lightness < 0:
lightness = 0
r, g, b = cc.to_rgb(color)
rl = r + (1.0-lightness)*(1.0 - r)
gl = g + (1.0-lightness)*(1.0 - g)
bl = b + (1.0-lightness)*(1.0 - b)
return to_hex((rl, gl, bl)).upper()
def colormap(name, colors, values=None):
""" Generate and register a color map.
From `plottools.colors`.
This is a simple shortcut to the cumbersome names and imports needed for
`matplotlib.colors.LinearSegmentedColormap` and `matplotlib.cm import register_cmap`.
Parameters
----------
name: string
Name of the color map. You can use this name to set the colormap, e.g.
```
ax.contourf(x, y, z, cmap=name)
```
colors: sequence of matplotlib color specifications
The colors from which to generate the color map.
values: sequence of floats or None
If None, `colors` are equidistantly mapped on the range 0 to 1.
Otherwise for each color the position in the colors map range.
Returns
-------
cmap: matplotlib colormap
The color map generated from `colors`.
"""
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.cm import register_cmap
if values is not None:
colors = list(zip(values, colors))
cmap = LinearSegmentedColormap.from_list(name, colors)
register_cmap(cmap=cmap)
return cmap
# colors_muted palette from plottools.colors:
palette = {}
palette['red'] = '#C02717'
palette['orange'] = '#F78017'
palette['yellow'] = '#F0D730'
palette['lightgreen'] = '#AAB71B'
palette['green'] = '#478010'
palette['darkgreen'] = '#007027'
palette['cyan'] = '#008767'
palette['lightblue'] = '#108790'
palette['blue'] = '#2060A7'
palette['purple'] = '#53379B'
palette['magenta'] = '#873770'
palette['pink'] = '#D03050'
palette['white'] = '#FFFFFF'
palette['gray'] = '#A0A0A0'
palette['black'] = '#32414B' # black from colors_unituebingen
# global styles for plotting fish:
csLine = dict(colors=palette['gray'], linewidths=0.1, linestyles='solid')
fishBody = dict(zorder=21, lw=0.1, edgecolor=palette['black'], facecolor=palette['black'])
fishFins = dict(zorder=20, lw=0.5, alpha=0.4, edgecolor=lighter(palette['black'], 0.4),
facecolor=palette['black'])
fishOpenBody = dict(zorder=21, lw=0.2, edgecolor=palette['black'], facecolor='none')
fishLightBody = dict(zorder=21, lw=0.2, edgecolor=palette['black'],
facecolor=lighter(palette['black'], 0.2))
fishLightFins = dict(zorder=20, lw=0.2, edgecolor=palette['black'],
facecolor=lighter(palette['black'], 0.05))
def plot_threewavefish(ax):
maxx = 30.0
maxy = maxx * aspect_ratio(ax)
x = np.linspace(-maxx, maxx, 600)
y = np.linspace(-maxy, maxy, 200)
xx, yy = np.meshgrid(x, y)
fish1 = (('Alepto', 'top'), (-16.5, -3.5), (1, 0.1), 18.0, 10)
fish2 = (('Alepto', 'top'), (17, 0.5), (1.0, 0.4), 20.0, -20)
fish3 = (('Alepto', 'top'), (2, 3), (1, -0.1), 16.0, -12)
poles1 = efish_monopoles(*fish1[1:])
poles2 = efish_monopoles(*fish2[1:])
poles3 = efish_monopoles(*fish3[1:])
pot = epotential_meshgrid(xx, yy, None, poles1, poles2, poles3)
mz = 0.65
zz = squareroot_transform(pot/200, mz)
levels = np.linspace(-mz, mz, 16)
ax.contourf(x, y, -zz, levels)
ax.contour(x, y, -zz, levels, **csLine)
plot_fish(ax, *fish1, bodykwargs=fishBody, finkwargs=fishFins)
plot_fish(ax, *fish2, bodykwargs=fishBody, finkwargs=fishFins)
plot_fish(ax, *fish3, bodykwargs=fishBody, finkwargs=fishFins)
ax.set_aspect('equal')
def plot_twowavefishside(ax):
maxx = 30.0
maxy = maxx * aspect_ratio(ax)
x = np.linspace(-maxx, maxx, 600)
y = np.linspace(-maxy, maxy, 200)
xx, yy = np.meshgrid(x, y)
fish1 = (('Alepto_male', 'side'), (-12, 0), (1, 0.2), 23.0, 15)
fish2 = (('Alepto', 'top'), (14, -1.5), (1.0, 0.45), 23.0, -20)
poles1 = efish_monopoles(*fish1[1:])
poles2 = efish_monopoles(*fish2[1:])
pot = epotential_meshgrid(xx, yy, None, poles1, poles2)
mz = 0.65
zz = squareroot_transform(pot/200, mz)
levels = np.linspace(-mz, mz, 16)
ax.contourf(x, y, -zz, levels)
ax.contour(x, y, -zz, levels, **csLine)
plot_fish(ax, *fish1, bodykwargs=fishBody, finkwargs=fishFins)
plot_fish(ax, *fish2, bodykwargs=fishBody, finkwargs=fishFins)
ax.set_aspect('equal')
if __name__ == "__main__":
# hide spines:
plt.rcParams['axes.spines.left'] = False
plt.rcParams['axes.spines.right'] = False
plt.rcParams['axes.spines.top'] = False
plt.rcParams['axes.spines.bottom'] = False
# color map:
cmcolors = [palette['red'], lighter(palette['orange'], 0.85),
lighter(palette['yellow'], 0.2), lighter(palette['lightblue'], 0.8),
palette['blue']]
cmvalues = [0.0, 0.25, 0.5, 0.8, 1.0]
colormap('RYB', cmcolors, cmvalues)
plt.rcParams['image.cmap'] = 'RYB'
#plt.rcParams['image.cmap'] = 'RdYlBu'
fig, ax = plt.subplots(figsize=(15.2/2.54, 4.0/2.54))
fig.subplots_adjust(left=0, right=1, top=1, bottom=0)
plot_threewavefish(ax)
#plot_twowavefishside(ax)
fig.savefig('efishtitle.pdf')