From 7dddbec513d5d8c167a8bf3a45f5ed1eef83d70c Mon Sep 17 00:00:00 2001 From: Impact <pascal.mouquet@ird.fr> Date: Fri, 13 Nov 2020 11:00:20 +0400 Subject: [PATCH] New test NDR Generic indice --- sen2chain/indices.py | 95 +++++++++++++++++++++++++++++++++- sen2chain/indices_functions.py | 21 ++++---- sen2chain/tiles.py | 2 +- 3 files changed, 106 insertions(+), 12 deletions(-) diff --git a/sen2chain/indices.py b/sen2chain/indices.py index 41cf778..28bfb3f 100644 --- a/sen2chain/indices.py +++ b/sen2chain/indices.py @@ -15,7 +15,7 @@ from typing import Union, List from .indices_functions import (create_raw_ndvi, create_raw_ndre, create_raw_ndwigao, create_raw_ndwimcf, create_raw_bigr, create_raw_birnir, create_raw_bibg, - create_raw_mndwi, + create_raw_mndwi, create_raw_ndr, create_masked_indice, index_tiff_2_jp2) from .colormap import matplotlib_colormap_to_rgb, create_colormap, create_rvb @@ -165,7 +165,6 @@ class Ndvi(Indice): #~ IndiceProduct(identifier = masked_indice_filename).init_md() #~ IndiceProduct(identifier = quicklook_filename).init_md() - class NdwiMcf(Indice): """ NDWI(McFeeters) = (GREEN-NIR) / (GREEN+NIR) @@ -255,6 +254,98 @@ class NdwiMcf(Indice): out_path=(self.out_path / quicklook_filename)) + +class GenericNDR(Indice): + """ + NDR = (B1-B2) / (B1+B2) + + B1: band + B2: band + """ + name = "GENERICNDR" + filename_template = "{product_identifier}_GENERICNDR{ext}" + ext = ".jp2" + ext_raw = ".tif" + #~ colormap = cm.RdYlBu + colormap = cm.colors.LinearSegmentedColormap.from_list("", ["red", "white", "blue"]) + + + def __init__(self, l2a_product_object, cm_product_object): + if (l2a_product_object or cm_product_object) is None: + raise ValueError("A L2aProduct and NewCloudMask objects must be provided") + else: + self.l2a_product = l2a_product_object + self.cm_product = cm_product_object + + # output path + self.out_path = None + + # filenames + self.indice_stem = self.filename_template.format(product_identifier=self.l2a_product.identifier, ext="") + self.indice_filename = self.indice_stem + self.ext + self.indice_raw = self.indice_stem + self.ext_raw + + def process_indice( + self, + out_path: pathlib.PosixPath, + reprocess: bool = False, + nodata_clouds: bool = False, + quicklook: bool = False + ) -> None: + """ process """ + self.out_path = out_path + if (out_path / self.indice_filename).exists() and not reprocess: + logger.info("{} already exists".format(self.indice_filename)) + else: + create_raw_ndr(b1_path=self.l2a_product.b08_10m, + b2_path=self.l2a_product.b11_20m, + out_path=(out_path / self.indice_raw)) + index_tiff_2_jp2(img_path=(out_path / self.indice_raw), + out_path=(out_path / self.indice_filename), + quality = 20 + ) + + if nodata_clouds: + if not self.cm_product.path.exists(): + raise ValueError("Cloud mask does not exist") + masked_indice_filename = self.indice_stem + "_" + self.cm_product.suffix + self.ext + masked_indice_raw = self.indice_stem + "_" + self.cm_product.suffix + self.ext_raw + + if (out_path / masked_indice_filename).exists() and not reprocess: + logger.info("{} already exists".format(masked_indice_filename)) + else: + if (out_path / self.indice_raw).exists(): + ndwimcf_path = (out_path / self.indice_raw) + else: + ndwimcf_path = (out_path / self.indice_filename) + create_masked_indice(indice_path=ndwimcf_path, + cloud_mask_path=self.cm_product.path, + out_path=(out_path / masked_indice_raw)) + index_tiff_2_jp2(img_path=(out_path / masked_indice_raw), + out_path=(out_path / masked_indice_filename)) + #~ os.remove(str(out_path / masked_indice_raw)) + + try: + #~ os.remove(str(out_path / self.indice_raw)) + logger.info("Removing {}".format(self.indice_raw)) + except: + pass + + if quicklook: + cmap = matplotlib_colormap_to_rgb(self.colormap, revers=False) + + quicklook_filename = self.indice_stem + "_" + self.cm_product.suffix + "_QL.tif" + + if (self.out_path / quicklook_filename).exists() and not reprocess: + logger.info("{} already exists".format(quicklook_filename)) + else: + logger.info("creating quicklook") + create_rvb(raster=(self.out_path / self.indice_filename), + cloud_mask=self.cm_product.path, + lut_dict=cmap, clouds_color="white", + out_path=(self.out_path / quicklook_filename)) + + class NdwiGao(Indice): """ NDWI(Gao) = (NIR-SWIR) / (NIR+SWIR) diff --git a/sen2chain/indices_functions.py b/sen2chain/indices_functions.py index 404f507..7f7c00f 100644 --- a/sen2chain/indices_functions.py +++ b/sen2chain/indices_functions.py @@ -103,11 +103,17 @@ def create_raw_ndr(b1_path: Union[str, pathlib.PosixPath], logger.info("creating raw generic NDR (tiff - int16)") with rasterio.open(str(b1_path)) as b1_src, \ - rasterio.open(str(B2_path)) as b2_src: + rasterio.open(str(b2_path)) as b2_src: b1_profile = b1_src.profile np.seterr(divide='ignore', invalid='ignore') # ignore warnings when dividing by zero - b1 = b1_src.read(1).astype(np.float32) - b2 = b2_src.read(1).astype(np.float32) + b1 = b1_src.read(1, + out_shape=(1, max(b1_src.height, b2_src.height), max(b1_src.width, b2_src.width)), + resampling=Resampling.bilinear)\ + .astype(np.float32) + b2 = b2_src.read(1, + out_shape=(1, max(b1_src.height, b2_src.height), max(b1_src.width, b2_src.width)), + resampling=Resampling.bilinear)\ + .astype(np.float32) ndr = ((b1 - b2) / (b1 + b2)*10000).astype(np.int16) ndr_masked = np.where(b1 != 0, ndr, 32767) @@ -500,10 +506,6 @@ def create_raw_bi(b1_path: Union[str, pathlib.PosixPath], dst.write(bigr_masked, 1) return Path(str(out_path)).absolute - - - - def create_masked_indice( indice_path: Union[str, pathlib.PosixPath], cloud_mask_path: Union[str, pathlib.PosixPath], @@ -554,7 +556,8 @@ def create_masked_indice( return str(Path(str(out_path)).absolute) def index_tiff_2_jp2(img_path: Union[str, pathlib.PosixPath], - out_path: Union[str, pathlib.PosixPath]="./indice_2_jp2.jp2") -> pathlib.PosixPath: + out_path: Union[str, pathlib.PosixPath]="./indice_2_jp2.jp2", + quality: int = 20) -> pathlib.PosixPath: """ Convert a indice file from TIF to JP2. :param out_path: path to the output raster. @@ -564,7 +567,7 @@ def index_tiff_2_jp2(img_path: Union[str, pathlib.PosixPath], driver = gdal.GetDriverByName("JP2OpenJPEG") for i in range(src_ds.RasterCount): src_ds.GetRasterBand(i+1).SetNoDataValue(float(16383)) - dst_ds = driver.CreateCopy(str(out_path), src_ds, options=['NBITS=15', 'CODEC=JP2', 'QUALITY=20']) + dst_ds = driver.CreateCopy(str(out_path), src_ds, options=['NBITS=15', 'CODEC=JP2', 'QUALITY=' + str(quality)]) dst_ds = None src_ds = None return str(Path(str(out_path)).absolute) diff --git a/sen2chain/tiles.py b/sen2chain/tiles.py index 157eb29..5a4a7f8 100644 --- a/sen2chain/tiles.py +++ b/sen2chain/tiles.py @@ -902,7 +902,7 @@ class Tile: else: l2a.process_ql(out_path = outfullpath, out_resolution=(750,750), jpg = True) else: - logger.info("No L2A product available") + logger.info("{} - No L2A product available".format(self.name)) def move_old_quicklooks(self): """ -- GitLab