Quick Start#

It’s easy as 1 - 2 - 3!

1 - import package#

The standard is to abbreviate ahlive as ah.

[1]:
import ahlive as ah

2 - load data#

Here, CO2 concentrations data is fetched.

[2]:
df = ah.open_dataset("annual_co2", names=["year", "co2", "uncertainty"], verbose=True)
display(df)
ANNUAL CO2

Source: NOAA ESRL
https://www.esrl.noaa.gov/

Description: The carbon dioxide data on Mauna Loa constitute the longest record of direct measurements of CO2 in the atmosphere. They were started by C. David Keeling of the Scripps Institution of Oceanography in March of 1958 at a facility of the National Oceanic and Atmospheric Administration [Keeling, 1976]. NOAA started its own CO2 measurements in May of 1974, and they have run in parallel with those made by Scripps since then [Thoning, 1989].

Data: https://www.esrl.noaa.gov/gmd/webdata/ccgg/trends/co2/co2_annmean_mlo.txt

year co2 uncertainty
0 1959 315.98 0.12
1 1960 316.91 0.12
2 1961 317.64 0.12
3 1962 318.45 0.12
4 1963 318.99 0.12
... ... ... ...
59 2018 408.72 0.12
60 2019 411.66 0.12
61 2020 414.24 0.12
62 2021 416.45 0.12
63 2022 418.56 0.12

64 rows × 3 columns

3 - generate animation#

Simply input the dataframe, df and map the dataframe’s column names to the plot’s axes, xs and ys.

[3]:
ah.DataFrame(
    df,
    xs="year",
    ys="co2",
).render()
gifsicle: warning: trivial adaptive palette (only 234 colors in source)
[3]:

add refinements#

In just three steps, an animation was output, but don’t stop there! Take advantage of the features supported in ahlive, conveniently accessible by keywords!

[4]:
import ahlive as ah

df, meta = ah.open_dataset(
    "annual_co2",
    names=["year", "co2", "uncertainty"],
    index_col="year",
    return_meta=True
)
df_cummax = df.cummax()

ah.DataFrame(
    df,
    # map columns to axes
    xs="year",
    ys="co2",

    # add dynamic labels
    inline_labels="co2",
    state_labels="year",

    # add static labels
    title=meta["label"].title(),
    ylabel="CO2 Concentrations [PPM]",
    note=meta["base_url"],
    caption=meta["description"].split("\n")[0].title(),

    # adjust dynamic limits
    ylim1s="fixed",
    xlim1s="explore_5",

    # adjust figure
    figsize=(13, 7),
    ymargins=0.1
).reference(
    y0s=df_cummax["co2"],
    inline_labels=df_cummax["co2"],
    inline_locs=1000
).remark(
    "Intergovernmental Panel on Climate Change (IPCC) is established",
    xs=1988
).remark(
    "CO2 levels surpasses 400 PPM for the first time in recorded history",
    xs=2016  # based off Scripp's records
).config(**{
    "ref_inline": dict(prefix="Record max of ", suffix=" PPM", ha="center"),
    "inline": dict(suffix=" PPM"),
    "caption": dict(width=120)
}).render()
/home/docs/checkouts/readthedocs.org/user_builds/ahlive/conda/main/lib/python3.11/site-packages/ahlive-1.0.3.post6+dirty-py3.11.egg/ahlive/easing.py:193: FutureWarning: In the future `np.object` will be defined as the corresponding NumPy scalar.
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[4], line 48
      3 df, meta = ah.open_dataset(
      4     "annual_co2",
      5     names=["year", "co2", "uncertainty"],
      6     index_col="year",
      7     return_meta=True
      8 )
      9 df_cummax = df.cummax()
     11 ah.DataFrame(
     12     df,
     13     # map columns to axes
     14     xs="year",
     15     ys="co2",
     16
     17     # add dynamic labels
     18     inline_labels="co2",
     19     state_labels="year",
     20
     21     # add static labels
     22     title=meta["label"].title(),
     23     ylabel="CO2 Concentrations [PPM]",
     24     note=meta["base_url"],
     25     caption=meta["description"].split("\n")[0].title(),
     26
     27     # adjust dynamic limits
     28     ylim1s="fixed",
     29     xlim1s="explore_5",
     30
     31     # adjust figure
     32     figsize=(13, 7),
     33     ymargins=0.1
     34 ).reference(
     35     y0s=df_cummax["co2"],
     36     inline_labels=df_cummax["co2"],
     37     inline_locs=1000
     38 ).remark(
     39     "Intergovernmental Panel on Climate Change (IPCC) is established",
     40     xs=1988
     41 ).remark(
     42     "CO2 levels surpasses 400 PPM for the first time in recorded history",
     43     xs=2016  # based off Scripp's records
     44 ).config(**{
     45     "ref_inline": dict(prefix="Record max of ", suffix=" PPM", ha="center"),
     46     "inline": dict(suffix=" PPM"),
     47     "caption": dict(width=120)
---> 48 }).render()

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/main/lib/python3.11/site-packages/ahlive-1.0.3.post6+dirty-py3.11.egg/ahlive/animation.py:1998, in Animation.render(self)
   1997 def render(self):
-> 1998     self_copy = self.finalize()
   1999     try:
   2000         data = self_copy.data

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/main/lib/python3.11/site-packages/ahlive-1.0.3.post6+dirty-py3.11.egg/ahlive/data.py:1417, in Data.finalize(self)
   1415 ds = self_copy._precompute_base(ds, chart)  # must be after config chart
   1416 ds = self_copy._add_geo_tiles(ds)  # before interp
-> 1417 ds = self_copy._interp_dataset(ds)
   1418 ds = self_copy._add_geo_transforms(ds, chart)  # after interp
   1419 ds = self_copy._add_geo_features(ds)

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/main/lib/python3.11/site-packages/ahlive-1.0.3.post6+dirty-py3.11.egg/ahlive/data.py:1115, in Data._interp_dataset(self, ds)
   1114 def _interp_dataset(self, ds):
-> 1115     ds = ds.map(self.interpolate, keep_attrs=True)
   1117     if "s" in ds:
   1118         ds["s"] = fillna(ds["s"].where(ds["s"] >= 0), how="both")

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/main/lib/python3.11/site-packages/xarray-2023.4.2-py3.11.egg/xarray/core/dataset.py:5964, in Dataset.map(self, func, keep_attrs, args, **kwargs)
   5962 if keep_attrs is None:
   5963     keep_attrs = _get_keep_attrs(default=False)
-> 5964 variables = {
   5965     k: maybe_wrap_array(v, func(v, *args, **kwargs))
   5966     for k, v in self.data_vars.items()
   5967 }
   5968 if keep_attrs:
   5969     for k, v in variables.items():

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/main/lib/python3.11/site-packages/xarray-2023.4.2-py3.11.egg/xarray/core/dataset.py:5965, in <dictcomp>(.0)
   5962 if keep_attrs is None:
   5963     keep_attrs = _get_keep_attrs(default=False)
   5964 variables = {
-> 5965     k: maybe_wrap_array(v, func(v, *args, **kwargs))
   5966     for k, v in self.data_vars.items()
   5967 }
   5968 if keep_attrs:
   5969     for k, v in variables.items():

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/main/lib/python3.11/site-packages/ahlive-1.0.3.post6+dirty-py3.11.egg/ahlive/easing.py:79, in Easing.interpolate(self, da, name)
     77 array_dtype = array.dtype
     78 if name in ["duration", "remark", "xerr", "yerr"] and not is_errorbar_morph:
---> 79     result = self._interp_first(
     80         array, num_states, num_steps, num_items, num_result, name
     81     )
     82 elif interp == "fill" or name.endswith(
     83     ("zoom", "discrete_trail", "morph_trail", "tick_label", "bar_label")
     84 ):
     85     result = self._interp_fill(array, num_states, num_steps, name)

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/main/lib/python3.11/site-packages/ahlive-1.0.3.post6+dirty-py3.11.egg/ahlive/easing.py:193, in Easing._interp_first(self, array, num_states, num_steps, num_items, num_result, name)
    191 if is_str(array):
    192     fill = ""
--> 193     dtype = np.object
    194 else:
    195     fill = 0.0

File ~/checkouts/readthedocs.org/user_builds/ahlive/conda/main/lib/python3.11/site-packages/numpy/__init__.py:305, in __getattr__(attr)
    300     warnings.warn(
    301         f"In the future `np.{attr}` will be defined as the "
    302         "corresponding NumPy scalar.", FutureWarning, stacklevel=2)
    304 if attr in __former_attrs__:
--> 305     raise AttributeError(__former_attrs__[attr])
    307 # Importing Tester requires importing all of UnitTest which is not a
    308 # cheap import Since it is mainly used in test suits, we lazy import it
    309 # here to save on the order of 10 ms of import time for most users
    310 #
    311 # The previous way Tester was imported also had a side effect of adding
    312 # the full `numpy.testing` namespace
    313 if attr == 'testing':

AttributeError: module 'numpy' has no attribute 'object'.
`np.object` was a deprecated alias for the builtin `object`. To avoid this error in existing code, use `object` by itself. Doing this will not modify any behavior and is safe.
The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at:
    https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations

explore datasets#

See, it’s that easy to get started. Don’t have a dataset readily available? No worries!

ahlive has a bunch of built-in datasets ready to use; learn more at Fetching.