diff --git a/sen2chain/colormap.py b/sen2chain/colormap.py index 1e0688877c3e1cb1ad3b0895b973e0a93458b90b..7f0692b09809a64c295f4ddd85bb874636058028 100644 --- a/sen2chain/colormap.py +++ b/sen2chain/colormap.py @@ -373,7 +373,7 @@ def create_l1c_ql(tci: Union[str, pathlib.PosixPath], with rasterio.open(str(tci)) as src: profile = src.profile - + fact = int(1000 // out_resolution[0]) dst_transform, dst_width, dst_height = calculate_default_transform( @@ -417,3 +417,121 @@ def create_l1c_ql(tci: Union[str, pathlib.PosixPath], #~ raster_band = raster_band.astype(np.uint8) dst.write_band(band_id, raster_band) return str(Path(str(out_path)).absolute) + +def create_l1c_ql_v2(tci: Union[str, pathlib.PosixPath], + out_path: Union[str, pathlib.PosixPath] = "./L1C_QL.tif", + out_resolution: Tuple[int, int] = (100, 100), + jpg = False, + ) -> str: + """ + Creating a color RVB quicklook from tci 3 bands file passed as argument + :param tci: path to tci raster + :param out_path: path to the output. + :param out_resolution: output resolution, default 100mx100m . + """ + with rasterio.open(str(tci)) as src: + profile = src.profile + + fact = int(out_resolution[0] // 10) + + dst_transform, dst_width, dst_height = calculate_default_transform( + src.crs, + src.crs, + src.width, + src.height, + *src.bounds, + resolution = out_resolution) + + logger.info("creating L1C QL - {}m/px - {}px".format(out_resolution[0], dst_width)) + + if out_path.suffix == ".jpg" or jpg: + profile.update(nodata=0, + driver="JPEG", + dtype=np.uint8, + transform=dst_transform, + width=dst_width, + height=dst_height, + tiled=False, + count=3) + profile.pop('tiled', None) + profile.pop('blockxsize', None) + profile.pop('blockysize', None) + profile.pop('interleave', None) + else: + profile.update(nodata=0, + driver="Gtiff", + dtype=np.uint8, + transform=dst_transform, + width=dst_width, + height=dst_height, + tiled=False, + count=3) + with rasterio.open(str(out_path), 'w', **profile) as dst: + raster_band = src.read(out_shape=(src.count, + dst_width, + dst_height, + ), + resampling=Resampling.nearest + ).astype(np.uint8) + dst.write(raster_band) + return str(Path(str(out_path)).absolute) + +def create_l2a_ql_v2(tci: Union[str, pathlib.PosixPath], + out_path: Union[str, pathlib.PosixPath] = "./L2A_QL.tif", + out_resolution: Tuple[int, int] = (100, 100), + jpg = False, + ) -> str: + """ + Creating a color RVB quicklook from tci 3 bands file passed as argument + :param tci: path to tci raster + :param out_path: path to the output. + :param out_resolution: output resolution, default 100mx100m . + """ + with rasterio.open(str(tci)) as src: + profile = src.profile + + fact = int(out_resolution[0] // 10) + + dst_transform, dst_width, dst_height = calculate_default_transform( + src.crs, + src.crs, + src.width, + src.height, + *src.bounds, + resolution = out_resolution) + + logger.info("creating L2A QL - {}m/px - {}px".format(out_resolution[0], dst_width)) + + if out_path.suffix == ".jpg" or jpg: + profile.update(nodata=0, + driver="JPEG", + dtype=np.uint8, + transform=dst_transform, + width=dst_width, + height=dst_height, + tiled=False, + count=3) + profile.pop('tiled', None) + profile.pop('blockxsize', None) + profile.pop('blockysize', None) + profile.pop('interleave', None) + else: + profile.update(nodata=0, + driver="Gtiff", + dtype=np.uint8, + transform=dst_transform, + width=dst_width, + height=dst_height, + tiled=False, + count=3) + with rasterio.open(str(out_path), 'w', **profile) as dst: + raster_band = src.read(out_shape=(src.count, + dst_width, + dst_height, + ), + resampling=Resampling.nearest + ).astype(np.uint8) + dst.write(raster_band) + return str(Path(str(out_path)).absolute) + + diff --git a/sen2chain/library.py b/sen2chain/library.py index 50de4f869093e326ad058c5723d5c795f979bcfd..348985c6b8ee139f9e2f7daff980c123cce1a95b 100644 --- a/sen2chain/library.py +++ b/sen2chain/library.py @@ -115,15 +115,7 @@ class Library: pass logger.info("Total l1c size to move: {}".format(human_size_decimal(total_size))) - def update_latest_ql(self): - """ - Produce or update the latest quicklook for the L2A library tiles - """ - try: - for tile in self.l2a: - Tile(tile).update_latest_ql() - except: - pass + def archive_l2a(self, tile_list: list = [], @@ -170,20 +162,46 @@ class Library: pass logger.info("Total size to move: {}".format(human_size_decimal(total_size))) - def create_all_ql(self, - product_list: list = [], + def compute_all_ql(self, tile_list: list = [], + product_list: list = [], ): - toto = 52 - + """ + Produce or update quicklooks for all the library tiles + """ + if not product_list: + # l1c + if not tile_list: + for tile in self.l1c: + try: + toto = 52 + except: + pass + for tile in self.l2a: + try: + #Tile(tile).compute_ql(product = "l2a") + toto = 12 + except: + pass + + - def update_latest_ql(self): """ Produce or update the latest quicklook for the L2A library tiles """ - for tile in self.l2a: - Tile(tile).update_latest_ql() + try: + for tile in self.l2a: + Tile(tile).update_latest_ql() + except: + pass + + #~ def update_latest_ql(self): + #~ """ + #~ Produce or update the latest quicklook for the L2A library tiles + #~ """ + #~ for tile in self.l2a: + #~ Tile(tile).update_latest_ql() def update_old_cloudmasks(self): """ diff --git a/sen2chain/products.py b/sen2chain/products.py index 3c52fb015923e2a6d99f15b82951e7d9ebbc68e2..1ae304788868c4993e8e9908e1f3654bfac9b713 100755 --- a/sen2chain/products.py +++ b/sen2chain/products.py @@ -19,8 +19,7 @@ from .xmlparser import MetadataParser, Sen2ChainMetadataParser from .sen2cor import process_sen2cor from .cloud_mask import create_cloud_mask, create_cloud_mask_v2, create_cloud_mask_b11, create_cloud_mask_v003, create_cloud_mask_v004 from .indices import IndicesCollection -from .colormap import create_l2a_ql, create_l1c_ql - +from .colormap import create_l2a_ql, create_l1c_ql, create_l1c_ql_v2, create_l2a_ql_v2 s2_tiles_index = SHARED_DATA.get("tiles_index") @@ -226,9 +225,9 @@ class L1cProduct(Product): logger.info("{}: processing L1C Quicklook".format(self.identifier)) if jpg: - ql_filename = self.identifier + "_QL.jpg" + ql_filename = self.identifier + "_QL-"+ str(out_resolution[0]) + "m.jpg" else: - ql_filename = self.identifier + "_QL.tif" + ql_filename = self.identifier + "_QL-"+ str(out_resolution[0]) + "m.tif" if out_path is None: ql_folder = self.library_path.parent / "QL" @@ -240,7 +239,11 @@ class L1cProduct(Product): if ql_path.exists() and not reprocess: logger.info("{} Quicklook already exists".format(self.identifier)) else: - create_l1c_ql(tci = self.tci, + #~ create_l1c_ql(tci = self.tci, + #~ out_path = ql_path, + #~ out_resolution = out_resolution, + #~ jpg = jpg) + create_l1c_ql_v2(tci = self.tci, out_path = ql_path, out_resolution = out_resolution, jpg = jpg) @@ -411,9 +414,9 @@ class L2aProduct(Product): logger.info("{}: processing L2A Quicklook".format(self.identifier)) if jpg: - ql_filename = self.identifier + "_QL.jpg" + ql_filename = self.identifier + "_QL-"+ str(out_resolution[0]) + "m.jpg" else: - ql_filename = self.identifier + "_QL.tif" + ql_filename = self.identifier + "_QL-"+ str(out_resolution[0]) + "m.tif" if out_path is None: ql_folder = self.library_path.parent / "QL" @@ -425,12 +428,18 @@ class L2aProduct(Product): if ql_path.exists() and not reprocess: logger.info("{} Quicklook already exists".format(self.identifier)) else: - create_l2a_ql(b02 = self.b02_10m, - b03 = self.b03_10m, - b04 = self.b04_10m, + #~ create_l2a_ql(b02 = self.b02_10m, + #~ b03 = self.b03_10m, + #~ b04 = self.b04_10m, + #~ out_path = ql_path, + #~ out_resolution = out_resolution, + #~ jpg = jpg) + + create_l2a_ql_v2(tci = self.tci_10m, out_path = ql_path, out_resolution = out_resolution, jpg = jpg) + self.user_ql = ql_path return self diff --git a/sen2chain/tiles.py b/sen2chain/tiles.py index 2ac10a19241dc8fd89d0b061329ad51e1018d042..d12ff1dbe42f11a4d2f1577fef84fdee89548552 100644 --- a/sen2chain/tiles.py +++ b/sen2chain/tiles.py @@ -995,6 +995,30 @@ class Tile: l2a_size = self.archive_l2a(size_only = size_only) return l1c_size + l2a_size + def compute_ql(self, + product_list: list = [], + resolution: int = 750, + jpg: bool = True, + ): + """ + Produce or update the latest l2a quicklook for the tile + And remove previous ones """ + for product in product_list: + # l1c + if "l1c" in [item.lower() for item in product_list]: + for p in self.l1c: + l1c = L1cProduct(p.identifier) + l1c.process_ql(out_resolution = (resolution, resolution), jpg = jpg) + # l2a + if "l2a" in [item.lower() for item in product_list]: + for p in self.l2a: + l2a = L2aProduct(p.identifier) + l2a.process_ql(out_resolution = (resolution, resolution), jpg = True) + # indices + + + + def update_latest_ql(self): """ Produce or update the latest l2a quicklook for the tile