diff --git a/doc/source/composites.rst b/doc/source/composites.rst index 4d457c40d9..4804aba0df 100644 --- a/doc/source/composites.rst +++ b/doc/source/composites.rst @@ -516,7 +516,6 @@ Enhancing the images - stretch - gamma - invert - - crefl_scaling - cira_stretch - lookup - colorize diff --git a/doc/source/enhancements.rst b/doc/source/enhancements.rst index 0386f6a4c7..9623c1b120 100644 --- a/doc/source/enhancements.rst +++ b/doc/source/enhancements.rst @@ -60,11 +60,6 @@ gamma invert ------ -crefl_scaling -------------- - -Deprecated. Use 'piecewise_linear_stretch' instead. - piecewise_linear_stretch ------------------------ diff --git a/satpy/_config.py b/satpy/_config.py index 58bcc70452..2b583c435c 100644 --- a/satpy/_config.py +++ b/satpy/_config.py @@ -25,8 +25,9 @@ import sys import tempfile from collections import OrderedDict -from importlib.metadata import entry_points +from importlib.metadata import EntryPoint, entry_points from pathlib import Path +from typing import Iterable try: from importlib.resources import files as impr_files # type: ignore @@ -123,10 +124,10 @@ def get_config_path_safe(): return config_path -def get_entry_points_config_dirs(name, include_config_path=True): +def get_entry_points_config_dirs(group_name: str, include_config_path: bool = True) -> list[str]: """Get the config directories for all entry points of given name.""" - dirs = [] - for entry_point in cached_entry_points().get(name, []): + dirs: list[str] = [] + for entry_point in cached_entry_point(group_name): module = _entry_point_module(entry_point) new_dir = str(impr_files(module) / "etc") if not dirs or dirs[-1] != new_dir: @@ -137,12 +138,21 @@ def get_entry_points_config_dirs(name, include_config_path=True): @cache -def cached_entry_points(): - """Return entry_points. +def cached_entry_point(group_name: str) -> Iterable[EntryPoint]: + """Return entry_point for specified ``group``. + + This is a dummy proxy to allow caching and provide compatibility between + versions of Python and importlib_metadata. - This is a dummy proxy to allow caching. """ - return entry_points() + try: + # mypy in pre-commit currently checks for Python 3.8 compatibility + # this line is for Python 3.10+ so it will fail checks + return entry_points(group=group_name) # type: ignore + except TypeError: + # Python <3.10 + entry_points_list = entry_points() + return entry_points_list.get(group_name, []) def _entry_point_module(entry_point): diff --git a/satpy/enhancements/__init__.py b/satpy/enhancements/__init__.py index 29f2cbdf54..b0fa2b8aa3 100644 --- a/satpy/enhancements/__init__.py +++ b/satpy/enhancements/__init__.py @@ -17,7 +17,6 @@ import logging import os -import warnings from collections import namedtuple from functools import wraps from numbers import Number @@ -126,18 +125,6 @@ def wrapper(data, **kwargs): return on_dask_array(wrapper) -def crefl_scaling(img, **kwargs): - """Apply non-linear stretch used by CREFL-based RGBs.""" - LOG.debug("Applying the crefl_scaling") - warnings.warn( - "'crefl_scaling' is deprecated, use 'piecewise_linear_stretch' instead.", - DeprecationWarning, - stacklevel=2 - ) - img.data.data = img.data.data / 100 - return piecewise_linear_stretch(img, xp=kwargs['idx'], fp=kwargs['sc'], reference_scale_factor=255) - - def piecewise_linear_stretch( img: XRImage, xp: ArrayLike, diff --git a/satpy/readers/ami_l1b.py b/satpy/readers/ami_l1b.py index 9070da9252..4569b996fa 100644 --- a/satpy/readers/ami_l1b.py +++ b/satpy/readers/ami_l1b.py @@ -161,10 +161,10 @@ def get_orbital_parameters(self): sc_position = self.nc['sc_position'].attrs['sc_position_center_pixel'] # convert ECEF coordinates to lon, lat, alt - ecef = pyproj.Proj(proj='geocent', a=a, b=b) - lla = pyproj.Proj(proj='latlong', a=a, b=b) - sc_position = pyproj.transform( - ecef, lla, sc_position[0], sc_position[1], sc_position[2]) + ecef = pyproj.CRS.from_dict({"proj": "geocent", "a": a, "b": b}) + lla = pyproj.CRS.from_dict({"proj": "latlong", "a": a, "b": b}) + transformer = pyproj.Transformer.from_crs(ecef, lla) + sc_position = transformer.transform(sc_position[0], sc_position[1], sc_position[2]) orbital_parameters = { 'projection_longitude': float(lon_0), diff --git a/satpy/readers/utils.py b/satpy/readers/utils.py index aae17d142d..7e5da3be51 100644 --- a/satpy/readers/utils.py +++ b/satpy/readers/utils.py @@ -391,9 +391,10 @@ def get_earth_radius(lon, lat, a, b): Earth Radius (meters) """ - geocent = pyproj.Proj(proj='geocent', a=a, b=b, units='m') - latlong = pyproj.Proj(proj='latlong', a=a, b=b, units='m') - x, y, z = pyproj.transform(latlong, geocent, lon, lat, 0.) + geocent = pyproj.CRS.from_dict({"proj": "geocent", "a": a, "b": b, "units": "m"}) + latlong = pyproj.CRS.from_dict({"proj": "latlong", "a": a, "b": b, "units": "m"}) + transformer = pyproj.Transformer.from_crs(latlong, geocent) + x, y, z = transformer.transform(lon, lat, 0.0) return np.sqrt(x**2 + y**2 + z**2) diff --git a/satpy/scene.py b/satpy/scene.py index 7579b30a92..d43c9d80d2 100644 --- a/satpy/scene.py +++ b/satpy/scene.py @@ -1006,10 +1006,15 @@ def to_geoviews(self, gvtype=None, datasets=None, kdims=None, vdims=None, dynami datasets (list): Limit included products to these datasets kdims (list of str): Key dimensions. See geoviews documentation for more information. - vdims : list of str, optional + vdims (list of str, optional): Value dimensions. See geoviews documentation for more information. If not given defaults to first data variable - dynamic : boolean, optional, default False + dynamic (bool, optional): Load and compute data on-the-fly during + visualization. Default is ``False``. See + https://holoviews.org/user_guide/Gridded_Datasets.html#working-with-xarray-data-types + for more information. Has no effect when data to be visualized + only has 2 dimensions (y/x or longitude/latitude) and doesn't + require grouping via the Holoviews ``groupby`` function. Returns: geoviews object @@ -1035,10 +1040,12 @@ def to_geoviews(self, gvtype=None, datasets=None, kdims=None, vdims=None, dynami else: gvds = gv.Dataset(ds) + # holoviews produces a log warning if you pass groupby arguments when groupby isn't used + groupby_kwargs = {"dynamic": dynamic} if gvds.ndims != 2 else {} if "latitude" in ds.coords: - gview = gvds.to(gv.QuadMesh, kdims=["longitude", "latitude"], vdims=vdims, dynamic=dynamic) + gview = gvds.to(gv.QuadMesh, kdims=["longitude", "latitude"], vdims=vdims, **groupby_kwargs) else: - gview = gvds.to(gvtype, kdims=["x", "y"], vdims=vdims, dynamic=dynamic) + gview = gvds.to(gvtype, kdims=["x", "y"], vdims=vdims, **groupby_kwargs) return gview diff --git a/satpy/tests/compositor_tests/test_spectral.py b/satpy/tests/compositor_tests/test_spectral.py index 2e9f59c13f..467adf119b 100644 --- a/satpy/tests/compositor_tests/test_spectral.py +++ b/satpy/tests/compositor_tests/test_spectral.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU General Public License along with # satpy. If not, see . """Tests for spectral correction compositors.""" +import warnings import dask.array as da import numpy as np @@ -87,8 +88,10 @@ def test_ndvi_hybrid_green(self): def test_green_corrector(self): """Test the deprecated class for green corrections.""" - comp = GreenCorrector('blended_channel', fractions=(0.85, 0.15), prerequisites=(0.51, 0.85), - standard_name='toa_bidirectional_reflectance') + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=UserWarning, message=r'.*deprecated.*') + comp = GreenCorrector('blended_channel', fractions=(0.85, 0.15), prerequisites=(0.51, 0.85), + standard_name='toa_bidirectional_reflectance') res = comp((self.c01, self.c03)) assert isinstance(res, xr.DataArray) assert isinstance(res.data, da.Array) diff --git a/satpy/tests/enhancement_tests/test_enhancements.py b/satpy/tests/enhancement_tests/test_enhancements.py index 89ce222ecd..8cef879352 100644 --- a/satpy/tests/enhancement_tests/test_enhancements.py +++ b/satpy/tests/enhancement_tests/test_enhancements.py @@ -178,15 +178,6 @@ def test_three_d_effect(self): [np.nan, np.nan, 85.5, 180.5, 1301.5]]]) run_and_check_enhancement(three_d_effect, self.ch1, expected) - def test_crefl_scaling(self): - """Test the crefl_scaling enhancement function.""" - from satpy.enhancements import crefl_scaling - expected = np.array([[ - [np.nan, 0., 0., 0.44378, 0.631734], - [0.737562, 0.825041, 0.912521, 1., 1.]]]) - run_and_check_enhancement(crefl_scaling, self.ch2, expected, idx=[0., 25., 55., 100., 255.], - sc=[0., 90., 140., 175., 255.]) - def test_piecewise_linear_stretch(self): """Test the piecewise_linear_stretch enhancement function.""" from satpy.enhancements import piecewise_linear_stretch diff --git a/satpy/tests/multiscene_tests/test_utils.py b/satpy/tests/multiscene_tests/test_utils.py index 22817d7629..409eb9cf86 100644 --- a/satpy/tests/multiscene_tests/test_utils.py +++ b/satpy/tests/multiscene_tests/test_utils.py @@ -62,18 +62,16 @@ def _fake_get_enhanced_image(img, enhance=None, overlay=None, decorate=None): def _create_test_area(proj_str=None, shape=DEFAULT_SHAPE, extents=None): """Create a test area definition.""" - from pyresample.utils import proj4_str_to_dict if proj_str is None: proj_str = '+proj=lcc +datum=WGS84 +ellps=WGS84 +lon_0=-95. ' \ '+lat_0=25 +lat_1=25 +units=m +no_defs' - proj_dict = proj4_str_to_dict(proj_str) extents = extents or (-1000., -1500., 1000., 1500.) return AreaDefinition( 'test', 'test', 'test', - proj_dict, + proj_str, shape[1], shape[0], extents diff --git a/satpy/tests/reader_tests/test_satpy_cf_nc.py b/satpy/tests/reader_tests/test_satpy_cf_nc.py index 52206e72b8..605f595e1f 100644 --- a/satpy/tests/reader_tests/test_satpy_cf_nc.py +++ b/satpy/tests/reader_tests/test_satpy_cf_nc.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License along with # satpy. If not, see . """Tests for the CF reader.""" - +import warnings from datetime import datetime import numpy as np @@ -371,12 +371,14 @@ def test_read_prefixed_channels_by_user_include_prefix(self, _cf_scene, _nc_file def test_read_prefixed_channels_by_user_no_prefix(self, _cf_scene, _nc_filename): """Check channels starting with digit is not prefixed by user.""" - _cf_scene.save_datasets(writer='cf', - filename=_nc_filename, - engine='netcdf4', - flatten_attrs=True, - pretty=True, - numeric_name_prefix='') + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=UserWarning, message=".*starts with a digit.*") + _cf_scene.save_datasets(writer='cf', + filename=_nc_filename, + engine='netcdf4', + flatten_attrs=True, + pretty=True, + numeric_name_prefix='') scn_ = Scene(reader='satpy_cf_nc', filenames=[_nc_filename]) scn_.load(['1']) diff --git a/satpy/tests/reader_tests/test_seviri_l1b_native.py b/satpy/tests/reader_tests/test_seviri_l1b_native.py index 6bf5d2705d..a1a73179e2 100644 --- a/satpy/tests/reader_tests/test_seviri_l1b_native.py +++ b/satpy/tests/reader_tests/test_seviri_l1b_native.py @@ -21,6 +21,7 @@ import os import unittest +import warnings from datetime import datetime from unittest import mock @@ -1279,7 +1280,8 @@ def test_satpos_no_valid_orbit_polynomial(self, file_handler): 'wavelength': (1, 2, 3), 'standard_name': 'counts' } - res = file_handler.get_dataset(dataset_id, dataset_info) + with pytest.warns(UserWarning, match="No orbit polynomial"): + res = file_handler.get_dataset(dataset_id, dataset_info) assert 'satellite_actual_longitude' not in res.attrs[ 'orbital_parameters'] @@ -1401,7 +1403,8 @@ def test_header_warning(): exp_warning = "The quality flag for this file indicates not OK. Use this data with caution!" fromfile.return_value = header_good - with pytest.warns(None): + with warnings.catch_warnings(): + warnings.simplefilter("error") NativeMSGFileHandler('myfile', {}, None) fromfile.return_value = header_bad diff --git a/satpy/tests/test_config.py b/satpy/tests/test_config.py index e44a6a65e4..10d3205223 100644 --- a/satpy/tests/test_config.py +++ b/satpy/tests/test_config.py @@ -31,7 +31,7 @@ import satpy from satpy import DatasetDict -from satpy._config import cached_entry_points +from satpy._config import cached_entry_point from satpy.composites.config_loader import load_compositor_configs_for_sensors # NOTE: @@ -66,8 +66,7 @@ def test_areas_pyproj(self): # we didn't provide enough info to freeze, hard to guess # in a generic test so just skip this area continue - proj_dict = area_obj.proj_dict - _ = pyproj.Proj(proj_dict) + _ = pyproj.Proj(area_obj.crs) def test_areas_rasterio(self): """Test all areas have valid projections with rasterio.""" @@ -99,14 +98,7 @@ def test_areas_rasterio(self): # we didn't provide enough info to freeze, hard to guess # in a generic test so just skip this area continue - proj_dict = area_obj.proj_dict - if proj_dict.get('proj') in ('ob_tran', 'nsper') and \ - 'wktext' not in proj_dict: - # FIXME: rasterio doesn't understand ob_tran unless +wktext - # See: https://github.com/pyproj4/pyproj/issues/357 - # pyproj 2.0+ seems to drop wktext from PROJ dict - continue - _ = CRS.from_dict(proj_dict) + _ = CRS.from_user_input(area_obj.crs) @contextlib.contextmanager @@ -299,7 +291,7 @@ class TestPluginsConfigs: def setup_method(self): """Set up the test.""" - cached_entry_points.cache_clear() + cached_entry_point.cache_clear() def test_get_plugin_configs(self, fake_composite_plugin_etc_path): """Check that the plugin configs are looked for."""