예제 #1
0
    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
예제 #2
0
    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)
예제 #3
0
    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"""
예제 #4
0
    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