def test_add_xy01_limits_ylim1s(direction, limit, padding): if limit.startswith("zero"): expected = 0 elif limit.startswith("fixed"): expected = 6 elif limit.startswith("follow"): expected = np.array([5.0, 6, 5]) elif limit.startswith("explore"): expected = np.array([5.0, 6, 6]) if padding is not None: expected += padding limit = f"{limit}_{padding}" ah_array1 = ah.Array([0, 1, 0], [3, 4, 5], ylim1s=limit, ymargins=0, frames=1) ah_array2 = ah.Array([-1, 1, -2], [5, 6, -5]) ah_objs = [ah_array1, ah_array2] if direction == "backward": ah_objs = ah_objs[::-1] ah_obj = ah.merge(ah_objs).finalize() ds = ah_obj[1, 1] actual = ds["ylim1"].values assert np.isclose(actual, expected).all()
def test_add_xy01_limits_xlim0s(direction, limit, padding): # TODO: test datetimes, strings if limit.startswith("zero"): expected = 0 elif limit.startswith("fixed"): expected = -2 elif limit.startswith("follow"): expected = np.array([-1.0, 1, -2]) elif limit.startswith("explore"): expected = np.array([-1.0, -1, -2]) if padding is not None: expected -= padding limit = f"{limit}_{padding}" ah_array1 = ah.Array([0, 1, 0], [3, 4, 5], xlim0s=limit, xmargins=0, frames=1) ah_array2 = ah.Array([-1, 1, -2], [5, 6, -5]) ah_objs = [ah_array1, ah_array2] if direction == "backward": ah_objs = ah_objs[::-1] ah_obj = ah.merge(ah_objs).finalize() ds = ah_obj[1, 1] actual = ds["xlim0"].values assert np.isclose(actual, expected).all()
def test_remark_overlay(): x = np.array([0, 1, 1, 3]) y1 = [4, 5, 6, 7] y2 = [8, 9, 10, 11] ah_obj = ah.Array(x, y1) * ah.Array(x, y2) ah_obj = ah_obj.remark("abc", ys=[4, 11]) ds = ah_obj[1, 1] remarks = ds["remark"] assert remarks.isel(item=0, state=0).item() == "abc" assert remarks.isel(item=1, state=-1).item() == "abc"
def test_morph_stacked(): ah_obj = (ah.Array([0, 1, 2], [5, 6, 7]) * ah.Array([0, 1, 2], [5, 8, 9]) * ah.Array([0, 1, 2], [3, 4, 10], preset="morph_trail", chart="line", color="red")).finalize() ds = ah_obj[1, 1] assert "x_morph_trail" in ds.data_vars assert "y_morph_trail" in ds.data_vars assert (ds["group"] == "_morph_group").all() assert (ds["color"] == "red").all()
def test_pie_chart(): ah_obj = (ah.Array([0, 1, 2], label="a", chart="pie", frames=1) * ah.Array([1, 0, 1], chart="pie")).finalize() ds = ah_obj[1, 1] assert (ds["group"] == "_pie_group").all() assert (pd.unique(ds["labels"].values.ravel()) == ["a", ""]).all() assert ds["item"].values.tolist() == [1, 2] assert ds["state"].values.tolist() == [1, 2, 3] np.testing.assert_almost_equal(ds["y"].values.ravel(), np.array([0, 1, 0.6666666, 1, 0, 0.3333333])) # normalize
def test_stacked_fixed_limit(): x = [0, 0] y1 = [1, 0] y2 = [2, 0] ah_obj = (ah.Array( x, y1, label="A", preset="stacked", chart="bar", revert="boomerang") * ah.Array( x, y2, label="B", preset="stacked", chart="bar", ylims="fixed")).finalize() ds = ah_obj[1, 1] np.testing.assert_almost_equal(ds["ylim0"].values, 0) np.testing.assert_almost_equal(ds["ylim1"].values, 2)
def test_config_morph_chart(how, chart): x = [0, 1, 2, 3, 4] y1 = [4, 5, 6, 7, 8] y2 = [8, 4, 2, 3, 4] ah_obj = (ah.Array(x, y1, preset="morph", chart=chart, group="A") * ah.Array(x, y2, chart=chart, group="A") * ah.Array(x, y2, chart=chart, group="B")) if how == "even": ah_obj *= ah.Array(x, y1, chart=chart, group="B") ah_obj = ah_obj.finalize() ds = ah_obj[1, 1] assert len(ds["item"] == 2) assert len(ds["batch"] == 5) assert len(ds["state"] == 30) assert (ds["group"].values == ["B", "A"]).all()
def test_add_animate_kwds_int(): ah_obj = ah.Array([0, 1, 2], [3, 4, 5], animate=1).finalize() attrs = ah_obj.attrs animate_kwds = attrs["animate_kwds"] assert animate_kwds["states"] == 1 assert animate_kwds["stitch"] assert animate_kwds["static"]
def test_geo_default_coastline(crs, tiles): ah_obj = ah.Array([0, 1, 2], [3, 4, 5], crs=crs, tiles=tiles).finalize() ds = ah_obj[1, 1] if tiles: assert len(ds.attrs["coastline_kwds"]) == 0 elif crs: assert len(ds.attrs["coastline_kwds"]) == 1
def test_precompute_base_ticks_datetime(): ah_obj = ah.Array(pd.date_range("2021-01-01", "2021-01-03"), [5, 6, 7]).finalize() attrs = ah_obj.attrs attrs["xticks_kwds"]["is_str"] = True attrs["base_kwds"]["xticks"] == np.datetime64("2021-01-01") attrs["xticks_kwds"]["is_datetime"] = True
def test_add_color_kwds_cticks(): cticks = [0, 5, 6, 7, 8, 9] ah_obj = ah.Array([0, 1, 2], [3, 4, 5], cs=[6, 7, 8], cticks=cticks).finalize() attrs = ah_obj.attrs assert attrs["cticks_kwds"]["ticks"] == cticks assert attrs["colorbar_kwds"]["show"]
def test_add_animate_kwds_bool(animate): ah_obj = ah.Array([0, 1, 2], [3, 4, 5], animate=animate).finalize() attrs = ah_obj.attrs animate_kwds = attrs["animate_kwds"] assert animate_kwds["states"] is None assert animate_kwds["stitch"] == animate assert not animate_kwds["static"]
def test_precompute_base_labels_datetime(): ah_obj = ah.Array( [1, 2, 3], [5, 6, 7], state_labels=pd.date_range("2021-01-01", "2021-01-03"), ).finalize() attrs = ah_obj.attrs float(attrs["base_kwds"]["state"]) == 86400000000000
def test_add_geo_tiles(xlim0s, tiles, zoom): ah_obj = (ah.Array([0, 1, 2], [3, 4, 5], xlim0s=xlim0s, tiles=tiles, zoom=zoom).finalize()).finalize() ds = ah_obj.data[1, 1] zoom = np.repeat(zoom or 7, len(ds["state"])) np.testing.assert_almost_equal(ds["zoom"].values, zoom)
def test_add_animate_kwds_slice(): ah_obj = ah.Array([0, 1, 2], [3, 4, 5], animate=slice(1, 10)).finalize() attrs = ah_obj.attrs animate_kwds = attrs["animate_kwds"] states = np.arange(1, 10) assert (animate_kwds["states"] == states).all() assert animate_kwds["stitch"] assert not animate_kwds["static"]
def test_labels(key, label): label_kwd = {key: label} ah_obj = ah.Array([0, 1, 2], [3, 4, 5], **label_kwd).finalize() if key != "label": sub_key = "text" if key == "clabel" else key assert ah_obj[1, 1].attrs[f"{key}_kwds"][sub_key] == label else: assert np.unique(ah_obj[1, 1][key].values) == [label]
def test_config_grid_axes(chart): ah_obj = ah.Array([0, 1], [2, 3], chart=chart).finalize() if chart == "barh": axis = "x" elif chart == "bar": axis = "y" else: axis = "both" ah_obj[1, 1].attrs["grid_kwds"]["axis"] == axis
def test_add_color_kwds_num_colors(num_colors): ah_obj = (ah.Array([0, 1, 2], [3, 4, 5], cs=[6, 7, 8]).config("cticks", num_colors=num_colors).finalize()) attrs = ah_obj.attrs assert len(attrs["cticks_kwds"]["ticks"]) == num_colors + 1 assert attrs["plot_kwds"]["vmin"] == 6 assert attrs["plot_kwds"]["vmax"] == 8 assert attrs["colorbar_kwds"]["show"]
def test_precompute_base_ticks_numeric(): ah_obj = ah.Array([0.01, 0.02, 1], [5, 6, 7]).finalize() attrs = ah_obj.attrs attrs["xticks_kwds"]["is_str"] = False attrs["base_kwds"]["xticks"] == 0.002 attrs["xticks_kwds"]["is_datetime"] = False attrs["yticks_kwds"]["is_str"] = False attrs["base_kwds"]["yticks"] == 0.6 attrs["yticks_kwds"]["is_datetime"] = False
def test_add_durations_input(): ah_obj = (ah.Array([0, 1], [2, 3], frames=3, durations=[0, 1]).config("durations", final_frame=2, transition_frames=2, aggregate="min").finalize()) ds = ah_obj[1, 1] assert ds["duration"].attrs["aggregate"] == "min" assert ds["duration"].attrs["transition_frames"] == 2 assert (ds["duration"].values == [0, 0, 3, 0]).all()
def test_add_margins_datetime(): ah_obj = ah.Array( pd.date_range("2017-02-01", "2017-02-02"), [2, 3], xlims="explore", xmargins=1, frames=1, ) assert ah_obj.attrs["margins_kwds"]["x"] == 1 ah_obj = ah_obj.finalize() ds = ah_obj[1, 1] assert (ds["xlim0"] == pd.to_datetime(["2017-02-01", "2017-01-31"])).all() assert (ds["xlim1"] == pd.to_datetime(["2017-02-01", "2017-02-03"])).all()
def test_remark_cascade_first(first): xs = np.array([0, 1, 2]) ys = np.array([3, 4, 4]) arr = ah.Array(xs, ys) arr = arr - arr arr = arr.remark(ys=4, remarks="4!!", first=first) ds = arr._ds actual = ds["remark"] if first: expected = np.array([["", "4!!", "", "", "", ""], ["", "", "", "", "4!!", ""]]) else: expected = np.array([["", "4!!", "4!!", "4!!", "4!!", "4!!"], ["", "", "", "", "4!!", "4!!"]]) assert (actual == expected).all()
def test_add_margins(): ah_obj = ah.Array( [-1, 1], [2, 3], xlims="explore", ylims="fixed", xmargins=10, ymargins=10, frames=1, ) assert ah_obj.attrs["margins_kwds"]["x"] == 10 assert ah_obj.attrs["margins_kwds"]["y"] == 10 ah_obj = ah_obj.finalize() ds = ah_obj[1, 1] np.testing.assert_almost_equal(ds["xlim0"], [-1, -21]) np.testing.assert_almost_equal(ds["xlim1"], [-1, 21]) np.testing.assert_almost_equal(ds["ylim0"], [-8, -8]) np.testing.assert_almost_equal(ds["ylim1"], [13, 13])
def test_add_animate_kwds_str(animate, value): if value is None: value = 11 else: animate = f"{animate}_{value}" ah_obj = ah.Array([0, 1, 2], [3, 4, 5], animate=animate).finalize() attrs = ah_obj.attrs num_states = len(ah_obj[1, 1]["state"]) if animate.startswith("test"): states = np.linspace(1, num_states, value).astype(int) elif animate.startswith("head"): states = np.arange(1, value) elif animate.startswith("tail"): states = np.arange(-value, 0, 1) animate_kwds = attrs["animate_kwds"] assert (animate_kwds["states"] == states).all() assert animate_kwds["fps"] == 1 assert animate_kwds["stitch"] assert not animate_kwds["static"]
def test_remark(dtype, chart, first): if dtype == "numeric": x = np.array([0.0, 1, 1, 3]) xs_condition = [0, 1] elif dtype == "datetime": x = pd.to_datetime( ["2017-02-01", "2017-02-02", "2017-02-02", "2017-02-03"]).values xs_condition = pd.to_datetime(["2017-02-01", "2017-02-02"]) y = [4, 5, 6, 7] ah_obj = (ah.Array(x, y, chart=chart).remark("x", xs=xs_condition).remark("abcdef", ys=7)) ds = ah_obj[1, 1] remarks = ds["remark"].squeeze().values assert ds["remark"].ndim == 2 if not first: assert (remarks[:3] == x[:3].astype(str)).all() assert remarks[-1] == "abcdef" else: assert (remarks[:2] == x[:2].astype(str)).all() assert remarks[-1] == "abcdef"
def test_reference_method_inline_labels(x0s, y0s, inline_locs): ah_obj = ah.Array([0, 1, 2], [3, 4, 5]) reference_kwds = dict(x0s=x0s, y0s=y0s, inline_locs=inline_locs, inline_labels="test") if x0s is None and y0s is None: with pytest.raises(ValueError): ah_obj.reference(**reference_kwds) else: ah_obj = ah_obj.reference(**reference_kwds).finalize() ds = ah_obj[1, 1] if x0s is not None: assert (ds["ref_x0"] == x0s).all() if y0s is not None: assert (ds["ref_y0"] == y0s).all() if inline_locs is not None: assert (ds["ref_inline_loc"] == inline_locs).all() assert (ds["ref_inline_label"] == "test").all()
def test_add_geo_transform(crs, projection): ah_obj = (ah.Array([0, 1, 2], [3, 4, 5], crs=crs, projection=projection).config( "projection", central_longitude=180).finalize()) if crs is None and projection is None: pytest.skip() ds = ah_obj.data[1, 1] attrs = ah_obj.attrs if isinstance(projection, (str, ccrs.Robinson)): projection = ccrs.Robinson else: projection = ccrs.PlateCarree assert attrs["projection_kwds"]["central_longitude"] == 180 for key in ITEMS["transformables"]: assert isinstance(attrs[key]["transform"], ccrs.PlateCarree) assert isinstance(ds["projection"].item(), projection) ds = ah_obj[1, 1] assert "projection" in ds
def test_config_trail_chart(chart): x = [0, 1, 2] y = [3, 4, 5] ah_array = (ah.Array(x, y, chart="scatter", preset="trail").config("preset", chart=chart).finalize()) ds = ah_array[1, 1] trail_vars = [] if chart in ["both", "scatter"]: trail_vars.extend(["x_discrete_trail", "y_discrete_trail"]) elif chart in ["both", "line"]: trail_vars.extend(["x_trail", "y_trail"]) for var in trail_vars: assert var in ds if "x" in var: if "discrete" in var: assert (x[:-1] == np.unique(ds[var].dropna("state"))).all() else: assert (ds["x"].values == ds[var].values).all() elif "y" in var: if "discrete" in var: assert (y[:-1] == np.unique(ds[var].dropna("state"))).all() else: assert (ds["y"].values == ds[var].values).all()
def test_ah_array(container, x, y): x_iterable = container(x) if isinstance(x, list) else x y_iterable = container(y) if isinstance(y, list) else y ah_array = ah.Array(x_iterable, y_iterable, s=y_iterable, label="test", frames=2) assert_types(ah_array) for ds in ah_array.data.values(): var_dict = { "x": x_iterable, "y": y_iterable, "s": y_iterable, "label": "test", } assert_values(ds, var_dict) configurables = CONFIGURABLES.copy() configurables.pop("grid") assert_attrs(ds, configurables) ah_array.finalize()
def test_propagate_params(direction, join): x = [0, 1] y = [2, 3] args = x, y a = ah.Array( *args, **canvas1_params, **subplot1_params, **geo1_params, **label1_params, ) b = ah.Reference( *args, **canvas2_params, ) c = ah.Array( *args, **canvas2_params, **subplot2_params, **geo2_params, **label2_params, ) ah_objs = [a, b, c] all1_params = { **canvas1_params, **subplot1_params, **geo1_params, **label1_params, } all2_params = { **canvas2_params, **subplot2_params, **geo2_params, **label2_params, } if direction == "backward": all1_params, all2_params = all2_params, all1_params ah_objs = ah_objs[::-1] ah_obj = ah.merge(ah_objs, join=join) for param in all1_params: configurable = PARAMS[param] key = f"{configurable}_kwds" method_key = CONFIGURABLES_KWDS[configurable][param] actual = ah_obj[1, 1].attrs[key][method_key] expected = all1_params[param] assert actual == expected for param in all2_params: configurable = PARAMS[param] key = f"{configurable}_kwds" method_key = CONFIGURABLES_KWDS[configurable][param] expected = all2_params[param] if join == "layout" and param not in CONFIGURABLES["canvas"]: actual = ah_obj[1, 3].attrs[key][method_key] assert actual == expected else: actual = ah_obj[1, 1].attrs[key][method_key] if param in all1_params: assert actual != expected else: assert actual == expected