Configuring#

Besides being super convenient, ahlive is super customizable.

keywords#

Common settings can be accessed through documented keywords.

For a list of documented keywords, see help(ah.Array).

[1]:
import ahlive as ah
ah.Array([0, 1, 2], [3, 4, 5], figsize=(3, 3)).render()
gifsicle: warning: trivial adaptive palette (only 179 colors in source)
[1]:

Do not expect all the keywords exposed in ahlive to match the matplotlib keywords!

This is because some keywords are too generic in matplotlib, e.g. plt.margins(x=1) is exposed as xmargins=1

Any keywords not documented are assumed to be plot keywords.

For example in vanilla matplotlib, to change the marker type:

[2]:
import matplotlib.pyplot as plt
_ = plt.scatter([0], [3], marker='o')
_ = plt.scatter([1], [4], marker='^')
_ = plt.scatter([2], [5], marker='v')
../_images/customizations_configuring_5_0.png

Here, although marker is not documented in ahlive’s docstring, it can still be used.

[3]:
import ahlive as ah
ah.Array([0, 1, 2], [3, 4, 5], marker=['o', '^', 'v']).render()
gifsicle: warning: trivial adaptive palette (only 218 colors in source)
[3]:

These plot keywords can be a scalar too.

[4]:
import ahlive as ah
ah.Array([0, 1, 2], [3, 4, 5], marker='^').render()
gifsicle: warning: trivial adaptive palette (only 207 colors in source)
[4]:

config#

However, because matplotlib is huge, not all keywords can be exposed. Instead, ahlive has a generic config method.

To set figsize without the built-in keyword, first pass the name of the method followed by the keyword arguments.

For example, to set figsize in vanilla matplotlib:

[5]:
import matplotlib.pyplot as plt
_ = plt.figure(figsize=(3, 3))
<Figure size 216x216 with 0 Axes>

The method is figure so that will be the first positional argument passed to config, and then the keyword argument is figsize=(3, 3).

[6]:
import ahlive as ah
arr = ah.Array([0, 1, 2], [3, 4, 5])
arr.config('figure', figsize=(3, 3)).render()
gifsicle: warning: trivial adaptive palette (only 179 colors in source)
[6]:

Or another way of doing this is to pass a nested dictionary; this way, multiple methods can be configured simultaneously.

[7]:
import ahlive as ah
arr = ah.Array([0, 1, 2], [3, 4, 5])
arr.config(**{
    'figure': {'figsize': (3, 3)},
    'axes': {'xlim': [0, 4], 'ylim': [0, 10]}
}).render()
gifsicle: warning: trivial adaptive palette (only 191 colors in source)
[7]:

However not all methods are named exactly as their matplotlib counterpart!

For example to set color in vanilla matplotlib:

[8]:
import matplotlib.pyplot as plt
plt.scatter([0, 1, 2], [3, 4, 5], color='red')
[8]:
<matplotlib.collections.PathCollection at 0x7f3de48b6c70>
../_images/customizations_configuring_17_1.png

The method is not scatter in ahlive, instead it’s plot! This is so that ahlive can handle plot, scatter, bar, etc. without too complex internal code.

[9]:
import ahlive as ah
arr = ah.Array([0, 1, 2], [3, 4, 5])
arr.config('plot', color='red').render()
gifsicle: warning: trivial adaptive palette (only 193 colors in source)
[9]:

Furthermore, methods are often prefixed: ref_ for references, grid_ for grids, remark_ for remarks, etc.

[10]:
import ahlive as ah
arr = ah.Reference([0, 1, 2])
arr.config('ref_plot', color='red').render()
[10]:

To get a full list of configurable methods:

[11]:
import ahlive as ah
for key, val in ah.CONFIGURABLES.items():
    print(f"{key}\n{val}\n")
canvas
['figure', 'suptitle', 'pool', 'animate', 'durations', 'savefig', 'watermark', 'spacing', 'interpolate', 'output']

subplot
['axes', 'plot', 'preset', 'legend', 'grid', 'xticks', 'yticks', 'limits', 'margins', 'adjust_text', 'hooks']

label
['state', 'inline', 'xlabel', 'ylabel', 'title', 'subtitle', 'caption', 'note', 'preset_inline']

geo
['crs', 'projection', 'borders', 'coastline', 'land', 'lakes', 'ocean', 'rivers', 'states', 'tiles']

color
['colorbar', 'clabel', 'cticks']

remark
['remark_plot', 'remark_inline']

grid
['grid_plot', 'grid_inline']

ref
['ref_plot', 'ref_inline']

hooks#

Still, there’s lots to be desired that ahlive is incapable of doing. Therefore, if there’s a need, things can be done the vanilla matplotlib way first and wrapped into a function listed in hooks.

[12]:
import ahlive as ah
import matplotlib.pyplot as plt
import numpy as np

def add_twinx(fig, ax):
    ax2 = ax.twinx()
    ax2.set_ylabel('The twin axes')
    ax2.set_ylim(0, 24)

ah.Array([0, 1], [0, 12], hooks=[add_twinx]).render()
gifsicle: warning: trivial adaptive palette (only 253 colors in source)
[12]:

hooks accept multiple custom functions.

style#

Setting style='minimal' reduces the number of tick labels and grid lines.

[13]:
import ahlive as ah
ah.Array([0, 1, 2], [3, 4, 5], style='minimal').render()
gifsicle: warning: trivial adaptive palette (only 229 colors in source)
[13]:

Setting style='bare' removes all tick labels, grid lines, borders, and spacing around the subplot.

[14]:
import ahlive as ah
ah.Array([0, 1, 2], [3, 4, 5], style='bare').render()
gifsicle: warning: trivial adaptive palette (only 72 colors in source)
[14]:

defaults#

To get a full list of configurable defaults:

[15]:
import ahlive as ah
for key, val in ah.DEFAULTS.items():
    print(f"{key}\n{val}\n")
durations_kwds
{'aggregate': 'max', 'transition_frames': 0.022222222222222223, 'final_frame': 0.55}

label_kwds
{'fontsize': 16, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False}

preset_kwds
{'trail': {'chart': 'scatter', 'expire': 100, 'stride': 1, 'zorder': 0}, 'morph_trail': {'chart': 'line', 'expire': 1, 'stride': 1, 'zorder': 0}, 'race': {'bar_label': True, 'limit': 5, 'ascending': False, 'annotation_clip': True}, 'delta': {'bar_label': True, 'capsize': 6}, 'scan': {'color': 'black', 'stride': 1}}

plot_kwds
{'pie': {'normalize': False}, 'scatter': {'alpha': 0.9}, 'bar': {'alpha': 0.9}, 'barh': {'alpha': 0.9}}

grid_plot_kwds
{'streamline': {'zorder': 2}, 'quiver': {'zorder': 2}, 'barbs': {'zorder': 2}}

ref_plot_kwds
{'rectangle': {'facecolor': '#696969', 'alpha': 0.45}, 'scatter': {'color': '#696969', 'marker': 'x'}, 'axvline': {'color': '#696969', 'linestyle': '--'}, 'axhline': {'color': '#696969', 'linestyle': '--'}, 'axvspan': {'color': '#696969', 'alpha': 0.45}, 'axhspan': {'color': '#696969', 'alpha': 0.45}}

remark_plot_kwds
{'marker': 'x', 'persist': True}

xlabel_kwds
{'fontsize': 16, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False}

ylabel_kwds
{'fontsize': 16, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False}

clabel_kwds
{'fontsize': 16, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False}

title_kwds
{'fontsize': 19, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False, 'loc': 'left'}

subtitle_kwds
{'fontsize': 14.8, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False, 'loc': 'right'}

note_kwds
{'x': 0.05, 'y': 0.08, 'ha': 'left', 'va': 'top', 'width': 75, 'fontsize': 9}

caption_kwds
{'x': 0, 'y': -0.28, 'alpha': 0.7, 'ha': 'left', 'va': 'bottom', 'width': 90, 'fontsize': 11}

suptitle_kwds
{'fontsize': 19, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False}

state_kwds
{'fontsize': 48, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False, 'alpha': 0.5, 'xy': (0.988, 0.01), 'ha': 'right', 'va': 'bottom', 'xycoords': 'axes fraction'}

inline_kwds
{'fontsize': 16, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False, 'textcoords': 'offset points'}

text_inline_kwds
{'fontsize': 16, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False, 'textcoords': 'offset points'}

ref_inline_kwds
{'fontsize': 16, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False, 'textcoords': 'offset points'}

grid_inline_kwds
{'fontsize': 16, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False, 'textcoords': 'offset points'}

preset_inline_kwds
{'fontsize': 16, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False, 'textcoords': 'offset points', 'clip_on': True}

remark_inline_kwds
{'fontsize': 16, 'replacements': {'_': ' '}, 'color': '#262626', 'comma': False, 'textcoords': 'offset points', 'xytext': (-8, -5), 'ha': 'right', 'va': 'top', 'width': 38, 'persist': False}

margins_kwds
{'x': 0.03, 'y': 0.03}

adjust_text_kwds
{'precision': 1}

legend_kwds
{'fontsize': 16, 'replacements': {'_': ' '}, 'comma': False, 'labelcolor': '#262626', 'framealpha': 0.28, 'facecolor': 'whitesmoke', 'loc': 'upper left'}

colorbar_kwds
{'orientation': 'vertical'}

ticks_kwds
{'replacements': {'_': ' '}, 'comma': False, 'labelcolor': '#262626', 'length': 0, 'which': 'both', 'labelsize': 14.8}

xticks_kwds
{'replacements': {'_': ' '}, 'comma': False, 'labelcolor': '#262626', 'length': 0, 'which': 'both', 'labelsize': 14.8, 'axis': 'x'}

yticks_kwds
{'replacements': {'_': ' '}, 'comma': False, 'labelcolor': '#262626', 'length': 0, 'which': 'both', 'labelsize': 14.8, 'axis': 'y'}

cticks_kwds
{'replacements': {'_': ' '}, 'comma': False, 'labelcolor': '#262626', 'length': 0, 'which': 'both', 'labelsize': 14.8, 'num_colors': 11}

grid_kwds
{'show': True, 'alpha': 0.28, 'color': 'lightgray'}

tiles_kwds
{'style': 'toner'}

land_kwds
{'facecolor': 'whitesmoke'}

num_kwds
{'default': 1, 'bounds': (1, None), 'constant': True, 'precedence': 14}

watermark_kwds
{'x': 0.995, 'y': 0.005, 'alpha': 0.28, 'ha': 'right', 'va': 'bottom', 'fontsize': 9, 's': 'animated using ahlive'}

savefig_kwds
{'format': 'png', 'backend': 'agg', 'facecolor': 'white', 'transparent': False}

pool_kwds
{'max_workers': 2, 'scheduler': 'processes', 'progress': True}

animate_kwds
{'mode': 'I', 'loop': 0, 'pygifsicle': True}

cache_kwds
{'directory': '/home/docs/.ahlive/'}

To set, or update, defaults, specify the relevant key as a positional argument, and the desired keyword arguments.

Here, the the final and transition frames’ durations, or lag, is updated to 3 and 0.25 seconds respectively.

[16]:
import ahlive as ah

ah.config_defaults("durations", final_frame=3, transition_frames=0.1)

ah.Array([0, 1, 2], [3, 4, 5]).render()
gifsicle: warning: trivial adaptive palette (only 193 colors in source)
[16]:

Or equivalently; emphasis on the double asterisks if done this way!

import ahlive as ah

ah.config_defaults("durations", **{'final_frame': 3, 'transition_frames': 0.1})

ah.Array([0, 1, 2], [3, 4, 5]).render()

Or another way of doing this is to pass a nested dictionary; this way, multiple default keys can be configured simultaneously. The _kwds suffix is optional.

[17]:
import ahlive as ah

ah.config_defaults(**{
    "durations_kwds": dict(final_frame=5, transition_frames=0.5),
    "plot": {"scatter": dict(color="red", s=1000)}
})

ah.Array([0, 1, 2], [3, 4, 5]).render()
gifsicle: warning: trivial adaptive palette (only 255 colors in source)
[17]:

Note that some defaults require an extra layer of nesting, with the keys as the name of the chart, like for plot_kwds, ref_plot_kwds, preset_kwds.

The new defaults will persist the entire session until restarted.

[18]:
ah.Array([0, 1, 0], [6, -1, 2]).render()
[18]: