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')