From bb9487c64b4392c3d4bd84fd24985a068ed4ece8 Mon Sep 17 00:00:00 2001
From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com>
Date: Wed, 21 May 2025 15:01:31 -0400
Subject: [PATCH 01/13] Sketch out the marginals version of the plot
---
src/data_morph/__init__.py | 2 +-
src/data_morph/data/dataset.py | 8 ++++++
src/data_morph/morpher.py | 6 +++++
src/data_morph/plotting/static.py | 43 ++++++++++++++++++++++++++-----
4 files changed, 52 insertions(+), 7 deletions(-)
diff --git a/src/data_morph/__init__.py b/src/data_morph/__init__.py
index 036bcbd5..6eae26ef 100644
--- a/src/data_morph/__init__.py
+++ b/src/data_morph/__init__.py
@@ -28,5 +28,5 @@
and `this slide deck `_.
"""
-__version__ = '0.3.1'
+__version__ = '0.4.0.dev0'
MAIN_DIR = __name__
diff --git a/src/data_morph/data/dataset.py b/src/data_morph/data/dataset.py
index 20d50173..1b98ed6f 100644
--- a/src/data_morph/data/dataset.py
+++ b/src/data_morph/data/dataset.py
@@ -6,6 +6,7 @@
from typing import TYPE_CHECKING
import matplotlib.pyplot as plt
+import numpy as np
from ..bounds.bounding_box import BoundingBox
from ..bounds.interval import Interval
@@ -69,6 +70,13 @@ def __init__(
self.plot_bounds: BoundingBox = self._derive_plotting_bounds()
"""BoundingBox: The bounds to use when plotting the morphed data."""
+ self.x_marginal: tuple[np.ndarray, np.ndarray] = np.histogram(
+ self.data.x, bins=30, range=self.plot_bounds.x_bounds
+ )
+ self.y_marginal: tuple[np.ndarray, np.ndarray] = np.histogram(
+ self.data.y, bins=30, range=self.plot_bounds.y_bounds
+ )
+
def __repr__(self) -> str:
return f'<{self.__class__.__name__} name={self.name} scaled={self._scaled}>'
diff --git a/src/data_morph/morpher.py b/src/data_morph/morpher.py
index c7a5483f..18107e6b 100644
--- a/src/data_morph/morpher.py
+++ b/src/data_morph/morpher.py
@@ -198,6 +198,8 @@ def _record_frames(
self,
data: pd.DataFrame,
bounds: BoundingBox,
+ x_marginal,
+ y_marginal,
base_file_name: str,
frame_number: str,
) -> None:
@@ -222,6 +224,8 @@ def _record_frames(
decimals=self.decimals,
x_bounds=bounds.x_bounds,
y_bounds=bounds.y_bounds,
+ x_marginal=x_marginal,
+ y_marginal=y_marginal,
dpi=150,
)
if (
@@ -442,6 +446,8 @@ def morph(
base_file_name = f'{start_shape.name}-to-{target_shape}'
record_frames = partial(
self._record_frames,
+ x_marginal=start_shape.x_marginal,
+ y_marginal=start_shape.y_marginal,
base_file_name=base_file_name,
bounds=start_shape.plot_bounds,
)
diff --git a/src/data_morph/plotting/static.py b/src/data_morph/plotting/static.py
index 20ba7d17..9852fb96 100644
--- a/src/data_morph/plotting/static.py
+++ b/src/data_morph/plotting/static.py
@@ -8,7 +8,7 @@
import matplotlib.pyplot as plt
import numpy as np
-from matplotlib.ticker import EngFormatter
+from matplotlib.ticker import EngFormatter, MaxNLocator
from ..data.stats import get_summary_statistics
from .style import plot_with_custom_style
@@ -26,6 +26,8 @@ def plot(
data: pd.DataFrame,
x_bounds: Iterable[Number],
y_bounds: Iterable[Number],
+ x_marginal,
+ y_marginal,
save_to: str | Path,
decimals: int,
**save_kwds: Any, # noqa: ANN401
@@ -53,21 +55,48 @@ def plot(
When ``save_to`` is falsey, an :class:`~matplotlib.axes.Axes` object is returned.
"""
fig, ax = plt.subplots(
- figsize=(7, 3), layout='constrained', subplot_kw={'aspect': 'equal'}
+ figsize=(9, 3), layout='constrained', subplot_kw={'aspect': 'equal'}
)
fig.get_layout_engine().set(w_pad=1.4, h_pad=0.2, wspace=0)
ax.scatter(data.x, data.y, s=1, alpha=0.7, color='black')
ax.set(xlim=x_bounds, ylim=y_bounds)
+ ax_histx = ax.inset_axes([0, 1.05, 1, 0.25], sharex=ax)
+ ax_histy = ax.inset_axes([1.05, 0, 0.25, 1], sharey=ax)
+
+ x_marginal_counts, x_marginal_bins = x_marginal
+ y_marginal_counts, y_marginal_bins = y_marginal
+
+ ax_histx.set(xlim=x_bounds, ylim=(0, np.ceil(x_marginal_counts.max() * 2)))
+ ax_histy.set(xlim=(0, np.ceil(y_marginal_counts.max() * 2)), ylim=y_bounds)
+
+ # no labels on marginal axis that shares with scatter plot
+ ax_histx.tick_params(axis='x', labelbottom=False)
+ ax_histy.tick_params(axis='y', labelleft=False)
+
+ # move marginal axis ticks that are visible to the corner and only show the non-zero label
+ locator = MaxNLocator(2, integer=True, prune='lower')
+ ax_histx.tick_params(axis='y', labelleft=False, labelright=True)
+ ax_histx.yaxis.set_major_locator(locator)
+ ax_histy.tick_params(axis='x', labelbottom=False, labeltop=True)
+ ax_histy.xaxis.set_major_locator(locator)
+
+ ax_histx.hist(data.x, bins=x_marginal_bins, color='gray', ec='black')
+ ax_histy.hist(
+ data.y, bins=y_marginal_bins, orientation='horizontal', color='gray', ec='black'
+ )
+
tick_formatter = EngFormatter()
ax.xaxis.set_major_formatter(tick_formatter)
+ ax_histy.xaxis.set_major_formatter(tick_formatter)
ax.yaxis.set_major_formatter(tick_formatter)
+ ax_histx.yaxis.set_major_formatter(tick_formatter)
res = get_summary_statistics(data)
labels = ('X Mean', 'Y Mean', 'X SD', 'Y SD', 'Corr.')
- locs = np.linspace(0.8, 0.2, num=len(labels))
+ locs = np.linspace(1.15, 0.1, num=len(labels))
max_label_length = max([len(label) for label in labels])
max_stat = int(np.log10(np.max(np.abs(res)))) + 1
mean_x_digits, mean_y_digits = (
@@ -90,17 +119,19 @@ def plot(
add_stat_text = partial(
ax.text,
- 1.05,
+ 1.4,
fontsize=15,
transform=ax.transAxes,
va='center',
)
- for label, loc, stat in zip(labels[:-1], locs, res):
+ for label, loc, stat in zip(labels[:-1], locs, res, strict=False):
add_stat_text(loc, formatter(label, stat), alpha=0.3)
add_stat_text(loc, formatter(label, stat)[:-stat_clip])
correlation_str = corr_formatter(labels[-1], res.correlation)
- for alpha, text in zip([0.3, 1], [correlation_str, correlation_str[:-stat_clip]]):
+ for alpha, text in zip(
+ [0.3, 1], [correlation_str, correlation_str[:-stat_clip]], strict=False
+ ):
add_stat_text(
locs[-1],
text,
From 673957ab8073512eca39eef9f5e6deaae9f38f45 Mon Sep 17 00:00:00 2001
From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com>
Date: Wed, 21 May 2025 15:01:52 -0400
Subject: [PATCH 02/13] Bump matplotlib version and min Python
---
pyproject.toml | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/pyproject.toml b/pyproject.toml
index 432001f5..15d6f995 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -24,14 +24,13 @@ authors = [
{ name = "Aaron Stevens", email = "bheklilr2@gmail.com" },
{ name = "Justin Matejka", email = "Justin.Matejka@Autodesk.com" },
]
-requires-python = ">=3.9"
+requires-python = ">=3.10"
classifiers = [
"Development Status :: 4 - Beta",
"Framework :: Matplotlib",
"Intended Audience :: Education",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3 :: Only",
- "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
@@ -44,7 +43,7 @@ dynamic = [
]
dependencies = [
- "matplotlib>=3.7",
+ "matplotlib>=3.10",
"numpy>=1.20",
"pandas>=1.2",
"rich>=13.9.4",
From 6fcbdf9fe6a9c48ff29122a1a9d448dd9bf32178 Mon Sep 17 00:00:00 2001
From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com>
Date: Wed, 21 May 2025 16:55:39 -0400
Subject: [PATCH 03/13] Remove 3.9 from testing matrix
---
.github/workflows/ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a187fb17..1c40bc1d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -44,7 +44,7 @@ jobs:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
- python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
env:
MPLBACKEND: Agg # non-interactive backend for matplotlib
From 502372b60e255efa0fbc6f03de5d5474a58fef31 Mon Sep 17 00:00:00 2001
From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com>
Date: Wed, 21 May 2025 21:29:28 -0400
Subject: [PATCH 04/13] Update tests
---
tests/plotting/test_animation.py | 1 +
tests/plotting/test_static.py | 28 +++++++++++++++++++++++-----
tests/test_morpher.py | 5 +++--
3 files changed, 27 insertions(+), 7 deletions(-)
diff --git a/tests/plotting/test_animation.py b/tests/plotting/test_animation.py
index 347094a1..62dd4edc 100644
--- a/tests/plotting/test_animation.py
+++ b/tests/plotting/test_animation.py
@@ -30,6 +30,7 @@ def test_frame_stitching(sample_data, tmp_path, forward_only):
save_to=(tmp_path / f'{start_shape}-to-{target_shape}-{frame}.png'),
decimals=2,
with_median=False,
+ marginals=None,
)
duration_multipliers = [0, 0, 0, 0, 1, 1, *frame_numbers[2:], frame_numbers[-1]]
diff --git a/tests/plotting/test_static.py b/tests/plotting/test_static.py
index 9b1064e5..d0f7b024 100644
--- a/tests/plotting/test_static.py
+++ b/tests/plotting/test_static.py
@@ -1,5 +1,7 @@
"""Test the static module."""
+import matplotlib.pyplot as plt
+import numpy as np
import pytest
from data_morph.plotting.static import plot
@@ -8,16 +10,23 @@
@pytest.mark.parametrize(
- ('file_path', 'with_median'),
+ ('file_path', 'with_median', 'classic'),
[
- ('test_plot.png', False),
- (None, True),
- (None, False),
+ ('test_plot.png', False, True),
+ (None, True, True),
+ (None, False, True),
+ (None, True, False),
+ (None, False, False),
],
)
-def test_plot(sample_data, tmp_path, file_path, with_median):
+def test_plot(sample_data, tmp_path, file_path, with_median, classic):
"""Test static plot creation."""
bounds = (-5.0, 105.0)
+
+ marginals = (
+ None if classic else (np.histogram(sample_data.x), np.histogram(sample_data.y))
+ )
+
if file_path:
save_to = tmp_path / 'another-level' / file_path
@@ -28,6 +37,7 @@ def test_plot(sample_data, tmp_path, file_path, with_median):
save_to=save_to,
decimals=2,
with_median=with_median,
+ marginals=marginals,
)
assert save_to.is_file()
@@ -39,6 +49,7 @@ def test_plot(sample_data, tmp_path, file_path, with_median):
save_to=None,
decimals=2,
with_median=with_median,
+ marginals=marginals,
)
# confirm that the stylesheet was used
@@ -52,3 +63,10 @@ def test_plot(sample_data, tmp_path, file_path, with_median):
expected_stats = 7 if with_median else 5
expected_texts = 2 * expected_stats # label and the number
assert len(ax.texts) == expected_texts
+
+ # if marginals should be there, check for two inset Axes
+ expected_insets = 0 if classic else 2
+ inset_axes = [
+ child for child in ax.get_children() if isinstance(child, plt.Axes)
+ ]
+ assert len(inset_axes) == expected_insets
diff --git a/tests/test_morpher.py b/tests/test_morpher.py
index b4892191..2b5b09d4 100644
--- a/tests/test_morpher.py
+++ b/tests/test_morpher.py
@@ -263,8 +263,9 @@ def test_record_frames(self, write_images, start_frame, tmp_path):
morpher._record_frames(
dataset.data,
dataset.plot_bounds,
- base_path,
- frame_number,
+ marginals=None,
+ base_file_name=base_path,
+ frame_number=frame_number,
)
images = list(tmp_path.glob(f'{base_path}*.png'))
From 12274bfcbac8456d7032bb2ba7712fa8b19db64d Mon Sep 17 00:00:00 2001
From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com>
Date: Wed, 21 May 2025 21:33:42 -0400
Subject: [PATCH 05/13] Update min dependency versions
---
pyproject.toml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pyproject.toml b/pyproject.toml
index 212db818..1ffa3b10 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -44,8 +44,8 @@ dynamic = [
dependencies = [
"matplotlib>=3.10",
- "numpy>=1.20",
- "pandas>=1.2",
+ "numpy>=1.23.0",
+ "pandas>=2.1",
"rich>=13.9.4",
]
optional-dependencies.dev = [
From 39332c77e84be5c53a863b542c8fc160a6a02aec Mon Sep 17 00:00:00 2001
From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com>
Date: Wed, 21 May 2025 21:40:08 -0400
Subject: [PATCH 06/13] Add ruff fixes for new min Python version
---
src/data_morph/plotting/animation.py | 6 ++++--
src/data_morph/plotting/style.py | 4 ++--
src/data_morph/shapes/bases/line_collection.py | 2 +-
src/data_morph/shapes/lines/star.py | 4 +++-
tests/bounds/test_interval.py | 2 +-
tests/data/test_loader.py | 4 +++-
tests/shapes/circles/test_circle.py | 1 +
7 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/src/data_morph/plotting/animation.py b/src/data_morph/plotting/animation.py
index f3d12d80..dc59500a 100644
--- a/src/data_morph/plotting/animation.py
+++ b/src/data_morph/plotting/animation.py
@@ -6,11 +6,13 @@
import re
from functools import wraps
from pathlib import Path
-from typing import TYPE_CHECKING, Callable
+from typing import TYPE_CHECKING
from PIL import Image
if TYPE_CHECKING:
+ from collections.abc import Callable
+
from ..shapes.bases.shape import Shape
@@ -115,7 +117,7 @@ def wrapper(step: int | float) -> int | float:
int or float
The eased value at the current step, from 0.0 to 1.0.
"""
- if not (isinstance(step, (int, float)) and 0 <= step <= 1):
+ if not (isinstance(step, int | float) and 0 <= step <= 1):
raise ValueError('Step must be an integer or float, between 0 and 1.')
return easing_function(step)
diff --git a/src/data_morph/plotting/style.py b/src/data_morph/plotting/style.py
index 42b7db55..e46c415b 100644
--- a/src/data_morph/plotting/style.py
+++ b/src/data_morph/plotting/style.py
@@ -1,11 +1,11 @@
"""Utility functions for styling Matplotlib plots."""
-from collections.abc import Generator
+from collections.abc import Callable, Generator
from contextlib import contextmanager
from functools import wraps
from importlib.resources import as_file, files
from pathlib import Path
-from typing import Any, Callable
+from typing import Any
import matplotlib.pyplot as plt
diff --git a/src/data_morph/shapes/bases/line_collection.py b/src/data_morph/shapes/bases/line_collection.py
index f19e6950..31807a2b 100644
--- a/src/data_morph/shapes/bases/line_collection.py
+++ b/src/data_morph/shapes/bases/line_collection.py
@@ -121,5 +121,5 @@ def plot(self, ax: Axes | None = None) -> Axes:
fig.get_layout_engine().set(w_pad=0.2, h_pad=0.2)
_ = ax.axis('equal')
for start, end in self.lines:
- ax.plot(*list(zip(start, end)), 'k-')
+ ax.plot(*list(zip(start, end, strict=False)), 'k-')
return ax
diff --git a/src/data_morph/shapes/lines/star.py b/src/data_morph/shapes/lines/star.py
index b5b339d1..16ae1f19 100644
--- a/src/data_morph/shapes/lines/star.py
+++ b/src/data_morph/shapes/lines/star.py
@@ -1,5 +1,7 @@
"""Star shape."""
+import itertools
+
from ...data.dataset import Dataset
from ..bases.line_collection import LineCollection
@@ -46,4 +48,4 @@ def __init__(self, dataset: Dataset) -> None:
[xmin, ymin + y_range * 0.625],
]
- super().__init__(*list(zip(pts[:-1], pts[1:])))
+ super().__init__(*list(itertools.pairwise(pts)))
diff --git a/tests/bounds/test_interval.py b/tests/bounds/test_interval.py
index 4c744dcb..3a75e3ea 100644
--- a/tests/bounds/test_interval.py
+++ b/tests/bounds/test_interval.py
@@ -91,7 +91,7 @@ def test_getitem(self):
def test_iter(self):
"""Test that the __iter__() method is working."""
limits = [0, 1]
- for bound, limit in zip(Interval(limits), limits):
+ for bound, limit in zip(Interval(limits), limits, strict=False):
assert bound == limit
@pytest.mark.parametrize(
diff --git a/tests/data/test_loader.py b/tests/data/test_loader.py
index a1a5d1bb..5bf27d55 100644
--- a/tests/data/test_loader.py
+++ b/tests/data/test_loader.py
@@ -67,7 +67,9 @@ def test_plot_available_datasets(self, monkeypatch, subset):
assert len(populated_axs) == len(DataLoader.AVAILABLE_DATASETS)
assert all(ax.get_xlabel() == ax.get_ylabel() == '' for ax in populated_axs)
- for dataset, ax in zip(DataLoader.AVAILABLE_DATASETS, populated_axs):
+ for dataset, ax in zip(
+ DataLoader.AVAILABLE_DATASETS, populated_axs, strict=False
+ ):
subplot_title = ax.get_title()
assert subplot_title.startswith(dataset)
assert subplot_title.endswith(' points)')
diff --git a/tests/shapes/circles/test_circle.py b/tests/shapes/circles/test_circle.py
index 2daa251d..2da5a147 100644
--- a/tests/shapes/circles/test_circle.py
+++ b/tests/shapes/circles/test_circle.py
@@ -32,5 +32,6 @@ def test_is_circle(self, shape):
for x, y in zip(
cx + shape.radius * np.cos(angles),
cy + shape.radius * np.sin(angles),
+ strict=False,
):
assert pytest.approx(shape.distance(x, y)) == 0
From 26917071d1fdaeb02d4f17e4ef396140bb5681b3 Mon Sep 17 00:00:00 2001
From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com>
Date: Wed, 21 May 2025 21:42:25 -0400
Subject: [PATCH 07/13] Add unsafe fixes
---
src/data_morph/bounds/_utils.py | 2 +-
src/data_morph/bounds/bounding_box.py | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/data_morph/bounds/_utils.py b/src/data_morph/bounds/_utils.py
index df17efe7..1f850aee 100644
--- a/src/data_morph/bounds/_utils.py
+++ b/src/data_morph/bounds/_utils.py
@@ -21,7 +21,7 @@ def _validate_2d(data: Iterable[Number], name: str) -> Iterable[Number]:
The validated data.
"""
if not (
- isinstance(data, (tuple, list))
+ isinstance(data, tuple | list)
and len(data) == 2
and all(isinstance(x, Number) and not isinstance(x, bool) for x in data)
):
diff --git a/src/data_morph/bounds/bounding_box.py b/src/data_morph/bounds/bounding_box.py
index 38804601..f85aab2e 100644
--- a/src/data_morph/bounds/bounding_box.py
+++ b/src/data_morph/bounds/bounding_box.py
@@ -38,7 +38,7 @@ def __init__(
if isinstance(inclusive, bool):
inclusive = [inclusive] * 2
if not (
- isinstance(inclusive, (tuple, list))
+ isinstance(inclusive, tuple | list)
and len(inclusive) == 2
and all(isinstance(x, bool) for x in inclusive)
):
@@ -47,19 +47,19 @@ def __init__(
' or a single Boolean value'
)
- self.x_bounds = (
+ self.x_bounds: Interval = (
x_bounds.clone()
if isinstance(x_bounds, Interval)
else Interval(x_bounds, inclusive[0])
)
- """Interval: The bounds for the x direction."""
+ """The bounds for the x direction."""
- self.y_bounds = (
+ self.y_bounds: Interval = (
y_bounds.clone()
if isinstance(y_bounds, Interval)
else Interval(y_bounds, inclusive[1])
)
- """Interval: The bounds for the y direction."""
+ """The bounds for the y direction."""
self._bounds = (self.x_bounds, self.y_bounds)
From 0ab11662984715dccf6e5a0bc59ae8faa3842bb0 Mon Sep 17 00:00:00 2001
From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com>
Date: Thu, 29 May 2025 16:43:23 +0200
Subject: [PATCH 08/13] Switch from gray to slategray
---
src/data_morph/plotting/static.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/data_morph/plotting/static.py b/src/data_morph/plotting/static.py
index f4da8e7f..42b12bca 100644
--- a/src/data_morph/plotting/static.py
+++ b/src/data_morph/plotting/static.py
@@ -110,12 +110,12 @@ def plot(
ax_histy.tick_params(axis='x', labelbottom=False, labeltop=True)
ax_histy.xaxis.set_major_locator(locator)
- ax_histx.hist(data.x, bins=x_marginal_bins, color='gray', ec='black')
+ ax_histx.hist(data.x, bins=x_marginal_bins, color='slategray', ec='black')
ax_histy.hist(
data.y,
bins=y_marginal_bins,
orientation='horizontal',
- color='gray',
+ color='slategray',
ec='black',
)
From 888c6d87e6e6ee6a7c5a1a578baa23944d9d77dc Mon Sep 17 00:00:00 2001
From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com>
Date: Thu, 10 Jul 2025 22:23:27 -0700
Subject: [PATCH 09/13] Remove old settings for interrogate in preparation for
switching to Docstringify
---
pyproject.toml | 3 ---
1 file changed, 3 deletions(-)
diff --git a/pyproject.toml b/pyproject.toml
index e0f6fc68..5e76c71c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -193,9 +193,6 @@ verbose = 2
quiet = false
color = true
omit-covered-files = false
-# TODO: revisit this later when I add badges to the README
-# generate-badge = "."
-# badge-format = "svg"
[tool.numpydoc_validation]
checks = [
From 7ce2d1f2822a61c7ac26e37e8429883e0374110d Mon Sep 17 00:00:00 2001
From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com>
Date: Fri, 24 Oct 2025 13:32:05 -0300
Subject: [PATCH 10/13] Update docs
---
README.md | 2 +-
..._to_star.gif => panda-to-star-classic.gif} | Bin
docs/_static/panda-to-star-eased.gif | Bin 2497127 -> 2135278 bytes
docs/_static/panda-to-star.gif | Bin 3209336 -> 2953560 bytes
docs/quickstart.rst | 18 ++++++++++++++++--
docs/tutorials/custom-datasets.rst | 2 +-
6 files changed, 18 insertions(+), 4 deletions(-)
rename docs/_static/{panda_to_star.gif => panda-to-star-classic.gif} (100%)
diff --git a/README.md b/README.md
index c273977e..48180d6c 100644
--- a/README.md
+++ b/README.md
@@ -70,7 +70,7 @@
Data Morph transforms an input dataset of 2D points into select shapes, while preserving the summary statistics to a given number of decimal points through simulated annealing. It is intended to be used as a teaching tool to illustrate the importance of data visualization (see the [Data Morph in the Classroom](https://stefaniemolin.com/data-morph/stable/index.html#classroom-ideas) section for ideas).
-

+
diff --git a/docs/_static/panda_to_star.gif b/docs/_static/panda-to-star-classic.gif
similarity index 100%
rename from docs/_static/panda_to_star.gif
rename to docs/_static/panda-to-star-classic.gif
diff --git a/docs/_static/panda-to-star-eased.gif b/docs/_static/panda-to-star-eased.gif
index 5659a7fd8dacad892f417b8ccb39137e4e27634a..84c53fae80403dc479733cb14d3bc435ef745b0d 100644
GIT binary patch
literal 2135278
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