Skip to content

Commit

Permalink
Merge pull request pytroll#2521 from mraspaud/feature_median_filter
Browse files Browse the repository at this point in the history
Add a median filter modifier
  • Loading branch information
mraspaud authored Jun 28, 2023
2 parents 04c80e3 + d22e117 commit 9b9e890
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 1 deletion.
1 change: 1 addition & 0 deletions continuous_integration/environment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ dependencies:
- xarray!=2022.9.0
- dask
- distributed
- dask-image
- donfig
- appdirs
- toolz
Expand Down
1 change: 1 addition & 0 deletions doc/rtd_environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ dependencies:
- pip
- appdirs
- dask
- dask-image
- defusedxml
- donfig
# 2.19.1 seems to cause library linking issues
Expand Down
5 changes: 5 additions & 0 deletions satpy/etc/composites/visir.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ modifiers:
- solar_azimuth_angle
- solar_zenith_angle

median5x5:
modifier: !!python/name:satpy.modifiers.filters.Median
median_filter_params:
size: 5

composites:

airmass:
Expand Down
34 changes: 34 additions & 0 deletions satpy/modifiers/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Tests for image filters."""
import logging

import xarray as xr

from satpy.modifiers import ModifierBase

logger = logging.getLogger(__name__)


class Median(ModifierBase):
"""Apply a median filter to the band."""

def __init__(self, median_filter_params, **kwargs):
"""Create the instance.
Args:
median_filter_params: The arguments to pass to dask-image's median_filter function. For example, {size: 3}
makes give the median filter a kernel of size 3.
"""
self.median_filter_params = median_filter_params
super().__init__(**kwargs)

def __call__(self, arrays, **info):
"""Get the median filtered band."""
from dask_image.ndfilters import median_filter

data = arrays[0]
logger.debug(f"Apply median filtering with parameters {self.median_filter_params}.")
res = xr.DataArray(median_filter(data.data, **self.median_filter_params),
dims=data.dims, attrs=data.attrs, coords=data.coords)
self.apply_modifier_info(data, res)
return res
35 changes: 35 additions & 0 deletions satpy/tests/modifier_tests/test_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Implementation of some image filters."""

import logging

import dask.array as da
import numpy as np
import xarray as xr

from satpy.modifiers.filters import Median


def test_median(caplog):
"""Test the median filter modifier."""
caplog.set_level(logging.DEBUG)
dims = "y", "x"
coordinates = dict(x=np.arange(6), y=np.arange(6))
attrs = dict(units="K")
median_filter_params = dict(size=3)
name = "median_filter"
median_filter = Median(median_filter_params, name=name)
array = xr.DataArray(da.arange(36).reshape((6, 6)), coords=coordinates, dims=dims, attrs=attrs)
res = median_filter([array])
filtered_array = np.array([[1, 2, 3, 4, 5, 5],
[6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29],
[30, 30, 31, 32, 33, 34]])
np.testing.assert_allclose(res, filtered_array)
assert res.dims == dims
assert attrs.items() <= res.attrs.items()
assert res.attrs["name"] == name
np.testing.assert_equal(res.coords["x"], coordinates["x"])
np.testing.assert_equal(res.coords["y"], coordinates["y"])
assert "Apply median filtering with parameters {'size': 3}" in caplog.text
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
'rasterio', 'geoviews', 'trollimage', 'fsspec', 'bottleneck',
'rioxarray', 'pytest', 'pytest-lazy-fixture', 'defusedxml',
's3fs', 'eccodes', 'h5netcdf', 'xarray-datatree',
'skyfield', 'ephem', 'pint-xarray', 'astropy']
'skyfield', 'ephem', 'pint-xarray', 'astropy', 'dask-image']

extras_require = {
# Readers:
Expand Down Expand Up @@ -77,6 +77,7 @@
# Composites/Modifiers:
'rayleigh': ['pyspectral >= 0.10.1'],
'angles': ['pyorbital >= 1.3.1'],
'filters': ['dask-image'],
# MultiScene:
'animations': ['imageio'],
# Documentation:
Expand Down

0 comments on commit 9b9e890

Please sign in to comment.