From 0a8ed00f3609634296cbdcde5f4f196a4b90c368 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Wed, 16 Oct 2024 15:49:22 -0400 Subject: [PATCH 01/29] Update the docs of the plotting and test_plotting modules --- src/plotting/plotting.py | 203 +++++++++++++++++++++++++++++-------- src/tests/test_plotting.py | 15 ++- 2 files changed, 174 insertions(+), 44 deletions(-) diff --git a/src/plotting/plotting.py b/src/plotting/plotting.py index 45a5644..bfda16e 100644 --- a/src/plotting/plotting.py +++ b/src/plotting/plotting.py @@ -1,4 +1,22 @@ -"""Visualization Module""" +"""Module to plot and customize various types of graphs. + +:author: A.M.E. Popo[#]_, + C.O. Mbengue[#]_, + +:organization: Elizabeth Consulting International Inc. + +This module contains the following classes: + + - :class:`Plot`: Class to plot various types of graphs. + - :class:`PlotUtilities`: Class containing auxillary utility functions for plotting. + - :class:`Multiplots`: Class to plot multiple subplots on the same graph. + +.. [#] Azendae Marie-Ange Elizabeth Popo, Research Assistant, apopo@ec-intl.com +.. [#] Cheikh Oumar Mbengue, Research Scientist, cmbengue@ec-intl.com +.. [#] Elizabeth Consulting International Inc. (ECI) is a private company that + specializes in the development of decision support systems for the + private sector. ECI is based in St. Lucia, West Indies. +""" import math @@ -17,32 +35,41 @@ class Plot: :param dict args: the master dictionary containing both optional and required fields - **Required Keys** + *Required Keys* - ax: an axis to plot the data - fig: the figure that the axis is on - - data: a data list + - data: a data list, or a list of data lists - **Optional Keys** + *Optional Keys* - axes_labels: the axes labels - boxplot_args: the optional customizations for a boxplot - cdf_args: the optional customizations for a cdf plot - hist_args: the optional customizations for a histogram - timeseries_args: the optional customizations for a timeseries plot - - **Usage** - >>> _, ax = plt.subplots() - >>> data = np.random.randint(50, size=(20)) - >>> args = {"ax": ax, "data": data} + - prob_plot_args: the optional customizations for a probability plot + - gen_plot_args: the optional customizations for a generic plot + - norm_cdf_args: the optional customizations for a normal cdf plot + - contour_args: the optional customizations for a contour plot + - density_args: the optional customizations for a density plot + - export_args: the optional customizations for exporting the plot to a file + + **Examples** + >>> fig, ax = plt.subplots() + >>> data = [1, 2, 3, 4, 5] + >>> args = {"ax": ax, "fig": fig, "data": data} >>> plot = Plot(args) + >>> plot.data + [1, 2, 3, 4, 5] """ def __init__(self, args): - """Initialize Plot Class""" - + """Initialize the Plot Class""" + # Extract the data, axis, and figure self.data = args.get("data") self.ax = args.get("ax") self.fig = args.get("fig") + # Initialize the Plot Utilities self.util = PlotUtilities() # Turn off interactive mode @@ -138,14 +165,14 @@ def set_defaults(self, field): defaults = { "axes_labels": def_axes_labels, "export": {"format": "eps", "fname": "plot.eps"}, - "cdf": {"logxscale": False}, + "cdf": {}, "density": {"color": "red", "fill": False, "label": " "}, "histogram": {"num_bins": 20, "color": "plum", "ran": None}, "timeseries": {"linestyle": "solid", "color": "black"}, "boxplots": {"showfliers": True}, "prob_plot": {"color": "orangered"}, "gen_plot": {"color": "navy", "linestyle": "solid"}, - "norm_cdf": {"add_datasets": []}, + "norm_cdf": {}, "contour": def_contour, } return defaults[field] @@ -175,12 +202,18 @@ def update_defaults(self, field, new_values): defaults[field].update(new_values) def label_axes(self): - """Label the axes of a graph. + """Label the axes of a graph. This method uses the axes_labels dict. + There are no required keys for this dict. + + *Optional Keys* + - xlabel: the x-axis label, default is " " + - ylabel: the y-axis label, default is " " + - title: the title of the graph, default is " " + - linelabel: the label for the line, default is " " + - show_legend: whether to show the legend or not, default is True + - scale: the scale of the axes, default is "linear" + - base: the base of the axes, default is 10 - :param ax: the axis. - :param dict axes_labels: Dict of the labels for each axes. These include - xlabel, ylabel, and title. - :param bool legend: whether to show the legend or not. """ self.ax.set_title(self.axes_labels["title"]) self.ax.set_xlabel(self.axes_labels["xlabel"]) @@ -196,7 +229,13 @@ def label_axes(self): self.ax.legend() def generic_plot(self) -> None: - """Generic Plot""" + """Plot a generic plot using y and/or x. This method uses the + gen_plot_args dict. There are no required keys for this dict. + + *Optional Keys* + - color: the color of the line, default is "navy" + - linestyle: the style of the line, default is "solid" + """ # Check if the data is 1D or 2D if isinstance(self.data[0], (list, np.ndarray)): # Check that both x and y data are present and of equal length @@ -222,7 +261,13 @@ def generic_plot(self) -> None: self.label_axes() def export_plot_to_file(self): - """Export the current figure to a file.""" + """Export the current figure to a file. This method uses the export_args dict. + There are no required keys for this dict. + + *Optional Keys* + - format: the format of the exported file, default is "eps" + - fname: the name of the exported file, default is "plot.eps" + """ self.fig.savefig( self.export_args["fname"], @@ -233,7 +278,9 @@ def export_plot_to_file(self): ) def plot_cdf(self) -> None: - """Plot CDF of a dataset.""" + """Plot CDF of a dataset. This method uses the cdf_args dict. There are + no required keys for this dict. + """ x = np.sort(self.data) y = np.cumsum(x) / np.sum(x) @@ -246,7 +293,14 @@ def plot_cdf(self) -> None: self.label_axes() def plot_density(self) -> None: - """Plot the density plot of a dataset using kernel density estimation""" + """Plot the density plot of a dataset using kernel density estimation. This + method uses the density_args dict. There are no required keys for this dict. + + *Optional Keys* + - color: the color of the density plot, default is "red" + - fill: whether to fill the density plot, default is False + - label: the label of the density plot, default is " " + """ # Plot a density plot sns.kdeplot( self.data, @@ -258,7 +312,12 @@ def plot_density(self) -> None: self.label_axes() def plot_box_plots(self) -> None: - """Plot Box Plots.""" + """Plot Box Plots. This method uses the boxplot_args dict. There are no + required keys for this dict. + + *Optional Keys* + - showfliers: whether to show the outliers, default is True + """ self.ax.boxplot( self.data, @@ -274,7 +333,14 @@ def plot_box_plots(self) -> None: self.label_axes() def plot_histogram(self): - """Plot histogram.""" + """Plot a histogram. This method uses the hist_args dict. There are no + required keys for this dict. + + *Optional Keys* + - num_bins: the number of bins in the histogram, default is 20 + - color: the color of the histogram, default is "plum" + - ran: the range of the histogram, default is None + """ self.ax.hist( self.data, bins=self.hist_args["num_bins"], @@ -287,7 +353,13 @@ def plot_histogram(self): self.label_axes() def plot_timeseries(self): - """Plot timeseries""" + """Plot a timeseries. This method uses the timeseries_args dict. There are no + required keys for this dict. + + *Optional Keys* + - linestyle: the style of the line, default is "solid" + - color: the color of the line, default is "black" + """ self.ax.plot( self.data, linewidth=2, @@ -298,7 +370,12 @@ def plot_timeseries(self): self.label_axes() def plot_probability_plot(self): - """Plot probability plot""" + """Plot a probability plot. This method uses the prob_plot_args dict. There are no + required keys for this dict. + + *Optional Keys* + - color: the color of the plot, default is "orangered" + """ # Extract Fields sample_data = self.data @@ -342,7 +419,9 @@ def plot_probability_plot(self): def plot_normal_cdf(self): """Plot a standard normal distribution CDF against the CDF - of other datasets.""" + of other datasets. This method uses the norm_cdf_args dict. There are no + required keys for this dict. + """ data_list = ( self.data if isinstance(self.data[0], (list, np.ndarray)) else [self.data] ) @@ -384,7 +463,16 @@ def plot_normal_cdf(self): self.label_axes() def plot_contour_plot(self): - """Plot a contour plot""" + """Plot a contour plot. This method uses the contour_args dict. There are no + required keys for this dict. Please note that the data must be a list of + 2D numpy arrays. + + *Optional Keys* + - filled: whether to fill the contour plot, default is False + - colors: the color of the contour plot, default is "k" + - inline: whether to show the inline labels, default is True + - fsize: the font size of the labels, default is 9 + """ func = self.ax.contourf if self.contour_args["filled"] else self.ax.contour assert len(self.data) == 3, "Contour plot requires 3 datasets" @@ -408,12 +496,28 @@ def plot_contour_plot(self): class Multiplots(Plot): """Class to plot multiple subplots on the same graph. - **Usage** - >>> multiplot = Multiplots() + :param dict args: the master dictionary containing the required fields. + + *Required Keys* + - super_title: the title of the main figure + - super_xlabel: the x-axis label of the main figure + - super_ylabel: the y-axis label of the main figure + - share_axes: whether to share the axes of the subplots + + **Example** + >>> args = { + ... "super_title": "Test Title", + ... "super_xlabel": "Test X Label", + ... "super_ylabel": "Test Y Label", + ... "share_axes": False, + ... } + >>> multiplot = Multiplots(args) + >>> multiplot.share_axes + False """ def __init__(self, args): - """Initialize multiplot class.""" + """Initialize the Multiplot Class.""" # Initialize the Plot Class super().__init__({"ax": "ax", "data": [], "fig": "fig"}) @@ -421,7 +525,6 @@ def __init__(self, args): self.super_title = args.get("super_title", " ") self.super_xlabel = args.get("super_xlabel", " ") self.super_ylabel = args.get("super_ylabel", " ") - self.share_axes = args.get("share_axes", True) # Turn off interactive mode @@ -446,16 +549,16 @@ def __init__(self, args): self.current_subplot = [] def overlay(self, overlay_args): - """Overlay new plot onto subplot. + """Overlay new plot onto current subplot. :param dict overlay_args: Master dictionary of all inputs - **Required Keys** + *Required Keys* - plot: The graph name. - data: The data to plot onto the graph - axes_labels: The axes labels - **Optional Keys** + *Optional Keys* customs: The plot's customization. """ plot = overlay_args.get("plot") @@ -478,12 +581,23 @@ def new_subplot(self): def __call__(self): """Build the main figure, label its axes and display the result. - - :param dict super_axes_labels: dict of all the main figure's labels - **Required Keys** - - title - - xlabel - - ylabel + + **Usage** + >>> args = { + ... "super_title": "Test Title", + ... "super_xlabel": "Test X Label", + ... "super_ylabel": "Test Y Label", + ... "share_axes": False, + ... } + >>> multiplot = Multiplots(args) + >>> multiplot.new_subplot() + >>> overlay_args = { + ... "plot": "cdf", + ... "data": [1, 2, 3, 4, 5], + ... "axes_labels": {"title": "CDF Plot", "xlabel": "X", "ylabel": "Y"}, + ... } + >>> multiplot.overlay(overlay_args) + >>> multiplot() """ # Collect and Store remaining overlays self.subplots.append(self.current_subplot) @@ -533,7 +647,7 @@ def __call__(self): self.clear_axis() def clear_axis(self): - """Reset Subplot Trackers""" + """Reset Subplot Trackers.""" self.subplot_count = 0 self.subplots = [] @@ -541,6 +655,8 @@ def tiling(self, num): """Calculates the number of rows and columns for the subplot. :param int num: the number of subplots + :return: the number of rows and columns + :rtype: tuple """ if num < 5: return 1, num @@ -563,7 +679,8 @@ class PlotUtilities: """ def standardize_dataset(self, data: list) -> np.ndarray: - """Standardize a dataset. + """Standardize a dataset by subtracting the mean and dividing the std + of the dataset from each value. :param list data: the data list :return: standardized data diff --git a/src/tests/test_plotting.py b/src/tests/test_plotting.py index 808dbb3..36dc761 100644 --- a/src/tests/test_plotting.py +++ b/src/tests/test_plotting.py @@ -1,4 +1,17 @@ -"""Test the plotting module.""" +"""Test plotting module. + +:author: C.O. Mbengue [#]_, + A.M.E. Popo [#]_ + +:organization: Elizabeth Consulting International Inc. [#]_ + +.. [#] Cheikh Oumar Mbengue, Research Scientist, cmbengue@ec-intl.com +.. [#] Azendae Marie-Ange Elizabeth Popo, Research Assistant, apopo@ec-intl.com +.. [#] Elizabeth Consulting International Inc. (ECI) is a private company that + specializes in the development of decision support systems for the + private sector. ECI is based in St. Lucia, West Indies. + +""" import unittest From c3827d7a5abd3bce4859e016547fa3d60d5a6a08 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Wed, 16 Oct 2024 15:52:48 -0400 Subject: [PATCH 02/29] update docs workflows --- .github/workflows/docs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index b8493af..1f4380b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -19,4 +19,6 @@ permissions: jobs: docs-tasks: uses: ec-intl/workflow-templates/.github/workflows/docs_template.yml@v1 + with: + doc-type: "sphinx" secrets: inherit From 07eb3cde8c89c20b1f271f33a837ff64a1b34132 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Wed, 16 Oct 2024 17:13:38 -0400 Subject: [PATCH 03/29] Fix Sphinx render --- .github/workflows/docs.yml | 68 ++++++++++++++++++-- .gitignore | 9 +++ docs/Makefile | 20 ++++++ docs/make.bat | 35 ++++++++++ docs/source/conf.py | 36 +++++++++++ docs/source/index.rst | 20 ++++++ src/plotting/plotting.py | 128 +++++++++++++++++++------------------ 7 files changed, 247 insertions(+), 69 deletions(-) create mode 100644 docs/Makefile create mode 100644 docs/make.bat create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 1f4380b..9f5c4ff 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,5 +1,4 @@ ---- -name: Docs +name: Sphinx-docs on: pull_request: @@ -17,8 +16,63 @@ permissions: checks: read jobs: - docs-tasks: - uses: ec-intl/workflow-templates/.github/workflows/docs_template.yml@v1 - with: - doc-type: "sphinx" - secrets: inherit + build-docs: + runs-on: ubuntu-latest + steps: + - name: Preamble + run: | + echo "🎉 A ${{ github.event_name }} triggered a ${{ runner.os }} job." + echo "🔎 The branch is ${{ github.ref_name }} in ${{ github.repository }}." + + - name: Check out repository code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + cache: 'pip' + + - name: Install Python dependencies + run: | + echo "📦 Installing Python dependencies." + python -m pip install --upgrade pip + if [ -f requirements/testing.txt ]; then + pip install -r requirements/testing.txt; + fi + + - name: Run Sphinx + run: | + echo "📦 Running Sphinx." + python -m venv pyenv + source pyenv/bin/activate + cd docs + sphinx-build -b html source ../docs + + - name: Deploy to GitHub Pages + if: github.ref == 'refs/heads/main' + run: | + mkdir -p /tmp/"${{ github.repository }}"-d + cp -r docs/* /tmp/"${{ github.repository }}"-d/ + git config user.name "${{ github.actor }}" + git config user.email "${{ github.actor }}@users.noreply.github.com" + git fetch + git checkout -B gh-pages origin/gh-pages || git checkout --orphan gh-pages + rm -rf ./* + cp -r /tmp/"${{ github.repository }}"-d/* . + touch .nojekyll + date > timestamp.txt + git add . + git commit -m "🚀 $(date): update docs" + git push origin gh-pages --force + + - name: Cleanup deployment + if: github.ref == 'refs/heads/main' + run: | + echo "Cleaning up now." + rm -rf /tmp/"${{ github.repository }}"-d/ + + - name: Finish + run: | + echo "📣 The job has been completed." + echo "🍏 This job's status is ${{ job.status }}." \ No newline at end of file diff --git a/.gitignore b/.gitignore index 266f314..a35cb4a 100644 --- a/.gitignore +++ b/.gitignore @@ -148,6 +148,15 @@ dmypy.json # Pyre type checker .pyre/ +docs/.buildinfo +docs/.doctrees/api.doctree +docs/.doctrees/environment.pickle +docs/.doctrees/generated/compute.doctree +docs/.doctrees/generated/data_formatter.doctree +docs/.doctrees/generated/downloader.doctree +docs/.doctrees/generated/wedapp_utilities.doctree +docs/.doctrees/index.doctree +docs/.doctrees/usage.doctree # pytype static type analyzer .pytype/ diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..747ffb7 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..bbbaa98 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,36 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'plotting' +copyright = '2024, Elizabeth Consulting International Inc' +author = 'Elizabeth Consulting International Inc' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + "sphinx.ext.duration", + "sphinx.ext.doctest", + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.inheritance_diagram", + "sphinx.ext.mathjax", + "matplotlib.sphinxext.plot_directive", + "IPython.sphinxext.ipython_directive", + "IPython.sphinxext.ipython_console_highlighting", + "autoapi.extension", +] + +templates_path = ['_templates'] +exclude_patterns = [] +autoapi_dirs = ['../../src'] +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'cloud' +html_static_path = ['_static'] diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..c1a7cab --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,20 @@ +.. plotting documentation master file, created by + sphinx-quickstart on Wed Oct 16 16:05:42 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +plotting documentation +====================== + +**plotting** is a simple tool that allows you to create plots from data. + + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + +Indices and tables +================== +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/src/plotting/plotting.py b/src/plotting/plotting.py index bfda16e..ca1f906 100644 --- a/src/plotting/plotting.py +++ b/src/plotting/plotting.py @@ -35,25 +35,26 @@ class Plot: :param dict args: the master dictionary containing both optional and required fields - *Required Keys* - - ax: an axis to plot the data - - fig: the figure that the axis is on - - data: a data list, or a list of data lists - - *Optional Keys* - - axes_labels: the axes labels - - boxplot_args: the optional customizations for a boxplot - - cdf_args: the optional customizations for a cdf plot - - hist_args: the optional customizations for a histogram - - timeseries_args: the optional customizations for a timeseries plot - - prob_plot_args: the optional customizations for a probability plot - - gen_plot_args: the optional customizations for a generic plot - - norm_cdf_args: the optional customizations for a normal cdf plot - - contour_args: the optional customizations for a contour plot - - density_args: the optional customizations for a density plot - - export_args: the optional customizations for exporting the plot to a file + Required Keys + - ax: an axis to plot the data + - fig: the figure that the axis is on + - data: a data list, or a list of data lists + + Optional Keys + - axes_labels: the axes labels + - boxplot_args: the optional customizations for a boxplot + - cdf_args: the optional customizations for a cdf plot + - hist_args: the optional customizations for a histogram + - timeseries_args: the optional customizations for a timeseries plot + - prob_plot_args: the optional customizations for a probability plot + - gen_plot_args: the optional customizations for a generic plot + - norm_cdf_args: the optional customizations for a normal cdf plot + - contour_args: the optional customizations for a contour plot + - density_args: the optional customizations for a density plot + - export_args: the optional customizations for exporting the plot to a file **Examples** + >>> fig, ax = plt.subplots() >>> data = [1, 2, 3, 4, 5] >>> args = {"ax": ax, "fig": fig, "data": data} @@ -205,14 +206,14 @@ def label_axes(self): """Label the axes of a graph. This method uses the axes_labels dict. There are no required keys for this dict. - *Optional Keys* - - xlabel: the x-axis label, default is " " - - ylabel: the y-axis label, default is " " - - title: the title of the graph, default is " " - - linelabel: the label for the line, default is " " - - show_legend: whether to show the legend or not, default is True - - scale: the scale of the axes, default is "linear" - - base: the base of the axes, default is 10 + Optional Keys + - xlabel: the x-axis label, default is " " + - ylabel: the y-axis label, default is " " + - title: the title of the graph, default is " " + - linelabel: the label for the line, default is " " + - show_legend: whether to show the legend or not, default is True + - scale: the scale of the axes, default is "linear" + - base: the base of the axes, default is 10 """ self.ax.set_title(self.axes_labels["title"]) @@ -232,9 +233,9 @@ def generic_plot(self) -> None: """Plot a generic plot using y and/or x. This method uses the gen_plot_args dict. There are no required keys for this dict. - *Optional Keys* - - color: the color of the line, default is "navy" - - linestyle: the style of the line, default is "solid" + Optional Keys + - color: the color of the line, default is "navy" + - linestyle: the style of the line, default is "solid" """ # Check if the data is 1D or 2D if isinstance(self.data[0], (list, np.ndarray)): @@ -264,9 +265,9 @@ def export_plot_to_file(self): """Export the current figure to a file. This method uses the export_args dict. There are no required keys for this dict. - *Optional Keys* - - format: the format of the exported file, default is "eps" - - fname: the name of the exported file, default is "plot.eps" + Optional Keys + - format: the format of the exported file, default is "eps" + - fname: the name of the exported file, default is "plot.eps" """ self.fig.savefig( @@ -296,10 +297,10 @@ def plot_density(self) -> None: """Plot the density plot of a dataset using kernel density estimation. This method uses the density_args dict. There are no required keys for this dict. - *Optional Keys* - - color: the color of the density plot, default is "red" - - fill: whether to fill the density plot, default is False - - label: the label of the density plot, default is " " + Optional Keys: + - color: the color of the density plot, default is "red" + - fill: whether to fill the density plot, default is False + - label: the label of the density plot, default is " " """ # Plot a density plot sns.kdeplot( @@ -315,8 +316,8 @@ def plot_box_plots(self) -> None: """Plot Box Plots. This method uses the boxplot_args dict. There are no required keys for this dict. - *Optional Keys* - - showfliers: whether to show the outliers, default is True + Optional Keys: + - showfliers: whether to show the outliers, default is True """ self.ax.boxplot( @@ -336,10 +337,10 @@ def plot_histogram(self): """Plot a histogram. This method uses the hist_args dict. There are no required keys for this dict. - *Optional Keys* - - num_bins: the number of bins in the histogram, default is 20 - - color: the color of the histogram, default is "plum" - - ran: the range of the histogram, default is None + Optional Keys: + - num_bins: the number of bins in the histogram, default is 20 + - color: the color of the histogram, default is "plum" + - ran: the range of the histogram, default is None """ self.ax.hist( self.data, @@ -356,9 +357,9 @@ def plot_timeseries(self): """Plot a timeseries. This method uses the timeseries_args dict. There are no required keys for this dict. - *Optional Keys* - - linestyle: the style of the line, default is "solid" - - color: the color of the line, default is "black" + Optional Keys: + - linestyle: the style of the line, default is "solid" + - color: the color of the line, default is "black" """ self.ax.plot( self.data, @@ -373,8 +374,8 @@ def plot_probability_plot(self): """Plot a probability plot. This method uses the prob_plot_args dict. There are no required keys for this dict. - *Optional Keys* - - color: the color of the plot, default is "orangered" + Optional Keys: + - color: the color of the plot, default is "orangered" """ # Extract Fields sample_data = self.data @@ -467,11 +468,11 @@ def plot_contour_plot(self): required keys for this dict. Please note that the data must be a list of 2D numpy arrays. - *Optional Keys* - - filled: whether to fill the contour plot, default is False - - colors: the color of the contour plot, default is "k" - - inline: whether to show the inline labels, default is True - - fsize: the font size of the labels, default is 9 + Optional Keys: + - filled: whether to fill the contour plot, default is False + - colors: the color of the contour plot, default is "k" + - inline: whether to show the inline labels, default is True + - fsize: the font size of the labels, default is 9 """ func = self.ax.contourf if self.contour_args["filled"] else self.ax.contour @@ -498,13 +499,14 @@ class Multiplots(Plot): :param dict args: the master dictionary containing the required fields. - *Required Keys* - - super_title: the title of the main figure - - super_xlabel: the x-axis label of the main figure - - super_ylabel: the y-axis label of the main figure - - share_axes: whether to share the axes of the subplots + Required Keys: + - super_title: the title of the main figure + - super_xlabel: the x-axis label of the main figure + - super_ylabel: the y-axis label of the main figure + - share_axes: whether to share the axes of the subplots **Example** + >>> args = { ... "super_title": "Test Title", ... "super_xlabel": "Test X Label", @@ -553,12 +555,12 @@ def overlay(self, overlay_args): :param dict overlay_args: Master dictionary of all inputs - *Required Keys* - - plot: The graph name. - - data: The data to plot onto the graph - - axes_labels: The axes labels + Required Keys: + - plot: The graph name. + - data: The data to plot onto the graph + - axes_labels: The axes labels - *Optional Keys* + *Optional Keys*: customs: The plot's customization. """ plot = overlay_args.get("plot") @@ -581,8 +583,9 @@ def new_subplot(self): def __call__(self): """Build the main figure, label its axes and display the result. - + **Usage** + >>> args = { ... "super_title": "Test Title", ... "super_xlabel": "Test X Label", @@ -675,6 +678,7 @@ class PlotUtilities: """Class containing auxillary utility functions for plotting. **Usage** + >>> util = PlottingUtilities() """ From 348334e0e512d2760d4a23242e7a5a5f1d1b8edc Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Thu, 17 Oct 2024 12:06:34 -0400 Subject: [PATCH 04/29] add docs --- .gitignore | 4 + docs/Multiplots.html | 254 ++++++++++++++++++++++ docs/Plot.html | 357 +++++++++++++++++++++++++++++++ docs/genindex.html | 425 +++++++++++++++++++++++++++++++++++++ docs/index.html | 271 ++++++++++++++++++++--- docs/py-modindex.html | 168 +++++++++++++++ docs/search.html | 150 +++++++++++++ docs/source/Multiplots.rst | 97 +++++++++ docs/source/Plot.rst | 218 +++++++++++++++++++ docs/source/index.rst | 68 +++++- src/plotting/plotting.py | 58 ++--- 11 files changed, 2009 insertions(+), 61 deletions(-) create mode 100644 docs/Multiplots.html create mode 100644 docs/Plot.html create mode 100644 docs/genindex.html create mode 100644 docs/py-modindex.html create mode 100644 docs/search.html create mode 100644 docs/source/Multiplots.rst create mode 100644 docs/source/Plot.rst diff --git a/.gitignore b/.gitignore index a35cb4a..71f1738 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,9 @@ instance/ # Sphinx documentation docs/_build/ +docs/_sources/ +docs/_static/ +docs/autoapi/ # PyBuilder .pybuilder/ @@ -149,6 +152,7 @@ dmypy.json # Pyre type checker .pyre/ docs/.buildinfo +docs/.doctrees/autoapi docs/.doctrees/api.doctree docs/.doctrees/environment.pickle docs/.doctrees/generated/compute.doctree diff --git a/docs/Multiplots.html b/docs/Multiplots.html new file mode 100644 index 0000000..54e9602 --- /dev/null +++ b/docs/Multiplots.html @@ -0,0 +1,254 @@ + + + + + + + + + + Plotting.Multiplots Usage Guide — plotting documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+
+
+ +
+

Plotting.Multiplots Usage Guide

+

The Multiplots Class allows users to plot multiple plots and overlay them on a single figure. The Multiplots Class requires a dictionary of arguments to be passed to the class:

+
    +
  • super_title (str): The title of the figure.

  • +
  • super_xlabel (str): The x-axis label of the figure.

  • +
  • super_ylabel (str): The y-axis label of the figure.

  • +
  • share_axes (bool): Whether to share the y-axes across all subplots.

  • +
+
+

Examples

+
+

Overlay Plots

+

The overlay method allows users to overlay multiple plots on a single subplot. The overlay method requires a dictionary of arguments to be passed to the method:

+
    +
  • plot

  • +
  • data (list): A list of data that will be plotted.

  • +
+
import plotting
+
+# define main figure labels
+args = {"super_title": "Overlay Example", "super_xlabel": "X", "super_ylabel": "Y", "share_axes": False}
+
+multi = plotting.Multiplots(args)
+
+# Define Some Data
+data = np.random.normal(loc=2, scale=1, size=1000)
+
+# Create a subplot
+multi.new_subplot()
+
+plots = ["histogram", "density"]
+
+for plot in plots:
+    # set up overlay payload
+    overlay_payload = {"plot": plot, "data": data, "axes_labels": {}}
+
+    # Overlay a histogram
+    multi.overlay(overlay_payload)
+
+# Overlay a density plot
+overlay_payload = {"plot": "density", "data": data, "axes_labels": {"xlabel": "X", "ylabel": "Y"}}
+multi.overlay(overlay_payload)
+
+multi()
+
+
+OverlayHeteroExample +
+
+

Subplots

+

The new_subplot method allows users to create a new subplot on the figure. The new_subplot method requires no arguments to be passed to the method. When a user is finished creating subplots, they can call the Multiplots object to render the figure.

+
import plotting
+
+# define main figure labels
+args = {"super_title": "Subplots Example", "super_xlabel": "X", "super_ylabel": "Y", "share_axes": False}
+
+multi = plotting.Multiplots(args)
+
+# Define Some Data
+data = np.random.normal(loc=0.8, scale=2, size=50)
+
+# Define Plots
+plots = ["histogram", "density", "prob_plot", "gen_plot", "norm_cdf"]
+
+for plot in plots:
+    # Create a subplot
+    multi.new_subplot()
+    axes_labels = {"xlabel": " ", "ylabel": " ", "title": plot}
+
+    overlay_payload = {"plot": plot, "data": data, "axes_labels": axes_labels}
+    multi.overlay(overlay_payload)
+
+multi.overlay(overlay_payload)
+
+multi()
+
+
+SubplotsExample +
+
+
+ + +
+
+
+
+ + + + + +
+
+
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/Plot.html b/docs/Plot.html new file mode 100644 index 0000000..93db462 --- /dev/null +++ b/docs/Plot.html @@ -0,0 +1,357 @@ + + + + + + + + + + Plotting.Plot Usage Guide — plotting documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+
+
+ +
+

Plotting.Plot Usage Guide

+

The Plot Class allows users to plot a single plot at a time on a specified axis. The Plot Class requires a dictionary of arguments to be passed to the class. The following keys are required in the dictionary:

+
    +
  • data: The data that will be plotted.

  • +
  • ax: The axis object that the plot will be plotted on.

  • +
  • fig: The figure object that the plot will be plotted on.

  • +
+

There are currently 9 different plot types that can be created using the Plot Class. The Plot Class also allows users to customize these plot by passing additional arguments in the dictionary. The following arguments can be passed to the dictionary:

+
    +
  • axes_labels: A dictionary containing the x, y, and title labels, and the scale for the plot.

  • +
  • gen_plot_args: A dictionary containing additional arguments for a generic plot, such as color, linestyle, etc.

  • +
  • hist_args: A dictionary containing additional arguments for a histogram plot, such as color, bins, etc.

  • +
  • timeseries_args: A dictionary containing additional arguments for a time series plot, such as color, linestyle, etc.

  • +
  • cdf_args: A dictionary containing additional arguments for a cumulative distribution function plot, such as color, linestyle, etc.

  • +
  • boxplot_args: A dictionary containing additional arguments for a boxplot plot, such as color, notch, etc.

  • +
  • norm_cdf_args: A dictionary containing additional arguments for a normal cumulative distribution function plot, such as color etc.

  • +
  • density_args: A dictionary containing additional arguments for a density plot, such as color, fill, etc.

  • +
  • prob_plot_args: A dictionary containing additional arguments for a probability plot, such as color etc.

  • +
  • contour_args: A dictionary containing additional arguments for a contour plot, such as color, filled, etc.

  • +
+
+

Examples

+
+

Generic Plot

+

The Generic Plot is a simple plot that can be used to plot any type of data. The plot is created using the generic_plot method. Users can pass both x and y data or just y data to the plot.

+
import matplotlib.pyplot as plt
+import plotting
+
+fig, ax = plt.subplots()
+
+# Only y data
+data = np.random.randn(100)
+
+# customize the plot
+gen_plot_args = {"color": "red", "linestyle": "--"}
+# label the plot
+axes_labels = {"ylabel": "Y", "title": "Generic Plot Example"}
+
+# set the arguments
+args = {"data": data, "ax": ax, "fig": fig, "gen_plot_args": gen_plot_args, "axes_labels": axes_labels}
+plot = plotting.Plot(args)
+
+plot.generic_plot()
+
+plt.show()
+
+
+GenericPlotOnlyY +
import matplotlib.pyplot as plt
+import plotting
+
+fig, ax = plt.subplots()
+
+# x and y data
+x = np.linspace(0, 10, 100)
+y = np.sin(x)
+
+# customize the plot
+gen_plot_args = {"color": "mediumpurple", "linestyle": "--"}
+
+# label the plot
+axes_labels = {"ylabel": "Y", "xlabel": "X", "title": "Generic Plot Example with X & Y"}
+
+args = {"data": [x, y], "ax": ax, "fig": fig, "gen_plot_args": gen_plot_args, "axes_labels": axes_labels}
+plot = plotting.Plot(args)
+
+plot.generic_plot()
+
+plt.show()
+
+
+GenericPlotXY +
+
+

Histogram

+

A histogram plot can be created using the plot_histogram method.

+
import matplotlib.pyplot as plt
+import plotting
+
+fig, ax = plt.subplots()
+
+data = np.random.randn(1000)
+
+# customize the plot
+
+histogram_args = {"color": "salmon", "num_bins": 30}
+
+# label the plot
+axes_labels = {"ylabel": "Frequency", "xlabel": "Value", "title": "Histogram Plot Example"}
+
+args = {"data": data, "ax": ax, "fig": fig, "histogram_args": histogram_args, "axes_labels": axes_labels}
+plot = plotting.Plot(args)
+
+plot.plot_histogram()
+
+plt.show()
+
+
+HistogramExample +
+
+

Contour Plot

+

Contour plots can be created using the plot_contour method. The contour plot requires 2D arrays of X, Y and Z data to be passed to the plot.

+
import matplotlib.pyplot as plt
+import plotting
+
+fig, ax = plt.subplots()
+
+x = np.linspace(-3.0, 3.0, 100)
+y = np.linspace(-3.0, 3.0, 100)
+X, Y = np.meshgrid(x, y)
+Z = np.cos(X/3) * np.sin(Y/3)
+
+# label the plot
+axes_labels = {"xlabel": "X", "ylabel": "Y", "title": "Contour Plot Example"}
+
+args = {"data": [X, Y, Z], "ax": ax, "fig": fig, "axes_labels": axes_labels}
+plot = plotting.Plot(args)
+
+plot.plot_contour()
+
+plt.show()
+
+
+ContourExample +
+
+

Normal Probability Plot

+

The normal probability plot is used to determine if a dataset is approximately normally distributed. A normal probability plot can be created using the plot_probability_plot method. The normal probability plot requires a 1D array of data to be passed to the plot.

+
import matplotlib.pyplot as plt
+import plotting
+
+fig, ax = plt.subplots()
+
+data = np.random.randn(100)
+
+# customize the plot
+prob_plot_args = {"color": "firebrick"}
+
+# label the plot
+axes_labels = {"title": "Normal Probability Plot Example"}
+
+args = {"data": data, "ax": ax, "fig": fig, "axes_labels": axes_labels, "prob_plot_args": prob_plot_args}
+plot = plotting.Plot(args)
+
+plot.plot_probability_plot()
+
+plt.show()
+
+
+NormalProbabilityExample +
+
+

Normal Cumulative Distribution Function Plot

+

The CDF of a dataset can be compared to the CDF of a normal distribution using the normal CDF plot. The normal CDF plot can be created using the plot_normal_cdf method. Users can pass multiple datasets to the plot.

+
import matplotlib.pyplot as plt
+import plotting
+
+fig, ax = plt.subplots()
+
+dataset_one = np.random.exponential(scale=1.0, size=500)
+dataset_two = np.random.normal(loc=20, scale=1, size=500)
+dataset_three = np.random.gamma(2, 2, 500)
+data = [dataset_one, dataset_two, dataset_three]
+
+
+# label the plot
+axes_labels = {"title": "Normal Cumulative Distribution Function Plot Example"}
+
+args = {"data": data, "ax": ax, "fig": fig, "axes_labels": axes_labels}
+plot = plotting.Plot(args)
+
+plot.plot_normal_cdf()
+
+plt.show()
+
+
+NormalCDFExample +
+
+
+ + +
+
+
+
+ + + + + +
+
+
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/genindex.html b/docs/genindex.html new file mode 100644 index 0000000..d98375d --- /dev/null +++ b/docs/genindex.html @@ -0,0 +1,425 @@ + + + + + + + + + Index — plotting documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+
+
+ + +

Index

+ +
+ _ + | A + | B + | C + | D + | E + | F + | G + | H + | L + | M + | N + | O + | P + | S + | T + | U + +
+

_

+ + +
+ +

A

+ + + +
+ +

B

+ + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + +
+ +

G

+ + + +
+ +

H

+ + +
+ +

L

+ + +
+ +

M

+ + + +
+ +

N

+ + + +
+ +

O

+ + +
+ +

P

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

U

+ + + +
+ + + +
+
+
+
+ + + + + +
+
+
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 9429e36..50745f3 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,32 +1,241 @@ + + - - - - - Template Repository - Coming Soon - - - -
-
- Template Repository Documentation -
-
- -
-
-
-

Amazing Documentation Coming Soon!

-

We're working hard to build incredible docs. Stay tuned!

-
-
-
- -
-
-

© Elizabeth Consulting International Inc.

-
-
- - - + + + + + + + Plotting — plotting documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+
+
+ +
+

Plotting

+
+

Overview

+

Plotting is a simple tool that allows you to create plots using minimal lines of code.

+
+
+
+
+

Requirements

+

The plotting package requires the following packages:

+
    +
  • matplotlib >= 3.9.1

  • +
  • numpy >= 1.26.4

  • +
  • scipy >= 1.14.0

  • +
  • seaborn >= 0.11.0

  • +
+
+
+

Installation

+

To install the plotting package, run the following command:

+
pip install plotting
+
+
+
+
+

Usage

+

To use the plotting package, you need to import the package and create a plot object. +There are two main methods that you can use to create a plot:

+
    +
  • Plot: This method plots a single plot at a time on a specified axis.

  • +
  • Multiplots: This method plots multiple plots and overlays on a single figure.

  • +
+

Here is an example of how to use the plotting package:

+
import matplotlib.pyplot as plt
+import plotting
+
+fig, ax = plt.subplots()
+data = np.random.randn(100)
+args = {"data": data, "ax": ax, "fig": fig}
+plot = plotting.Plot(args)
+
+plot.generic_plot()
+
+plt.show()
+
+
+SimpleExampleResult + + +
+
+
+

Indices and tables

+ +
+ + +
+
+
+
+ + + + + +
+
+
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/py-modindex.html b/docs/py-modindex.html new file mode 100644 index 0000000..90f4dae --- /dev/null +++ b/docs/py-modindex.html @@ -0,0 +1,168 @@ + + + + + + + + + Python Module Index — plotting documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+
+
+ + +

Python Module Index

+ +
+ p | + t +
+ + + + + + + + + + + + + + + + + + +
 
+ p
+ plotting +
    + plotting.plotting +
 
+ t
+ tests +
    + tests.test_plotting +
+ + +
+
+
+
+ + + + + +
+
+
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/search.html b/docs/search.html new file mode 100644 index 0000000..8115dee --- /dev/null +++ b/docs/search.html @@ -0,0 +1,150 @@ + + + + + + + + + Search — plotting documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+
+
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + +
+ + +
+
+
+
+ + + + + +
+
+
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/source/Multiplots.rst b/docs/source/Multiplots.rst new file mode 100644 index 0000000..d4f848e --- /dev/null +++ b/docs/source/Multiplots.rst @@ -0,0 +1,97 @@ +Plotting.Multiplots Usage Guide +=============================== + +The Multiplots Class allows users to plot multiple plots and overlay them on a single figure. The Multiplots Class requires a dictionary of arguments to be passed to the class: + +- `super_title` (str): The title of the figure. +- `super_xlabel` (str): The x-axis label of the figure. +- `super_ylabel` (str): The y-axis label of the figure. +- `share_axes` (bool): Whether to share the y-axes across all subplots. + + +Examples +-------- + +Overlay Plots +~~~~~~~~~~~~~ + +The `overlay` method allows users to overlay multiple plots on a single subplot. The overlay method requires a dictionary of arguments to be passed to the method: + +- `plot` +- `data` (list): A list of data that will be plotted. + + + +.. code-block:: python + + import plotting + + # define main figure labels + args = {"super_title": "Overlay Example", "super_xlabel": "X", "super_ylabel": "Y", "share_axes": False} + + multi = plotting.Multiplots(args) + + # Define Some Data + data = np.random.normal(loc=2, scale=1, size=1000) + + # Create a subplot + multi.new_subplot() + + plots = ["histogram", "density"] + + for plot in plots: + # set up overlay payload + overlay_payload = {"plot": plot, "data": data, "axes_labels": {}} + + # Overlay a histogram + multi.overlay(overlay_payload) + + # Overlay a density plot + overlay_payload = {"plot": "density", "data": data, "axes_labels": {"xlabel": "X", "ylabel": "Y"}} + multi.overlay(overlay_payload) + + multi() + + +.. image:: https://clidapp.s3.amazonaws.com/static/server/img/overlay_hetero_eg.jpg + :alt: OverlayHeteroExample + :align: center + + +Subplots +~~~~~~~~ + +The `new_subplot` method allows users to create a new subplot on the figure. The new_subplot method requires no arguments to be passed to the method. When a user is finished creating subplots, they can call the Multiplots object to render the figure. + + +.. code-block:: python + + import plotting + + # define main figure labels + args = {"super_title": "Subplots Example", "super_xlabel": "X", "super_ylabel": "Y", "share_axes": False} + + multi = plotting.Multiplots(args) + + # Define Some Data + data = np.random.normal(loc=0.8, scale=2, size=50) + + # Define Plots + plots = ["histogram", "density", "prob_plot", "gen_plot", "norm_cdf"] + + for plot in plots: + # Create a subplot + multi.new_subplot() + axes_labels = {"xlabel": " ", "ylabel": " ", "title": plot} + + overlay_payload = {"plot": plot, "data": data, "axes_labels": axes_labels} + multi.overlay(overlay_payload) + + multi.overlay(overlay_payload) + + multi() + +.. image:: https://clidapp.s3.amazonaws.com/static/server/img/subplots_eg.jpg + :alt: SubplotsExample + :align: center + diff --git a/docs/source/Plot.rst b/docs/source/Plot.rst new file mode 100644 index 0000000..d86e4b8 --- /dev/null +++ b/docs/source/Plot.rst @@ -0,0 +1,218 @@ +Plotting.Plot Usage Guide +========================= + +The Plot Class allows users to plot a single plot at a time on a specified axis. The Plot Class requires a dictionary of arguments to be passed to the class. The following keys are required in the dictionary: + +- `data`: The data that will be plotted. +- `ax`: The axis object that the plot will be plotted on. +- `fig`: The figure object that the plot will be plotted on. + + +There are currently 9 different plot types that can be created using the Plot Class. The Plot Class also allows users to customize these plot by passing additional arguments in the dictionary. The following arguments can be passed to the dictionary: + +- `axes_labels`: A dictionary containing the x, y, and title labels, and the scale for the plot. +- `gen_plot_args`: A dictionary containing additional arguments for a generic plot, such as color, linestyle, etc. +- `hist_args`: A dictionary containing additional arguments for a histogram plot, such as color, bins, etc. +- `timeseries_args`: A dictionary containing additional arguments for a time series plot, such as color, linestyle, etc. +- `cdf_args`: A dictionary containing additional arguments for a cumulative distribution function plot, such as color, linestyle, etc. +- `boxplot_args`: A dictionary containing additional arguments for a boxplot plot, such as color, notch, etc. +- `norm_cdf_args`: A dictionary containing additional arguments for a normal cumulative distribution function plot, such as color etc. +- `density_args`: A dictionary containing additional arguments for a density plot, such as color, fill, etc. +- `prob_plot_args`: A dictionary containing additional arguments for a probability plot, such as color etc. +- `contour_args`: A dictionary containing additional arguments for a contour plot, such as color, filled, etc. + +Examples +-------- + +Generic Plot +~~~~~~~~~~~~ + +The Generic Plot is a simple plot that can be used to plot any type of data. The plot is created using the `generic_plot` method. Users can pass both x and y data or just y data to the plot. + +.. code-block:: python + + import matplotlib.pyplot as plt + import plotting + + fig, ax = plt.subplots() + + # Only y data + data = np.random.randn(100) + + # customize the plot + gen_plot_args = {"color": "red", "linestyle": "--"} + # label the plot + axes_labels = {"ylabel": "Y", "title": "Generic Plot Example"} + + # set the arguments + args = {"data": data, "ax": ax, "fig": fig, "gen_plot_args": gen_plot_args, "axes_labels": axes_labels} + plot = plotting.Plot(args) + + plot.generic_plot() + + plt.show() + +.. image:: https://clidapp.s3.amazonaws.com/static/server/img/gen_plot_only_y.jpg + :alt: GenericPlotOnlyY + :align: center + + +.. code-block:: python + + import matplotlib.pyplot as plt + import plotting + + fig, ax = plt.subplots() + + # x and y data + x = np.linspace(0, 10, 100) + y = np.sin(x) + + # customize the plot + gen_plot_args = {"color": "mediumpurple", "linestyle": "--"} + + # label the plot + axes_labels = {"ylabel": "Y", "xlabel": "X", "title": "Generic Plot Example with X & Y"} + + args = {"data": [x, y], "ax": ax, "fig": fig, "gen_plot_args": gen_plot_args, "axes_labels": axes_labels} + plot = plotting.Plot(args) + + plot.generic_plot() + + plt.show() + +.. image:: https://clidapp.s3.amazonaws.com/static/server/img/gen_plot_x_y.jpg + :alt: GenericPlotXY + :align: center + + +Histogram +~~~~~~~~~ + +A histogram plot can be created using the `plot_histogram` method. + + +.. code-block:: python + + import matplotlib.pyplot as plt + import plotting + + fig, ax = plt.subplots() + + data = np.random.randn(1000) + + # customize the plot + + histogram_args = {"color": "salmon", "num_bins": 30} + + # label the plot + axes_labels = {"ylabel": "Frequency", "xlabel": "Value", "title": "Histogram Plot Example"} + + args = {"data": data, "ax": ax, "fig": fig, "histogram_args": histogram_args, "axes_labels": axes_labels} + plot = plotting.Plot(args) + + plot.plot_histogram() + + plt.show() + +.. image:: https://clidapp.s3.amazonaws.com/static/server/img/hist_eg.jpg + :alt: HistogramExample + :align: center + + +Contour Plot +~~~~~~~~~~~~ + +Contour plots can be created using the `plot_contour` method. The contour plot requires 2D arrays of X, Y and Z data to be passed to the plot. + +.. code-block:: python + + import matplotlib.pyplot as plt + import plotting + + fig, ax = plt.subplots() + + x = np.linspace(-3.0, 3.0, 100) + y = np.linspace(-3.0, 3.0, 100) + X, Y = np.meshgrid(x, y) + Z = np.cos(X/3) * np.sin(Y/3) + + # label the plot + axes_labels = {"xlabel": "X", "ylabel": "Y", "title": "Contour Plot Example"} + + args = {"data": [X, Y, Z], "ax": ax, "fig": fig, "axes_labels": axes_labels} + plot = plotting.Plot(args) + + plot.plot_contour() + + plt.show() + +.. image:: https://clidapp.s3.amazonaws.com/static/server/img/contour_eg.jpg + :alt: ContourExample + :align: center + + +Normal Probability Plot +~~~~~~~~~~~~~~~~~~~~~~~ + +The normal probability plot is used to determine if a dataset is approximately normally distributed. A normal probability plot can be created using the `plot_probability_plot` method. The normal probability plot requires a 1D array of data to be passed to the plot. + +.. code-block:: python + + import matplotlib.pyplot as plt + import plotting + + fig, ax = plt.subplots() + + data = np.random.randn(100) + + # customize the plot + prob_plot_args = {"color": "firebrick"} + + # label the plot + axes_labels = {"title": "Normal Probability Plot Example"} + + args = {"data": data, "ax": ax, "fig": fig, "axes_labels": axes_labels, "prob_plot_args": prob_plot_args} + plot = plotting.Plot(args) + + plot.plot_probability_plot() + + plt.show() + +.. image:: https://clidapp.s3.amazonaws.com/static/server/img/norm_prob_eg.jpg + :alt: NormalProbabilityExample + :align: center + +Normal Cumulative Distribution Function Plot +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The CDF of a dataset can be compared to the CDF of a normal distribution using the normal CDF plot. The normal CDF plot can be created using the `plot_normal_cdf` method. Users can pass multiple datasets to the plot. + + +.. code-block:: python + + import matplotlib.pyplot as plt + import plotting + + fig, ax = plt.subplots() + + dataset_one = np.random.exponential(scale=1.0, size=500) + dataset_two = np.random.normal(loc=20, scale=1, size=500) + dataset_three = np.random.gamma(2, 2, 500) + data = [dataset_one, dataset_two, dataset_three] + + + # label the plot + axes_labels = {"title": "Normal Cumulative Distribution Function Plot Example"} + + args = {"data": data, "ax": ax, "fig": fig, "axes_labels": axes_labels} + plot = plotting.Plot(args) + + plot.plot_normal_cdf() + + plt.show() + +.. image:: https://clidapp.s3.amazonaws.com/static/server/img/norm_cdf_eg.jpg + :alt: NormalCDFExample + :align: center + diff --git a/docs/source/index.rst b/docs/source/index.rst index c1a7cab..25b9fa0 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -3,16 +3,78 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -plotting documentation -====================== +Plotting +======== + +Overview +-------- + +**Plotting** is a simple tool that allows you to create plots using minimal lines of code. -**plotting** is a simple tool that allows you to create plots from data. .. toctree:: :maxdepth: 2 :caption: Contents: +Requirements +------------ + +The plotting package requires the following packages: + +- `matplotlib` >= 3.9.1 +- `numpy` >= 1.26.4 +- `scipy` >= 1.14.0 +- `seaborn` >= 0.11.0 + +Installation +------------ +To install the plotting package, run the following command: + +.. code-block:: shell + + pip install plotting + + +Usage +----- +To use the plotting package, you need to import the package and create a plot object. +There are two main methods that you can use to create a plot: + +- `Plot`: This method plots a single plot at a time on a specified axis. +- `Multiplots`: This method plots multiple plots and overlays on a single figure. + +Here is an example of how to use the plotting package: + +.. code-block:: python + + import matplotlib.pyplot as plt + import plotting + + fig, ax = plt.subplots() + data = np.random.randn(100) + args = {"data": data, "ax": ax, "fig": fig} + plot = plotting.Plot(args) + + plot.generic_plot() + + plt.show() + +.. image:: https://clidapp.s3.amazonaws.com/static/server/img/plot_index_eg.jpg + :alt: SimpleExampleResult + :align: center + +.. toctree:: + :maxdepth: 2 + + Plot + +.. toctree:: + :maxdepth: 2 + + Multiplots + + Indices and tables ================== * :ref:`genindex` diff --git a/src/plotting/plotting.py b/src/plotting/plotting.py index ca1f906..4e068d6 100644 --- a/src/plotting/plotting.py +++ b/src/plotting/plotting.py @@ -166,7 +166,7 @@ def set_defaults(self, field): defaults = { "axes_labels": def_axes_labels, "export": {"format": "eps", "fname": "plot.eps"}, - "cdf": {}, + "cdf": {"color": "dogerblue"}, "density": {"color": "red", "fill": False, "label": " "}, "histogram": {"num_bins": 20, "color": "plum", "ran": None}, "timeseries": {"linestyle": "solid", "color": "black"}, @@ -229,6 +229,23 @@ def label_axes(self): if self.axes_labels["show_legend"]: self.ax.legend() + def export_plot_to_file(self): + """Export the current figure to a file. This method uses the export_args dict. + There are no required keys for this dict. + + Optional Keys + - format: the format of the exported file, default is "eps" + - fname: the name of the exported file, default is "plot.eps" + """ + + self.fig.savefig( + self.export_args["fname"], + format=self.export_args["format"], + bbox_inches="tight", + pad_inches=1, + orientation="portrait", + ) + def generic_plot(self) -> None: """Plot a generic plot using y and/or x. This method uses the gen_plot_args dict. There are no required keys for this dict. @@ -261,23 +278,6 @@ def generic_plot(self) -> None: ) self.label_axes() - def export_plot_to_file(self): - """Export the current figure to a file. This method uses the export_args dict. - There are no required keys for this dict. - - Optional Keys - - format: the format of the exported file, default is "eps" - - fname: the name of the exported file, default is "plot.eps" - """ - - self.fig.savefig( - self.export_args["fname"], - format=self.export_args["format"], - bbox_inches="tight", - pad_inches=1, - orientation="portrait", - ) - def plot_cdf(self) -> None: """Plot CDF of a dataset. This method uses the cdf_args dict. There are no required keys for this dict. @@ -286,7 +286,7 @@ def plot_cdf(self) -> None: x = np.sort(self.data) y = np.cumsum(x) / np.sum(x) - self.ax.plot(x, y, linewidth=1.5, label=self.axes_labels["linelabel"]) + self.ax.plot(x, y, linewidth=1.5, label=self.axes_labels["linelabel"], color=self.cdf_args["color"]) for hline in (0.1, 0.5, 0.9): self.ax.axhline(y=hline, color="black", linewidth=1, linestyle="dashed") @@ -404,15 +404,17 @@ def plot_probability_plot(self): ) # Plot Solid Line - plt.axline((0, mu), slope=sigma, color="black", linewidth=1) + plt.axline( + (0, mu), + slope=sigma, + color="black", + linewidth=1, + label=f"slope={mu:.2f}, y-intercept={sigma:.2f}", + ) # Create Axes Labels self.axes_labels.update( - { - "xlabel": "z percentile", - "ylabel": "Observations", - "show_legend": False, - } + {"xlabel": "z percentile", "ylabel": "Observations"} ) # label the axes @@ -463,7 +465,7 @@ def plot_normal_cdf(self): # label the axes self.label_axes() - def plot_contour_plot(self): + def plot_contour(self): """Plot a contour plot. This method uses the contour_args dict. There are no required keys for this dict. Please note that the data must be a list of 2D numpy arrays. @@ -544,7 +546,8 @@ def __init__(self, args): "boxplots": self.plot_box_plots, "prob_plot": self.plot_probability_plot, "gen_plot": self.generic_plot, - "contour": self.plot_contour_plot, + "contour": self.plot_contour, + "norm_cdf": self.plot_normal_cdf, } self.subplots = [] @@ -644,6 +647,7 @@ def __call__(self): self.fig.supxlabel(self.super_xlabel) self.fig.supylabel(self.super_ylabel) self.fig.tight_layout() + plt.savefig("same_overlay_eg.jpg") plt.show() # Reset Canvas From c0723efe3a29a065bab2c7a4f2afe2753e026227 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Thu, 17 Oct 2024 13:59:16 -0400 Subject: [PATCH 05/29] rename plotting --> chartly --- docs/Multiplots.html | 28 ++-- docs/Plot.html | 52 +++--- docs/genindex.html | 148 +++++++++--------- docs/index.html | 42 ++--- docs/py-modindex.html | 12 +- docs/searchindex.js | 1 + docs/source/Multiplots.rst | 10 +- docs/source/Plot.rst | 26 +-- docs/source/index.rst | 20 +-- src/{plotting => chartly}/__init__.py | 0 .../plotting.py => chartly/chartly.py} | 0 .../{test_plotting.py => test_chartly.py} | 2 +- 12 files changed, 171 insertions(+), 170 deletions(-) create mode 100644 docs/searchindex.js rename src/{plotting => chartly}/__init__.py (100%) rename src/{plotting/plotting.py => chartly/chartly.py} (100%) rename src/tests/{test_plotting.py => test_chartly.py} (98%) diff --git a/docs/Multiplots.html b/docs/Multiplots.html index 54e9602..1dcd807 100644 --- a/docs/Multiplots.html +++ b/docs/Multiplots.html @@ -7,7 +7,7 @@ - Plotting.Multiplots Usage Guide — plotting documentation + Chartly.Multiplots Usage Guide — plotting documentation @@ -37,7 +37,7 @@ - + @@ -70,8 +70,8 @@

Navigation

-
-

Plotting.Multiplots Usage Guide

+
+

Chartly.Multiplots Usage Guide

The Multiplots Class allows users to plot multiple plots and overlay them on a single figure. The Multiplots Class requires a dictionary of arguments to be passed to the class:

@@ -70,8 +70,8 @@

Navigation

-
-

Plotting.Plot Usage Guide

+
+

chartly.Plot Usage Guide

The Plot Class allows users to plot a single plot at a time on a specified axis. The Plot Class requires a dictionary of arguments to be passed to the class. The following keys are required in the dictionary:

@@ -218,11 +232,11 @@

M

N

@@ -230,7 +244,7 @@

N

O

@@ -238,43 +252,29 @@

O

P

@@ -282,25 +282,25 @@

P

S

@@ -308,23 +308,23 @@

S

T

  • - tests.test_plotting + tests.test_chartly
  • -
  • tiling() (plotting.plotting.Multiplots method) +
  • tiling() (chartly.chartly.Multiplots method)
  • -
  • timeseries_args (plotting.plotting.Plot attribute) +
  • timeseries_args (chartly.chartly.Plot attribute)
  • @@ -350,11 +350,11 @@

    T

    U

    diff --git a/docs/index.html b/docs/index.html index 50745f3..02d72f9 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ - Plotting — plotting documentation + Chartly — plotting documentation @@ -36,7 +36,7 @@ - +
    @@ -51,11 +51,11 @@

    Navigation

    modules    
  • - next    
  • plotting documentation »
  • - +
    @@ -66,17 +66,17 @@

    Navigation

    -
    -

    Plotting

    +
    +

    Chartly

    Overview

    -

    Plotting is a simple tool that allows you to create plots using minimal lines of code.

    +

    Chartly is a simple tool that allows you to create plots using minimal lines of code.

    Requirements

    -

    The plotting package requires the following packages:

    +

    The chartly package requires the following packages:

    • matplotlib >= 3.9.1

    • numpy >= 1.26.4

    • @@ -86,27 +86,27 @@

      Requirements

      Installation

      -

      To install the plotting package, run the following command:

      -
      pip install plotting
      +

      To install the chartly package, run the following command:

      +
      pip install chartly
       

    Usage

    -

    To use the plotting package, you need to import the package and create a plot object. +

    To use the chartly package, you need to import the package and create a plot object. There are two main methods that you can use to create a plot:

    • Plot: This method plots a single plot at a time on a specified axis.

    • Multiplots: This method plots multiple plots and overlays on a single figure.

    -

    Here is an example of how to use the plotting package:

    +

    Here is an example of how to use the chartly package:

    import matplotlib.pyplot as plt
    -import plotting
    +import chartly
     
     fig, ax = plt.subplots()
     data = np.random.randn(100)
     args = {"data": data, "ax": ax, "fig": fig}
    -plot = plotting.Plot(args)
    +plot = chartly.Plot(args)
     
     plot.generic_plot()
     
    @@ -116,7 +116,7 @@ 

    Usage SimpleExampleResult
    diff --git a/docs/py-modindex.html b/docs/py-modindex.html index 90f4dae..89416e7 100644 --- a/docs/py-modindex.html +++ b/docs/py-modindex.html @@ -68,24 +68,24 @@

    Navigation

    Python Module Index

    - p | + c | t
    - +
     
    - p
    + c
    - plotting + chartly
        - plotting.plotting + chartly.chartly
     
    @@ -99,7 +99,7 @@

    Python Module Index

        - tests.test_plotting + tests.test_chartly
    diff --git a/docs/searchindex.js b/docs/searchindex.js new file mode 100644 index 0000000..28a94fa --- /dev/null +++ b/docs/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"alltitles": {"API Reference": [[4, null]], "Attributes": [[2, "attributes"]], "Chartly": [[7, null]], "Chartly.Multiplots Usage Guide": [[0, null]], "Classes": [[2, "classes"], [6, "classes"]], "Contour Plot": [[1, "contour-plot"]], "Examples": [[0, "examples"], [1, "examples"]], "Generic Plot": [[1, "generic-plot"]], "Histogram": [[1, "histogram"]], "Indices and tables": [[7, "indices-and-tables"]], "Installation": [[7, "installation"]], "Module Contents": [[2, "module-contents"], [6, "module-contents"]], "Normal Cumulative Distribution Function Plot": [[1, "normal-cumulative-distribution-function-plot"]], "Normal Probability Plot": [[1, "normal-probability-plot"]], "Overlay Plots": [[0, "overlay-plots"]], "Overview": [[7, "overview"]], "Requirements": [[7, "requirements"]], "Submodules": [[3, "submodules"], [5, "submodules"]], "Subplots": [[0, "subplots"]], "Usage": [[7, "usage"]], "chartly": [[3, null]], "chartly.Plot Usage Guide": [[1, null]], "chartly.chartly": [[2, null]], "tests": [[5, null]], "tests.test_chartly": [[6, null]]}, "docnames": ["Multiplots", "Plot", "autoapi/chartly/chartly/index", "autoapi/chartly/index", "autoapi/index", "autoapi/tests/index", "autoapi/tests/test_chartly/index", "index"], "envversion": {"sphinx": 64, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["Multiplots.rst", "Plot.rst", "autoapi/chartly/chartly/index.rst", "autoapi/chartly/index.rst", "autoapi/index.rst", "autoapi/tests/index.rst", "autoapi/tests/test_chartly/index.rst", "index.rst"], "indexentries": {"__call__() (chartly.chartly.multiplots method)": [[2, "chartly.chartly.Multiplots.__call__", false]], "ax (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.ax", false]], "axes_labels (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.axes_labels", false]], "boxplot_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.boxplot_args", false]], "cdf_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.cdf_args", false]], "chartly": [[3, "module-chartly", false]], "chartly.chartly": [[2, "module-chartly.chartly", false]], "clear_axis() (chartly.chartly.multiplots method)": [[2, "chartly.chartly.Multiplots.clear_axis", false]], "color_list (in module chartly.chartly)": [[2, "chartly.chartly.color_list", false]], "contour_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.contour_args", false]], "current_subplot (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.current_subplot", false]], "data (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.data", false]], "density_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.density_args", false]], "export_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.export_args", false]], "export_plot_to_file() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.export_plot_to_file", false]], "fig (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.fig", false]], "gen_plot_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.gen_plot_args", false]], "generic_plot() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.generic_plot", false]], "graphs (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.graphs", false]], "hist_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.hist_args", false]], "label_axes() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.label_axes", false]], "module": [[2, "module-chartly.chartly", false], [3, "module-chartly", false], [5, "module-tests", false], [6, "module-tests.test_chartly", false]], "multiplots (class in chartly.chartly)": [[2, "chartly.chartly.Multiplots", false]], "new_subplot() (chartly.chartly.multiplots method)": [[2, "chartly.chartly.Multiplots.new_subplot", false]], "norm_cdf_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.norm_cdf_args", false]], "overlay() (chartly.chartly.multiplots method)": [[2, "chartly.chartly.Multiplots.overlay", false]], "plot (class in chartly.chartly)": [[2, "chartly.chartly.Plot", false]], "plot_box_plots() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_box_plots", false]], "plot_cdf() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_cdf", false]], "plot_contour() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_contour", false]], "plot_density() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_density", false]], "plot_histogram() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_histogram", false]], "plot_normal_cdf() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_normal_cdf", false]], "plot_probability_plot() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_probability_plot", false]], "plot_timeseries() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_timeseries", false]], "plotutilities (class in chartly.chartly)": [[2, "chartly.chartly.PlotUtilities", false]], "prob_plot_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.prob_plot_args", false]], "set_defaults() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.set_defaults", false]], "setup() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.setUp", false]], "share_axes (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.share_axes", false]], "standardize_dataset() (chartly.chartly.plotutilities method)": [[2, "chartly.chartly.PlotUtilities.standardize_dataset", false]], "subplot_count (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.subplot_count", false]], "subplots (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.subplots", false]], "super_title (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.super_title", false]], "super_xlabel (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.super_xlabel", false]], "super_ylabel (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.super_ylabel", false]], "test_contour_data_length() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_contour_data_length", false]], "test_default() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_default", false]], "test_gen_plot_data_length() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_gen_plot_data_length", false]], "test_gen_plot_data_type() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_gen_plot_data_type", false]], "test_multi_clear_axis() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_multi_clear_axis", false]], "test_mutli_subplot_count() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_mutli_subplot_count", false]], "test_standardize_data() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_standardize_data", false]], "testplotting (class in tests.test_chartly)": [[6, "tests.test_chartly.TestPlotting", false]], "tests": [[5, "module-tests", false]], "tests.test_chartly": [[6, "module-tests.test_chartly", false]], "tiling() (chartly.chartly.multiplots method)": [[2, "chartly.chartly.Multiplots.tiling", false]], "timeseries_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.timeseries_args", false]], "update_defaults() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.update_defaults", false]], "util (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.util", false]]}, "objects": {"": [[3, 0, 0, "-", "chartly"], [5, 0, 0, "-", "tests"]], "chartly": [[2, 0, 0, "-", "chartly"]], "chartly.chartly": [[2, 1, 1, "", "Multiplots"], [2, 1, 1, "", "Plot"], [2, 1, 1, "", "PlotUtilities"], [2, 4, 1, "", "color_list"]], "chartly.chartly.Multiplots": [[2, 2, 1, "", "__call__"], [2, 2, 1, "", "clear_axis"], [2, 3, 1, "", "current_subplot"], [2, 3, 1, "", "graphs"], [2, 2, 1, "", "new_subplot"], [2, 2, 1, "", "overlay"], [2, 3, 1, "", "share_axes"], [2, 3, 1, "", "subplot_count"], [2, 3, 1, "", "subplots"], [2, 3, 1, "", "super_title"], [2, 3, 1, "", "super_xlabel"], [2, 3, 1, "", "super_ylabel"], [2, 2, 1, "", "tiling"]], "chartly.chartly.Plot": [[2, 3, 1, "", "ax"], [2, 3, 1, "", "axes_labels"], [2, 3, 1, "", "boxplot_args"], [2, 3, 1, "", "cdf_args"], [2, 3, 1, "", "contour_args"], [2, 3, 1, "", "data"], [2, 3, 1, "", "density_args"], [2, 3, 1, "", "export_args"], [2, 2, 1, "", "export_plot_to_file"], [2, 3, 1, "", "fig"], [2, 3, 1, "", "gen_plot_args"], [2, 2, 1, "", "generic_plot"], [2, 3, 1, "", "hist_args"], [2, 2, 1, "", "label_axes"], [2, 3, 1, "", "norm_cdf_args"], [2, 2, 1, "", "plot_box_plots"], [2, 2, 1, "", "plot_cdf"], [2, 2, 1, "", "plot_contour"], [2, 2, 1, "", "plot_density"], [2, 2, 1, "", "plot_histogram"], [2, 2, 1, "", "plot_normal_cdf"], [2, 2, 1, "", "plot_probability_plot"], [2, 2, 1, "", "plot_timeseries"], [2, 3, 1, "", "prob_plot_args"], [2, 2, 1, "", "set_defaults"], [2, 3, 1, "", "timeseries_args"], [2, 2, 1, "", "update_defaults"], [2, 3, 1, "", "util"]], "chartly.chartly.PlotUtilities": [[2, 2, 1, "", "standardize_dataset"]], "tests": [[6, 0, 0, "-", "test_chartly"]], "tests.test_chartly": [[6, 1, 1, "", "TestPlotting"]], "tests.test_chartly.TestPlotting": [[6, 2, 1, "", "setUp"], [6, 2, 1, "", "test_contour_data_length"], [6, 2, 1, "", "test_default"], [6, 2, 1, "", "test_gen_plot_data_length"], [6, 2, 1, "", "test_gen_plot_data_type"], [6, 2, 1, "", "test_multi_clear_axis"], [6, 2, 1, "", "test_mutli_subplot_count"], [6, 2, 1, "", "test_standardize_data"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "attribute", "Python attribute"], "4": ["py", "data", "Python data"]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:attribute", "4": "py:data"}, "terms": {"": 2, "0": [0, 1, 2, 7], "1": [0, 1, 2, 4, 6, 7], "10": [1, 2], "100": [1, 7], "1000": [0, 1], "11": 7, "14": 7, "1d": [1, 6], "2": [0, 1, 2, 6], "20": [1, 2], "26": 7, "2d": [1, 2, 6], "3": [1, 2, 6, 7], "30": 1, "4": [2, 7], "5": 2, "50": 0, "500": 1, "8": 0, "9": [1, 2, 7], "A": [0, 1, 2, 6], "The": [0, 1, 2, 7], "There": [1, 2, 7], "To": 7, "_": 2, "__call__": 2, "across": 0, "add": [], "addit": 1, "against": 2, "all": [0, 2], "allow": [0, 1, 7], "also": 1, "an": [2, 6, 7], "ang": [2, 6], "ani": 1, "api": 7, "apopo": [2, 6], "approxim": 1, "ar": [1, 2, 6, 7], "arg": [0, 1, 2, 7], "argument": [0, 1], "arrai": [1, 2], "assist": [2, 6], "author": [2, 6], "auto": 4, "autoapi": 4, "auxillari": 2, "ax": [0, 1, 2, 7], "axes_label": [0, 1, 2], "axi": [0, 1, 2, 6, 7], "azenda": [2, 6], "base": [2, 6], "bin": [1, 2], "black": 2, "bool": 0, "both": [1, 2, 6], "box": 2, "boxplot": [1, 2], "boxplot_arg": [1, 2], "build": 2, "c": [2, 6], "calcul": 2, "call": 0, "can": [0, 1, 6, 7], "cdf": [1, 2], "cdf_arg": [1, 2], "chartli": 4, "cheikh": [2, 6], "class": [0, 1], "clear": 6, "clear_axi": 2, "cmbengu": [2, 6], "co": 1, "code": 7, "color": [1, 2], "color_list": 2, "column": 2, "com": [2, 6], "command": 7, "compani": [2, 6], "compar": 1, "consult": [2, 6], "contain": [1, 2, 4], "content": [], "contour": [2, 6], "contour_arg": [1, 2], "correctli": 6, "creat": [0, 1, 2, 4, 6, 7], "current": [1, 2], "current_subplot": 2, "custom": [1, 2], "data": [0, 1, 2, 6, 7], "dataset": [1, 2], "dataset_on": 1, "dataset_thre": 1, "dataset_two": 1, "decis": [2, 6], "default": [2, 6], "defin": 0, "densiti": [0, 1, 2], "density_arg": [1, 2], "detail": [], "determin": 1, "develop": [2, 6], "dict": 2, "dictionari": [0, 1, 2], "differ": 1, "displai": 2, "distribut": 2, "divid": 2, "document": 4, "e": [2, 6], "each": 2, "ec": [2, 6], "eci": [2, 6], "elizabeth": [2, 6], "ep": 2, "error": 6, "estim": 2, "etc": 1, "exampl": [2, 7], "exponenti": 1, "export": 2, "export_arg": 2, "export_plot_to_fil": 2, "fals": [0, 2], "field": 2, "fig": [1, 2, 7], "figur": [0, 1, 2, 7], "file": 2, "fill": [1, 2], "finish": 0, "firebrick": 1, "fname": 2, "follow": [1, 2, 7], "font": 2, "format": 2, "frequenc": 1, "from": 2, "fsize": 2, "function": 2, "gamma": 1, "gen_plot": 0, "gen_plot_arg": [1, 2], "gener": [2, 4, 6], "generic_plot": [1, 2, 7], "graph": 2, "guid": 7, "handl": 6, "here": 7, "hist_arg": [1, 2], "histogram": [0, 2], "histogram_arg": 1, "hold": 2, "how": 7, "i": [0, 1, 2, 6, 7], "import": [0, 1, 7], "inc": [2, 6], "index": 7, "indi": [2, 6], "inlin": 2, "input": 2, "int": 2, "intern": [2, 6], "intl": [2, 6], "its": 2, "just": 1, "k": 2, "kei": [1, 2], "kernel": 2, "label": [0, 1, 2], "label_ax": 2, "legend": 2, "length": 6, "lightpink": 2, "line": [2, 7], "linear": 2, "linelabel": 2, "linestyl": [1, 2], "linspac": 1, "list": [0, 2, 6], "loc": [0, 1], "lucia": [2, 6], "m": [2, 6], "main": [0, 2, 7], "mari": [2, 6], "master": 2, "matplotlib": [1, 7], "mbengu": [2, 6], "mean": 2, "mediumpurpl": 1, "mediumvioletr": 2, "meshgrid": 1, "method": [0, 1, 2, 7], "methodnam": 6, "minim": 7, "modul": 7, "multi": 0, "multipl": [0, 1, 2, 6, 7], "multiplot": [2, 6, 7], "must": 2, "name": 2, "navi": 2, "ndarrai": 2, "need": 7, "new": [0, 2], "new_subplot": [0, 2], "new_valu": 2, "none": 2, "norm_cdf": 0, "norm_cdf_arg": [1, 2], "normal": [0, 2], "notch": 1, "note": 2, "np": [0, 1, 7], "num": 2, "num_bin": [1, 2], "number": 2, "numpi": [2, 7], "o": [2, 6], "object": [0, 1, 6, 7], "onli": 1, "onto": 2, "option": 2, "orang": 2, "organ": [2, 6], "other": 2, "oumar": [2, 6], "outlier": 2, "overlai": [2, 7], "overlay_arg": 2, "overlay_payload": 0, "packag": 7, "page": [4, 7], "paramet": 2, "pass": [0, 1], "payload": 0, "pip": 7, "pleas": 2, "plot": [2, 6, 7], "plot_box_plot": 2, "plot_cdf": 2, "plot_contour": [1, 2], "plot_contour_plot": [], "plot_dens": 2, "plot_histogram": [1, 2], "plot_normal_cdf": [1, 2], "plot_probability_plot": [1, 2], "plot_timeseri": 2, "plottingutil": 2, "plotutil": 2, "plt": [1, 2, 7], "plum": 2, "popo": [2, 6], "privat": [2, 6], "prob_plot": 0, "prob_plot_arg": [1, 2], "probabl": 2, "pyplot": [1, 7], "ran": 2, "randn": [1, 7], "random": [0, 1, 7], "rang": 2, "red": [1, 2], "refer": 7, "render": 0, "requir": [0, 1, 2], "research": [2, 6], "reset": 2, "restructuredtext": [], "result": 2, "return": 2, "row": 2, "run": 7, "runtest": 6, "salmon": 1, "same": 2, "scale": [0, 1, 2], "scientist": [2, 6], "scipi": 7, "seaborn": 7, "search": 7, "sector": [2, 6], "see": [], "seri": 1, "set": [0, 1, 2, 6], "set_default": 2, "setup": 6, "share": [0, 2], "share_ax": [0, 2], "show": [1, 2, 7], "show_legend": 2, "showflier": 2, "simpl": [1, 7], "sin": 1, "singl": [0, 1, 7], "size": [0, 1, 2], "skyblu": 2, "slateblu": 2, "solid": 2, "some": 0, "special": [2, 6], "specifi": [1, 7], "sphinx": 4, "st": [2, 6], "standard": [2, 6], "standardize_dataset": 2, "std": 2, "str": [0, 2], "style": 2, "subplot": [1, 2, 6, 7], "subplot_count": 2, "subtract": 2, "super_titl": [0, 2], "super_xlabel": [0, 2], "super_ylabel": [0, 2], "support": [2, 6], "syntax": [], "system": [2, 6], "test": [2, 4, 7], "test_chartli": [4, 5], "test_contour_data_length": 6, "test_default": 6, "test_gen_plot_data_length": 6, "test_gen_plot_data_typ": 6, "test_multi_clear_axi": 6, "test_mutli_subplot_count": 6, "test_plot": [], "test_standardize_data": 6, "testcas": 6, "testplot": 6, "thei": 0, "them": 0, "thi": [2, 4, 7], "throw": 6, "tile": 2, "time": [1, 7], "timeseri": 2, "timeseries_arg": [1, 2], "titl": [0, 1, 2], "tool": 7, "tracker": 2, "true": 2, "tupl": 2, "two": 7, "type": [1, 2], "unequ": 6, "unittest": 6, "up": [0, 6], "updat": 2, "update_default": 2, "us": [1, 2, 6, 7], "usag": 2, "user": [0, 1], "util": 2, "valu": [1, 2], "variou": 2, "west": [2, 6], "when": 0, "whether": [0, 2], "x": [0, 1, 2], "xlabel": [0, 1, 2], "y": [0, 1, 2], "ylabel": [0, 1, 2], "you": 7, "your": [], "z": 1}, "titles": ["Chartly.Multiplots Usage Guide", "chartly.Plot Usage Guide", "chartly.chartly", "chartly", "API Reference", "tests", "tests.test_chartly", "Chartly"], "titleterms": {"api": 4, "attribut": 2, "chartli": [0, 1, 2, 3, 7], "class": [2, 6], "content": [2, 6], "contour": 1, "cumul": 1, "distribut": 1, "document": [], "exampl": [0, 1], "function": 1, "gener": 1, "guid": [0, 1], "histogram": 1, "indic": 7, "instal": 7, "modul": [2, 6], "multiplot": 0, "normal": 1, "overlai": 0, "overview": 7, "plot": [0, 1], "probabl": 1, "refer": 4, "requir": 7, "submodul": [3, 5], "subplot": 0, "tabl": 7, "test": [5, 6], "test_chartli": 6, "test_plot": [], "usag": [0, 1, 7]}}) \ No newline at end of file diff --git a/docs/source/Multiplots.rst b/docs/source/Multiplots.rst index d4f848e..b9dae7e 100644 --- a/docs/source/Multiplots.rst +++ b/docs/source/Multiplots.rst @@ -1,4 +1,4 @@ -Plotting.Multiplots Usage Guide +Chartly.Multiplots Usage Guide =============================== The Multiplots Class allows users to plot multiple plots and overlay them on a single figure. The Multiplots Class requires a dictionary of arguments to be passed to the class: @@ -24,12 +24,12 @@ The `overlay` method allows users to overlay multiple plots on a single subplot. .. code-block:: python - import plotting + import chartly # define main figure labels args = {"super_title": "Overlay Example", "super_xlabel": "X", "super_ylabel": "Y", "share_axes": False} - multi = plotting.Multiplots(args) + multi = chartly.Multiplots(args) # Define Some Data data = np.random.normal(loc=2, scale=1, size=1000) @@ -66,12 +66,12 @@ The `new_subplot` method allows users to create a new subplot on the figure. The .. code-block:: python - import plotting + import chartly # define main figure labels args = {"super_title": "Subplots Example", "super_xlabel": "X", "super_ylabel": "Y", "share_axes": False} - multi = plotting.Multiplots(args) + multi = chartly.Multiplots(args) # Define Some Data data = np.random.normal(loc=0.8, scale=2, size=50) diff --git a/docs/source/Plot.rst b/docs/source/Plot.rst index d86e4b8..a7bc549 100644 --- a/docs/source/Plot.rst +++ b/docs/source/Plot.rst @@ -1,4 +1,4 @@ -Plotting.Plot Usage Guide +Chartly.Plot Usage Guide ========================= The Plot Class allows users to plot a single plot at a time on a specified axis. The Plot Class requires a dictionary of arguments to be passed to the class. The following keys are required in the dictionary: @@ -32,7 +32,7 @@ The Generic Plot is a simple plot that can be used to plot any type of data. The .. code-block:: python import matplotlib.pyplot as plt - import plotting + import chartly fig, ax = plt.subplots() @@ -46,7 +46,7 @@ The Generic Plot is a simple plot that can be used to plot any type of data. The # set the arguments args = {"data": data, "ax": ax, "fig": fig, "gen_plot_args": gen_plot_args, "axes_labels": axes_labels} - plot = plotting.Plot(args) + plot = chartly.Plot(args) plot.generic_plot() @@ -60,7 +60,7 @@ The Generic Plot is a simple plot that can be used to plot any type of data. The .. code-block:: python import matplotlib.pyplot as plt - import plotting + import chartly fig, ax = plt.subplots() @@ -75,7 +75,7 @@ The Generic Plot is a simple plot that can be used to plot any type of data. The axes_labels = {"ylabel": "Y", "xlabel": "X", "title": "Generic Plot Example with X & Y"} args = {"data": [x, y], "ax": ax, "fig": fig, "gen_plot_args": gen_plot_args, "axes_labels": axes_labels} - plot = plotting.Plot(args) + plot = chartly.Plot(args) plot.generic_plot() @@ -95,7 +95,7 @@ A histogram plot can be created using the `plot_histogram` method. .. code-block:: python import matplotlib.pyplot as plt - import plotting + import chartly fig, ax = plt.subplots() @@ -109,7 +109,7 @@ A histogram plot can be created using the `plot_histogram` method. axes_labels = {"ylabel": "Frequency", "xlabel": "Value", "title": "Histogram Plot Example"} args = {"data": data, "ax": ax, "fig": fig, "histogram_args": histogram_args, "axes_labels": axes_labels} - plot = plotting.Plot(args) + plot = chartly.Plot(args) plot.plot_histogram() @@ -128,7 +128,7 @@ Contour plots can be created using the `plot_contour` method. The contour plot r .. code-block:: python import matplotlib.pyplot as plt - import plotting + import chartly fig, ax = plt.subplots() @@ -141,7 +141,7 @@ Contour plots can be created using the `plot_contour` method. The contour plot r axes_labels = {"xlabel": "X", "ylabel": "Y", "title": "Contour Plot Example"} args = {"data": [X, Y, Z], "ax": ax, "fig": fig, "axes_labels": axes_labels} - plot = plotting.Plot(args) + plot = chartly.Plot(args) plot.plot_contour() @@ -160,7 +160,7 @@ The normal probability plot is used to determine if a dataset is approximately n .. code-block:: python import matplotlib.pyplot as plt - import plotting + import chartly fig, ax = plt.subplots() @@ -173,7 +173,7 @@ The normal probability plot is used to determine if a dataset is approximately n axes_labels = {"title": "Normal Probability Plot Example"} args = {"data": data, "ax": ax, "fig": fig, "axes_labels": axes_labels, "prob_plot_args": prob_plot_args} - plot = plotting.Plot(args) + plot = chartly.Plot(args) plot.plot_probability_plot() @@ -192,7 +192,7 @@ The CDF of a dataset can be compared to the CDF of a normal distribution using t .. code-block:: python import matplotlib.pyplot as plt - import plotting + import chartly fig, ax = plt.subplots() @@ -206,7 +206,7 @@ The CDF of a dataset can be compared to the CDF of a normal distribution using t axes_labels = {"title": "Normal Cumulative Distribution Function Plot Example"} args = {"data": data, "ax": ax, "fig": fig, "axes_labels": axes_labels} - plot = plotting.Plot(args) + plot = chartly.Plot(args) plot.plot_normal_cdf() diff --git a/docs/source/index.rst b/docs/source/index.rst index 25b9fa0..fb65c4a 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,15 +1,15 @@ -.. plotting documentation master file, created by +.. chartly documentation master file, created by sphinx-quickstart on Wed Oct 16 16:05:42 2024. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Plotting +Chartly ======== Overview -------- -**Plotting** is a simple tool that allows you to create plots using minimal lines of code. +**Chartly** is a simple tool that allows you to create plots using minimal lines of code. @@ -20,7 +20,7 @@ Overview Requirements ------------ -The plotting package requires the following packages: +The chartly package requires the following packages: - `matplotlib` >= 3.9.1 - `numpy` >= 1.26.4 @@ -29,32 +29,32 @@ The plotting package requires the following packages: Installation ------------ -To install the plotting package, run the following command: +To install the chartly package, run the following command: .. code-block:: shell - pip install plotting + pip install chartly Usage ----- -To use the plotting package, you need to import the package and create a plot object. +To use the chartly package, you need to import the package and create a plot object. There are two main methods that you can use to create a plot: - `Plot`: This method plots a single plot at a time on a specified axis. - `Multiplots`: This method plots multiple plots and overlays on a single figure. -Here is an example of how to use the plotting package: +Here is an example of how to use the chartly package: .. code-block:: python import matplotlib.pyplot as plt - import plotting + import chartly fig, ax = plt.subplots() data = np.random.randn(100) args = {"data": data, "ax": ax, "fig": fig} - plot = plotting.Plot(args) + plot = chartly.Plot(args) plot.generic_plot() diff --git a/src/plotting/__init__.py b/src/chartly/__init__.py similarity index 100% rename from src/plotting/__init__.py rename to src/chartly/__init__.py diff --git a/src/plotting/plotting.py b/src/chartly/chartly.py similarity index 100% rename from src/plotting/plotting.py rename to src/chartly/chartly.py diff --git a/src/tests/test_plotting.py b/src/tests/test_chartly.py similarity index 98% rename from src/tests/test_plotting.py rename to src/tests/test_chartly.py index 36dc761..10990e2 100644 --- a/src/tests/test_plotting.py +++ b/src/tests/test_chartly.py @@ -17,7 +17,7 @@ import matplotlib.pyplot as plt import numpy as np -from plotting.plotting import Multiplots, Plot, PlotUtilities +from chartly.chartly import Multiplots, Plot, PlotUtilities class TestPlotting(unittest.TestCase): From 9983d674bd187d77e881fae1a8231077e9664b12 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Thu, 17 Oct 2024 14:21:47 -0400 Subject: [PATCH 06/29] linting --- docs/source/conf.py | 2 -- src/chartly/chartly.py | 16 ++++++++++------ src/tests/test_chartly.py | 6 +++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index bbbaa98..7172429 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,8 +21,6 @@ "sphinx.ext.inheritance_diagram", "sphinx.ext.mathjax", "matplotlib.sphinxext.plot_directive", - "IPython.sphinxext.ipython_directive", - "IPython.sphinxext.ipython_console_highlighting", "autoapi.extension", ] diff --git a/src/chartly/chartly.py b/src/chartly/chartly.py index 4e068d6..35185b8 100644 --- a/src/chartly/chartly.py +++ b/src/chartly/chartly.py @@ -286,7 +286,13 @@ def plot_cdf(self) -> None: x = np.sort(self.data) y = np.cumsum(x) / np.sum(x) - self.ax.plot(x, y, linewidth=1.5, label=self.axes_labels["linelabel"], color=self.cdf_args["color"]) + self.ax.plot( + x, + y, + linewidth=1.5, + label=self.axes_labels["linelabel"], + color=self.cdf_args["color"], + ) for hline in (0.1, 0.5, 0.9): self.ax.axhline(y=hline, color="black", linewidth=1, linestyle="dashed") @@ -408,14 +414,12 @@ def plot_probability_plot(self): (0, mu), slope=sigma, color="black", - linewidth=1, + linewidth=1, label=f"slope={mu:.2f}, y-intercept={sigma:.2f}", ) # Create Axes Labels - self.axes_labels.update( - {"xlabel": "z percentile", "ylabel": "Observations"} - ) + self.axes_labels.update({"xlabel": "z percentile", "ylabel": "Observations"}) # label the axes self.label_axes() @@ -687,7 +691,7 @@ class PlotUtilities: """ def standardize_dataset(self, data: list) -> np.ndarray: - """Standardize a dataset by subtracting the mean and dividing the std + """Standardize a dataset by subtracting the mean and dividing the std of the dataset from each value. :param list data: the data list diff --git a/src/tests/test_chartly.py b/src/tests/test_chartly.py index 10990e2..a3aab84 100644 --- a/src/tests/test_chartly.py +++ b/src/tests/test_chartly.py @@ -106,18 +106,18 @@ def test_contour_data_length(self): # Test that the contour plot throws an error when a user does not send 3 datasets self.plot.data = [self.dataset_one, self.dataset_two] with self.assertRaises(AssertionError): - self.plot.plot_contour_plot() + self.plot.plot_contour() # test that the contour plot does not throw an error when a user sends 3 datasets X, Y = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100)) Z = np.sin(X) * np.cos(Y) self.plot.data = [X, Y, Z] - self.assertIsNone(self.plot.plot_contour_plot()) + self.assertIsNone(self.plot.plot_contour()) # Test that the contour plot throws an error when the data sets are not 2D self.plot.data = [X, Y, Z[0]] with self.assertRaises(AssertionError): - self.plot.plot_contour_plot() + self.plot.plot_contour() def test_default(self): """Test that the default plot is created correctly.""" From 84fcd7941acc06d401c988606ec9fc50ddc579a2 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Thu, 17 Oct 2024 14:24:56 -0400 Subject: [PATCH 07/29] Remove unused CSS and HTML files --- docs/Multiplots.html | 254 -------------- docs/Plot.html | 357 -------------------- docs/{static/js/site.js => __init__.py} | 0 docs/genindex.html | 425 ------------------------ docs/index.html | 241 -------------- docs/py-modindex.html | 168 ---------- docs/search.html | 150 --------- docs/searchindex.js | 1 - docs/static/css/site.css | 60 ---- 9 files changed, 1656 deletions(-) delete mode 100644 docs/Multiplots.html delete mode 100644 docs/Plot.html rename docs/{static/js/site.js => __init__.py} (100%) delete mode 100644 docs/genindex.html delete mode 100644 docs/index.html delete mode 100644 docs/py-modindex.html delete mode 100644 docs/search.html delete mode 100644 docs/searchindex.js delete mode 100644 docs/static/css/site.css diff --git a/docs/Multiplots.html b/docs/Multiplots.html deleted file mode 100644 index 1dcd807..0000000 --- a/docs/Multiplots.html +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - - - - - Chartly.Multiplots Usage Guide — plotting documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - -
    - - -
    -
    -
    -
    - -
    -

    Chartly.Multiplots Usage Guide

    -

    The Multiplots Class allows users to plot multiple plots and overlay them on a single figure. The Multiplots Class requires a dictionary of arguments to be passed to the class:

    -
      -
    • super_title (str): The title of the figure.

    • -
    • super_xlabel (str): The x-axis label of the figure.

    • -
    • super_ylabel (str): The y-axis label of the figure.

    • -
    • share_axes (bool): Whether to share the y-axes across all subplots.

    • -
    -
    -

    Examples

    -
    -

    Overlay Plots

    -

    The overlay method allows users to overlay multiple plots on a single subplot. The overlay method requires a dictionary of arguments to be passed to the method:

    -
      -
    • plot

    • -
    • data (list): A list of data that will be plotted.

    • -
    -
    import chartly
    -
    -# define main figure labels
    -args = {"super_title": "Overlay Example", "super_xlabel": "X", "super_ylabel": "Y", "share_axes": False}
    -
    -multi = chartly.Multiplots(args)
    -
    -# Define Some Data
    -data = np.random.normal(loc=2, scale=1, size=1000)
    -
    -# Create a subplot
    -multi.new_subplot()
    -
    -plots = ["histogram", "density"]
    -
    -for plot in plots:
    -    # set up overlay payload
    -    overlay_payload = {"plot": plot, "data": data, "axes_labels": {}}
    -
    -    # Overlay a histogram
    -    multi.overlay(overlay_payload)
    -
    -# Overlay a density plot
    -overlay_payload = {"plot": "density", "data": data, "axes_labels": {"xlabel": "X", "ylabel": "Y"}}
    -multi.overlay(overlay_payload)
    -
    -multi()
    -
    -
    -OverlayHeteroExample -
    -
    -

    Subplots

    -

    The new_subplot method allows users to create a new subplot on the figure. The new_subplot method requires no arguments to be passed to the method. When a user is finished creating subplots, they can call the Multiplots object to render the figure.

    -
    import chartly
    -
    -# define main figure labels
    -args = {"super_title": "Subplots Example", "super_xlabel": "X", "super_ylabel": "Y", "share_axes": False}
    -
    -multi = chartly.Multiplots(args)
    -
    -# Define Some Data
    -data = np.random.normal(loc=0.8, scale=2, size=50)
    -
    -# Define Plots
    -plots = ["histogram", "density", "prob_plot", "gen_plot", "norm_cdf"]
    -
    -for plot in plots:
    -    # Create a subplot
    -    multi.new_subplot()
    -    axes_labels = {"xlabel": " ", "ylabel": " ", "title": plot}
    -
    -    overlay_payload = {"plot": plot, "data": data, "axes_labels": axes_labels}
    -    multi.overlay(overlay_payload)
    -
    -multi.overlay(overlay_payload)
    -
    -multi()
    -
    -
    -SubplotsExample -
    -
    -
    - - -
    -
    -
    -
    - - - - - -
    -
    -
    - - -
    - - - - - \ No newline at end of file diff --git a/docs/Plot.html b/docs/Plot.html deleted file mode 100644 index 79f80c9..0000000 --- a/docs/Plot.html +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - chartly.Plot Usage Guide — plotting documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - -
    - - -
    -
    -
    -
    - -
    -

    chartly.Plot Usage Guide

    -

    The Plot Class allows users to plot a single plot at a time on a specified axis. The Plot Class requires a dictionary of arguments to be passed to the class. The following keys are required in the dictionary:

    -
      -
    • data: The data that will be plotted.

    • -
    • ax: The axis object that the plot will be plotted on.

    • -
    • fig: The figure object that the plot will be plotted on.

    • -
    -

    There are currently 9 different plot types that can be created using the Plot Class. The Plot Class also allows users to customize these plot by passing additional arguments in the dictionary. The following arguments can be passed to the dictionary:

    -
      -
    • axes_labels: A dictionary containing the x, y, and title labels, and the scale for the plot.

    • -
    • gen_plot_args: A dictionary containing additional arguments for a generic plot, such as color, linestyle, etc.

    • -
    • hist_args: A dictionary containing additional arguments for a histogram plot, such as color, bins, etc.

    • -
    • timeseries_args: A dictionary containing additional arguments for a time series plot, such as color, linestyle, etc.

    • -
    • cdf_args: A dictionary containing additional arguments for a cumulative distribution function plot, such as color, linestyle, etc.

    • -
    • boxplot_args: A dictionary containing additional arguments for a boxplot plot, such as color, notch, etc.

    • -
    • norm_cdf_args: A dictionary containing additional arguments for a normal cumulative distribution function plot, such as color etc.

    • -
    • density_args: A dictionary containing additional arguments for a density plot, such as color, fill, etc.

    • -
    • prob_plot_args: A dictionary containing additional arguments for a probability plot, such as color etc.

    • -
    • contour_args: A dictionary containing additional arguments for a contour plot, such as color, filled, etc.

    • -
    -
    -

    Examples

    -
    -

    Generic Plot

    -

    The Generic Plot is a simple plot that can be used to plot any type of data. The plot is created using the generic_plot method. Users can pass both x and y data or just y data to the plot.

    -
    import matplotlib.pyplot as plt
    -import chartly
    -
    -fig, ax = plt.subplots()
    -
    -# Only y data
    -data = np.random.randn(100)
    -
    -# customize the plot
    -gen_plot_args = {"color": "red", "linestyle": "--"}
    -# label the plot
    -axes_labels = {"ylabel": "Y", "title": "Generic Plot Example"}
    -
    -# set the arguments
    -args = {"data": data, "ax": ax, "fig": fig, "gen_plot_args": gen_plot_args, "axes_labels": axes_labels}
    -plot = chartly.Plot(args)
    -
    -plot.generic_plot()
    -
    -plt.show()
    -
    -
    -GenericPlotOnlyY -
    import matplotlib.pyplot as plt
    -import chartly
    -
    -fig, ax = plt.subplots()
    -
    -# x and y data
    -x = np.linspace(0, 10, 100)
    -y = np.sin(x)
    -
    -# customize the plot
    -gen_plot_args = {"color": "mediumpurple", "linestyle": "--"}
    -
    -# label the plot
    -axes_labels = {"ylabel": "Y", "xlabel": "X", "title": "Generic Plot Example with X & Y"}
    -
    -args = {"data": [x, y], "ax": ax, "fig": fig, "gen_plot_args": gen_plot_args, "axes_labels": axes_labels}
    -plot = chartly.Plot(args)
    -
    -plot.generic_plot()
    -
    -plt.show()
    -
    -
    -GenericPlotXY -
    -
    -

    Histogram

    -

    A histogram plot can be created using the plot_histogram method.

    -
    import matplotlib.pyplot as plt
    -import chartly
    -
    -fig, ax = plt.subplots()
    -
    -data = np.random.randn(1000)
    -
    -# customize the plot
    -
    -histogram_args = {"color": "salmon", "num_bins": 30}
    -
    -# label the plot
    -axes_labels = {"ylabel": "Frequency", "xlabel": "Value", "title": "Histogram Plot Example"}
    -
    -args = {"data": data, "ax": ax, "fig": fig, "histogram_args": histogram_args, "axes_labels": axes_labels}
    -plot = chartly.Plot(args)
    -
    -plot.plot_histogram()
    -
    -plt.show()
    -
    -
    -HistogramExample -
    -
    -

    Contour Plot

    -

    Contour plots can be created using the plot_contour method. The contour plot requires 2D arrays of X, Y and Z data to be passed to the plot.

    -
    import matplotlib.pyplot as plt
    -import chartly
    -
    -fig, ax = plt.subplots()
    -
    -x = np.linspace(-3.0, 3.0, 100)
    -y = np.linspace(-3.0, 3.0, 100)
    -X, Y = np.meshgrid(x, y)
    -Z = np.cos(X/3) * np.sin(Y/3)
    -
    -# label the plot
    -axes_labels = {"xlabel": "X", "ylabel": "Y", "title": "Contour Plot Example"}
    -
    -args = {"data": [X, Y, Z], "ax": ax, "fig": fig, "axes_labels": axes_labels}
    -plot = chartly.Plot(args)
    -
    -plot.plot_contour()
    -
    -plt.show()
    -
    -
    -ContourExample -
    -
    -

    Normal Probability Plot

    -

    The normal probability plot is used to determine if a dataset is approximately normally distributed. A normal probability plot can be created using the plot_probability_plot method. The normal probability plot requires a 1D array of data to be passed to the plot.

    -
    import matplotlib.pyplot as plt
    -import chartly
    -
    -fig, ax = plt.subplots()
    -
    -data = np.random.randn(100)
    -
    -# customize the plot
    -prob_plot_args = {"color": "firebrick"}
    -
    -# label the plot
    -axes_labels = {"title": "Normal Probability Plot Example"}
    -
    -args = {"data": data, "ax": ax, "fig": fig, "axes_labels": axes_labels, "prob_plot_args": prob_plot_args}
    -plot = chartly.Plot(args)
    -
    -plot.plot_probability_plot()
    -
    -plt.show()
    -
    -
    -NormalProbabilityExample -
    -
    -

    Normal Cumulative Distribution Function Plot

    -

    The CDF of a dataset can be compared to the CDF of a normal distribution using the normal CDF plot. The normal CDF plot can be created using the plot_normal_cdf method. Users can pass multiple datasets to the plot.

    -
    import matplotlib.pyplot as plt
    -import chartly
    -
    -fig, ax = plt.subplots()
    -
    -dataset_one = np.random.exponential(scale=1.0, size=500)
    -dataset_two = np.random.normal(loc=20, scale=1, size=500)
    -dataset_three = np.random.gamma(2, 2, 500)
    -data = [dataset_one, dataset_two, dataset_three]
    -
    -
    -# label the plot
    -axes_labels = {"title": "Normal Cumulative Distribution Function Plot Example"}
    -
    -args = {"data": data, "ax": ax, "fig": fig, "axes_labels": axes_labels}
    -plot = chartly.Plot(args)
    -
    -plot.plot_normal_cdf()
    -
    -plt.show()
    -
    -
    -NormalCDFExample -
    -
    -
    - - -
    -
    -
    -
    - - - - - -
    -
    -
    - - -
    - - - - - \ No newline at end of file diff --git a/docs/static/js/site.js b/docs/__init__.py similarity index 100% rename from docs/static/js/site.js rename to docs/__init__.py diff --git a/docs/genindex.html b/docs/genindex.html deleted file mode 100644 index 2f49f2a..0000000 --- a/docs/genindex.html +++ /dev/null @@ -1,425 +0,0 @@ - - - - - - - - - Index — plotting documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - -
    - - -
    -
    -
    -
    - - -

    Index

    - -
    - _ - | A - | B - | C - | D - | E - | F - | G - | H - | L - | M - | N - | O - | P - | S - | T - | U - -
    -

    _

    - - -
    - -

    A

    - - - -
    - -

    B

    - - -
    - -

    C

    - - - -
    - -

    D

    - - - -
    - -

    E

    - - - -
    - -

    F

    - - -
    - -

    G

    - - - -
    - -

    H

    - - -
    - -

    L

    - - -
    - -

    M

    - - - -
    - -

    N

    - - - -
    - -

    O

    - - -
    - -

    P

    - - - -
    - -

    S

    - - - -
    - -

    T

    - - - -
    - -

    U

    - - - -
    - - - -
    -
    -
    -
    - - - - - -
    -
    -
    - - -
    - - - - - \ No newline at end of file diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 02d72f9..0000000 --- a/docs/index.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - - - - - Chartly — plotting documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - -
    - - -
    -
    -
    -
    - -
    -

    Chartly

    -
    -

    Overview

    -

    Chartly is a simple tool that allows you to create plots using minimal lines of code.

    -
    -
    -
    -
    -

    Requirements

    -

    The chartly package requires the following packages:

    -
      -
    • matplotlib >= 3.9.1

    • -
    • numpy >= 1.26.4

    • -
    • scipy >= 1.14.0

    • -
    • seaborn >= 0.11.0

    • -
    -
    -
    -

    Installation

    -

    To install the chartly package, run the following command:

    -
    pip install chartly
    -
    -
    -
    -
    -

    Usage

    -

    To use the chartly package, you need to import the package and create a plot object. -There are two main methods that you can use to create a plot:

    -
      -
    • Plot: This method plots a single plot at a time on a specified axis.

    • -
    • Multiplots: This method plots multiple plots and overlays on a single figure.

    • -
    -

    Here is an example of how to use the chartly package:

    -
    import matplotlib.pyplot as plt
    -import chartly
    -
    -fig, ax = plt.subplots()
    -data = np.random.randn(100)
    -args = {"data": data, "ax": ax, "fig": fig}
    -plot = chartly.Plot(args)
    -
    -plot.generic_plot()
    -
    -plt.show()
    -
    -
    -SimpleExampleResult - - -
    -
    -
    -

    Indices and tables

    - -
    - - -
    -
    -
    -
    - - - - - -
    -
    -
    - - -
    - - - - - \ No newline at end of file diff --git a/docs/py-modindex.html b/docs/py-modindex.html deleted file mode 100644 index 89416e7..0000000 --- a/docs/py-modindex.html +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - - - - Python Module Index — plotting documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - -
    - - -
    -
    -
    -
    - - -

    Python Module Index

    - -
    - c | - t -
    - - - - - - - - - - - - - - - - - - -
     
    - c
    - chartly -
        - chartly.chartly -
     
    - t
    - tests -
        - tests.test_chartly -
    - - -
    -
    -
    -
    - - - - - -
    -
    -
    - - -
    - - - - - \ No newline at end of file diff --git a/docs/search.html b/docs/search.html deleted file mode 100644 index 8115dee..0000000 --- a/docs/search.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - Search — plotting documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - -
    - - -
    -
    -
    -
    - -

    Search

    - - - - -

    - Searching for multiple words only shows matches that contain - all words. -

    - - -
    - - - -
    - - -
    - - -
    -
    -
    -
    - - - - - -
    -
    -
    - - -
    - - - - - \ No newline at end of file diff --git a/docs/searchindex.js b/docs/searchindex.js deleted file mode 100644 index 28a94fa..0000000 --- a/docs/searchindex.js +++ /dev/null @@ -1 +0,0 @@ -Search.setIndex({"alltitles": {"API Reference": [[4, null]], "Attributes": [[2, "attributes"]], "Chartly": [[7, null]], "Chartly.Multiplots Usage Guide": [[0, null]], "Classes": [[2, "classes"], [6, "classes"]], "Contour Plot": [[1, "contour-plot"]], "Examples": [[0, "examples"], [1, "examples"]], "Generic Plot": [[1, "generic-plot"]], "Histogram": [[1, "histogram"]], "Indices and tables": [[7, "indices-and-tables"]], "Installation": [[7, "installation"]], "Module Contents": [[2, "module-contents"], [6, "module-contents"]], "Normal Cumulative Distribution Function Plot": [[1, "normal-cumulative-distribution-function-plot"]], "Normal Probability Plot": [[1, "normal-probability-plot"]], "Overlay Plots": [[0, "overlay-plots"]], "Overview": [[7, "overview"]], "Requirements": [[7, "requirements"]], "Submodules": [[3, "submodules"], [5, "submodules"]], "Subplots": [[0, "subplots"]], "Usage": [[7, "usage"]], "chartly": [[3, null]], "chartly.Plot Usage Guide": [[1, null]], "chartly.chartly": [[2, null]], "tests": [[5, null]], "tests.test_chartly": [[6, null]]}, "docnames": ["Multiplots", "Plot", "autoapi/chartly/chartly/index", "autoapi/chartly/index", "autoapi/index", "autoapi/tests/index", "autoapi/tests/test_chartly/index", "index"], "envversion": {"sphinx": 64, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["Multiplots.rst", "Plot.rst", "autoapi/chartly/chartly/index.rst", "autoapi/chartly/index.rst", "autoapi/index.rst", "autoapi/tests/index.rst", "autoapi/tests/test_chartly/index.rst", "index.rst"], "indexentries": {"__call__() (chartly.chartly.multiplots method)": [[2, "chartly.chartly.Multiplots.__call__", false]], "ax (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.ax", false]], "axes_labels (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.axes_labels", false]], "boxplot_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.boxplot_args", false]], "cdf_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.cdf_args", false]], "chartly": [[3, "module-chartly", false]], "chartly.chartly": [[2, "module-chartly.chartly", false]], "clear_axis() (chartly.chartly.multiplots method)": [[2, "chartly.chartly.Multiplots.clear_axis", false]], "color_list (in module chartly.chartly)": [[2, "chartly.chartly.color_list", false]], "contour_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.contour_args", false]], "current_subplot (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.current_subplot", false]], "data (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.data", false]], "density_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.density_args", false]], "export_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.export_args", false]], "export_plot_to_file() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.export_plot_to_file", false]], "fig (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.fig", false]], "gen_plot_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.gen_plot_args", false]], "generic_plot() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.generic_plot", false]], "graphs (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.graphs", false]], "hist_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.hist_args", false]], "label_axes() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.label_axes", false]], "module": [[2, "module-chartly.chartly", false], [3, "module-chartly", false], [5, "module-tests", false], [6, "module-tests.test_chartly", false]], "multiplots (class in chartly.chartly)": [[2, "chartly.chartly.Multiplots", false]], "new_subplot() (chartly.chartly.multiplots method)": [[2, "chartly.chartly.Multiplots.new_subplot", false]], "norm_cdf_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.norm_cdf_args", false]], "overlay() (chartly.chartly.multiplots method)": [[2, "chartly.chartly.Multiplots.overlay", false]], "plot (class in chartly.chartly)": [[2, "chartly.chartly.Plot", false]], "plot_box_plots() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_box_plots", false]], "plot_cdf() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_cdf", false]], "plot_contour() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_contour", false]], "plot_density() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_density", false]], "plot_histogram() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_histogram", false]], "plot_normal_cdf() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_normal_cdf", false]], "plot_probability_plot() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_probability_plot", false]], "plot_timeseries() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.plot_timeseries", false]], "plotutilities (class in chartly.chartly)": [[2, "chartly.chartly.PlotUtilities", false]], "prob_plot_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.prob_plot_args", false]], "set_defaults() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.set_defaults", false]], "setup() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.setUp", false]], "share_axes (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.share_axes", false]], "standardize_dataset() (chartly.chartly.plotutilities method)": [[2, "chartly.chartly.PlotUtilities.standardize_dataset", false]], "subplot_count (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.subplot_count", false]], "subplots (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.subplots", false]], "super_title (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.super_title", false]], "super_xlabel (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.super_xlabel", false]], "super_ylabel (chartly.chartly.multiplots attribute)": [[2, "chartly.chartly.Multiplots.super_ylabel", false]], "test_contour_data_length() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_contour_data_length", false]], "test_default() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_default", false]], "test_gen_plot_data_length() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_gen_plot_data_length", false]], "test_gen_plot_data_type() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_gen_plot_data_type", false]], "test_multi_clear_axis() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_multi_clear_axis", false]], "test_mutli_subplot_count() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_mutli_subplot_count", false]], "test_standardize_data() (tests.test_chartly.testplotting method)": [[6, "tests.test_chartly.TestPlotting.test_standardize_data", false]], "testplotting (class in tests.test_chartly)": [[6, "tests.test_chartly.TestPlotting", false]], "tests": [[5, "module-tests", false]], "tests.test_chartly": [[6, "module-tests.test_chartly", false]], "tiling() (chartly.chartly.multiplots method)": [[2, "chartly.chartly.Multiplots.tiling", false]], "timeseries_args (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.timeseries_args", false]], "update_defaults() (chartly.chartly.plot method)": [[2, "chartly.chartly.Plot.update_defaults", false]], "util (chartly.chartly.plot attribute)": [[2, "chartly.chartly.Plot.util", false]]}, "objects": {"": [[3, 0, 0, "-", "chartly"], [5, 0, 0, "-", "tests"]], "chartly": [[2, 0, 0, "-", "chartly"]], "chartly.chartly": [[2, 1, 1, "", "Multiplots"], [2, 1, 1, "", "Plot"], [2, 1, 1, "", "PlotUtilities"], [2, 4, 1, "", "color_list"]], "chartly.chartly.Multiplots": [[2, 2, 1, "", "__call__"], [2, 2, 1, "", "clear_axis"], [2, 3, 1, "", "current_subplot"], [2, 3, 1, "", "graphs"], [2, 2, 1, "", "new_subplot"], [2, 2, 1, "", "overlay"], [2, 3, 1, "", "share_axes"], [2, 3, 1, "", "subplot_count"], [2, 3, 1, "", "subplots"], [2, 3, 1, "", "super_title"], [2, 3, 1, "", "super_xlabel"], [2, 3, 1, "", "super_ylabel"], [2, 2, 1, "", "tiling"]], "chartly.chartly.Plot": [[2, 3, 1, "", "ax"], [2, 3, 1, "", "axes_labels"], [2, 3, 1, "", "boxplot_args"], [2, 3, 1, "", "cdf_args"], [2, 3, 1, "", "contour_args"], [2, 3, 1, "", "data"], [2, 3, 1, "", "density_args"], [2, 3, 1, "", "export_args"], [2, 2, 1, "", "export_plot_to_file"], [2, 3, 1, "", "fig"], [2, 3, 1, "", "gen_plot_args"], [2, 2, 1, "", "generic_plot"], [2, 3, 1, "", "hist_args"], [2, 2, 1, "", "label_axes"], [2, 3, 1, "", "norm_cdf_args"], [2, 2, 1, "", "plot_box_plots"], [2, 2, 1, "", "plot_cdf"], [2, 2, 1, "", "plot_contour"], [2, 2, 1, "", "plot_density"], [2, 2, 1, "", "plot_histogram"], [2, 2, 1, "", "plot_normal_cdf"], [2, 2, 1, "", "plot_probability_plot"], [2, 2, 1, "", "plot_timeseries"], [2, 3, 1, "", "prob_plot_args"], [2, 2, 1, "", "set_defaults"], [2, 3, 1, "", "timeseries_args"], [2, 2, 1, "", "update_defaults"], [2, 3, 1, "", "util"]], "chartly.chartly.PlotUtilities": [[2, 2, 1, "", "standardize_dataset"]], "tests": [[6, 0, 0, "-", "test_chartly"]], "tests.test_chartly": [[6, 1, 1, "", "TestPlotting"]], "tests.test_chartly.TestPlotting": [[6, 2, 1, "", "setUp"], [6, 2, 1, "", "test_contour_data_length"], [6, 2, 1, "", "test_default"], [6, 2, 1, "", "test_gen_plot_data_length"], [6, 2, 1, "", "test_gen_plot_data_type"], [6, 2, 1, "", "test_multi_clear_axis"], [6, 2, 1, "", "test_mutli_subplot_count"], [6, 2, 1, "", "test_standardize_data"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "attribute", "Python attribute"], "4": ["py", "data", "Python data"]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:attribute", "4": "py:data"}, "terms": {"": 2, "0": [0, 1, 2, 7], "1": [0, 1, 2, 4, 6, 7], "10": [1, 2], "100": [1, 7], "1000": [0, 1], "11": 7, "14": 7, "1d": [1, 6], "2": [0, 1, 2, 6], "20": [1, 2], "26": 7, "2d": [1, 2, 6], "3": [1, 2, 6, 7], "30": 1, "4": [2, 7], "5": 2, "50": 0, "500": 1, "8": 0, "9": [1, 2, 7], "A": [0, 1, 2, 6], "The": [0, 1, 2, 7], "There": [1, 2, 7], "To": 7, "_": 2, "__call__": 2, "across": 0, "add": [], "addit": 1, "against": 2, "all": [0, 2], "allow": [0, 1, 7], "also": 1, "an": [2, 6, 7], "ang": [2, 6], "ani": 1, "api": 7, "apopo": [2, 6], "approxim": 1, "ar": [1, 2, 6, 7], "arg": [0, 1, 2, 7], "argument": [0, 1], "arrai": [1, 2], "assist": [2, 6], "author": [2, 6], "auto": 4, "autoapi": 4, "auxillari": 2, "ax": [0, 1, 2, 7], "axes_label": [0, 1, 2], "axi": [0, 1, 2, 6, 7], "azenda": [2, 6], "base": [2, 6], "bin": [1, 2], "black": 2, "bool": 0, "both": [1, 2, 6], "box": 2, "boxplot": [1, 2], "boxplot_arg": [1, 2], "build": 2, "c": [2, 6], "calcul": 2, "call": 0, "can": [0, 1, 6, 7], "cdf": [1, 2], "cdf_arg": [1, 2], "chartli": 4, "cheikh": [2, 6], "class": [0, 1], "clear": 6, "clear_axi": 2, "cmbengu": [2, 6], "co": 1, "code": 7, "color": [1, 2], "color_list": 2, "column": 2, "com": [2, 6], "command": 7, "compani": [2, 6], "compar": 1, "consult": [2, 6], "contain": [1, 2, 4], "content": [], "contour": [2, 6], "contour_arg": [1, 2], "correctli": 6, "creat": [0, 1, 2, 4, 6, 7], "current": [1, 2], "current_subplot": 2, "custom": [1, 2], "data": [0, 1, 2, 6, 7], "dataset": [1, 2], "dataset_on": 1, "dataset_thre": 1, "dataset_two": 1, "decis": [2, 6], "default": [2, 6], "defin": 0, "densiti": [0, 1, 2], "density_arg": [1, 2], "detail": [], "determin": 1, "develop": [2, 6], "dict": 2, "dictionari": [0, 1, 2], "differ": 1, "displai": 2, "distribut": 2, "divid": 2, "document": 4, "e": [2, 6], "each": 2, "ec": [2, 6], "eci": [2, 6], "elizabeth": [2, 6], "ep": 2, "error": 6, "estim": 2, "etc": 1, "exampl": [2, 7], "exponenti": 1, "export": 2, "export_arg": 2, "export_plot_to_fil": 2, "fals": [0, 2], "field": 2, "fig": [1, 2, 7], "figur": [0, 1, 2, 7], "file": 2, "fill": [1, 2], "finish": 0, "firebrick": 1, "fname": 2, "follow": [1, 2, 7], "font": 2, "format": 2, "frequenc": 1, "from": 2, "fsize": 2, "function": 2, "gamma": 1, "gen_plot": 0, "gen_plot_arg": [1, 2], "gener": [2, 4, 6], "generic_plot": [1, 2, 7], "graph": 2, "guid": 7, "handl": 6, "here": 7, "hist_arg": [1, 2], "histogram": [0, 2], "histogram_arg": 1, "hold": 2, "how": 7, "i": [0, 1, 2, 6, 7], "import": [0, 1, 7], "inc": [2, 6], "index": 7, "indi": [2, 6], "inlin": 2, "input": 2, "int": 2, "intern": [2, 6], "intl": [2, 6], "its": 2, "just": 1, "k": 2, "kei": [1, 2], "kernel": 2, "label": [0, 1, 2], "label_ax": 2, "legend": 2, "length": 6, "lightpink": 2, "line": [2, 7], "linear": 2, "linelabel": 2, "linestyl": [1, 2], "linspac": 1, "list": [0, 2, 6], "loc": [0, 1], "lucia": [2, 6], "m": [2, 6], "main": [0, 2, 7], "mari": [2, 6], "master": 2, "matplotlib": [1, 7], "mbengu": [2, 6], "mean": 2, "mediumpurpl": 1, "mediumvioletr": 2, "meshgrid": 1, "method": [0, 1, 2, 7], "methodnam": 6, "minim": 7, "modul": 7, "multi": 0, "multipl": [0, 1, 2, 6, 7], "multiplot": [2, 6, 7], "must": 2, "name": 2, "navi": 2, "ndarrai": 2, "need": 7, "new": [0, 2], "new_subplot": [0, 2], "new_valu": 2, "none": 2, "norm_cdf": 0, "norm_cdf_arg": [1, 2], "normal": [0, 2], "notch": 1, "note": 2, "np": [0, 1, 7], "num": 2, "num_bin": [1, 2], "number": 2, "numpi": [2, 7], "o": [2, 6], "object": [0, 1, 6, 7], "onli": 1, "onto": 2, "option": 2, "orang": 2, "organ": [2, 6], "other": 2, "oumar": [2, 6], "outlier": 2, "overlai": [2, 7], "overlay_arg": 2, "overlay_payload": 0, "packag": 7, "page": [4, 7], "paramet": 2, "pass": [0, 1], "payload": 0, "pip": 7, "pleas": 2, "plot": [2, 6, 7], "plot_box_plot": 2, "plot_cdf": 2, "plot_contour": [1, 2], "plot_contour_plot": [], "plot_dens": 2, "plot_histogram": [1, 2], "plot_normal_cdf": [1, 2], "plot_probability_plot": [1, 2], "plot_timeseri": 2, "plottingutil": 2, "plotutil": 2, "plt": [1, 2, 7], "plum": 2, "popo": [2, 6], "privat": [2, 6], "prob_plot": 0, "prob_plot_arg": [1, 2], "probabl": 2, "pyplot": [1, 7], "ran": 2, "randn": [1, 7], "random": [0, 1, 7], "rang": 2, "red": [1, 2], "refer": 7, "render": 0, "requir": [0, 1, 2], "research": [2, 6], "reset": 2, "restructuredtext": [], "result": 2, "return": 2, "row": 2, "run": 7, "runtest": 6, "salmon": 1, "same": 2, "scale": [0, 1, 2], "scientist": [2, 6], "scipi": 7, "seaborn": 7, "search": 7, "sector": [2, 6], "see": [], "seri": 1, "set": [0, 1, 2, 6], "set_default": 2, "setup": 6, "share": [0, 2], "share_ax": [0, 2], "show": [1, 2, 7], "show_legend": 2, "showflier": 2, "simpl": [1, 7], "sin": 1, "singl": [0, 1, 7], "size": [0, 1, 2], "skyblu": 2, "slateblu": 2, "solid": 2, "some": 0, "special": [2, 6], "specifi": [1, 7], "sphinx": 4, "st": [2, 6], "standard": [2, 6], "standardize_dataset": 2, "std": 2, "str": [0, 2], "style": 2, "subplot": [1, 2, 6, 7], "subplot_count": 2, "subtract": 2, "super_titl": [0, 2], "super_xlabel": [0, 2], "super_ylabel": [0, 2], "support": [2, 6], "syntax": [], "system": [2, 6], "test": [2, 4, 7], "test_chartli": [4, 5], "test_contour_data_length": 6, "test_default": 6, "test_gen_plot_data_length": 6, "test_gen_plot_data_typ": 6, "test_multi_clear_axi": 6, "test_mutli_subplot_count": 6, "test_plot": [], "test_standardize_data": 6, "testcas": 6, "testplot": 6, "thei": 0, "them": 0, "thi": [2, 4, 7], "throw": 6, "tile": 2, "time": [1, 7], "timeseri": 2, "timeseries_arg": [1, 2], "titl": [0, 1, 2], "tool": 7, "tracker": 2, "true": 2, "tupl": 2, "two": 7, "type": [1, 2], "unequ": 6, "unittest": 6, "up": [0, 6], "updat": 2, "update_default": 2, "us": [1, 2, 6, 7], "usag": 2, "user": [0, 1], "util": 2, "valu": [1, 2], "variou": 2, "west": [2, 6], "when": 0, "whether": [0, 2], "x": [0, 1, 2], "xlabel": [0, 1, 2], "y": [0, 1, 2], "ylabel": [0, 1, 2], "you": 7, "your": [], "z": 1}, "titles": ["Chartly.Multiplots Usage Guide", "chartly.Plot Usage Guide", "chartly.chartly", "chartly", "API Reference", "tests", "tests.test_chartly", "Chartly"], "titleterms": {"api": 4, "attribut": 2, "chartli": [0, 1, 2, 3, 7], "class": [2, 6], "content": [2, 6], "contour": 1, "cumul": 1, "distribut": 1, "document": [], "exampl": [0, 1], "function": 1, "gener": 1, "guid": [0, 1], "histogram": 1, "indic": 7, "instal": 7, "modul": [2, 6], "multiplot": 0, "normal": 1, "overlai": 0, "overview": 7, "plot": [0, 1], "probabl": 1, "refer": 4, "requir": 7, "submodul": [3, 5], "subplot": 0, "tabl": 7, "test": [5, 6], "test_chartli": 6, "test_plot": [], "usag": [0, 1, 7]}}) \ No newline at end of file diff --git a/docs/static/css/site.css b/docs/static/css/site.css deleted file mode 100644 index 0644f7a..0000000 --- a/docs/static/css/site.css +++ /dev/null @@ -1,60 +0,0 @@ -/* General Styles */ -body { - font-family: sans-serif; - margin: 0; - display: flex; - flex-direction: column; - min-height: 100vh; -} - -.container { - max-width: 960px; - margin: 0 auto; - padding: 20px; -} - -/* Header */ -header { - background-color: #f0f0f0; - padding: 20px 0; -} - -.logo { - text-decoration: none; - color: #333; - font-size: 24px; -} - -/* Hero Section */ -.hero { - text-align: center; - padding: 100px 0; -} - -.hero h1 { - font-size: 48px; - margin-bottom: 20px; -} - -.subscribe input[type="email"] { - padding: 10px; - border: 1px solid #ccc; - margin-right: 10px; -} - -.subscribe button { - background-color: #007bff; - color: white; - padding: 10px 20px; - border: none; - cursor: pointer; -} - -/* Footer */ -footer { - background-color: #333; - color: white; - text-align: center; - padding: 20px 0; - margin-top: auto; /* Push to bottom */ -} From e74ac604445bd8d4235402dfa08417b3cf3d5143 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Thu, 17 Oct 2024 14:27:55 -0400 Subject: [PATCH 08/29] WIP --- .github/workflows/docs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9f5c4ff..831cbd5 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,4 +1,5 @@ -name: Sphinx-docs +--- +name: Docs on: pull_request: From e4b2254123f134943547e2ff6d7978c03569e64e Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Thu, 17 Oct 2024 14:33:24 -0400 Subject: [PATCH 09/29] update linting --- docs/source/conf.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 7172429..8a214cb 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -6,9 +6,9 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -project = 'plotting' -copyright = '2024, Elizabeth Consulting International Inc' -author = 'Elizabeth Consulting International Inc' +project = "plotting" +copyright = "2024, Elizabeth Consulting International Inc" +author = "Elizabeth Consulting International Inc" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration @@ -24,11 +24,11 @@ "autoapi.extension", ] -templates_path = ['_templates'] +templates_path = ["_templates"] exclude_patterns = [] -autoapi_dirs = ['../../src'] +autoapi_dirs = ["../../src"] # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output -html_theme = 'cloud' -html_static_path = ['_static'] +html_theme = "cloud" +html_static_path = ["_static"] From 4d3122022f665f50c46d14135c5a38af2a3ee410 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Thu, 17 Oct 2024 14:48:10 -0400 Subject: [PATCH 10/29] update workflows --- .github/workflows/cd.yml | 64 ++++++++++++++++++++---------- .github/workflows/ci.yml | 46 ++++++++++++++++++--- .github/workflows/guard.yml | 49 +++++++++++++++-------- .github/workflows/release-log.yml | 14 ------- .github/workflows/super-linter.yml | 51 ++++++++++++++++-------- 5 files changed, 151 insertions(+), 73 deletions(-) delete mode 100644 .github/workflows/release-log.yml diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index d86b7be..647a4d8 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,28 +1,50 @@ --- -name: Continuous-Deployment + name: Continuous-Deployment + permissions: + contents: write + id-token: write + packages: write + actions: write + checks: write + concurrency: + group: production + cancel-in-progress: true + on: + push: + branches: [main] -env: - TMPDIR: "/tmp/deployment" + jobs: + deployment: + runs-on: ubuntu-latest + environment: production + steps: + - name: Check out the code + uses: actions/checkout@v4 -permissions: - contents: write - checks: write + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' -concurrency: - group: production - cancel-in-progress: true + - name: Install dependencies + run: | + echo "📦 Installing Python dependencies." + python -m pip install --upgrade pip + if [ -f requirements/production.txt ]; then + pip install -r requirements/production.txt; + fi -on: - push: - branches: [main] + - name: Upgrade build tools + run: python -m pip install --upgrade build -jobs: - deployment-tasks: - uses: ec-intl/workflow-templates/.github/workflows/cd_template.yml@v1 - with: - other-files: "notebooks,src,environments" - secrets: inherit + - name: Build the package + run: python -m build - release-tasks: - uses: ec-intl/workflow-templates/.github/workflows/make-release_template.yml@v1 - secrets: inherit + - name: Upload to PyPI + if: ${{ vars.DEPLOY_TO_PYPI == 'yes' }} + env: + TWINE_PASSWORD: ${{ secrets.PYPI_KEY }} + run: python -m twine upload dist/* + + - name: Done + run: echo "🎉 Deployment complete!" \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 983a9c1..eab99d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,3 @@ ---- name: Continuous-Integration on: @@ -13,9 +12,46 @@ permissions: contents: read checks: read +env: + EVENT: ${{ github.event_name }} + BRANCH: ${{ github.ref }} + jobs: ci-tasks: - uses: ec-intl/workflow-templates/.github/workflows/ci_template.yml@v1 - with: - runner-name: 'za-3' - secrets: inherit + runs-on: ubuntu-latest + environment: staging + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run tests + run: | + pytest -v --cov ./src/tests/ + + - name: Build and upload to Test PyPI + if: ${{ vars.STAGE_TO_PYPI == 'yes' && contains(env.BRANCH, 'staging') && env.EVENT == 'merge_group' }} + env: + TWINE_PASSWORD: ${{ secrets.TEST_PYPI_KEY }} + run: | + echo "📦 Installing Python dependencies." + python -m pip install --upgrade pip + if [ -f requirements/staging.txt ]; then + pip install -r requirements/staging.txt; + fi + python -m pip install --upgrade build + python -m build + python -m twine upload --repository testpypi dist/* + + - name: Done + run: echo "🎉 Deployment complete!" \ No newline at end of file diff --git a/.github/workflows/guard.yml b/.github/workflows/guard.yml index b6b514f..1ba723f 100644 --- a/.github/workflows/guard.yml +++ b/.github/workflows/guard.yml @@ -1,18 +1,33 @@ --- -name: Guard Main Branch - -on: - pull_request: - types: - - auto_merge_enabled - branches: - - main - merge_group: - -permissions: - contents: read - -jobs: - guardian-jobs: - uses: ec-intl/workflow-templates/.github/workflows/guard_template.yml@v1 - secrets: inherit + name: Guard Main Branch + on: + pull_request: + types: + - auto_merge_enabled + branches: + - main + merge_group: + permissions: + contents: read + jobs: + branch-check: + runs-on: ubuntu-latest + if: ${{ !contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]') }} + steps: + - name: Preamble + run: | + echo "🎉 A $EVENT triggered a ${{ runner.os }} job." + echo "🔎 The branch is $BRANCH in $REPO." + - name: Check out repository code + uses: actions/checkout@v4 + - name: Guard the main branch + if: ${{ env.HEAD != 'staging' && env.HEAD != ''}} + run: | + echo "🚫 The main branch is protected." + echo "🚫 Pull requests to main must come from staging branch." + exit 1 + - name: Notify + run: | + echo "📣 The job has been completed." + echo "🔔 The main branch is protected." + echo "🍏 This job's status is ${{ job.status }}." diff --git a/.github/workflows/release-log.yml b/.github/workflows/release-log.yml deleted file mode 100644 index e54dcc4..0000000 --- a/.github/workflows/release-log.yml +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: Release Log - -on: - pull_request: - types: [closed] - -permissions: - contents: write - -jobs: - logging-tasks: - uses: ec-intl/workflow-templates/.github/workflows/release-log_template.yml@v1 - secrets: inherit diff --git a/.github/workflows/super-linter.yml b/.github/workflows/super-linter.yml index ef5f44d..b4814f1 100644 --- a/.github/workflows/super-linter.yml +++ b/.github/workflows/super-linter.yml @@ -1,17 +1,36 @@ +# This workflow executes several linters on changed +# files based on languages used in your code base whenever +# you push a code or open a pull request. +# +# You can adjust the behavior by modifying this file. +# For more information, see: +# https://github.com/github/super-linter --- -name: Lint Code Base - -on: - pull_request: - types: [auto_merge_enabled] - branches: [staging] - merge_group: - -permissions: - contents: read - checks: read - -jobs: - linting-jobs: - uses: ec-intl/workflow-templates/.github/workflows/super-linter_template.yml@v1 - secrets: inherit + name: Lint Codebase + + on: + pull_request: + types: [auto_merge_enabled] + branches: [staging] + merge_group: + + jobs: + run-lint: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + # Full git history is needed to get a proper + # list of changed files within `super-linter` + fetch-depth: 0 + + - name: Lint Code Base + uses: github/super-linter@v5 + env: + VALIDATE_ALL_CODEBASE: true + DEFAULT_BRANCH: main + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VALIDATE_DOCKERFILE_HADOLINT: false + VALIDATE_JSCPD: false + VALIDATE_GITHUB_ACTIONS: false From 90de96cd752af02dbb07b4b5fff8c0f55337d8f0 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Thu, 17 Oct 2024 14:58:28 -0400 Subject: [PATCH 11/29] Update exclude_patterns in conf.py --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 8a214cb..031d6cb 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -25,7 +25,7 @@ ] templates_path = ["_templates"] -exclude_patterns = [] +exclude_patterns: list[str] = [] autoapi_dirs = ["../../src"] # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output From 169acc085b17ad0e9a3085c3d7ea8275d59ded96 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Thu, 17 Oct 2024 16:14:37 -0400 Subject: [PATCH 12/29] adds manifest.in file --- .github/workflows/cd.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/docs.yml | 2 +- MANIFEST.in | 1 + setup.py | 12 ++++++------ 5 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 MANIFEST.in diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 647a4d8..a931fc9 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -47,4 +47,4 @@ run: python -m twine upload dist/* - name: Done - run: echo "🎉 Deployment complete!" \ No newline at end of file + run: echo "🎉 Deployment complete!" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eab99d7..fa2893f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,4 +54,4 @@ jobs: python -m twine upload --repository testpypi dist/* - name: Done - run: echo "🎉 Deployment complete!" \ No newline at end of file + run: echo "🎉 Deployment complete!" diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 831cbd5..66113ca 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -76,4 +76,4 @@ jobs: - name: Finish run: | echo "📣 The job has been completed." - echo "🍏 This job's status is ${{ job.status }}." \ No newline at end of file + echo "🍏 This job's status is ${{ job.status }}." diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..ceeea23 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include VERSION diff --git a/setup.py b/setup.py index cd442eb..0276d1f 100644 --- a/setup.py +++ b/setup.py @@ -5,19 +5,19 @@ version = version_file.read().strip() setup( - name="plotting", + name="chartly", version=version, author="Elizabeth Consulting International Inc.", author_email="info@ec-intl.com", - description=("A Python package for plotting multiple plots."), + description=("A Python package for chartly multiple plots."), long_description=open("README.md", encoding="utf-8").read(), long_description_content_type="text/markdown", - url="https://github.com/ec-intl/plotting", + url="https://github.com/ec-intl/chartly", project_urls={ - "Homepage": "https://github.com/ec-intl/plotting", - "Issues": "https://github.com/ec-intl/plotting/issues", + "Homepage": "https://github.com/ec-intl/chartly", + "Issues": "https://github.com/ec-intl/chartly/issues", }, - packages=["plotting"], + packages=["chartly"], package_dir={"": "src"}, license="Apache License 2.0", classifiers=[ From 4e7eb60c2cbfad341784dd0893ab9c104b0ff908 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Mon, 21 Oct 2024 10:49:19 -0400 Subject: [PATCH 13/29] Adds CustomizePlot Class --- src/chartly/chartly.py | 337 +++++++++++++++++++---------------------- 1 file changed, 156 insertions(+), 181 deletions(-) diff --git a/src/chartly/chartly.py b/src/chartly/chartly.py index 35185b8..a901d55 100644 --- a/src/chartly/chartly.py +++ b/src/chartly/chartly.py @@ -42,16 +42,14 @@ class Plot: Optional Keys - axes_labels: the axes labels - - boxplot_args: the optional customizations for a boxplot - - cdf_args: the optional customizations for a cdf plot - - hist_args: the optional customizations for a histogram - - timeseries_args: the optional customizations for a timeseries plot - - prob_plot_args: the optional customizations for a probability plot - - gen_plot_args: the optional customizations for a generic plot - - norm_cdf_args: the optional customizations for a normal cdf plot - - contour_args: the optional customizations for a contour plot - - density_args: the optional customizations for a density plot - - export_args: the optional customizations for exporting the plot to a file + - boxplot: the optional customizations for a boxplot + - cdf: the optional customizations for a cdf plot + - histogram: the optional customizations for a histogram + - probability_plot: the optional customizations for a probability plot + - line_plot: the optional customizations for a generic plot + - normal_cdf: the optional customizations for a normal cdf plot + - contour: the optional customizations for a contour plot + - density: the optional customizations for a density plot **Examples** @@ -65,118 +63,70 @@ class Plot: def __init__(self, args): """Initialize the Plot Class""" - # Extract the data, axis, and figure + # Turn off interactive mode + plt.ioff() + + self.args = args + + # initialize the figure and axis + self._fig, self._ax = plt.subplots() + + self.display = args.get("display", True) + + # Extract the data self.data = args.get("data") - self.ax = args.get("ax") - self.fig = args.get("fig") + + # Set the filename and format + self._fname = "plot" + self._format = "eps" # Initialize the Plot Utilities self.util = PlotUtilities() - # Turn off interactive mode - plt.ioff() - # Extract axis labels self.axes_labels = { **self.set_defaults("axes_labels"), **args.get("axes_labels", {}), } - # Extract Export Args - self.export_args = { - **self.set_defaults("export"), - **args.get("export_args", {}), - } + # Set Customizations + self.customs = CustomizePlot(self.args) - # Extract Generic Plot Args - self.gen_plot_args = { - **self.set_defaults("gen_plot"), - **args.get("gen_plot_args", {}), - } + @property + def fig(self): + """Get the figure.""" + return self._fig - # Extract boxplot Args - self.boxplot_args = { - **self.set_defaults("boxplots"), - **args.get("boxplot_args", {}), - } + @fig.setter + def fig(self, value): + self._fig = value - # Extract CDF Args - self.cdf_args = {**self.set_defaults("cdf"), **args.get("cdf_args", {})} + @property + def ax(self): + """Get the figure.""" + return self._ax - # Extract Density Plot Args - self.density_args = { - **self.set_defaults("density"), - **args.get("density_args", {}), - } - args.get("density_args", self.set_defaults("density")) - - # Extract Histogram Args - self.hist_args = { - **self.set_defaults("histogram"), - **args.get("histogram_args", {}), - } - - # Extract Timeseries Args - self.timeseries_args = { - **self.set_defaults("timeseries"), - **args.get("timeseries_args", {}), - } - # Extract Probability Plot Args - self.prob_plot_args = { - **self.set_defaults("prob_plot"), - **args.get("prob_plot_args", {}), - } + @ax.setter + def ax(self, value): + self._ax = value - # Extract Normal CDF Args - self.norm_cdf_args = { - **self.set_defaults("norm_cdf"), - **args.get("norm_cdf_args", {}), - } - - # Extract Contour Plot Args - self.contour_args = { - **self.set_defaults("contour"), - **args.get("contour_args", {}), - } + @property + def fname(self): + """Get the figure.""" + return self._fname - def set_defaults(self, field): - """Set Plot Class optional fields defaults + @fname.setter + def fname(self, value): + self._fname = value - :param str field: the field name - :return: the plot default - :rtype: dict - """ - def_axes_labels = { - "title": " ", - "xlabel": " ", - "ylabel": " ", - "linelabel": " ", - "boxlabel": " ", - "show_legend": True, - "scale": "linear", - "base": 10, - } - def_contour = { - "filled": False, - "colors": "k", - "inline": True, - "fsize": 9, - } + @property + def format(self): + """Get the figure.""" + return self._format - defaults = { - "axes_labels": def_axes_labels, - "export": {"format": "eps", "fname": "plot.eps"}, - "cdf": {"color": "dogerblue"}, - "density": {"color": "red", "fill": False, "label": " "}, - "histogram": {"num_bins": 20, "color": "plum", "ran": None}, - "timeseries": {"linestyle": "solid", "color": "black"}, - "boxplots": {"showfliers": True}, - "prob_plot": {"color": "orangered"}, - "gen_plot": {"color": "navy", "linestyle": "solid"}, - "norm_cdf": {}, - "contour": def_contour, - } - return defaults[field] + @format.setter + def format(self, value): + self._format = value def update_defaults(self, field, new_values): """Update the optional fields default values. @@ -185,22 +135,8 @@ def update_defaults(self, field, new_values): :param dict values: the updated optional fields dict :rtype: None """ - - defaults = { - "axes_labels": self.axes_labels, - "export": self.export_args, - "cdf": self.cdf_args, - "density": self.density_args, - "histogram": self.hist_args, - "timeseries": self.timeseries_args, - "boxplots": self.boxplot_args, - "prob_plot": self.prob_plot_args, - "gen_plot": self.gen_plot_args, - "norm_cdf": self.norm_cdf_args, - "contour": self.contour_args, - } - - defaults[field].update(new_values) + self.args[field].update(new_values) + self.customs = CustomizePlot(self.args) def label_axes(self): """Label the axes of a graph. This method uses the axes_labels dict. @@ -229,26 +165,23 @@ def label_axes(self): if self.axes_labels["show_legend"]: self.ax.legend() - def export_plot_to_file(self): - """Export the current figure to a file. This method uses the export_args dict. - There are no required keys for this dict. + if self.display: + plt.show() - Optional Keys - - format: the format of the exported file, default is "eps" - - fname: the name of the exported file, default is "plot.eps" - """ + def save(self): + """Export the current figure to a file.""" self.fig.savefig( - self.export_args["fname"], - format=self.export_args["format"], + f"{self.fname}.{self.format}", + format=self.format, bbox_inches="tight", pad_inches=1, orientation="portrait", ) - def generic_plot(self) -> None: + def line_plot(self) -> None: """Plot a generic plot using y and/or x. This method uses the - gen_plot_args dict. There are no required keys for this dict. + line_plot_args dict. There are no required keys for this dict. Optional Keys - color: the color of the line, default is "navy" @@ -263,22 +196,22 @@ def generic_plot(self) -> None: self.ax.plot( self.data[0], self.data[1], - color=self.gen_plot_args["color"], + color=self.customs.line_plot["color"], linewidth=1.5, - linestyle=self.gen_plot_args["linestyle"], + linestyle=self.customs.line_plot["linestyle"], label=self.axes_labels["linelabel"], ) else: self.ax.plot( self.data, - color=self.gen_plot_args["color"], + color=self.customs.line_plot["color"], linewidth=1.5, - linestyle=self.gen_plot_args["linestyle"], + linestyle=self.customs.line_plot["linestyle"], label=self.axes_labels["linelabel"], ) self.label_axes() - def plot_cdf(self) -> None: + def cdf(self) -> None: """Plot CDF of a dataset. This method uses the cdf_args dict. There are no required keys for this dict. """ @@ -291,7 +224,7 @@ def plot_cdf(self) -> None: y, linewidth=1.5, label=self.axes_labels["linelabel"], - color=self.cdf_args["color"], + color=self.customs.cdf["color"], ) for hline in (0.1, 0.5, 0.9): @@ -299,7 +232,7 @@ def plot_cdf(self) -> None: self.label_axes() - def plot_density(self) -> None: + def density(self) -> None: """Plot the density plot of a dataset using kernel density estimation. This method uses the density_args dict. There are no required keys for this dict. @@ -311,14 +244,14 @@ def plot_density(self) -> None: # Plot a density plot sns.kdeplot( self.data, - color=self.density_args["color"], + color=self.customs.density["color"], ax=self.ax, - fill=self.density_args["fill"], - label=self.density_args["label"], + fill=self.customs.density["fill"], + label=self.customs.density["label"], ) self.label_axes() - def plot_box_plots(self) -> None: + def boxplot(self) -> None: """Plot Box Plots. This method uses the boxplot_args dict. There are no required keys for this dict. @@ -334,12 +267,12 @@ def plot_box_plots(self) -> None: whiskerprops=dict(color="blue"), capprops=dict(color="red"), tick_labels=self.axes_labels["boxlabel"], - showfliers=self.boxplot_args["showfliers"], + showfliers=self.customs.boxplot["showfliers"], ) self.axes_labels["show_legend"] = False self.label_axes() - def plot_histogram(self): + def histogram(self): """Plot a histogram. This method uses the hist_args dict. There are no required keys for this dict. @@ -350,33 +283,16 @@ def plot_histogram(self): """ self.ax.hist( self.data, - bins=self.hist_args["num_bins"], - color=self.hist_args["color"], + bins=self.customs.histogram["num_bins"], + color=self.customs.histogram["color"], edgecolor="black", weights=np.ones_like(self.data) / len(self.data), - range=self.hist_args["ran"], + range=self.customs.histogram["ran"], ) self.axes_labels["show_legend"] = False self.label_axes() - def plot_timeseries(self): - """Plot a timeseries. This method uses the timeseries_args dict. There are no - required keys for this dict. - - Optional Keys: - - linestyle: the style of the line, default is "solid" - - color: the color of the line, default is "black" - """ - self.ax.plot( - self.data, - linewidth=2, - linestyle=self.timeseries_args["linestyle"], - label=self.axes_labels["linelabel"], - color=self.timeseries_args["color"], - ) - self.label_axes() - - def plot_probability_plot(self): + def probability_plot(self): """Plot a probability plot. This method uses the prob_plot_args dict. There are no required keys for this dict. @@ -404,7 +320,7 @@ def plot_probability_plot(self): self.ax.scatter( z, sample_data, - color=self.prob_plot_args["color"], + color=self.customs.probability_plot["color"], s=30, marker="x", ) @@ -424,7 +340,7 @@ def plot_probability_plot(self): # label the axes self.label_axes() - def plot_normal_cdf(self): + def normal_cdf(self): """Plot a standard normal distribution CDF against the CDF of other datasets. This method uses the norm_cdf_args dict. There are no required keys for this dict. @@ -469,7 +385,7 @@ def plot_normal_cdf(self): # label the axes self.label_axes() - def plot_contour(self): + def contour(self): """Plot a contour plot. This method uses the contour_args dict. There are no required keys for this dict. Please note that the data must be a list of 2D numpy arrays. @@ -480,7 +396,7 @@ def plot_contour(self): - inline: whether to show the inline labels, default is True - fsize: the font size of the labels, default is 9 """ - func = self.ax.contourf if self.contour_args["filled"] else self.ax.contour + func = self.ax.contourf if self.customs.contour["filled"] else self.ax.contour assert len(self.data) == 3, "Contour plot requires 3 datasets" @@ -491,10 +407,10 @@ def plot_contour(self): self.data[0], self.data[1], self.data[2], - colors=self.contour_args["colors"], + colors=self.customs.contour["colors"], ) self.ax.clabel( - CS, fontsize=self.contour_args["fsize"], inline=self.contour_args["inline"] + CS, fontsize=self.customs.contour["fsize"], inline=self.customs.contour["inline"] ) self.axes_labels["show_legend"] = False self.label_axes() @@ -527,7 +443,7 @@ class Multiplots(Plot): def __init__(self, args): """Initialize the Multiplot Class.""" # Initialize the Plot Class - super().__init__({"ax": "ax", "data": [], "fig": "fig"}) + super().__init__({"data": []}) # Extract Graph labels self.super_title = args.get("super_title", " ") @@ -543,15 +459,14 @@ def __init__(self, args): # Define the various graphing functions self.graphs = { - "cdf": self.plot_cdf, - "density": self.plot_density, - "histogram": self.plot_histogram, - "timeseries": self.plot_timeseries, - "boxplots": self.plot_box_plots, - "prob_plot": self.plot_probability_plot, - "gen_plot": self.generic_plot, - "contour": self.plot_contour, - "norm_cdf": self.plot_normal_cdf, + "cdf": self.cdf, + "density": self.density, + "histogram": self.histogram, + "boxplot": self.boxplot, + "probability_plot": self.probability_plot, + "line_plot": self.line_plot, + "contour": self.contour, + "normal_cdf": self.normal_cdf, } self.subplots = [] @@ -651,7 +566,6 @@ def __call__(self): self.fig.supxlabel(self.super_xlabel) self.fig.supylabel(self.super_ylabel) self.fig.tight_layout() - plt.savefig("same_overlay_eg.jpg") plt.show() # Reset Canvas @@ -707,3 +621,64 @@ def standardize_dataset(self, data: list) -> np.ndarray: # Return the standardized data return (data - mu) / sigma + + +class CustomizePlot: + """Class to customize the appearance of a map. + + **Usage** + + >>> cmap = CustomizePlot() + """ + + def __init__(self, customs): + """Initialize the CustomizeMap Class.""" + self.customs = customs + self._line_plot = {"color": "navy", "linestyle": "solid"} + self._cdf = {"color": "dogerblue"} + self._density = {"color": "red", "fill": False, "label": " "} + self._boxplot = {"showfliers": True} + self._histogram = {"num_bins": 20, "color": "plum", "ran": None} + self._probability_plot = {"color": "orangered"} + self._normal_cdf = {} + self._contour = {"filled": False, "colors": "k", "inline": True, "fsize": 9} + + @property + def line_plot(self): + """Customize the line plot.""" + return self._line_plot.update(self.customs.get("line_plot", {})) + + @property + def cdf(self): + """Customize the cdf plot.""" + return self._cdf.update(self.customs.get("cdf", {})) + + @property + def density(self): + """Customize the density plot.""" + return self._density.update(self.customs.get("density", {})) + + @property + def boxplot(self): + """Customize the boxplot.""" + return self._boxplot.update(self.customs.get("boxplot", {})) + + @property + def histogram(self): + """Customize the histogram.""" + return self._histogram.update(self.customs.get("histogram", {})) + + @property + def probability_plot(self): + """Customize the probability plot.""" + return self._probability_plot.update(self.customs.get("probability_plot", {})) + + @property + def normal_cdf(self): + """Customize the normal cdf plot.""" + return self._normal_cdf.update(self.customs.get("normal_cdf", {})) + + @property + def contour(self): + """Customize the contour plot.""" + return self._contour.update(self.customs.get("contour", {})) From a0a6a6a554a6e7f378684a4a2cce84538fc3c7f4 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Mon, 21 Oct 2024 11:48:40 -0400 Subject: [PATCH 14/29] update docs to reflect new changes --- docs/source/Plot.rst | 91 ++++++++++++++---------------------------- docs/source/index.rst | 5 +-- src/chartly/chartly.py | 50 +++++++++++++++-------- 3 files changed, 63 insertions(+), 83 deletions(-) diff --git a/docs/source/Plot.rst b/docs/source/Plot.rst index a7bc549..93ac382 100644 --- a/docs/source/Plot.rst +++ b/docs/source/Plot.rst @@ -4,53 +4,45 @@ Chartly.Plot Usage Guide The Plot Class allows users to plot a single plot at a time on a specified axis. The Plot Class requires a dictionary of arguments to be passed to the class. The following keys are required in the dictionary: - `data`: The data that will be plotted. -- `ax`: The axis object that the plot will be plotted on. -- `fig`: The figure object that the plot will be plotted on. There are currently 9 different plot types that can be created using the Plot Class. The Plot Class also allows users to customize these plot by passing additional arguments in the dictionary. The following arguments can be passed to the dictionary: - `axes_labels`: A dictionary containing the x, y, and title labels, and the scale for the plot. -- `gen_plot_args`: A dictionary containing additional arguments for a generic plot, such as color, linestyle, etc. -- `hist_args`: A dictionary containing additional arguments for a histogram plot, such as color, bins, etc. -- `timeseries_args`: A dictionary containing additional arguments for a time series plot, such as color, linestyle, etc. -- `cdf_args`: A dictionary containing additional arguments for a cumulative distribution function plot, such as color, linestyle, etc. -- `boxplot_args`: A dictionary containing additional arguments for a boxplot plot, such as color, notch, etc. -- `norm_cdf_args`: A dictionary containing additional arguments for a normal cumulative distribution function plot, such as color etc. -- `density_args`: A dictionary containing additional arguments for a density plot, such as color, fill, etc. -- `prob_plot_args`: A dictionary containing additional arguments for a probability plot, such as color etc. +- `line_plot`: A dictionary containing additional arguments for a generic plot, such as color, linestyle, etc. +- `histogram`: A dictionary containing additional arguments for a histogram plot, such as color, bins, etc. +- `cdf`: A dictionary containing additional arguments for a cumulative distribution function plot, such as color, linestyle, etc. +- `boxplot`: A dictionary containing additional arguments for a boxplot plot, such as color, notch, etc. +- `normal_cdf`: A dictionary containing additional arguments for a normal cumulative distribution function plot, such as color etc. +- `density`: A dictionary containing additional arguments for a density plot, such as color, fill, etc. +- `probability_plot`: A dictionary containing additional arguments for a probability plot, such as color etc. - `contour_args`: A dictionary containing additional arguments for a contour plot, such as color, filled, etc. Examples -------- -Generic Plot +Line Plot ~~~~~~~~~~~~ -The Generic Plot is a simple plot that can be used to plot any type of data. The plot is created using the `generic_plot` method. Users can pass both x and y data or just y data to the plot. +The Line Plot is a simple plot that can be used to plot any type of data. The plot is created using the `line_plot` method. Users can pass both x and y data or just y data to the plot. .. code-block:: python - import matplotlib.pyplot as plt import chartly - fig, ax = plt.subplots() - # Only y data data = np.random.randn(100) # customize the plot - gen_plot_args = {"color": "red", "linestyle": "--"} + customs = {"color": "red", "linestyle": "--"} # label the plot axes_labels = {"ylabel": "Y", "title": "Generic Plot Example"} # set the arguments - args = {"data": data, "ax": ax, "fig": fig, "gen_plot_args": gen_plot_args, "axes_labels": axes_labels} + args = {"data": data, "line_plot": customs, "axes_labels": axes_labels} plot = chartly.Plot(args) - plot.generic_plot() - - plt.show() + plot.line_plot() .. image:: https://clidapp.s3.amazonaws.com/static/server/img/gen_plot_only_y.jpg :alt: GenericPlotOnlyY @@ -58,28 +50,22 @@ The Generic Plot is a simple plot that can be used to plot any type of data. The .. code-block:: python - - import matplotlib.pyplot as plt import chartly - fig, ax = plt.subplots() - # x and y data x = np.linspace(0, 10, 100) y = np.sin(x) # customize the plot - gen_plot_args = {"color": "mediumpurple", "linestyle": "--"} + customs = {"color": "mediumpurple", "linestyle": "--"} # label the plot axes_labels = {"ylabel": "Y", "xlabel": "X", "title": "Generic Plot Example with X & Y"} - args = {"data": [x, y], "ax": ax, "fig": fig, "gen_plot_args": gen_plot_args, "axes_labels": axes_labels} + args = {"data": [x, y], "line_plot": customs, "axes_labels": axes_labels} plot = chartly.Plot(args) - plot.generic_plot() - - plt.show() + plot.line_plot() .. image:: https://clidapp.s3.amazonaws.com/static/server/img/gen_plot_x_y.jpg :alt: GenericPlotXY @@ -89,31 +75,26 @@ The Generic Plot is a simple plot that can be used to plot any type of data. The Histogram ~~~~~~~~~ -A histogram plot can be created using the `plot_histogram` method. +A histogram plot can be created using the `histogram` method. .. code-block:: python - import matplotlib.pyplot as plt import chartly - fig, ax = plt.subplots() - data = np.random.randn(1000) # customize the plot - histogram_args = {"color": "salmon", "num_bins": 30} + customs = {"color": "salmon", "num_bins": 30} # label the plot axes_labels = {"ylabel": "Frequency", "xlabel": "Value", "title": "Histogram Plot Example"} - args = {"data": data, "ax": ax, "fig": fig, "histogram_args": histogram_args, "axes_labels": axes_labels} + args = {"data": data, "histogram": customs, "axes_labels": axes_labels} plot = chartly.Plot(args) - plot.plot_histogram() - - plt.show() + plot.histogram() .. image:: https://clidapp.s3.amazonaws.com/static/server/img/hist_eg.jpg :alt: HistogramExample @@ -123,15 +104,12 @@ A histogram plot can be created using the `plot_histogram` method. Contour Plot ~~~~~~~~~~~~ -Contour plots can be created using the `plot_contour` method. The contour plot requires 2D arrays of X, Y and Z data to be passed to the plot. +Contour plots can be created using the `contour` method. The contour plot requires 2D arrays of X, Y and Z data to be passed to the plot. .. code-block:: python - import matplotlib.pyplot as plt import chartly - fig, ax = plt.subplots() - x = np.linspace(-3.0, 3.0, 100) y = np.linspace(-3.0, 3.0, 100) X, Y = np.meshgrid(x, y) @@ -140,12 +118,11 @@ Contour plots can be created using the `plot_contour` method. The contour plot r # label the plot axes_labels = {"xlabel": "X", "ylabel": "Y", "title": "Contour Plot Example"} - args = {"data": [X, Y, Z], "ax": ax, "fig": fig, "axes_labels": axes_labels} + args = {"data": [X, Y, Z], "axes_labels": axes_labels} plot = chartly.Plot(args) - plot.plot_contour() + plot.contour() - plt.show() .. image:: https://clidapp.s3.amazonaws.com/static/server/img/contour_eg.jpg :alt: ContourExample @@ -155,29 +132,24 @@ Contour plots can be created using the `plot_contour` method. The contour plot r Normal Probability Plot ~~~~~~~~~~~~~~~~~~~~~~~ -The normal probability plot is used to determine if a dataset is approximately normally distributed. A normal probability plot can be created using the `plot_probability_plot` method. The normal probability plot requires a 1D array of data to be passed to the plot. +The normal probability plot is used to determine if a dataset is approximately normally distributed. A normal probability plot can be created using the `probability_plot` method. The normal probability plot requires a 1D array of data to be passed to the plot. .. code-block:: python - import matplotlib.pyplot as plt import chartly - fig, ax = plt.subplots() - data = np.random.randn(100) # customize the plot - prob_plot_args = {"color": "firebrick"} + customs = {"color": "firebrick"} # label the plot axes_labels = {"title": "Normal Probability Plot Example"} - args = {"data": data, "ax": ax, "fig": fig, "axes_labels": axes_labels, "prob_plot_args": prob_plot_args} + args = {"data": data, "axes_labels": axes_labels, "probability_plot": customs} plot = chartly.Plot(args) - plot.plot_probability_plot() - - plt.show() + plot.probability_plot() .. image:: https://clidapp.s3.amazonaws.com/static/server/img/norm_prob_eg.jpg :alt: NormalProbabilityExample @@ -186,16 +158,13 @@ The normal probability plot is used to determine if a dataset is approximately n Normal Cumulative Distribution Function Plot ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The CDF of a dataset can be compared to the CDF of a normal distribution using the normal CDF plot. The normal CDF plot can be created using the `plot_normal_cdf` method. Users can pass multiple datasets to the plot. +The CDF of a dataset can be compared to the CDF of a normal distribution using the normal CDF plot. The normal CDF plot can be created using the `normal_cdf` method. Users can pass multiple datasets to the plot. .. code-block:: python - import matplotlib.pyplot as plt import chartly - fig, ax = plt.subplots() - dataset_one = np.random.exponential(scale=1.0, size=500) dataset_two = np.random.normal(loc=20, scale=1, size=500) dataset_three = np.random.gamma(2, 2, 500) @@ -205,12 +174,10 @@ The CDF of a dataset can be compared to the CDF of a normal distribution using t # label the plot axes_labels = {"title": "Normal Cumulative Distribution Function Plot Example"} - args = {"data": data, "ax": ax, "fig": fig, "axes_labels": axes_labels} + args = {"data": data, "axes_labels": axes_labels} plot = chartly.Plot(args) - plot.plot_normal_cdf() - - plt.show() + plot.normal_cdf() .. image:: https://clidapp.s3.amazonaws.com/static/server/img/norm_cdf_eg.jpg :alt: NormalCDFExample diff --git a/docs/source/index.rst b/docs/source/index.rst index fb65c4a..0388f53 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -48,17 +48,14 @@ Here is an example of how to use the chartly package: .. code-block:: python - import matplotlib.pyplot as plt import chartly - fig, ax = plt.subplots() data = np.random.randn(100) - args = {"data": data, "ax": ax, "fig": fig} + args = {"data": data} plot = chartly.Plot(args) plot.generic_plot() - plt.show() .. image:: https://clidapp.s3.amazonaws.com/static/server/img/plot_index_eg.jpg :alt: SimpleExampleResult diff --git a/src/chartly/chartly.py b/src/chartly/chartly.py index a901d55..2bafb1a 100644 --- a/src/chartly/chartly.py +++ b/src/chartly/chartly.py @@ -36,8 +36,6 @@ class Plot: and required fields Required Keys - - ax: an axis to plot the data - - fig: the figure that the axis is on - data: a data list, or a list of data lists Optional Keys @@ -53,9 +51,8 @@ class Plot: **Examples** - >>> fig, ax = plt.subplots() >>> data = [1, 2, 3, 4, 5] - >>> args = {"ax": ax, "fig": fig, "data": data} + >>> args = {"data": data} >>> plot = Plot(args) >>> plot.data [1, 2, 3, 4, 5] @@ -83,9 +80,20 @@ def __init__(self, args): # Initialize the Plot Utilities self.util = PlotUtilities() + def_axes_labels = { + "title": " ", + "xlabel": " ", + "ylabel": " ", + "linelabel": " ", + "boxlabel": " ", + "show_legend": True, + "scale": "linear", + "base": 10, + } + # Extract axis labels self.axes_labels = { - **self.set_defaults("axes_labels"), + **def_axes_labels, **args.get("axes_labels", {}), } @@ -442,8 +450,11 @@ class Multiplots(Plot): def __init__(self, args): """Initialize the Multiplot Class.""" + # Turn off interactive mode + plt.ioff() + # Initialize the Plot Class - super().__init__({"data": []}) + super().__init__({"data": [], "display": False}) # Extract Graph labels self.super_title = args.get("super_title", " ") @@ -451,9 +462,6 @@ def __init__(self, args): self.super_ylabel = args.get("super_ylabel", " ") self.share_axes = args.get("share_axes", True) - # Turn off interactive mode - plt.ioff() - # Set the subplot count self.subplot_count = 0 @@ -646,39 +654,47 @@ def __init__(self, customs): @property def line_plot(self): """Customize the line plot.""" - return self._line_plot.update(self.customs.get("line_plot", {})) + self._line_plot.update(self.customs.get("line_plot", {})) + return self._line_plot @property def cdf(self): """Customize the cdf plot.""" - return self._cdf.update(self.customs.get("cdf", {})) + self._cdf.update(self.customs.get("cdf", {})) + return self._cdf @property def density(self): """Customize the density plot.""" - return self._density.update(self.customs.get("density", {})) + self._density.update(self.customs.get("density", {})) + return self._density @property def boxplot(self): """Customize the boxplot.""" - return self._boxplot.update(self.customs.get("boxplot", {})) + self._boxplot.update(self.customs.get("boxplot", {})) + return self._boxplot @property def histogram(self): """Customize the histogram.""" - return self._histogram.update(self.customs.get("histogram", {})) + self._histogram.update(self.customs.get("histogram", {})) + return self._histogram @property def probability_plot(self): """Customize the probability plot.""" - return self._probability_plot.update(self.customs.get("probability_plot", {})) + self._probability_plot.update(self.customs.get("probability_plot", {})) + return self._probability_plot @property def normal_cdf(self): """Customize the normal cdf plot.""" - return self._normal_cdf.update(self.customs.get("normal_cdf", {})) + self._normal_cdf.update(self.customs.get("normal_cdf", {})) + return self._normal_cdf @property def contour(self): """Customize the contour plot.""" - return self._contour.update(self.customs.get("contour", {})) + self._contour.update(self.customs.get("contour", {})) + return self._contour From 33126a0e199e34c202b1e191626ef7c8a79bc748 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Mon, 21 Oct 2024 14:09:49 -0400 Subject: [PATCH 15/29] Adds HatchArea Class --- src/chartly/chartly.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/chartly/chartly.py b/src/chartly/chartly.py index 2bafb1a..91e17d7 100644 --- a/src/chartly/chartly.py +++ b/src/chartly/chartly.py @@ -23,6 +23,7 @@ import matplotlib.pyplot as plt import numpy as np import seaborn as sns +from matplotlib.patches import Rectangle from scipy.stats import norm color_list = ["slateblue", "lightpink", "skyblue", "plum", "mediumvioletred"] @@ -698,3 +699,37 @@ def contour(self): """Customize the contour plot.""" self._contour.update(self.customs.get("contour", {})) return self._contour + + +class HatchArea: + """Class to hatch the area between two points.""" + + def __init__(self, args): + """Initialize the HatchArea Class.""" + self.args = args + self.xy1 = self.args.get("xy1") + self.xy2 = self.args.get("xy2") + self.ax = self.args.get("ax") + self.hatch = self.args.get("hatch", "...") + self.color = self.args.get("color", "black") + self.alpha = self.args.get("alpha", 0.5) + self.fill = self.args.get("fill", True) + + def hatch_area(self): + """Hatch the area between two points.""" + x = self.xy1[0] + y = self.xy1[1] + width = self.xy2[0] - self.xy1[0] + height = self.xy2[1] - self.xy1[1] + + self.ax.add_patch( + Rectangle( + (x, y), + width, + height, + fill=self.fill, + color=self.color, + alpha=self.alpha, + hatch=self.hatch + ) + ) From 06263a6486cd94f408544de8517d7f07e2658419 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Mon, 21 Oct 2024 14:40:46 -0400 Subject: [PATCH 16/29] update contour plot function --- src/chartly/chartly.py | 46 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/chartly/chartly.py b/src/chartly/chartly.py index 91e17d7..93bbbab 100644 --- a/src/chartly/chartly.py +++ b/src/chartly/chartly.py @@ -406,6 +406,11 @@ def contour(self): - fsize: the font size of the labels, default is 9 """ func = self.ax.contourf if self.customs.contour["filled"] else self.ax.contour + color = ( + self.customs.contour["colors"] + if not self.customs.contour["filled"] + else None + ) assert len(self.data) == 3, "Contour plot requires 3 datasets" @@ -416,11 +421,27 @@ def contour(self): self.data[0], self.data[1], self.data[2], - colors=self.customs.contour["colors"], + colors=color, + cmap=self.customs.contour["cmap"], ) self.ax.clabel( - CS, fontsize=self.customs.contour["fsize"], inline=self.customs.contour["inline"] + CS, + fontsize=self.customs.contour["fsize"], + inline=self.customs.contour["inline"], ) + + if self.customs.contour["hatch"]: + payload = { + "ax": self.ax, + "xy1": self.customs.contour["xy1"], + "xy2": self.customs.contour["xy2"], + "pattern": self.customs.contour["pattern"], + "color": self.customs.contour["hatch_color"], + "alpha": self.customs.contour["hatch_alpha"], + "fill": self.customs.contour["hatch_fill"], + } + hatch = HatchArea(payload) + hatch() self.axes_labels["show_legend"] = False self.label_axes() @@ -650,7 +671,20 @@ def __init__(self, customs): self._histogram = {"num_bins": 20, "color": "plum", "ran": None} self._probability_plot = {"color": "orangered"} self._normal_cdf = {} - self._contour = {"filled": False, "colors": "k", "inline": True, "fsize": 9} + self._contour = { + "filled": False, + "colors": None, + "inline": True, + "fsize": 9, + "cmap": "viridis", + "hatch": False, + "hatch_color": "black", + "hatch_alpha": 0.5, + "hatch_fill": True, + "pattern": "...", + "xy1": (0, 0), + "xy2": (1, 1), + } @property def line_plot(self): @@ -710,12 +744,12 @@ def __init__(self, args): self.xy1 = self.args.get("xy1") self.xy2 = self.args.get("xy2") self.ax = self.args.get("ax") - self.hatch = self.args.get("hatch", "...") + self.pattern = self.args.get("pattern", "...") self.color = self.args.get("color", "black") self.alpha = self.args.get("alpha", 0.5) self.fill = self.args.get("fill", True) - def hatch_area(self): + def __call__(self): """Hatch the area between two points.""" x = self.xy1[0] y = self.xy1[1] @@ -730,6 +764,6 @@ def hatch_area(self): fill=self.fill, color=self.color, alpha=self.alpha, - hatch=self.hatch + hatch=self.pattern, ) ) From 7c0298deb367447c74fc2e9f0dabfb72c97bda76 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Mon, 21 Oct 2024 17:34:56 -0400 Subject: [PATCH 17/29] adds contour mask hatching --- src/chartly/chartly.py | 44 +++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/chartly/chartly.py b/src/chartly/chartly.py index 93bbbab..c473a01 100644 --- a/src/chartly/chartly.py +++ b/src/chartly/chartly.py @@ -746,24 +746,36 @@ def __init__(self, args): self.ax = self.args.get("ax") self.pattern = self.args.get("pattern", "...") self.color = self.args.get("color", "black") - self.alpha = self.args.get("alpha", 0.5) + self.alpha = self.args.get("alpha", 0.2) self.fill = self.args.get("fill", True) + self.data = self.args.get("data", None) - def __call__(self): + def __call__(self, func): """Hatch the area between two points.""" - x = self.xy1[0] - y = self.xy1[1] - width = self.xy2[0] - self.xy1[0] - height = self.xy2[1] - self.xy1[1] - - self.ax.add_patch( - Rectangle( - (x, y), - width, - height, - fill=self.fill, - color=self.color, + if func == "grid": + x = self.xy1[0] + y = self.xy1[1] + width = self.xy2[0] - self.xy1[0] + height = self.xy2[1] - self.xy1[1] + + self.ax.add_patch( + Rectangle( + (x, y), + width, + height, + fill=self.fill, + color=self.color, + alpha=self.alpha, + hatch=self.pattern, + ) + ) + if func == "mask": + assert self.data is not None, "Data must be provided" + self.ax.contourf( + self.data[0], + self.data[1], + self.data[2], + [0.5, 1], + hatches=[self.pattern], alpha=self.alpha, - hatch=self.pattern, ) - ) From a8ecb645f957af11bddcaaf307cb11d5fd4a9f9b Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Mon, 21 Oct 2024 17:49:25 -0400 Subject: [PATCH 18/29] WIP --- src/chartly/chartly.py | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/chartly/chartly.py b/src/chartly/chartly.py index c473a01..8acaf27 100644 --- a/src/chartly/chartly.py +++ b/src/chartly/chartly.py @@ -430,7 +430,7 @@ def contour(self): inline=self.customs.contour["inline"], ) - if self.customs.contour["hatch"]: + if self.customs.contour["hatch_grid"]: payload = { "ax": self.ax, "xy1": self.customs.contour["xy1"], @@ -441,7 +441,18 @@ def contour(self): "fill": self.customs.contour["hatch_fill"], } hatch = HatchArea(payload) - hatch() + hatch("grid") + if self.customs.contour["hatch_mask"]: + payload = { + "ax": self.ax, + "data": [self.data[0], self.data[1], self.customs.contour["mask"]], + "pattern": self.customs.contour["pattern"], + "color": self.customs.contour["hatch_color"], + "alpha": self.customs.contour["hatch_alpha"], + "fill": self.customs.contour["hatch_fill"], + } + hatch = HatchArea(payload) + hatch("mask") self.axes_labels["show_legend"] = False self.label_axes() @@ -679,11 +690,14 @@ def __init__(self, customs): "cmap": "viridis", "hatch": False, "hatch_color": "black", - "hatch_alpha": 0.5, + "hatch_alpha": 0, "hatch_fill": True, - "pattern": "...", + "pattern": "..", "xy1": (0, 0), "xy2": (1, 1), + "hatch_grid": False, + "hatch_mask": False, + "mask": None, } @property @@ -741,10 +755,10 @@ class HatchArea: def __init__(self, args): """Initialize the HatchArea Class.""" self.args = args - self.xy1 = self.args.get("xy1") - self.xy2 = self.args.get("xy2") + self.xy1 = self.args.get("xy1", (0, 0)) + self.xy2 = self.args.get("xy2", (1, 1)) self.ax = self.args.get("ax") - self.pattern = self.args.get("pattern", "...") + self.pattern = self.args.get("pattern", "..") self.color = self.args.get("color", "black") self.alpha = self.args.get("alpha", 0.2) self.fill = self.args.get("fill", True) From 1cf7114398d61bb476a8df1b5b797f8826093a97 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Tue, 22 Oct 2024 07:44:53 -0400 Subject: [PATCH 19/29] update tests --- src/tests/test_chartly.py | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/tests/test_chartly.py b/src/tests/test_chartly.py index a3aab84..5bb2c2e 100644 --- a/src/tests/test_chartly.py +++ b/src/tests/test_chartly.py @@ -15,8 +15,8 @@ import unittest -import matplotlib.pyplot as plt import numpy as np + from chartly.chartly import Multiplots, Plot, PlotUtilities @@ -27,16 +27,13 @@ def setUp(self): """Set up the test class.""" self.util = PlotUtilities() - # Create a figure and axis - self.fig, self.ax = plt.subplots() - # Create a data list self.dataset_one = np.random.randint(50, size=(20)) self.dataset_two = np.random.randint(50, size=(20)) self.data = [self.dataset_one, self.dataset_two] # Create a dictionary of arguments - args = {"ax": self.ax, "fig": self.fig, "data": self.data} + args = {"display": False, "data": self.data} # Create a plot object self.plot = Plot(args) @@ -54,17 +51,17 @@ def test_gen_plot_data_type(self): """Test that the generic plot can use both a 1D and 2D list of data.""" # Test 1D data self.plot.data = self.dataset_one - self.assertIsNone(self.plot.generic_plot()) + self.assertIsNone(self.plot.line_plot()) # Test 2D data self.plot.data = self.data - self.assertIsNone(self.plot.generic_plot()) + self.assertIsNone(self.plot.line_plot()) def test_gen_plot_data_length(self): """Test that the generic plot throws an error if the data lengths are unequal.""" self.plot.data = [self.dataset_one, self.dataset_two[:-1]] with self.assertRaises(AssertionError): - self.plot.generic_plot() + self.plot.line_plot() def test_standardize_data(self): """Test that the data is standardized correctly.""" @@ -106,37 +103,36 @@ def test_contour_data_length(self): # Test that the contour plot throws an error when a user does not send 3 datasets self.plot.data = [self.dataset_one, self.dataset_two] with self.assertRaises(AssertionError): - self.plot.plot_contour() + self.plot.contour() # test that the contour plot does not throw an error when a user sends 3 datasets X, Y = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100)) Z = np.sin(X) * np.cos(Y) self.plot.data = [X, Y, Z] - self.assertIsNone(self.plot.plot_contour()) + self.assertIsNone(self.plot.contour()) # Test that the contour plot throws an error when the data sets are not 2D self.plot.data = [X, Y, Z[0]] with self.assertRaises(AssertionError): - self.plot.plot_contour() + self.plot.contour() def test_default(self): """Test that the default plot is created correctly.""" # Test that the default plot is created correctly gen_args = {"color": "pink"} args = { - "ax": self.ax, - "fig": self.fig, "data": self.data, - "gen_plot_args": gen_args, + "line_plot": gen_args, + "display": False, } plot_two = Plot(args) expect = {"color": "pink", "linestyle": "solid"} - self.assertEqual(plot_two.gen_plot_args, expect) + self.assertEqual(plot_two.customs.line_plot, expect) # Test that the customs are updated correctly - plot_two.update_defaults("gen_plot", {"color": "blue"}) + plot_two.update_defaults("line_plot", {"color": "blue"}) expect = {"color": "blue", "linestyle": "solid"} - self.assertEqual(plot_two.gen_plot_args, expect) + self.assertEqual(plot_two.customs.line_plot, expect) if __name__ == "__main__": From 191697add733d52ab6acfdd30c14d1595f64a228 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Tue, 22 Oct 2024 11:06:13 -0400 Subject: [PATCH 20/29] add basemap to chartly --- requirements.txt | 2 + requirements/production.txt | 2 + requirements/staging.txt | 2 + requirements/testing.txt | 2 + src/chartly/chartly.py | 95 ++++++++++++++++++++++++++++++------- 5 files changed, 87 insertions(+), 16 deletions(-) diff --git a/requirements.txt b/requirements.txt index 74c0a2b..4f8e534 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,7 @@ +basemap==1.4.1 cloud-sptheme==1.10.1.post20200504175005 matplotlib==3.9.1 +mpl_toolkits==1.3.0 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 diff --git a/requirements/production.txt b/requirements/production.txt index 6ff924e..9460fcf 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -1,5 +1,7 @@ +basemap==1.4.1 cloud-sptheme==1.10.1.post20200504175005 matplotlib==3.9.1 +mpl_toolkits==1.3.0 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 diff --git a/requirements/staging.txt b/requirements/staging.txt index 6ff924e..9460fcf 100644 --- a/requirements/staging.txt +++ b/requirements/staging.txt @@ -1,5 +1,7 @@ +basemap==1.4.1 cloud-sptheme==1.10.1.post20200504175005 matplotlib==3.9.1 +mpl_toolkits==1.3.0 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 diff --git a/requirements/testing.txt b/requirements/testing.txt index 6ff924e..9460fcf 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -1,5 +1,7 @@ +basemap==1.4.1 cloud-sptheme==1.10.1.post20200504175005 matplotlib==3.9.1 +mpl_toolkits==1.3.0 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 diff --git a/src/chartly/chartly.py b/src/chartly/chartly.py index 8acaf27..3da15ce 100644 --- a/src/chartly/chartly.py +++ b/src/chartly/chartly.py @@ -24,6 +24,7 @@ import numpy as np import seaborn as sns from matplotlib.patches import Rectangle +from mpl_toolkits.basemap import Basemap from scipy.stats import norm color_list = ["slateblue", "lightpink", "skyblue", "plum", "mediumvioletred"] @@ -430,29 +431,72 @@ def contour(self): inline=self.customs.contour["inline"], ) - if self.customs.contour["hatch_grid"]: + if self.customs.contour["hatch_grid"] or self.customs.contour["hatch_mask"]: payload = { "ax": self.ax, - "xy1": self.customs.contour["xy1"], - "xy2": self.customs.contour["xy2"], "pattern": self.customs.contour["pattern"], "color": self.customs.contour["hatch_color"], "alpha": self.customs.contour["hatch_alpha"], "fill": self.customs.contour["hatch_fill"], } - hatch = HatchArea(payload) - hatch("grid") - if self.customs.contour["hatch_mask"]: - payload = { - "ax": self.ax, - "data": [self.data[0], self.data[1], self.customs.contour["mask"]], - "pattern": self.customs.contour["pattern"], - "color": self.customs.contour["hatch_color"], - "alpha": self.customs.contour["hatch_alpha"], - "fill": self.customs.contour["hatch_fill"], - } - hatch = HatchArea(payload) - hatch("mask") + if self.customs.contour["hatch_grid"]: + payload.update( + { + "ax": self.ax, + "xy1": self.customs.contour["xy1"], + "xy2": self.customs.contour["xy2"], + } + ) + hatch = HatchArea(payload) + hatch("grid") + if self.customs.contour["hatch_mask"]: + payload.update( + { + "data": [ + self.data[0], + self.data[1], + self.customs.contour["mask"], + ], + } + ) + hatch = HatchArea(payload) + hatch("mask") + self.axes_labels["show_legend"] = False + self.label_axes() + + def basemap(self): + """Plot a base map. This method uses the basemap customs. The customs are + + Optional Keys: + - proj: the projection of the map, default is "ortho" + - draw_coastlines: whether to draw coastlines, default is True + - fillcontinents: whether to fill continents, default is False + - draw_countries: whether to draw countries, default is False + - draw_states: whether to draw states, default is False + - draw_rivers: whether to draw rivers, default is False + - bluemarble: whether to use the bluemarble map, default is False + - shaderelief: whether to use the shaded relief map, default is False + - draw_parallels: whether to draw parallels, default is False + - draw_meridians: whether to draw meridians, default is False + """ + map_ = Basemap(projection=self.customs.basemap["proj"], lat_0=0, lon_0=0) + + basemap_methods = { + "draw_coastlines": map_.drawcoastlines, + "fillcontinents": map_.fillcontinents, + "draw_countries": map_.drawcountries, + "draw_states": map_.drawstates, + "draw_rivers": map_.drawrivers, + "bluemarble": map_.bluemarble, + "shaderelief": map_.shadedrelief, + "draw_parallels": lambda: map_.drawparallels(np.arange(-90, 90, 30)), + "draw_meridians": lambda: map_.drawmeridians(np.arange(0, 360, 60)), + } + + for key, method in basemap_methods.items(): + if self.customs.basemap.get(key): + method() + self.axes_labels["show_legend"] = False self.label_axes() @@ -508,6 +552,7 @@ def __init__(self, args): "line_plot": self.line_plot, "contour": self.contour, "normal_cdf": self.normal_cdf, + "basemap": self.basemap, } self.subplots = [] @@ -699,6 +744,18 @@ def __init__(self, customs): "hatch_mask": False, "mask": None, } + self._basemap = { + "proj": "ortho", + "draw_coastlines": True, + "fillcontinents": False, + "draw_countries": False, + "draw_states": False, + "draw_rivers": False, + "bluemarble": False, + "shaderelief": False, + "draw_parallels": False, + "draw_meridians": False, + } @property def line_plot(self): @@ -748,6 +805,12 @@ def contour(self): self._contour.update(self.customs.get("contour", {})) return self._contour + @property + def basemap(self): + """Customize the basemap.""" + self._basemap.update(self.customs.get("basemap", {})) + return self._basemap + class HatchArea: """Class to hatch the area between two points.""" From 3a42658f841f82127105504bd304c3052fb261be Mon Sep 17 00:00:00 2001 From: Azendae Popo <97713029+Azendae-Popo@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:58:51 -0400 Subject: [PATCH 21/29] Delete docs/Makefile --- docs/Makefile | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 docs/Makefile diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index d0c3cbf..0000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) From 4da34b6d36d1a782577921547bedbe5fe74cc721 Mon Sep 17 00:00:00 2001 From: Azendae Popo <97713029+Azendae-Popo@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:59:03 -0400 Subject: [PATCH 22/29] Delete docs/make.bat --- docs/make.bat | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 docs/make.bat diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 747ffb7..0000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd From dd33e8bd088a2f6324e506265d35a2d95eadc94a Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Mon, 28 Oct 2024 14:16:55 -0400 Subject: [PATCH 23/29] adds basemap feature to the class --- VERSION | 2 +- chartly/chartly.py | 2 + chartly/charts.py | 73 ++++ src/chartly/__init__.py | 0 src/chartly/chartly.py | 858 -------------------------------------- src/tests/test_chartly.py | 139 ------ 6 files changed, 76 insertions(+), 998 deletions(-) delete mode 100644 src/chartly/__init__.py delete mode 100644 src/chartly/chartly.py delete mode 100644 src/tests/test_chartly.py diff --git a/VERSION b/VERSION index 8acdd82..4e379d2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.0.1 +0.0.2 diff --git a/chartly/chartly.py b/chartly/chartly.py index 770c7ea..f861937 100644 --- a/chartly/chartly.py +++ b/chartly/chartly.py @@ -21,6 +21,7 @@ from .base import Plot from .charts import ( CDF, + Basemap, BoxPlot, Contour, Density, @@ -84,6 +85,7 @@ def __init__(self, args={}): "line_plot": LinePlot, "contour": Contour, "normal_cdf": NormalCDF, + "basemap": Basemap, } self.subplots = [] diff --git a/chartly/charts.py b/chartly/charts.py index e6ce274..7e85edf 100644 --- a/chartly/charts.py +++ b/chartly/charts.py @@ -28,6 +28,7 @@ import seaborn as sns from matplotlib.colors import LinearSegmentedColormap from matplotlib.patches import Rectangle +from mpl_toolkits.basemap import Basemap as bmap from scipy.stats import norm from .base import CustomizePlot, Plot @@ -614,3 +615,75 @@ def __call__(self): hatches=[self.customs["pattern"]], alpha=self.customs["alpha"], ) + +class Basemap(Plot, CustomizePlot): + """Class to plot a basemap. + + :param dict args: the master dictionary containing the required fields. + + Required Keys + - data: the data to plot + + Optional Keys + - customs: the plot's customization + - axes_labels: the axes labels + + Available Customizations: + - proj: the projection of the map, default is "ortho" + - draw_coastlines: whether to draw coastlines, default is True + - fillcontinents: whether to fill continents, default is False + - draw_countries: whether to draw countries, default is False + - draw_states: whether to draw states, default is False + - draw_rivers: whether to draw rivers, default is False + - bluemarble: whether to use the bluemarble map, default is False + - shaderelief: whether to use the shaded relief map, default is False + - draw_parallels: whether to draw parallels, default is False + - draw_meridians: whether to draw meridians, default is False + """ + + def __init__(self, args): + """Initialize the Contour Class.""" + # Get the arguments + self.args = args + + # Extract the customs + customs_ = self.args.get("customs", {}) + super().__init__(self.args) + CustomizePlot.__init__(self, customs_) + + def defaults(self): + return { + "proj": "ortho", + "draw_coastlines": True, + "fillcontinents": False, + "draw_countries": False, + "draw_states": False, + "draw_rivers": False, + "bluemarble": False, + "shaderelief": False, + "draw_parallels": False, + "draw_meridians": False, + } + + def __call__(self): + """Plot a basemap.""" + map_ = bmap(projection=self.customs["proj"], lat_0=0, lon_0=0) + + basemap_methods = { + "draw_coastlines": map_.drawcoastlines, + "fillcontinents": map_.fillcontinents, + "draw_countries": map_.drawcountries, + "draw_states": map_.drawstates, + "draw_rivers": map_.drawrivers, + "bluemarble": map_.bluemarble, + "shaderelief": map_.shadedrelief, + "draw_parallels": lambda: map_.drawparallels(np.arange(-90, 90, 30)), + "draw_meridians": lambda: map_.drawmeridians(np.arange(0, 360, 60)), + } + + for key, method in basemap_methods.items(): + if self.customs.get(key): + method() + + self.axes_labels["show_legend"] = False + self.label_axes() diff --git a/src/chartly/__init__.py b/src/chartly/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/chartly/chartly.py b/src/chartly/chartly.py deleted file mode 100644 index 3da15ce..0000000 --- a/src/chartly/chartly.py +++ /dev/null @@ -1,858 +0,0 @@ -"""Module to plot and customize various types of graphs. - -:author: A.M.E. Popo[#]_, - C.O. Mbengue[#]_, - -:organization: Elizabeth Consulting International Inc. - -This module contains the following classes: - - - :class:`Plot`: Class to plot various types of graphs. - - :class:`PlotUtilities`: Class containing auxillary utility functions for plotting. - - :class:`Multiplots`: Class to plot multiple subplots on the same graph. - -.. [#] Azendae Marie-Ange Elizabeth Popo, Research Assistant, apopo@ec-intl.com -.. [#] Cheikh Oumar Mbengue, Research Scientist, cmbengue@ec-intl.com -.. [#] Elizabeth Consulting International Inc. (ECI) is a private company that - specializes in the development of decision support systems for the - private sector. ECI is based in St. Lucia, West Indies. -""" - -import math - -import matplotlib.pyplot as plt -import numpy as np -import seaborn as sns -from matplotlib.patches import Rectangle -from mpl_toolkits.basemap import Basemap -from scipy.stats import norm - -color_list = ["slateblue", "lightpink", "skyblue", "plum", "mediumvioletred"] - - -class Plot: - """ - Class that holds various methods used to plot graphs. - - :param dict args: the master dictionary containing both optional - and required fields - - Required Keys - - data: a data list, or a list of data lists - - Optional Keys - - axes_labels: the axes labels - - boxplot: the optional customizations for a boxplot - - cdf: the optional customizations for a cdf plot - - histogram: the optional customizations for a histogram - - probability_plot: the optional customizations for a probability plot - - line_plot: the optional customizations for a generic plot - - normal_cdf: the optional customizations for a normal cdf plot - - contour: the optional customizations for a contour plot - - density: the optional customizations for a density plot - - **Examples** - - >>> data = [1, 2, 3, 4, 5] - >>> args = {"data": data} - >>> plot = Plot(args) - >>> plot.data - [1, 2, 3, 4, 5] - """ - - def __init__(self, args): - """Initialize the Plot Class""" - # Turn off interactive mode - plt.ioff() - - self.args = args - - # initialize the figure and axis - self._fig, self._ax = plt.subplots() - - self.display = args.get("display", True) - - # Extract the data - self.data = args.get("data") - - # Set the filename and format - self._fname = "plot" - self._format = "eps" - - # Initialize the Plot Utilities - self.util = PlotUtilities() - - def_axes_labels = { - "title": " ", - "xlabel": " ", - "ylabel": " ", - "linelabel": " ", - "boxlabel": " ", - "show_legend": True, - "scale": "linear", - "base": 10, - } - - # Extract axis labels - self.axes_labels = { - **def_axes_labels, - **args.get("axes_labels", {}), - } - - # Set Customizations - self.customs = CustomizePlot(self.args) - - @property - def fig(self): - """Get the figure.""" - return self._fig - - @fig.setter - def fig(self, value): - self._fig = value - - @property - def ax(self): - """Get the figure.""" - return self._ax - - @ax.setter - def ax(self, value): - self._ax = value - - @property - def fname(self): - """Get the figure.""" - return self._fname - - @fname.setter - def fname(self, value): - self._fname = value - - @property - def format(self): - """Get the figure.""" - return self._format - - @format.setter - def format(self, value): - self._format = value - - def update_defaults(self, field, new_values): - """Update the optional fields default values. - - :param str field: the optional field to be updated - :param dict values: the updated optional fields dict - :rtype: None - """ - self.args[field].update(new_values) - self.customs = CustomizePlot(self.args) - - def label_axes(self): - """Label the axes of a graph. This method uses the axes_labels dict. - There are no required keys for this dict. - - Optional Keys - - xlabel: the x-axis label, default is " " - - ylabel: the y-axis label, default is " " - - title: the title of the graph, default is " " - - linelabel: the label for the line, default is " " - - show_legend: whether to show the legend or not, default is True - - scale: the scale of the axes, default is "linear" - - base: the base of the axes, default is 10 - - """ - self.ax.set_title(self.axes_labels["title"]) - self.ax.set_xlabel(self.axes_labels["xlabel"]) - self.ax.set_ylabel(self.axes_labels["ylabel"]) - - if self.axes_labels["scale"] in "semilogy loglog": - plt.yscale("log", base=self.axes_labels["base"]) - - if self.axes_labels["scale"] in "semilogx loglog": - plt.xscale("log", base=self.axes_labels["base"]) - - if self.axes_labels["show_legend"]: - self.ax.legend() - - if self.display: - plt.show() - - def save(self): - """Export the current figure to a file.""" - - self.fig.savefig( - f"{self.fname}.{self.format}", - format=self.format, - bbox_inches="tight", - pad_inches=1, - orientation="portrait", - ) - - def line_plot(self) -> None: - """Plot a generic plot using y and/or x. This method uses the - line_plot_args dict. There are no required keys for this dict. - - Optional Keys - - color: the color of the line, default is "navy" - - linestyle: the style of the line, default is "solid" - """ - # Check if the data is 1D or 2D - if isinstance(self.data[0], (list, np.ndarray)): - # Check that both x and y data are present and of equal length - assert len(self.data) == 2, "Data must contain both x and y list" - assert len(self.data[0]) == len(self.data[1]), "Data lengths must be equal" - - self.ax.plot( - self.data[0], - self.data[1], - color=self.customs.line_plot["color"], - linewidth=1.5, - linestyle=self.customs.line_plot["linestyle"], - label=self.axes_labels["linelabel"], - ) - else: - self.ax.plot( - self.data, - color=self.customs.line_plot["color"], - linewidth=1.5, - linestyle=self.customs.line_plot["linestyle"], - label=self.axes_labels["linelabel"], - ) - self.label_axes() - - def cdf(self) -> None: - """Plot CDF of a dataset. This method uses the cdf_args dict. There are - no required keys for this dict. - """ - - x = np.sort(self.data) - y = np.cumsum(x) / np.sum(x) - - self.ax.plot( - x, - y, - linewidth=1.5, - label=self.axes_labels["linelabel"], - color=self.customs.cdf["color"], - ) - - for hline in (0.1, 0.5, 0.9): - self.ax.axhline(y=hline, color="black", linewidth=1, linestyle="dashed") - - self.label_axes() - - def density(self) -> None: - """Plot the density plot of a dataset using kernel density estimation. This - method uses the density_args dict. There are no required keys for this dict. - - Optional Keys: - - color: the color of the density plot, default is "red" - - fill: whether to fill the density plot, default is False - - label: the label of the density plot, default is " " - """ - # Plot a density plot - sns.kdeplot( - self.data, - color=self.customs.density["color"], - ax=self.ax, - fill=self.customs.density["fill"], - label=self.customs.density["label"], - ) - self.label_axes() - - def boxplot(self) -> None: - """Plot Box Plots. This method uses the boxplot_args dict. There are no - required keys for this dict. - - Optional Keys: - - showfliers: whether to show the outliers, default is True - """ - - self.ax.boxplot( - self.data, - flierprops=dict(marker="o", markersize=1), - medianprops=dict(color="red"), - boxprops=dict(color="navy"), - whiskerprops=dict(color="blue"), - capprops=dict(color="red"), - tick_labels=self.axes_labels["boxlabel"], - showfliers=self.customs.boxplot["showfliers"], - ) - self.axes_labels["show_legend"] = False - self.label_axes() - - def histogram(self): - """Plot a histogram. This method uses the hist_args dict. There are no - required keys for this dict. - - Optional Keys: - - num_bins: the number of bins in the histogram, default is 20 - - color: the color of the histogram, default is "plum" - - ran: the range of the histogram, default is None - """ - self.ax.hist( - self.data, - bins=self.customs.histogram["num_bins"], - color=self.customs.histogram["color"], - edgecolor="black", - weights=np.ones_like(self.data) / len(self.data), - range=self.customs.histogram["ran"], - ) - self.axes_labels["show_legend"] = False - self.label_axes() - - def probability_plot(self): - """Plot a probability plot. This method uses the prob_plot_args dict. There are no - required keys for this dict. - - Optional Keys: - - color: the color of the plot, default is "orangered" - """ - # Extract Fields - sample_data = self.data - - # Data Stats - n = len(sample_data) - sigma = np.std(sample_data) - mu = np.mean(sample_data) - - # Sort the data - sample_data.sort() - - # Find percentiles - pctls = [(i - 0.5) / n for i in range(1, n + 1)] - - # Find z percentiles - z = [norm.ppf(pctl) for pctl in pctls] - - # Plot (z pctl, obs) ordered pairs - self.ax.scatter( - z, - sample_data, - color=self.customs.probability_plot["color"], - s=30, - marker="x", - ) - - # Plot Solid Line - plt.axline( - (0, mu), - slope=sigma, - color="black", - linewidth=1, - label=f"slope={mu:.2f}, y-intercept={sigma:.2f}", - ) - - # Create Axes Labels - self.axes_labels.update({"xlabel": "z percentile", "ylabel": "Observations"}) - - # label the axes - self.label_axes() - - def normal_cdf(self): - """Plot a standard normal distribution CDF against the CDF - of other datasets. This method uses the norm_cdf_args dict. There are no - required keys for this dict. - """ - data_list = ( - self.data if isinstance(self.data[0], (list, np.ndarray)) else [self.data] - ) - - for idx, data in enumerate(data_list): - # Standardize the data - x = np.sort(self.util.standardize_dataset(data)) - n = len(x) - - # Find the percentiles - pctls = [(i - 0.5) / n for i in range(1, n + 1)] - - # Plot Sample CDF - self.ax.plot( - x, - pctls, - linewidth=1.5, - linestyle="solid", - label=f"Sample Dataset {idx + 1} CDF", - ) - - # Find the z values - z = np.linspace(-3.4, 3.4) - - # Find the p values - p_vals = [norm.cdf(z_) for z_ in z] - - # Plot Stanfard Normal CDF - self.ax.plot( - z, - p_vals, - linewidth=1.5, - linestyle="dashed", - label="Standard Normal CDF", - color="red", - ) - - # label the axes - self.label_axes() - - def contour(self): - """Plot a contour plot. This method uses the contour_args dict. There are no - required keys for this dict. Please note that the data must be a list of - 2D numpy arrays. - - Optional Keys: - - filled: whether to fill the contour plot, default is False - - colors: the color of the contour plot, default is "k" - - inline: whether to show the inline labels, default is True - - fsize: the font size of the labels, default is 9 - """ - func = self.ax.contourf if self.customs.contour["filled"] else self.ax.contour - color = ( - self.customs.contour["colors"] - if not self.customs.contour["filled"] - else None - ) - - assert len(self.data) == 3, "Contour plot requires 3 datasets" - - for data_ in self.data: - assert data_.ndim == 2, "Data must be a 2D numpy array" - - CS = func( - self.data[0], - self.data[1], - self.data[2], - colors=color, - cmap=self.customs.contour["cmap"], - ) - self.ax.clabel( - CS, - fontsize=self.customs.contour["fsize"], - inline=self.customs.contour["inline"], - ) - - if self.customs.contour["hatch_grid"] or self.customs.contour["hatch_mask"]: - payload = { - "ax": self.ax, - "pattern": self.customs.contour["pattern"], - "color": self.customs.contour["hatch_color"], - "alpha": self.customs.contour["hatch_alpha"], - "fill": self.customs.contour["hatch_fill"], - } - if self.customs.contour["hatch_grid"]: - payload.update( - { - "ax": self.ax, - "xy1": self.customs.contour["xy1"], - "xy2": self.customs.contour["xy2"], - } - ) - hatch = HatchArea(payload) - hatch("grid") - if self.customs.contour["hatch_mask"]: - payload.update( - { - "data": [ - self.data[0], - self.data[1], - self.customs.contour["mask"], - ], - } - ) - hatch = HatchArea(payload) - hatch("mask") - self.axes_labels["show_legend"] = False - self.label_axes() - - def basemap(self): - """Plot a base map. This method uses the basemap customs. The customs are - - Optional Keys: - - proj: the projection of the map, default is "ortho" - - draw_coastlines: whether to draw coastlines, default is True - - fillcontinents: whether to fill continents, default is False - - draw_countries: whether to draw countries, default is False - - draw_states: whether to draw states, default is False - - draw_rivers: whether to draw rivers, default is False - - bluemarble: whether to use the bluemarble map, default is False - - shaderelief: whether to use the shaded relief map, default is False - - draw_parallels: whether to draw parallels, default is False - - draw_meridians: whether to draw meridians, default is False - """ - map_ = Basemap(projection=self.customs.basemap["proj"], lat_0=0, lon_0=0) - - basemap_methods = { - "draw_coastlines": map_.drawcoastlines, - "fillcontinents": map_.fillcontinents, - "draw_countries": map_.drawcountries, - "draw_states": map_.drawstates, - "draw_rivers": map_.drawrivers, - "bluemarble": map_.bluemarble, - "shaderelief": map_.shadedrelief, - "draw_parallels": lambda: map_.drawparallels(np.arange(-90, 90, 30)), - "draw_meridians": lambda: map_.drawmeridians(np.arange(0, 360, 60)), - } - - for key, method in basemap_methods.items(): - if self.customs.basemap.get(key): - method() - - self.axes_labels["show_legend"] = False - self.label_axes() - - -class Multiplots(Plot): - """Class to plot multiple subplots on the same graph. - - :param dict args: the master dictionary containing the required fields. - - Required Keys: - - super_title: the title of the main figure - - super_xlabel: the x-axis label of the main figure - - super_ylabel: the y-axis label of the main figure - - share_axes: whether to share the axes of the subplots - - **Example** - - >>> args = { - ... "super_title": "Test Title", - ... "super_xlabel": "Test X Label", - ... "super_ylabel": "Test Y Label", - ... "share_axes": False, - ... } - >>> multiplot = Multiplots(args) - >>> multiplot.share_axes - False - """ - - def __init__(self, args): - """Initialize the Multiplot Class.""" - # Turn off interactive mode - plt.ioff() - - # Initialize the Plot Class - super().__init__({"data": [], "display": False}) - - # Extract Graph labels - self.super_title = args.get("super_title", " ") - self.super_xlabel = args.get("super_xlabel", " ") - self.super_ylabel = args.get("super_ylabel", " ") - self.share_axes = args.get("share_axes", True) - - # Set the subplot count - self.subplot_count = 0 - - # Define the various graphing functions - self.graphs = { - "cdf": self.cdf, - "density": self.density, - "histogram": self.histogram, - "boxplot": self.boxplot, - "probability_plot": self.probability_plot, - "line_plot": self.line_plot, - "contour": self.contour, - "normal_cdf": self.normal_cdf, - "basemap": self.basemap, - } - - self.subplots = [] - self.current_subplot = [] - - def overlay(self, overlay_args): - """Overlay new plot onto current subplot. - - :param dict overlay_args: Master dictionary of all inputs - - Required Keys: - - plot: The graph name. - - data: The data to plot onto the graph - - axes_labels: The axes labels - - *Optional Keys*: - customs: The plot's customization. - """ - plot = overlay_args.get("plot") - data = overlay_args.get("data") - axes_labels = overlay_args.get("axes_labels") - customs = overlay_args.get("customs", {}) - - self.current_subplot.append([plot, data, axes_labels, customs]) - - def new_subplot(self): - """Create new subplot with current overlays""" - # Increment the number of subplots already plotted - self.subplot_count += 1 - if len(self.current_subplot) > 0: - # Add all current overlays to a subplot - self.subplots.append(self.current_subplot) - - # Reset current subplot - self.current_subplot = [] - - def __call__(self): - """Build the main figure, label its axes and display the result. - - **Usage** - - >>> args = { - ... "super_title": "Test Title", - ... "super_xlabel": "Test X Label", - ... "super_ylabel": "Test Y Label", - ... "share_axes": False, - ... } - >>> multiplot = Multiplots(args) - >>> multiplot.new_subplot() - >>> overlay_args = { - ... "plot": "cdf", - ... "data": [1, 2, 3, 4, 5], - ... "axes_labels": {"title": "CDF Plot", "xlabel": "X", "ylabel": "Y"}, - ... } - >>> multiplot.overlay(overlay_args) - >>> multiplot() - """ - # Collect and Store remaining overlays - self.subplots.append(self.current_subplot) - # reset current overlay - self.current_subplot = [] - - # Set Up the Figure and Num of Rows and Columns - self.fig = plt.figure(figsize=(20, 8)) - rows, cols = self.tiling(self.subplot_count) - ax1 = None - - # Add subplots - for idx, subplot in enumerate(self.subplots): - if idx == 0: - ax = self.fig.add_subplot(rows, cols, idx + 1) - ax1 = ax - else: - if self.share_axes: - ax = self.fig.add_subplot(rows, cols, idx + 1, sharey=ax1) - else: - ax = self.fig.add_subplot(rows, cols, idx + 1) - for overlay in subplot: - plot_name = overlay[0] - self.ax, self.data = ax, overlay[1] - - # Update the axes labels - self.update_defaults("axes_labels", overlay[2]) - - # Update the plot's defaults - self.update_defaults(plot_name, overlay[3]) - - # Plot the graph - try: - self.graphs[plot_name]() - except Exception: - self.clear_axis() - raise - - # Add super titles - self.fig.suptitle(self.super_title) - self.fig.supxlabel(self.super_xlabel) - self.fig.supylabel(self.super_ylabel) - self.fig.tight_layout() - plt.show() - - # Reset Canvas - self.clear_axis() - - def clear_axis(self): - """Reset Subplot Trackers.""" - self.subplot_count = 0 - self.subplots = [] - - def tiling(self, num): - """Calculates the number of rows and columns for the subplot. - - :param int num: the number of subplots - :return: the number of rows and columns - :rtype: tuple - """ - if num < 5: - return 1, num - else: - root = int(math.isqrt(num)) - if num == root**2: - return root, root - else: - col = root + 1 - del_row = (col**2 - num) // col - row = col - del_row - return row, col - - -class PlotUtilities: - """Class containing auxillary utility functions for plotting. - - **Usage** - - >>> util = PlottingUtilities() - """ - - def standardize_dataset(self, data: list) -> np.ndarray: - """Standardize a dataset by subtracting the mean and dividing the std - of the dataset from each value. - - :param list data: the data list - :return: standardized data - :rtype: ndarray - """ - # Convert the Data Into an array - data = np.array(data) - - # Find the stats on the data - mu = np.mean(data) - sigma = np.std(data) - - # Return the standardized data - return (data - mu) / sigma - - -class CustomizePlot: - """Class to customize the appearance of a map. - - **Usage** - - >>> cmap = CustomizePlot() - """ - - def __init__(self, customs): - """Initialize the CustomizeMap Class.""" - self.customs = customs - self._line_plot = {"color": "navy", "linestyle": "solid"} - self._cdf = {"color": "dogerblue"} - self._density = {"color": "red", "fill": False, "label": " "} - self._boxplot = {"showfliers": True} - self._histogram = {"num_bins": 20, "color": "plum", "ran": None} - self._probability_plot = {"color": "orangered"} - self._normal_cdf = {} - self._contour = { - "filled": False, - "colors": None, - "inline": True, - "fsize": 9, - "cmap": "viridis", - "hatch": False, - "hatch_color": "black", - "hatch_alpha": 0, - "hatch_fill": True, - "pattern": "..", - "xy1": (0, 0), - "xy2": (1, 1), - "hatch_grid": False, - "hatch_mask": False, - "mask": None, - } - self._basemap = { - "proj": "ortho", - "draw_coastlines": True, - "fillcontinents": False, - "draw_countries": False, - "draw_states": False, - "draw_rivers": False, - "bluemarble": False, - "shaderelief": False, - "draw_parallels": False, - "draw_meridians": False, - } - - @property - def line_plot(self): - """Customize the line plot.""" - self._line_plot.update(self.customs.get("line_plot", {})) - return self._line_plot - - @property - def cdf(self): - """Customize the cdf plot.""" - self._cdf.update(self.customs.get("cdf", {})) - return self._cdf - - @property - def density(self): - """Customize the density plot.""" - self._density.update(self.customs.get("density", {})) - return self._density - - @property - def boxplot(self): - """Customize the boxplot.""" - self._boxplot.update(self.customs.get("boxplot", {})) - return self._boxplot - - @property - def histogram(self): - """Customize the histogram.""" - self._histogram.update(self.customs.get("histogram", {})) - return self._histogram - - @property - def probability_plot(self): - """Customize the probability plot.""" - self._probability_plot.update(self.customs.get("probability_plot", {})) - return self._probability_plot - - @property - def normal_cdf(self): - """Customize the normal cdf plot.""" - self._normal_cdf.update(self.customs.get("normal_cdf", {})) - return self._normal_cdf - - @property - def contour(self): - """Customize the contour plot.""" - self._contour.update(self.customs.get("contour", {})) - return self._contour - - @property - def basemap(self): - """Customize the basemap.""" - self._basemap.update(self.customs.get("basemap", {})) - return self._basemap - - -class HatchArea: - """Class to hatch the area between two points.""" - - def __init__(self, args): - """Initialize the HatchArea Class.""" - self.args = args - self.xy1 = self.args.get("xy1", (0, 0)) - self.xy2 = self.args.get("xy2", (1, 1)) - self.ax = self.args.get("ax") - self.pattern = self.args.get("pattern", "..") - self.color = self.args.get("color", "black") - self.alpha = self.args.get("alpha", 0.2) - self.fill = self.args.get("fill", True) - self.data = self.args.get("data", None) - - def __call__(self, func): - """Hatch the area between two points.""" - if func == "grid": - x = self.xy1[0] - y = self.xy1[1] - width = self.xy2[0] - self.xy1[0] - height = self.xy2[1] - self.xy1[1] - - self.ax.add_patch( - Rectangle( - (x, y), - width, - height, - fill=self.fill, - color=self.color, - alpha=self.alpha, - hatch=self.pattern, - ) - ) - if func == "mask": - assert self.data is not None, "Data must be provided" - self.ax.contourf( - self.data[0], - self.data[1], - self.data[2], - [0.5, 1], - hatches=[self.pattern], - alpha=self.alpha, - ) diff --git a/src/tests/test_chartly.py b/src/tests/test_chartly.py deleted file mode 100644 index 5bb2c2e..0000000 --- a/src/tests/test_chartly.py +++ /dev/null @@ -1,139 +0,0 @@ -"""Test plotting module. - -:author: C.O. Mbengue [#]_, - A.M.E. Popo [#]_ - -:organization: Elizabeth Consulting International Inc. [#]_ - -.. [#] Cheikh Oumar Mbengue, Research Scientist, cmbengue@ec-intl.com -.. [#] Azendae Marie-Ange Elizabeth Popo, Research Assistant, apopo@ec-intl.com -.. [#] Elizabeth Consulting International Inc. (ECI) is a private company that - specializes in the development of decision support systems for the - private sector. ECI is based in St. Lucia, West Indies. - -""" - -import unittest - -import numpy as np - -from chartly.chartly import Multiplots, Plot, PlotUtilities - - -class TestPlotting(unittest.TestCase): - """Test the plotting module.""" - - def setUp(self): - """Set up the test class.""" - self.util = PlotUtilities() - - # Create a data list - self.dataset_one = np.random.randint(50, size=(20)) - self.dataset_two = np.random.randint(50, size=(20)) - self.data = [self.dataset_one, self.dataset_two] - - # Create a dictionary of arguments - args = {"display": False, "data": self.data} - - # Create a plot object - self.plot = Plot(args) - - # Create a dictionary of multiplot arguments - args = { - "super_title": " Test Title", - "super_x_label": "Test X Label", - "super_y_label": "Test Y Label", - } - # Create a multiplot object - self.multiplot = Multiplots(args) - - def test_gen_plot_data_type(self): - """Test that the generic plot can use both a 1D and 2D list of data.""" - # Test 1D data - self.plot.data = self.dataset_one - self.assertIsNone(self.plot.line_plot()) - - # Test 2D data - self.plot.data = self.data - self.assertIsNone(self.plot.line_plot()) - - def test_gen_plot_data_length(self): - """Test that the generic plot throws an error if the data lengths are unequal.""" - self.plot.data = [self.dataset_one, self.dataset_two[:-1]] - with self.assertRaises(AssertionError): - self.plot.line_plot() - - def test_standardize_data(self): - """Test that the data is standardized correctly.""" - data = [val for val in range(10, 100, 20)] - expected_std_data = [-1.4, -0.7, 0, 0.7, 1.4] - std_data = [np.round(val, 1) for val in self.util.standardize_dataset(data)] - self.assertEqual(std_data, expected_std_data) - - def test_mutli_subplot_count(self): - """Test that the multiplot object can handle multiple subplots.""" - # Test that initial subplot count is 0 - self.assertEqual(self.multiplot.subplot_count, 0) - - # Create a new subplot - self.multiplot.new_subplot() - - # Test that the subplot count is now 1 - self.assertEqual(self.multiplot.subplot_count, 1) - - # Reset the subplot count - self.multiplot.clear_axis() - - def test_multi_clear_axis(self): - """Test that the multiplot object can clear the axis.""" - # Create a new subplot - self.multiplot.new_subplot() - - # Test that the subplot count is now 1 - self.assertEqual(self.multiplot.subplot_count, 1) - - # Clear the axis - self.multiplot.clear_axis() - - # Test that the subplot count is now 0 - self.assertEqual(self.multiplot.subplot_count, 0) - - def test_contour_data_length(self): - """Test that the contour plot throws an error if the data lengths are unequal.""" - # Test that the contour plot throws an error when a user does not send 3 datasets - self.plot.data = [self.dataset_one, self.dataset_two] - with self.assertRaises(AssertionError): - self.plot.contour() - - # test that the contour plot does not throw an error when a user sends 3 datasets - X, Y = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100)) - Z = np.sin(X) * np.cos(Y) - self.plot.data = [X, Y, Z] - self.assertIsNone(self.plot.contour()) - - # Test that the contour plot throws an error when the data sets are not 2D - self.plot.data = [X, Y, Z[0]] - with self.assertRaises(AssertionError): - self.plot.contour() - - def test_default(self): - """Test that the default plot is created correctly.""" - # Test that the default plot is created correctly - gen_args = {"color": "pink"} - args = { - "data": self.data, - "line_plot": gen_args, - "display": False, - } - plot_two = Plot(args) - expect = {"color": "pink", "linestyle": "solid"} - self.assertEqual(plot_two.customs.line_plot, expect) - - # Test that the customs are updated correctly - plot_two.update_defaults("line_plot", {"color": "blue"}) - expect = {"color": "blue", "linestyle": "solid"} - self.assertEqual(plot_two.customs.line_plot, expect) - - -if __name__ == "__main__": - unittest.main() From 2e814ba9f2d852c15225751244a9bdf0e3e0b53a Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Mon, 28 Oct 2024 14:20:24 -0400 Subject: [PATCH 24/29] update requirements --- requirements.txt | 1 - requirements/production.txt | 1 - requirements/staging.txt | 1 - requirements/testing.txt | 1 - 4 files changed, 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 4f8e534..bd84b7d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,6 @@ basemap==1.4.1 cloud-sptheme==1.10.1.post20200504175005 matplotlib==3.9.1 -mpl_toolkits==1.3.0 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 diff --git a/requirements/production.txt b/requirements/production.txt index 9460fcf..421dbc9 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -1,7 +1,6 @@ basemap==1.4.1 cloud-sptheme==1.10.1.post20200504175005 matplotlib==3.9.1 -mpl_toolkits==1.3.0 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 diff --git a/requirements/staging.txt b/requirements/staging.txt index 9460fcf..421dbc9 100644 --- a/requirements/staging.txt +++ b/requirements/staging.txt @@ -1,7 +1,6 @@ basemap==1.4.1 cloud-sptheme==1.10.1.post20200504175005 matplotlib==3.9.1 -mpl_toolkits==1.3.0 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 diff --git a/requirements/testing.txt b/requirements/testing.txt index 9460fcf..421dbc9 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -1,7 +1,6 @@ basemap==1.4.1 cloud-sptheme==1.10.1.post20200504175005 matplotlib==3.9.1 -mpl_toolkits==1.3.0 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 From 43ee21a47469a731d4a7bbe58b3bf5e4fc830535 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Mon, 28 Oct 2024 14:24:59 -0400 Subject: [PATCH 25/29] update requirement file --- requirements.txt | 4 ++-- requirements/production.txt | 2 +- requirements/staging.txt | 2 +- requirements/testing.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements.txt b/requirements.txt index bd84b7d..c76119b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -basemap==1.4.1 +basemap cloud-sptheme==1.10.1.post20200504175005 -matplotlib==3.9.1 +matplotlib==3.8.4 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 diff --git a/requirements/production.txt b/requirements/production.txt index 421dbc9..bae7fef 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -1,6 +1,6 @@ basemap==1.4.1 cloud-sptheme==1.10.1.post20200504175005 -matplotlib==3.9.1 +matplotlib==3.8.4 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 diff --git a/requirements/staging.txt b/requirements/staging.txt index 421dbc9..bae7fef 100644 --- a/requirements/staging.txt +++ b/requirements/staging.txt @@ -1,6 +1,6 @@ basemap==1.4.1 cloud-sptheme==1.10.1.post20200504175005 -matplotlib==3.9.1 +matplotlib==3.8.4 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 diff --git a/requirements/testing.txt b/requirements/testing.txt index 421dbc9..bae7fef 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -1,6 +1,6 @@ basemap==1.4.1 cloud-sptheme==1.10.1.post20200504175005 -matplotlib==3.9.1 +matplotlib==3.8.4 numpy==1.26.4 pytest==8.3.2 pytest-cov==5.0.0 From b33b0a73aac04f579c48df3c49c290659eb3b296 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Mon, 28 Oct 2024 14:32:33 -0400 Subject: [PATCH 26/29] linting --- chartly/charts.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/chartly/charts.py b/chartly/charts.py index 7e85edf..8bd92b1 100644 --- a/chartly/charts.py +++ b/chartly/charts.py @@ -616,6 +616,7 @@ def __call__(self): alpha=self.customs["alpha"], ) + class Basemap(Plot, CustomizePlot): """Class to plot a basemap. @@ -627,7 +628,7 @@ class Basemap(Plot, CustomizePlot): Optional Keys - customs: the plot's customization - axes_labels: the axes labels - + Available Customizations: - proj: the projection of the map, default is "ortho" - draw_coastlines: whether to draw coastlines, default is True @@ -642,13 +643,17 @@ class Basemap(Plot, CustomizePlot): """ def __init__(self, args): - """Initialize the Contour Class.""" - # Get the arguments + """Initialize the Basemap Class.""" + # Get the basemap arguments self.args = args # Extract the customs customs_ = self.args.get("customs", {}) + + # Initialize the Plot Class super().__init__(self.args) + + # Initialize the CustomizePlot Class CustomizePlot.__init__(self, customs_) def defaults(self): From 55f409ed5faf0b8f42f18619eb50c283023070d5 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Mon, 28 Oct 2024 15:23:03 -0400 Subject: [PATCH 27/29] Add Contour Plot and Hatching to basemap --- chartly/charts.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/chartly/charts.py b/chartly/charts.py index 8bd92b1..1937dfa 100644 --- a/chartly/charts.py +++ b/chartly/charts.py @@ -668,6 +668,12 @@ def defaults(self): "shaderelief": False, "draw_parallels": False, "draw_meridians": False, + "contour": False, + "contourf": False, + "hatch": False, + "hatch_customs": {}, + "mask": None, + "contour_customs": {}, } def __call__(self): @@ -690,5 +696,26 @@ def __call__(self): if self.customs.get(key): method() + # vAdd Contour or filled contour + for contour_type in ["contour", "contourf"]: + if self.customs.get(contour_type): + cs = getattr(map_, contour_type)( + self.data[0], + self.data[1], + self.data[2], + ) + + # Add Contour Hatch + if self.customs.get("hatch"): + self.customs["hatch_customs"].update({"ax": map_}) + if self.customs["hatch_customs"]["type"] == "mask": + self.customs["hatch_customs"]["data"] = [ + self.data[0], + self.data[1], + self.customs["mask"], + ] + hatch = HatchArea(self.customs["hatch_customs"]) + hatch() + self.axes_labels["show_legend"] = False self.label_axes() From 542aa3f4a86e9c742a091093b19c64b2c8c46422 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Tue, 29 Oct 2024 08:11:50 -0400 Subject: [PATCH 28/29] Adds annotations class to basemap --- chartly/charts.py | 71 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/chartly/charts.py b/chartly/charts.py index 1937dfa..c044a2f 100644 --- a/chartly/charts.py +++ b/chartly/charts.py @@ -674,11 +674,21 @@ def defaults(self): "hatch_customs": {}, "mask": None, "contour_customs": {}, + "annotation": False, + "annotation_customs": {}, } def __call__(self): """Plot a basemap.""" - map_ = bmap(projection=self.customs["proj"], lat_0=0, lon_0=0) + map_ = bmap( + projection=self.customs["proj"], + lat_0=0, + lon_0=0, + llcrnrlon=-180, + llcrnrlat=-60, # Lower-left corner coordinates + urcrnrlon=180, + urcrnrlat=85, + ) basemap_methods = { "draw_coastlines": map_.drawcoastlines, @@ -717,5 +727,64 @@ def __call__(self): hatch = HatchArea(self.customs["hatch_customs"]) hatch() + # Add Annotations + if self.customs.get("annotation"): + annotate = AnnotateBasemap(self.customs["annotation_customs"]) + annotate() + self.axes_labels["show_legend"] = False self.label_axes() + + +class AnnotateBasemap(CustomizePlot): + """Class to annotate a basemap.""" + + def __init__(self, args): + """Initialize the AnnotateBasemap Class.""" + # Get the basemap arguments + self.args = args + + # Extract the customs + customs_ = self.args.get("customs", {}) + + # Initialize the CustomizePlot Class + super().__init__(self.args) + + def defaults(self): + return { + "text": None, + "xy": None, + "xytext": None, + "arrowprops": None, + "fontsize": 12, + "color": "black", + } + + def __call__(self): + """Annotate a basemap.""" + assert self.customs["xy"] is not None, "xy positions must be provided" + + if self.customs["xytext"] is not None: + assert len(self.customs["xy"]) == len( + self.customs["xytext"] + ), "xy positions and xytext positions must be of the same length" + + for idx in range(len(self.customs["xy"])): + self.ax.annotate( + self.customs["text"][idx], + xy=self.customs["xy"][idx], + xytext=self.customs["xytext"][idx], + arrowprops=self.customs["arrowprops"], + fontsize=self.customs["fontsize"], + color=self.customs["color"], + ) + + else: + for idx in range(len(self.customs["xy"])): + self.ax.annotate( + self.customs["text"][idx], + xy=self.customs["xy"][idx], + arrowprops=self.customs["arrowprops"], + fontsize=self.customs["fontsize"], + color=self.customs["color"], + ) From 500744840f3e3295c6bb70e78b30c1f4ebe5d225 Mon Sep 17 00:00:00 2001 From: Azendae Popo Date: Tue, 29 Oct 2024 09:06:02 -0400 Subject: [PATCH 29/29] WIP --- chartly/charts.py | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/chartly/charts.py b/chartly/charts.py index c044a2f..0ec96a7 100644 --- a/chartly/charts.py +++ b/chartly/charts.py @@ -674,21 +674,13 @@ def defaults(self): "hatch_customs": {}, "mask": None, "contour_customs": {}, - "annotation": False, - "annotation_customs": {}, + "annotate": False, + "annotate_customs": {}, } def __call__(self): """Plot a basemap.""" - map_ = bmap( - projection=self.customs["proj"], - lat_0=0, - lon_0=0, - llcrnrlon=-180, - llcrnrlat=-60, # Lower-left corner coordinates - urcrnrlon=180, - urcrnrlat=85, - ) + map_ = bmap(projection=self.customs["proj"], lat_0=0, lon_0=0) basemap_methods = { "draw_coastlines": map_.drawcoastlines, @@ -728,8 +720,9 @@ def __call__(self): hatch() # Add Annotations - if self.customs.get("annotation"): - annotate = AnnotateBasemap(self.customs["annotation_customs"]) + if self.customs.get("annotate"): + self.customs["annotate_customs"].update({"ax": self.ax, "map": map_}) + annotate = AnnotateBasemap(self.customs["annotate_customs"]) annotate() self.axes_labels["show_legend"] = False @@ -752,6 +745,8 @@ def __init__(self, args): def defaults(self): return { + "ax": None, + "map": None, "text": None, "xy": None, "xytext": None, @@ -764,16 +759,19 @@ def __call__(self): """Annotate a basemap.""" assert self.customs["xy"] is not None, "xy positions must be provided" + map_ = self.customs["map"] + ax = self.customs["ax"] + if self.customs["xytext"] is not None: assert len(self.customs["xy"]) == len( self.customs["xytext"] ), "xy positions and xytext positions must be of the same length" for idx in range(len(self.customs["xy"])): - self.ax.annotate( + ax.annotate( self.customs["text"][idx], - xy=self.customs["xy"][idx], - xytext=self.customs["xytext"][idx], + xy=map_(*self.customs["xy"][idx]), + xytext=map_(*self.customs["xytext"][idx]), arrowprops=self.customs["arrowprops"], fontsize=self.customs["fontsize"], color=self.customs["color"], @@ -781,9 +779,9 @@ def __call__(self): else: for idx in range(len(self.customs["xy"])): - self.ax.annotate( + ax.annotate( self.customs["text"][idx], - xy=self.customs["xy"][idx], + xy=map_(*self.customs["xy"][idx]), arrowprops=self.customs["arrowprops"], fontsize=self.customs["fontsize"], color=self.customs["color"],