Skip to content

Commit e32eb62

Browse files
authored
Merge pull request #146 from betonr/master
Fix landsat harmonization and update qa_mask (lc8-collection2)
2 parents 27469b2 + cbd61e1 commit e32eb62

File tree

13 files changed

+1048
-273
lines changed

13 files changed

+1048
-273
lines changed

cube_builder_aws/cube_builder_aws/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@
2323
DYNAMO_TB_ACTIVITY = os.environ.get('DYNAMO_TB_ACTIVITY', '')
2424
DBNAME_TB_CONTROL = os.environ.get('DBNAME_TB_CONTROL', '')
2525
DBNAME_TB_PROCESS = os.environ.get('DBNAME_TB_PROCESS', '')
26+
DBNAME_TB_HARM = os.environ.get('DBNAME_TB_HARM', '')

cube_builder_aws/cube_builder_aws/constants.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,16 @@
152152

153153
PNG_MIME_TYPE = 'image/png'
154154

155-
SRID_ALBERS_EQUAL_AREA = 100001
155+
SRID_ALBERS_EQUAL_AREA = 100001
156+
157+
HARMONIZATION = dict(
158+
landsat = dict(
159+
bands = dict(
160+
L05 = ["SR_B1" ,"SR_B2", "SR_B3", "SR_B4", "SR_B5", "SR_B7"],
161+
L07 = ["SR_B1" ,"SR_B2", "SR_B3", "SR_B4", "SR_B5", "SR_B7"],
162+
L08 = ["SR_B2", "SR_B3", "SR_B4", "SR_B5", "SR_B6", "SR_B7"]
163+
),
164+
bucket_src = 's3://usgs-landsat',
165+
format_path = 'collection{collectionNumber}/level-2/standard/{instrument}/{acquisitionYear}/{path}/{row}/{scene_id}/{scene_id}_{band}.TIF'
166+
)
167+
)

cube_builder_aws/cube_builder_aws/controller.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,30 @@
1212
from datetime import datetime
1313
from typing import Tuple, Union
1414

15-
import rasterio
1615
import sqlalchemy
1716
from bdc_catalog.models import (Band, BandSRC, Collection, CompositeFunction,
1817
GridRefSys, Item, MimeType, Quicklook,
1918
ResolutionUnit, SpatialRefSys, Tile)
20-
from bdc_catalog.models.base_sql import BaseModel, db
19+
from bdc_catalog.models.base_sql import db
2120
from geoalchemy2 import func
2221
from geoalchemy2.shape import from_shape
2322
from rasterio.crs import CRS
2423
from rasterio.warp import transform
2524
from shapely.geometry import Polygon
26-
from werkzeug.exceptions import BadRequest, Conflict, NotFound
25+
from werkzeug.exceptions import BadRequest, NotFound
2726

2827
from .config import ITEM_PREFIX
29-
from .constants import (CENTER_WAVELENGTH, CLEAR_OBSERVATION_ATTRIBUTES,
30-
CLEAR_OBSERVATION_NAME, COG_MIME_TYPE,
31-
DATASOURCE_ATTRIBUTES, FULL_WIDTH_HALF_MAX,
28+
from .constants import (CLEAR_OBSERVATION_ATTRIBUTES, CLEAR_OBSERVATION_NAME,
29+
COG_MIME_TYPE, DATASOURCE_ATTRIBUTES,
3230
PROVENANCE_ATTRIBUTES, PROVENANCE_NAME,
33-
REVISIT_BY_SATELLITE, SRID_ALBERS_EQUAL_AREA,
34-
SRID_BDC_GRID, TOTAL_OBSERVATION_ATTRIBUTES,
31+
SRID_ALBERS_EQUAL_AREA, TOTAL_OBSERVATION_ATTRIBUTES,
3532
TOTAL_OBSERVATION_NAME)
3633
from .forms import CollectionForm
37-
from .maestro import (blend, merge_warped, orchestrate, posblend,
38-
prepare_merge, publish, solo)
34+
from .maestro import (blend, harmonization, merge_warped, orchestrate,
35+
posblend, prepare_harm, prepare_merge, publish, solo)
3936
from .services import CubeServices
4037
from .utils.image import validate_merges
41-
from .utils.processing import (format_version, generate_hash_md5,
42-
get_cube_name, get_cube_parts, get_date,
38+
from .utils.processing import (format_version, get_cube_parts, get_date,
4339
get_or_create_model)
4440
from .utils.serializer import DecimalEncoder, Serializer
4541
from .utils.timeline import Timeline
@@ -59,6 +55,10 @@ def continue_process_stream(self, params_list):
5955
if 'channel' in params and params['channel'] == 'kinesis':
6056
solo(self, params_list)
6157

58+
# dispatch HARMONIZATION
59+
elif params['action'] == 'harmonization':
60+
harmonization(self, params)
61+
6262
# dispatch MERGE
6363
elif params['action'] == 'merge':
6464
merge_warped(self, params)
@@ -246,7 +246,7 @@ def _create_cube_definition(self, cube_id: str, params: dict) -> dict:
246246
collection=cube,
247247
min_value=0,
248248
max_value=10000 if is_not_cloud else 4,
249-
nodata=-9999 if is_not_cloud else 255,
249+
nodata=band['nodata'],
250250
scale=0.0001 if is_not_cloud else 1,
251251
data_type=data_type,
252252
resolution_x=params['resolution'],
@@ -287,7 +287,8 @@ def _create_cube_definition(self, cube_id: str, params: dict) -> dict:
287287
_ = self.get_or_create_band(cube.id, **PROVENANCE_ATTRIBUTES, resolution_unit_id=resolution_meter.id,
288288
resolution_x=params['resolution'], resolution_y=params['resolution'])
289289

290-
if params.get('is_combined') and function != 'MED':
290+
landsat_harm = params['parameters'].get('landsat_harmonization')
291+
if landsat_harm and landsat_harm.get('datasets') and function != 'MED':
291292
_ = self.get_or_create_band(cube.id, **DATASOURCE_ATTRIBUTES, resolution_unit_id=resolution_meter.id,
292293
resolution_x=params['resolution'], resolution_y=params['resolution'])
293294

@@ -465,6 +466,15 @@ def get_cube_status(self, cube_name):
465466
error = 0
466467
), 200
467468

469+
470+
def start_harmonization_process(self, params):
471+
_ = prepare_harm(self, params['scenes'], params['bucket_dst'], params['bucket_angles'])
472+
473+
return dict(
474+
message='Harmonization processing started with succesfully'
475+
), 200
476+
477+
468478
def start_process(self, params):
469479
response = {}
470480
datacube_identify = f'{params["datacube"]}-{params["datacube_version"]}'

cube_builder_aws/cube_builder_aws/forms.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,29 @@ class BandDefinition(Schema):
5656
name = fields.String(required=True, allow_none=False)
5757
common_name = fields.String(required=True, allow_none=False)
5858
data_type = fields.String(required=True, allow_none=False, validate=OneOf(SUPPORTED_DATA_TYPES))
59+
nodata = fields.Integer(required=False, allow_none=False)
5960
metadata = fields.Dict(required=False, allow_none=False)
6061

6162

63+
class QAConfidence(Schema):
64+
"""Define that will discard all cloud values which has confidence greater or equal MEDIUM.
65+
qa = QAConfidence(cloud='cloud >= MEDIUM', cloud_shadow=None, cirrus=None, snow=None, landsat_8=True)."""
66+
67+
cloud = fields.String(required=False, allow_none=True)
68+
cloud_shadow = fields.String(required=False, allow_none=True)
69+
cirrus = fields.String(required=False, allow_none=True)
70+
snow = fields.String(required=False, allow_none=True)
71+
72+
6273
class CustomMaskDefinition(Schema):
6374
"""Define a custom mask."""
6475

6576
clear_data = fields.List(fields.Integer, required=True, allow_none=False)
6677
not_clear_data = fields.List(fields.Integer, required=True, allow_none=False)
6778
saturated_data = fields.List(fields.Integer, required=True, allow_none=False)
6879
nodata = fields.Integer(required=True, allow_none=False)
80+
bits = fields.Boolean(required=False, allow_none=False, default=False)
81+
confidence = fields.Nested(QAConfidence)
6982

7083

7184
class StacDefinitionForm(Schema):
@@ -76,6 +89,15 @@ class StacDefinitionForm(Schema):
7689
collection = fields.String(required=True, allow_none=False)
7790

7891

92+
class LandsatHarmonization(Schema):
93+
"""Define parser for params of the landsat harmonization."""
94+
95+
apply = fields.Boolean(required=False, allow_none=False, default=False)
96+
bucket_dst = fields.String(required=True, allow_none=False)
97+
datasets = fields.List(fields.String(required=True, allow_none=False))
98+
map_bands = fields.Dict(required=False, allow_none=False)
99+
100+
79101
class DataCubeForm(Schema):
80102
"""Define parser for datacube creation."""
81103

@@ -98,7 +120,8 @@ class DataCubeForm(Schema):
98120
is_combined = fields.Boolean(required=False, allow_none=False, default=False)
99121
parameters = fields.Dict(
100122
mask = fields.Nested(CustomMaskDefinition),
101-
stac_list = fields.List(fields.Nested(StacDefinitionForm))
123+
stac_list = fields.List(fields.Nested(StacDefinitionForm)),
124+
landsat_harmonization = fields.Nested(LandsatHarmonization)
102125
)
103126

104127
@pre_load
@@ -167,6 +190,15 @@ class DataCubeProcessForm(Schema):
167190
indexes_only_regular_cube = fields.Boolean(required=False, allow_none=True, default=False)
168191

169192

193+
class DataCubeHarmonizationForm(Schema):
194+
"""Define parser for harmonization generate."""
195+
196+
scenes = fields.List(fields.String, required=True, allow_none=False)
197+
bucket_dst = fields.String(required=True, allow_none=False)
198+
bucket_angles = fields.String(required=True, allow_none=False)
199+
satellite = fields.String(required=True, allow_none=False, validate=OneOf(['landsat']))
200+
201+
170202
class PeriodForm(Schema):
171203
"""Define parser for Data Cube Periods."""
172204

0 commit comments

Comments
 (0)