|
| 1 | +from datetime import datetime |
| 2 | +import openeo |
| 3 | +from openeo import processes, UDF |
| 4 | + |
| 5 | +from efast.constants import S3L2SYNClassificationAerosolFlags, S3L2SYNCloudFlags |
| 6 | +from efast.openeo.preprocessing.general import _extract_bit_mask |
| 7 | + |
| 8 | +from . import extract_mask |
| 9 | + |
| 10 | +DATE_FORMAT = "%Y-%m-%d" |
| 11 | + |
| 12 | + |
| 13 | +def extract_clear_land_mask(s3_cube: openeo.DataCube): |
| 14 | + CLOUD_FLAGS_COMBINED = ( |
| 15 | + S3L2SYNCloudFlags.CLOUD |
| 16 | + | S3L2SYNCloudFlags.CLOUD_AMBIGUOUS |
| 17 | + | S3L2SYNCloudFlags.CLOUD_MARGIN |
| 18 | + ) |
| 19 | + cloud_mask = (s3_cube.band("CLOUD_flags") & CLOUD_FLAGS_COMBINED.value) != 0 |
| 20 | + land_mask = ( |
| 21 | + s3_cube.band("SYN_flags") & S3L2SYNClassificationAerosolFlags.SYN_land.value |
| 22 | + ) != 0 |
| 23 | + return ((cloud_mask == 0) & land_mask) != 0 |
| 24 | + |
| 25 | + |
| 26 | +# TODO add land mask, broken |
| 27 | +# TODO debug as a batch job, to access logs |
| 28 | +def _extract_clear_land_mask(s3_cube: openeo.DataCube) -> openeo.DataCube: |
| 29 | + mask = _extract_bit_mask( |
| 30 | + s3_cube, |
| 31 | + { |
| 32 | + "CLOUD_flags": ( |
| 33 | + S3L2SYNCloudFlags.CLOUD |
| 34 | + | S3L2SYNCloudFlags.CLOUD_AMBIGUOUS |
| 35 | + | S3L2SYNCloudFlags.CLOUD_MARGIN |
| 36 | + ).value |
| 37 | + }, |
| 38 | + invert=True, |
| 39 | + ) # | extract_bit_mask( |
| 40 | + # s3_cube, |
| 41 | + # { |
| 42 | + # "SYN_flags": S3L2SYNClassificationAerosolFlags.SYN_land.value, |
| 43 | + # }, |
| 44 | + # ) |
| 45 | + return mask |
| 46 | + |
| 47 | + |
| 48 | +def composite(cube): |
| 49 | + # What we want: sliding window computation |
| 50 | + # distance_to_cloud_score = compute_distance_to_cloud_score(distance_to_cloud) # add normalization |
| 51 | + # merged = distance_to_cloud_score.merge_cubes(cube) |
| 52 | + # merged.apply_neighbourhood(process=produce_weighted_composite) |
| 53 | + pass |
| 54 | + |
| 55 | + |
| 56 | +# TODO rename D to something more useful |
| 57 | +def compute_distance_to_cloud_score( |
| 58 | + distance_to_cloud: processes.ProcessBuilder, D: float |
| 59 | +) -> processes.ProcessBuilder: |
| 60 | + score = (distance_to_cloud - 1) / D |
| 61 | + return processes.clip(score, 0.0, 1.0) |
| 62 | + |
| 63 | + |
| 64 | +def compute_time_weighted_cube( |
| 65 | + unweighted_cube: processes.ProcessBuilder, target_date: datetime |
| 66 | +) -> processes.ProcessBuilder: |
| 67 | + udf_compute_temporal_score = UDF.from_file( |
| 68 | + "efast/openeo/udf/compute_temporal_score", |
| 69 | + context={"target_date": target_date.strftime(DATE_FORMAT)}, |
| 70 | + ) |
| 71 | + return unweighted_cube.apply_dimension( |
| 72 | + process=udf_compute_temporal_score, dimension="t" |
| 73 | + ) |
| 74 | + |
| 75 | + |
| 76 | +def produce_weighted_composite( |
| 77 | + s3_cube: processes.ProcessBuilder, |
| 78 | + distance_to_cloud_score: processes.ProcessBuilder, |
| 79 | + target_date: datetime, |
| 80 | +) -> processes.ProcessBuilder: |
| 81 | + """ |
| 82 | + :param distance_to_cloud_score: |
| 83 | + """ |
| 84 | + # input1: all relevant Sentinel-3 images to produce a single output composite |
| 85 | + # input2: distance to cloud scores for all Sentinel-3 observations to avoid |
| 86 | + # recomputing them for each composite |
| 87 | + |
| 88 | + pass |
0 commit comments