def _is_filename_valid(product_path: str, regex: Union[list, re.Pattern]) -> bool: """ Check if the filename corresponds to the given satellite regex. Checks also if a file inside the directory is correct. .. WARNING:: Two level max for the moment Args: product_path (str): Product path regex (Union[list, re.Pattern]): Regex or list of regex Returns: bool: True if the filename corresponds to the given satellite regex """ product_file_name = files.get_filename(product_path) # Case folder is not enough to identify the products (ie. COSMO Skymed) # WARNING: Two level max for the moment is_valid = bool(regex[0].match(product_file_name)) if is_valid and len(regex) > 1: is_valid = False # Reset if os.path.isdir(product_path): file_list = os.listdir(product_path) for file in file_list: if regex[1].match(file): is_valid = True break else: LOGGER.debug("The product should be a folder.") return is_valid
def __init__(self, product_path: str, archive_path: str = None, output_path=None) -> None: try: self._img_path = glob.glob(os.path.join(product_path, "*.h5"))[0] except IndexError as ex: raise InvalidProductError( f"Image file (*.h5) not found in {product_path}") from ex self._real_name = files.get_filename(self._img_path) # Initialization from the super class super().__init__(product_path, archive_path, output_path)
def __init__(self, product_path: str, archive_path: str = None, output_path: str = None) -> None: self.name = files.get_filename(product_path) """Product name (its filename without any extension).""" self.split_name = self._get_split_name() """Split name, to retrieve every information from its filename (dates, tile, product type...).""" self.archive_path = archive_path if archive_path else product_path """Archive path, same as the product path if not specified. Useful when you want to know where both the extracted and archived version of your product are stored.""" self.path = product_path """Usable path to the product, either extracted or archived path, according to the satellite.""" self.is_archived = os.path.isfile(self.path) """ Is the archived product is processed (a products is considered as archived if its products path is a directory).""" self.needs_extraction = True """Does this products needs to be extracted to be processed ? (`True` by default).""" # The output will be given later if output_path: self._tmp = None self._output = output_path os.makedirs(output_path, exist_ok=True) else: self._tmp = tempfile.TemporaryDirectory() self._output = self._tmp.name """Output directory of the product, to write orthorectified data for example.""" # Get the products date and datetime self.date = self.get_date(as_date=True) """Acquisition date.""" self.datetime = self.get_datetime(as_datetime=True) """Acquisition datetime.""" self.tile_name = None """Tile if possible (for data that can be piled, for example S2 and Landsats).""" self.sensor_type = None """Sensor type, SAR or optical.""" self.product_type = None """Product type, satellite-related field, such as L1C or L2A for Sentinel-2 data.""" self.band_names = None """Band mapping between band wrapping names such as `GREEN` and band real number such as `03` for Sentinel-2.""" self.is_reference = False """If the product is a reference, used for algorithms that need pre and post data, such as fire detection.""" self.corresponding_ref = [] """The corresponding reference products to the current one (if the product is not a reference but has a reference data corresponding to it). A list because of multiple ref in case of non-stackable products (S3, S1...)""" self.nodata = -9999 """ Product nodata, set to 0 by default. Please do not touch this or all index will fail. """ # Mask values self._mask_true = 1 self._mask_false = 0 self.platform = self._get_platform() """Product platform, such as Sentinel-2""" # Post initialization self._post_init() # Set product type, needs to be done after the post-initialization self._set_product_type() # Set the resolution, needs to be done when knowing the product type self.resolution = self._set_resolution() """ Default resolution in meters of the current product. For SAR product, we use Ground Range resolution as we will automatically orthorectify the tiles. """ self.condensed_name = self._get_condensed_name() """ Condensed name, the filename with only useful data to keep the name unique (ie. `20191215T110441_S2_30TXP_L2A_122756`). Used to shorten names and paths. """ self.sat_id = self.platform.name """Satellite ID, i.e. `S2` for Sentinel-2"""
def _read_band( self, path: str, resolution: Union[tuple, list, float] = None, size: Union[list, tuple] = None, ) -> XDS_TYPE: """ Read band from a dataset. .. WARNING:: Invalid pixels are not managed here ! Args: path (str): Band path resolution (Union[tuple, list, float]): Resolution of the wanted band, in dataset resolution unit (X, Y) size (Union[tuple, list]): Size of the array (width, height). Not used if resolution is provided. Returns: XDS_TYPE: Radiometrically coherent band, saved as float 32 and its metadata """ # Get band name: the last number of the filename: # ie: 'LC08_L1TP_200030_20191218_20191226_01_T1_B1' if self.is_archived: filename = files.get_filename(path.split("!")[-1]) else: filename = files.get_filename(path) band_name = filename[-1] if self._quality_id in filename or self._nodata_band_id in filename: band = rasters.read( path, resolution=resolution, size=size, resampling=Resampling.nearest, # NEAREST TO KEEP THE FLAGS masked=False, ).astype(np.uint16) else: # Read band (call superclass generic method) band = rasters.read(path, resolution=resolution, size=size, resampling=Resampling.bilinear).astype( np.float32) # Open mtd mtd_data = self.read_mtd(force_pd=True) # Get band nb and corresponding coeff c_mul_str = "REFLECTANCE_MULT_BAND_" + band_name c_add_str = "REFLECTANCE_ADD_BAND_" + band_name # Get coeffs to convert DN to reflectance c_mul = mtd_data[c_mul_str].value c_add = mtd_data[c_add_str].value # Manage NULL values try: c_mul = float(c_mul) except ValueError: c_mul = 1 try: c_add = float(c_add) except ValueError: c_add = 0 # Compute the correct radiometry of the band and set no data to 0 band = c_mul * band + c_add # Already in float return band