Presetting#

Awesome presets, built-in!

preset keywords#

ahlive has these keywords for presetting data:

ahlive keyword

charts

description

trail

scatter

have a line or point follow the original

race

bar, barh

move bars around by ranking

delta

bar, barh

highlight differences between adjacent bars

stacked

bar, barh

pile bars atop rather than side-by-side

morph

line, scatter, bar, barh, errorbar, area

plot all states simultaneously

morph_trail

line, scatter, errorbar, area

plot all states simultaneously plus trail

morph_stacked

bar, barh

plot all states simultaneously plus stacked

rotate

line, scatter, errorbar, area, pcolormesh, contourf, contour, hexbin, quiver, streamplot

show data on a revolving globe

scan_x

pcolormesh, contourf, contour, hexbin, quiver, streamplot

replace old data with new from left to right

scan_y

pcolormesh, contourf, contour, hexbin, quiver, streamplot

replace old data with new from top to bottom

trail#

trail allows scatter charts to leave behind footprints.

[1]:
import ahlive as ah
ah.Array([0, 1, 2], [3, 4, 5], color="red", preset='trail').render()

Hi!
I am the author of pygifsicle , which you use in this Notebook.
I hope my work has saved you some time!
I love to code, but I also need coffee. Please sponsor me on GitHub ❤️
Good luck in your coding 🍀!
- Luca

gifsicle: warning: trivial adaptive palette (only 60 colors in source)
[1]:

trail can be configured to expire in number of base states and only show a trailing line.

[2]:
import ahlive as ah
arr = ah.Array([0, 1, 2], [0, 1, 0], chart='scatter', preset='trail')
arr.config('preset', chart='line', expire=1).render()
gifsicle: warning: trivial adaptive palette (only 160 colors in source)
[2]:

race#

race will yield bar chart races as long as there is more than one item overlaid. It’s also possible to customize bar_label and ascending.

[3]:
import ahlive as ah
import pandas as pd
x = ['a', 'a', 'b', 'b']
y =  [4, 5, 3, 6]
df = pd.DataFrame({'x': x, 'y': y})
ah.DataFrame(
    df, 'x', 'y', label='x', inline_labels='y',
    chart='bar', preset='race'
).config(
    'preset', bar_label=False, ascending=True
).render()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: len() of unsized object
Exception ignored in: 'pandas._libs.lib.is_string_array'
Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/pandas-2.0.1-py3.11-linux-x86_64.egg/pandas/core/dtypes/common.py", line 1724, in is_all_strings
    and lib.infer_dtype(value, skipna=False) == "string"
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: len() of unsized object
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: len() of unsized object
Exception ignored in: 'pandas._libs.lib.is_string_array'
Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/pandas-2.0.1-py3.11-linux-x86_64.egg/pandas/core/dtypes/common.py", line 1724, in is_all_strings
    and lib.infer_dtype(value, skipna=False) == "string"
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: len() of unsized object
[3]:

delta#

delta will highlight the differences in values for bar charts.

[4]:
import ahlive as ah
import pandas as pd
x = ['a', 'a', 'b', 'b']
y =  [4, 5, 3, 8]
df = pd.DataFrame({'x': x, 'y': y})
ah.DataFrame(
    df, 'x', 'y', label='x', inline_labels='y',
    chart='barh', preset='delta'
).render()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: len() of unsized object
Exception ignored in: 'pandas._libs.lib.is_string_array'
Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/pandas-2.0.1-py3.11-linux-x86_64.egg/pandas/core/dtypes/common.py", line 1724, in is_all_strings
    and lib.infer_dtype(value, skipna=False) == "string"
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: len() of unsized object
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: len() of unsized object
Exception ignored in: 'pandas._libs.lib.is_string_array'
Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/pandas-2.0.1-py3.11-linux-x86_64.egg/pandas/core/dtypes/common.py", line 1724, in is_all_strings
    and lib.infer_dtype(value, skipna=False) == "string"
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: len() of unsized object
---------------------------------------------------------------------------
_RemoteTraceback                          Traceback (most recent call last)
_RemoteTraceback:
"""
Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/concurrent/futures/process.py", line 256, in _process_worker
    r = call_item.fn(*call_item.args, **call_item.kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/ahlive-1.0.4.post1+dirty-py3.11.egg/ahlive/animation.py", line 1769, in _draw_frame
    self._draw_subplot(state_ds, ax, canvas_kwds)
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/ahlive-1.0.4.post1+dirty-py3.11.egg/ahlive/animation.py", line 1683, in _draw_subplot
    base_mappable = self._process_base_vars(state_ds, ax, mpl_texts)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/ahlive-1.0.4.post1+dirty-py3.11.egg/ahlive/animation.py", line 1105, in _process_base_vars
    self._plot_deltas(
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/ahlive-1.0.4.post1+dirty-py3.11.egg/ahlive/animation.py", line 546, in _plot_deltas
    ax.errorbar(x_centers, y_centers, **preset_kwds)
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/matplotlib/__init__.py", line 1423, in inner
    return func(ax, *map(sanitize_sequence, args), **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/matplotlib/axes/_axes.py", line 3595, in errorbar
    raise ValueError(
ValueError: 'xerr' must not contain negative values
"""

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
Cell In[4], line 9
      4 y =  [4, 5, 3, 8]
      5 df = pd.DataFrame({'x': x, 'y': y})
      6 ah.DataFrame(
      7     df, 'x', 'y', label='x', inline_labels='y',
      8     chart='barh', preset='delta'
----> 9 ).render()

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/ahlive-1.0.4.post1+dirty-py3.11.egg/ahlive/animation.py:2042, in Animation.render(self)
   2040     return out_obj
   2041 except Exception as e:
-> 2042     raise e
   2043 finally:
   2044     if os.path.exists(self_copy._temp_file):

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/ahlive-1.0.4.post1+dirty-py3.11.egg/ahlive/animation.py:2035, in Animation.render(self)
   2032         warnings.warn("durations is not supported with fps set")
   2033     pop(ds, "duration")
-> 2035 buf_list = self_copy._create_frames(data, canvas_kwds)
   2036 out_obj, ext = self_copy._write_rendered(buf_list, durations, canvas_kwds)
   2038 if (stitch or static) and show:

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/ahlive-1.0.4.post1+dirty-py3.11.egg/ahlive/animation.py:1841, in Animation._create_frames(self, data, canvas_kwds)
   1839 buf_list = []
   1840 for job in jobs:
-> 1841     buf = job.result()
   1842     if buf is not None:
   1843         buf_list.append(buf)

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/concurrent/futures/_base.py:449, in Future.result(self, timeout)
    447     raise CancelledError()
    448 elif self._state == FINISHED:
--> 449     return self.__get_result()
    451 self._condition.wait(timeout)
    453 if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/concurrent/futures/_base.py:401, in Future.__get_result(self)
    399 if self._exception:
    400     try:
--> 401         raise self._exception
    402     finally:
    403         # Break a reference cycle with the exception in self._exception
    404         self = None

ValueError: 'xerr' must not contain negative values

stacked#

Create stacked bar charts instead of the default side by side.

[5]:
import ahlive as ah

x = ["X", "X"]
y1 = [1, 0]
y2 = [2, 0]

(ah.Array(x, y1, label="A", preset="stacked", chart="bar", revert="boomerang") *
 ah.Array(x, y2, label="B", preset="stacked", chart="bar", ylims=(0, 3))
).render()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: len() of unsized object
Exception ignored in: 'pandas._libs.lib.is_string_array'
Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/pandas-2.0.1-py3.11-linux-x86_64.egg/pandas/core/dtypes/common.py", line 1724, in is_all_strings
    and lib.infer_dtype(value, skipna=False) == "string"
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: len() of unsized object
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: len() of unsized object
Exception ignored in: 'pandas._libs.lib.is_string_array'
Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/pandas-2.0.1-py3.11-linux-x86_64.egg/pandas/core/dtypes/common.py", line 1724, in is_all_strings
    and lib.infer_dtype(value, skipna=False) == "string"
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: len() of unsized object
/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/ahlive-1.0.4.post1+dirty-py3.11.egg/ahlive/data.py:425: UserWarning: Multiple items found, you may want to use the 'morph' preset
gifsicle: warning: trivial adaptive palette (only 74 colors in source)
[5]:

morph#

The initial states are batched together and each item gets morphed into a new state, grouped by group as the new items.

[6]:
import ahlive as ah

x = [0, 1, 2, 3]
y1 = [4, 5, 6, 7]
y2 = [2, 10, 15, 20]

(
    ah.Array(x, y1, group="A") *  # item 1, state 1
    ah.Array(x, y2, group="A") *  # item 1, state 2
    ah.Array(x, y2, group="B") *  # item 2, state 1
    ah.Array(x, y1, group="B", chart="line", preset="morph", fps=30, revert="boomerang")  # item 2, state 2
).render()
[6]:

morph_trail#

Same as morph with a footprint.

[7]:
import ahlive as ah

x = [0, 1, 2]
y1 = [0, 36, 0]
y2 = [0, 72, 0]
y3 = [0, 144, 0]

(
    ah.Array(x, y1, group="a") *
    ah.Array(x, y3, group="a") *
    ah.Array(x, y2, group="b") *
    ah.Array(x, y1, group="b", preset="morph_trail", chart="line", revert="boomerang")
).config(
    "preset", color="gray"
).render()
[7]:

morph_stacked#

Same as morph, but for bar and barh charts: stacking separate groups.

[8]:
import ahlive as ah

x = [0, 1]
y1 = [0, 0.8]
y2 = [1, 0.2]

(
    ah.Array(x, y1, group="A") *  # item 1, state 1
    ah.Array(x, y2, group="A") *  # item 1, state 2
    ah.Array(x, y2, group="B") *  # item 2, state 1
    ah.Array(x, y1, group="B", preset="morph_stacked", ylims="fixed",
             fps=30, revert="boomerang", chart="barh")  # item 2, state 2
).render()
gifsicle: warning: trivial adaptive palette (only 115 colors in source)
[8]:

rotate#

rotate will yie ld a rotating globe for gridded charts. Geostationary views of the world can be achieved through worldwide=True, and the start and end of the central longitudes can be specified as a tuple in central_lon.

[9]:
import xarray as xr
import ahlive as ah
ds = xr.tutorial.open_dataset('air_temperature').isel(time=slice(0, 8))
ah.Dataset(
    ds, 'lon', 'lat', 'air', crs='platecarree', preset='rotate',
    central_lon=(-90, -110), worldwide=True
).render()
/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/ahlive-1.0.4.post1+dirty-py3.11.egg/ahlive/animation.py:1759: UserWarning: Failed to render state=2 due to [Errno 17] File exists: '/home/docs/.local/share/cartopy/shapefiles/natural_earth/physical'!
  warnings.warn(error_msg)
/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_physical/ne_110m_coastline.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/latest/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_physical/ne_110m_coastline.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
[9]:

scan_x#

For each state, scan_x will scan left to right, replacing the old state’s value with the new state, and the scan can be reverted with traceback.

[10]:
import xarray as xr
import ahlive as ah
ds = xr.tutorial.open_dataset('air_temperature').isel(time=[0, 120])
ah.Dataset(
    ds, 'lon', 'lat', 'air', state_labels='time',
    crs='platecarree', preset='scan_x', fps=30, revert="traceback"
).render()
[10]:

scan_y#

There’s an equivalent scan_y which goes from top to down.