def get_cams_info(self):
     l_cams_info = dict()
     l_cams_info["extinction_coeffs"] = []
     if self.has_cams_info():
         l_count = int(
             xml_tools.get_attribute(
                 self.root,
                 "/Earth_Explorer_Header/Variable_Header/Specific_Product_Header/Extinction_Coefs_List",
                 "count"))
         # loop on coefficients
         for i in range(0, l_count):
             extcoeffs = {}
             l_string = str(i + 1)
             # retrieve description name and value
             extcoeffs["Description"] = xml_tools.get_xml_string_value(
                 self.root, "/Earth_Explorer_Header/Variable_Header/" +
                 "Specific_Product_Header/Extinction_Coefs_List/Extinction_Coef[@n="
                 + l_string + "]/Description")
             extcoeffs["Name"] = xml_tools.get_xml_string_value(
                 self.root,
                 "/Earth_Explorer_Header/Variable_Header/Specific_Product_Header/"
                 + "Extinction_Coefs_List/Extinction_Coef[@n=" + l_string +
                 "]/Name")
             extcoeffs["Values"] = xml_tools.as_string_list(
                 xml_tools.get_xml_string_value(
                     self.root,
                     "/Earth_Explorer_Header/Variable_Header/Specific_Product_Header/"
                     + "Extinction_Coefs_List/Extinction_Coef[@n=" +
                     l_string + "]/Values"))
             l_cams_info["extinction_coeffs"].append(extcoeffs)
     l_cams_info["rh_dep"] = xml_tools.get_xml_bool_value(
         self.root,
         "//Earth_Explorer_Header/Variable_Header/Specific_Product_Header/RH_dep"
     )
     l_cams_info["rh_tab"] = xml_tools.as_string_list(
         xml_tools.get_xml_string_value(
             self.root,
             "//Earth_Explorer_Header/Variable_Header/Specific_Product_Header/RH_Tab"
         ))
     return l_cams_info
    def run(self, dict_of_input, dict_of_output):
        LOGGER.info("Cirrus Correction start")
        cirrus_working = dict_of_input.get(
            "AppHandler").get_directory_manager().get_temporary_directory(
                "CirrusCorrProc_", do_always_remove=True)
        refres_name = dict_of_input.get(
            "Plugin").CirrusCorrectionReferenceResolution
        refres_idx = 9999
        bands_definition = dict_of_input.get("Plugin").BandsDefinitions
        for i in range(0, len(bands_definition.ListOfL2Resolution)):
            if bands_definition.ListOfL2Resolution[i] == refres_name:
                refres_idx = i
        # TODO test refres_idx
        result = {}
        ref_result = self._gamma_compute_at_res(dict_of_input, dict_of_output,
                                                refres_idx, cirrus_working)
        result[bands_definition.ListOfL2Resolution[refres_idx]] = ref_result
        if ref_result[2]:
            LOGGER.info("Cirrus flag enabled on reference resolution")
            l_gammamean = ref_result[3] * ref_result[4]
            l_nbgamma = ref_result[3]
            for i in range(0, len(bands_definition.ListOfL2Resolution)):
                if bands_definition.ListOfL2Resolution[i] != refres_name:
                    res_result = self._gamma_compute_at_res(
                        dict_of_input, dict_of_output, i, cirrus_working)
                    result[bands_definition.ListOfL2Resolution[i]] = res_result
                    l_gammamean = l_gammamean + res_result[3] * res_result[4]
                    l_nbgamma = l_nbgamma + res_result[3]
            l_gammamean = l_gammamean / l_nbgamma
            l_gamma_max = float(
                dict_of_input.get("L2COMM").get_value(
                    "CirrusCorrectionMaxGammaValue"))
            l_gamma_min = float(
                dict_of_input.get("L2COMM").get_value(
                    "CirrusCorrectionMinGammaValue"))
            # Boundary set for gamma
            if l_gammamean > l_gamma_max:
                l_gammamean = l_gamma_max
            if l_gammamean < l_gamma_min:
                l_gammamean = l_gamma_min

            LOGGER.info("Gamma : " + str(l_gammamean))

            # Apply correction
            for i in range(0, len(bands_definition.ListOfL2Resolution)):
                l_res = bands_definition.ListOfL2Resolution[i]
                corrected_toa = os.path.join(cirrus_working,
                                             "toac_" + l_res + ".tif")
                l_gammaswir = l_gammamean * float(
                    dict_of_input.get("L2COMM").get_value(
                        "CirrusCorrectionSWIRGammaFactor"))
                l_l2bandcodes = bands_definition.get_list_of_l2_band_code(
                    l_res)
                swir_band_list = xml_tools.as_string_list(
                    dict_of_input.get("L2COMM").get_value(
                        "CirrusCorrectionSWIRBandCodes"))
                # Param of cirrus apply app
                param_cirrus_apply = {
                    "l2toa":
                    dict_of_output["AtmoAbsIPTOA_" + l_res],
                    "l2edg":
                    dict_of_input.get("L1Reader").get_value("L2EDGOutputList")
                    [i],
                    "l2dtm":
                    dict_of_input.get("DEM").ALTList[i],
                    "l2cirrus":
                    result[l_res][0],
                    "cirrusmask":
                    result[l_res][1],
                    "resolution":
                    bands_definition.get_l1_resolution(l_res),
                    "maxdistance":
                    float(
                        dict_of_input.get("L2COMM").get_value(
                            "CirrusCorrectionMaxDistance")),
                    "thresholdgain":
                    float(
                        dict_of_input.get("L2COMM").get_value(
                            "CirrusMaskThresholdGain")),
                    "thresholdoffset":
                    float(
                        dict_of_input.get("L2COMM").get_value(
                            "CirrusMaskThresholdOffset")),
                    "thresholdfactor":
                    float(
                        dict_of_input.get("L2COMM").get_value(
                            "CirrusCorrectionThresholdFactor")),
                    "gammamean":
                    l_gammamean,
                    "swirgammafactor":
                    l_gammaswir,
                    "maxreflectance":
                    float(
                        dict_of_input.get("L2COMM").get_value(
                            "CirrusMaxReflectance")),
                    "bandcodelist":
                    l_l2bandcodes,
                    "swirbandcodelist":
                    swir_band_list,
                    "correctedtoa":
                    corrected_toa
                }
                app = OtbAppHandler(
                    "CirrusCorrectionApply",
                    param_cirrus_apply,
                    write_output=(False or is_croco_on("cirruscorrection")))
                self._l2_pipeline.add_otb_app(app)
                dict_of_output["L2TOA_" +
                               l_res] = app.getoutput().get("correctedtoa")
        else:
            LOGGER.info(
                "Cirrus flag disabled on reference resolution, no cirrus correction"
            )
        # return cirrus corrected flag
        dict_of_output["CirrusCorrected"] = ref_result[2]
        return ref_result[2]
    def _gamma_compute_at_res(self, dict_of_input, dict_of_output, p_res,
                              p_working):
        bands_definition = dict_of_input.get("Plugin").BandsDefinitions
        l_res = bands_definition.ListOfL2Resolution[p_res]
        LOGGER.info("Cirrus gamma compute at res " + l_res + " start")

        # ---------- Resample L1 Cirrus to resolution ---------------
        l1cirrus_resampled = os.path.join(p_working,
                                          "toacirrus_" + l_res + ".tif")
        param_l1cirrus_resample = {
            "dtm": dict_of_input.get("DEM").ALTList[p_res],
            "im": dict_of_input.get("L1Reader").get_value("L1TOACirrusImage"),
            "interp": "bco",
            "out": l1cirrus_resampled
        }
        app_l1cirrus_resamp = OtbAppHandler("Resampling",
                                            param_l1cirrus_resample,
                                            write_output=True)

        # ---------- Resample Cirrus cloud to resolution ---------------
        cld_cirrus_resampled = dict_of_output[CLOUD_MASK_CIRRUS + "_" + l_res]
        cirrusmask_resampled = os.path.join(p_working,
                                            "cirrusmask_" + l_res + ".tif")
        # ---------- Resample All cloud to resolution ---------------
        cld_all_resampled = dict_of_output[CLOUD_MASK_ALL + "_" + l_res]
        allmask_resampled = os.path.join(p_working,
                                         "allmask_" + l_res + ".tif")
        # ---------- Resample Refl cloud to resolution ---------------
        cld_refl_resampled = dict_of_output[CLOUD_MASK_REFL + "_" + l_res]
        allreflresampled = os.path.join(p_working,
                                        "reflmask_" + l_res + ".tif")
        # -----   Caching of L2TOA
        l2toa_cach = os.path.join(p_working, "l2toa_" + l_res + ".tif")
        #Write to caching
        write_images([
            cld_cirrus_resampled, cld_all_resampled, cld_refl_resampled,
            dict_of_output["L2TOA_" + l_res]
        ], [
            cirrusmask_resampled, allmask_resampled, allreflresampled,
            l2toa_cach
        ])
        # Update dict
        clean_pipe(dict_of_output[CLOUD_MASK_CIRRUS + "_" + l_res])
        clean_pipe(dict_of_output[CLOUD_MASK_ALL + "_" + l_res])
        clean_pipe(dict_of_output[CLOUD_MASK_REFL + "_" + l_res])
        clean_pipe(dict_of_output["L2TOA_" + l_res])
        dict_of_output[CLOUD_MASK_CIRRUS + "_" + l_res] = cirrusmask_resampled
        dict_of_output[CLOUD_MASK_ALL + "_" + l_res] = allmask_resampled
        dict_of_output[CLOUD_MASK_REFL + "_" + l_res] = allreflresampled
        dict_of_output["L2TOA_" + l_res] = l2toa_cach

        # --------------------- Gamma compute for the resolution
        # construct band list
        gamm_band_list = xml_tools.as_string_list(
            dict_of_input.get("L2COMM").get_value(
                "CirrusCorrectionGammaBandCodes"))
        l_l2bandcodes = bands_definition.get_list_of_l2_band_code(l_res)
        l_resbandlist = []
        for i in range(0, len(l_l2bandcodes)):
            if l_l2bandcodes[i] in gamm_band_list:
                l_resbandlist.append(str(i))
        cirrus_mask = os.path.join(p_working,
                                   "cirrus_corr_mask_" + l_res + ".tif")
        param_gamma_compute = {
            "l2toa":
            l2toa_cach,
            "l2edg":
            dict_of_input.get("L1Reader").get_value("L2EDGOutputList")[p_res],
            "l2dtm":
            dict_of_input.get("DEM").ALTList[p_res],
            "l2cirrus":
            app_l1cirrus_resamp.getoutput().get("out"),
            "bandlist":
            l_resbandlist,
            "cloudcirrus":
            cirrusmask_resampled,
            "cloudall":
            allmask_resampled,
            "cloudrefl":
            allreflresampled,
            "cirrusminpixinlist":
            int(
                dict_of_input.get("L2COMM").get_value(
                    "CirrusCorrectionMinPixInList")),
            "mask":
            cirrus_mask + ":uint8"
        }
        gamma_compute_app = OtbAppHandler("GammaCompute",
                                          param_gamma_compute,
                                          write_output=True)
        cirr_flag = bool(gamma_compute_app.getoutput()["cirrusflag"])
        gamma = float(gamma_compute_app.getoutput()["gamma"])
        del gamma_compute_app
        del app_l1cirrus_resamp
        return [
            l1cirrus_resampled, cirrus_mask, cirr_flag,
            len(l_resbandlist), gamma
        ]
示例#4
0
    def read(self, product_info, app_handler, l2comm, dem, pReadL1Mode):
        """product_info,plugin, l2comm,mode

        :param product_info: L1ImageInformationsBase
        :param pReadL1Mode: ReadL1ModeType
        :return:
        """

        product_filename = product_info.HeaderFilename
        working_dir = app_handler.get_directory_manager(
        ).get_temporary_directory("L1Read_", do_always_remove=True)

        self._plugin.initialize(app_handler)
        self._GIPPL2COMMHandler = l2comm
        LOGGER.info("Start Sentinel2 L1 ImageFileReader ...")
        self._ReadL1Mode = pReadL1Mode
        self._dem = dem

        # --------------------------------------
        # Check the extension of th efile. For Muscate, must be .XML (in upper case)
        IsValidSatellite = (product_info.HeaderHandler is not None)
        if not IsValidSatellite:
            raise MajaPluginSentinel2Exception(
                "The file <{}> is not a valid Sentinel2 L1 product.".format(
                    product_filename))

        # Check the validity with the schema
        lSchemaLocationFile = os.path.join(
            app_handler.get_schemas_root_install_dir(),
            self._plugin.MAJA_INSTALL_SCHEMAS_L1PRODUCT_FILE)

        if app_handler.get_validate_schemas():
            # remplacer par un appel à pylint ? un check xml
            result = check_xml(product_filename, xsd_file=lSchemaLocationFile)
            if not result:
                raise MajaPluginSentinel2Exception(
                    "The xml file <{}> is not conform with its schema <{}> !, Log of execution :{}"
                    .format(product_filename, lSchemaLocationFile,
                            str(result)))

        # --------------------------------------
        # Load the header tile file in the xml tile handler to read tile information
        xmlTileFilename = product_info.xmlTileFilename

        # *******************************************************************************************************
        # TOA & masks Reader connection
        # *******************************************************************************************************
        l_BandsDefinitions = self._plugin.BandsDefinitions  # BandsDefinitions
        l_ListOfTOAImageFileNames = product_info.HeaderHandler.get_list_of_toa_images(
        )  # ListOfStrings
        l_SatPixFileNames = product_info.TileHandler.ListOfSaturatedPixelsHeaderFileName  # ListOfStrings
        l_DefectivPixFileNames = product_info.TileHandler.ListOfDefectivPixelsHeaderFileName  # ListOfStrings
        l_ZoneMaskFileNames = product_info.TileHandler.ListOfDetFootPrintHeaderFileName  # ListOfStrings
        l_NoDataMaskFileNames = product_info.TileHandler.ListOfNoDataPixelsHeaderFileName  # ListOfStrings
        l_ListOfTOABandCode = product_info.HeaderHandler.get_list_of_band_codes(
        )  # ListOfStrings
        l_ListOfL1Resolution = l_BandsDefinitions.ListOfL1Resolution  # ListOfStrings
        l_ListOfL2Resolution = l_BandsDefinitions.ListOfL2Resolution  # ListOfStrings
        l_NbL1Res = len(l_ListOfL1Resolution)  # int
        l_NbL2Res = len(l_ListOfL2Resolution)  # int
        l_NbBand = len(l_ListOfTOAImageFileNames)  # int
        # TODO: check ConfigUserCameraXMLFileHandler
        # TODO; check GetL2CoarseResolution grep L2CoarseResolution

        l_Areas = dem.L2Areas
        l_L2CoarseArea = dem.CoarseArea
        l_L2CoarseResolution = int(round(dem.CoarseArea.spacing[0]))
        LOGGER.debug(l_L2CoarseResolution)

        l_L1NoData = product_info.L1NoData
        l_ReflectanceQuantificationValue = product_info.ReflectanceQuantification
        l_RealL1NoData = l_L1NoData * l_ReflectanceQuantificationValue  # RealNoDataType

        if (len(l_ListOfTOABandCode) != len(l_ListOfTOAImageFileNames)) or (
                len(l_ListOfTOABandCode) != len(l_SatPixFileNames)) or (
                    len(l_ListOfTOABandCode) != len(l_DefectivPixFileNames)):
            raise MajaPluginSentinel2Exception(
                "Sentinel2L1ImageFileReader.CanRead: Internal error: The number of image file, sat file and band code are different !"
            )

        # =======> GENERATE TOA CACHING
        #
        # * Get calibration coeffs if activated

        l_reflectanceMultiplicationValues = []  # ListOfDoubles
        if xml_tools.as_bool(l2comm.get_value("CalAdjustOption")):
            l_factors = xml_tools.as_float_list(
                l2comm.get_value("CalAdjustFactor"))
            if len(l_factors) != len(l_ListOfTOABandCode):
                raise MajaPluginSentinel2Exception(
                    "Not the same number of Calibration coeffs than L1 bands ( {}, {} )"
                    .format(len(l_factors), len(l_ListOfTOABandCode)))
            for i in range(len(l_ListOfTOABandCode)):
                l_reflectanceMultiplicationValues.append(
                    l_ReflectanceQuantificationValue * l_factors[i])
        else:
            for i in range(len(l_ListOfTOABandCode)):
                l_reflectanceMultiplicationValues.append(
                    l_ReflectanceQuantificationValue)

        l_ProjectionRef = self._dem.ProjRef
        self.generate_toa(l_ListOfTOAImageFileNames,
                          l_reflectanceMultiplicationValues,
                          working_dir)  # string

        # ***********************************************************************************************************
        # Generate EDG at L2coarse and L2 resolutions
        # ***********************************************************************************************************
        self.generate_edg_images_from_toa(l_ListOfTOAImageFileNames,
                                          working_dir)

        # ***********************************************************************************************************
        # Get the bounding box of each L1 resolution
        # ***********************************************************************************************************
        # list of bounding box per resolution
        l_L1BoundingBoxMap = {}  # BoundingBoxMapType

        for res in range(l_NbL1Res):
            curRes = l_ListOfL1Resolution[res]  # string
            l_IntResolution = l_BandsDefinitions.get_l1_resolution(curRes)
            # Read the bounding box for the current resolution
            l_BoundingBox = product_info.TileHandler.get_geoposition_boundingbox(
                l_IntResolution)  # BoundingBoxType
            LOGGER.debug(
                "S2 Geoposition BoundingBox computed: xmin, ymin, xmax, ymax: %s, %s, %s, %s.",
                l_BoundingBox.xmin, l_BoundingBox.ymin, l_BoundingBox.xmax,
                l_BoundingBox.ymax)

            # Store the bounding box per resolution
            l_L1BoundingBoxMap[curRes] = l_BoundingBox

        # ***********************************************************************************************************
        # ***********************************************************************************************************
        # ***********************************************************************************************************
        #                                     START READ L1 for ALGORITHMS
        # ***********************************************************************************************************
        # ***********************************************************************************************************
        # ***********************************************************************************************************
        if pReadL1Mode == ReadL1Mode.READ_L1_MODE_FOR_ALGORITHMS:
            # --------------------------------------
            # Get information of areas (footprint) of the product (Origin, Spacing and Size for L2 and L2Coarse resolution)
            # --------------------------------------
            l_L2Dems = dem.ALTList
            l_CoarseDem = dem.ALC

            # ***********************************************************************************************************
            # Get the bounding box of each L1 resolution
            # ***********************************************************************************************************
            # list of bounding box per resolution
            l_L2CoarseBoundingBoxMap = {}  # BoundingBoxMapType

            for res in range(l_NbL1Res):
                curRes = l_ListOfL1Resolution[res]  # string
                l_IntResolution = l_BandsDefinitions.get_l1_resolution(curRes)
                l_PointXY = product_info.TileHandler.get_geoposition_upperleftcorner(
                    l_IntResolution)  # PointXYType
                l_L2CoarseBoundingBox = BoundingBox()
                # ATTENTION: For coordinates, cf. FD 73233
                l_L2CoarseBoundingBox.xmin = l_PointXY.x
                l_L2CoarseBoundingBox.ymin = l_PointXY.y - l_L2CoarseArea.size[
                    1] * l_L2CoarseResolution
                l_L2CoarseBoundingBox.xmax = l_PointXY.x + l_L2CoarseArea.size[
                    0] * l_L2CoarseResolution
                l_L2CoarseBoundingBox.ymax = l_PointXY.y

                l_L2CoarseBoundingBoxMap[curRes] = l_L2CoarseBoundingBox

            LOGGER.debug("Start SubSampling ...")

            # =======> GENERATE TOA SUB IMAGES AT L2 COARSE RESOLUTION
            self.generate_toa_sub_images(working_dir)

            LOGGER.debug("Start SubSampling done.")

            # *******************************************************************************************************
            # L2 TOA image pipeline connection
            # ******************* ************************************************************************************

            # =======> GENERATE L2 TOA IMAGES
            self.generate_l2_toa_images(working_dir)

            # *******************************************************************************************************
            # Rasterize the gml mask per L2 resolution per band
            # *******************************************************************************************************

            # =======> GENERATE MASK RASTERS
            self.generate_mask_rasters_gml(
                l_L1BoundingBoxMap, l_Areas, l_ProjectionRef,
                l_SatPixFileNames, l_DefectivPixFileNames, l_ZoneMaskFileNames,
                self._plugin.
                GDAL_RASTERIZE_GML_MASK_ADDITIONAL_COMMAND_LINE_PARAMETERS,
                self._plugin.
                GDAL_RASTERIZE_GML_DETECTOR_ADDITIONAL_COMMAND_LINE_PARAMETERS,
                working_dir)

            l_CurrentConfigUserCamera = self._plugin.ConfigUserCamera
            grid_ref_alt = l_CurrentConfigUserCamera.get_Algorithms(
            ).get_GRID_Reference_Altitudes()
            l_VIEHRef = grid_ref_alt.get_VIEHRef()  # double
            l_SOLH1 = grid_ref_alt.get_SOLH1()  # double

            # *******************************************************************************************************
            # IPSOL Sub image pipeline connection
            # *******************************************************************************************************
            LOGGER.debug("Start IPSOL SubSampling ...")
            l_solarAngleFile = product_info.TileHandler.angles.sun_angles.write(
                working_dir)

            # =======> GENERATE SOLAR ANGLE GRIDS
            self.get_solar_grids(self._dem.ALC, l_solarAngleFile, l_SOLH1,
                                 working_dir)

            LOGGER.debug("Start IPSOL SubSampling done.")

            # *******************************************************************************************************
            # IPVIE Sub image pipeline connection
            # *******************************************************************************************************
            LOGGER.debug("Start IPVIE SubSampling ...")

            LOGGER.debug("For each band ...")
            for l_band in range(l_NbBand):
                l_L1Resolution = l_BandsDefinitions.get_l1_resolution_for_band_code(
                    l_ListOfTOABandCode[l_band])  # string

                # Get the list of detectors (index)
                l_ListOfZone = product_info.TileHandler.get_list_of_zones(
                    l_band)  # ListOfUIntegers

                l_BoundingBox = l_L2CoarseBoundingBoxMap[
                    l_L1Resolution]  # BoundingBoxType

                # Get the list of viewing angles in the header file of the tile
                l_vieAngles = product_info.TileHandler.angles.viewing_incidence_angle.get_viewing_angles(
                    l_band)  # ListOfListOfStrings
                if len(l_vieAngles) == 0:
                    raise MajaPluginSentinel2Exception(
                        "No viewing angles for band " + str(l_band))
                # =======> GENERATE VIEWING ANGLE GRIDS
                self.get_viewing_grids(
                    l_band, l_L2CoarseArea, l_ProjectionRef, l_VIEHRef,
                    l_SatPixFileNames[l_band], l_ZoneMaskFileNames[l_band],
                    l_NoDataMaskFileNames[l_band], l_ListOfZone, l_BoundingBox,
                    l_vieAngles, self._plugin.
                    GDAL_RASTERIZE_GML_MASK_ADDITIONAL_COMMAND_LINE_PARAMETERS,
                    self._plugin.
                    GDAL_RASTERIZE_GML_DETECTOR_ADDITIONAL_COMMAND_LINE_PARAMETERS,
                    self._plugin.
                    GDAL_RASTERIZE_GML_NODATA_ADDITIONAL_COMMAND_LINE_PARAMETERS,
                    l_NbBand, working_dir)

            LOGGER.debug("Start IPVIE SubSampling done.")
            # To check mean angle values
            # TODO: TBD
            # zones = self.m_ViewingZenithMeanMap.keys()
            # values = zip(zones,
            #             [self.m_ViewingZenithMeanMap.get(zone) for zone in zones],
            #             [self.m_ViewingAzimuthMeanMap.get(zone) for zone in zones])
            # for zone, zenith, azimuth in values:
            #    LOGGER.debug(" Mean for zone %s is [zen;azi] : [%s;%s].", zone, zenith, azimuth)

            # *******************************************************************************************************
            # IPEDGSub and L2EDG pipeline connection
            # *******************************************************************************************************

            # *******************************************************************************************************
            # IPSAT Sub and L2SAT image pipeline connection
            # *******************************************************************************************************

            # =======> GENERATE SAT IMAGES
            self.generate_sat_images(working_dir)

            # *******************************************************************************************************
            # CLA image pipeline connection
            # *******************************************************************************************************

            # =======> GENERATE CLA IMAGES
            self.generate_cla_images(l_RealL1NoData, working_dir)

            # Fill the datas
            self.dict_of_vals["IPEDGSubOutput"] = self._edgsubmask
            self.dict_of_vals["SOL1Image"] = self._sol1image
            l_DTMBandCode = xml_tools.as_string_list(
                l2comm.get_value("DTMViewingDirectionBandCode"))[0]
            l_DTMBandIdx = self._plugin.BandsDefinitions.get_band_id_in_l2_coarse(
                l_DTMBandCode)
            LOGGER.info("DTMBandCode= " + l_DTMBandCode)
            self.dict_of_vals["DTMVIEImage"] = self._vieimagelist[l_DTMBandIdx]
            self.dict_of_vals["IPTOASubOutput"] = self._sub_toa
            self.dict_of_vals["L2TOAImageList"] = self._l2toaimagelist

            self.dict_of_vals["ViewingZenithMeanMap"] = self._meanZenithMap
            self.dict_of_vals["ViewingAzimuthMeanMap"] = self._meanAzimuthMap

            self.dict_of_vals["CLAImage"] = self._claimage

            self.dict_of_vals["IPSATSubOutput"] = self._subsatimage
            l_CLDBandCode = l2comm.get_value("CLDViewingDirectionBandCode")
            l_CLDBandIdx = self._plugin.BandsDefinitions.get_band_id_in_l2_coarse(
                l_CLDBandCode)
            self.dict_of_vals["ShadowVIEImage"] = self._vieimagelist[
                l_CLDBandIdx]
            l_CirrusBandCode = l2comm.get_value("CirrusBandCode")
            l_CirrusBandIdx = self._plugin.BandsDefinitions.get_band_id_in_l2_coarse(
                l_CirrusBandCode)

            self.dict_of_vals["L1TOACirrusImage"] = self._toa_scalar_list[
                l_CirrusBandIdx]

            self.dict_of_vals["AngleZoneMaskList"] = self._l2zoneimagelist
            self.dict_of_vals["L2EDGOutputList"] = self._l2edgmasklist
            self.dict_of_vals["L2SATImageList"] = self._l2satmasklist
            self.dict_of_vals["L2PIXImageList"] = self._l2piximagelist
    def run(self, dict_of_input, dict_of_output):
        LOGGER.info("AOT estimation computation start")
        LOGGER.debug("Caching %s", dict_of_input.get("Params").get("Caching"))
        l_caching = dict_of_input.get("Params").get("Caching")
        l_writeL2 = dict_of_input.get("Params").get(
            "WriteL2ProductToL2Resolution")

        aot_working = dict_of_input.get(
            "AppHandler").get_directory_manager().get_temporary_directory(
                "AOTEstimationProc_", do_always_remove=True)

        init_Mode = dict_of_input.get("Params").get("InitMode")
        bands_definition = dict_of_input.get("Plugin").BandsDefinitions
        # TODO concatenate cloud masks
        param_darkest = {
            "toac":
            dict_of_output["AtmoAbsIPTOAC"],
            "cld":
            dict_of_output[constants.CLOUD_MASK_ALL],
            "dtm":
            dict_of_input.get("DEM").ALC,
            "edg":
            dict_of_input.get("L1Reader").get_value("IPEDGSubOutput"),
            "shd":
            dict_of_output["dtm_shd"],
            "lutheader":
            dict_of_input.get("L2TOCR"),
            "lutimage":
            dict_of_output["cr_lut"],
            "darkestchanneltoac":
            dict_of_input.get("Params").get("DarkBandIndex_DateD"),
            "thresholddarkpixel":
            float(dict_of_input.get("L2SITE").get_value("DarkPixelThreshold")),
            "darksurfacereflectance":
            float(
                dict_of_input.get("L2SITE").get_value(
                    "DarkestPixelSurfaceReflectance")),
            "darkestchannelrtc":
            dict_of_input.get("Params").get("DarkBandIndex_DateD")
        }
        if not init_Mode:
            param_darkest["l2ndt"] = dict_of_input.get("L2Reader").get_value(
                "NDTImage")
            param_darkest["l2rtc"] = dict_of_input.get("L2Reader").get_value(
                "RTCImage")
        else:
            param_darkest["init"] = init_Mode

        darkest_app = OtbAppHandler("DarkestPixelAOT",
                                    param_darkest,
                                    write_output=True)
        aot_computed = darkest_app.getoutput()["aotcomputed"]
        darkest_aot = darkest_app.getoutput()["darkestaot"]
        l_aotmethod = dict_of_input.get("Params").get("AOTMethod")
        LOGGER.debug("AOT Estimation Computation Method: " + str(l_aotmethod))
        #AOT Params xml holder
        xml_aot_param = AOT_Estimation()
        #Common parameters
        xml_aot_param.set_Sampling_Interval_Min(
            dict_of_input.get("L2COMM").get_value_i("SamplingIntervalMin"))
        xml_aot_param.set_Sampling_Interval_Max(
            dict_of_input.get("L2COMM").get_value_i("SamplingIntervalMax"))
        xml_aot_param.set_Increment_N_Distance(
            dict_of_input.get("L2COMM").get_value_i("IncrementNDistance"))
        xml_aot_param.set_Half_Window_Size(
            dict_of_input.get("L2COMM").get_value_i("HalfWindowSize"))
        xml_aot_param.set_Max_Iterations(
            dict_of_input.get("L2COMM").get_value_i("MaxIterations"))
        xml_aot_param.set_Step_AOT(
            dict_of_input.get("L2COMM").get_value_i("StepAOT"))
        xml_aot_param.set_N_Pix_Min(
            dict_of_input.get("L2COMM").get_value_i("NPixMin"))
        xml_aot_param.set_F_Tolerance(
            dict_of_input.get("L2COMM").get_value_f("FTolerance"))
        xml_aot_param.set_G_Tolerance(
            dict_of_input.get("L2COMM").get_value_f("GTolerance"))
        xml_aot_param.set_X_Tolerance(
            dict_of_input.get("L2COMM").get_value_f("XTolerance"))
        xml_aot_param.set_Epsilon_Function(
            dict_of_input.get("L2COMM").get_value_f("EpsilonFunction"))
        xml_aot_param.set_AOT_initial_D(
            dict_of_input.get("L2COMM").get_value_f("AOTinitialD"))
        xml_aot_param.set_W_dark(
            dict_of_input.get("L2COMM").get_value_f("Wdark"))
        xml_aot_param.set_W_bounds(
            dict_of_input.get("L2COMM").get_value_f("Wbounds"))
        xml_aot_param.set_AOT_min(
            dict_of_input.get("L2COMM").get_value_f("AOTmin"))
        xml_aot_param.set_AOT_Max_Age(
            dict_of_input.get("L2COMM").get_value_f("AOTMaxAge"))
        xml_aot_param.set_SE_Mask_Dilatation_Radius(
            dict_of_input.get("L2COMM").get_value_f("SEMaskDilatationRadius"))
        xml_aot_param.set_SE_Valid_AOT_Radius(
            dict_of_input.get("L2COMM").get_value_f("SEValidAOTRadius"))

        aot_image = os.path.join(aot_working, "aot_computed.tif")
        aot_mask_estimation = os.path.join(aot_working,
                                           "aot_mask_computed.tif")
        param_aot = {
            "toac": dict_of_output["AtmoAbsIPTOAC"],
            "sat": dict_of_input.get("L1Reader").get_value("IPSATSubOutput"),
            "was": dict_of_output["WaterMask"],
            "dtm": dict_of_input.get("DEM").ALC,
            "edg": dict_of_input.get("L1Reader").get_value("IPEDGSubOutput"),
            "shd": dict_of_output["dtm_shd"],
            "lutheader": dict_of_input.get("L2TOCR"),
            "lutimage": dict_of_output["cr_lut"],
            "cld": dict_of_output[constants.CLOUD_MASK_ALL],
            "reall2nodata": dict_of_input.get("Params").get("RealL2NoData"),
            "jday": dict_of_input.get("Params").get("JDay"),
            "darkestaot": darkest_aot,
            "aotcomputed": aot_image,
            "aotmask": aot_mask_estimation
        }
        if init_Mode:
            param_aot["init"] = init_Mode

        if l_aotmethod == AOTEstimation.MULTISPECTRAL:
            param_aot["mode"] = "multispectral"
        elif l_aotmethod == AOTEstimation.MULTITEMPORAL:
            param_aot["mode"] = "multitemporal"
        elif l_aotmethod == AOTEstimation.SPECTROTEMPORAL:
            param_aot["mode"] = "spectrotemporal"

        if l_aotmethod == AOTEstimation.SPECTROTEMPORAL or l_aotmethod == AOTEstimation.MULTITEMPORAL:
            stdevbandid = bands_definition.get_band_id_in_l2_coarse(
                dict_of_input.get("L2COMM").get_value("StdevBandCode"))
            if not init_Mode:
                param_aot["temporal.lutmap"] = dict_of_input.get(
                    "L2Reader").get_value("LTCImage")
            param_aot["temporal.altitudemean"] = dict_of_input.get(
                "DEM").ALT_Mean
            xml_aot_param.set_Multi_Temporal_Method(
                Multi_Temporal_MethodType())
            xml_aot_param.get_Multi_Temporal_Method().set_First_AOT(
                dict_of_input.get("L2COMM").get_value_f("FirstAOT"))
            xml_aot_param.get_Multi_Temporal_Method().set_Second_AOT(
                dict_of_input.get("L2COMM").get_value_f("SecondAOT"))
            xml_aot_param.get_Multi_Temporal_Method().set_TOA_Reflectance_Min(
                dict_of_input.get("L2COMM").get_value_f("TOAReflectanceMin"))
            xml_aot_param.get_Multi_Temporal_Method().set_TOA_Reflectance_Max(
                dict_of_input.get("L2COMM").get_value_f("TOAReflectanceMax"))
            xml_aot_param.get_Multi_Temporal_Method().set_TOA_Reflectance_Step(
                dict_of_input.get("L2COMM").get_value_f("TOAReflectanceStep"))
            xml_aot_param.get_Multi_Temporal_Method(
            ).set_Min_Difference_Thresholds_Calculation(
                dict_of_input.get("L2COMM").get_value_f(
                    "MinDifferenceThreshold"))
            xml_aot_param.get_Multi_Temporal_Method().set_Relative_Var_Max(
                dict_of_input.get("L2COMM").get_value_f("RelativeVarMax"))
            xml_aot_param.get_Multi_Temporal_Method().set_Var_Band_Code_D(
                dict_of_input.get("Params").get("VarBandIndex_DateD"))
            xml_aot_param.get_Multi_Temporal_Method().set_Var_Band_Code_Dm1(
                dict_of_input.get("Params").get("VarBandIndex_DateDm1"))
            xml_aot_param.get_Multi_Temporal_Method().set_Stdev_Band_Code(
                stdevbandid)
            xml_aot_param.get_Multi_Temporal_Method().set_Std_Noise(
                dict_of_input.get("L2COMM").get_value_f("StdNoise"))
            xml_aot_param.get_Multi_Temporal_Method().set_Stdev_Min(
                dict_of_input.get("L2COMM").get_value_f("StdevMin"))
            xml_aot_param.get_Multi_Temporal_Method().set_AOT_initial_Dm1(
                dict_of_input.get("L2COMM").get_value_f("AOTinitialDm1"))
            xml_aot_param.get_Multi_Temporal_Method().set_W_MT_equation2(
                dict_of_input.get("L2COMM").get_value_f("WMTequation2"))
            xml_aot_param.get_Multi_Temporal_Method().set_MT_AOT_Band_Code_D([
                str(i)
                for i in dict_of_input.get("Params").get("MTAOTbandsDateD")
            ])
            xml_aot_param.get_Multi_Temporal_Method(
            ).set_MT_AOT_Band_Reflectance_Composite_Dm1([
                str(i) for i in dict_of_input.get("Params").get(
                    "MTAOTbandsOfTheReflectancesComposite_DateDm1")
            ])
            xml_aot_param.get_Multi_Temporal_Method(
            ).set_MT_AOT_Band_LUT_Composite_Dm1([
                str(i) for i in dict_of_input.get("Params").get(
                    "MTAOTbandsOfTheLTCComposite_DateDm1")
            ])

        if l_aotmethod == AOTEstimation.MULTISPECTRAL or l_aotmethod == AOTEstimation.SPECTROTEMPORAL:
            lMSAOTRedBand = bands_definition.get_band_id_in_l2_coarse(
                dict_of_input.get("L2COMM").get_value("MSAOTRedBandCode"))
            lNDVIAOTBand1 = bands_definition.get_band_id_in_l2_coarse(
                dict_of_input.get("L2COMM").get_value("NDVIAOTBand1Code"))
            lNDVIAOTBand2 = bands_definition.get_band_id_in_l2_coarse(
                dict_of_input.get("L2COMM").get_value("NDVIAOTBand2Code"))
            l_AOTUsedBandCodes = xml_tools.as_string_list(
                dict_of_input.get("L2COMM").get_value("MSAOTBandCode"))
            lMSAOTbands = [
                str(bands_definition.get_band_id_in_l2_coarse(f))
                for f in l_AOTUsedBandCodes
            ]

            xml_aot_param.set_Multi_Spectral_Method(
                Multi_Spectral_MethodType())
            xml_aot_param.get_Multi_Spectral_Method().set_MS_AOT_Band_Code(
                lMSAOTbands)
            xml_aot_param.get_Multi_Spectral_Method().set_MS_AOT_Red_Band_Code(
                lMSAOTRedBand)
            xml_aot_param.get_Multi_Spectral_Method().set_NDVI_AOT_Band1_Code(
                lNDVIAOTBand1)
            xml_aot_param.get_Multi_Spectral_Method().set_NDVI_AOT_Band2_Code(
                lNDVIAOTBand2)
            xml_aot_param.get_Multi_Spectral_Method().set_Red_TOA_Threshold(
                dict_of_input.get("L2COMM").get_value_f("RedTOAThreshold"))
            xml_aot_param.get_Multi_Spectral_Method().set_NDVI_Threshold(
                dict_of_input.get("L2COMM").get_value_f("NDVIThreshold"))
            xml_aot_param.get_Multi_Spectral_Method().set_MS_Slope(
                dict_of_input.get("L2COMM").get_value_f("MSSlope"))
            xml_aot_param.get_Multi_Spectral_Method().set_MS_YIntercept(
                dict_of_input.get("L2COMM").get_value_f("MSYIntercept"))
            xml_aot_param.get_Multi_Spectral_Method().set_NDVI_Slope(
                dict_of_input.get("L2COMM").get_value_f("NDVISlope"))
            xml_aot_param.get_Multi_Spectral_Method().set_NDVI_YIntercept(
                dict_of_input.get("L2COMM").get_value_f("NDVIYIntercept"))
            xml_aot_param.get_Multi_Spectral_Method().set_W_MS(
                dict_of_input.get("L2COMM").get_value_f("WMS"))

        if l_aotmethod == AOTEstimation.SPECTROTEMPORAL:
            spectrotemp = Spectro_Temporal_MethodType()
            xml_aot_param.set_Spectro_Temporal_Method(spectrotemp)
            xml_aot_param.get_Spectro_Temporal_Method(
            ).set_MT_Weight_Threshold(
                dict_of_input.get("L2COMM").get_value_f("MTWeightThreshold"))
            xml_aot_param.get_Spectro_Temporal_Method().set_A_Coefficient(
                dict_of_input.get("L2COMM").get_value_f("ACoefficient"))
            xml_aot_param.get_Spectro_Temporal_Method().set_B_Coefficient(
                dict_of_input.get("L2COMM").get_value_f("BCoefficient"))

        const_mask_filename = os.path.join(aot_working, "cloud_constzero.tif")
        constant_app = constant_image(dict_of_input.get("DEM").ALC,
                                      0,
                                      const_mask_filename + ":uint8",
                                      write_output=l_caching)
        constant_mask = constant_app.getoutput()["out"]

        if dict_of_input.get("Params").get("SnowBandAvailable"):
            param_aot["snow"] = dict_of_output.get("cld_snow")
        else:
            param_aot["snow"] = constant_mask

        if not init_Mode:
            param_aot["l2ndt"] = dict_of_input.get("L2Reader").get_value(
                "NDTImage")
            param_aot["l2pxd"] = dict_of_input.get("L2Reader").get_value(
                "PXDImage")
            param_aot["l2rtc"] = dict_of_input.get("L2Reader").get_value(
                "RTCImage")
            param_aot["l2rta"] = dict_of_input.get("L2Reader").get_value(
                "RTAImage")

        # Cams related parameters
        if dict_of_input.get("Params").get("UseCamsData"):
            xml_aot_param.set_AOT_KPondCAMS(
                dict_of_input.get("L2COMM").get_value_f("KPondsCams"))
            xml_aot_param.set_AOT_HeightScale(
                dict_of_input.get("L2COMM").get_value_f("HeighScale"))
            param_aot["cams.nodatatau"] = dict_of_input.get("Params").get(
                "RealL2NoData")
            param_aot["cams.altmean"] = dict_of_input.get("DEM").ALT_Mean
            param_aot["cams.aot"] = dict_of_input.get("CAMS_AOT")
            aot_cams_image = os.path.join(aot_working, "aot_cams.tif")
            param_aot["aotcams"] = aot_cams_image

        #Write down the xml interface
        output = io.StringIO()
        output.write('<?xml version="1.0" ?>\n')
        xml_aot_param.export(output,
                             0,
                             name_='AOTEstimation',
                             namespacedef_='',
                             pretty_print=True)
        l_xml_param_filename = os.path.join(aot_working, "AOTParams.xml")
        with open(l_xml_param_filename, "w") as fh:
            fh.write(output.getvalue().replace("    ", "  "))
        LOGGER.info("Writed aot params to " + l_xml_param_filename)
        param_aot["xmlparamsfile"] = l_xml_param_filename
        # Effectively launch the app
        aot_app = OtbAppHandler("AOTEstimation",
                                param_aot,
                                write_output=l_caching)
        if not l_caching:
            self._aot_pipeline.add_otb_app(aot_app)

        aot_mean = aot_app.getoutput()["aotmean"]
        aot_valid = aot_app.getoutput()["aotvalid"]

        # If cams used then no gapfilling needed
        if dict_of_input.get("Params").get("UseCamsData"):
            smoothing_input = aot_app.getoutput()["aotcomputed"]
            mask_input = aot_app.getoutput()["aotmask"]
        else:
            aot_gapfilled_image = os.path.join(aot_working,
                                               "aot_gapfilled.tif")
            aot_gapfilled_mask = os.path.join(aot_working,
                                              "aot_gapfilled_mask.tif")
            param_gapfilling = {
                "im":
                aot_app.getoutput()["aotcomputed"],
                "initwindowsradius":
                dict_of_input.get("L2COMM").get_value_i("InitWindowRadius"),
                "maxwindowsradius":
                dict_of_input.get("L2COMM").get_value_i("MaxWindowRadius"),
                "reall2nodata":
                dict_of_input.get("Params").get("RealL2NoData"),
                "mean":
                aot_mean,
                "hasvalidpixels":
                aot_valid,
                "defaultvalue":
                dict_of_input.get("L2COMM").get_value_f("DefaultAOT"),
                "out":
                aot_gapfilled_image,
                "outmask":
                aot_gapfilled_mask + ":uint8"
            }

            gap_filling_app = OtbAppHandler("GapFilling",
                                            param_gapfilling,
                                            write_output=(l_caching
                                                          or l_writeL2))
            if not (l_caching or l_writeL2):
                self._aot_pipeline.add_otb_app(gap_filling_app)
            smoothing_input = gap_filling_app.getoutput()["out"]
            mask_input = gap_filling_app.getoutput()["outmask"]

        aot_smoothed_image = os.path.join(aot_working, "aot_smoothed.tif")
        param_smoothing = {
            "in":
            smoothing_input,
            "out":
            aot_smoothed_image,
            "type":
            "gaussian",
            "type.gaussian.radius":
            dict_of_input.get("L2COMM").get_value_f("SigmaSmoothingAOT"),
            "type.gaussian.maxkernelwidth":
            4.0 * dict_of_input.get("L2COMM").get_value_f("SigmaSmoothingAOT"),
            "type.gaussian.maxerror":
            1e-15
        }

        smoothed_app = OtbAppHandler("SmoothingBis",
                                     param_smoothing,
                                     write_output=l_caching)
        if (not l_caching):
            self._aot_pipeline.add_otb_app(smoothed_app)

        aot_sub_image = os.path.join(aot_working, "aot_sub.tif")
        param_subresampling = {
            "dtm": dict_of_input.get("DEM").ALC,
            "im": smoothed_app.getoutput()["out"],
            "interp": "linear",
            "out": aot_sub_image
        }

        subresampling_app = OtbAppHandler("Resampling",
                                          param_subresampling,
                                          write_output=(l_caching
                                                        or l_writeL2))
        if (not (l_caching or l_writeL2)):
            self._aot_pipeline.add_otb_app(subresampling_app)
        dict_of_output["AOT_Sub"] = subresampling_app.getoutput()["out"]

        if l_writeL2:
            l_nbRes = len(bands_definition.ListOfL2Resolution)
            aot_list = []
            aotmask_list = []
            for r in range(0, l_nbRes):
                l_res = bands_definition.ListOfL2Resolution[r]
                aot_image = os.path.join(aot_working, "aot_" + l_res + ".tif")
                aot_mask = os.path.join(aot_working,
                                        "aotmask_" + l_res + ".tif")
                param_subresampling["dtm"] = dict_of_input.get(
                    "DEM").ALTList[r]
                param_subresampling["im"] = subresampling_app.getoutput(
                )["out"]
                param_subresampling["out"] = aot_image
                resamp_aot_app = OtbAppHandler("Resampling",
                                               param_subresampling)

                dict_of_output["AOT_" +
                               l_res] = resamp_aot_app.getoutput().get("out")
                param_maskresampling = {
                    "dtm": dict_of_input.get("DEM").ALTList[r],
                    "im": mask_input,
                    "interp": "linear",
                    "out": aot_mask + ":uint8",
                    "threshold": 0.25
                }
                resamp_aotmask_app = OtbAppHandler("Resampling",
                                                   param_maskresampling)
                dict_of_output["AOTMASK_" +
                               l_res] = resamp_aotmask_app.getoutput().get(
                                   "out")
                aot_list.append(resamp_aot_app.getoutput().get("out"))
                aotmask_list.append(resamp_aotmask_app.getoutput().get("out"))
            dict_of_output["L2AOTList"] = aot_list
            dict_of_output["L2AOTMaskList"] = aotmask_list
    def read(self, product_info, app_handler, l2comm, dem, pReadL1Mode):
        """product_info,plugin, l2comm,mode

        :param product_info: L1ImageInformationsBase
        :param pReadL1Mode: ReadL1ModeType
        :return:
        """
        LOGGER.info("Start Sentinel2Muscate L1 ImageFileReader ...")
        product_filename = product_info.HeaderFilename
        LOGGER.info(
            "Start Sentinel2Muscate L1 ImageFileReader with filename : " +
            product_filename)
        working_dir = app_handler.get_directory_manager(
        ).get_temporary_directory("L1Read_", do_always_remove=True)
        self._plugin.initialize(app_handler)
        self._GIPPL2COMMHandler = l2comm
        LOGGER.info("Start Sentinel2Muscate L1 ImageFileReader ...")
        self._ReadL1Mode = pReadL1Mode
        self._dem = dem

        # --------------------------------------
        # Check the extension of th efile. For Muscate, must be .XML (in upper case)
        IsValidSatellite = (product_info.HeaderHandler is not None)
        if not IsValidSatellite:
            raise MajaExceptionPluginSentinel2Muscate(
                "The file <{}> is not a valid Sentinel2 L1 product.".format(
                    product_filename))
        self.m_headerHandler = product_info.HeaderHandler
        # Get satellite name
        self.m_Satellite = product_info.Satellite

        # --------------------------------------
        # Load the header tile file in the xml tile handler to read tile information
        xmlTileFilename = product_info.xmlTileFilename
        l_BandsDefinitions = self._plugin.BandsDefinitions  # BandsDefinitions

        # TOA & masks Reader connection
        l_ListOfTOAImageFileNames = product_info.HeaderHandler.get_list_of_toa_image_filenames(
        )
        l_SatPixFileNames = product_info.HeaderHandler.get_list_of_l1_sat_image_filenames(
        )
        l_DefectivPixFileNames = product_info.HeaderHandler.get_list_of_defective_pixel_image_filenames(
        )
        l_ZoneMaskFileNames = product_info.HeaderHandler.get_map_list_of_detector_footprint_image_filenames(
        )
        l_NoDataMaskFileNames = product_info.HeaderHandler.get_list_of_l1_ndt_image_filenames(
        )
        l_ListOfTOABandCode = product_info.HeaderHandler.get_list_of_band_code(
        )  # ListOfStrings
        l_NbBand = len(l_ListOfTOAImageFileNames)  # int
        l_L1NoData = product_info.L1NoData
        l_ReflectanceQuantificationValue = product_info.ReflectanceQuantification
        l_RealL1NoData = l_L1NoData * l_ReflectanceQuantificationValue  # RealNoDataType

        if (len(l_ListOfTOABandCode) != len(l_ListOfTOAImageFileNames)) or (
                len(l_ListOfTOABandCode) != len(l_SatPixFileNames)) or (
                    len(l_ListOfTOABandCode) != len(l_DefectivPixFileNames)):
            raise MajaExceptionPluginSentinel2Muscate(
                "Sentinel2L1ImageFileReader.CanRead: Internal error: The number of image file, sat file and band code are different !"
            )

        # =======> GENERATE TOA
        # Get calibration coeffs if activated
        l_reflectanceMultiplicationValues = []  # ListOfDoubles
        if xml_tools.as_bool(l2comm.get_value("CalAdjustOption")):
            l_factors = xml_tools.as_float_list(
                l2comm.get_value("CalAdjustFactor"))
            if len(l_factors) != len(l_ListOfTOABandCode):
                raise MajaDataException(
                    "Not the same number of Calibration coeffs than L1 bands ( {}, {} )"
                    .format(len(l_factors), len(l_ListOfTOABandCode)))
            for i in range(len(l_ListOfTOABandCode)):
                l_reflectanceMultiplicationValues.append(
                    l_ReflectanceQuantificationValue * l_factors[i])
        else:
            for i in range(len(l_ListOfTOABandCode)):
                l_reflectanceMultiplicationValues.append(
                    l_ReflectanceQuantificationValue)

        l_ProjectionRef = self._dem.ProjRef
        self.generate_toa(l_ListOfTOAImageFileNames,
                          l_reflectanceMultiplicationValues,
                          working_dir)  # string

        #                                     START READ L1 for ALGORITHMS
        if pReadL1Mode == ReadL1Mode.READ_L1_MODE_FOR_ALGORITHMS:
            # =======> GENERATE TOA SUB IMAGES AT L2 COARSE RESOLUTION
            LOGGER.debug("Start SubSampling ...")
            self.generate_toa_sub_images(working_dir)
            LOGGER.debug("Start SubSampling done.")
            #  the gml mask per L2 resolution per band
            self.generate_mask_rasters(l_SatPixFileNames,
                                       l_DefectivPixFileNames,
                                       l_ZoneMaskFileNames,
                                       l_NoDataMaskFileNames,
                                       l_ListOfTOABandCode, working_dir)

            LOGGER.debug("Filenames Mask Rasters : ")
            LOGGER.debug(l_SatPixFileNames)
            LOGGER.debug(l_DefectivPixFileNames)
            LOGGER.debug(l_ZoneMaskFileNames)
            LOGGER.debug(l_NoDataMaskFileNames)
            LOGGER.debug(l_ListOfTOABandCode)

            # Get the ref altitude
            l_CurrentConfigUserCamera = self._plugin.ConfigUserCamera
            grid_ref_alt = l_CurrentConfigUserCamera.get_Algorithms(
            ).get_GRID_Reference_Altitudes()
            l_VIEHRef = grid_ref_alt.get_VIEHRef()  # double
            l_SOLH1 = grid_ref_alt.get_SOLH1()  # double

            # IPSOL Sub image pipeline connection
            LOGGER.debug("Start IPSOL SubSampling ...")
            sun_angle_col_step = int(
                product_info.HeaderHandler.get_string_value_of(
                    "SunAngleColStep"))
            sun_angle_row_step = int(
                product_info.HeaderHandler.get_string_value_of(
                    "SunAngleRowStep"))
            # ATTENTION : * -1 for compatibility negative spacing
            LOGGER.debug(
                "Angle Resolution Spacing computed in 5000 resolution: " +
                str(sun_angle_col_step) + " , " + str(sun_angle_row_step))

            l_zenithSolarAngles = product_info.HeaderHandler.get_sun_zenithal_angles(
            )
            l_azimuthSolarAngles = product_info.HeaderHandler.get_sun_azimuthal_angles(
            )
            LOGGER.debug("ZenithSolarAngles nb values: " +
                         str(len(l_zenithSolarAngles)))
            LOGGER.debug("AzimuthSolarAngles nb values: " +
                         str(len(l_azimuthSolarAngles)))

            l_solarAngleFile = app_handler.get_directory_manager(
            ).get_temporary_file("sun_angles_") + ".xml"

            LOGGER.debug("Angles output_filename : %s", l_solarAngleFile)
            writer = MajaInternalXmlInputAngles(l_zenithSolarAngles,
                                                l_azimuthSolarAngles,
                                                sun_angle_col_step,
                                                sun_angle_row_step,
                                                l_solarAngleFile)
            writer.write()
            # =======> GENERATE SOLAR ANGLE GRIDS
            self.get_solar_grids(self._dem.ALC, l_solarAngleFile, l_SOLH1,
                                 working_dir)
            LOGGER.debug("Start IPSOL SubSampling done.")

            # IPVIE Sub image pipeline connection
            LOGGER.debug("Start IPVIE SubSampling ...")
            vie_angle_col_step = int(
                product_info.HeaderHandler.get_string_value_of(
                    "SunAngleColStep"))
            vie_angle_row_step = int(
                product_info.HeaderHandler.get_string_value_of(
                    "SunAngleRowStep"))
            LOGGER.debug("For each band ...")
            for l_band in l_ListOfTOABandCode:
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l_band)
                # Get the list of detectors (index)
                l_ListOfZone = product_info.HeaderHandler.get_list_of_zones(
                    l_band)
                # Get the list of viewing angles in the header file of the tile
                l_zenithVieAngles = product_info.HeaderHandler.get_viewing_zenithal_angles(
                    l_band)
                l_azimuthVieAngles = product_info.HeaderHandler.get_viewing_azimuthal_angles(
                    l_band)
                if len(l_zenithVieAngles) != len(l_azimuthVieAngles):
                    raise MajaExceptionPluginSentinel2Muscate(
                        "The number of detector for viewing zenithal angles and viewing azimuthal angles is different or null !"
                    )

                # =======> GENERATE VIEWING ANGLE GRIDS
                self.GetViewingGrids(l_band, l_NbBand, l_VIEHRef,
                                     l_SatPixFileNames[l1BandIdx],
                                     l_ZoneMaskFileNames[l1BandIdx],
                                     l_NoDataMaskFileNames[l1BandIdx],
                                     l_ListOfZone, vie_angle_col_step,
                                     vie_angle_row_step, l_zenithVieAngles,
                                     l_azimuthVieAngles, working_dir)

            # end loop nbBand

            LOGGER.debug("Start IPVIE SubSampling done.")

            # To check mean angle values
            # TODO

            # IPEDGSub and L2EDG pipeline connection
            # =======> GENERATE EDG IMAGES
            self.generate_edg_images(working_dir)
            # L2 TOA image pipeline connection
            # =======> GENERATE L2 TOA IMAGES
            self.generate_l2_toa_images(working_dir)
            # IPSAT Sub and L2SAT image pipeline connection
            # =======> GENERATE SAT IMAGES
            self.generate_sat_images(working_dir)
            # CLA image pipeline connection
            # =======> GENERATE CLA IMAGES
            self.generate_cla_images(l_RealL1NoData, working_dir)

            # Fill the datas
            self.dict_of_vals["IPEDGSubOutput"] = self._edgsubmask
            self.dict_of_vals["SOL1Image"] = self._sol1image
            l_DTMBandCode = xml_tools.as_string_list(
                l2comm.get_value("DTMViewingDirectionBandCode"))[0]
            l_DTMBandIdx = self._plugin.BandsDefinitions.get_band_id_in_l2_coarse(
                l_DTMBandCode)

            self.dict_of_vals["DTMVIEImage"] = self._vieimagelist[l_DTMBandIdx]

            LOGGER.debug("l_DTMBandIdx : ")
            LOGGER.debug(l_DTMBandIdx)
            self.dict_of_vals["IPTOASubOutput"] = self._sub_toa
            self.dict_of_vals["L2TOAImageList"] = self._l2toaimagelist

            self.dict_of_vals["ViewingZenithMeanMap"] = self._meanZenithMap
            self.dict_of_vals["ViewingAzimuthMeanMap"] = self._meanAzimuthMap

            self.dict_of_vals["CLAImage"] = self._claimage

            self.dict_of_vals["IPSATSubOutput"] = self._subsatimage
            l_CLDBandCode = l2comm.get_value("CLDViewingDirectionBandCode")
            l_CLDBandIdx = self._plugin.BandsDefinitions.get_band_id_in_l2_coarse(
                l_CLDBandCode)
            LOGGER.debug("l_CLDBandIdx: ")
            LOGGER.debug(l_CLDBandIdx)
            self.dict_of_vals["ShadowVIEImage"] = self._vieimagelist[
                l_CLDBandIdx]
            l_CirrusBandCode = l2comm.get_value("CirrusBandCode")
            l_CirrusBandIdx = self._plugin.BandsDefinitions.get_band_id_in_l2_coarse(
                l_CirrusBandCode)

            LOGGER.debug("l_CirrusBandIdx: ")
            LOGGER.debug(l_CirrusBandIdx)

            self.dict_of_vals["L1TOACirrusImage"] = self._toa_scalar_list[
                l_CirrusBandIdx]

            self.dict_of_vals["AngleZoneMaskList"] = self._l2zoneimagelist
            self.dict_of_vals["L2EDGOutputList"] = self._l2edgmasklist
            self.dict_of_vals["L2SATImageList"] = self._l2satmasklist
            self.dict_of_vals["L2PIXImageList"] = self._l2piximagelist
            self.dict_of_vals["L2DFPImageList"] = self._l2dfpimagelist
示例#7
0
    def run(self, dict_of_input, dict_of_output):
        LOGGER.info("Lut computation start")
        l_writeL2 = dict_of_input.get("Params").get(
            "WriteL2ProductToL2Resolution")
        viewing_zenith = dict_of_input.get(
            "L1Info").ListOfViewingZenithAnglesPerBandAtL2CoarseResolution
        viewing_azimuth = dict_of_input.get(
            "L1Info").ListOfViewingAzimuthAnglesPerBandAtL2CoarseResolution
        # CR Lut generation
        rlc_working = dict_of_input.get(
            "AppHandler").get_directory_manager().get_temporary_directory(
                "ReduceLutProc_", do_always_remove=True)
        cr_lut_file = os.path.join(rlc_working, "CR_Lut.mha")
        param_cr_lut = {
            "lut":
            dict_of_input.get("L2TOCR"),
            "solar.zenith":
            float(dict_of_input.get("L1Info").SolarAngle["sun_zenith_angle"]),
            "solar.azimuth":
            float(dict_of_input.get("L1Info").SolarAngle["sun_azimuth_angle"]),
            "viewing.zenith":
            viewing_zenith,
            "viewing.azimuth":
            viewing_azimuth,
            "reducelut":
            cr_lut_file
        }
        if dict_of_input.get(
                "Plugin").DirectionalCorrection and dict_of_input.get(
                    "L2COMM").get_value("DirCorrOption"):
            param_cr_lut["coeffsr"] = xml_tools.as_string_list(
                dict_of_input.get("L2COMM").get_value("CoefsR"))
            param_cr_lut["coeffsv"] = xml_tools.as_string_list(
                dict_of_input.get("L2COMM").get_value("CoefsV"))
            param_cr_lut["refzenith"] = float(
                dict_of_input.get("L2COMM").get_value("ZenithRef"))
            param_cr_lut["refazimuth"] = float(
                dict_of_input.get("L2COMM").get_value("AzimuthRef"))
            param_cr_lut["dircorr"] = True

        OtbAppHandler("ReduceLut", param_cr_lut)
        dict_of_output["cr_lut"] = cr_lut_file
        # Read the input lut header to get indexes
        old_lut = maja_xml_app_lut.parse(dict_of_input.get("L2TOCR"), True)
        # HR lut if wide field
        l_lutmap = LUTMap()
        # Add cr lut to map
        l_listoffile = List_Of_FilesType()
        l_listoffile.add_Relative_File_Path(os.path.basename(cr_lut_file))
        l_lut = LUT(index=0,
                    Indexes=old_lut.get_Indexes(),
                    List_Of_Files=l_listoffile)
        l_lutmap.add_LUT(l_lut)
        if dict_of_input.get("Plugin").WideFieldSensor and l_writeL2:
            m_ViewingZenithAnglesMap = dict_of_input.get("L1Reader").get_value(
                "ViewingZenithMeanMap")
            m_ViewingAzimuthAnglesMap = dict_of_input.get(
                "L1Reader").get_value("ViewingAzimuthMeanMap")
            for key in list(m_ViewingZenithAnglesMap.keys()):
                if key not in m_ViewingAzimuthAnglesMap:
                    raise MajaDataException(
                        "Internal ERROR: The Viewing Zenith angles Map per zone are incorrect !!"
                    )
                l_listoffile = List_Of_FilesType()
                l_listoffile.add_Relative_File_Path("HR_Lut_" + key + ".mha")
                l_lut = LUT(index=key,
                            Indexes=old_lut.get_Indexes(),
                            List_Of_Files=l_listoffile)
                l_ViewingZenithAngle = m_ViewingZenithAnglesMap.get(key)
                l_ViewingAzimuthAngle = m_ViewingAzimuthAnglesMap.get(key)
                if len(l_ViewingZenithAngle) != len(
                        dict_of_input.get(
                            "Plugin").BandsDefinitions.L2CoarseBandMap):
                    raise MajaDataException(
                        "Error on input L1 product: missing Viewing angles for some l2 coarse band on detector "
                        + key +
                        " , all l2 coarse bands are needed for HR_Lut generation"
                    )

                hr_lut_file = os.path.join(rlc_working,
                                           "HR_Lut_" + key + ".mha")
                param_hr_lut = {
                    "lut":
                    dict_of_input.get("L2TOCR"),
                    "solar.zenith":
                    float(
                        dict_of_input.get(
                            "L1Info").SolarAngle["sun_zenith_angle"]),
                    "solar.azimuth":
                    float(
                        dict_of_input.get(
                            "L1Info").SolarAngle["sun_azimuth_angle"]),
                    "viewing.zenith":
                    l_ViewingZenithAngle,
                    "viewing.azimuth":
                    l_ViewingAzimuthAngle,
                    "reducelut":
                    hr_lut_file
                }
                OtbAppHandler("ReduceLut", param_hr_lut)
                dict_of_output["hr_lut_" + key] = hr_lut_file
                l_lutmap.add_LUT(l_lut)
        # Write down the lut map
        output = io.StringIO()
        output.write('<?xml version="1.0" ?>\n')
        l_lutmap.export(output,
                        0,
                        name_='LUTMap',
                        namespacedef_='',
                        pretty_print=True)
        l_lutmap_filename = os.path.join(rlc_working, "HR_LutMap.xml")
        with open(l_lutmap_filename, "w") as fh:
            fh.write(output.getvalue().replace("    ", "  "))
            LOGGER.info("Writed new gipp lutmap to " + l_lutmap_filename)
        output.close()
        dict_of_output["hr_lutmap"] = l_lutmap_filename
    def read(self, product_info, app_handler, l2comm, dem, pReadL1Mode):
        """product_info,plugin, l2comm,mode

        :param product_info: L1ImageInformationsBase
        :param pReadL1Mode: ReadL1ModeType
        :return:
        """
        LOGGER.info("Start Muscate L1 ImageFileReader ...")
        product_filename = product_info.HeaderFilename
        LOGGER.info("Start Muscate L1 ImageFileReader with filename : " +
                    product_filename)
        working_dir = app_handler.get_directory_manager(
        ).get_temporary_directory("L1Read_", do_always_remove=True)

        self._plugin.initialize(app_handler)
        self._GIPPL2COMMHandler = l2comm
        LOGGER.info("Start Muscate L1 ImageFileReader ...")
        self._ReadL1Mode = pReadL1Mode
        self._dem = dem
        self._header_handler = product_info.HeaderHandler
        # --------------------------------------
        # Check the extension of th efile. For Muscate, must be .XML (in upper case)
        IsValidSatellite = (self._header_handler is not None)
        if not IsValidSatellite:
            raise MajaExceptionPluginMuscate(
                "The file <{}> is not a valid Muscate L1 product.".format(
                    product_filename))
        # Get satellite name
        self.m_Satellite = product_info.Satellite

        # --------------------------------------
        # Load the header tile file in the xml tile handler to read tile information
        xmlTileFilename = product_info.xmlTileFilename
        l_BandsDefinitions = self._plugin.BandsDefinitions  # BandsDefinitions

        # TOA & masks Reader connection
        l_ListOfTOAImageFileNamesInHeader = self._header_handler.get_list_of_toa_image_filenames(
        )
        l_ListOfTOAImageFileNames = []
        l_ListOfTOABandCode = l_BandsDefinitions.get_list_of_band_code_in_l2_coarse_sorted_by_index(
        )  # ListOfStrings
        for band in l_ListOfTOABandCode:
            LOGGER.debug(band)
            l_ListOfTOAImageFileNames.append(l_ListOfTOAImageFileNamesInHeader[
                self._header_handler.get_index_of_band_code(band)])
        l_ListOfL1Resolution = l_BandsDefinitions.ListOfL1Resolution  # ListOfStrings
        l_ListOfL2Resolution = l_BandsDefinitions.ListOfL2Resolution  # ListOfStrings

        l_L1NoData = product_info.L1NoData
        l_ReflectanceQuantificationValue = product_info.ReflectanceQuantification
        l_RealL1NoData = l_L1NoData * l_ReflectanceQuantificationValue  # RealNoDataType

        # =======> GENERATE TOA
        # Get calibration coeffs if activated
        l_reflectanceMultiplicationValues = []  # ListOfDoubles
        if xml_tools.as_bool(l2comm.get_value("CalAdjustOption")):
            l_factors = xml_tools.as_float_list(
                l2comm.get_value("CalAdjustFactor"))
            if len(l_factors) != len(l_ListOfTOABandCode):
                raise MajaDataException(
                    "Not the same number of Calibration coeffs than L1 bands ( {}, {} )"
                    .format(len(l_factors), len(l_ListOfTOABandCode)))
            for i in range(len(l_ListOfTOABandCode)):
                l_reflectanceMultiplicationValues.append(
                    l_ReflectanceQuantificationValue * l_factors[i])
        else:
            for i in range(len(l_ListOfTOABandCode)):
                l_reflectanceMultiplicationValues.append(
                    l_ReflectanceQuantificationValue)

        l_ProjectionRef = self._dem.ProjRef
        self.generate_toa(l_ListOfTOAImageFileNames,
                          l_reflectanceMultiplicationValues,
                          working_dir)  # string
        if pReadL1Mode == ReadL1Mode.READ_L1_MODE_FOR_ALGORITHMS:
            # --------------------------------------
            # Get information of areas (footprint) of the product (Origin, Spacing and Size for L2 and L2Coarse resolution)
            l_L2Dems = dem.ALTList
            l_CoarseDem = dem.ALC

            # =======> GENERATE TOA SUB IMAGES AT L2 COARSE RESOLUTION
            LOGGER.debug("Start SubSampling ...")
            self.generate_toa_sub_images(working_dir)
            LOGGER.debug("Start SubSampling done.")
            #  the gml mask per L2 resolution per band
            self.generate_mask_rasters(l_ListOfTOABandCode, working_dir)
            # IPEDGSub and L2EDG pipeline connection
            # L2 TOA image pipeline connection
            # =======> GENERATE L2 TOA IMAGES
            self.generate_l2_toa_images(working_dir)
            # =======> GENERATE L1 TOA IMAGES
            self.generate_l1_toa_images(working_dir)
            # =======> GENERATE EDG IMAGES
            self.generate_edg_images(working_dir)
            # IPSAT Sub and L2SAT image pipeline connection
            # =======> GENERATE SAT IMAGES
            self.generate_sat_images(working_dir)
            # CLA image pipeline connection
            # *********************************************************************************************************
            self.generate_cla_image(l_RealL1NoData, working_dir)
            # SOL1 image pipeline connection
            # *********************************************************************************************************
            sol_h1 = self._plugin.ConfigUserCamera.get_Algorithms(
            ).get_GRID_Reference_Altitudes().get_SOLH1()
            LOGGER.debug("sol_H1 : ")
            LOGGER.debug(sol_h1)
            self.generate_sol1_image(sol_h1, working_dir)
            # SOL2 image pipeline connection
            # *********************************************************************************************************
            if self._plugin.GRIDReferenceAltitudesSOL2GridAvailable:
                sol_h2 = self._plugin.ConfigUserCamera.get_Algorithms(
                ).get_GRID_Reference_Altitudes().get_SOLH2()
                self.generate_sol2_image(sol_h2, working_dir)
            # VIE image pipeline connection
            # *********************************************************************************************************
            vie_href = self._plugin.ConfigUserCamera.get_Algorithms(
            ).get_GRID_Reference_Altitudes().get_VIEHRef()
            self.generate_vie_image(vie_href, working_dir)

            # Fill the datas
            self.dict_of_vals["IPEDGSubOutput"] = self._edgsubmask
            self.dict_of_vals["SOL1Image"] = self._sol1image
            self.dict_of_vals["SOL2Image"] = self._sol2image

            if len(self._vieimagelist) > 2:
                l_DTMBandCode = xml_tools.as_string_list(
                    l2comm.get_value("DTMViewingDirectionBandCode"))[0]
                l_DTMBandIdx = self._plugin.BandsDefinitions.get_band_id_in_l2_coarse(
                    l_DTMBandCode)
                LOGGER.info("DTMBandCode= " + l_DTMBandCode)

                self.dict_of_vals["DTMVIEImage"] = self._vieimagelist[
                    l_DTMBandIdx]
            else:
                self.dict_of_vals["DTMVIEImage"] = self._vieimagelist[0]
            self.dict_of_vals["IPTOASubOutput"] = self._sub_toa
            self.dict_of_vals["L2TOAImageList"] = self._l2toaimagelist
            self.dict_of_vals["ViewingZenithMeanMap"] = self._meanZenithMap
            self.dict_of_vals["ViewingAzimuthMeanMap"] = self._meanAzimuthMap
            self.dict_of_vals["CLAImage"] = self._claimage
            self.dict_of_vals["IPSATSubOutput"] = self._subsatimage
            if len(self._vieimagelist) > 2:
                l_CLDBandCode = l2comm.get_value("CLDViewingDirectionBandCode")
                l_CLDBandIdx = self._plugin.BandsDefinitions.get_band_id_in_l2_coarse(
                    l_CLDBandCode)
                self.dict_of_vals["ShadowVIEImage"] = self._vieimagelist[
                    l_CLDBandIdx]
            elif len(self._vieimagelist) > 1:
                self.dict_of_vals["ShadowVIEImage"] = self._vieimagelist[1]
            else:
                self.dict_of_vals["ShadowVIEImage"] = self._vieimagelist[0]
            if self._plugin.CirrusMasking:
                l_CirrusBandCode = l2comm.get_value("CirrusBandCode")
                l_CirrusBandIdx = self._plugin.BandsDefinitions.get_band_id_in_l2_coarse(
                    l_CirrusBandCode)
                self.dict_of_vals["L1TOACirrusImage"] = self._toa_scalar_list[
                    l_CirrusBandIdx]
            self.dict_of_vals["L2EDGOutputList"] = self._l2edgmasklist
            self.dict_of_vals["L2SATImageList"] = self._l2satmasklist
            self.dict_of_vals["L2PIXImageList"] = self._l2dfpimagelist