예제 #1
0
    def get_band_paths(self,
                       band_list: list,
                       resolution: float = None) -> dict:
        """
        Return the paths of required bands.

        .. WARNING:: This functions orthorectifies SAR bands if not existing !

        .. code-block:: python

            >>> from eoreader.reader import Reader
            >>> from eoreader.bands.alias import *
            >>> path = r"S1A_IW_GRDH_1SDV_20191215T060906_20191215T060931_030355_0378F7_3696.zip"
            >>> prod = Reader().open(path)
            >>> prod.get_band_paths([VV, HH])
            {
                <SarBandNames.VV: 'VV'>: '20191215T060906_S1_IW_GRD\\20191215T060906_S1_IW_GRD_VV.tif'  # HH doesn't exist
            }

        Args:
            band_list (list): List of the wanted bands
            resolution (float): Band resolution

        Returns:
            dict: Dictionary containing the path of each queried band
        """
        band_paths = {}
        for band in band_list:
            bname = self.band_names[band]
            if bname is None:
                raise InvalidProductError(
                    f"Non existing band ({band.name}) for {self.name}")
            try:
                # Try to load orthorectified bands
                band_paths[band] = files.get_file_in_dir(
                    self._get_band_folder(),
                    f"{self.condensed_name}_{bname}.tif",
                    exact_name=True,
                )
            except FileNotFoundError:
                speckle_band = sbn.corresponding_speckle(band)
                if speckle_band in self.pol_channels:
                    if sbn.is_despeckle(band):
                        # Despeckle the noisy band
                        band_paths[band] = self._despeckle_sar(speckle_band)
                    else:
                        all_band_paths = self._pre_process_sar(resolution)
                        band_paths = {
                            band: path
                            for band, path in all_band_paths.items()
                            if band in band_list
                        }

        return band_paths
예제 #2
0
    def _pre_process_sar(self, resolution: float = None) -> dict:
        """
        Pre-process SAR data (geocoding...)

        Args:
            resolution (float): Resolution

        Returns:
            dict: Dictionary containing {band: path}
        """
        out = {}

        # Create target dir (tmp dir)
        with tempfile.TemporaryDirectory() as tmp_dir:
            # Set command as a list
            target_file = os.path.join(tmp_dir, f"{self.condensed_name}")

            # Use dimap for speed and security (ie. GeoTiff's broken georef)
            pp_target = f"{target_file}"
            pp_dim = pp_target + ".dim"

            # Pre-process graph
            if PP_GRAPH not in os.environ:
                sat = "s1" if self.sat_id == Platform.S1.name else "sar"
                spt = "grd" if self.sar_prod_type == SarProductType.GDRG else "cplx"
                pp_graph = os.path.join(utils.get_data_dir(),
                                        f"{spt}_{sat}_preprocess_default.xml")
            else:
                pp_graph = os.environ[PP_GRAPH]
                if not os.path.isfile(pp_graph) or not pp_graph.endswith(
                        ".xml"):
                    FileNotFoundError(f"{pp_graph} cannot be found.")

            # Command line
            if not os.path.isfile(pp_dim):
                def_res = float(os.environ.get(SAR_DEF_RES, self.resolution))
                res_m = resolution if resolution else def_res
                res_deg = res_m / 10.0 * 8.983152841195215e-5  # Approx
                cmd_list = snap.get_gpt_cli(
                    pp_graph,
                    [
                        f"-Pfile={strings.to_cmd_string(self._snap_path)}",
                        f"-Pout={pp_dim}",
                        f"-Pcrs={self.crs()}",
                        f"-Pres_m={res_m}",
                        f"-Pres_deg={res_deg}",
                    ],
                    display_snap_opt=LOGGER.level == logging.DEBUG,
                )

                # Pre-process SAR images according to the given graph
                LOGGER.debug("Pre-process SAR image")
                misc.run_cli(cmd_list)

            # Convert DIMAP images to GeoTiff
            for pol in self.pol_channels:
                # Speckle image
                out[sbn.from_value(pol)] = self._write_sar(pp_dim, pol.value)

        return out
예제 #3
0
def test_bands():
    # SAR
    assert SarBandNames.from_list(["VV", "VH"]) == [VV, VH]
    assert SarBandNames.to_value_list([HV_DSPK, VV]) == ["HV_DSPK", "VV"]
    assert SarBandNames.to_value_list() == SarBandNames.list_values()
    assert SarBandNames.corresponding_speckle(SarBandNames.VV) == VV
    assert SarBandNames.corresponding_speckle(SarBandNames.VV_DSPK) == VV

    # OPTIC
    map_dic = {
        CA: "01",
        BLUE: "02",
        GREEN: "03",
        RED: "04",
        VRE_1: "05",
        VRE_2: "06",
        VRE_3: "07",
        NIR: "08",
        NARROW_NIR: "8A",
        WV: "09",
        SWIR_1: "11",
        SWIR_2: "12",
    }
    ob = OpticalBands()
    ob.map_bands(map_dic)

    for key, val in map_dic.items():
        assert key in ob._band_map
        assert ob._band_map[key] == map_dic[key]

    with pytest.raises(InvalidTypeError):
        ob.map_bands({VV: "wrong_val"})
예제 #4
0
    def get_existing_band_paths(self) -> dict:
        """
        Return the existing orthorectified band paths (including despeckle bands).

        .. WARNING:: This functions orthorectifies SAR bands if not existing !

        .. WARNING:: This functions despeckles SAR bands if not existing !

        .. code-block:: python

            >>> from eoreader.reader import Reader
            >>> from eoreader.bands.alias import *
            >>> path = r"S1A_IW_GRDH_1SDV_20191215T060906_20191215T060931_030355_0378F7_3696.zip"
            >>> prod = Reader().open(path)
            >>> prod.get_existing_band_paths()
            Executing processing graph
            ....10%....20%....30%....40%....50%....60%....70%....80%....90% done.
            Executing processing graph
            ....10%....20%....30%....40%....50%....60%....70%....80%....90% done.
            {
                <SarBandNames.VV: 'VV'>: '20191215T060906_S1_IW_GRD\\20191215T060906_S1_IW_GRD_VV.tif',
                <SarBandNames.VH: 'VH'>: '20191215T060906_S1_IW_GRD\\20191215T060906_S1_IW_GRD_VH.tif',
                <SarBandNames.VV_DSPK: 'VV_DSPK'>: '20191215T060906_S1_IW_GRD\\20191215T060906_S1_IW_GRD_VV_DSPK.tif',
                <SarBandNames.VH_DSPK: 'VH_DSPK'>: '20191215T060906_S1_IW_GRD\\20191215T060906_S1_IW_GRD_VH_DSPK.tif'
            }

        Returns:
            dict: Dictionary containing the path of every orthorectified bands
        """
        # Get raw bands (maximum number of bands)
        raw_bands = self._get_raw_bands()
        possible_bands = raw_bands + [
            sbn.corresponding_despeckle(band) for band in raw_bands
        ]

        return self.get_band_paths(possible_bands)
예제 #5
0
def to_band(to_convert: list) -> list:
    """
    Convert a string (or real value) to any alias, band or index.

    You can pass the name or the value of the bands.

    .. code-block:: python

        >>> to_band(["NDVI", "GREEN", RED, "VH_DSPK", "SLOPE", DEM, "CLOUDS", CLOUDS])
        [<function NDVI at 0x00000154DDB12488>,
        <OpticalBandNames.GREEN: 'GREEN'>,
        <OpticalBandNames.RED: 'RED'>,
        <SarBandNames.VH_DSPK: 'VH_DSPK'>,
        <DemBandNames.SLOPE: 'SLOPE'>,
        <DemBandNames.DEM: 'DEM'>,
        <ClassifBandNames.CLOUDS: 'CLOUDS'>,
        <ClassifBandNames.CLOUDS: 'CLOUDS'>]

    Args:
        to_convert (list): Values to convert into band objects

    Returns:
        list: converted values

    """
    if not isinstance(to_convert, list):
        to_convert = [to_convert]

    bands = []
    for tc in to_convert:
        band_or_idx = None
        # Try legit types
        if isinstance(tc, str):
            # Try index
            if hasattr(_idx, tc):
                band_or_idx = getattr(_idx, tc)
            else:
                try:
                    band_or_idx = _sbn.convert_from(tc)[0]
                except TypeError:
                    try:
                        band_or_idx = _obn.convert_from(tc)[0]
                    except TypeError:
                        try:
                            band_or_idx = _dem.convert_from(tc)[0]
                        except TypeError:
                            try:
                                band_or_idx = _clouds.convert_from(tc)[0]
                            except TypeError:
                                pass

        elif is_index(tc) or is_band(tc) or is_dem(tc) or is_clouds(tc):
            band_or_idx = tc

        # Store it
        if band_or_idx:
            bands.append(band_or_idx)
        else:
            raise InvalidTypeError(f"Unknown band or index: {tc}")

    return bands