From 69aa6e1a385a21e98bacfe16c04e24bd763bcef3 Mon Sep 17 00:00:00 2001
From: Impact <pascal.mouquet@ird.fr>
Date: Fri, 6 May 2022 16:53:03 +0400
Subject: [PATCH] add new ql functions

---
 sen2chain/colormap.py | 120 +++++++++++++++++++++++++++++++++++++++++-
 sen2chain/library.py  |  50 ++++++++++++------
 sen2chain/products.py |  29 ++++++----
 sen2chain/tiles.py    |  24 +++++++++
 4 files changed, 196 insertions(+), 27 deletions(-)

diff --git a/sen2chain/colormap.py b/sen2chain/colormap.py
index 1e06888..7f0692b 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 50de4f8..348985c 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 3c52fb0..1ae3047 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 2ac10a1..d12ff1d 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
-- 
GitLab