From ed7d180451d1b76da3f6fd6e1740f9bcc725b980 Mon Sep 17 00:00:00 2001 From: Julie Prestopnik Date: Mon, 9 Jun 2025 10:33:28 -0600 Subject: [PATCH 01/15] Feature METplus2857 main v3.1 support (#512) * Making index consistent with other METplus repositories * Initial commit of overview --- docs/Users_Guide/index.rst | 3 +- docs/Users_Guide/overview.rst | 55 +++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 docs/Users_Guide/overview.rst diff --git a/docs/Users_Guide/index.rst b/docs/Users_Guide/index.rst index 1cc0cbf92..9b2730acf 100644 --- a/docs/Users_Guide/index.rst +++ b/docs/Users_Guide/index.rst @@ -65,6 +65,8 @@ Atmospheric Research (NCAR), sponsored by National Science Foundation. :titlesonly: :numbered: 4 + overview + release-notes installation line box @@ -94,7 +96,6 @@ Atmospheric Research (NCAR), sponsored by National Science Foundation. fv3_physics tcmpr_plots scatter - release-notes references diff --git a/docs/Users_Guide/overview.rst b/docs/Users_Guide/overview.rst new file mode 100644 index 000000000..0365ac52e --- /dev/null +++ b/docs/Users_Guide/overview.rst @@ -0,0 +1,55 @@ +******** +Overview +******** + +Purpose and Organization of the User's Guide +============================================ + +The goal of this User’s Guide is to provide basic information for users of +METplotpy. METplotpy is a Python-based plotting library designed to generate +a wide range of diagnostic and verification visualizations. It helps users +interpret verification statistics through meaningful plots, making it easier +to evaluate forecast performance and model behavior. + +The METplotpy User's Guide is organized as follows. An overview of METplotpy +can be found below. The guide also includes information about how to create +a variety of plots and diagrams including, for example but not limited to, +box plots, bar plots, performance diagrams, reliability diagrams, and more. + +The Developmental Testbed Center (DTC) +====================================== + +METplotpy has been developed, and will be maintained and enhanced, by the +Developmental Testbed Center (DTC; http://www.dtcenter.org/ ). +The main goal of the DTC is to serve as a bridge between operations and +research, to facilitate the activities of these two important components of +the numerical weather prediction (NWP) community. The DTC provides an +environment that is functionally equivalent to the operational environment +in which the research community can test model enhancements; the operational +community benefits from DTC testing and evaluation of models before new models +are implemented operationally. METplotpy serves both the research and +operational communities in this way - offering capabilities for researchers +to test their own enhancements to models and providing a capability for +the DTC to evaluate the strengths and weaknesses of advances in NWP +prior to operational implementation. + +METplotpy will also be available to DTC visitors and to the modeling community +for testing and evaluation of new model capabilities, applications in new +environments, and so on. + +Future Development Plans +======================== + +METplotpy is an evolving software package. New capabilities are planned in +controlled, successive version releases. Bug fixes and user-identified +problems will be addressed as they are found. Plans are also in place to +incorporate new capabilities and options in future releases of METplotpy. + +User Support +============ + +METplotpy is one component of the larger METplus system for which user support +is provided through the +`METplus GitHub Discussions Forum `_, +as described in the +`METplus User's Guide `_. From 69c28d14f43295987a6a3b1f4b395da2db6c4360 Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Mon, 9 Jun 2025 10:59:24 -0600 Subject: [PATCH 02/15] Per #515, remove deprecated import (#516) --- .../contributed/stratosphere_diagnostics/stratosphere_plots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metplotpy/contributed/stratosphere_diagnostics/stratosphere_plots.py b/metplotpy/contributed/stratosphere_diagnostics/stratosphere_plots.py index d95099c3c..d6da90892 100644 --- a/metplotpy/contributed/stratosphere_diagnostics/stratosphere_plots.py +++ b/metplotpy/contributed/stratosphere_diagnostics/stratosphere_plots.py @@ -109,7 +109,7 @@ def plot_qbo_phase_circuits(inits,periods,rean_qbo_pcs,rfcst_qbo_pcs,outfile): def plot_qbo_phase_space(rean_qbo_pcs,eofs,ptitle,outfile): - from mpl_toolkits.axes_grid1.inset_locator import (inset_axes, InsetPosition, mark_inset) + from mpl_toolkits.axes_grid1.inset_locator import (inset_axes, mark_inset) fig = plt.figure(4) From 6239d5a43f6de3ec631bbae0652355078ede87d5 Mon Sep 17 00:00:00 2001 From: MWin <3753118+bikegeek@users.noreply.github.com> Date: Fri, 27 Jun 2025 14:53:41 -0600 Subject: [PATCH 03/15] Update base_plot.py comment out the pio.kaleido.scope line, this is now causing tests to fail due to kaleido warning for deprecations in September 2025 --- metplotpy/plots/base_plot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metplotpy/plots/base_plot.py b/metplotpy/plots/base_plot.py index 4897c0f0e..27d68a74b 100644 --- a/metplotpy/plots/base_plot.py +++ b/metplotpy/plots/base_plot.py @@ -28,7 +28,7 @@ from metplotpy.plots.context_filter import ContextFilter # set kaleido to use single process to prevent GPU errors in containers -pio.kaleido.scope.chromium_args += ("--single-process",) +# pio.kaleido.scope.chromium_args += ("--single-process",) class BasePlot: """A class that provides methods for building Plotly plot's common features From 4dedb9f90e544f83f1b6bff2940ee1d7f759ee55 Mon Sep 17 00:00:00 2001 From: MWin <3753118+bikegeek@users.noreply.github.com> Date: Fri, 27 Jun 2025 17:31:05 -0600 Subject: [PATCH 04/15] Update base_plot.py backing out the latest from pio.kaleido line. WARNING: GHA tests may fail due to upcoming deprecation and warnings that emanate due to Python 3.12 still features that will be deprecated. --- metplotpy/plots/base_plot.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/metplotpy/plots/base_plot.py b/metplotpy/plots/base_plot.py index 27d68a74b..e1001edbc 100644 --- a/metplotpy/plots/base_plot.py +++ b/metplotpy/plots/base_plot.py @@ -28,7 +28,8 @@ from metplotpy.plots.context_filter import ContextFilter # set kaleido to use single process to prevent GPU errors in containers -# pio.kaleido.scope.chromium_args += ("--single-process",) +# NOTE: this may result in GHA tests failing due to impending deprecations in kaleido +pio.kaleido.scope.chromium_args += ("--single-process",) class BasePlot: """A class that provides methods for building Plotly plot's common features From 0b165a254d0465342ac5a465f62b0377c3d278a1 Mon Sep 17 00:00:00 2001 From: MWin <3753118+bikegeek@users.noreply.github.com> Date: Fri, 27 Jun 2025 18:20:43 -0600 Subject: [PATCH 05/15] Update test_scatter.py Tests pass outside of GHA. Something in GHA is causing issues with Python 3.12 and kaleido (causes AssertionError in kaleido) --- test/scatter/test_scatter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/scatter/test_scatter.py b/test/scatter/test_scatter.py index aee0593f4..e232dd3d9 100644 --- a/test/scatter/test_scatter.py +++ b/test/scatter/test_scatter.py @@ -23,6 +23,7 @@ def read_config(config_filename) -> dict: return parms except yaml.YAMLError as exc: print(exc) +@pytest.mark.skip("Skipping until GHA issue with Python 3.12 and kaleido are resolved") def test_files_exist(): """ Generate a scatter plot from reformatted MPR Usecase data and From 5dbd1be005a157f9c99a5e5607ef7d5ea64b8ba9 Mon Sep 17 00:00:00 2001 From: bikegeek Date: Sat, 28 Jun 2025 19:18:26 -0600 Subject: [PATCH 06/15] Updates for coordinated release --- docs/Users_Guide/release-notes.rst | 50 ++++-------------------------- docs/conf.py | 6 ++-- 2 files changed, 9 insertions(+), 47 deletions(-) diff --git a/docs/Users_Guide/release-notes.rst b/docs/Users_Guide/release-notes.rst index 21b271caf..a67911faa 100644 --- a/docs/Users_Guide/release-notes.rst +++ b/docs/Users_Guide/release-notes.rst @@ -7,7 +7,7 @@ describes the bugfix, enhancement, or new feature: `METplotpy GitHub issues. `_ -METplotpy Version 3.1.0-rc1 release notes (20250522) +METplotpy Version 3.1.0 release notes (20250701) ==================================================== .. dropdown:: New Plots @@ -23,66 +23,28 @@ METplotpy Version 3.1.0-rc1 release notes (20250522) .. dropdown:: Bugfixes - None - -.. dropdown:: Documentation - - * Documentation: TCMPR filtering (`#507 `_) - -.. dropdown:: Repository, build, and test - - None - -METplotpy Version 3.1.0-beta2 release notes (20250331) -====================================================== - -.. dropdown:: New Plots - - None - -.. dropdown:: Enhancements - - None - -.. dropdown:: Bugfixes - + * Make default configs available in package (`#476 `_) + * Import from metplotpy.contributed instead of relative import (`#478 `_) * Series names in legend don't get ordered correctly (`#347 `_) * Support various formats of show_legend values (`#482 `_) * Reliability Diagram show_legend setting should work with True/False rather than 1/0 values; see bugfix #482 (`#455 `_) * Better handling of determining min and max for confidence limits when data contains NaN values (`#494 `_) * Plotly line plots are plotting confidence limit bars at zero with zero length error bars (`#495 `_) + + .. dropdown:: Documentation * Enhance METplotpy User's Guide Installation Instructions (`#457 `_) * Provide more background information on the Taylor Diagram (`#435 `_) * Enhance the Table of Contents to include all METplus components (`#499 `_) + * Documentation: TCMPR filtering (`#507 `_) .. dropdown:: Repository, build, and test * Update infrastructure to reflect move to developing with Python 3.12 (`#496 `_) * Update modulefiles used on various machines (`#488 `_) -METplotpy Version 3.1.0-beta1 release notes (20250123) -====================================================== - -.. dropdown:: New Plots - - None - -.. dropdown:: Enhancements - - None - -.. dropdown:: Bugfixes - - * Make default configs available in package (`#476 `_) - * Import from metplotpy.contributed instead of relative import (`#478 `_) - -.. dropdown:: Documentation - - None - METplotpy Upgrade Instructions ============================== diff --git a/docs/conf.py b/docs/conf.py index d1a976ad8..deef4f30c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -24,13 +24,13 @@ project = 'METplotpy' copyright = '2025, NSF NCAR' author = 'UCAR/NSF NCAR, NOAA, CSU/CIRA, and CU/CIRES' -author_list = 'Fisher, H., D. Adriaansen, C. Kalb, D. Fillmore, T. Jensen, L. Goodrich, M. Win-Gildenmeister and T. Burek' -version = '3.1.0-rc1' +author_list = 'Adriaansen, D., C. Kalb, D. Fillmore, T. Jensen, L. Goodrich, M. Win-Gildenmeister, T. Burek, and H. Fisher' +version = '3.1.0' verinfo = version release = f'{version}' release_year = '2025' -release_date = f'{release_year}-05-22' +release_date = f'{release_year}-07-01' copyright = f'{release_year}, {author}' From 3998c648270a1d6e1943af35430fb2e47cabbcfd Mon Sep 17 00:00:00 2001 From: jprestop Date: Mon, 7 Jul 2025 14:55:04 -0600 Subject: [PATCH 07/15] Adding modulefile for new machine ursa --- .../installation/modulefiles/3.1.0_ursa | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 internal/scripts/installation/modulefiles/3.1.0_ursa diff --git a/internal/scripts/installation/modulefiles/3.1.0_ursa b/internal/scripts/installation/modulefiles/3.1.0_ursa new file mode 100644 index 000000000..9ffb356e9 --- /dev/null +++ b/internal/scripts/installation/modulefiles/3.1.0_ursa @@ -0,0 +1,25 @@ +#%Module###################################################################### +## +## METplotpy +## +proc ModulesHelp { } { + puts stderr "Sets up the paths and environment variables to use the METplotpy-3.1.0. + *** For help see the official MET webpage at http://www.dtcenter.org/met/users ***" +} + +prereq intel-oneapi-compilers/2025.1.1 + +setenv METPLOTPY_SOURCE /contrib/METplotpy/METplotpy-3.1.0 +setenv METPLOTPY_BASE /contrib/METplotpy/METplotpy-3.1.0 + +prepend-path PATH /scratch3/BMC/dtc/METplus/miniconda/miniconda3/envs/metplus_v6.1_py3.12/bin +prepend-path PATH /contrib/METplotpy/METplotpy-3.1.0/metplotpy/contributed +prepend-path PATH /contrib/METplotpy/METplotpy-3.1.0/metplotpy/plots/performance_diagram +prepend-path PATH /contrib/METplotpy/METplotpy-3.1.0/metplotpy/plots +prepend-path PATH /contrib/METplotpy/METplotpy-3.1.0/metplotpy +prepend-path PATH /contrib/METplotpy/METplotpy-3.1.0 +prepend-path PYTHONPATH /contrib/METplotpy/METplotpy-3.1.0/metplotpy/contributed +prepend-path PYTHONPATH /contrib/METplotpy/METplotpy-3.1.0/metplotpy/plots/performance_diagram +prepend-path PYTHONPATH /contrib/METplotpy/METplotpy-3.1.0/metplotpy/plots +prepend-path PYTHONPATH /contrib/METplotpy/METplotpy-3.1.0/metplotpy +prepend-path PYTHONPATH /contrib/METplotpy/METplotpy-3.1.0 From e2e52b7f94aa39f6bc679b06c7b3b232c26d07cc Mon Sep 17 00:00:00 2001 From: MWin <3753118+bikegeek@users.noreply.github.com> Date: Tue, 8 Jul 2025 08:02:57 -0600 Subject: [PATCH 08/15] Feature 525 update plotly kaleido (#526) * Update conf.py update version for 3.20 beta1 development * Feature 504 installation files (#511) * Update Orion file for Python 3.12 * Per #504, updating Casper file for Python 3.12 * Per # 504, updating compiler for Orion * Per #504, updating hera file for Python 3.12 * Per #504, updating jet file for Python 3.12 * Feature METplus2857 support (#513) * Making index consistent with other METplus repositories * Initial commit of overview * Bugfix #515 develop - remove deprecated import (#517) * Per #515, remove deprecated import * remove additional unused import to resolve SQ * Update base_plot.py Comment out pio.kaleido.scope.chromium line. Python 3.12 updates with updated deprecations in kaleido will cause some tests to fail due to these warnings. * Remove soon to be deprecated call to plotly.io.kaleido.scope * Comment out soon-to-be deprecated call to plolty.io.kaleido.scope * add call to install chrome * Add test_* to trigger and setup test to use test_requirements.txt * To test plotly/kaleido updates * Try using kaleido_get_chrome_sync * Update import to use ploty.io._kaleido * Using latest import, invoke the get_chrome() method instead of get_chrome_sync() * explicitly pip install kaleido 1.0 * Add Google Chrome action * fix syntax error * remove - from the run command * Explicitly get the Chrome environment, bypass the calls to plotly.io.kaleido for installing chrome, which already exists * Set up a CHROME_INSTALL path and save it as an environment * remove no-sudo * removed extra line at top of file * move env definition by indenting * Removed all imports that didn't work and the soon to be deprecated reference to kaleido.scope. Running after installing Chrome without setting an ENV variable. * Remove any attempt to set an env * Remove the --version to the path under the chrome installation * Remove skip * Update test_requirements.txt match up with requirements.txt except for kaleido and plotly * Attempt to get chrome via kaleido.get_chrome_sync() * Update unit_tests.yaml Comment out installation of Chrome for now but don't delete it in the event that Chrome will need to be explicitly available. * Update base_plot.py Remove old comment and update to reflect upcoming changes to kaleido * Replace test_requirements.txt with requirements.txt * Update Plotly from 6.0.0 to 6.1.1 and kaleido from 0.2.1 to 1.0.0 * Adding modulefile for new machine ursa --------- Co-authored-by: Julie Prestopnik Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> --- .github/workflows/unit_tests.yaml | 15 +++++++++-- docs/conf.py | 2 +- .../installation/modulefiles/3.1.0_casper | 2 +- .../installation/modulefiles/3.1.0_hera | 2 +- .../installation/modulefiles/3.1.0_jet | 2 +- .../installation/modulefiles/3.1.0_orion | 4 +-- .../installation/modulefiles/3.2.0_ursa | 25 +++++++++++++++++++ .../stratosphere_plots.py | 4 ++- metplotpy/plots/base_plot.py | 8 +++--- requirements.txt | 6 ++--- test/scatter/test_scatter.py | 1 - test_requirements.txt | 21 ++++++++++++++++ 12 files changed, 76 insertions(+), 16 deletions(-) create mode 100644 internal/scripts/installation/modulefiles/3.2.0_ursa create mode 100644 test_requirements.txt diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 514f051a6..702a7ec89 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -1,6 +1,5 @@ # This workflow will install Python dependencies, run tests the specified Python version # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - name: Python 3.12 tests on: @@ -11,6 +10,7 @@ on: - feature_* - main_* - bugfix_* + - test_* paths-ignore: - 'docs/**' - '.github/pull_request_template.md' @@ -21,6 +21,8 @@ on: pull_request: types: [opened, reopened, synchronize] + + jobs: build: @@ -49,8 +51,17 @@ jobs: run: | python -m pip install --upgrade pip if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pip install --upgrade kaleido - + +# - uses: browser-actions/setup-chrome@v1 +# - name: Install Google Chrome for Plotly +# run: | +# chrome --version +# ${{ steps.setup-chrome.outputs.chrome-path }} + + + # Checking the branch name, not necessary but useful when setting things up. # - name: Extract branch name # shell: bash diff --git a/docs/conf.py b/docs/conf.py index d1a976ad8..5fbd7fbae 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -25,7 +25,7 @@ copyright = '2025, NSF NCAR' author = 'UCAR/NSF NCAR, NOAA, CSU/CIRA, and CU/CIRES' author_list = 'Fisher, H., D. Adriaansen, C. Kalb, D. Fillmore, T. Jensen, L. Goodrich, M. Win-Gildenmeister and T. Burek' -version = '3.1.0-rc1' +version = '3.2.0-beta1-dev' verinfo = version release = f'{version}' release_year = '2025' diff --git a/internal/scripts/installation/modulefiles/3.1.0_casper b/internal/scripts/installation/modulefiles/3.1.0_casper index 09db94448..2d786c42e 100644 --- a/internal/scripts/installation/modulefiles/3.1.0_casper +++ b/internal/scripts/installation/modulefiles/3.1.0_casper @@ -10,7 +10,7 @@ proc ModulesHelp { } { module load ncarenv/24.12 module load intel/2024.2.1 -prepend-path PATH /glade/work/dtcrt/METplus/casper/miniconda/miniconda3/envs/metplus_v5.1_py3.10/bin +prepend-path PATH /glade/work/dtcrt/METplus/casper/miniconda/miniconda3/envs/metplus_v6.1_py3.12/bin setenv METPLOTPY_SOURCE /glade/work/dtcrt/METplus/casper/components/METplotpy/installations/METplotpy-3.1.0 setenv METPLOTPY_BASE /glade/work/dtcrt/METplus/casper/components/METplotpy/installations/METplotpy-3.1.0 diff --git a/internal/scripts/installation/modulefiles/3.1.0_hera b/internal/scripts/installation/modulefiles/3.1.0_hera index 4e4165e91..07f1c960e 100644 --- a/internal/scripts/installation/modulefiles/3.1.0_hera +++ b/internal/scripts/installation/modulefiles/3.1.0_hera @@ -12,7 +12,7 @@ prereq intel/2024.2.1 setenv METPLOTPY_SOURCE /contrib/METplotpy/METplotpy-3.1.0 setenv METPLOTPY_BASE /contrib/METplotpy/METplotpy-3.1.0 -prepend-path PATH /scratch1/BMC/dtc/miniconda/miniconda3/envs/metplus_v5.1_py3.10/bin +prepend-path PATH /scratch1/BMC/dtc/miniconda/miniconda3/envs/metplus_v6.1_py3.12/bin prepend-path PATH /contrib/METplotpy/METplotpy-3.1.0/metplotpy/contributed prepend-path PATH /contrib/METplotpy/METplotpy-3.1.0/metplotpy/plots/performance_diagram prepend-path PATH /contrib/METplotpy/METplotpy-3.1.0/metplotpy/plots diff --git a/internal/scripts/installation/modulefiles/3.1.0_jet b/internal/scripts/installation/modulefiles/3.1.0_jet index b35a32d2c..85bf61c75 100644 --- a/internal/scripts/installation/modulefiles/3.1.0_jet +++ b/internal/scripts/installation/modulefiles/3.1.0_jet @@ -12,7 +12,7 @@ prereq intel/2024.2.1 setenv METPLOTPY_SOURCE /contrib/met/METplotpy/METplotpy-3.1.0 setenv METPLOTPY_BASE /contrib/met/METplotpy/METplotpy-3.1.0 -prepend-path PATH /lfs5/HFIP/dtc-hurr/METplus/miniconda/miniconda3/envs/metplus_v5.1_py3.10/bin +prepend-path PATH /lfs6/HFIP/dtc-hurr/METplus/miniconda/miniconda3/envs/metplus_v6.1_py3.12/bin prepend-path PATH /contrib/met/METplotpy/METplotpy-3.1.0/metplotpy/contributed prepend-path PATH /contrib/met/METplotpy/METplotpy-3.1.0/metplotpy/plots/performance_diagram prepend-path PATH /contrib/met/METplotpy/METplotpy-3.1.0/metplotpy/plots diff --git a/internal/scripts/installation/modulefiles/3.1.0_orion b/internal/scripts/installation/modulefiles/3.1.0_orion index 2a424ebe4..b233f0a93 100644 --- a/internal/scripts/installation/modulefiles/3.1.0_orion +++ b/internal/scripts/installation/modulefiles/3.1.0_orion @@ -8,13 +8,13 @@ proc ModulesHelp { } { } module load contrib -module load intel-oneapi-compilers/2022.2.1 +module load intel-oneapi-compilers/2024.1.0 setenv METPLOTPY_SOURCE /apps/contrib/MET/METplotpy/METplotpy-3.1.0 setenv METPLOTPY_BASE /apps/contrib/MET/METplotpy/METplotpy-3.1.0 #setenv METPLOTPY_PATH /apps/contrib/MET/METplotpy/METplotpy-3.1.0/ -prepend-path PATH /work/noaa/ovp/miniconda/miniconda3/envs/metplus_v5.1_py3.10/bin +prepend-path PATH /work/noaa/ovp/miniconda/miniconda3/envs/metplus_v6.1_py3.12/bin prepend-path PATH /apps/contrib/MET/METplotpy/METplotpy-3.1.0/metplotpy/contributed prepend-path PATH /apps/contrib/MET/METplotpy/METplotpy-3.1.0/metplotpy/plots/performance_diagram prepend-path PATH /apps/contrib/MET/METplotpy/METplotpy-3.1.0/metplotpy/plots diff --git a/internal/scripts/installation/modulefiles/3.2.0_ursa b/internal/scripts/installation/modulefiles/3.2.0_ursa new file mode 100644 index 000000000..1ef5d6e56 --- /dev/null +++ b/internal/scripts/installation/modulefiles/3.2.0_ursa @@ -0,0 +1,25 @@ +#%Module###################################################################### +## +## METplotpy +## +proc ModulesHelp { } { + puts stderr "Sets up the paths and environment variables to use the METplotpy-3.2.0. + *** For help see the official MET webpage at http://www.dtcenter.org/met/users ***" +} + +prereq intel-oneapi-compilers/2025.1.1 + +setenv METPLOTPY_SOURCE /contrib/METplotpy/METplotpy-3.2.0 +setenv METPLOTPY_BASE /contrib/METplotpy/METplotpy-3.2.0 + +prepend-path PATH /scratch3/BMC/dtc/METplus/miniconda/miniconda3/envs/metplus_v6.1_py3.12/bin +prepend-path PATH /contrib/METplotpy/METplotpy-3.2.0/metplotpy/contributed +prepend-path PATH /contrib/METplotpy/METplotpy-3.2.0/metplotpy/plots/performance_diagram +prepend-path PATH /contrib/METplotpy/METplotpy-3.2.0/metplotpy/plots +prepend-path PATH /contrib/METplotpy/METplotpy-3.2.0/metplotpy +prepend-path PATH /contrib/METplotpy/METplotpy-3.2.0 +prepend-path PYTHONPATH /contrib/METplotpy/METplotpy-3.2.0/metplotpy/contributed +prepend-path PYTHONPATH /contrib/METplotpy/METplotpy-3.2.0/metplotpy/plots/performance_diagram +prepend-path PYTHONPATH /contrib/METplotpy/METplotpy-3.2.0/metplotpy/plots +prepend-path PYTHONPATH /contrib/METplotpy/METplotpy-3.2.0/metplotpy +prepend-path PYTHONPATH /contrib/METplotpy/METplotpy-3.2.0 diff --git a/metplotpy/contributed/stratosphere_diagnostics/stratosphere_plots.py b/metplotpy/contributed/stratosphere_diagnostics/stratosphere_plots.py index d6da90892..bf29db1d3 100644 --- a/metplotpy/contributed/stratosphere_diagnostics/stratosphere_plots.py +++ b/metplotpy/contributed/stratosphere_diagnostics/stratosphere_plots.py @@ -109,7 +109,9 @@ def plot_qbo_phase_circuits(inits,periods,rean_qbo_pcs,rfcst_qbo_pcs,outfile): def plot_qbo_phase_space(rean_qbo_pcs,eofs,ptitle,outfile): - from mpl_toolkits.axes_grid1.inset_locator import (inset_axes, mark_inset) + + from mpl_toolkits.axes_grid1.inset_locator import mark_inset + fig = plt.figure(4) diff --git a/metplotpy/plots/base_plot.py b/metplotpy/plots/base_plot.py index e1001edbc..ac16e2759 100644 --- a/metplotpy/plots/base_plot.py +++ b/metplotpy/plots/base_plot.py @@ -27,9 +27,11 @@ from .config import Config from metplotpy.plots.context_filter import ContextFilter -# set kaleido to use single process to prevent GPU errors in containers -# NOTE: this may result in GHA tests failing due to impending deprecations in kaleido -pio.kaleido.scope.chromium_args += ("--single-process",) +# kaleido 0.x will be deprecated after September 2025 and Chrome will no longer +# be included with kaleido from version 1.0.0. Explicitly get Chrome via call to kaleido. +import kaleido +kaleido.get_chrome_sync() + class BasePlot: """A class that provides methods for building Plotly plot's common features diff --git a/requirements.txt b/requirements.txt index 3aafb80e6..eeb792d5f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ + imageio>=2.37.0 imutils>=0.5.4 -kaleido>=0.2.1 +kaleido>=1.0.0 matplotlib>=3.10.0 metpy>=1.6.3 netcdf4>=1.7.2 @@ -8,7 +9,7 @@ numpy>=2.2.2 opencv-python>=4.10.0 pandas>=2.2.3 pint>=0.24.4 -plotly>=6.0.0 +plotly>=6.1.1 pytest>=8.3.4 pyyaml>=6.0.2 scikit-image>=0.25.1 @@ -18,4 +19,3 @@ eofs>=2.0.0 cartopy>=0.24.0 scikit-learn>=1.6.1 cmocean>=4.0.3 - diff --git a/test/scatter/test_scatter.py b/test/scatter/test_scatter.py index e232dd3d9..aee0593f4 100644 --- a/test/scatter/test_scatter.py +++ b/test/scatter/test_scatter.py @@ -23,7 +23,6 @@ def read_config(config_filename) -> dict: return parms except yaml.YAMLError as exc: print(exc) -@pytest.mark.skip("Skipping until GHA issue with Python 3.12 and kaleido are resolved") def test_files_exist(): """ Generate a scatter plot from reformatted MPR Usecase data and diff --git a/test_requirements.txt b/test_requirements.txt new file mode 100644 index 000000000..eeb792d5f --- /dev/null +++ b/test_requirements.txt @@ -0,0 +1,21 @@ + +imageio>=2.37.0 +imutils>=0.5.4 +kaleido>=1.0.0 +matplotlib>=3.10.0 +metpy>=1.6.3 +netcdf4>=1.7.2 +numpy>=2.2.2 +opencv-python>=4.10.0 +pandas>=2.2.3 +pint>=0.24.4 +plotly>=6.1.1 +pytest>=8.3.4 +pyyaml>=6.0.2 +scikit-image>=0.25.1 +scipy>=1.15.1 +xarray>=2025.1.2 +eofs>=2.0.0 +cartopy>=0.24.0 +scikit-learn>=1.6.1 +cmocean>=4.0.3 From 2a57b436ea90f01eece3246d338fb4248bca31ae Mon Sep 17 00:00:00 2001 From: MWin <3753118+bikegeek@users.noreply.github.com> Date: Mon, 21 Jul 2025 08:07:42 -0600 Subject: [PATCH 09/15] Feature 525 update plotly kaleido (#528) * Update conf.py update version for 3.20 beta1 development * Feature 504 installation files (#511) * Update Orion file for Python 3.12 * Per #504, updating Casper file for Python 3.12 * Per # 504, updating compiler for Orion * Per #504, updating hera file for Python 3.12 * Per #504, updating jet file for Python 3.12 * Feature METplus2857 support (#513) * Making index consistent with other METplus repositories * Initial commit of overview * Bugfix #515 develop - remove deprecated import (#517) * Per #515, remove deprecated import * remove additional unused import to resolve SQ * Update base_plot.py Comment out pio.kaleido.scope.chromium line. Python 3.12 updates with updated deprecations in kaleido will cause some tests to fail due to these warnings. * Remove soon to be deprecated call to plotly.io.kaleido.scope * Comment out soon-to-be deprecated call to plolty.io.kaleido.scope * add call to install chrome * Add test_* to trigger and setup test to use test_requirements.txt * To test plotly/kaleido updates * Try using kaleido_get_chrome_sync * Update import to use ploty.io._kaleido * Using latest import, invoke the get_chrome() method instead of get_chrome_sync() * explicitly pip install kaleido 1.0 * Add Google Chrome action * fix syntax error * remove - from the run command * Explicitly get the Chrome environment, bypass the calls to plotly.io.kaleido for installing chrome, which already exists * Set up a CHROME_INSTALL path and save it as an environment * remove no-sudo * removed extra line at top of file * move env definition by indenting * Removed all imports that didn't work and the soon to be deprecated reference to kaleido.scope. Running after installing Chrome without setting an ENV variable. * Remove any attempt to set an env * Remove the --version to the path under the chrome installation * Remove skip * Update test_requirements.txt match up with requirements.txt except for kaleido and plotly * Attempt to get chrome via kaleido.get_chrome_sync() * Update unit_tests.yaml Comment out installation of Chrome for now but don't delete it in the event that Chrome will need to be explicitly available. * Update base_plot.py Remove old comment and update to reflect upcoming changes to kaleido * Replace test_requirements.txt with requirements.txt * Update Plotly from 6.0.0 to 6.1.1 and kaleido from 0.2.1 to 1.0.0 * Adding modulefile for new machine ursa * Feature 525 update plotly kaleido (for develop/v3.2 release) (#527) * Feature METplus2857 main v3.1 support (#512) * Making index consistent with other METplus repositories * Initial commit of overview * Per #515, remove deprecated import (#516) * Update base_plot.py comment out the pio.kaleido.scope line, this is now causing tests to fail due to kaleido warning for deprecations in September 2025 * Update base_plot.py backing out the latest from pio.kaleido line. WARNING: GHA tests may fail due to upcoming deprecation and warnings that emanate due to Python 3.12 still features that will be deprecated. * Update test_scatter.py Tests pass outside of GHA. Something in GHA is causing issues with Python 3.12 and kaleido (causes AssertionError in kaleido) * Remove soon to be deprecated call to plotly.io.kaleido.scope * Comment out soon-to-be deprecated call to plolty.io.kaleido.scope * add call to install chrome * Add test_* to trigger and setup test to use test_requirements.txt * To test plotly/kaleido updates * Try using kaleido_get_chrome_sync * Update import to use ploty.io._kaleido * Using latest import, invoke the get_chrome() method instead of get_chrome_sync() * explicitly pip install kaleido 1.0 * Add Google Chrome action * fix syntax error * remove - from the run command * Explicitly get the Chrome environment, bypass the calls to plotly.io.kaleido for installing chrome, which already exists * Set up a CHROME_INSTALL path and save it as an environment * remove no-sudo * removed extra line at top of file * move env definition by indenting * Removed all imports that didn't work and the soon to be deprecated reference to kaleido.scope. Running after installing Chrome without setting an ENV variable. * Remove any attempt to set an env * Remove the --version to the path under the chrome installation * Remove skip * Update test_requirements.txt match up with requirements.txt except for kaleido and plotly * Attempt to get chrome via kaleido.get_chrome_sync() * Update unit_tests.yaml Comment out installation of Chrome for now but don't delete it in the event that Chrome will need to be explicitly available. * Update base_plot.py Remove old comment and update to reflect upcoming changes to kaleido * Replace test_requirements.txt with requirements.txt * Update Plotly from 6.0.0 to 6.1.1 and kaleido from 0.2.1 to 1.0.0 --------- Co-authored-by: Julie Prestopnik Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * Added support for env variable to turn on/off invoking the get_chrome_sync() to install Chrome at run-time * test truthiness for booleans rather than string * Update logic for checking PRE_LOAD_CHROME environment variable that is defined in the Dockerfile * Remove print statement * Add check for PRE_LOAD_CHROME env variable set in Dockerfile to turn on/off invoking kaleido.get_chrome_sync() * Updated versions for Plotly and kaleido * Allow logging to stdout and/or file to indicate whether Chrome is getting downloaded at runtime. This facilitates testing for debugging. Setting the PRE_LOAD_CHROME env variable to False (either as bool or string-case is insensitive) will invoke downloading Chrome via Plotly/kaleido. If PRE_LOAD_CHROME is not defined, Chrome will also be downloaded from Plotly/kaleido at run time. Logging can be turned on/off by setting the LOG_BASE_PLOT to true/false (boolean or string) and a log file can be saved by setting the WRITE_LOG env var to true (boolean or string). * Update the runtime loading of Chrome by allowing logging to monitor if Chrome is being downloaded at runtime. Use METplotpy util.py strtobool to replace the distutils.util.strtobool to return a boolean value from the PRE_LOAD_CHROME and logging env vars. * Implement our own version of the deprecated (in Python 3.12+) of distutils.utils.strtobool * Add testing for the strtobool implementation in util.py * Fix import for util strtobool * Forgot to change the args to strtobool to match our implementation * Include the information about impacts of kaleido 1.0.0 changes under the METplotpy Upgrade Instructions * Still one more place to fix the input to strtobool to match our implementation * Refactor to eliminate sonarqube code smell * Remove test code --------- Co-authored-by: Julie Prestopnik Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> --- docs/Users_Guide/release-notes.rst | 17 +++++++++++ metplotpy/plots/base_plot.py | 45 ++++++++++++++++++++++++---- metplotpy/plots/util.py | 47 ++++++++++++++++++++++++++++++ nco_requirements.txt | 4 +-- test/util/test_util.py | 47 +++++++++++++++++++++++++++++- 5 files changed, 152 insertions(+), 8 deletions(-) diff --git a/docs/Users_Guide/release-notes.rst b/docs/Users_Guide/release-notes.rst index 21b271caf..27cc996ef 100644 --- a/docs/Users_Guide/release-notes.rst +++ b/docs/Users_Guide/release-notes.rst @@ -93,3 +93,20 @@ METplotpy Upgrade Instructions development with Python 3.12. View the requirements.txt/nco_requirements.txt file at the top level of the repository for version numbers for the corresponding third-party packages. + + In June 2025, Plotly made significant updates to the kaleido package with the 1.0.0 + release by removing Google Chrome code. Now, users will need to have Google Chrome + installed in directories specified in this Plotly documentation (based on operating + system): + +https://plotly.com/python/static-image-export/ + +The METplotpy code downloads Chrome at runtime by invoking the kaleido.get_chrome_sync() +method call. + +If users do not wish to have Chrome downloaded at run time and already have Chrome installed +in one of the expected locations (specified in the Plotly link above), then the PRE_LOAD_CHROME environment variable +will need to be set to 'True' (case insensitive string). + +Refer to the Kaleido README for more information on the changes: +https://github.com/plotly/Kaleido diff --git a/metplotpy/plots/base_plot.py b/metplotpy/plots/base_plot.py index ac16e2759..23d28571a 100644 --- a/metplotpy/plots/base_plot.py +++ b/metplotpy/plots/base_plot.py @@ -20,18 +20,53 @@ import numpy as np import yaml from typing import Union - -import plotly.io as pio - +import kaleido import metplotpy.plots.util +from metplotpy.plots.util import strtobool from .config import Config from metplotpy.plots.context_filter import ContextFilter # kaleido 0.x will be deprecated after September 2025 and Chrome will no longer # be included with kaleido from version 1.0.0. Explicitly get Chrome via call to kaleido. -import kaleido -kaleido.get_chrome_sync() +# In some instances, we do NOT want Chrome to be installed at run-time. If the +# PRE_LOAD_CHROME environment variable exists, or set to TRUE, +# then Chrome will be assumed to have been pre-loaded. Otherwise, +# invoke get_chrome_sync() to install Chrome in the +# /path-to-python-libs/pythonx.yz/site-packages/... directory + +# Check if the PRE_LOAD_CHROME env variable exists +aquire_chrome = False + +turn_on_logging = strtobool('LOG_BASE_PLOT') +# Log when Chrome is downloaded at runtime +if turn_on_logging is True: + log = logging.getLogger("base_plot") + log.setLevel(logging.INFO) + + formatter = logging.Formatter("%(asctime)s [%(levelname)s] | %(name)s | %(message)s") + + # set the WRITE_LOG env var to True to save the log message to a + # separate log file + write_log = strtobool('WRITE_LOG') + if write_log is True: + file_handler = logging.FileHandler("./base_plot.log") + file_handler.setFormatter(formatter) + log.addHandler(file_handler) + +# Only load Chrome at run-time if PRE_LOAD_CHROME is False or not defined. +# Some applications may not want to load Chrome at runtime and +# will set the PRE_LOAD_CHROME to True to indicate that it is already +# loaded/downloaded prior to runtime. +chrome_env =strtobool ('PRE_LOAD_CHROME') +if ('PRE_LOAD_CHROME' not in os.environ)or (chrome_env is False): + aquire_chrome=True + kaleido.get_chrome_sync() + + +# Log when kaleido is downloading Chrome +if aquire_chrome is True and turn_on_logging is True: + log.info("Plotly kaleido is loading Chrome at run time") class BasePlot: """A class that provides methods for building Plotly plot's common features diff --git a/metplotpy/plots/util.py b/metplotpy/plots/util.py index 7b2c32897..2664f32df 100644 --- a/metplotpy/plots/util.py +++ b/metplotpy/plots/util.py @@ -623,3 +623,50 @@ def prepare_ctc_roc(subset_df, is_ascending): thresh = pd.concat([thresh, pd.Series([''])], ignore_index=True) return pody, pofd, thresh + + +def strtobool(env_var:str)->bool: + """ + Since distutils.util.strtobool was deprecated in Python 3.12, implement + our own version. + + In the distutils.util.strtobool, a simple one line command was used to determine + whether an environment variable was set to True or False. In this + example, the default value is set to False in the event that the environment + variable is not defined: + + turn_on_logging = strtobool(os.getenv('LOG_BASE_PLOT', 'False') ) + + Environment variables can be set as string or bool. Evaluate whether a string + value for true or false (support case-insensitive text) is True/False and + set the default value. + + Args: + @parm env_vars: string name of the environment variable to evaluate + + turn_on_logging = strtobool(os.getenv('LOG_BASE_PLOT') ) + """ + + true_list = ['true', 't', '1',] + false_list = ['false', 'f', '0' ] + # if the environment variable does not exist, then return False + try: + val = os.environ[env_var] + except KeyError: + return False + + # If the environment variable is None, return false + if val is None: + return False + else: + # Check for variations of truth values + lower = val.lower() + if lower in true_list: + return True + elif lower in false_list: + return False + else: + msg = "Value does not represent a truth value (i.e. true or false)" + raise ValueError(msg) + + diff --git a/nco_requirements.txt b/nco_requirements.txt index 7330a6f7e..4156ef860 100644 --- a/nco_requirements.txt +++ b/nco_requirements.txt @@ -1,4 +1,4 @@ -kaleido>=0.2.1 +kaleido>=1.0.0 matplotlib>=3.10.0 metpy>=1.6.3 netcdf4>=1.7.2 @@ -6,7 +6,7 @@ numpy==2.2.2 scipy>=1.15.1 pandas>=2.2.3 pint>=0.24.4 -plotly>=6.0.0 +plotly>=6.1.1 pytest>=8.3.4 pyyaml>=6.0.2 xarray>=2025.1.2 diff --git a/test/util/test_util.py b/test/util/test_util.py index b22bcc04c..4d853708a 100644 --- a/test/util/test_util.py +++ b/test/util/test_util.py @@ -1,6 +1,6 @@ import os import pandas as pd - +import pytest import metplotpy.plots.util as util import gc @@ -170,3 +170,48 @@ def test_filter_by_fixed_vars(): for filtered in filtered_list: assert filtered in expected_list + + +def test_strtobool(): + """ + Test that strtobool is returning the corresponding bool value to an environment + + """ + + # Non-existent env var should return boolean False + assert (util.strtobool('NON_EXISTENT') is False) + + # Variations of false should return boolean False + os.environ['FALSE_1'] = 'f' + os.environ['FALSE_2'] = 'FaLSE' + os.environ['FALSE_3'] = '0' + os.environ['FALSE_4'] = 'F' + false_1 = 'FALSE_1' + false_2 = 'FALSE_2' + false_3 = 'FALSE_3' + false_4 = 'FALSE_4' + assert(util.strtobool(false_1) is False) + assert(util.strtobool(false_2) is False) + assert(util.strtobool(false_3) is False) + assert(util.strtobool(false_4) is False) + + + # Variations of true should return boolean True + os.environ['TRUE_1'] = 't' + os.environ['TRUE_2'] = 'T' + os.environ['TRUE_3'] = 'tRuE' + os.environ['TRUE_4'] = '1' + true_1 = 'TRUE_1' + true_2 = 'TRUE_2' + true_3 = 'TRUE_3' + true_4 = 'TRUE_4' + assert (util.strtobool(true_1) is True) + assert (util.strtobool(true_2) is True) + assert (util.strtobool(true_3) is True) + assert (util.strtobool(true_4) is True) + + # non-truth values should raise a ValueError + os.environ['BOGUS'] = 'Whatever' + var = 'BOGUS' + with pytest.raises(ValueError): + util.strtobool(var) From 52b26908cf99f323cafe6344eb4d0713d7017281 Mon Sep 17 00:00:00 2001 From: MWin <3753118+bikegeek@users.noreply.github.com> Date: Mon, 21 Jul 2025 08:10:37 -0600 Subject: [PATCH 10/15] Update release-notes.rst updated the date for release --- docs/Users_Guide/release-notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Users_Guide/release-notes.rst b/docs/Users_Guide/release-notes.rst index a67911faa..6fa10ceb3 100644 --- a/docs/Users_Guide/release-notes.rst +++ b/docs/Users_Guide/release-notes.rst @@ -7,7 +7,7 @@ describes the bugfix, enhancement, or new feature: `METplotpy GitHub issues. `_ -METplotpy Version 3.1.0 release notes (20250701) +METplotpy Version 3.1.0 release notes (20250721) ==================================================== .. dropdown:: New Plots From 9bb5717a8f287a6ffbf84cf008c4585aadfd4c5c Mon Sep 17 00:00:00 2001 From: MWin <3753118+bikegeek@users.noreply.github.com> Date: Mon, 21 Jul 2025 08:13:17 -0600 Subject: [PATCH 11/15] Update conf.py update date of release --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index deef4f30c..f9c46ba0f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -30,7 +30,7 @@ release = f'{version}' release_year = '2025' -release_date = f'{release_year}-07-01' +release_date = f'{release_year}-07-21' copyright = f'{release_year}, {author}' From 01dfc0503bd3362f368168c48938592f91b9ce9d Mon Sep 17 00:00:00 2001 From: bikegeek Date: Mon, 21 Jul 2025 08:46:49 -0600 Subject: [PATCH 12/15] separated the Plotly note from the Python 3.12 note --- docs/Users_Guide/release-notes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Users_Guide/release-notes.rst b/docs/Users_Guide/release-notes.rst index d82236e43..273513b3b 100644 --- a/docs/Users_Guide/release-notes.rst +++ b/docs/Users_Guide/release-notes.rst @@ -55,6 +55,7 @@ METplotpy Upgrade Instructions development with Python 3.12. View the requirements.txt/nco_requirements.txt file at the top level of the repository for version numbers for the corresponding third-party packages. +.. note:: In June 2025, Plotly made significant updates to the kaleido package with the 1.0.0 release by removing Google Chrome code. Now, users will need to have Google Chrome From 34d07c18450e50138abe51140967e7b826ecaa4d Mon Sep 17 00:00:00 2001 From: bikegeek Date: Mon, 21 Jul 2025 08:57:18 -0600 Subject: [PATCH 13/15] Modify formatting so link to Plotly site is within note block --- docs/Users_Guide/release-notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Users_Guide/release-notes.rst b/docs/Users_Guide/release-notes.rst index 273513b3b..4e3caa868 100644 --- a/docs/Users_Guide/release-notes.rst +++ b/docs/Users_Guide/release-notes.rst @@ -62,7 +62,7 @@ METplotpy Upgrade Instructions installed in directories specified in this Plotly documentation (based on operating system): -https://plotly.com/python/static-image-export/ + https://plotly.com/python/static-image-export/ The METplotpy code downloads Chrome at runtime by invoking the kaleido.get_chrome_sync() method call. From feca810cb9458703f5f4ef4f9385c5e929fcf4dd Mon Sep 17 00:00:00 2001 From: bikegeek Date: Mon, 21 Jul 2025 08:59:03 -0600 Subject: [PATCH 14/15] reapply different formatting to Notes section for Plotly/kaleido --- docs/Users_Guide/release-notes.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/Users_Guide/release-notes.rst b/docs/Users_Guide/release-notes.rst index 4e3caa868..f1ba760ca 100644 --- a/docs/Users_Guide/release-notes.rst +++ b/docs/Users_Guide/release-notes.rst @@ -61,7 +61,6 @@ METplotpy Upgrade Instructions release by removing Google Chrome code. Now, users will need to have Google Chrome installed in directories specified in this Plotly documentation (based on operating system): - https://plotly.com/python/static-image-export/ The METplotpy code downloads Chrome at runtime by invoking the kaleido.get_chrome_sync() From da48f9bfbd7c0e76307f3d83562a283cc3fd027f Mon Sep 17 00:00:00 2001 From: bikegeek Date: Mon, 21 Jul 2025 09:21:55 -0600 Subject: [PATCH 15/15] Fix indentation --- docs/Users_Guide/release-notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Users_Guide/release-notes.rst b/docs/Users_Guide/release-notes.rst index f1ba760ca..cce496ca1 100644 --- a/docs/Users_Guide/release-notes.rst +++ b/docs/Users_Guide/release-notes.rst @@ -61,7 +61,7 @@ METplotpy Upgrade Instructions release by removing Google Chrome code. Now, users will need to have Google Chrome installed in directories specified in this Plotly documentation (based on operating system): - https://plotly.com/python/static-image-export/ + https://plotly.com/python/static-image-export/ The METplotpy code downloads Chrome at runtime by invoking the kaleido.get_chrome_sync() method call.