From 415d6f1c2c9bf3f62b29da1dd752cb34a18168a3 Mon Sep 17 00:00:00 2001 From: Saairam Venkatesh Date: Tue, 11 Jun 2024 18:39:00 -0500 Subject: [PATCH] feat!: support syntaxless-api (#47) --- .github/workflows/ci.yml | 2 + .../bar/matplotlib/example_mpl_bar_plot.html | 337 ---- .../bar/matplotlib/example_mpl_bar_plot.py | 42 +- example/bar/seaborn/example_sns_bar_plot.html | 396 ----- example/bar/seaborn/example_sns_bar_plot.py | 52 +- example/box/matplotlib/example_mpl_box.html | 469 ----- example/box/matplotlib/example_mpl_box.py | 65 +- example/box/seaborn/example_sns_box.html | 488 ------ example/box/seaborn/example_sns_box.py | 45 +- .../count/seaborn/example_sns_count_plot.html | 364 ---- .../count/seaborn/example_sns_count_plot.py | 35 +- .../matplotlib/example_mpl_heatmap.html | 989 ----------- .../heatmap/matplotlib/example_mpl_heatmap.py | 109 +- .../heatmap/seaborn/example_sns_heatmap.html | 1240 ------------- .../heatmap/seaborn/example_sns_heatmap.py | 37 +- .../histogram/matplotlib/example_mpl_hist.py | 41 +- .../matplotlib/example_mpl_histogram.html | 632 ------- example/histogram/seaborn/example_sns_hist.py | 43 +- .../seaborn/example_sns_histogram.html | 533 ------ example/line/matplotlib/example_mpl_line.html | 471 ----- example/line/matplotlib/example_mpl_line.py | 55 +- example/line/seaborn/example_sns_line.html | 701 -------- example/line/seaborn/example_sns_line.py | 63 +- .../matplotlib/example_mpl_scatter.html | 1230 ------------- .../scatter/matplotlib/example_mpl_scatter.py | 45 +- .../scatter/seaborn/example_sns_scatter.html | 1558 ----------------- .../scatter/seaborn/example_sns_scatter.py | 44 +- example/utils/__init__.py | 0 example/utils/box.html | 470 +++++ example/utils/file_utils.py | 28 + maidr/__init__.py | 12 +- maidr/core/context_manager.py | 43 + maidr/core/enum/__init__.py | 1 + {tests => maidr}/core/enum/library.py | 2 +- maidr/core/enum/plot_type.py | 1 + maidr/core/figure_manager.py | 20 +- maidr/core/plot/{bar_plot.py => barplot.py} | 5 +- maidr/core/plot/{box_plot.py => boxplot.py} | 87 +- ...grouped_bar_plot.py => grouped_barplot.py} | 0 maidr/core/plot/{heat_plot.py => heatmap.py} | 4 +- .../core/plot/{hist_plot.py => histogram.py} | 0 maidr/core/plot/{line_plot.py => lineplot.py} | 0 maidr/core/plot/maidr_plot.py | 8 +- maidr/core/plot/maidr_plot_factory.py | 16 +- .../plot/{scatter_plot.py => scatterplot.py} | 0 maidr/maidr.py | 463 +---- maidr/patch/__init__.py | 0 maidr/patch/barplot.py | 22 + maidr/patch/boxplot.py | 71 + maidr/patch/common.py | 23 + maidr/patch/heatmap.py | 31 + maidr/patch/histogram.py | 43 + maidr/patch/lineplot.py | 20 + maidr/patch/scatterplot.py | 20 + poetry.lock | 83 +- pyproject.toml | 1 + tests/conftest.py | 2 +- tests/core/plot/test_bar_plot.py | 30 - tests/core/plot/test_barplot.py | 52 + tests/core/plot/test_boxplot.py | 58 + tests/core/test_figure_manager.py | 18 +- tests/core/test_maidr_plot_factory.py | 16 +- tests/fixture/matplotlib_factory.py | 22 +- tests/fixture/seaborn_factory.py | 31 +- 64 files changed, 1359 insertions(+), 10430 deletions(-) delete mode 100644 example/bar/matplotlib/example_mpl_bar_plot.html delete mode 100644 example/bar/seaborn/example_sns_bar_plot.html delete mode 100644 example/box/matplotlib/example_mpl_box.html delete mode 100644 example/box/seaborn/example_sns_box.html delete mode 100644 example/count/seaborn/example_sns_count_plot.html delete mode 100644 example/heatmap/matplotlib/example_mpl_heatmap.html delete mode 100644 example/heatmap/seaborn/example_sns_heatmap.html delete mode 100644 example/histogram/matplotlib/example_mpl_histogram.html delete mode 100644 example/histogram/seaborn/example_sns_histogram.html delete mode 100644 example/line/matplotlib/example_mpl_line.html delete mode 100644 example/line/seaborn/example_sns_line.html delete mode 100644 example/scatter/matplotlib/example_mpl_scatter.html delete mode 100644 example/scatter/seaborn/example_sns_scatter.html create mode 100644 example/utils/__init__.py create mode 100644 example/utils/box.html create mode 100644 example/utils/file_utils.py create mode 100644 maidr/core/context_manager.py rename {tests => maidr}/core/enum/library.py (75%) rename maidr/core/plot/{bar_plot.py => barplot.py} (93%) rename maidr/core/plot/{box_plot.py => boxplot.py} (67%) rename maidr/core/plot/{grouped_bar_plot.py => grouped_barplot.py} (100%) rename maidr/core/plot/{heat_plot.py => heatmap.py} (96%) rename maidr/core/plot/{hist_plot.py => histogram.py} (100%) rename maidr/core/plot/{line_plot.py => lineplot.py} (100%) rename maidr/core/plot/{scatter_plot.py => scatterplot.py} (100%) create mode 100644 maidr/patch/__init__.py create mode 100644 maidr/patch/barplot.py create mode 100644 maidr/patch/boxplot.py create mode 100644 maidr/patch/common.py create mode 100644 maidr/patch/heatmap.py create mode 100644 maidr/patch/histogram.py create mode 100644 maidr/patch/lineplot.py create mode 100644 maidr/patch/scatterplot.py delete mode 100644 tests/core/plot/test_bar_plot.py create mode 100644 tests/core/plot/test_barplot.py create mode 100644 tests/core/plot/test_boxplot.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f875e45..d9a2c1b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,6 +77,8 @@ jobs: uses: psf/black@stable with: options: "--diff --check --color --verbose" + version: "23.3.0" + commit-lint: runs-on: ubuntu-latest diff --git a/example/bar/matplotlib/example_mpl_bar_plot.html b/example/bar/matplotlib/example_mpl_bar_plot.html deleted file mode 100644 index 7a3a058..0000000 --- a/example/bar/matplotlib/example_mpl_bar_plot.html +++ /dev/null @@ -1,337 +0,0 @@ - - - - MAIDR - - - - -
- - - - - - 2024-04-01T11:32:50.281213 - image/svg+xml - - - Matplotlib v3.7.5, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/bar/matplotlib/example_mpl_bar_plot.py b/example/bar/matplotlib/example_mpl_bar_plot.py index 4e2a3ed..89688d8 100644 --- a/example/bar/matplotlib/example_mpl_bar_plot.py +++ b/example/bar/matplotlib/example_mpl_bar_plot.py @@ -1,37 +1,17 @@ -import os - import matplotlib.pyplot as plt import maidr import seaborn as sns +# Load dataset +tips = sns.load_dataset("tips") -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Load dataset - tips = sns.load_dataset("tips") - - # Create a bar plot - cut_counts = tips["day"].value_counts() - plt.figure(figsize=(10, 6)) - b_plot = plt.bar(cut_counts.index, list(cut_counts.values), color="skyblue") - plt.title("The Number of Tips by Day") - plt.xlabel("Day") - plt.ylabel("Count") - - return b_plot - - -def main(): - bar_plot = plot() - bar_maidr = maidr.bar(bar_plot) - bar_maidr.save_html(get_filepath("example_mpl_bar_plot.html")) - bar_maidr.show() - +# Create a bar plot +cut_counts = tips["day"].value_counts() +plt.figure(figsize=(10, 6)) +b_plot = plt.bar(cut_counts.index, list(cut_counts.values), color="skyblue") +plt.title("The Number of Tips by Day") +plt.xlabel("Day") +plt.ylabel("Count") -if __name__ == "__main__": - main() +plt.show() +maidr.show(b_plot) diff --git a/example/bar/seaborn/example_sns_bar_plot.html b/example/bar/seaborn/example_sns_bar_plot.html deleted file mode 100644 index eb35ba2..0000000 --- a/example/bar/seaborn/example_sns_bar_plot.html +++ /dev/null @@ -1,396 +0,0 @@ - - - - MAIDR - - - - -
- - - - - - 2024-04-01T11:31:47.317608 - image/svg+xml - - - Matplotlib v3.7.5, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/bar/seaborn/example_sns_bar_plot.py b/example/bar/seaborn/example_sns_bar_plot.py index fc6dcaa..0a2a56d 100644 --- a/example/bar/seaborn/example_sns_bar_plot.py +++ b/example/bar/seaborn/example_sns_bar_plot.py @@ -1,38 +1,24 @@ -import os - import matplotlib.pyplot as plt import maidr import seaborn as sns -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Load the penguins dataset - penguins = sns.load_dataset("penguins") - - # Create a bar plot showing the average body mass of penguins by species - plt.figure(figsize=(10, 6)) - b_plot = sns.barplot( - x="species", y="body_mass_g", data=penguins, errorbar="sd", palette="Blues_d" - ) - plt.title("Average Body Mass of Penguins by Species") - plt.xlabel("Species") - plt.ylabel("Body Mass (g)") - - return b_plot - - -def main(): - bar_plot = plot() - bar_maidr = maidr.bar(bar_plot) - bar_maidr.save_html(get_filepath("example_sns_bar_plot.html")) - bar_maidr.show() - - -if __name__ == "__main__": - main() +# Load the penguins dataset +penguins = sns.load_dataset("penguins") + +# Create a bar plot showing the average body mass of penguins by species +plt.figure(figsize=(10, 6)) +b_plot = sns.barplot( + x="species", + y="body_mass_g", + data=penguins, + errorbar="sd", + palette="Blues_d", + library="seaborn z", +) +plt.title("Average Body Mass of Penguins by Species") +plt.xlabel("Species") +plt.ylabel("Body Mass (g)") + +plt.show() +maidr.show(b_plot) diff --git a/example/box/matplotlib/example_mpl_box.html b/example/box/matplotlib/example_mpl_box.html deleted file mode 100644 index 4377c06..0000000 --- a/example/box/matplotlib/example_mpl_box.html +++ /dev/null @@ -1,469 +0,0 @@ - - - - MAIDR - - - - -
- - - - - - 2024-04-01T08:53:23.559572 - image/svg+xml - - - Matplotlib v3.7.5, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/box/matplotlib/example_mpl_box.py b/example/box/matplotlib/example_mpl_box.py index a5c3d57..5213723 100644 --- a/example/box/matplotlib/example_mpl_box.py +++ b/example/box/matplotlib/example_mpl_box.py @@ -1,54 +1,33 @@ -import os - import matplotlib.pyplot as plt import maidr import numpy as np -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Generating random data for three different groups - data_group1 = np.random.normal(100, 10, 200) - data_group2 = np.random.normal(90, 20, 200) - data_group3 = np.random.normal(80, 30, 200) - - # Combine these different datasets into a list - data_to_plot = [data_group1, data_group2, data_group3] - - # Create a figure instance - fig, ax = plt.subplots() - - # Create the boxplot - bp = ax.boxplot(data_to_plot, patch_artist=True) - - # Customize the boxplot colors - colors = ["lightblue", "lightgreen", "tan"] - for patch, color in zip(bp["boxes"], colors): - patch.set_facecolor(color) - - # Adding labels and title - ax.set_xticklabels(["Group 1", "Group 2", "Group 3"]) - ax.set_title("Box Plot Example") - ax.set_xlabel("Group") - ax.set_ylabel("Values") +# Generating random data for three different groups +data_group1 = np.random.normal(100, 10, 200) +data_group2 = np.random.normal(90, 20, 200) +data_group3 = np.random.normal(80, 30, 200) - # Show the plot - plt.show() +# Combine these different datasets into a list +data_to_plot = [data_group1, data_group2, data_group3] - return bp +# Create a figure instance +fig, ax = plt.subplots() +# Create the boxplot +bp = ax.boxplot(data_to_plot, patch_artist=True) -def main(): - box_plot = plot() - box_maidr = maidr.box(box_plot) - box_maidr.save_html(get_filepath("example_mpl_box.html")) - box_maidr.show() +# Customize the boxplot colors +colors = ["lightblue", "lightgreen", "tan"] +for patch, color in zip(bp["boxes"], colors): + patch.set_facecolor(color) +# Adding labels and title +ax.set_xticklabels(["Group 1", "Group 2", "Group 3"]) +ax.set_title("Box Plot Example") +ax.set_xlabel("Group") +ax.set_ylabel("Values") -if __name__ == "__main__": - main() +# Show the plot +plt.show() +maidr.show(bp) diff --git a/example/box/seaborn/example_sns_box.html b/example/box/seaborn/example_sns_box.html deleted file mode 100644 index 0c855bf..0000000 --- a/example/box/seaborn/example_sns_box.html +++ /dev/null @@ -1,488 +0,0 @@ - - - - MAIDR - - - - -
- - - - - - 2024-04-01T11:07:33.406938 - image/svg+xml - - - Matplotlib v3.7.5, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/box/seaborn/example_sns_box.py b/example/box/seaborn/example_sns_box.py index de4418f..1504155 100644 --- a/example/box/seaborn/example_sns_box.py +++ b/example/box/seaborn/example_sns_box.py @@ -1,42 +1,21 @@ -import os - import matplotlib.pyplot as plt import maidr import seaborn as sns -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Load the Iris dataset - iris = sns.load_dataset("iris") - - # Start a new figure - plt.figure() - - # Create box plot - box_plot = sns.boxplot(x="species", y="petal_length", data=iris) - - # Adding labels and title - plt.title("Box Plot of Petal Length by Iris Species") - plt.xlabel("Species") - plt.ylabel("Petal Length (cm)") - - plt.show() - - return box_plot +# Load the Iris dataset +iris = sns.load_dataset("iris") +# Start a new figure +plt.figure() -def main(): - box_plot = plot() - box_maidr = maidr.box(box_plot) - box_maidr.save_html(get_filepath("example_sns_box.html")) - box_maidr.show() +# Create box plot +box_plot = sns.boxplot(x="species", y="petal_length", data=iris) +# Adding labels and title +plt.title("Box Plot of Petal Length by Iris Species") +plt.xlabel("Species") +plt.ylabel("Petal Length (cm)") -if __name__ == "__main__": - main() +plt.show() +maidr.show(box_plot) diff --git a/example/count/seaborn/example_sns_count_plot.html b/example/count/seaborn/example_sns_count_plot.html deleted file mode 100644 index 92bb3b2..0000000 --- a/example/count/seaborn/example_sns_count_plot.html +++ /dev/null @@ -1,364 +0,0 @@ - - - - MAIDR - - - - -
- - - - - - 2024-02-19T08:42:09.381744 - image/svg+xml - - - Matplotlib v3.8.2, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/count/seaborn/example_sns_count_plot.py b/example/count/seaborn/example_sns_count_plot.py index 2da33ef..7b375a5 100644 --- a/example/count/seaborn/example_sns_count_plot.py +++ b/example/count/seaborn/example_sns_count_plot.py @@ -1,35 +1,16 @@ -import os - import matplotlib.pyplot as plt import maidr import seaborn as sns -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Load the Titanic dataset - titanic = sns.load_dataset("titanic") - - # Create a countplot - count_plot = sns.countplot(x="class", data=titanic) - - # Set the title and show the plot - plt.title("Passenger Class Distribution on the Titanic") - - return count_plot - +# Load the Titanic dataset +titanic = sns.load_dataset("titanic") -def main(): - count_plot = plot() - count_maidr = maidr.count(count_plot) - count_maidr.save_html(get_filepath("example_sns_count_plot.html")) - count_maidr.show() +# Create a countplot +count_plot = sns.countplot(x="class", data=titanic) +# Set the title and show the plot +plt.title("Passenger Class Distribution on the Titanic") -if __name__ == "__main__": - main() +plt.show() +maidr.show(count_plot) diff --git a/example/heatmap/matplotlib/example_mpl_heatmap.html b/example/heatmap/matplotlib/example_mpl_heatmap.html deleted file mode 100644 index 0d83cb1..0000000 --- a/example/heatmap/matplotlib/example_mpl_heatmap.html +++ /dev/null @@ -1,989 +0,0 @@ - - - - - - MAIDR - - - - -
- - - - - 2024-04-11T19:27:01.742991 - image/svg+xml - - - Matplotlib v3.7.5, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - \ No newline at end of file diff --git a/example/heatmap/matplotlib/example_mpl_heatmap.py b/example/heatmap/matplotlib/example_mpl_heatmap.py index 124efca..8fc1449 100644 --- a/example/heatmap/matplotlib/example_mpl_heatmap.py +++ b/example/heatmap/matplotlib/example_mpl_heatmap.py @@ -1,76 +1,57 @@ -import os - import maidr import matplotlib.pyplot as plt import numpy as np -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - vegetables = [ - "cucumber", - "tomato", - "lettuce", - "asparagus", - "potato", - "wheat", - "barley", +vegetables = [ + "cucumber", + "tomato", + "lettuce", + "asparagus", + "potato", + "wheat", + "barley", +] +farmers = [ + "Farmer Joe", + "Upland Bros.", + "Smith Gardening", + "Agrifun", + "Organiculture", + "BioGoods Ltd.", + "Cornylee Corp.", +] + +harvest = np.array( + [ + [0.8, 2.4, 2.5, 3.9, 0.0, 4.0, 0.0], + [2.4, 0.0, 4.0, 1.0, 2.7, 0.0, 0.0], + [1.1, 2.4, 0.8, 4.3, 1.9, 4.4, 0.0], + [0.6, 0.0, 0.3, 0.0, 3.1, 0.0, 0.0], + [0.7, 1.7, 0.6, 2.6, 2.2, 6.2, 0.0], + [1.3, 1.2, 0.0, 0.0, 0.0, 3.2, 5.1], + [0.1, 2.0, 0.0, 1.4, 0.0, 1.9, 6.3], ] - farmers = [ - "Farmer Joe", - "Upland Bros.", - "Smith Gardening", - "Agrifun", - "Organiculture", - "BioGoods Ltd.", - "Cornylee Corp.", - ] - - harvest = np.array( - [ - [0.8, 2.4, 2.5, 3.9, 0.0, 4.0, 0.0], - [2.4, 0.0, 4.0, 1.0, 2.7, 0.0, 0.0], - [1.1, 2.4, 0.8, 4.3, 1.9, 4.4, 0.0], - [0.6, 0.0, 0.3, 0.0, 3.1, 0.0, 0.0], - [0.7, 1.7, 0.6, 2.6, 2.2, 6.2, 0.0], - [1.3, 1.2, 0.0, 0.0, 0.0, 3.2, 5.1], - [0.1, 2.0, 0.0, 1.4, 0.0, 1.9, 6.3], - ] - ) - - fig, ax = plt.subplots() - im = ax.imshow(harvest) - im.get_array() - - # Show all ticks and label them with the respective list entries - ax.set_xticks(np.arange(len(farmers)), labels=farmers) - ax.set_yticks(np.arange(len(vegetables)), labels=vegetables) - - # Rotate the tick labels and set their alignment. - plt.setp(ax.get_xticklabels(), rotation=45, ha="right", rotation_mode="anchor") - - # Loop over data dimensions and create text annotations. - for i in range(len(vegetables)): - for j in range(len(farmers)): - ax.text(j, i, harvest[i, j], ha="center", va="center", color="w") +) - ax.set_title("Harvest of local farmers (in tons/year)") - fig.tight_layout() +fig, ax = plt.subplots() +im = ax.imshow(harvest, fill_label="Harvest") +im.get_array() - return im +# Show all ticks and label them with the respective list entries +ax.set_xticks(np.arange(len(farmers)), labels=farmers) +ax.set_yticks(np.arange(len(vegetables)), labels=vegetables) +# Rotate the tick labels and set their alignment. +plt.setp(ax.get_xticklabels(), rotation=45, ha="right", rotation_mode="anchor") -def main(): - heatmap = plot() - heat_maidr = maidr.heat(heatmap, fill_label="Harvest") - heat_maidr.save_html(get_filepath("example_mpl_heatmap.html")) - heat_maidr.show() +# Loop over data dimensions and create text annotations. +for i in range(len(vegetables)): + for j in range(len(farmers)): + ax.text(j, i, harvest[i, j], ha="center", va="center", color="w") +ax.set_title("Harvest of local farmers (in tons/year)") +fig.tight_layout() -if __name__ == "__main__": - main() +plt.show() +maidr.show(im) diff --git a/example/heatmap/seaborn/example_sns_heatmap.html b/example/heatmap/seaborn/example_sns_heatmap.html deleted file mode 100644 index 6f377c0..0000000 --- a/example/heatmap/seaborn/example_sns_heatmap.html +++ /dev/null @@ -1,1240 +0,0 @@ - - - - MAIDR - - - - -
- - - - - - 2024-04-01T11:09:37.697783 - image/svg+xml - - - Matplotlib v3.7.5, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/heatmap/seaborn/example_sns_heatmap.py b/example/heatmap/seaborn/example_sns_heatmap.py index 4526f49..2ad5476 100644 --- a/example/heatmap/seaborn/example_sns_heatmap.py +++ b/example/heatmap/seaborn/example_sns_heatmap.py @@ -1,35 +1,16 @@ -import os - import matplotlib.pyplot as plt import maidr import seaborn as sns -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Load an example dataset from seaborn - glue = sns.load_dataset("glue").pivot(index="Model", columns="Task", values="Score") - - # Plot a heatmap - plt.figure(figsize=(10, 8)) - heatmap = sns.heatmap(glue, annot=True) - plt.title("Heatmap of Model Scores by Task") - plt.show() - - return heatmap - - -def main(): - heatmap = plot() - heat_maidr = maidr.heat(heatmap) - heat_maidr.save_html(get_filepath("example_sns_heatmap.html")) - heat_maidr.show() +# Load an example dataset from seaborn +glue = sns.load_dataset("glue").pivot(index="Model", columns="Task", values="Score") +# Plot a heatmap +plt.figure(figsize=(10, 8)) +heatmap = sns.heatmap(glue, annot=True, fill_label="Score") +plt.title("Heatmap of Model Scores by Task") -if __name__ == "__main__": - main() +# Show the plot +plt.show() +maidr.show(heatmap) diff --git a/example/histogram/matplotlib/example_mpl_hist.py b/example/histogram/matplotlib/example_mpl_hist.py index 1e99aae..0c53c41 100644 --- a/example/histogram/matplotlib/example_mpl_hist.py +++ b/example/histogram/matplotlib/example_mpl_hist.py @@ -1,38 +1,19 @@ -import os - import maidr import matplotlib.pyplot as plt import seaborn as sns -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Load the dataset - iris = sns.load_dataset("iris") - - # Choose a column for the histogram, for example, the 'petal_length' - data = iris["petal_length"] - - # Create the histogram plot - _, _, hist_plot = plt.hist(data, bins=20, edgecolor="black") - plt.title("Histogram of Petal Lengths in Iris Dataset") - plt.xlabel("Petal Length (cm)") - plt.ylabel("Frequency") - - return hist_plot - +# Load the dataset +iris = sns.load_dataset("iris") -def main(): - hist = plot() - hist_maidr = maidr.hist(hist) - hist_maidr.save_html(get_filepath("example_mpl_histogram.html")) - hist_maidr.show() +# Choose a column for the histogram, for example, the 'petal_length' +data = iris["petal_length"] +# Create the histogram plot +_, _, hist_plot = plt.hist(data, bins=20, edgecolor="black") +plt.title("Histogram of Petal Lengths in Iris Dataset") +plt.xlabel("Petal Length (cm)") +plt.ylabel("Frequency") -if __name__ == "__main__": - main() +plt.show() +maidr.show(hist_plot) diff --git a/example/histogram/matplotlib/example_mpl_histogram.html b/example/histogram/matplotlib/example_mpl_histogram.html deleted file mode 100644 index bfc371c..0000000 --- a/example/histogram/matplotlib/example_mpl_histogram.html +++ /dev/null @@ -1,632 +0,0 @@ - - - - MAIDR - - - - -
- - - - - - 2024-03-03T08:42:30.024851 - image/svg+xml - - - Matplotlib v3.8.3, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/histogram/seaborn/example_sns_hist.py b/example/histogram/seaborn/example_sns_hist.py index 1047af4..0d701bb 100644 --- a/example/histogram/seaborn/example_sns_hist.py +++ b/example/histogram/seaborn/example_sns_hist.py @@ -1,40 +1,21 @@ -import os - import matplotlib.pyplot as plt import maidr import seaborn as sns -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Load the Iris dataset - iris = sns.load_dataset("iris") - - # Select the petal lengths - petal_lengths = iris["petal_length"] - - # Plot a histogram of the petal lengths - plt.figure(figsize=(10, 6)) - hist_plot = sns.histplot(petal_lengths, kde=True, color="blue", binwidth=0.5) - - plt.title("Histogram of Petal Lengths in Iris Dataset") - plt.xlabel("Petal Length (cm)") - plt.ylabel("Frequency") - - return hist_plot +# Load the Iris dataset +iris = sns.load_dataset("iris") +# Select the petal lengths +petal_lengths = iris["petal_length"] -def main(): - hist = plot() - hist_maidr = maidr.hist(hist) - hist_maidr.save_html(get_filepath("example_sns_histogram.html")) - hist_maidr.show() +# Plot a histogram of the petal lengths +plt.figure(figsize=(10, 6)) +hist_plot = sns.histplot(petal_lengths, kde=True, color="blue", binwidth=0.5) +plt.title("Histogram of Petal Lengths in Iris Dataset") +plt.xlabel("Petal Length (cm)") +plt.ylabel("Frequency") -if __name__ == "__main__": - main() +plt.show() +maidr.show(hist_plot) diff --git a/example/histogram/seaborn/example_sns_histogram.html b/example/histogram/seaborn/example_sns_histogram.html deleted file mode 100644 index 61edf70..0000000 --- a/example/histogram/seaborn/example_sns_histogram.html +++ /dev/null @@ -1,533 +0,0 @@ - - - - MAIDR - - - - -
- - - - - - 2024-03-03T08:47:29.135731 - image/svg+xml - - - Matplotlib v3.8.3, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/line/matplotlib/example_mpl_line.html b/example/line/matplotlib/example_mpl_line.html deleted file mode 100644 index f3e5f55..0000000 --- a/example/line/matplotlib/example_mpl_line.html +++ /dev/null @@ -1,471 +0,0 @@ - - - - MAIDR - - - - - - - - - -
- - - - - - 2024-03-04T11:20:18.194196 - image/svg+xml - - - Matplotlib v3.8.3, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/line/matplotlib/example_mpl_line.py b/example/line/matplotlib/example_mpl_line.py index 2570e25..f6b9e52 100644 --- a/example/line/matplotlib/example_mpl_line.py +++ b/example/line/matplotlib/example_mpl_line.py @@ -1,47 +1,30 @@ -import os - import maidr import matplotlib.pyplot as plt import seaborn as sns -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Load the flights dataset from seaborn - flights = sns.load_dataset("flights") - - # Pivot the dataset to wide form to make it easier to plot - flights_wide = flights.pivot(index="year", columns="month", values="passengers") - - # Create a time series by taking the sum of passengers per year - flights_wide["Total"] = flights_wide.sum(axis=1) - - # Reset index to use 'year' as a column - flights_wide.reset_index(inplace=True) - - # Plot the total number of passengers per year - plt.figure(figsize=(14, 7)) - line_plot = plt.plot(flights_wide["year"], flights_wide["Total"], marker="o") +# Load the flights dataset from seaborn +flights = sns.load_dataset("flights") - # Adding title and labels - plt.title("Total Passengers per Year\nFrom the Flights Dataset", fontsize=16) - plt.xlabel("Year", fontsize=12) - plt.ylabel("Total Passengers (Thousands)", fontsize=12) +# Pivot the dataset to wide form to make it easier to plot +flights_wide = flights.pivot(index="year", columns="month", values="passengers") - return line_plot +# Create a time series by taking the sum of passengers per year +flights_wide["Total"] = flights_wide.sum(axis=1) +# Reset index to use 'year' as a column +flights_wide.reset_index(inplace=True) -def main(): - line = plot() - line_maidr = maidr.line(line) - line_maidr.save_html(get_filepath("example_mpl_line.html")) - line_maidr.show() +# Plot the total number of passengers per year +plt.figure(figsize=(14, 7)) +line_plot = plt.plot(flights_wide["year"], flights_wide["Total"], marker="o") +# Adding title and labels +plt.title("Total Passengers per Year\nFrom the Flights Dataset", fontsize=16) +plt.xlabel("Year", fontsize=12) +plt.ylabel("Total Passengers (Thousands)", fontsize=12) -if __name__ == "__main__": - main() +# Show the plot +plt.show() +maidr.show(line_plot) +print() diff --git a/example/line/seaborn/example_sns_line.html b/example/line/seaborn/example_sns_line.html deleted file mode 100644 index f46605d..0000000 --- a/example/line/seaborn/example_sns_line.html +++ /dev/null @@ -1,701 +0,0 @@ - - - - MAIDR - - - - -
- - - - - - 2024-03-04T13:03:54.029318 - image/svg+xml - - - Matplotlib v3.8.3, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/line/seaborn/example_sns_line.py b/example/line/seaborn/example_sns_line.py index 9d53c43..ed4dc30 100644 --- a/example/line/seaborn/example_sns_line.py +++ b/example/line/seaborn/example_sns_line.py @@ -1,46 +1,27 @@ -import os - import matplotlib.pyplot as plt import maidr import seaborn as sns -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Load the 'tips' dataset from seaborn - tips = sns.load_dataset("tips") - - # Choose a specific subset of the dataset (e.g., data for 'Thursday') - subset_data = tips[tips["day"] == "Thur"] - - # Create a line plot - plt.figure(figsize=(10, 6)) - line_plot = sns.lineplot( - data=subset_data, - x="total_bill", - y="tip", - markers=True, - style="day", - legend=False, - ) - plt.title("Line Plot of Tips vs Total Bill (Thursday)") - plt.xlabel("Total Bill") - plt.ylabel("Tip") - - return line_plot - - -def main(): - line = plot() - line_maidr = maidr.line(line) - line_maidr.save_html(get_filepath("example_sns_line.html")) - line_maidr.show() - - -if __name__ == "__main__": - main() +# Load the 'tips' dataset from seaborn +tips = sns.load_dataset("tips") + +# Choose a specific subset of the dataset (e.g., data for 'Thursday') +subset_data = tips[tips["day"] == "Thur"] + +# Create a line plot +plt.figure(figsize=(10, 6)) +line_plot = sns.lineplot( + data=subset_data, + x="total_bill", + y="tip", + markers=True, + style="day", + legend=False, +) +plt.title("Line Plot of Tips vs Total Bill (Thursday)") +plt.xlabel("Total Bill") +plt.ylabel("Tip") + +plt.show() +maidr.show(line_plot) diff --git a/example/scatter/matplotlib/example_mpl_scatter.html b/example/scatter/matplotlib/example_mpl_scatter.html deleted file mode 100644 index 862931c..0000000 --- a/example/scatter/matplotlib/example_mpl_scatter.html +++ /dev/null @@ -1,1230 +0,0 @@ - - - - MAIDR - - - - -
- - - - - - 2024-03-19T16:55:54.809656 - image/svg+xml - - - Matplotlib v3.7.5, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/scatter/matplotlib/example_mpl_scatter.py b/example/scatter/matplotlib/example_mpl_scatter.py index 67b8322..6f95b90 100644 --- a/example/scatter/matplotlib/example_mpl_scatter.py +++ b/example/scatter/matplotlib/example_mpl_scatter.py @@ -1,39 +1,20 @@ -import os - import maidr import matplotlib.pyplot as plt import seaborn as sns -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Load the Iris dataset - iris = sns.load_dataset("iris") - - # Plot sepal_length vs sepal_width - plt.figure(figsize=(10, 6)) # Optional: Sets the figure size - scatter_plot = plt.scatter( - iris["sepal_length"], iris["sepal_width"], c="blue", label="Iris Data Points" - ) - plt.title("Iris Dataset: Sepal Length vs Sepal Width") # Title of the plot - plt.xlabel("Sepal Length (cm)") # X-axis label - plt.ylabel("Sepal Width (cm)") # Y-axis label - plt.legend() # Shows the legend - - return scatter_plot - - -def main(): - scatter = plot() - scatter_maidr = maidr.scatter(scatter) - scatter_maidr.save_html(get_filepath("example_mpl_scatter.html")) - scatter_maidr.show() +# Load the Iris dataset +iris = sns.load_dataset("iris") +# Plot sepal_length vs sepal_width +plt.figure(figsize=(10, 6)) # Optional: Sets the figure size +scatter_plot = plt.scatter( + iris["sepal_length"], iris["sepal_width"], c="blue", label="Iris Data Points" +) +plt.title("Iris Dataset: Sepal Length vs Sepal Width") # Title of the plot +plt.xlabel("Sepal Length (cm)") # X-axis label +plt.ylabel("Sepal Width (cm)") # Y-axis label +plt.legend() # Shows the legend -if __name__ == "__main__": - main() +plt.show() +maidr.show(scatter_plot) diff --git a/example/scatter/seaborn/example_sns_scatter.html b/example/scatter/seaborn/example_sns_scatter.html deleted file mode 100644 index 2199a3e..0000000 --- a/example/scatter/seaborn/example_sns_scatter.html +++ /dev/null @@ -1,1558 +0,0 @@ - - - - MAIDR - - - - -
- - - - - - 2024-03-19T17:12:09.149926 - image/svg+xml - - - Matplotlib v3.7.5, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/example/scatter/seaborn/example_sns_scatter.py b/example/scatter/seaborn/example_sns_scatter.py index 7b87a45..17c8a72 100644 --- a/example/scatter/seaborn/example_sns_scatter.py +++ b/example/scatter/seaborn/example_sns_scatter.py @@ -1,39 +1,21 @@ -import os - import matplotlib.pyplot as plt import maidr import seaborn as sns -def get_filepath(filename: str) -> str: - current_file_path = os.path.abspath(__file__) - directory = os.path.dirname(current_file_path) - return os.path.join(directory, filename) - - -def plot(): - # Load the Iris dataset - iris = sns.load_dataset("iris") - - # Create a scatter plot - scatter_plot = sns.scatterplot( - data=iris, x="sepal_length", y="sepal_width", hue="species" - ) - - # Adding title and labels (optional) - plt.title("Iris Sepal Length vs Sepal Width") - plt.xlabel("Sepal Length") - plt.ylabel("Sepal Width") - - return scatter_plot - +# Load the Iris dataset +iris = sns.load_dataset("iris") -def main(): - scatter = plot() - scatter_maidr = maidr.scatter(scatter) - scatter_maidr.save_html(get_filepath("example_sns_scatter.html")) - scatter_maidr.show() +# Create a scatter plot +scatter_plot = sns.scatterplot( + data=iris, x="sepal_length", y="sepal_width", hue="species" +) +# Adding title and labels (optional) +plt.title("Iris Sepal Length vs Sepal Width") +plt.xlabel("Sepal Length") +plt.ylabel("Sepal Width") -if __name__ == "__main__": - main() +# Show the plot +plt.show() +maidr.show(scatter_plot) diff --git a/example/utils/__init__.py b/example/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/example/utils/box.html b/example/utils/box.html new file mode 100644 index 0000000..d645f3c --- /dev/null +++ b/example/utils/box.html @@ -0,0 +1,470 @@ + + + + + + MAIDR + + + + +
+ + + + + 2024-06-10T19:49:48.481950 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/example/utils/file_utils.py b/example/utils/file_utils.py new file mode 100644 index 0000000..994bb04 --- /dev/null +++ b/example/utils/file_utils.py @@ -0,0 +1,28 @@ +import os + + +def example_path(filename: str) -> str: + current_file_path = os.path.abspath(__file__) + directory = os.path.dirname(current_file_path) + return os.path.join(directory, filename) + + +import matplotlib.pyplot as plt +import seaborn as sns +import maidr + + +fig, ax = plt.subplots() +# box = sns.boxplot(data=[[1, 2, 3], [4, 5, 6], [7, 8, 9]], ax=ax) +# ax.set_title("Test seaborn box title") +# ax.set_xlabel("Test seaborn x label") +# ax.set_ylabel("Test seaborn y label") +# +# plt.show() + +ax.boxplot([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) +ax.set_title("Test matplotlib box title") +ax.set_xlabel("Test matplotlib box x label") +ax.set_ylabel("Test matplotlib box y label") + +plt.show() diff --git a/maidr/__init__.py b/maidr/__init__.py index 12ec649..694d27c 100644 --- a/maidr/__init__.py +++ b/maidr/__init__.py @@ -2,15 +2,11 @@ from .core import Maidr from .core.enum import PlotType -from .maidr import bar, box, count, heat, hist, line, scatter, stacked +from .patch import barplot, boxplot, heatmap, histogram, lineplot, scatterplot +from .maidr import save_html, show, stacked __all__ = [ - "bar", - "box", - "count", - "heat", - "hist", - "line", - "scatter", + "save_html", + "show", "stacked", ] diff --git a/maidr/core/context_manager.py b/maidr/core/context_manager.py new file mode 100644 index 0000000..2fdec44 --- /dev/null +++ b/maidr/core/context_manager.py @@ -0,0 +1,43 @@ +import contextlib +import contextvars +import threading + +import wrapt + + +class ContextManager: + _instance = None + _lock = threading.Lock() + + _internal_context = contextvars.ContextVar("internal_context", default=False) + + def __new__(cls): + if not cls._instance: + with cls._lock: + if not cls._instance: + cls._instance = super(ContextManager, cls).__new__() + return cls._instance + + @classmethod + @contextlib.contextmanager + def set_internal_context(cls): + token_internal_context = cls._internal_context.set(True) + try: + yield + finally: + cls._internal_context.reset(token_internal_context) + + @classmethod + def is_internal_context(cls): + return cls._internal_context.get() + + +@wrapt.decorator +def manage_context(wrapped=None, _=None, args=None, kwargs=None): + # Don't proceed if the call is made internally by the patched function. + if ContextManager.is_internal_context(): + return wrapped(*args, **kwargs) + + # Set the internal context to avoid cyclic processing. + with ContextManager.set_internal_context(): + return wrapped(*args, **kwargs) diff --git a/maidr/core/enum/__init__.py b/maidr/core/enum/__init__.py index e4db007..6c0319e 100644 --- a/maidr/core/enum/__init__.py +++ b/maidr/core/enum/__init__.py @@ -1,2 +1,3 @@ +from .library import Library from .maidr_key import MaidrKey from .plot_type import PlotType diff --git a/tests/core/enum/library.py b/maidr/core/enum/library.py similarity index 75% rename from tests/core/enum/library.py rename to maidr/core/enum/library.py index 2ec5c64..679b9a3 100644 --- a/tests/core/enum/library.py +++ b/maidr/core/enum/library.py @@ -1,6 +1,6 @@ from enum import Enum -class Library(Enum): +class Library(str, Enum): MATPLOTLIB = "matplotlib" SEABORN = "seaborn" diff --git a/maidr/core/enum/plot_type.py b/maidr/core/enum/plot_type.py index d46dd5d..75019bd 100644 --- a/maidr/core/enum/plot_type.py +++ b/maidr/core/enum/plot_type.py @@ -6,6 +6,7 @@ class PlotType(str, Enum): BAR = "bar" BOX = "box" + COUNT = "count" DODGED = "dodged_bar" HEAT = "heat" HIST = "hist" diff --git a/maidr/core/figure_manager.py b/maidr/core/figure_manager.py index 565862f..de26516 100644 --- a/maidr/core/figure_manager.py +++ b/maidr/core/figure_manager.py @@ -1,5 +1,6 @@ from __future__ import annotations from typing import Any +import threading from matplotlib.artist import Artist from matplotlib.axes import Axes @@ -33,7 +34,17 @@ class FigureManager: Recursively extracts Axes objects from the input artist or container. """ - figs = dict() + figs = {} + + _instance = None + _lock = threading.Lock() + + def __new__(cls): + if not cls._instance: + with cls._lock: + if not cls._instance: + cls._instance = super(FigureManager, cls).__new__() + return cls._instance @classmethod def create_maidr(cls, ax: Axes, plot_type: PlotType, **kwargs) -> Maidr: @@ -59,6 +70,13 @@ def _get_maidr(cls, fig: Figure) -> Maidr: cls.figs[fig] = Maidr(fig) return cls.figs[fig] + @classmethod + def get_maidr(cls, fig: Figure) -> Maidr: + """Retrieve the Maidr instance for the given Figure.""" + if fig not in cls.figs.keys(): + raise ValueError(f"No MAIDR found for figure: {fig}.") + return cls.figs[fig] + @staticmethod def get_axes( artist: Artist | Axes | BarContainer | dict | list | None, diff --git a/maidr/core/plot/bar_plot.py b/maidr/core/plot/barplot.py similarity index 93% rename from maidr/core/plot/bar_plot.py rename to maidr/core/plot/barplot.py index 461ae97..e24954a 100644 --- a/maidr/core/plot/bar_plot.py +++ b/maidr/core/plot/barplot.py @@ -15,14 +15,13 @@ class BarPlot(MaidrPlot, ContainerExtractorMixin, LevelExtractorMixin, DictMergerMixin): def __init__(self, ax: Axes) -> None: - self.__level = self.extract_level(ax) super().__init__(ax, PlotType.BAR) def _extract_axes_data(self) -> dict: base_schema = super()._extract_axes_data() bar_ax_schema = { MaidrKey.X: { - MaidrKey.LEVEL: self.__level, + MaidrKey.LEVEL: self.extract_level(self.ax), }, } return self.merge_dict(base_schema, bar_ax_schema) @@ -47,7 +46,7 @@ def _extract_bar_container_data( # So, extract data correspondingly based on the level. # Flatten all the `list[BarContainer]` to `list[Patch]`. plot = [patch for container in plot for patch in container.patches] - level = self.__level + level = self.extract_level(self.ax) if len(plot) != len(level): return None diff --git a/maidr/core/plot/box_plot.py b/maidr/core/plot/boxplot.py similarity index 67% rename from maidr/core/plot/box_plot.py rename to maidr/core/plot/boxplot.py index e250835..f92a136 100644 --- a/maidr/core/plot/box_plot.py +++ b/maidr/core/plot/boxplot.py @@ -12,40 +12,37 @@ ) -class BoxPlotContainer: - """Custom wrapper mirroring seaborn.categorical.BoxPlotContainer""" - - def __init__(self, artist_dict): - self.boxes = artist_dict["boxes"] - self.medians = artist_dict["medians"] - self.whiskers = artist_dict["whiskers"] - self.caps = artist_dict["caps"] - self.fliers = artist_dict["fliers"] - - self._label = None - self._children = [ - *self.boxes, - *self.medians, - *self.whiskers, - *self.caps, - *self.fliers, - ] +class BoxPlotContainer(DictMergerMixin): + def __init__(self): + self.boxes = [] + self.medians = [] + self.whiskers = [] + self.caps = [] + self.fliers = [] def __repr__(self): return f"" - def get_label(self): - return self._label - - def set_label(self, value): - self._label = value - - def get_children(self): - return self._children - - def remove(self): - for child in self._children: - child.remove() + def add_artists(self, artist: dict): + for box in artist["boxes"]: + self.boxes.append(box) + for median in artist["medians"]: + self.medians.append(median) + for whisker in artist["whiskers"]: + self.whiskers.append(whisker) + for cap in artist["caps"]: + self.caps.append(cap) + for flier in artist["fliers"]: + self.fliers.append(flier) + + def bxp_stats(self) -> dict: + return { + "boxes": self.boxes, + "medians": self.medians, + "whiskers": self.whiskers, + "caps": self.caps, + "fliers": self.fliers, + } class _BoxPlotExtractorMixin: @@ -114,7 +111,7 @@ class BoxPlot( DictMergerMixin, ): def __init__(self, ax: Axes, **kwargs) -> None: - self.__container_type = kwargs.pop("container_type") + self._bxp_stats = kwargs.pop("bxp_stats", None) super().__init__(ax, PlotType.BOX) def _extract_axes_data(self) -> dict: @@ -127,20 +124,22 @@ def _extract_axes_data(self) -> dict: return self.merge_dict(base_ax_schema, box_ax_schema) def _extract_plot_data(self) -> list: - plot = self.extract_container(self.ax, self.__container_type) - data = self._extract_box_container_data(plot) + data = self._extract_bxp_maidr(self._bxp_stats) if data is None: - raise ExtractionError(self.type, plot) + raise ExtractionError(self.type, self.ax) return data - def _extract_bxp_maidr(self, bxpstats: dict) -> list[dict]: + def _extract_bxp_maidr(self, bxp_stats: dict) -> list[dict] | None: + if bxp_stats is None: + return None + bxp_maidr = list() - whiskers = self.extract_whiskers(bxpstats["whiskers"]) - caps = self.extract_caps(bxpstats["caps"]) - medians = self.extract_medians(bxpstats["medians"]) - outliers = self.extract_outliers(bxpstats["fliers"], caps) + whiskers = self.extract_whiskers(bxp_stats["whiskers"]) + caps = self.extract_caps(bxp_stats["caps"]) + medians = self.extract_medians(bxp_stats["medians"]) + outliers = self.extract_outliers(bxp_stats["fliers"], caps) for whisker, cap, median, outlier in zip(whiskers, caps, medians, outliers): bxp_maidr.append( @@ -156,13 +155,3 @@ def _extract_bxp_maidr(self, bxpstats: dict) -> list[dict]: ) return bxp_maidr - - def _extract_box_container_data(self, plot: BoxPlotContainer | None) -> list[dict]: - bxpstats = { - "whiskers": plot.whiskers, - "medians": plot.medians, - "caps": plot.caps, - "fliers": plot.fliers, - } - - return self._extract_bxp_maidr(bxpstats) diff --git a/maidr/core/plot/grouped_bar_plot.py b/maidr/core/plot/grouped_barplot.py similarity index 100% rename from maidr/core/plot/grouped_bar_plot.py rename to maidr/core/plot/grouped_barplot.py diff --git a/maidr/core/plot/heat_plot.py b/maidr/core/plot/heatmap.py similarity index 96% rename from maidr/core/plot/heat_plot.py rename to maidr/core/plot/heatmap.py index 7b43171..adaec3b 100644 --- a/maidr/core/plot/heat_plot.py +++ b/maidr/core/plot/heatmap.py @@ -21,8 +21,8 @@ def __init__(self, ax: Axes, **kwargs) -> None: self._fill_label = kwargs.pop("fill_label") super().__init__(ax, PlotType.HEAT) - def _init_maidr(self) -> dict: - base_maidr = super()._init_maidr() + def render(self) -> dict: + base_maidr = super().render() heat_maidr = { MaidrKey.LABELS: { MaidrKey.FILL: self._fill_label, diff --git a/maidr/core/plot/hist_plot.py b/maidr/core/plot/histogram.py similarity index 100% rename from maidr/core/plot/hist_plot.py rename to maidr/core/plot/histogram.py diff --git a/maidr/core/plot/line_plot.py b/maidr/core/plot/lineplot.py similarity index 100% rename from maidr/core/plot/line_plot.py rename to maidr/core/plot/lineplot.py diff --git a/maidr/core/plot/maidr_plot.py b/maidr/core/plot/maidr_plot.py index ee4f6e1..49ca179 100644 --- a/maidr/core/plot/maidr_plot.py +++ b/maidr/core/plot/maidr_plot.py @@ -40,9 +40,9 @@ def __init__(self, ax: Axes, plot_type: PlotType) -> None: # MAIDR data self.type = plot_type - self._schema = self._init_maidr() + self._schema = {} - def _init_maidr(self) -> dict: + def render(self) -> dict: """Initialize the MAIDR schema dictionary with basic plot information.""" return { MaidrKey.TYPE: self.type, @@ -70,8 +70,12 @@ def _extract_plot_data(self) -> list | dict: @property def schema(self) -> dict: """Return the MAIDR schema of the plot as a dictionary.""" + if not self._schema: + self._schema = self.render() return self._schema def set_id(self, maidr_id: str) -> None: """Set the unique identifier for the plot within the MAIDR schema.""" + if not self._schema: + self._schema = self.render() self._schema[MaidrKey.ID.value] = maidr_id diff --git a/maidr/core/plot/maidr_plot_factory.py b/maidr/core/plot/maidr_plot_factory.py index a3ff2b8..6f8a02e 100644 --- a/maidr/core/plot/maidr_plot_factory.py +++ b/maidr/core/plot/maidr_plot_factory.py @@ -4,13 +4,13 @@ from maidr.core.enum import PlotType from maidr.core.plot.maidr_plot import MaidrPlot -from maidr.core.plot.bar_plot import BarPlot -from maidr.core.plot.box_plot import BoxPlot -from maidr.core.plot.heat_plot import HeatPlot -from maidr.core.plot.hist_plot import HistPlot -from maidr.core.plot.line_plot import LinePlot -from maidr.core.plot.scatter_plot import ScatterPlot -from maidr.core.plot.grouped_bar_plot import GroupedBarPlot +from maidr.core.plot.barplot import BarPlot +from maidr.core.plot.boxplot import BoxPlot +from maidr.core.plot.heatmap import HeatPlot +from maidr.core.plot.histogram import HistPlot +from maidr.core.plot.lineplot import LinePlot +from maidr.core.plot.scatterplot import ScatterPlot +from maidr.core.plot.grouped_barplot import GroupedBarPlot class MaidrPlotFactory: @@ -30,7 +30,7 @@ class MaidrPlotFactory: @staticmethod def create(ax: Axes, plot_type: PlotType, **kwargs) -> MaidrPlot: - if PlotType.BAR == plot_type: + if PlotType.BAR == plot_type or PlotType.COUNT == plot_type: return BarPlot(ax) elif PlotType.BOX == plot_type: return BoxPlot(ax, **kwargs) diff --git a/maidr/core/plot/scatter_plot.py b/maidr/core/plot/scatterplot.py similarity index 100% rename from maidr/core/plot/scatter_plot.py rename to maidr/core/plot/scatterplot.py diff --git a/maidr/maidr.py b/maidr/maidr.py index 8b35178..14dc5fa 100644 --- a/maidr/maidr.py +++ b/maidr/maidr.py @@ -1,451 +1,27 @@ from __future__ import annotations +from typing import Literal, Any + from matplotlib.axes import Axes -from matplotlib.collections import QuadMesh, PathCollection from matplotlib.container import BarContainer -from matplotlib.image import AxesImage -from matplotlib.lines import Line2D from maidr.core import Maidr from maidr.core.enum import PlotType from maidr.core.figure_manager import FigureManager -from maidr.core.plot.box_plot import BoxPlotContainer - - -def bar(plot: Axes | BarContainer) -> Maidr: - r""" - Create and return a Maidr object representing a bar plot. - - Parameters - ---------- - plot : Axes | BarContainer - A matplotlib or seaborn plot containing the bar plot data, either as an - ``matplotlib.axes.Axes`` object with bar plot elements or directly as a - ``matplotlib.container.BarContainer`` object. - - Returns - ------- - Maidr - An instance of the ``maidr.core.Maidr`` class representing the bar plot. - - Raises - ------ - ValueError - If `plot` is missing the ``matplotlib.figure.Figure`` or - ``matplotlib.figure.Axes``. - ExtractionError - If bar plot data is not extractable from `plot`. - - See Also - -------- - maidr.core.Maidr : The core class encapsulating the plot with its MAIDR structure. - maidr.count : Function to create a Maidr object for seaborn count plot. - - Notes - ----- - The input plot must be part of a ``matplotlib.figure.Figure``. - - Examples - -------- - Matplotlib - - >>> import matplotlib.pyplot as plt - >>> import maidr - >>> bar_plot = plt.bar(['A', 'B', 'C'], [1, 2, 3]) - >>> bar_maidr = maidr.bar(bar_plot) - >>> bar_maidr.show() - - Seaborn - - >>> import seaborn as sns - >>> import maidr - >>> tips = sns.load_dataset("tips") - >>> bar_plot = sns.barplot(x="day", y="total_bill", data=tips) - >>> bar_maidr = maidr.bar(bar_plot) - >>> bar_maidr.show() - """ - ax = FigureManager.get_axes(plot) - return FigureManager.create_maidr(ax, PlotType.BAR) - - -def get_sns_container() -> type[BoxPlotContainer]: - """Return the BoxPlotContainer class from seaborn if version >= 0.12, else raise ImportError.""" # noqa - from packaging import version - import seaborn.categorical - - min_version = "0.12" - sns_version = seaborn.__version__ # type: ignore - - if version.parse(sns_version) < version.parse(min_version): - raise ImportError( - f"Seaborn>={min_version} is required, but found {sns_version}." - ) - else: - return seaborn.categorical.BoxPlotContainer # type: ignore - - -def box(plot: Axes | dict) -> Maidr: - r""" - Create and return a Maidr object representing a box plot. - - Parameters - ---------- - plot : Axes | dict - A matplotlib or seaborn plot containing the box plot data, either as a - ``matplotlib.axes.Axes`` object containing the box plot elements, or as a - dictionary mapping each component of the boxplot to a list of the - ``matplotlib.lines.Line2D`` instances created. - - If a dictionary is provided, the dictionary should have the following keys: - - - ``boxes``: the main body of the boxplot showing the quartiles and the - median's confidence intervals if enabled. - - - ``medians``: horizontal lines at the median of each box. - - - ``whiskers``: the vertical lines extending to the most extreme, non-outlier - data points. - - - ``caps``: the horizontal lines at the ends of the whiskers. - - - ``fliers``: points representing data that extend beyond the whiskers (fliers). - - Returns - ------- - Maidr - An instance of the ``maidr.core.Maidr`` class representing the box plot. - - Raises - ------ - ValueError - If `plot` is missing the ``matplotlib.figure.Figure`` or - ``matplotlib.figure.Axes``. - ImportError - If `plot` is created using seaborn and the seaborn version is less than 0.12. - ExtractionError - If box plot data is not extractable from `plot`. - - See Also - -------- - maidr.core.Maidr : The core class encapsulating the plot with its MAIDR structure. - - Warnings - ________ - This function is dependent on ``seaborn.categorical.BoxPlotContainer``, when using - seaborn, which requires seaborn version 0.12 or higher. - - Notes - ----- - The Axes object or dictionary values must be part of a ``matplotlib.figure.Figure``. - - Examples - ________ - Matplotlib - - >>> import matplotlib.pyplot as plt - >>> import maidr - >>> data = [25, 28, 29, 29, 30, 34, 35, 35, 37, 38] - >>> box_plot = plt.boxplot(data) - >>> box_maidr = maidr.box(box_plot) - >>> box_maidr.show() - - Seaborn - - >>> import seaborn as sns - >>> import maidr - >>> iris = sns.load_dataset("iris") - >>> box_plot = sns.boxplot(x="species", y="petal_length", data=iris) - >>> box_maidr = maidr.box(box_plot) - >>> box_maidr.show() - """ - ax = FigureManager.get_axes(plot) - if not isinstance(plot, dict): - cntr_type = get_sns_container() - else: - ax.add_container(BoxPlotContainer(plot)) - cntr_type = BoxPlotContainer - - return FigureManager.create_maidr(ax, PlotType.BOX, container_type=cntr_type) - - -def count(plot: Axes) -> Maidr: - r""" - Create and return a Maidr object representing a count plot. - - Parameters - ---------- - plot : Axes - A `matplotlib.axes.Axes` object containing the count plot elements. - - Returns - ------- - Maidr - An instance of the ``maidr.core.Maidr`` class representing the count plot. - - Raises - ------ - ValueError - If `plot` is missing the `matplotlib.figure.Figure` or `matplotlib.figure.Axes`. - ExtractionError - If count plot data is not extractable from `plot`. - - See Also - -------- - maidr.core.Maidr : The core class encapsulating the plot with its MAIDR structure. - maidr.bar : Function to create a Maidr object for matplotlib bar plot. - - Notes - ----- - - The Axes object must be part of a ``matplotlib.figure.Figure``. - - Since a count plot is a specific case of a bar plot, this function internally uses - the `bar()` function to process the plot. The `count()` function is provided as a - convenience to align with the `seaborn.countplot()` method. - - Examples - -------- - Seaborn - >>> import seaborn as sns - >>> import maidr - >>> data = sns.load_dataset("titanic") - >>> count_plot = sns.countplot(x="class", data=data) - >>> count_maidr = maidr.count(count_plot) - >>> count_maidr.show() - """ - return bar(plot) - -def heat(plot: Axes | AxesImage | QuadMesh, *, fill_label: str = "Fill value") -> Maidr: - r""" - Create and return a Maidr object representing a heatmap. - - Parameters - ---------- - plot : Axes | AxesImage | QuadMesh - A matplotlib or seaborn plot containing heatmap data. This can be an - ``matplotlib.axes.Axes`` instance with heatmap elements, or more directly, an - ``matplotlib.image.AxesImage`` or ``matplotlib.collections.QuadMesh``. - fill_label : str, default="Fill value" - Label describing the fill value in the heatmap, by default "Fill value". - - Returns - ------- - Maidr - An instance of the ``maidr.core.Maidr`` class representing the heatmap. - - Raises - ------ - ValueError - If `plot` is missing the ``matplotlib.figure.Figure`` or - ``matplotlib.axes.Axes``. - ExtractionError - If heatmap data is not extractable from `plot`. - - See Also - -------- - maidr.core.Maidr : The core class for encapsulating plots with MAIDR structure. - - Notes - ----- - The input plot must be part of a ``matplotlib.figure.Figure``. - - Examples - -------- - Matplotlib - - >>> import matplotlib.pyplot as plt - >>> import numpy as np - >>> data = np.random.rand(10, 10) - >>> fig, _ax = plt.subplots() - >>> heatmap = _ax.imshow(data, cmap='hot') - >>> heat_maidr = maidr.heat(heatmap) - >>> heat_maidr.show() - - Seaborn - - >>> import seaborn as sns - >>> import maidr - >>> flights = sns.load_dataset("flights") - >>> flights = flights.pivot("month", "year", "passengers") - >>> heatmap = sns.heatmap(flights) - >>> heat_maidr = maidr.heat(heatmap, fill_label="Passenger count") - >>> heat_maidr.show() - """ +def show(plot: Any, renderer: Literal["auto", "ipython", "browser"] = "auto") -> object: ax = FigureManager.get_axes(plot) - return FigureManager.create_maidr(ax, PlotType.HEAT, fill_label=fill_label) - - -def hist(plot: Axes | BarContainer) -> Maidr: - r""" - Create and return a Maidr object representing a histogram plot. + maidr = FigureManager.get_maidr(ax.get_figure()) + return maidr.show(renderer) - Parameters - ---------- - plot : Axes | BarContainer - A matplotlib or seaborn plot containing the histogram plot data, which can be - an ``matplotlib.axes.Axes`` object with histogram plot elements, a - ``matplotlib.container.BarContainer`` which represents the bins of a histogram. - Returns - ------- - Maidr - An instance of the ``maidr.core.Maidr`` class representing the histogram plot. - - Raises - ------ - ValueError - If `plot` is missing the ``matplotlib.figure.Figure`` or - ``matplotlib.figure.Axes``. - ExtractionError - If histogram plot data is not extractable from `plot`. - - See Also - -------- - maidr.core.Maidr : The core class encapsulating the plot with its MAIDR structure. - - Notes - ----- - The input plot must be part of a ``matplotlib.figure.Figure``. - - Examples - -------- - Matplotlib - - >>> import matplotlib.pyplot as plt - >>> import maidr - >>> import numpy as np - >>> data = [np.random.normal(0, 100) for _ in range(1, 4)] - >>> _, _, hist_plot = plt.hist(data, bins=30) - >>> hist_maidr = maidr.hist(hist_plot) - >>> hist_maidr.show() - - Seaborn - - >>> import seaborn as sns - >>> import maidr - >>> tips = sns.load_dataset("tips") - >>> hist_plot = sns.histplot(tips['total_bill'], bins=20) - >>> hist_maidr = maidr.hist(hist_plot) - >>> hist_maidr.show() - """ +def save_html( + plot: Any, file: str, *, lib_dir: str | None = "lib", include_version: bool = True +) -> str: ax = FigureManager.get_axes(plot) - return FigureManager.create_maidr(ax, PlotType.HIST) - - -def line(plot: Axes | list[Line2D]) -> Maidr: - r""" - Create and return a Maidr object representing a line plot. - - Parameters - ---------- - plot : Axes | list[Line2D] - A matplotlib or seaborn plot containing the line plot data. This can be a - ``matplotlib.axes.Axes`` object with line plot elements or a list of - ``matplotlib.lines.Line2D`` objects. - - Returns - ------- - Maidr - An instance of the ``maidr.core.Maidr`` class representing the line plot. - - Raises - ------ - ValueError - If `plot` is missing the ``matplotlib.figure.Figure`` or - ``matplotlib.figure.Axes``. - ExtractionError - If line plot data is not extractable from `plot`. - - See Also - -------- - maidr.core.Maidr : The core class encapsulating the plot with its MAIDR structure. - - Notes - ----- - - The input plot must be part of a ``matplotlib.figure.Figure``. - - If multiple lines are present, only the last one will be represented with MAIDR - structure. - - Examples - -------- - Matplotlib - - >>> import matplotlib.pyplot as plt - >>> import maidr - >>> line_plot = plt.plot([1, 2, 3], [4, 5, 6]) - >>> line_maidr = maidr.line(ax) - >>> line_maidr.save_html("maidr_line_plot.html") - >>> line_maidr.show() - - Seaborn - - >>> import seaborn as sns - >>> import maidr - >>> tips = sns.load_dataset("tips") - >>> subset_data = tips[tips["day"] == "Thur"] - >>> line_plot = sns.lineplot(data=subset_data, x="total_bill", y="tip") - >>> line_maidr = maidr.line(line_plot) - >>> line_maidr.show() - """ - ax = FigureManager.get_axes(plot) - return FigureManager.create_maidr(ax, PlotType.LINE) - - -def scatter(plot: Axes | PathCollection) -> Maidr: - r""" - Create and return a Maidr object representing a scatter plot. - - Parameters - ---------- - plot : Axes | PathCollection - A matplotlib or seaborn plot that contains scatter plot data. This can be an - ``matplotlib.axes.Axes`` instance with a scatter plot or a - ``matplotlib.collections.PathCollection`` directly. - - Returns - ------- - Maidr - An instance of the Maidr class representing the scatter plot. - - Raises - ------ - ValueError - If `plot` is missing the ``matplotlib.figure.Figure`` or - ``matplotlib.figure.Axes``. - ExtractionError - If scatter plot data is not extractable from `plot`. - - See Also - -------- - maidr.core.Maidr : The core class encapsulating the plot with its MAIDR structure. - - Notes - ----- - The input plot must be part of a ``matplotlib.figure.Figure``. - - Examples - -------- - Matplotlib - - >>> import matplotlib.pyplot as plt - >>> import maidr - >>> x = [1, 2, 3] - >>> y = [4, 5, 6] - >>> scatter_plot = plt.scatter(x, y) - >>> scatter_maidr = maidr.scatter(scatter_plot) - >>> scatter_maidr.show() - - Seaborn - - >>> import seaborn as sns - >>> import maidr - >>> tips = sns.load_dataset("tips") - >>> scatter_plot = sns.scatterplot(x="total_bill", y="tip", data=tips) - >>> scatter_maidr = maidr.scatter(scatter_plot) - >>> scatter_maidr.show() - """ - ax = FigureManager.get_axes(plot) - return FigureManager.create_maidr(ax, PlotType.SCATTER) + maidr = FigureManager.get_maidr(ax.get_figure()) + return maidr.save_html(file, lib_dir=lib_dir, include_version=include_version) def stacked(plot: Axes | BarContainer) -> Maidr: @@ -455,3 +31,22 @@ def stacked(plot: Axes | BarContainer) -> Maidr: def close() -> None: pass + + +def test_enum_comparison(): + print( + f"PlotType.COUNT == PlotType.BAR: {PlotType.COUNT == PlotType.BAR}" + ) # Should be False + print( + f"PlotType.COUNT is PlotType.BAR: {PlotType.COUNT is PlotType.BAR}" + ) # Should be False + print( + f"PlotType.COUNT == PlotType.COUNT: {PlotType.COUNT == PlotType.COUNT}" + ) # Should be True + print( + f"PlotType.BAR == PlotType.BAR: {PlotType.BAR == PlotType.BAR}" + ) # Should be True + print( + f"PlotType.COUNT is PlotType.COUNT: {PlotType.COUNT is PlotType.COUNT}" + ) # Should be True + print(f"PlotType.BAR is PlotType.BAR: {PlotType.BAR is PlotType.BAR}") diff --git a/maidr/patch/__init__.py b/maidr/patch/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/maidr/patch/barplot.py b/maidr/patch/barplot.py new file mode 100644 index 0000000..63a15dc --- /dev/null +++ b/maidr/patch/barplot.py @@ -0,0 +1,22 @@ +from __future__ import annotations + +import wrapt + +from matplotlib.axes import Axes +from matplotlib.container import BarContainer + +from maidr.core.enum import PlotType +from maidr.patch.common import common + + +def bar(wrapped, instance, args, kwargs) -> Axes | BarContainer: + return common(PlotType.BAR, wrapped, instance, args, kwargs) + + +# Patch matplotlib functions. +wrapt.wrap_function_wrapper(Axes, "bar", bar) +wrapt.wrap_function_wrapper(Axes, "barh", bar) + +# Patch seaborn functions. +wrapt.wrap_function_wrapper("seaborn", "barplot", bar) +wrapt.wrap_function_wrapper("seaborn", "countplot", bar) diff --git a/maidr/patch/boxplot.py b/maidr/patch/boxplot.py new file mode 100644 index 0000000..ceba5c5 --- /dev/null +++ b/maidr/patch/boxplot.py @@ -0,0 +1,71 @@ +from __future__ import annotations + +import contextlib +import contextvars +import wrapt + +from matplotlib.axes import Axes + +from maidr.core.context_manager import ContextManager +from maidr.core.enum import PlotType +from maidr.core.figure_manager import FigureManager +from maidr.core.plot.boxplot import BoxPlotContainer + + +class BoxplotContextManager(ContextManager): + _bxp_context = contextvars.ContextVar("bxp_context", default=BoxPlotContainer()) + + @classmethod + @contextlib.contextmanager + def set_internal_context(cls): + with super(BoxplotContextManager, cls).set_internal_context(): + token = cls._bxp_context.set(BoxPlotContainer()) + try: + yield cls.get_bxp_context() + finally: + cls._bxp_context.reset(token) + + @classmethod + def get_bxp_context(cls) -> BoxPlotContainer: + return cls._bxp_context.get() + + @classmethod + def add_bxp_context(cls, bxp_context: dict) -> None: + cls.get_bxp_context().add_artists(bxp_context) + + +@wrapt.patch_function_wrapper(Axes, "bxp") +def mpl_box(wrapped, _, args, kwargs) -> dict: + # Don't proceed if the call is made internally by the patched function. + if BoxplotContextManager.is_internal_context(): + plot = wrapped(*args, **kwargs) + BoxplotContextManager.add_bxp_context(plot) + return plot + + # Set the internal context to avoid cyclic processing. + with ContextManager.set_internal_context(): + # Patch `ax.boxplot()` and `ax.bxp()`. + plot = wrapped(*args, **kwargs) + + # Extract the boxplot data points for MAIDR from the plot. + ax = FigureManager.get_axes(plot) + FigureManager.create_maidr(ax, PlotType.BOX, bxp_stats=plot) + + # Return to the caller. + return plot + + +@wrapt.patch_function_wrapper("seaborn", "boxplot") +def sns_box(wrapped, _, args, kwargs) -> Axes: + # Set the internal context to avoid cyclic processing. + with BoxplotContextManager.set_internal_context() as bxp_context: + # Patch `ax.boxplot()` and `ax.bxp()`. + plot = wrapped(*args, **kwargs) + bxp_container = bxp_context + + # Extract the boxplot data points for MAIDR from the plot. + ax = FigureManager.get_axes(bxp_container.bxp_stats()) + FigureManager.create_maidr(ax, PlotType.BOX, bxp_stats=bxp_container.bxp_stats()) + + # Return to the caller. + return plot diff --git a/maidr/patch/common.py b/maidr/patch/common.py new file mode 100644 index 0000000..061c972 --- /dev/null +++ b/maidr/patch/common.py @@ -0,0 +1,23 @@ +from __future__ import annotations + +from typing import Any + +from maidr.core.context_manager import ContextManager +from maidr.core.figure_manager import FigureManager + + +def common(plot_type, wrapped, _, args, kwargs) -> Any: + # Don't proceed if the call is made internally by the patched function. + if ContextManager.is_internal_context(): + return wrapped(*args, **kwargs) + + # Set the internal context to avoid cyclic processing. + with ContextManager.set_internal_context(): + # Patch the plotting function. + plot = wrapped(*args, **kwargs) + + # Extract the data points for MAIDR from the plot. + ax = FigureManager.get_axes(plot) + FigureManager.create_maidr(ax, plot_type) + + return plot diff --git a/maidr/patch/heatmap.py b/maidr/patch/heatmap.py new file mode 100644 index 0000000..5bca950 --- /dev/null +++ b/maidr/patch/heatmap.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +import wrapt + +from matplotlib.axes import Axes +from matplotlib.image import AxesImage + +from maidr.core.enum import PlotType +from maidr.core.figure_manager import FigureManager + + +def heat(wrapped, _, args, kwargs) -> Axes | AxesImage: + # Check for additional label used by MAIDR heatmap. + fill_label = kwargs.pop("fill_label", "Fill") + + # Patch `ax.imshow()` and `seaborn.heatmap`. + plot = wrapped(*args, **kwargs) + + # Extract the heatmap data points for MAIDR from the plots. + ax = FigureManager.get_axes(plot) + FigureManager.create_maidr(ax, PlotType.HEAT, fill_label=fill_label) + + # Return to the caller. + return plot + + +# Patch matplotlib function. +wrapt.wrap_function_wrapper(Axes, "imshow", heat) + +# Patch seaborn function. +wrapt.wrap_function_wrapper("seaborn", "heatmap", heat) diff --git a/maidr/patch/histogram.py b/maidr/patch/histogram.py new file mode 100644 index 0000000..0787328 --- /dev/null +++ b/maidr/patch/histogram.py @@ -0,0 +1,43 @@ +from __future__ import annotations + +import wrapt + +import numpy as np +from matplotlib.axes import Axes +from matplotlib.container import BarContainer +from matplotlib.patches import Polygon + +from maidr.core.context_manager import ContextManager +from maidr.core.enum import PlotType +from maidr.core.figure_manager import FigureManager +from maidr.patch.common import common + + +@wrapt.patch_function_wrapper(Axes, "hist") +def mpl_hist( + wrapped, _, args, kwargs +) -> tuple[ + np.ndarray | list[np.ndarray], + np.ndarray, + BarContainer | Polygon | list[BarContainer | Polygon], +]: + # Don't proceed if the call is made internally by the patched function. + if ContextManager.is_internal_context(): + return wrapped(*args, **kwargs) + + # Set the internal context to avoid cyclic processing. + with ContextManager.set_internal_context(): + # Patch `ax.hist()`. + n, bins, plot = wrapped(*args, **kwargs) + + # Extract the histogram data points for MAIDR from the plots. + ax = FigureManager.get_axes(plot) + FigureManager.create_maidr(ax, PlotType.HIST) + + # Return to the caller. + return n, bins, plot + + +@wrapt.patch_function_wrapper("seaborn", "histplot") +def sns_hist(wrapped, instance, args, kwargs) -> Axes: + return common(PlotType.HIST, wrapped, instance, args, kwargs) diff --git a/maidr/patch/lineplot.py b/maidr/patch/lineplot.py new file mode 100644 index 0000000..9cf87bb --- /dev/null +++ b/maidr/patch/lineplot.py @@ -0,0 +1,20 @@ +from __future__ import annotations + +import wrapt + +from matplotlib.axes import Axes +from matplotlib.lines import Line2D + +from maidr.core.enum import PlotType +from maidr.patch.common import common + + +def line(wrapped, instance, args, kwargs) -> Axes | list[Line2D]: + return common(PlotType.LINE, wrapped, instance, args, kwargs) + + +# Patch matplotlib function. +wrapt.wrap_function_wrapper(Axes, "plot", line) + +# Patch seaborn function. +wrapt.wrap_function_wrapper("seaborn", "lineplot", line) diff --git a/maidr/patch/scatterplot.py b/maidr/patch/scatterplot.py new file mode 100644 index 0000000..b30edfb --- /dev/null +++ b/maidr/patch/scatterplot.py @@ -0,0 +1,20 @@ +from __future__ import annotations + +import wrapt + +from matplotlib.axes import Axes +from matplotlib.collections import PathCollection + +from maidr.core.enum import PlotType +from maidr.patch.common import common + + +def scatter(wrapped, instance, args, kwargs) -> Axes | PathCollection: + return common(PlotType.SCATTER, wrapped, instance, args, kwargs) + + +# Patch matplotlib function. +wrapt.wrap_function_wrapper(Axes, "scatter", scatter) + +# Patch seaborn function. +wrapt.wrap_function_wrapper("seaborn", "scatterplot", scatter) diff --git a/poetry.lock b/poetry.lock index accde54..72565d8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2200,7 +2200,6 @@ optional = false python-versions = ">=3.9" files = [ {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, - {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, @@ -2221,7 +2220,6 @@ files = [ {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, - {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, @@ -3957,6 +3955,85 @@ files = [ {file = "widgetsnbextension-4.0.10.tar.gz", hash = "sha256:64196c5ff3b9a9183a8e699a4227fb0b7002f252c814098e66c4d1cd0644688f"}, ] +[[package]] +name = "wrapt" +version = "1.16.0" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, +] + [[package]] name = "zipp" version = "3.18.1" @@ -3975,4 +4052,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9" -content-hash = "78fcf51313518ee04601c94b0659dad518d343f603380d5030a6734eaeee408d" +content-hash = "78358b3a45ba53d355d805b8c4f02501189b71e641df445c37965dc518f112a1" diff --git a/pyproject.toml b/pyproject.toml index a84c087..ba66fc5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,7 @@ seaborn = ">=0.12" lxml = ">=5.1.0" htmltools = ">=0.5" jupyter = "^1.0.0" +wrapt = "^1.16.0" [tool.poetry.group.dev.dependencies] black = "24.3.0" diff --git a/tests/conftest.py b/tests/conftest.py index e48c911..4c87305 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,7 @@ from matplotlib import pyplot as plt from maidr.core.enum.plot_type import PlotType -from tests.core.enum.library import Library +from maidr.core.enum.library import Library from tests.fixture.matplotlib_factory import MatplotlibFactory from tests.fixture.seaborn_factory import SeabornFactory diff --git a/tests/core/plot/test_bar_plot.py b/tests/core/plot/test_bar_plot.py deleted file mode 100644 index 7f36799..0000000 --- a/tests/core/plot/test_bar_plot.py +++ /dev/null @@ -1,30 +0,0 @@ -from maidr.core.enum.maidr_key import MaidrKey -from maidr.core.enum.plot_type import PlotType -from maidr.core.plot.bar_plot import BarPlot - -import pytest - -from tests.core.enum.library import Library - - -@pytest.mark.parametrize("lib", [Library.MATPLOTLIB, Library.SEABORN]) -def test_bar_plot_data(plot_fixture, lib): - expected_maidr_data = { - MaidrKey.TYPE.value: PlotType.BAR.value, - MaidrKey.TITLE.value: f"Test {lib.value} title", - MaidrKey.AXES.value: { - MaidrKey.X.value: { - MaidrKey.LABEL.value: f"Test {lib.value} x label", - MaidrKey.LEVEL.value: ["1", "2", "3"], - }, - MaidrKey.Y.value: { - MaidrKey.LABEL.value: f"Test {lib.value} y label", - }, - }, - MaidrKey.DATA.value: [4, 5, 6], - } - - _, ax = plot_fixture(lib, PlotType.BAR) - actual_maidr = BarPlot(ax) - - assert actual_maidr.schema == expected_maidr_data diff --git a/tests/core/plot/test_barplot.py b/tests/core/plot/test_barplot.py new file mode 100644 index 0000000..af1bcad --- /dev/null +++ b/tests/core/plot/test_barplot.py @@ -0,0 +1,52 @@ +from maidr.core.enum.maidr_key import MaidrKey +from maidr.core.enum.plot_type import PlotType +from maidr.core.plot.barplot import BarPlot + +import pytest + +from maidr.core.enum.library import Library + + +@pytest.mark.parametrize("lib", [Library.MATPLOTLIB, Library.SEABORN]) +def test_bar_plot_data(plot_fixture, lib): + expected_maidr_data = { + MaidrKey.TYPE: PlotType.BAR, + MaidrKey.TITLE: f"Test {lib.value} bar title", + MaidrKey.AXES: { + MaidrKey.X: { + MaidrKey.LABEL: f"Test {lib.value} bar x label", + MaidrKey.LEVEL: ["1", "2", "3"], + }, + MaidrKey.Y: { + MaidrKey.LABEL: f"Test {lib.value} bar y label", + }, + }, + MaidrKey.DATA: [4, 5, 6], + } + + _, ax = plot_fixture(lib, PlotType.BAR) + actual_maidr = BarPlot(ax) + + assert actual_maidr.schema == expected_maidr_data + + +def test_sns_count_plot_data(plot_fixture): + expected_maidr_data = { + MaidrKey.TYPE: PlotType.BAR, + MaidrKey.TITLE: f"Test seaborn count title", + MaidrKey.AXES: { + MaidrKey.X: { + MaidrKey.LABEL: f"Test seaborn count x label", + MaidrKey.LEVEL: ["a", "b", "c"], + }, + MaidrKey.Y: { + MaidrKey.LABEL: f"Test seaborn count y label", + }, + }, + MaidrKey.DATA: [3, 2, 1], + } + + _, ax = plot_fixture(Library.SEABORN, PlotType.COUNT) + actual_maidr = BarPlot(ax) + + assert actual_maidr.schema == expected_maidr_data diff --git a/tests/core/plot/test_boxplot.py b/tests/core/plot/test_boxplot.py new file mode 100644 index 0000000..3842bc2 --- /dev/null +++ b/tests/core/plot/test_boxplot.py @@ -0,0 +1,58 @@ +import pytest + +from maidr.core.enum.library import Library +from maidr.core.enum.maidr_key import MaidrKey +from maidr.core.enum.plot_type import PlotType +from maidr.core.figure_manager import FigureManager + + +@pytest.mark.parametrize("lib", [Library.MATPLOTLIB, Library.SEABORN]) +def test_box_plot_data(plot_fixture, lib): + x_level = ["1", "2", "3"] if lib == Library.MATPLOTLIB else ["0", "1", "2"] + expected_maidr_data = { + MaidrKey.TYPE: PlotType.BOX, + MaidrKey.TITLE: f"Test {lib.value} box title", + MaidrKey.AXES: { + MaidrKey.X: { + MaidrKey.LABEL: f"Test {lib.value} box x label", + MaidrKey.LEVEL: x_level, + }, + MaidrKey.Y: { + MaidrKey.LABEL: f"Test {lib.value} box y label", + }, + }, + MaidrKey.DATA: [ + { + MaidrKey.LOWER_OUTLIER: [], + MaidrKey.MIN: 1.0, + MaidrKey.Q1: 1.5, + MaidrKey.Q2: 2.0, + MaidrKey.Q3: 2.5, + MaidrKey.MAX: 3.0, + MaidrKey.UPPER_OUTLIER: [], + }, + { + MaidrKey.LOWER_OUTLIER: [], + MaidrKey.MIN: 4.0, + MaidrKey.Q1: 4.5, + MaidrKey.Q2: 5.0, + MaidrKey.Q3: 5.5, + MaidrKey.MAX: 6.0, + MaidrKey.UPPER_OUTLIER: [], + }, + { + MaidrKey.LOWER_OUTLIER: [], + MaidrKey.MIN: 7.0, + MaidrKey.Q1: 7.5, + MaidrKey.Q2: 8.0, + MaidrKey.Q3: 8.5, + MaidrKey.MAX: 9.0, + MaidrKey.UPPER_OUTLIER: [], + }, + ], + } + + fig, _ = plot_fixture(lib, PlotType.BOX) + actual_maidr = FigureManager.get_maidr(fig) + + assert actual_maidr.plots[0].schema == expected_maidr_data diff --git a/tests/core/test_figure_manager.py b/tests/core/test_figure_manager.py index 4499a82..206569c 100644 --- a/tests/core/test_figure_manager.py +++ b/tests/core/test_figure_manager.py @@ -5,7 +5,7 @@ from maidr.core import Maidr from maidr.core.enum.plot_type import PlotType from maidr.core.figure_manager import FigureManager -from tests.core.enum.library import Library +from maidr.core.enum.library import Library # test cases for invalid inputs @@ -25,24 +25,32 @@ def test_create_maidr_with_none_plot_type(mocker): assert "No plot type found." == str(e.value) -# Parametrize the test to run with different libraries and plot types +# Parametrize the test to run with different libraries and plot types. @pytest.mark.parametrize( "lib, plot_type", [ + # Parametrize matplotlib plots. (Library.MATPLOTLIB, PlotType.BAR), + (Library.MATPLOTLIB, PlotType.BOX), + # Parametrize seaborn plots. (Library.SEABORN, PlotType.BAR), + (Library.SEABORN, PlotType.BOX), + (Library.SEABORN, PlotType.COUNT), ], ) -def test_create_maidr_with_single_axes(plot_fixture, lib, plot_type): +def test_get_maidr_with_single_axes(plot_fixture, lib, plot_type): fig, ax = plot_fixture(lib, plot_type) - maidr = FigureManager.create_maidr(ax, plot_type) + maidr = FigureManager.get_maidr(fig) assert isinstance(maidr, Maidr) assert maidr.fig is fig assert len(maidr.plots) == len([plot_type]) == 1 for m_data, p_type in zip(maidr.plots, [plot_type]): - assert m_data.type == p_type + if p_type == PlotType.COUNT: + assert m_data.type == PlotType.BAR + else: + assert m_data.type == p_type # group tests related to matplotlib diff --git a/tests/core/test_maidr_plot_factory.py b/tests/core/test_maidr_plot_factory.py index 3f83e0e..0be21a1 100644 --- a/tests/core/test_maidr_plot_factory.py +++ b/tests/core/test_maidr_plot_factory.py @@ -1,8 +1,14 @@ import pytest from maidr.core.enum.plot_type import PlotType -from maidr.core.plot.bar_plot import BarPlot +from maidr.core.plot.barplot import BarPlot +from maidr.core.plot.boxplot import BoxPlot +from maidr.core.plot.grouped_barplot import GroupedBarPlot +from maidr.core.plot.heatmap import HeatPlot +from maidr.core.plot.histogram import HistPlot +from maidr.core.plot.lineplot import LinePlot from maidr.core.plot.maidr_plot_factory import MaidrPlotFactory +from maidr.core.plot.scatterplot import ScatterPlot # test invalid inputs @@ -17,6 +23,14 @@ def test_create_with_invalid_plot_type(mocker): "plot_type, expected_plot_data", [ (PlotType.BAR, BarPlot), + (PlotType.BOX, BoxPlot), + (PlotType.COUNT, BarPlot), + (PlotType.DODGED, GroupedBarPlot), + (PlotType.HEAT, HeatPlot), + (PlotType.HIST, HistPlot), + (PlotType.LINE, LinePlot), + (PlotType.SCATTER, ScatterPlot), + (PlotType.STACKED, GroupedBarPlot), ], ) def test_create_plot_data(mocker, plot_type, expected_plot_data): diff --git a/tests/fixture/matplotlib_factory.py b/tests/fixture/matplotlib_factory.py index 84c44d8..afba08e 100644 --- a/tests/fixture/matplotlib_factory.py +++ b/tests/fixture/matplotlib_factory.py @@ -25,14 +25,22 @@ def create_plot(self, plot_types: list[PlotType]) -> Any: finally: plt.close(fig) - def plot_on_ax(self, ax: Axes, plot_type: PlotType): - if plot_type == PlotType.BAR: - self.create_bar_plot(ax) + def plot_on_ax(self, ax: Axes, plot_type: PlotType) -> None: + if PlotType.BAR is plot_type: + self.create_barplot(ax) + elif PlotType.BOX is plot_type: + self.create_boxplot(ax) - def create_bar_plot(self, ax: Axes) -> Any: + def create_barplot(self, ax: Axes) -> Any: # TODO: using numbers makes matplotlib to add additional ticks messing with the # level extraction ax.bar(["1", "2", "3"], [4, 5, 6]) - ax.set_title("Test matplotlib title") - ax.set_xlabel("Test matplotlib x label") - ax.set_ylabel("Test matplotlib y label") + ax.set_title("Test matplotlib bar title") + ax.set_xlabel("Test matplotlib bar x label") + ax.set_ylabel("Test matplotlib bar y label") + + def create_boxplot(self, ax: Axes) -> Any: + ax.boxplot([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + ax.set_title("Test matplotlib box title") + ax.set_xlabel("Test matplotlib box x label") + ax.set_ylabel("Test matplotlib box y label") diff --git a/tests/fixture/seaborn_factory.py b/tests/fixture/seaborn_factory.py index 4cf7628..ea407f9 100644 --- a/tests/fixture/seaborn_factory.py +++ b/tests/fixture/seaborn_factory.py @@ -8,13 +8,30 @@ from tests.fixture.matplotlib_factory import MatplotlibFactory +def create_countplot(ax: Axes) -> Any: + sns.countplot(x=["a", "b", "a", "c", "b", "a"], ax=ax) + ax.set_title("Test seaborn count title") + ax.set_xlabel("Test seaborn count x label") + ax.set_ylabel("Test seaborn count y label") + + class SeabornFactory(MatplotlibFactory): - def plot_on_ax(self, ax: Axes, plot_type: PlotType): - if plot_type == PlotType.BAR: - self.create_bar_plot(ax) + def plot_on_ax(self, ax: Axes, plot_type: PlotType) -> Any: + if plot_type == PlotType.COUNT: + create_countplot(ax) + elif plot_type is PlotType.BAR: + self.create_barplot(ax) + elif plot_type is PlotType.BOX: + self.create_boxplot(ax) - def create_bar_plot(self, ax: Axes) -> Any: + def create_barplot(self, ax: Axes) -> Any: sns.barplot(x=[1, 2, 3], y=[4, 5, 6], ax=ax) - ax.set_title("Test seaborn title") - ax.set_xlabel("Test seaborn x label") - ax.set_ylabel("Test seaborn y label") + ax.set_title("Test seaborn bar title") + ax.set_xlabel("Test seaborn bar x label") + ax.set_ylabel("Test seaborn bar y label") + + def create_boxplot(self, ax: Axes) -> Any: + sns.boxplot(data=[[1, 2, 3], [4, 5, 6], [7, 8, 9]], ax=ax) + ax.set_title("Test seaborn box title") + ax.set_xlabel("Test seaborn box x label") + ax.set_ylabel("Test seaborn box y label")