def get_detfoo_index_detector_list(maskFilename, shift):

        l_result = {}

        # Load the MSK_DETFOO gml file
        maskHandler = get_root_xml(maskFilename, deannotate=True)

        # Get the mask feature nodes
        # as : <eop:MaskFeature gml:id="detector_footprint-B02-10-2">
        xnodes = get_all_values(maskHandler,
                                "//*[local-name(.) = 'MaskFeature']")

        # Two indices : the detector index and the feature index
        detId = 0

        # For each feature
        for i in range(len(xnodes)):
            feat = xnodes[i]
            # Get the attribute of the feature node
            # "detector_footprint-B02-10-2"
            attribute = list(feat.items())[0][1]
            element = attribute.split('-')

            # Get the detector index and the feature index
            detId = int(element[-2])
            featId = int(element[-1])

            l_result[featId + shift] = detId
        return l_result
Example #2
0
 def get_no_data(self):
     nodata = 0
     special_values = xml_tools.get_all_values(self.root, XPATH_MAIN_S2.get("special_values"))
     for values in special_values:
         if values.findtext("SPECIAL_VALUE_TEXT") == "NODATA":
             nodata = int(values.findtext("SPECIAL_VALUE_INDEX"))
             return nodata
     raise MajaDriverException("NODATA not found in the L1 Header file")
Example #3
0
 def get_list_of_packaged_dbl_files(self, absolute, check):
     nodes = xml_tools.get_all_values(
         self.root, EARTH_EXPLORER_HANDLER_XPATH["DBLFilenames"])
     list_of_files = [nd.text for nd in nodes]
     if absolute:
         l_rootbasepath = os.path.dirname(self.main_xml_file)
         list_of_files = [
             os.path.join(l_rootbasepath, nd.text) for nd in nodes
         ]
     if check:
         for fi in list_of_files:
             if not os.path.exists(fi):
                 raise MajaDataException("File " + fi + " does not exists")
     return list_of_files
 def get_list_of_gipp_files(self):
     """
     GetList_of_GIPP_Files
     :return:
     """
     l_listofgipps = []
     for gipp_node in xml_tools.get_all_values(self.root, GIPP_FILE):
         one_gipp = dict()
         one_gipp["index"] = xml_tools.get_only_value(gipp_node, GIPP_FILE_INDEX)
         one_gipp["file_location"] = xml_tools.get_xml_string_value(gipp_node, GIPP_FILE_LOCATION)
         one_gipp["nature"] = xml_tools.get_xml_string_value(gipp_node, GIPP_FILE_NATURE)
         one_gipp["logical_name"] = xml_tools.get_xml_string_value(gipp_node, GIPP_FILE_LOGICAL_NAME)
         l_listofgipps.append(one_gipp)
     return l_listofgipps
    def get_list_of_zones(self, bandIdx):
        list_of_zone = []
        # Convert the band index integer value in string
        path = "//Viewing_Incidence_Angles_Grids[@bandId='" + str(
            bandIdx) + "']"
        xnodes = xml_tools.get_all_values(self.root, path)
        # Two indices : the detector index and the feature index
        detId = 0

        # For each feature
        for i in range(len(xnodes)):
            LOGGER.debug((list(xnodes[i].items())))
            list_of_zone.append(xnodes[i].get("detectorId"))

        return list_of_zone
    def get_detfoo_index_shift(maskFilename):
        """
        Get the shift between the detector index and the feature index in the MSK_DETFOO mask

        :param maskFilename: string
        :return:
        """
        shift = 0

        # Load the MSK_DETFOO gml file
        maskHandler = get_root_xml(maskFilename, deannotate=True)

        # Get the mask feature nodes
        # as : <eop:MaskFeature gml:id="detector_footprint-B02-10-2">
        xnodes = get_all_values(maskHandler,
                                "//*[local-name(.) = 'MaskFeature']")
        # Two indices : the detector index and the feature index
        detId = 0

        # For each feature
        for i in range(len(xnodes)):
            feat = xnodes[i]
            prevShift = shift
            prevDetId = detId
            # "detector_footprint-B02-10-2"
            attribute = list(feat.items())[0][1]
            element = attribute.split('-')

            # Get the detector index and the feature index
            detId = int(element[-2])
            featId = int(element[-1])

            # The shift between those two indices must be constant
            # because it should not have a gap of detector between to consecutive features
            shift = detId - featId
            # Check the index values of the next features
            if (i > 0) and ((shift != prevShift) or (detId != prevDetId + 1)):
                LOGGER.warn(
                    "Sentinel2L1ImageFileReaderBase::get_detfoo_index_shift: The detector indices are not in ascending order "
                    "or do not have a constant shift with the feature indices in the MSK_DETFOO "
                    + maskFilename + " !")
                return False, shift

        return True, shift
 def get_mask_feature_count(maskFilename, regex=None):
     """
     Get the number of layers in a gml file
     :param maskFilename:
     :return:
     """
     maskHandler = get_root_xml(maskFilename, deannotate=True)
     xnodes = get_all_values(maskHandler, "//*[local-name(.) = 'MaskFeature']")
     if xnodes is not None:
         if regex is None:
             return len(xnodes)
         else:
             nb = 0
             for x in xnodes:
                 for a in list(x.items()):
                     if regex in a[1]:
                         nb = nb + 1
             return nb
     else:
         return 0
    def get_list_of_quality_index(self):
        """
        GetListOfQualityIndexes
        :return:
        """
        l_listofqualityindexes = []

        for quality_index_node in xml_tools.get_all_values(self.root, ONE_QUALITY_INDEX):
            one_quality_index = dict()
            one_quality_index["index"] = xml_tools.get_xml_int_value(quality_index_node, GIPP_FILE_INDEX)
            one_quality_index["code"] = xml_tools.get_xml_int_value(quality_index_node, QUALITY_INDEX_CODE)
            one_quality_index["value"] = xml_tools.get_xml_int_value(quality_index_node, QUALITY_INDEX_VALUE)
            one_quality_index["band_code"] = QUALITY_INDEX_BAND_CODE

            l_listofqualityindexes.append(one_quality_index)

            LOGGER.debug("Add the quality index [%s] Code=<%s> Value=<%s>  Band_Code=<%s> ",
                         one_quality_index["index"],
                         one_quality_index["code"],
                         one_quality_index["value"],
                         one_quality_index["band_code"])
    def muscate_initialize(self,
                           product_filename,
                           plugin_base,
                           validate=False,
                           schema_path=None):
        # Initialize the Image filename provider
        if not MajaMuscateL1ImageInformations.is_a_muscate_by_checking_the_filename(
                product_filename):
            LOGGER.debug("The filename <" + product_filename +
                         "> is not an 'muscate' L1 header file.")
            return False
        if not MajaMuscateL1ImageInformations.is_a_muscate_by_checking_the_satellite(
                product_filename, plugin_base):
            LOGGER.debug(
                "The filename <" + product_filename +
                "> is not an 'muscate' L1 header file (by reading platform in the xml file)."
            )
            return False
        # Init XML handler
        lHandler = MuscateXMLFileHandler(product_filename,
                                         validate=validate,
                                         schema_path=schema_path)
        # Store the satellite
        self.Satellite = lHandler.get_string_value_of("Platform")
        self.SatelliteID = self.Satellite.upper().replace("-", "")
        # Store the plugin name
        self.PluginName = plugin_base.PluginName
        self.ProductFileName = product_filename

        self.FileCategory = plugin_base.ShortFileType  # LSC
        self.LevelType = "L1VALD"
        self.Prefix = self.Satellite
        self.FileClass = "TEST"  # LANDSAT5-TM-XSTH...
        self.Site = lHandler.get_string_value_of("ZoneGeo")
        self.ProductDateStr = lHandler.get_acquisition_date_formated_yyyymmdd(
        )  # YYYYMMDD
        # LANDSAT5-TM-XSTH_20100118-103000-000_L1C_EU93066200A00B_C_V1-0
        self.ProductId = lHandler.get_string_value_of("ProductId")
        self.ProductVersion = lHandler.get_string_value_of("ProductVersion")
        l_DatePDV = lHandler.get_date_pdv_formated_utc(
        )  # UTC=2010-01-18T12:00:00

        self.ProductDate = date_utils.get_datetime_from_utc(l_DatePDV)

        self.GenerationDateStr = lHandler.get_string_value_of("ProductionDate")

        self.AcquisitionStart = lHandler.get_string_value_of("AcquisitionDate")

        self.OrbitNumber = lHandler.get_string_value_of("OrbitNumber")

        self.ReferenceSiteDefinitionId = "UNKNOWN"

        self.HeaderFilename = product_filename
        self.HeaderHandler = lHandler

        if xml_tools.get_only_value(lHandler.root,
                                    "//Product_Characteristics/INSTRUMENT",
                                    check=True) is not None:
            self.Instrument = lHandler.get_string_value_of("Instrument")

        if xml_tools.get_only_value(
                lHandler.root,
                "//Product_Characteristics/SPECTRAL_CONTENT",
                check=True) is not None:
            self.SpectralContent = lHandler.get_string_value_of(
                "SpectralContent").replace("+", "")

        # VENUS specification
        # Store the VIE and SOL filenames (DATA and Headers) to copy in the L2 product
        self.SOLHeaderFileName = ""
        self.SOLImageFileName = ""
        self.VIEHeaderFileName = ""
        self.VIEImageFileName = ""
        #         Initialize the parameters necessary for the core of the algorithms of MACCS
        # Get longitude and latitude coordinates of the product
        ulc = lHandler.get_upper_left_corner()
        lrc = lHandler.get_lower_right_corner()
        # Estimation of the coordinate of the central point
        center = lHandler.get_center()

        #l_Corner.Longitude = ulc[0] + (lrc[0] - ulc[0]) / 2.
        #l_Corner.Latitude = ulc[1] + (lrc[1] - ulc[1]) / 2.
        self.CenterCorner.longitude = center[0]
        self.CenterCorner.latitude = center[1]
        self.CenterCorner.column = 0
        self.CenterCorner.line = 0
        # Initialize the Validity Start/Stop
        l_UTCValidity = date_utils.get_utc_from_datetime(self.ProductDate)
        if l_UTCValidity.endswith('.000Z'):
            l_UTCValidity = l_UTCValidity[:-5]
        self.UTCValidityStart = l_UTCValidity
        self.UTCValidityStop = l_UTCValidity

        # Get the list of bands in a L2 product
        l_BandsDefinitions = plugin_base.BandsDefinitions

        l_ListOfBandsL2Coarse = l_BandsDefinitions.get_list_of_band_id_in_l2_coarse(
        )
        l_NbBandsL2Coarse = len(l_ListOfBandsL2Coarse)

        LOGGER.debug(
            "l_BandsDefinitions->GetListOfBandCodeInL2Coarse -> l_NbBandsL2Coarse: "
            + str(l_NbBandsL2Coarse))
        LOGGER.debug(
            "MuscateXmllHandler->GetListOfBands      -> l_NbBands                : "
            + str(len(lHandler.get_list_of_bands())))

        self.ListOfViewingAnglesPerBandAtL2Resolution = []
        self.ListOfViewingAnglesPerBandAtL2CoarseResolution = []
        self.ListOfViewingZenithAnglesPerBandAtL2CoarseResolution = []
        self.ListOfViewingAzimuthAnglesPerBandAtL2CoarseResolution = []

        # Initialize the Viewing angles for each detectors (Zenith and Azimuth)
        # Read the constants values from the Header Envi file name
        # The angles must be in degree
        if plugin_base.WideFieldSensor:
            # Initialize the Viewing angles for each detectors (Zenith and Azimuth)
            l_MeanViewingZenithalAngles = lHandler.get_mean_viewing_zenithal_angles(
            )
            l_MeanViewingAzimuthalAngles = lHandler.get_mean_viewing_azimuthal_angles(
            )
            self.ViewingAngle = {
                "incidence_zenith_angle":
                str(statistics.mean(l_MeanViewingZenithalAngles)),
                "incidence_azimuth_angle":
                str(statistics.mean(l_MeanViewingAzimuthalAngles))
            }

            # For each bands for EnviProduct
            for bd in range(0, len(l_ListOfBandsL2Coarse)):
                angles = {
                    "incidence_zenith_angle":
                    str(l_MeanViewingZenithalAngles[bd]),
                    "incidence_azimuth_angle":
                    str(l_MeanViewingAzimuthalAngles[bd])
                }
                self.ListOfViewingAnglesPerBandAtL2CoarseResolution.append(
                    angles)
                self.ListOfViewingZenithAnglesPerBandAtL2CoarseResolution.append(
                    str(angles["incidence_zenith_angle"]))
                self.ListOfViewingAzimuthAnglesPerBandAtL2CoarseResolution.append(
                    str(angles["incidence_azimuth_angle"]))
        else:
            lViewingAngles = lHandler.get_mean_viewing_angles()
            l_ViewAngleZenith = lViewingAngles[0]
            l_ViewAngleAzimuth = lViewingAngles[1]
            self.ViewingAngle = {
                "incidence_zenith_angle": str(l_ViewAngleZenith),
                "incidence_azimuth_angle": str(l_ViewAngleAzimuth)
            }

            # For each bands for EnviProduct
            for bd in l_ListOfBandsL2Coarse:
                angles = {
                    "incidence_zenith_angle": str(l_ViewAngleZenith),
                    "incidence_azimuth_angle": str(l_ViewAngleAzimuth)
                }
                self.ListOfViewingAnglesPerBandAtL2CoarseResolution.append(
                    angles)
                self.ListOfViewingZenithAnglesPerBandAtL2CoarseResolution.append(
                    str(angles["incidence_zenith_angle"]))
                self.ListOfViewingAzimuthAnglesPerBandAtL2CoarseResolution.append(
                    str(angles["incidence_azimuth_angle"]))

        # Fill the L2 resolution angles
        l_nbRes = len(l_BandsDefinitions.ListOfL2Resolution)
        for r in range(0, l_nbRes):
            l_res = l_BandsDefinitions.ListOfL2Resolution[r]
            l_l2bandcodes = l_BandsDefinitions.get_list_of_l2_band_code(l_res)
            l_l2bandidx = [
                l_BandsDefinitions.get_band_id_in_l2_coarse(b)
                for b in l_l2bandcodes
            ]
            for b in l_l2bandidx:
                self.ListOfViewingAnglesPerBandAtL2Resolution.append(
                    self.ListOfViewingAnglesPerBandAtL2CoarseResolution[b])

        # Solar Angles
        lSolarAngles = lHandler.get_mean_solar_angles()
        self.SolarAngle = {
            "sun_zenith_angle": lSolarAngles[0],
            "sun_azimuth_angle": lSolarAngles[1]
        }

        if xml_tools.get_only_value(lHandler.root,
                                    "//Angles_Grids_List/Sun_Angles_Grids",
                                    check=True) is not None:
            self.SolarAngleGrid["StepUnit"] = xml_tools.get_attribute(
                lHandler.root, "//Angles_Grids_List/Sun_Angles_Grids/Zenith",
                "step_unit")
            self.SolarAngleGrid["ColStep"] = lHandler.get_string_value_of(
                "SunAngleColStep")
            self.SolarAngleGrid["RowStep"] = lHandler.get_string_value_of(
                "SunAngleRowStep")
            self.SolarAngleGrid["Azimuth"] = lHandler.get_sun_azimuthal_angles(
            )
            self.SolarAngleGrid["Zenith"] = lHandler.get_sun_zenithal_angles()

        # Viewing angle grids
        self.ViewingAngleGrids = []
        if len(
                xml_tools.get_all_values(
                    lHandler.root,
                    "//Angles_Grids_List/Viewing_Incidence_Angles_Grids_List/Band_Viewing_Incidence_Angles_Grids_List"
                )):
            if lHandler.has_per_band_angles():
                for bn, bandid in l_BandsDefinitions.L2CoarseBandMap.items():
                    zonelist = lHandler.get_list_of_zones(bn)
                    zenith_values = lHandler.get_viewing_zenithal_angles(bn)
                    azimuth_values = lHandler.get_viewing_azimuthal_angles(bn)
                    LOGGER.debug("Viewing Angle grid for band " + str(bn))
                    for d, det in enumerate(zonelist):
                        self.ViewingAngleGrids.append({
                            "StepUnit":
                            lHandler.get_viewing_grid_step_unit(bn, det),
                            "ColStep":
                            lHandler.get_viewing_grid_col_step(bn, det),
                            "RowStep":
                            lHandler.get_viewing_grid_row_step(bn, det),
                            "Band":
                            str(bandid),
                            "Detector":
                            det.lstrip('0'),
                            "Azimuth":
                            azimuth_values[d],
                            "Zenith":
                            zenith_values[d]
                        })
            else:
                zonelist = lHandler.get_list_of_zones("dummy")
                for det in zonelist:
                    LOGGER.debug("Viewing Angle grid for det " + det)
                    self.ViewingAngleGrids.append({
                        "StepUnit":
                        lHandler.get_viewing_grid_step_unit(bandid=None,
                                                            det=det),
                        "ColStep":
                        lHandler.get_viewing_grid_col_step(bandid=None,
                                                           det=det),
                        "RowStep":
                        lHandler.get_viewing_grid_row_step(bandid=None,
                                                           det=det),
                        "Detector":
                        det.lstrip('0'),
                        "Azimuth":
                        lHandler.get_viewing_azimuthal_angles(det)[0],
                        "Zenith":
                        lHandler.get_viewing_zenithal_angles(det)[0]
                    })

        # Area by resolution
        self.AreaByResolution = []
        l_grpSuffixes = l_BandsDefinitions.ListOfL2Resolution
        if len(l_grpSuffixes) == 1:
            l_grpSuffixes = ["XS"]
        for res in l_grpSuffixes:
            l_path_group_geo = "//Group_Geopositioning_List/Group_Geopositioning[@group_id='{}']/{}"
            curArea = Area()
            curArea.origin = (xml_tools.get_xml_string_value(
                lHandler.root, l_path_group_geo.format(res, "ULX")),
                              xml_tools.get_xml_string_value(
                                  lHandler.root,
                                  l_path_group_geo.format(res, "ULY")))
            curArea.spacing = (xml_tools.get_xml_string_value(
                lHandler.root, l_path_group_geo.format(res, "XDIM")),
                               xml_tools.get_xml_string_value(
                                   lHandler.root,
                                   l_path_group_geo.format(res, "YDIM")))
            curArea.size = (xml_tools.get_xml_string_value(
                lHandler.root, l_path_group_geo.format(res, "NCOLS")),
                            xml_tools.get_xml_string_value(
                                lHandler.root,
                                l_path_group_geo.format(res, "NROWS")))
            self.AreaByResolution.append(curArea)
        # Spectral information
        self.SpectralInfo = []
        l_pathBase = "//Spectral_Band_Informations_List/Spectral_Band_Informations[@band_id='{}']"
        l_pathNativeCoeff = "/Calibration_Coefficients_Lists/Native_Coefficients_List/COEFFICIENT[@name='{}']"
        l_pathRadiance = "/SOLAR_IRRADIANCE"
        l_pathWavelength = "/Wavelength/{}"
        l_pathResponse = "/Spectral_Response/{}"
        l_pathsSpecInfo = {
            'PhysicalGain': l_pathNativeCoeff.format("PhysicalGain"),
            'LuminanceMax': l_pathNativeCoeff.format("LuminanceMax"),
            'LuminanceMin': l_pathNativeCoeff.format("LuminanceMin"),
            'QuantizeCalMax': l_pathNativeCoeff.format("QuantizeCalMax"),
            'QuantizeCalMin': l_pathNativeCoeff.format("QuantizeCalMin"),
            'RadianceAdd': l_pathNativeCoeff.format("RadianceAdd"),
            'RadianceMult': l_pathNativeCoeff.format("RadianceMult"),
            'ReflectanceAdd': l_pathNativeCoeff.format("ReflectanceAdd"),
            'ReflectanceMult': l_pathNativeCoeff.format("ReflectanceMult"),
            'SolarIrradiance': l_pathRadiance,
            'WavelengthMin': l_pathWavelength.format("MIN"),
            'WavelengthMax': l_pathWavelength.format("MAX"),
            'WavelengthCentral': l_pathWavelength.format("CENTRAL"),
            'ResponseStep': l_pathResponse.format("STEP"),
            'ResponseValues': l_pathResponse.format("VALUES")
        }
        for b, bidx in l_BandsDefinitions.L1BandMap.items():
            specInfo = {"Band": b}
            realBase = l_pathBase.format(b)
            for measure, pathMeasure in l_pathsSpecInfo.items():
                res = xml_tools.get_xml_string_value(lHandler.root,
                                                     realBase + pathMeasure,
                                                     check=True)
                if len(res):
                    specInfo[measure] = res
                    if measure == 'PhysicalGain':
                        specInfo[measure] = float(res)
            self.SpectralInfo.append(specInfo)

        # -------------------------------------------------------------------------
        # 4.2: New
        # Set the L1 no data value
        self.L1NoData = int(lHandler.get_string_value_of("L1NoData"))
        # Set the reflectance quantification value
        self.ReflectanceQuantification = 1. / float(
            lHandler.get_string_value_of("QuantificationValue"))
        # Computes the real value of the L1 NoData
        self.RealL1NoData = float(
            self.L1NoData) * self.ReflectanceQuantification

        # Save metadata related to Muscate format
        self.MuscateData["Node_MetadataFormat"] = xml_tools.extract_nodes(
            lHandler.root, "//Metadata_Identification/METADATA_FORMAT")
        l_NodeOriginalDataDiffuser = xml_tools.extract_nodes(
            lHandler.root, "//ORIGINAL_DATA_DIFFUSER")
        if l_NodeOriginalDataDiffuser is not None:
            self.MuscateData[
                "Node_OriginalDataDiffuser"] = l_NodeOriginalDataDiffuser
        self.MuscateData[
            "Node_Geoposition_Informations"] = xml_tools.extract_nodes(
                lHandler.root, "//Geoposition_Informations")
        self.MuscateData[
            "Node_Geometric_Informations"] = xml_tools.extract_nodes(
                lHandler.root, "//Geometric_Informations")
        #~ self.MuscateData["Identifier"] = lIdent
        self.MuscateData["Authority"] = lHandler.get_string_value_of(
            "Authority")
        self.MuscateData["Producer"] = lHandler.get_string_value_of("Producer")
        self.MuscateData["Project"] = lHandler.get_string_value_of("Project")
        self.MuscateData["ZoneGeo"] = lHandler.get_string_value_of("ZoneGeo")
        #~ self.MuscateData["Platform"] = self.Satellite

        self.MuscateData["AcquisitionDate"] = lHandler.get_string_value_of(
            "AcquisitionDate")
        self.MuscateData[
            "UTCAcquisitionRangeMean"] = lHandler.get_string_value_of(
                "UTCAcquisitionRangeMean")
        self.MuscateData[
            "UTCAcquisitionRangeDatePrecision"] = lHandler.get_string_value_of(
                "UTCAcquisitionRangeDatePrecision")

        l_NodeSolarAnglesGrid = xml_tools.extract_nodes(
            lHandler.root,
            "//Data_List/Data[Data_Properties/NATURE='Solar_Angles_Grid']")
        if l_NodeSolarAnglesGrid is not None:
            self.MuscateData["Node_Solar_Angles_Grid"] = l_NodeSolarAnglesGrid

        l_NodeViewingAnglesGrid = xml_tools.extract_nodes(
            lHandler.root,
            "//Data_List/Data[Data_Properties/NATURE='Viewing_Angles_Grid']")
        if l_NodeViewingAnglesGrid is not None:
            self.MuscateData[
                "Node_Viewing_Angles_Grid"] = l_NodeViewingAnglesGrid

        l_NodeUsefulImageInfoFile = xml_tools.extract_nodes(
            lHandler.root,
            "//Data_List/Data[Data_Properties/NATURE='Useful_Image_Informations_File']"
        )
        if l_NodeUsefulImageInfoFile is not None:
            self.MuscateData[
                "Node_Useful_Image_Informations_File"] = l_NodeUsefulImageInfoFile

        l_NodeUsefulImage = xml_tools.extract_nodes(
            lHandler.root,
            "//Mask_List/Mask[Mask_Properties/NATURE='Useful_Image']")
        if l_NodeUsefulImage is not None:
            self.MuscateData["Node_Useful_Image"] = l_NodeUsefulImage

        l_NodeDetFoo = xml_tools.get_only_value(
            lHandler.root,
            "//Mask_List/Mask/Mask_Properties/NATURE[.='Detector_Footprint']",
            check=True)
        if l_NodeDetFoo is not None:
            self.MuscateData[
                "ZoneMaskFileNames"] = lHandler.get_map_list_of_detector_footprint_image_filenames(
                )

        pix_node = xml_tools.get_only_value(
            lHandler.root,
            "//Mask_List/Mask/Mask_Properties/NATURE[.='Aberrant_Pixels']",
            check=True)
        if pix_node is not None:
            self.MuscateData[
                "PIXImages"] = lHandler.get_list_of_pix_mask_filenames()
            self.MuscateData[
                "PIXIndices"] = lHandler.get_list_of_pix_mask_indices()

        spectral_node = xml_tools.extract_nodes(
            lHandler.root,
            "//Radiometric_Informations/Spectral_Band_Informations_List")
        if spectral_node is not None:
            self.MuscateData[
                "Node_Spectral_Band_Informations_List"] = spectral_node

        qualityGeo_node = xml_tools.extract_nodes(
            lHandler.root,
            "//Current_Product/Product_Quality_List[@level='Geo']")
        if qualityGeo_node is not None:
            self.MuscateData["Node_Product_Quality_List_Geo"] = qualityGeo_node

        qualityNatif_node = xml_tools.extract_nodes(
            lHandler.root,
            "//Current_Product/Product_Quality_List[@level='Natif']")
        if qualityNatif_node is not None:
            self.MuscateData[
                "Node_Product_Quality_List_Natif"] = qualityNatif_node

        processingJob_node = xml_tools.extract_nodes(
            lHandler.root, "//Production_Informations/Processing_Jobs_List")
        if processingJob_node is not None:
            self.MuscateData["Node_Processing_Jobs_List"] = processingJob_node

        return True
    def write_public_images(self, p_PublicDirectory, p_L2BaseFilename,
                            p_ReflectanceQuantificationValue,
                            p_AOTQuantificationValue, p_AOTNodataValue,
                            p_VAPQuantificationValue, p_VAPNodataValue,
                            p_CLDDataBandsSelected, p_CLDCoreAlgorithmsMapBand,
                            p_WritePublicProduct, p_EnvCorOption, working_dir):

        # IF PUBLIC PART OF L2 PRODUCT IS WRITTEN
        if p_WritePublicProduct:
            l_BandsDefinitions = self._plugin.BandsDefinitions

            l_ListOfL2Res = l_BandsDefinitions.ListOfL2Resolution
            l_NumberOfResolutions = len(l_ListOfL2Res)
            LOGGER.debug(
                "L2ImageFileWriterBase::Initialize Number of resolutions: " +
                str(l_NumberOfResolutions) + ".")
            # Not use the list of XS band because for Landsat8, the band B9 is not
            # selected in the L2 resolution (only in L2Coarse resolution)
            l_BaseL2FullFilename = os.path.join(p_PublicDirectory,
                                                p_L2BaseFilename)
            l_MASKSDirectory = os.path.join(p_PublicDirectory, "MASKS")
            l_BaseL2FullMASKSFilename = os.path.join(l_MASKSDirectory,
                                                     p_L2BaseFilename)
            file_utils.create_directory(l_MASKSDirectory)
            resol_QLK = 0
            l_RedBandId, l_BlueBandId, l_GreenBandId = l_BandsDefinitions.get_l2_information_for_quicklook_band_code(
                self._quicklookredbandcode, self._quicklookgreenbandcode,
                self._quicklookbluebandcode)

            # *************************************************************************************************************
            # ****  LOOP on RESOLUTION   *********************************************
            # *************************************************************************************************************
            for resol in range(0, l_NumberOfResolutions):
                l_StrResolution = l_BandsDefinitions.ListOfL2Resolution[resol]
                # --------------------------------------------------------
                # L2 area AreaType l_AreaToL2Resolution

                l_AreaFile = self._sre_list[resol]
                l_ListOfBand = l_BandsDefinitions.get_list_of_l2_band_code(
                    l_StrResolution)

                l_NumberOfBands = len(l_ListOfBand)
                LOGGER.debug(
                    "L2ImageFileReader::Gen Public image file for the resolution "
                    + l_StrResolution + ".")
                l_grpSuffix = ""
                if l_NumberOfResolutions == 1:
                    l_grpSuffix = "XS"
                else:
                    l_grpSuffix = l_ListOfL2Res[resol]
                l_StrResolution = l_BandsDefinitions.ListOfL2Resolution[resol]

                # Read the Coef apply for SRE and FRE images
                LOGGER.info(
                    "SRE and FRE values multiply by the reflectance quantification value "
                    + str(p_ReflectanceQuantificationValue) + ".")
                # *************************************************************************************************************
                # ****  PUBLIC  DATA      ************************************************
                # *************************************************************************************************************

                # START WRITING SRE Image file DATA
                # Initialize the Scalar filter
                sre_pipeline = OtbPipelineManager()

                #Extract each channel for each file
                tmp_l2_filename_list = []
                tmp_l2_image_list = []
                tmp_sre_scaled = os.path.join(
                    working_dir,
                    "tmp_sre_multi_round_" + l_StrResolution + ".tif")
                param_scaled_sre = {
                    "im": self._sre_list[resol],
                    "coef": p_ReflectanceQuantificationValue,
                    "out": tmp_sre_scaled
                }
                scaled_sre_app = OtbAppHandler("RoundImage",
                                               param_scaled_sre,
                                               write_output=False)
                sre_pipeline.add_otb_app(scaled_sre_app)
                for i in range(l_NumberOfBands):
                    if resol == resol_QLK and (l_RedBandId == i
                                               or l_GreenBandId == i
                                               or l_BlueBandId == i):
                        tmp_sre_roi = os.path.join(
                            working_dir,
                            "tmp_sre_roi_" + l_ListOfBand[i] + ".tif")
                        tmp_sre_roi_app = extract_roi(self._sre_list[resol],
                                                      [i],
                                                      tmp_sre_roi,
                                                      write_output=False)
                        tmp_l2_image_list.append(
                            tmp_sre_roi_app.getoutput().get("out"))
                        tmp_l2_filename_list.append(tmp_sre_roi)
                        if l_RedBandId == i:
                            self._qckl_red_image = tmp_sre_roi
                        elif l_GreenBandId == i:
                            self._qckl_green_image = tmp_sre_roi
                        elif l_BlueBandId == i:
                            self._qckl_blue_image = tmp_sre_roi
                        sre_pipeline.add_otb_app(tmp_sre_roi_app)
                    tmp_sre_scaled_roi = os.path.join(
                        working_dir,
                        "tmp_sre_scaled_roi_" + l_ListOfBand[i] + ".tif")
                    tmp_sre_scaled_roi_app = extract_roi(
                        scaled_sre_app.getoutput().get("out"), [i],
                        tmp_sre_scaled_roi + ":int16",
                        write_output=False)
                    tmp_l2_image_list.append(
                        tmp_sre_scaled_roi_app.getoutput().get("out"))
                    sre_pipeline.add_otb_app(tmp_sre_scaled_roi_app)
                    tmp_l2_filename_list.append(
                        l_BaseL2FullFilename + "_SRE_" + l_ListOfBand[i] +
                        ".tif" + file_utils.
                        get_extended_filename_write_image_file_standard())

                # START WRITING FRE Image file DATA
                tmp_tgs_filename = os.path.join(
                    working_dir, "tmp_tgs_" + l_StrResolution + ".tif")
                tmp_stl_filename = os.path.join(
                    working_dir, "tmp_stl_" + l_StrResolution + ".tif")
                fre_pipeline = OtbPipelineManager()
                if p_EnvCorOption:
                    # Initialize the Scalar filter
                    tmp_fre_scaled = os.path.join(
                        working_dir,
                        "tmp_fre_multi_round_" + l_StrResolution + ".tif")
                    param_scaled_fre = {
                        "im": self._fre_list[resol],
                        "coef": p_ReflectanceQuantificationValue,
                        "out": tmp_fre_scaled
                    }
                    scaled_fre_app = OtbAppHandler("RoundImage",
                                                   param_scaled_fre,
                                                   write_output=False)
                    fre_pipeline.add_otb_app(scaled_fre_app)
                    # Extract each channel for each file
                    for i in range(l_NumberOfBands):
                        tmp_fre_roi = os.path.join(
                            working_dir,
                            "tmp_fre_roi_" + l_ListOfBand[i] + ".tif")
                        tmp_fre_roi_app = extract_roi(
                            scaled_fre_app.getoutput().get("out"), [i],
                            tmp_fre_roi + ":int16",
                            write_output=False)
                        tmp_l2_image_list.append(
                            tmp_fre_roi_app.getoutput().get("out"))
                        fre_pipeline.add_otb_app(tmp_fre_roi_app)
                        tmp_l2_filename_list.append(
                            l_BaseL2FullFilename + "_FRE_" + l_ListOfBand[i] +
                            ".tif" + file_utils.
                            get_extended_filename_write_image_file_standard())
                    #Add tgs and stl also provided by the envcorr
                    tmp_l2_image_list.append(self._tgs_list[resol])
                    tmp_l2_filename_list.append(tmp_tgs_filename)
                    tmp_l2_image_list.append(self._stl_list[resol])
                    tmp_l2_filename_list.append(tmp_stl_filename)

                # START WRITING ATB Image file DATA
                # Initialize the Scalar filter
                # FA1424: Temporary Fix to address cosmetic aspects of FA1424
                # VAPThreshold.SetInput(self.GetVAPImageList()[resol))
                # VAPThreshold.SetOutsideValue(255. / p_VAPQuantificationValue)
                # VAPThreshold.ThresholdAbove(255. / p_VAPQuantificationValue)

                # VAPScalar.SetInput(VAPThreshold.GetOutput())
                # VAPScalar.SetCoef(p_VAPQuantificationValue)
                atb_pipeline = OtbPipelineManager()
                tmp_vap = os.path.join(
                    working_dir, "tmp_vap_scaled_" + l_StrResolution + ".tif")
                param_bandmath_vap = {
                    "il":
                    [self._l2vapimagelist[resol], self._l2edgimagelist[resol]],
                    "exp":
                    "(im2b1 == 1)?" + str(p_VAPNodataValue) + ":" + "im1b1*" +
                    str(p_VAPQuantificationValue),
                    "out":
                    tmp_vap
                }
                vap_scal_app = OtbAppHandler("BandMathDouble",
                                             param_bandmath_vap,
                                             write_output=False)
                atb_pipeline.add_otb_app(vap_scal_app)

                tmp_round_vap = os.path.join(
                    working_dir, "tmp_vap_round_" + l_StrResolution + ".tif")
                param_round_vap = {
                    "im": vap_scal_app.getoutput().get("out"),
                    "out": tmp_round_vap
                }
                vap_round_app = OtbAppHandler("RoundImage",
                                              param_round_vap,
                                              write_output=False)
                atb_pipeline.add_otb_app(vap_round_app)
                tmp_aot = os.path.join(
                    working_dir, "tmp_aot_scaled_" + l_StrResolution + ".tif")
                param_bandmath_aot = {
                    "il":
                    [self._l2aotlist[resol], self._l2edgimagelist[resol]],
                    "exp":
                    "(im2b1 == 1)?" + str(p_AOTNodataValue) + ":" + "im1b1*" +
                    str(p_AOTQuantificationValue),
                    "out":
                    tmp_aot
                }
                aot_scal_app = OtbAppHandler("BandMathDouble",
                                             param_bandmath_aot,
                                             write_output=False)
                atb_pipeline.add_otb_app(aot_scal_app)
                tmp_round_aot = os.path.join(
                    working_dir, "tmp_aot_round_" + l_StrResolution + ".tif")
                param_round_aot = {
                    "im": aot_scal_app.getoutput().get("out"),
                    "out": tmp_round_aot
                }
                aot_round_app = OtbAppHandler("RoundImage",
                                              param_round_aot,
                                              write_output=False)
                atb_pipeline.add_otb_app(aot_round_app)
                atb_filename = l_BaseL2FullFilename + "_ATB_" + l_grpSuffix + ".tif"
                param_atb_concat = {
                    "il": [
                        vap_round_app.getoutput().get("out"),
                        aot_round_app.getoutput().get("out")
                    ],
                    "out":
                    atb_filename + ":uint8" + file_utils.
                    get_extended_filename_write_image_file_standard()
                }

                atb_binconcat_app = OtbAppHandler("ConcatenateImages",
                                                  param_atb_concat,
                                                  write_output=False)
                #tmp_l2_image_list.append(atb_binconcat_app.getoutput().get("out"))
                #tmp_l2_filename_list.append(atb_filename)
                atb_pipeline.add_otb_app(atb_binconcat_app)

                # START WRITING IAB MASK
                iab_pipeline = OtbPipelineManager()
                # Create the image list
                tmp_iab = os.path.join(
                    working_dir, "tmp_iab_concat_" + l_StrResolution + ".tif")
                param_iab_concat = {
                    "il":
                    [self._l2iwcmasklist[resol], self._l2taomasklist[resol]],
                    "out": tmp_iab + ":uint8"
                }
                tmp_iab_concat_app = OtbAppHandler("ConcatenateImages",
                                                   param_iab_concat,
                                                   write_output=False)
                iab_pipeline.add_otb_app(tmp_iab_concat_app)
                iab_filename = l_BaseL2FullMASKSFilename + "_IAB_" + l_grpSuffix + ".tif"
                param_iab_binconcat = {
                    "im":
                    tmp_iab_concat_app.getoutput().get("out"),
                    "out":
                    iab_filename + ":uint8" + file_utils.
                    get_extended_filename_write_image_file_standard()
                }
                iab_binconcat_app = OtbAppHandler("BinaryConcatenate",
                                                  param_iab_binconcat,
                                                  write_output=False)
                iab_pipeline.add_otb_app(iab_binconcat_app)
                write_images([
                    atb_binconcat_app.getoutput().get("out"),
                    iab_binconcat_app.getoutput().get("out")
                ], [atb_filename, iab_filename])

                #tmp_l2_image_list.append(iab_binconcat_app.getoutput().get("out"))
                #tmp_l2_filename_list.append(iab_filename)

                # START WRITING EDG Image file DATA
                tmp_l2_image_list.append(self._l2edgimagelist[resol])
                tmp_l2_filename_list.append(l_BaseL2FullMASKSFilename +
                                            "_EDG_" + l_grpSuffix + ".tif")
                #--------------------------
                # Write all the images at L2 Reso
                write_images(tmp_l2_image_list, tmp_l2_filename_list)
                atb_pipeline.free_otb_app()
                iab_pipeline.free_otb_app()
                fre_pipeline.free_otb_app()
                sre_pipeline.free_otb_app()
                # --------------------------

                #Caching of cloud images needed for MG2
                l_cm2_index = p_CLDCoreAlgorithmsMapBand[CLOUD_MASK_ALL_CLOUDS]
                l_shadows_index = p_CLDCoreAlgorithmsMapBand[
                    CLOUD_MASK_SHADOWS]
                l_shadvar_index = p_CLDCoreAlgorithmsMapBand[
                    CLOUD_MASK_SHADVAR]

                # START WRITING MG2 Image file DATA
                l_mg2_image_list = []
                mg2_pipeline = OtbPipelineManager()
                # Connect the WAM image
                wat_resampled = os.path.join(
                    working_dir, "wat_resampled_" + l_StrResolution + ".tif")
                app_resample_wat = resample(self._wasimage,
                                            self._dtm.ALTList[resol],
                                            wat_resampled,
                                            method=OtbResampleType.LINEAR,
                                            threshold=0.25,
                                            write_output=False)
                l_mg2_image_list.append(
                    app_resample_wat.getoutput().get("out"))
                mg2_pipeline.add_otb_app(app_resample_wat)
                # Extract the CM2 cloud mask
                l_mg2_image_list.append(self._l2cldlist[resol][l_cm2_index])

                #Connect the SNW image if any
                if self._cld_snow is not None:
                    LOGGER.debug(
                        "Snow mask has been successfully computed, adding it to the MG2"
                    )
                    snw_resampled = os.path.join(
                        working_dir,
                        "snw_resampled_" + l_StrResolution + ".tif")
                    app_resample_snw = resample(self._cld_snow,
                                                self._dtm.ALTList[resol],
                                                snw_resampled,
                                                method=OtbResampleType.LINEAR,
                                                threshold=0.25,
                                                write_output=False)
                    l_mg2_image_list.append(
                        app_resample_snw.getoutput().get("out"))
                    mg2_pipeline.add_otb_app(app_resample_snw)
                else:
                    # Add a constant mask
                    tmp_constant_filename = os.path.join(
                        working_dir, "Const_shd_masks.tif")
                    cst_snw_app = constant_image(self._dtm.ALTList[resol],
                                                 0,
                                                 tmp_constant_filename +
                                                 ":uint8",
                                                 write_output=False)
                    l_mg2_image_list.append(cst_snw_app.getoutput().get("out"))
                    mg2_pipeline.add_otb_app(cst_snw_app)

                # Connect the shadow or mask
                tmp_shador_bandmath = os.path.join(
                    working_dir,
                    "tmp_shador_bandmath_" + l_StrResolution + ".tif")
                tmp_band_math_app = band_math([
                    self._l2cldlist[resol][l_shadows_index],
                    self._l2cldlist[resol][l_shadvar_index]
                ],
                                              "im1b1 || im2b1",
                                              tmp_shador_bandmath + ":uint8",
                                              write_output=False)
                l_mg2_image_list.append(
                    tmp_band_math_app.getoutput().get("out"))
                mg2_pipeline.add_otb_app(tmp_band_math_app)
                # Connect the HID image
                hid_resampled = os.path.join(
                    working_dir, "hid_resampled_" + l_StrResolution + ".tif")
                app_resample_hid = resample(self._dtm_hid,
                                            self._dtm.ALTList[resol],
                                            hid_resampled,
                                            method=OtbResampleType.LINEAR,
                                            threshold=0.25,
                                            write_output=False)
                l_mg2_image_list.append(
                    app_resample_hid.getoutput().get("out"))
                mg2_pipeline.add_otb_app(app_resample_hid)
                # Connect the SHDimage
                shd_resampled = os.path.join(
                    working_dir, "shd_resampled_" + l_StrResolution + ".tif")
                app_resample_shd = resample(self._dtm_shd,
                                            self._dtm.ALTList[resol],
                                            shd_resampled,
                                            method=OtbResampleType.LINEAR,
                                            threshold=0.25,
                                            write_output=False)
                mg2_pipeline.add_otb_app(app_resample_shd)
                l_mg2_image_list.append(
                    app_resample_shd.getoutput().get("out"))
                if p_EnvCorOption:
                    # Append STL
                    l_mg2_image_list.append(tmp_stl_filename)
                    # Append TGS
                    l_mg2_image_list.append(tmp_tgs_filename)
                else:
                    # Append STL
                    l_mg2_image_list.append(self._stl_list[resol])
                    # Append TGS
                    l_mg2_image_list.append(self._tgs_list[resol])
                # Concatenate all
                tmp_mg2 = os.path.join(
                    working_dir, "tmp_mg2_concat_" + l_StrResolution + ".tif")
                param_mg2_concat = {"il": l_mg2_image_list, "out": tmp_mg2}
                tmp_mg2_concat_app = OtbAppHandler("ConcatenateImages",
                                                   param_mg2_concat,
                                                   write_output=False)
                param_mg2_binconcat = {
                    "im":
                    tmp_mg2_concat_app.getoutput().get("out"),
                    "out":
                    l_BaseL2FullMASKSFilename + "_MG2_" + l_grpSuffix +
                    ".tif" + ":uint8" + file_utils.
                    get_extended_filename_write_image_file_standard()
                }
                mg2_binconcat_app = OtbAppHandler("BinaryConcatenate",
                                                  param_mg2_binconcat,
                                                  write_output=True)
                mg2_pipeline.add_otb_app(mg2_binconcat_app)
                mg2_pipeline.free_otb_app()

                # START WRITING SAT Image file DATA
                # TODO Create the writer with test on number of bands
                param_sat_binconcat = {
                    "im":
                    self._l2satimagelist[resol],
                    "out":
                    l_BaseL2FullMASKSFilename + "_SAT_" + l_grpSuffix +
                    ".tif" + ":uint8" + file_utils.
                    get_extended_filename_write_image_file_standard()
                }
                sat_binconcat_app = OtbAppHandler("BinaryConcatenate",
                                                  param_sat_binconcat,
                                                  write_output=True)

                # START WRITING PIX Image file DATA
                if "PIXImages" in self._l1_image_info.MuscateData:
                    LOGGER.debug(
                        "The L1 product have 'Aberrant_Pixels' masks. There are writed in the L2 out product..."
                    )
                    otb_file_utils.otb_copy_image_to_file(
                        self._l2piximagelist[resol],
                        l_BaseL2FullMASKSFilename + "_PIX_" + l_grpSuffix +
                        ".tif")
                else:
                    LOGGER.debug("No PIX node detected to write")

                # START WRITING USI Image file DATA
                if "Node_Useful_Image" in self._l1_image_info.MuscateData:
                    LOGGER.debug(
                        "The L1 product have 'Useful_Image' files. There are copied in the L2 out product..."
                    )

                    # Write the USI in the Xml file, in the Useful_Imagenode !
                    l_XPathRootUSI_In = "//Mask[Mask_Properties/NATURE='Useful_Image']/Mask_File_List/MASK_FILE[@group_id='{}']"
                    xnodes_in = xml_tools.get_all_values(
                        self._l1_image_info.MuscateData["Node_Useful_Image"],
                        l_XPathRootUSI_In.format(l_grpSuffix))
                    # Get the path in the xml product filename
                    lPath = os.path.dirname(self._l1_image_info.HeaderFilename)
                    for node_in in xnodes_in:
                        l_FullPathFilename = os.path.join(lPath, node_in.text)
                        # Expand threshold the file
                        usi_resampled = l_BaseL2FullMASKSFilename + "_USI_" + l_grpSuffix + ".tif"\
                                        + file_utils.get_extended_filename_write_mask_file_muscate()
                        resample(l_FullPathFilename,
                                 self._dtm.ALTList[resol],
                                 usi_resampled,
                                 threshold=0.25,
                                 method=OtbResampleType.LINEAR,
                                 write_output=True)

                    else:
                        LOGGER.debug(
                            "No 'Useful_Image' mask detected in the L1 product."
                        )
                # Fin si manage USI

                # START WRITING DFP Image file DATA (=DFP in MUSCATE) #TODO
                if self._l2dfpimagelist is not None:
                    param_dfp_binconcat = {
                        "im":
                        self._l2dfpimagelist[resol],
                        "out":
                        l_BaseL2FullMASKSFilename + "_DFP_" + l_grpSuffix +
                        ".tif"
                    }
                    dfp_binconcat_app = OtbAppHandler("BinaryConcatenate",
                                                      param_dfp_binconcat,
                                                      write_output=True)
                else:
                    LOGGER.debug("DFP Masks not available.")

                # START WRITING CLM (CLD) Image file DATA
                # Connect the CLD image
                # Connect the CLD image
                # -------------------------------------
                l_cld_uses_filenames = False
                for f in self._l2cldlist[resol]:
                    if not otb_is_swig_pointer(f) and os.path.exists(f):
                        l_cld_uses_filenames = True
                self.write_cld_image(self._l2cldlist[resol],
                                     p_CLDDataBandsSelected,
                                     l_BaseL2FullMASKSFilename + "_CLM_" +
                                     l_grpSuffix + ".tif",
                                     use_filenames=l_cld_uses_filenames)
                LOGGER.debug("Writing L2 resolution image done !")