diff --git a/src/coastsat/SDS_preprocess.py b/src/coastsat/SDS_preprocess.py index 83a99a4..dde28c1 100644 --- a/src/coastsat/SDS_preprocess.py +++ b/src/coastsat/SDS_preprocess.py @@ -971,7 +971,7 @@ def is_set(x, n): # erroneously identified as clouds by the CFMASK algorithm applied to the images by the USGS. if sum(sum(cloud_mask)) > 0 and sum(sum(~cloud_mask)) > 0: cloud_mask = morphology.remove_small_objects( - cloud_mask, min_size=40, connectivity=1 + cloud_mask, max_size=39, connectivity=1 ) # this is only for if the cloud mask was applied to the shoreline accidentally if cloud_mask_issue: @@ -983,7 +983,7 @@ def is_set(x, n): cloud_mask_temp, elem ) # perform image opening cloud_mask_temp = morphology.remove_small_objects( - cloud_mask_temp, min_size=100, connectivity=1 + cloud_mask_temp, max_size=99, connectivity=1 ) cloud_mask = np.logical_or(cloud_mask, cloud_mask_temp) diff --git a/tests/test_create_cloud_mask_thresholds.py b/tests/test_create_cloud_mask_thresholds.py new file mode 100644 index 0000000..7a836ba --- /dev/null +++ b/tests/test_create_cloud_mask_thresholds.py @@ -0,0 +1,54 @@ +import sys +import types +import warnings + +import numpy as np + + +if "osgeo" not in sys.modules: + osgeo_stub = types.ModuleType("osgeo") + osgeo_stub.gdal = types.SimpleNamespace() + osgeo_stub.osr = types.SimpleNamespace() + sys.modules["osgeo"] = osgeo_stub + +from coastsat import SDS_preprocess + + +def test_create_cloud_mask_keeps_size_40_removes_size_39_without_deprecation_warning(): + im_QA = np.zeros((30, 30), dtype=np.uint16) + im_QA[1:4, 1:14] = 8 # 39 pixels (3x13) + im_QA[10:15, 10:18] = 8 # 40 pixels (5x8) + + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + cloud_mask = SDS_preprocess.create_cloud_mask( + im_QA, satname="L8", cloud_mask_issue=False, collection="C02" + ) + + assert np.sum(cloud_mask) == 40 + assert cloud_mask[10:15, 10:18].all() + assert not cloud_mask[1:4, 1:14].any() + assert not any( + issubclass(w.category, FutureWarning) for w in caught_warnings + ), "create_cloud_mask should not emit FutureWarning from remove_small_objects." + + +def test_create_cloud_mask_issue_keeps_size_100_removes_size_99(monkeypatch): + im_QA = np.zeros((50, 50), dtype=np.uint16) + im_QA[1:10, 1:12] = 8 # 99 pixels (9x11) + im_QA[20:30, 20:30] = 8 # 100 pixels (10x10) + + monkeypatch.setattr( + SDS_preprocess.morphology, "binary_opening", lambda image, _: image + ) + monkeypatch.setattr( + SDS_preprocess.morphology, "square", lambda width: np.ones((width, width), dtype=bool) + ) + + cloud_mask = SDS_preprocess.create_cloud_mask( + im_QA, satname="L8", cloud_mask_issue=True, collection="C02" + ) + + assert np.sum(cloud_mask) == 100 + assert cloud_mask[20:30, 20:30].all() + assert not cloud_mask[1:10, 1:12].any()