@@ -275,14 +275,15 @@ def harmonization(self, activity):
275
275
# MERGE
276
276
###############################
277
277
def prepare_merge (self , datacube , irregular_datacube , datasets , satellite , bands , bands_ids ,
278
- quicklook , resx , resy , nodata , crs , quality_band , functions , version ,
278
+ quicklook , resx , resy , crs , nodata , quality_nodata , quality_band , functions , version ,
279
279
force = False , mask = None , bands_expressions = dict (), indexes_only_regular_cube = False ,
280
280
landsat_harmonization = None ):
281
281
services = self .services
282
282
283
283
# Build the basics of the merge activity
284
284
activity = {}
285
285
activity ['action' ] = 'merge'
286
+ activity ['bucket_name' ] = services .bucket_name
286
287
activity ['datacube' ] = datacube
287
288
activity ['irregular_datacube' ] = irregular_datacube
288
289
activity ['version' ] = version
@@ -294,9 +295,9 @@ def prepare_merge(self, datacube, irregular_datacube, datasets, satellite, bands
294
295
activity ['quicklook' ] = quicklook
295
296
activity ['resx' ] = resx
296
297
activity ['resy' ] = resy
297
- activity ['nodata' ] = nodata
298
298
activity ['srs' ] = crs
299
- activity ['bucket_name' ] = services .bucket_name
299
+ activity ['nodata' ] = int (nodata )
300
+ activity ['quality_nodata' ] = int (quality_nodata )
300
301
activity ['quality_band' ] = quality_band
301
302
activity ['functions' ] = functions
302
303
activity ['force' ] = force
@@ -549,7 +550,7 @@ def merge_warped(self, activity):
549
550
ymax = float (activity ['ymax' ])
550
551
dist_x = float (activity ['dist_x' ])
551
552
dist_y = float (activity ['dist_y' ])
552
- nodata = int (activity ['nodata' ])
553
+ nodata = int (activity ['quality_nodata' ]) if is_quality_band else int ( activity [ ' nodata' ])
553
554
554
555
shape = activity .get ('shape' , None )
555
556
if shape :
@@ -570,14 +571,13 @@ def merge_warped(self, activity):
570
571
571
572
is_sentinel_landsat_quality_fmask = ('LANDSAT' in satellite or satellite == 'SENTINEL-2' ) and \
572
573
(is_quality_band and activity_mask ['nodata' ] != 0 )
573
- source_nodata = 0
574
+ source_nodata = activity . get ( 'source_nodata' , 0 )
574
575
575
576
# Quality band is resampled by nearest, other are bilinear
576
577
if is_quality_band :
577
578
resampling = Resampling .nearest
578
579
579
- nodata = activity_mask ['nodata' ]
580
- source_nodata = nodata
580
+ source_nodata = source_nodata if activity .get ('source_nodata' ) else activity_mask ['nodata' ]
581
581
582
582
raster = numpy .zeros ((numlin , numcol ,), dtype = numpy .uint16 )
583
583
raster_merge = numpy .full ((numlin , numcol ,), dtype = numpy .uint16 , fill_value = source_nodata )
@@ -616,96 +616,98 @@ def merge_warped(self, activity):
616
616
new_url = url
617
617
if landsat_harmonization :
618
618
if not is_quality_band :
619
- bucket_src = HARMONIZATION ['landsat' ]['bucket_src' ]
620
- new_url = new_url .replace (bucket_src , landsat_harmonization ['bucket_dst' ])
619
+ key_path = new_url .replace (HARMONIZATION ['landsat' ]['bucket_src' ], '' )
620
+ if services .s3_file_exists (bucket_name = landsat_harmonization ['bucket_dst' ], key = key_path , request_payer = True ):
621
+ bucket_src = HARMONIZATION ['landsat' ]['bucket_src' ].replace ('s3://' , '' )
622
+ new_url = new_url .replace (bucket_src , landsat_harmonization ['bucket_dst' ])
621
623
622
- from rasterio .session import AWSSession
624
+ from rasterio .session import AWSSession
623
625
624
- aws_session = AWSSession (services .session , requester_pays = True )
625
- with rasterio .Env (aws_session , AWS_SESSION_TOKEN = "" ):
626
+ aws_session = AWSSession (services .session , requester_pays = True )
627
+ with rasterio .Env (aws_session , AWS_SESSION_TOKEN = "" ):
626
628
627
- with rasterio .open (new_url ) as src :
629
+ with rasterio .open (new_url ) as src :
628
630
629
- kwargs = src .meta .copy ()
631
+ kwargs = src .meta .copy ()
632
+ kwargs .update ({
633
+ 'width' : numcol ,
634
+ 'height' : numlin
635
+ })
636
+ if not shape :
630
637
kwargs .update ({
631
- 'width ' : numcol ,
632
- 'height ' : numlin
638
+ 'crs ' : activity [ 'srs' ] ,
639
+ 'transform ' : transform
633
640
})
634
- if not shape :
635
- kwargs .update ({
636
- 'crs' : activity ['srs' ],
637
- 'transform' : transform
638
- })
639
-
640
- if src .profile ['nodata' ] is not None :
641
- source_nodata = src .profile ['nodata' ]
642
-
643
- elif 'source_nodata' in activity :
644
- source_nodata = activity ['source_nodata' ]
645
641
646
- elif 'LANDSAT' in satellite and not is_quality_band :
647
- source_nodata = nodata if src .profile ['dtype' ] == 'int16' else 0
642
+ if src .profile ['nodata' ] is not None :
643
+ source_nodata = src .profile ['nodata' ]
644
+
645
+ elif 'source_nodata' in activity :
646
+ source_nodata = activity ['source_nodata' ]
647
+
648
+ elif 'LANDSAT' in satellite and not is_quality_band :
649
+ source_nodata = nodata if src .profile ['dtype' ] == 'int16' else 0
650
+
651
+ elif 'CBERS' in satellite and not is_quality_band :
652
+ source_nodata = nodata
648
653
649
- elif 'CBERS' in satellite and not is_quality_band :
650
- source_nodata = nodata
654
+ kwargs .update ({
655
+ 'nodata' : source_nodata
656
+ })
651
657
658
+ if is_quality_band and activity_mask .get ('bits' ):
652
659
kwargs .update ({
653
- 'nodata' : source_nodata
660
+ 'blockxsize' : 2048 ,
661
+ 'blockysize' : 2048 ,
662
+ 'tiled' : True
654
663
})
655
664
656
- if is_quality_band and activity_mask .get ('bits' ):
657
- kwargs .update ({
658
- 'blockxsize' : 2048 ,
659
- 'blockysize' : 2048 ,
660
- 'tiled' : True
661
- })
662
-
663
- with MemoryFile () as memfile :
664
- with memfile .open (** kwargs ) as dst :
665
- if shape :
666
- raster = src .read (1 )
667
- else :
668
- reproject (
669
- source = rasterio .band (src , 1 ),
670
- destination = raster ,
671
- src_transform = src .transform ,
672
- src_crs = src .crs ,
673
- dst_transform = transform ,
674
- dst_crs = activity ['srs' ],
675
- src_nodata = source_nodata ,
676
- dst_nodata = nodata ,
677
- resampling = resampling )
678
-
679
- if not is_quality_band or is_sentinel_landsat_quality_fmask :
680
- valid_data_scene = raster [raster != nodata ]
681
- raster_merge [raster != nodata ] = valid_data_scene .reshape (numpy .size (valid_data_scene ))
682
-
683
- valid_data_scene = None
684
- else :
685
- factor = raster * raster_mask
686
- raster_merge = raster_merge + factor
665
+ with MemoryFile () as memfile :
666
+ with memfile .open (** kwargs ) as dst :
667
+ if shape :
668
+ raster = src .read (1 )
669
+ else :
670
+ reproject (
671
+ source = rasterio .band (src , 1 ),
672
+ destination = raster ,
673
+ src_transform = src .transform ,
674
+ src_crs = src .crs ,
675
+ dst_transform = transform ,
676
+ dst_crs = activity ['srs' ],
677
+ src_nodata = source_nodata ,
678
+ dst_nodata = nodata ,
679
+ resampling = resampling )
680
+
681
+ if not is_quality_band or is_sentinel_landsat_quality_fmask :
682
+ valid_data_scene = raster [raster != nodata ]
683
+ raster_merge [raster != nodata ] = valid_data_scene .reshape (numpy .size (valid_data_scene ))
684
+
685
+ valid_data_scene = None
686
+ else :
687
+ factor = raster * raster_mask
688
+ raster_merge = raster_merge + factor
687
689
688
- raster_mask [raster != nodata ] = 0
690
+ raster_mask [raster != nodata ] = 0
689
691
690
- if build_provenance :
691
- raster_masked = numpy .ma .masked_where (raster == nodata , raster )
692
+ if build_provenance :
693
+ raster_masked = numpy .ma .masked_where (raster == nodata , raster )
692
694
693
- where_valid = numpy .invert (raster_masked .mask )
694
- raster_provenance [where_valid ] = datasets .index (platforms [url ])
695
+ where_valid = numpy .invert (raster_masked .mask )
696
+ raster_provenance [where_valid ] = datasets .index (platforms [url ])
695
697
696
- where_valid = None
697
- raster_masked = None
698
+ where_valid = None
699
+ raster_masked = None
698
700
699
- if template is None :
700
- template = dst .profile
701
+ if template is None :
702
+ template = dst .profile
701
703
702
- template ['driver' ] = 'GTiff'
704
+ template ['driver' ] = 'GTiff'
703
705
704
- raster_blocks = list (dst .block_windows ())
706
+ raster_blocks = list (dst .block_windows ())
705
707
706
- if not is_quality_band :
707
- template .update ({'dtype' : 'int16' })
708
- template ['nodata' ] = nodata
708
+ if not is_quality_band :
709
+ template .update ({'dtype' : 'int16' })
710
+ template ['nodata' ] = nodata
709
711
710
712
711
713
raster = None
@@ -734,7 +736,7 @@ def merge_warped(self, activity):
734
736
else :
735
737
raster_merge = raster_merge .astype (numpy .uint8 )
736
738
737
- nodata = activity_mask [ 'nodata ' ]
739
+ nodata = activity [ 'quality_nodata ' ]
738
740
739
741
# Save merged image on S3
740
742
create_cog_in_s3 (services , template , key , raster_merge , bucket_name , nodata = nodata )
@@ -779,7 +781,7 @@ def next_blend(services, mergeactivity):
779
781
blendactivity = {}
780
782
blendactivity ['action' ] = 'blend'
781
783
for key in ['datasets' , 'satellite' , 'bands' , 'quicklook' , 'srs' , 'functions' , 'bands_ids' ,
782
- 'tileid' , 'start' , 'end' , 'dirname' , 'nodata' , 'bucket_name' , 'quality_band' ,
784
+ 'tileid' , 'start' , 'end' , 'dirname' , 'nodata' , 'bucket_name' , 'quality_band' , 'quality_nodata' ,
783
785
'internal_bands' , 'force' , 'version' , 'datacube' , 'irregular_datacube' , 'mask' ,
784
786
'bands_expressions' , 'indexes_only_regular_cube' , 'empty_file' , 'landsat_harmonization' ]:
785
787
blendactivity [key ] = mergeactivity .get (key , '' )
@@ -950,9 +952,7 @@ def blend(self, activity):
950
952
band = activity ['band' ]
951
953
numscenes = len (activity ['scenes' ])
952
954
953
- nodata = int (activity .get ('nodata' , - 9999 ))
954
- if band == activity ['quality_band' ]:
955
- nodata = activity_mask ['nodata' ]
955
+ nodata = int (activity .get ('nodata' , - 9999 )) if band != activity ['quality_band' ] else activity ['quality_nodata' ]
956
956
957
957
# Check if band ARDfiles are in activity
958
958
for date_ref in activity ['scenes' ]:
@@ -1010,6 +1010,8 @@ def blend(self, activity):
1010
1010
resolution = 10
1011
1011
mask_tuples .append ((100. * efficacy / resolution , key ))
1012
1012
1013
+ mask_tuples = sorted (mask_tuples , reverse = True )
1014
+
1013
1015
provenance_merge_map = dict ()
1014
1016
build_provenance = activity .get ('internal_band' ) == PROVENANCE_NAME
1015
1017
build_clear_observation = activity .get ('internal_band' ) == CLEAR_OBSERVATION_NAME
0 commit comments