Skip to content

Commit 9297c72

Browse files
authored
Merge pull request #1014 from planetlabs/cloud-filter-subscriptions-1013
Add SDK support for cloud_filter tool in Subscriptions API
2 parents 8b29a93 + 27e74d8 commit 9297c72

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

planet/subscription_request.py

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
# the License.
1414
"""Functionality for preparing subscription requests."""
1515
from datetime import datetime
16-
from typing import Any, Dict, Optional, List, Mapping, Sequence
16+
from dataclasses import dataclass, asdict
17+
from typing import Any, Dict, Optional, List, Mapping, Sequence, Union
1718

1819
from typing_extensions import Literal
1920

@@ -651,3 +652,63 @@ def toar_tool(scale_factor: int = 10000) -> dict:
651652
reflectances not fitting in 16bit integers.
652653
"""
653654
return _tool('toar', {'scale_factor': scale_factor})
655+
656+
657+
@dataclass
658+
class FilterValue:
659+
"""Represents a filter value with optional greater than or equal to (gte)
660+
and less than or equal to (lte) constraints.
661+
662+
Attributes:
663+
gte (Optional[float]): The minimum threshold value for the filter.
664+
lte (Optional[float]): The maximum threshold value for the filter.
665+
"""
666+
667+
gte: Optional[float] = None
668+
lte: Optional[float] = None
669+
670+
671+
def cloud_filter_tool(
672+
clear_percent: Optional[FilterValue] = None,
673+
cloud_percent: Optional[FilterValue] = None,
674+
shadow_percent: Optional[FilterValue] = None,
675+
heavy_haze_percent: Optional[FilterValue] = None,
676+
light_haze_percent: Optional[FilterValue] = None,
677+
snow_ice_percent: Optional[FilterValue] = None,
678+
) -> Dict[str, Dict[str, Union[float, int]]]:
679+
"""Specify a subscriptions API cloud_filter tool.
680+
681+
The cloud_filter tool filters imagery after the clip tool has run and certain
682+
metadata values have been updated to pertain to the clip AOI. This tool offers
683+
a more detailed filtering of cloudy imagery than what can be achieved using
684+
only catalog source filters. For instance, you might want to receive only images
685+
that, after clipping, have a cloud_percent value of less than or equal to 25%.
686+
687+
Parameters:
688+
clear_percent: Filters for images based on the percentage of clear sky.
689+
cloud_percent: Filters for images based on the percentage of cloud cover.
690+
shadow_percent: Filters for images based on the percentage of shadow cover.
691+
heavy_haze_percent: Filters for images based on the percentage of heavy haze cover.
692+
light_haze_percent: Filters for images based on the percentage of light haze cover.
693+
snow_ice_percent: Filters for images based on the percentage of snow or ice cover.
694+
"""
695+
filters = {
696+
"clear_percent": clear_percent,
697+
"cloud_percent": cloud_percent,
698+
"shadow_percent": shadow_percent,
699+
"heavy_haze_percent": heavy_haze_percent,
700+
"light_haze_percent": light_haze_percent,
701+
"snow_ice_percent": snow_ice_percent,
702+
}
703+
704+
result = {}
705+
706+
for key, value in filters.items():
707+
if value:
708+
inner_dict = asdict(value)
709+
result[key] = {
710+
k: v
711+
for k, v in inner_dict.items() if v is not None
712+
}
713+
714+
return _tool("cloud_filter", result)

tests/unit/test_subscription_request.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,3 +407,22 @@ def test_catalog_source_time_range_type_acquired(geom_geojson):
407407
)
408408

409409
assert source["parameters"]["time_range_type"] == "acquired"
410+
411+
412+
def test_cloud_filter_tool_success():
413+
res = subscription_request.cloud_filter_tool(
414+
clear_percent=subscription_request.FilterValue(gte=90),
415+
cloud_percent=subscription_request.FilterValue(lte=10, gte=5))
416+
expected = {
417+
"type": "cloud_filter",
418+
"parameters": {
419+
"clear_percent": {
420+
"gte": 90
421+
},
422+
"cloud_percent": {
423+
"lte": 10, "gte": 5
424+
}
425+
}
426+
}
427+
428+
assert res == expected

0 commit comments

Comments
 (0)