Serializing#

For ahlive to work, data must be serialized into a standard format.

serializing classes#

ahlive incorporates these classes to achieve this:

ahlive class

input data type

use cases

ah.Array

collections.Iterable

for single, unlabeled 1D arrays

ah.DataFrame

pd.DataFrame

for multiple, labeled 1D arrays

ah.Array2D

np.ndarray

for single, unlabeled 2D arrays

ah.Dataset

xr.Dataset

for multiple, labeled 2D arrays

ahlive.Array#

ah.Array is the basic building block for building an animation in ahlive.

To instantiate, xs and ys are often specified as positional arguments; they are, respectively, the horizontal and vertical coordinates of a single data point. If ys is not specified, ys is set to xs, and xs is set as an incremental range.

label is a common keyword argument for instantiation which yields a legend label in the output animation. Note, the legend will not show automatically if there is only a single item so legend=True must be specified.

[1]:
import ahlive as ah
x = [1, 2, 3]
y = [40, 50, 60]
ah_arr = ah.Array(x, y, label='Array', legend=True)
print(ah_arr)
ah_arr.render()
<ahlive.Data>
Subplot:         (1, 1)
Dimensions:      (item: 1, state: 3)
Data variables:
    x        (item, state) float64 1.0 2.0 3.0
    y        (item, state) float64 40.0 50.0 60.0
    chart    (item) <U7 'scatter'
    label    (item, state) <U5 'Array' 'Array' 'Array'
    group    (item) <U1 ''
Attributes (1/49):
    legend_kwds  {'show': True}


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

The desired type of plot can be specified; e.g. chart='bar'

ahlive.DataFrame#

ah.DataFrame builds off ah.Array, but utilize column names.

To instantiate, df is required on top of xs and ys. However, unlike ah.Array, column names from the pd.DataFrame are passed, i.e. not the actual data values– likewise for label.

An advantage of using ah.DataFrame instead of ah.Array is automatic labeling from column names.

[2]:
import pandas as pd
import ahlive as ah
x = [1, 2, 3]
y = [40, 50, 60]
df = pd.DataFrame({'the_x_name': x, 'y_axis': y})
ah_df = ah.DataFrame(df, 'the_x_name', 'y_axis')
print(ah_df)
ah_df.render()
<ahlive.Data>
Subplot:         (1, 1)
Dimensions:      (item: 1, state: 3)
Data variables:
    x        (item, state) float64 1.0 2.0 3.0
    y        (item, state) float64 40.0 50.0 60.0
    chart    (item) <U7 'scatter'
    label    (item, state) <U1 '' '' ''
    group    (item) <U1 ''
Attributes (2/49):
    xlabel_kwds  {'xlabel': 'The_X_Name'}
    ylabel_kwds  {'ylabel': 'Y_Axis'}


gifsicle: warning: trivial adaptive palette (only 52 colors in source)
[2]:

Another advantage is if the label column contains multiple unique values; the unique values will be grouped and joined separately.

[3]:
import pandas as pd
import ahlive as ah
x = [1, 2, 3, 4]
y = [40, 50, 60, 70]
labels = ['a', 'a', 'b', 'b']
df = pd.DataFrame({'the_x_name': x, 'y_axis': y, 'label': labels})
display(df)
ah_df = ah.DataFrame(df, 'the_x_name', 'y_axis', label='label')
print(ah_df)
ah_df.render()
the_x_name y_axis label
0 1 40 a
1 2 50 a
2 3 60 b
3 4 70 b
<ahlive.Data>
Subplot:         (1, 1)
Dimensions:      (item: 2, state: 2)
Data variables:
    x        (item, state) float64 1.0 2.0 3.0 4.0
    y        (item, state) float64 40.0 50.0 60.0 70.0
    chart    (item) <U7 'scatter' 'scatter'
    label    (item, state) object 'a' 'a' 'b' 'b'
    group    (item) <U1 '' ''
Attributes (2/49):
    xlabel_kwds  {'xlabel': 'The_X_Name'}
    ylabel_kwds  {'ylabel': 'Y_Axis'}


gifsicle: warning: trivial adaptive palette (only 74 colors in source)
[3]:

ah.DataFrame expects a tidy format df:

  1. Each variable forms a column.

  2. Each observation forms a row.

  3. Each type of observational unit forms a table.

If the input pd.DataFrame is not tidy, try using pd.melt.

ahlive.Array2D#

ah.Array2D is much like ah.Array but for gridded, 2D arrays.

In addition to xs and ys, ah.Array2D requires cs which is a 2D array used for colormapping.

[4]:
import numpy as np
import ahlive as ah
x = np.arange(0, 3)
y = np.arange(3, 6)
c = np.random.random((2, len(y), len(x)))
ah_arr2d = ah.Array2D(x, y, c)
ah_arr2d.render()
gifsicle: warning: trivial adaptive palette (only 65 colors in source)
[4]:

ahlive.Dataset#

ah.Dataset is the ah.Array2D version of ah.DataFrame.

ah.Dataset requires a total of four positional arguments: ds, xs, ys, cs. Similar to ah.DataFrame, these arguments should be labels from the xr.Dataset, not actual arrays.

[5]:
import numpy as np
import xarray as xr
import ahlive as ah
x = np.arange(0, 3)
y = np.arange(3, 6)
c = np.random.random((2, len(y), len(x)))
ds = xr.Dataset()
ds['color_data'] = xr.DataArray(
    c, coords={'the_x_name': x, 'y_axis': y},
    dims=('time_dim', 'y_axis', 'the_x_name'))
ah_ds = ah.Dataset(ds, 'the_x_name', 'y_axis', 'color_data')
print(ah_ds)
ah_ds.render()
<ahlive.Data>
Subplot:         (1, 1)
Dimensions:      (grid_item: 1, state: 2, grid_y: 3, grid_x: 3)
Data variables:
    grid_c      (grid_item, state, grid_y, grid_x) float64 0.5276 ... 0.455
    grid_chart  (grid_item) <U10 'pcolormesh'
    grid_label  (grid_item, state) <U1 '' ''
    grid_group  (grid_item) <U1 ''
Attributes (2/50):
    xlabel_kwds  {'xlabel': 'The_X_Name'}
    ylabel_kwds  {'ylabel': 'Y_Axis'}


gifsicle: warning: trivial adaptive palette (only 52 colors in source)
[5]:

If you have an xr.Dataset with 1D arrays for data variables, do not use ah.Dataset!

Instead, first convert to a pd.DataFrame using ds.to_dataframe() then use ah.DataFrame to serialize the data.

ahlive.Data#

The aforementioned classes all inherit from the internal class, ah.Data.

It’s essentially a higher level dict. The dict is accessible through the data property.

[6]:
import ahlive as ah
ah.Array([0, 1, 2], [3, 4, 5]).data
[6]:
{(1,
  1): <xarray.Dataset>
 Dimensions:  (item: 1, state: 3)
 Coordinates:
   * item     (item) int64 1
   * state    (state) int64 1 2 3
 Data variables:
     x        (item, state) float64 0.0 1.0 2.0
     y        (item, state) float64 3.0 4.0 5.0
     chart    (item) <U7 'scatter'
     label    (item, state) <U1 '' '' ''
     group    (item) <U1 ''
 Attributes: (12/49)
     plot_kwds:           {}
     grid_plot_kwds:      {}
     ref_plot_kwds:       {}
     configured:          {'remark_plot': True, 'remark_inline': True, 'colorb...
     remark_plot_kwds:    {}
     remark_inline_kwds:  {}
     ...                  ...
     land_kwds:           {}
     lakes_kwds:          {}
     ocean_kwds:          {}
     rivers_kwds:         {}
     states_kwds:         {}
     tiles_kwds:          {}}

The keys of the dict store the subplots’ positions as a (row, col) tuple.

[7]:
import ahlive as ah
arr_dict = ah.Array([0, 1, 2], [3, 4, 5]).data
print(arr_dict.keys())
dict_keys([(1, 1)])

The values of the dict store the serialized input data as xr.Datasets.

[8]:
import ahlive as ah
arr_dict = ah.Array([0, 1, 2], [3, 4, 5]).data
print(arr_dict.values())
dict_values([<xarray.Dataset>
Dimensions:  (item: 1, state: 3)
Coordinates:
  * item     (item) int64 1
  * state    (state) int64 1 2 3
Data variables:
    x        (item, state) float64 0.0 1.0 2.0
    y        (item, state) float64 3.0 4.0 5.0
    chart    (item) <U7 'scatter'
    label    (item, state) <U1 '' '' ''
    group    (item) <U1 ''
Attributes: (12/49)
    plot_kwds:           {}
    grid_plot_kwds:      {}
    ref_plot_kwds:       {}
    configured:          {'remark_plot': True, 'remark_inline': True, 'colorb...
    remark_plot_kwds:    {}
    remark_inline_kwds:  {}
    ...                  ...
    land_kwds:           {}
    lakes_kwds:          {}
    ocean_kwds:          {}
    rivers_kwds:         {}
    states_kwds:         {}
    tiles_kwds:          {}])

To access individual xr.Datasets, simply specify the subplot’s position.

[9]:
import ahlive as ah
arr_dict = ah.Array([0, 1, 2], [3, 4, 5]).data
print(arr_dict[1, 1])
<xarray.Dataset>
Dimensions:  (item: 1, state: 3)
Coordinates:
  * item     (item) int64 1
  * state    (state) int64 1 2 3
Data variables:
    x        (item, state) float64 0.0 1.0 2.0
    y        (item, state) float64 3.0 4.0 5.0
    chart    (item) <U7 'scatter'
    label    (item, state) <U1 '' '' ''
    group    (item) <U1 ''
Attributes: (12/49)
    plot_kwds:           {}
    grid_plot_kwds:      {}
    ref_plot_kwds:       {}
    configured:          {'remark_plot': True, 'remark_inline': True, 'colorb...
    remark_plot_kwds:    {}
    remark_inline_kwds:  {}
    ...                  ...
    land_kwds:           {}
    lakes_kwds:          {}
    ocean_kwds:          {}
    rivers_kwds:         {}
    states_kwds:         {}
    tiles_kwds:          {}

You can also manually edit the xr.Dataset after calling finalize.

[10]:
import ahlive as ah
arr_dict = ah.Array([0, 1, 2], [3, 4, 5]).finalize().data
for rowcol, ds in arr_dict.items():
    ds['x'] += 10
print(arr_dict)
{(1, 1): <xarray.Dataset>
Dimensions:   (item: 1, state: 41)
Coordinates:
  * item      (item) int64 1
  * state     (state) int64 1 2 3 4 5 6 7 8 9 10 ... 33 34 35 36 37 38 39 40 41
Data variables:
    x         (item, state) float64 10.0 10.0 10.0 10.02 ... 12.0 12.0 12.0 12.0
    y         (item, state) float64 3.0 3.001 3.005 3.016 ... 4.999 5.0 5.0
    chart     (item) <U7 'scatter'
    label     (item, state) <U1 '' '' '' '' '' '' '' '' ... '' '' '' '' '' '' ''
    group     (item) <U1 ''
    xlim0     (state) float64 -0.06 -0.06 -0.06 -0.06 ... -0.06 -0.06 -0.06
    xlim1     (state) float64 2.06 2.06 2.06 2.06 2.06 ... 2.06 2.06 2.06 2.06
    ylim0     (state) float64 2.94 2.94 2.94 2.94 2.94 ... 2.94 2.94 2.94 2.94
    ylim1     (state) float64 5.06 5.06 5.06 5.06 5.06 ... 5.06 5.06 5.06 5.06
    duration  (state) float64 0.5 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 1.05 0.0
Attributes: (12/51)
    plot_kwds:           {}
    grid_plot_kwds:      {}
    ref_plot_kwds:       {}
    configured:          {'remark_plot': True, 'remark_inline': True, 'colorb...
    remark_plot_kwds:    {}
    remark_inline_kwds:  {}
    ...                  ...
    ocean_kwds:          {}
    rivers_kwds:         {}
    states_kwds:         {}
    tiles_kwds:          {}
    base_kwds:           {'xticks': 0.1, 'yticks': 0.4}
    finalized:           True}