diff --git a/.github/actions/install-conda/action.yml b/.github/actions/install-conda/action.yml index 43e8112a417..6948900fab6 100644 --- a/.github/actions/install-conda/action.yml +++ b/.github/actions/install-conda/action.yml @@ -24,7 +24,7 @@ runs: - name: Install dependencies shell: bash -l {0} - run: micromamba install --quiet --yes --file ci/${{ inputs.type }}_requirements.txt --file ci/extra_requirements.txt --file ci/requirements.txt + run: micromamba install --yes --file ci/${{ inputs.type }}_requirements.txt --file ci/extra_requirements.txt --file ci/requirements.txt - name: Download Cartopy Maps shell: bash -l {0} diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 48fad6bbc0b..ae80f123555 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -10,8 +10,8 @@ concurrency: cancel-in-progress: true jobs: - flake8: - name: Flake8 + lint: + name: Run Lint Tools runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -27,19 +27,10 @@ jobs: run: python -m pip install -r ci/linting_requirements.txt - name: Set up reviewdog - run: | - mkdir -p $HOME/bin - curl -sfL \ - https://github.com/reviewdog/reviewdog/raw/master/install.sh | \ - sh -s -- -b $HOME/bin - echo "$HOME/bin" >> $GITHUB_PATH + uses: reviewdog/action-setup@v1 - name: Run ruff - env: - REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - set -o pipefail - ruff check . | reviewdog -f=pep8 -name=ruff -reporter=github-check -filter-mode=nofilter + run: ruff check --output-format github - name: Run flake8 env: diff --git a/ci/doc_requirements.txt b/ci/doc_requirements.txt index 07d9865bae9..8a77af29277 100644 --- a/ci/doc_requirements.txt +++ b/ci/doc_requirements.txt @@ -1,7 +1,7 @@ sphinx==7.3.7 pydata-sphinx-theme==0.15.2 -sphinx-design==0.6.0 -sphinx-gallery==0.16.0 +sphinx-design==0.6.1 +sphinx-gallery==0.17.1 myst-parser==3.0.1 netCDF4==1.7.1 geopandas==0.14.4 diff --git a/ci/extra_requirements.txt b/ci/extra_requirements.txt index f859559129b..1b7612964f1 100644 --- a/ci/extra_requirements.txt +++ b/ci/extra_requirements.txt @@ -1,3 +1,3 @@ -cartopy==0.22.0 -dask==2024.7.0 +cartopy==0.23.0 +dask==2024.8.0 shapely==2.0.5 diff --git a/ci/linting_requirements.txt b/ci/linting_requirements.txt index b46c33a9d5a..e30eb9686f4 100644 --- a/ci/linting_requirements.txt +++ b/ci/linting_requirements.txt @@ -1,7 +1,7 @@ -ruff==0.5.2 +ruff==0.6.1 -flake8==7.1.0 -pycodestyle==2.12.0 +flake8==7.1.1 +pycodestyle==2.12.1 pyflakes==3.2.0 flake8-continuation==1.0.5 diff --git a/ci/requirements.txt b/ci/requirements.txt index a596d64d8aa..e4d40f9354b 100644 --- a/ci/requirements.txt +++ b/ci/requirements.txt @@ -1,9 +1,9 @@ -matplotlib==3.9.1 -numpy==1.26.4 +matplotlib==3.9.2 +numpy==2.0.1 pandas==2.2.2 pooch==1.8.2 pint==0.24.3 pyproj==3.6.1 scipy==1.13.1 traitlets==5.14.3 -xarray==2024.6.0 +xarray==2024.7.0 diff --git a/ci/test_requirements.txt b/ci/test_requirements.txt index 78d30b3c514..b3609af7d0a 100644 --- a/ci/test_requirements.txt +++ b/ci/test_requirements.txt @@ -1,5 +1,5 @@ packaging==24.1 -pytest==8.2.2 +pytest==8.3.2 pytest-mpl==0.17.0 netCDF4==1.7.1 -coverage==7.5.3 +coverage==7.6.1 diff --git a/examples/meteogram_metpy.py b/examples/meteogram_metpy.py index e0bff215de3..90bb8784de0 100644 --- a/examples/meteogram_metpy.py +++ b/examples/meteogram_metpy.py @@ -181,7 +181,7 @@ def plot_pressure(self, p, plot_range=None): # Parse dates from .csv file, knowing their format as a string and convert to datetime def parse_date(date): - return dt.datetime.strptime(date.decode('ascii'), '%Y-%m-%d %H:%M:%S') + return dt.datetime.strptime(date, '%Y-%m-%d %H:%M:%S') testdata = np.genfromtxt(get_test_data('timeseries.csv', False), names=True, dtype=None, diff --git a/pyproject.toml b/pyproject.toml index f0210908422..5f5d6c2a66b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -120,7 +120,7 @@ filterwarnings = [ [tool.ruff] line-length = 95 -exclude = ["docs", "build", "src/metpy/io/_metar_parser/metar_parser.py"] +exclude = ["docs", "build", "src/metpy/io/_metar_parser/metar_parser.py", "talks"] preview = true [tool.ruff.lint] diff --git a/src/metpy/calc/thermo.py b/src/metpy/calc/thermo.py index 86d88da7bf4..b87a037e056 100644 --- a/src/metpy/calc/thermo.py +++ b/src/metpy/calc/thermo.py @@ -2588,7 +2588,7 @@ def most_unstable_parcel(pressure, temperature, dewpoint, height=None, bottom=No >>> # find most unstable parcel of depth 50 hPa >>> most_unstable_parcel(p, T, Td, depth=50*units.hPa) (, , - , 0) + , np.int64(0)) See Also -------- diff --git a/src/metpy/plots/declarative.py b/src/metpy/plots/declarative.py index 843c82d92b6..614707b90ee 100644 --- a/src/metpy/plots/declarative.py +++ b/src/metpy/plots/declarative.py @@ -1012,7 +1012,9 @@ def _build(self): # If we're on a map, we use min/max for y and manually figure out origin to try to # avoid upside down images created by images where y[0] > y[-1], as well as # specifying the transform - kwargs['extent'] = (x_like[0], x_like[-1], y_like.min(), y_like.max()) + # TODO item() shouldn't be necessary, but is until pydata/xarray#9043 is fixed. + kwargs['extent'] = (x_like[0].item(), x_like[-1].item(), + y_like.min().item(), y_like.max().item()) kwargs['origin'] = 'upper' if y_like[0] > y_like[-1] else 'lower' kwargs.setdefault('cmap', self._cmap_obj) kwargs.setdefault('norm', self._norm_obj) diff --git a/src/metpy/testing.py b/src/metpy/testing.py index a46a5ea8059..46f62805fd5 100644 --- a/src/metpy/testing.py +++ b/src/metpy/testing.py @@ -9,7 +9,7 @@ """ import contextlib import functools -from importlib.metadata import requires, version +from importlib.metadata import PackageNotFoundError, requires, version import operator as op import re @@ -55,7 +55,12 @@ def version_check(version_spec): metadata_spec = _get_metadata_spec(module_name) _, _, minimum_version_number = _parse_version_spec(metadata_spec) - installed_version = Version(version(module_name)) + try: + installed_version = Version(version(module_name)) + except PackageNotFoundError: + # Package not installed considered false condition for spec + return False + specified_version = Version(version_number) minimum_version = Version(minimum_version_number) diff --git a/tests/plots/baseline/test_au_plotting.png b/tests/plots/baseline/test_au_plotting.png index 9482df16edb..3eb0a6c8190 100644 Binary files a/tests/plots/baseline/test_au_plotting.png and b/tests/plots/baseline/test_au_plotting.png differ diff --git a/tests/plots/baseline/test_colorfill_no_colorbar.png b/tests/plots/baseline/test_colorfill_no_colorbar.png index 4ad1399db18..32d257b0a64 100644 Binary files a/tests/plots/baseline/test_colorfill_no_colorbar.png and b/tests/plots/baseline/test_colorfill_no_colorbar.png differ diff --git a/tests/plots/baseline/test_colorfill_with_image_range.png b/tests/plots/baseline/test_colorfill_with_image_range.png index e88380af7dd..a51da521cf0 100644 Binary files a/tests/plots/baseline/test_colorfill_with_image_range.png and b/tests/plots/baseline/test_colorfill_with_image_range.png differ diff --git a/tests/plots/baseline/test_declarative_additional_layers_plot_options.png b/tests/plots/baseline/test_declarative_additional_layers_plot_options.png index 5f6deadf56e..066d1e18656 100644 Binary files a/tests/plots/baseline/test_declarative_additional_layers_plot_options.png and b/tests/plots/baseline/test_declarative_additional_layers_plot_options.png differ diff --git a/tests/plots/baseline/test_declarative_barb_gfs.png b/tests/plots/baseline/test_declarative_barb_gfs.png index 40aa33185c7..143adf3e454 100644 Binary files a/tests/plots/baseline/test_declarative_barb_gfs.png and b/tests/plots/baseline/test_declarative_barb_gfs.png differ diff --git a/tests/plots/baseline/test_declarative_barb_gfs_knots.png b/tests/plots/baseline/test_declarative_barb_gfs_knots.png index a21c640e998..2c1af561ecb 100644 Binary files a/tests/plots/baseline/test_declarative_barb_gfs_knots.png and b/tests/plots/baseline/test_declarative_barb_gfs_knots.png differ diff --git a/tests/plots/baseline/test_declarative_colorbar_fontsize.png b/tests/plots/baseline/test_declarative_colorbar_fontsize.png index 0ce9d419b77..75a94ca188d 100644 Binary files a/tests/plots/baseline/test_declarative_colorbar_fontsize.png and b/tests/plots/baseline/test_declarative_colorbar_fontsize.png differ diff --git a/tests/plots/baseline/test_declarative_contour.png b/tests/plots/baseline/test_declarative_contour.png index c3eebe6fba0..1d887898010 100644 Binary files a/tests/plots/baseline/test_declarative_contour.png and b/tests/plots/baseline/test_declarative_contour.png differ diff --git a/tests/plots/baseline/test_declarative_contour_convert_units.png b/tests/plots/baseline/test_declarative_contour_convert_units.png index 9674f0bc63d..fbe1aa4c42d 100644 Binary files a/tests/plots/baseline/test_declarative_contour_convert_units.png and b/tests/plots/baseline/test_declarative_contour_convert_units.png differ diff --git a/tests/plots/baseline/test_declarative_contour_options.png b/tests/plots/baseline/test_declarative_contour_options.png index 9c819ce0f67..86667e72c15 100644 Binary files a/tests/plots/baseline/test_declarative_contour_options.png and b/tests/plots/baseline/test_declarative_contour_options.png differ diff --git a/tests/plots/baseline/test_declarative_figsize.png b/tests/plots/baseline/test_declarative_figsize.png index fbd85e75516..f4a7d181c55 100644 Binary files a/tests/plots/baseline/test_declarative_figsize.png and b/tests/plots/baseline/test_declarative_figsize.png differ diff --git a/tests/plots/baseline/test_declarative_gridded_scale.png b/tests/plots/baseline/test_declarative_gridded_scale.png index 70781118c68..25cefa83be9 100644 Binary files a/tests/plots/baseline/test_declarative_gridded_scale.png and b/tests/plots/baseline/test_declarative_gridded_scale.png differ diff --git a/tests/plots/baseline/test_declarative_layers_plot_options.png b/tests/plots/baseline/test_declarative_layers_plot_options.png index f40a6e24eaa..2a5d63f9b22 100644 Binary files a/tests/plots/baseline/test_declarative_layers_plot_options.png and b/tests/plots/baseline/test_declarative_layers_plot_options.png differ diff --git a/tests/plots/baseline/test_declarative_multiple_sfc_obs_change_units.png b/tests/plots/baseline/test_declarative_multiple_sfc_obs_change_units.png index 79386be01d4..199b79ee5db 100644 Binary files a/tests/plots/baseline/test_declarative_multiple_sfc_obs_change_units.png and b/tests/plots/baseline/test_declarative_multiple_sfc_obs_change_units.png differ diff --git a/tests/plots/baseline/test_declarative_region_modifier_zoom_out.png b/tests/plots/baseline/test_declarative_region_modifier_zoom_out.png index 49fcc6a2c11..c3197fce609 100644 Binary files a/tests/plots/baseline/test_declarative_region_modifier_zoom_out.png and b/tests/plots/baseline/test_declarative_region_modifier_zoom_out.png differ diff --git a/tests/plots/baseline/test_declarative_sfc_obs.png b/tests/plots/baseline/test_declarative_sfc_obs.png index 1ccac8450ed..1f6178006e7 100644 Binary files a/tests/plots/baseline/test_declarative_sfc_obs.png and b/tests/plots/baseline/test_declarative_sfc_obs.png differ diff --git a/tests/plots/baseline/test_declarative_sfc_obs_args.png b/tests/plots/baseline/test_declarative_sfc_obs_args.png index b4b74e9df70..9fad66b5986 100644 Binary files a/tests/plots/baseline/test_declarative_sfc_obs_args.png and b/tests/plots/baseline/test_declarative_sfc_obs_args.png differ diff --git a/tests/plots/baseline/test_declarative_sfc_obs_change_units.png b/tests/plots/baseline/test_declarative_sfc_obs_change_units.png index cb35fd68113..b975ef13cf2 100644 Binary files a/tests/plots/baseline/test_declarative_sfc_obs_change_units.png and b/tests/plots/baseline/test_declarative_sfc_obs_change_units.png differ diff --git a/tests/plots/baseline/test_declarative_sfc_obs_changes.png b/tests/plots/baseline/test_declarative_sfc_obs_changes.png index 37434466137..b15e7fe5dbb 100644 Binary files a/tests/plots/baseline/test_declarative_sfc_obs_changes.png and b/tests/plots/baseline/test_declarative_sfc_obs_changes.png differ diff --git a/tests/plots/baseline/test_declarative_smooth_contour.png b/tests/plots/baseline/test_declarative_smooth_contour.png index 42a69bc10dd..2d6406d4d1d 100644 Binary files a/tests/plots/baseline/test_declarative_smooth_contour.png and b/tests/plots/baseline/test_declarative_smooth_contour.png differ diff --git a/tests/plots/baseline/test_declarative_smooth_contour_calculation.png b/tests/plots/baseline/test_declarative_smooth_contour_calculation.png index 448162c0f9f..aa09ebbfad7 100644 Binary files a/tests/plots/baseline/test_declarative_smooth_contour_calculation.png and b/tests/plots/baseline/test_declarative_smooth_contour_calculation.png differ diff --git a/tests/plots/baseline/test_declarative_smooth_contour_order.png b/tests/plots/baseline/test_declarative_smooth_contour_order.png index fa32a930ce1..7618ebeb3e6 100644 Binary files a/tests/plots/baseline/test_declarative_smooth_contour_order.png and b/tests/plots/baseline/test_declarative_smooth_contour_order.png differ diff --git a/tests/plots/baseline/test_declarative_smooth_field.png b/tests/plots/baseline/test_declarative_smooth_field.png index 7e52df2d2c4..57b14c36ce8 100644 Binary files a/tests/plots/baseline/test_declarative_smooth_field.png and b/tests/plots/baseline/test_declarative_smooth_field.png differ diff --git a/tests/plots/baseline/test_us_states_scales.png b/tests/plots/baseline/test_us_states_scales.png index 5f12b9dd360..5945b68353f 100644 Binary files a/tests/plots/baseline/test_us_states_scales.png and b/tests/plots/baseline/test_us_states_scales.png differ diff --git a/tests/plots/baseline/test_uslcc_plotting.png b/tests/plots/baseline/test_uslcc_plotting.png index aed4966dca3..287053a737a 100644 Binary files a/tests/plots/baseline/test_uslcc_plotting.png and b/tests/plots/baseline/test_uslcc_plotting.png differ diff --git a/tests/plots/test_cartopy_utils.py b/tests/plots/test_cartopy_utils.py index 83e95088265..1cc864a3683 100644 --- a/tests/plots/test_cartopy_utils.py +++ b/tests/plots/test_cartopy_utils.py @@ -6,6 +6,7 @@ import pytest import metpy.plots as mpplots +from metpy.testing import version_check @pytest.mark.mpl_image_compare(tolerance=0.053, remove_text=True) @@ -48,7 +49,8 @@ def test_us_states_defaults(ccrs): return fig -@pytest.mark.mpl_image_compare(tolerance=0.092, remove_text=True) +@pytest.mark.mpl_image_compare(tolerance=0.248 if version_check('cartopy<0.23') else 0., + remove_text=True) def test_us_states_scales(ccrs): """Test the default US States plotting with all scales.""" proj = ccrs.LambertConformal(central_longitude=-85.0, central_latitude=45.0) diff --git a/tests/plots/test_declarative.py b/tests/plots/test_declarative.py index 48588101f88..121ca2717aa 100644 --- a/tests/plots/test_declarative.py +++ b/tests/plots/test_declarative.py @@ -92,7 +92,8 @@ def test_declarative_four_dims_error(): pc.draw() -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.096) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.163 if version_check('cartopy<0.23') else 0.09) @needs_cartopy def test_declarative_contour(): """Test making a contour plot.""" @@ -151,7 +152,8 @@ def test_declarative_titles(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.101) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.159 if version_check('cartopy<0.23') else 0.066) @needs_cartopy def test_declarative_smooth_contour(): """Test making a contour plot using smooth_contour.""" @@ -180,7 +182,8 @@ def test_declarative_smooth_contour(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.121) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.155 if version_check('cartopy<0.23') else 0.006) @needs_cartopy def test_declarative_smooth_contour_calculation(): """Test making a contour plot using smooth_contour.""" @@ -222,7 +225,8 @@ def test_declarative_smooth_contour_calculation(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.034) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.142 if version_check('cartopy<0.23') else 0.0038) @needs_cartopy def test_declarative_smooth_contour_order(): """Test making a contour plot using smooth_contour with tuple.""" @@ -251,7 +255,8 @@ def test_declarative_smooth_contour_order(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.063) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.114 if version_check('cartopy<0.23') else 0.058) @needs_cartopy def test_declarative_figsize(): """Test having an all float figsize.""" @@ -279,7 +284,8 @@ def test_declarative_figsize(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.039) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.104 if version_check('cartopy<0.23') else 0.033) @needs_cartopy def test_declarative_smooth_field(): """Test the smoothing of the field with smooth_field trait.""" @@ -367,7 +373,8 @@ def test_declarative_contour_options(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.085) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.152 if version_check('cartopy<0.23') else 0.009) @needs_cartopy def test_declarative_layers_plot_options(): """Test declarative layer options of edgecolor and linewidth.""" @@ -397,7 +404,8 @@ def test_declarative_layers_plot_options(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.021) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.055 if version_check('cartopy<0.23') else 0.009) @needs_cartopy def test_declarative_additional_layers_plot_options(): """Test additional declarative layer options of linestyle, zorder, and alpha.""" @@ -432,7 +440,9 @@ def test_declarative_additional_layers_plot_options(): @pytest.mark.mpl_image_compare( remove_text=True, - tolerance=2.74 if version_check('matplotlib<3.8') else 1.91) + tolerance=( + 3.34 if version_check('cartopy<0.23') else + 2.74 if version_check('matplotlib<3.8') else 1.91)) @needs_cartopy def test_declarative_contour_convert_units(): """Test making a contour plot.""" @@ -468,7 +478,6 @@ def test_declarative_contour_convert_units(): def test_declarative_events(): """Test that resetting traitlets properly propagates.""" data = xr.open_dataset(get_test_data('narr_example.nc', as_file_obj=False)) - contour = ContourPlot() contour.data = data contour.field = 'Temperature' @@ -658,7 +667,8 @@ def test_colorfill(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.02) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.238 if version_check('cartopy<0.23') else 0.004) def test_colorfill_with_image_range(cfeature): """Test that we can use ContourFillPlot with image_range bounds.""" data = xr.open_dataset(get_test_data('narr_example.nc', as_file_obj=False)) @@ -685,7 +695,9 @@ def test_colorfill_with_image_range(cfeature): @pytest.mark.mpl_image_compare( - remove_text=True, tolerance=0.02, filename='test_colorfill_with_image_range.png' + remove_text=True, + tolerance=0.238 if version_check('cartopy<0.23') else 0.004, + filename='test_colorfill_with_image_range.png' ) def test_colorfill_with_normalize_instance_image_range(cfeature): """Test that we can use ContourFillPlot with image_range bounds.""" @@ -763,7 +775,8 @@ def test_colorbar_kwargs(cfeature): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.02) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.370 if version_check('cartopy<0.23') else 0.005) def test_colorfill_no_colorbar(cfeature): """Test that we can use ContourFillPlot with no colorbar.""" data = xr.open_dataset(get_test_data('narr_example.nc', as_file_obj=False)) @@ -1041,7 +1054,8 @@ def test_declarative_overlay_projections(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.047) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.133 if version_check('cartopy<0.23') else 0.0094) @needs_cartopy def test_declarative_gridded_scale(): """Test making a contour plot.""" @@ -1099,7 +1113,7 @@ def test_declarative_global_gfs(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=1.05) +@pytest.mark.mpl_image_compare(remove_text=True, tolerance=1.42) @needs_cartopy def test_declarative_barb_gfs(): """Test making a contour plot.""" @@ -1128,7 +1142,7 @@ def test_declarative_barb_gfs(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.607) +@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.665) @needs_cartopy def test_declarative_barb_scale(): """Test making a contour plot.""" @@ -1158,7 +1172,7 @@ def test_declarative_barb_scale(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.668) +@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.722) @needs_cartopy def test_declarative_barb_gfs_knots(): """Test making a contour plot.""" @@ -1334,7 +1348,8 @@ def test_plotobs_units_with_formatter(ccrs, pandas_sfc): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.025) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.081 if version_check('cartopy<0.23') else 0.025) def test_declarative_sfc_obs(ccrs, pandas_sfc): """Test making a surface observation plot.""" obs = PlotObs() @@ -1363,7 +1378,8 @@ def test_declarative_sfc_obs(ccrs, pandas_sfc): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.025) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.075 if version_check('cartopy<0.23') else 0.) def test_declarative_sfc_obs_args(ccrs, pandas_sfc): """Test making a surface observation plot with mpl arguments.""" obs = PlotObs() @@ -1424,7 +1440,8 @@ def test_declarative_sfc_text(pandas_sfc): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.025) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.081 if version_check('cartopy<0.23') else 0.) def test_declarative_sfc_obs_changes(ccrs, pandas_sfc): """Test making a surface observation plot, changing the field.""" obs = PlotObs() @@ -1486,7 +1503,7 @@ def test_declarative_colored_barbs(ccrs, pandas_sfc): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.305) +@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.314) def test_declarative_sfc_obs_full(ccrs, pandas_sfc): """Test making a full surface observation plot.""" obs = PlotObs() @@ -1663,7 +1680,8 @@ def test_attribute_error_station(ccrs, pandas_sfc): plt.close(pc.figure) -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.024) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.082 if version_check('cartopy<0.23') else 0.) def test_declarative_sfc_obs_change_units(ccrs): """Test making a surface observation plot.""" data = parse_metar_file(get_test_data('metar_20190701_1200.txt', as_file_obj=False), @@ -1696,7 +1714,8 @@ def test_declarative_sfc_obs_change_units(ccrs): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.022) +@pytest.mark.mpl_image_compare(remove_text=True, + tolerance=0.125 if version_check('cartopy<0.23') else 0.0) def test_declarative_multiple_sfc_obs_change_units(ccrs): """Test making a surface observation plot.""" data = parse_metar_file(get_test_data('metar_20190701_1200.txt', as_file_obj=False), @@ -1761,7 +1780,8 @@ def test_declarative_title_fontsize(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=False, tolerance=0.607) +@pytest.mark.mpl_image_compare(remove_text=False, + tolerance=0.951 if version_check('cartopy<0.23') else 0.) @needs_cartopy def test_declarative_colorbar_fontsize(): """Test adjusting the font size of a colorbar.""" @@ -1933,7 +1953,7 @@ def test_declarative_region_modifier_zoom_in(): return pc.figure -@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.338) +@pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.377) @needs_cartopy def test_declarative_region_modifier_zoom_out(): """Test that '-' suffix on area string properly expands extent of map.""" diff --git a/tests/plots/test_mapping.py b/tests/plots/test_mapping.py index 8992112b790..271c29fc652 100644 --- a/tests/plots/test_mapping.py +++ b/tests/plots/test_mapping.py @@ -5,6 +5,8 @@ import pytest +from metpy.testing import version_check + ccrs = pytest.importorskip('cartopy.crs') from metpy.plots.mapping import CFProjection # noqa: E402 @@ -147,6 +149,7 @@ def test_lcc(): assert crs.globe.to_proj4_params()['ellps'] == 'sphere' +@pytest.mark.xfail(version_check('cartopy==0.23.0'), reason='SciTools/cartopy#2377') def test_lcc_minimal(): """Test handling lambert conformal conic projection with minimal attributes.""" attrs = {'grid_mapping_name': 'lambert_conformal_conic'} @@ -154,6 +157,7 @@ def test_lcc_minimal(): assert isinstance(crs, ccrs.LambertConformal) +@pytest.mark.xfail(version_check('cartopy==0.23.0'), reason='SciTools/cartopy#2377') def test_lcc_single_std_parallel(): """Test lambert conformal projection with one standard parallel.""" attrs = {'grid_mapping_name': 'lambert_conformal_conic', 'standard_parallel': 25} diff --git a/tests/plots/test_plot_areas.py b/tests/plots/test_plot_areas.py index 6328bcb88a3..0c3903f8cbc 100644 --- a/tests/plots/test_plot_areas.py +++ b/tests/plots/test_plot_areas.py @@ -6,8 +6,10 @@ import matplotlib.pyplot as plt import pytest +from metpy.testing import version_check -@pytest.mark.mpl_image_compare(tolerance=0.023) + +@pytest.mark.mpl_image_compare(tolerance=0.555 if version_check('cartopy<0.23') else 0.002) def test_uslcc_plotting(ccrs, cfeature): """Test plotting the uslcc area with projection.""" from metpy.plots import named_areas @@ -27,7 +29,7 @@ def test_uslcc_plotting(ccrs, cfeature): return fig -@pytest.mark.mpl_image_compare(tolerance=0.016) +@pytest.mark.mpl_image_compare(tolerance=0.119 if version_check('cartopy<0.23') else 0.) def test_au_plotting(ccrs, cfeature): """Test plotting the au area with projection.""" from metpy.plots import named_areas diff --git a/tutorials/README.md b/tutorials/README.md new file mode 100644 index 00000000000..a388761397f --- /dev/null +++ b/tutorials/README.md @@ -0,0 +1,36 @@ +# MetPy Tutorials + +Welcome to the MetPy tutorials! These tutorials are designed to help you get started with using MetPy for meteorological data analysis and visualization. Whether you're a beginner looking to explore the basics or an experienced user seeking advanced techniques, these tutorials will guide you through various aspects of MetPy. + +## Purpose + +The purpose of these tutorials is to provide hands-on examples and explanations to help you learn how to use MetPy effectively for your meteorological data analysis tasks. Each tutorial focuses on a specific aspect of MetPy, gradually building your understanding and skills as you progress through them. + +## Getting Started + +If this is your first time using MetPy head over to the [installation guide](https://unidata.github.io/MetPy/latest/userguide/installguide.html) to make sure the required dependencies have been installed. + +## Tutorials by Difficulty Level + +### Beginner Level + +1. **Area Tutorial**: Learn how to use predefined areas with MetPy. + +2. **Declarative Tutorial**: MetPy's declarative syntax simplifies data exploration and analysis by streamlining plotting in Python, hiding complexity to make data investigation more accessible. + +3. **Unit Tutorial**: Learn how to work with units within Metpy! + +### Intermediate Level + +1. **Upper Air Soundings**: Upper air analysis is a staple of many synoptic and mesoscale analysis problems. In this tutorial we will gather weather balloon data, plot it, perform a series of thermodynamic calculations, and summarize the results. + +2. **xarray with MetPy Tutorial**: This tutorial demonstrates how to work with xarray, a powerful Python package for labeled arrays and datasets. MetPy seamlessly integrates with xarray's data model, offering convenient methods and properties for coordinate, coordinate reference system, and unit operations. +### Advanced Level + +1. **Advanced Tutorials Coming Soon** + +The [Examples Gallery](https://unidata.github.io/MetPy/latest/examples/index.html) has more examples of what else you can create with MetPy! + +## Contribution + +We welcome contributions to these tutorials! If you have any suggestions for improvements or would like to add new tutorials feel free to submit an issue or make a pull request. More information on how to contribute can be found by checking out the [Contributors Guide](https://github.com/Unidata/MetPy/blob/main/CONTRIBUTING.md) diff --git a/tutorials/README.txt b/tutorials/README.txt deleted file mode 100644 index 568a1bf6c6d..00000000000 --- a/tutorials/README.txt +++ /dev/null @@ -1,7 +0,0 @@ -.. _tutorials-index: - -Tutorials -========= - -This collection of tutorials (under development) demonstrates the use of MetPy to perform -common meteorological tasks.