Ejemplo n.º 1
0
 def __init__(self):
     self.Date = None
     self.Satellite = ""
     self.Acquisition_Date = ""
     self.Validity_Start = ""
     self.Validity_Stop = ""
     self.Nick_Name = ""
     self.Reference_SiteDefinition_Id = ""
     self.Adjacency_Effects_And_Slope_Correction = False
     self.Reflectance_Quantification_Value = ""
     self.Nodata_Value = None
     self.RealL2Nodata_Value = None
     self.VAP_Nodata_Value = None
     self.RealVAP_Nodata_Value = None
     self.VAP_Quantification_Value = None
     self.AOT_Nodata_Value = None
     self.RealAOT_Nodata_Value = None
     self.AOT_Quantification_Value = None
     self.ProjectionRef = ""
     self.List_of_GIPP_Files = []
     self.PluginName = ""
     self.FileClass = ""
     self.LevelType = ""
     self.Prefix = ""
     self.ListOfBandTheoreticalWavelengthOfTheReflectancesComposite = []
     self.ListOfBandTheoreticalWavelengthOfTheLTCComposite = []
     self.STOBandTheoreticalWavelengthIsPresent = False
     self.STOBandTheoreticalWavelengthValue = 0
     self.GlobalProductFilename = None
     self.ProductFilename = ""
     self.STOListOfStringDates = []
     self.L2PrivateImageFilenamesProvider = None
     self.dict_of_vals = {}
     self._coarse_pipeline = OtbPipelineManager()
     self._dem = None
    def __init__(self):
        super(Sentinel2L1ImageFileReaderBase, self).__init__()
        self._toa_scalar_list = []
        self._toa_sub_list = []
        self._l2toaimagelist = []
        self._sol1image = ""
        self._sub_toa = ""
        self._l2satmasklist = []
        self._l2satimagelist = []
        self._subsatimage = ""
        self._l2zonemasklist = []
        self._l2defectmasklist = []
        self._l2edgmasklist = []
        self._l2piximagelist = []
        self._l2dfpimagelist = []
        self._l2zoneimagelist = []
        self._satmasksublist = []
        self._zonemasksublist = []
        self._nodatamasksublist = []
        self._edgsubmask = ""
        self._claimage = ""
        self._vieimagelist = []
        self._meanZenithMap = {}
        self._meanAzimuthMap = {}

        # Store the apps
        self._pipeline = OtbPipelineManager()
        self._subedg_pipeline = OtbPipelineManager()
Ejemplo n.º 3
0
 def __init__(self):
     self.ALTList = []
     self.ALT_Mean = 0
     self.ALT_Min = 0
     self.ALT_Max = 0
     self.ALT_Stdv = 0
     self.ALT_LogicalName = ""
     self.__ASPListInternal = []
     self.ASPList = []
     self.__SLPListInternal = []
     self.SLPList = []
     self.ALC = ""
     self.MSK = ""
     self.ASC = None
     self.__SLCInternal = ""
     self.SLC = ""
     self.Satellite = ""
     self._coeff = 0.01
     self._resList = []
     self._expr = "im1b1 * "
     self.CoarseArea = None
     self.L2Areas = []
     self.ProjRef = ""
     self.ProjCode = ""
     self.ProjType = ""
     self.ProjName = ""
     self.Site = ""
     self._apps = OtbPipelineManager()
 def __init__(self):
     """
     Constructor
     """
     super(MajaMaskResampling, self).__init__()
     self.in_keys_to_check = ["AppHandler", "Plugin", "DEM"]
     self.out_keys_to_check = []
     self.out_keys_provided = ["L2CLDList"]
     self._apps =  OtbPipelineManager()
Ejemplo n.º 5
0
 def __init__(self):
     """
     Constructor
     """
     super(MajaEnvCorr, self).__init__()
     self.in_keys_to_check = ["Params.Caching", "AppHandler", "Plugin", "L1Reader","L2COMM", "DEM",
                              "L2DIRT", "L2DIFT", "L2ALBD", "Params.RealL2NoData"]
     self.out_keys_to_check = ["TOC_sub", "AOT_Sub"]
     self.out_keys_provided = ["SRE_List"]
     self._l2_pipeline = OtbPipelineManager()
Ejemplo n.º 6
0
 def __init__(self):
     """
     Constructor
     """
     super(MajaSlopeCorrection, self).__init__()
     self.in_keys_to_check = [
         "Params.Caching", "AppHandler", "Plugin", "L1Reader", "L2COMM",
         "DEM", "L2DIRT", "L2DIFT", "L1Info"
     ]
     self.out_keys_to_check = ["AOT_Sub"]
     self.out_keys_provided = ["FRE_List", "STL_List", "TGS_List"]
     self._l2_app_pipeline = OtbPipelineManager()
 def __init__(self):
     """
     Constructor
     """
     super(MajaCirrusCorrection, self).__init__()
     self.in_keys_to_check = [
         "Params.Caching", "AppHandler", "Plugin", "L1Reader", "L2COMM",
         "DEM"
     ]
     self.out_keys_to_check = []
     self.out_keys_provided = []
     self._l2_pipeline = OtbPipelineManager()
 def __init__(self):
     """
     Constructor
     """
     super(MajaWaterVaporPostProcessing, self).__init__()
     self.in_keys_to_check = [
         "Params.Caching", "AppHandler", "Plugin", "L1Reader", "L2Reader",
         "L2COMM", "DEM"
     ]
     self.out_keys_to_check = ["RayleighIPTOCR", "dtm_shd", "SunglintFlag"]
     self.out_keys_provided = ["L2VAPList", "L2VAPMaskList"]
     self._l2_pipeline = OtbPipelineManager()
Ejemplo n.º 9
0
 def __init__(self):
     """
     Constructor
     """
     super(MajaScatteringCorrection, self).__init__()
     self._scattering_sub_app = None
     self.in_keys_to_check = [
         "Params.Caching", "AppHandler", "Plugin", "L1Reader", "L2COMM",
         "DEM", "Params.RealL2NoData"
     ]
     self.out_keys_to_check = ["AtmoAbsIPTOAC", "hr_lutmap", "AOT_Sub"]
     self.out_keys_provided = ["TOC_sub"]
     self._l2_pipeline = OtbPipelineManager()
Ejemplo n.º 10
0
 def __init__(self):
     """
     Constructor
     """
     super(MajaAthmosphericAbsorption, self).__init__()
     self._coarse_pipeline = OtbPipelineManager()
     self._l2_pipeline = OtbPipelineManager()
     self.in_keys_to_check = ["Params.WriteL2ProductToL2Resolution", "Params.RealL2NoData",
                              "Params.OzoneAmount",
                              "AppHandler", "Plugin", "L1Reader", "L1Info" ,
                              "L2COMM", "DEM"]
     self.out_keys_to_check = []
     self.out_keys_provided = ["AtmoAbsIPTOAC"]
 def __init__(self):
     super(Sentinel2MuscateL1ImageFileReader, self).__init__()
     self._Satellite = "SENTINEL2"
     self._plugin = MajaSentinel2MuscatePlugin()
     self._toa_pipeline = OtbPipelineManager()
     self._l2_dfp_pipeline = OtbPipelineManager()
     self._l2_sat_pipeline = OtbPipelineManager()
     self._sub_sat_pipeline = OtbPipelineManager()
     self._l2_detf_pipeline = OtbPipelineManager()
     self._l2_zone_pipeline = OtbPipelineManager()
     self._l2_edg_pipeline = OtbPipelineManager()
     self.m_headerHandler = None
     self._band_zone_map = {}
    def __init__(self):
        super(ModuleAOTEstimationComputation, self).__init__()
        self._aot_pipeline = OtbPipelineManager()

        self.in_keys_to_check = [
            "Params.Caching", "Params.WriteL2ProductToL2Resolution",
            "Params.DarkBandIndex_DateD", "Params.DarkBandIndex_DateD",
            "Params.AOTMethod", "Params.InitMode", "Params.MTAOTbandsDateD",
            "AppHandler", "Plugin", "L1Reader", "L2COMM", "DEM", "L2TOCR",
            "L2SITE"
        ]

        self.out_keys_to_check = ["AtmoAbsIPTOAC", "dtm_shd", "cr_lut"]
        self.out_keys_provided = ["AOT_Sub"]
    def generate_toa_sub_images(self, working):
        dtm_coarse = self._dem.ALC

        # For each band of the input product
        tmp_sub_toa_pipe = OtbPipelineManager()
        for i, toa in enumerate(self._toa_scalar_list):
            # undersampling at L2CoarseResolution
            toa_sub_image = os.path.join(working, "aot_sub_{}.tif".format(i))
            app = resample(toa,
                           dtm_coarse,
                           toa_sub_image,
                           OtbResampleType.LINEAR_WITH_RADIUS,
                           write_output=False)
            self._toa_sub_list.append(app.getoutput()["out"])
            tmp_sub_toa_pipe.add_otb_app(app)
        # end band loop

        # *******************************************************************************************************
        # TOA Sub image pipeline connection
        # *******************************************************************************************************
        toa_sub_image = os.path.join(working, "aot_sub.tif")
        param_concatenate = {"il": self._toa_sub_list, "out": toa_sub_image}
        OtbAppHandler("ConcatenateDoubleImages", param_concatenate)
        self._sub_toa = toa_sub_image
        tmp_sub_toa_pipe.free_otb_app()
 def __init__(self):
     """
     Constructor
     """
     super(MajaCloudMaskComputation, self).__init__()
     self.in_keys_to_check = [
         "Params.Caching", "Params.BlueBandIndex_DateD",
         "Params.RedBandIndex_DateD", "Params.NIRBandIndex_DateD",
         "Params.CorrelBandIndex_DateD", "Params.ShadowBandIndex_DateD",
         "Params.ReflectanceWaterBandIndex_DateD", "Params.InitMode",
         "Params.SWIRBandAvailable", "Params.StoListOfDates", "AppHandler",
         "Plugin", "L1Reader", "L2Reader", "L2COMM", "DEM"
     ]
     self.out_keys_to_check = ["SunglintFlag", "RayleighIPTOCR", "CLA_Sub"]
     self.out_keys_provided = [
         "cld_l2cla", "CLDList", constants.CLOUD_MASK_ALL,
         constants.CLOUD_MASK_ALL_CLOUDS, constants.CLOUD_MASK_SHADOWS,
         constants.CLOUD_MASK_SHADVAR, constants.CLOUD_MASK_REFL,
         constants.CLOUD_MASK_REFL_VAR, constants.CLOUD_MASK_EXTENSION,
         constants.CLOUD_MASK_EXTENSION, constants.CLOUD_MASK_ALT,
         constants.CLOUD_MASK_CIRRUS
     ]
     self._apps = OtbPipelineManager()
Ejemplo n.º 15
0
    def test_otb_chain_memory(self):
        """
        Test the initialization of the object
        """
        l_pipeline = OtbPipelineManager()

        out_memory_1 = band_math([QB_1_ORTHO_EXTRACT.get("image_fullpath", None)], "im1b1",
                                 self.working_test_directory, write_output=False)

        l_pipeline.add_otb_app(out_memory_1)
        self.assertEqual(len(l_pipeline.otb_app_coarse_resolution), 1)

        out_memory_2 = band_math([out_memory_1.getoutput().get("out")], "im1b1",
                                 self.working_test_directory, write_output=False)
        l_pipeline.add_otb_app(out_memory_2)
        self.assertEqual(len(l_pipeline.otb_app_coarse_resolution), 2)
        out_memory_3 = band_math([out_memory_2.getoutput().get("out")], "im1b1",
                                 self.working_test_directory, write_output=True)

        l_pipeline.free_otb_app()
        self.assertEqual(len(l_pipeline.otb_app_coarse_resolution), 0)
Ejemplo n.º 16
0
def assign_zenith_and_azimuth_image_to_grid_to_image(input_image_zen, input_value_azi, output_filename):
    """

    :param output_filename:
    :param input_image_zen:
    :param input_value_azi:
    :return:
    """
    band_math_1 = OtbAppHandler("BandMath", {"il": [input_image_zen, input_value_azi],
                                             "exp": "tan(im1b1)*sin(im2b1)"}, write_output=False)

    pipeline = OtbPipelineManager()
    pipeline.add_otb_app(band_math_1)
    band_math_2 = OtbAppHandler("BandMath", {"il": [input_image_zen, input_value_azi],
                                             "exp": "tan(im1b1)*cos(im2b1)"}, write_output=False)
    pipeline.add_otb_app(band_math_2)

    concat = OtbAppHandler("ConcatenateImages", {"il": [band_math_1.getoutput().get(
        "out"), band_math_2.getoutput().get("out")], "out": output_filename}, write_output=True)
    pipeline.add_otb_app(concat)

    return pipeline
class MajaCloudMaskComputation(MajaModule):
    """
    classdocs
    """

    NAME = "CloudMask"

    def __init__(self):
        """
        Constructor
        """
        super(MajaCloudMaskComputation, self).__init__()
        self.in_keys_to_check = [
            "Params.Caching", "Params.BlueBandIndex_DateD",
            "Params.RedBandIndex_DateD", "Params.NIRBandIndex_DateD",
            "Params.CorrelBandIndex_DateD", "Params.ShadowBandIndex_DateD",
            "Params.ReflectanceWaterBandIndex_DateD", "Params.InitMode",
            "Params.SWIRBandAvailable", "Params.StoListOfDates", "AppHandler",
            "Plugin", "L1Reader", "L2Reader", "L2COMM", "DEM"
        ]
        self.out_keys_to_check = ["SunglintFlag", "RayleighIPTOCR", "CLA_Sub"]
        self.out_keys_provided = [
            "cld_l2cla", "CLDList", constants.CLOUD_MASK_ALL,
            constants.CLOUD_MASK_ALL_CLOUDS, constants.CLOUD_MASK_SHADOWS,
            constants.CLOUD_MASK_SHADVAR, constants.CLOUD_MASK_REFL,
            constants.CLOUD_MASK_REFL_VAR, constants.CLOUD_MASK_EXTENSION,
            constants.CLOUD_MASK_EXTENSION, constants.CLOUD_MASK_ALT,
            constants.CLOUD_MASK_CIRRUS
        ]
        self._apps = OtbPipelineManager()

    def cleanup(self):
        self._apps.free_otb_app()

    @staticmethod
    def _dilate_and_mask(input, temp, output, mask, radius, caching):
        param_dilate = {
            "in": input,
            "out": temp + ":uint8",
            "structype": "ball",
            "xradius": radius,
            "yradius": radius,
            "filter": "dilate"
        }
        dilate_app = OtbAppHandler("BinaryMorphologicalOperation",
                                   param_dilate,
                                   write_output=caching)

        param_mask = {
            "il": [dilate_app.getoutput()["out"], mask],
            "out": output + ":uint8",
            "exp": "(im2b1 !=0)?0:im1b1"
        }
        mask_app = OtbAppHandler("BandMath", param_mask, write_output=caching)
        return mask_app

    def run(self, dict_of_input, dict_of_output):
        LOGGER.info("Cloud mask computation start")
        init_Mode = dict_of_input.get("Params").get("InitMode")
        cloud_working = ""
        caching = dict_of_input.get("Params").get("Caching")
        if caching:
            cloud_working = dict_of_input.get(
                "AppHandler").get_directory_manager().get_temporary_directory(
                    "CloudMaskingProc_", do_always_remove=True)
        cloud_reflectance_filename = os.path.join(cloud_working,
                                                  "cloud_refl.tif")
        cloud_reflext_filename = os.path.join(cloud_working,
                                              "cloud_reflext.tif")
        cloud_reflvar_filename = os.path.join(cloud_working,
                                              "cloud_reflvar.tif")
        const_mask_filename = os.path.join(cloud_working,
                                           "cloud_constzero.tif")

        water_treshold = float(
            dict_of_input.get("L2COMM").get_value("WaterReflectanceThreshold"))
        if dict_of_output.get("SunglintFlag"):
            water_treshold = float(
                dict_of_input.get("L2COMM").get_value(
                    "WaterSunglintReflectanceThreshold"))

        bluebandtocr_idx = dict_of_input.get("Params").get(
            "BlueBandIndex_DateD")
        redbandtocr_idx = dict_of_input.get("Params").get("RedBandIndex_DateD")
        nirbandtocr_idx = dict_of_input.get("Params").get("NIRBandIndex_DateD")
        correlbandtocr_idx = dict_of_input.get("Params").get(
            "CorrelBandIndex_DateD")
        shadowbandtocr_idx = dict_of_input.get("Params").get(
            "ShadowBandIndex_DateD")
        reflwaterband_idx = dict_of_input.get("Params").get(
            "ReflectanceWaterBandIndex_DateD")
        bluebandrcr_idx = 999
        redbandrcr_idx = 999
        nirbandrcr_idx = 999
        correlbandrcr_idx = 999
        shadowbandrcr_idx = 999

        # ---------------------------------------------------------------
        # ------------------- Constant zero mask --------------------------
        constant_app = constant_image(dict_of_input.get("DEM").ALC,
                                      0,
                                      const_mask_filename + ":uint8",
                                      write_output=caching)
        constant_mask = constant_app.getoutput()["out"]
        # ---------------------------------------------------------------
        # ------------------- Relfectance app --------------------------
        compute_reflvar = False
        param_reflectance = {
            "tocr":
            dict_of_output.get("RayleighIPTOCR"),
            "edg":
            dict_of_input.get("L1Reader").get_value("IPEDGSubOutput"),
            "sat":
            dict_of_input.get("L1Reader").get_value("IPSATSubOutput"),
            "waterthreshold":
            water_treshold,
            "bluebandtocr":
            bluebandtocr_idx,
            "redbandtocr":
            redbandtocr_idx,
            "nirbandtocr":
            nirbandtocr_idx,
            "correlbandtocr":
            correlbandtocr_idx,
            "bluereflectancethresholdvalue":
            dict_of_input.get("L2COMM").get_value_f(
                "CloudBlueReflectanceThreshold"),
            "redreflectancethresholdvalue":
            dict_of_input.get("L2COMM").get_value_f(
                "CloudRedReflectanceThreshold"),
            "nirredratiomaxthresholdvalue":
            dict_of_input.get("L2COMM").get_value_f("NirRedRatioMaxThreshold"),
            "nirredratiominthresholdvalue":
            dict_of_input.get("L2COMM").get_value_f("NirRedRatioMinThreshold"),
            "nodata":
            dict_of_input.get("Params").get("RealL2NoData"),
            "foregroundvalue":
            1,
            "reflectancewaterband":
            reflwaterband_idx,
            "refl":
            cloud_reflectance_filename + ":uint8"
        }

        if dict_of_input.get("Params").get("InitMode"):
            param_reflectance["initmode"] = dict_of_input.get("Params").get(
                "InitMode")

        if dict_of_input.get("Params").get("SnowBandAvailable"):
            param_reflectance["snow"] = dict_of_output.get("SnowMask")

        if dict_of_input.get("Params").get("SWIRBandAvailable"):
            bands_definition = dict_of_input.get("Plugin").BandsDefinitions
            # Get some datas
            swirbandidx = bands_definition.get_band_id_in_l2_coarse(
                dict_of_input.get("L2COMM").get_value("SWIR1BandCode"))
            param_reflectance["swir.bandtocr"] = swirbandidx
            param_reflectance["swir.nirswirratiomin"] = dict_of_input.get(
                "L2COMM").get_value_f("NirSwirRatioMinThreshold")

        if not init_Mode:
            compute_reflvar = True
            bluebandrcr_idx = dict_of_input.get("Params").get(
                "BlueBandIndex_DateDm1")
            redbandrcr_idx = dict_of_input.get("Params").get(
                "RedBandIndex_DateDm1")
            nirbandrcr_idx = dict_of_input.get("Params").get(
                "NIRBandIndex_DateDm1")
            correlbandrcr_idx = dict_of_input.get("Params").get(
                "CorrelBandIndex_DateDm1")
            shadowbandrcr_idx = dict_of_input.get("Params").get(
                "ShadowBandIndex_DateDm1")
            param_reflectance_nominal = {
                "l2was":
                dict_of_input.get("L2Reader").get_value("WASImage"),
                "l2rcr":
                dict_of_input.get("L2Reader").get_value("RCRImage"),
                "l2sto":
                dict_of_input.get("L2Reader").get_value("STOImage"),
                "l2pxd":
                dict_of_input.get("L2Reader").get_value("PXDImage"),
                "l2ndt":
                dict_of_input.get("L2Reader").get_value("NDTImage"),
                "nominal.seradius":
                dict_of_input.get("L2COMM").get_value_i("SEInputMasksRadius"),
                "nominal.bluebandrcr":
                bluebandrcr_idx,
                "nominal.redbandrcr":
                redbandrcr_idx,
                "nominal.nirbandrcr":
                nirbandrcr_idx,
                "nominal.correlbandrcr":
                correlbandrcr_idx,
                "nominal.jday":
                dict_of_input.get("Params").get("JDay"),
                "nominal.cloudforgettingduration":
                dict_of_input.get("L2COMM").get_value_i(
                    "CloudForgettingDuration"),
                "nominal.minvarthreshold":
                dict_of_input.get("L2COMM").get_value_f("MinThresholdVarBlue"),
                "nominal.maxvarthreshold":
                dict_of_input.get("L2COMM").get_value_f("MaxThresholdVarBlue"),
                "nominal.knirblue":
                dict_of_input.get("L2COMM").get_value_f("KNIRBlue"),
                "nominal.kredblue":
                dict_of_input.get("L2COMM").get_value_f("KRedBlue"),
                "nominal.deltathreshold":
                dict_of_input.get("L2COMM").get_value_f("DeltaThreshold"),
                "nominal.minpixelcorrelation":
                dict_of_input.get("L2COMM").get_value_f("MinPixelCorrel"),
                "nominal.correlthreshold":
                float(
                    dict_of_input.get("L2COMM").get_value_f("CorrelThreshold"))
                / 100.0,
                "nominal.ncorrel":
                dict_of_input.get("L2COMM").get_value_f("NCorrel"),
                "nominal.stolistofdates":
                dict_of_input.get("Params").get("StoListOfDates"),
                "reflvar":
                cloud_reflvar_filename + ":uint8",
                "reflext":
                cloud_reflext_filename + ":uint8"
            }
            param_reflectance.update(param_reflectance_nominal)

        # Launch the app
        reflectance_app = OtbAppHandler("CloudReflectance",
                                        param_reflectance,
                                        write_output=caching)
        self._apps.add_otb_app(reflectance_app)
        cloud_reflectance_image = reflectance_app.getoutput()["refl"]
        cloud_reflext_image = reflectance_app.getoutput()["reflext"]
        if not init_Mode:
            cloud_reflectvar_image = reflectance_app.getoutput()["reflvar"]
        else:
            cloud_reflectvar_image = constant_mask
        # ------------------- Relfectance app ---------------------------
        # ---------------------------------------------------------------

        # ---------------------------------------------------------------
        # ------------------- Snow app ---------------------------------
        tmp_reflectance_image = os.path.join(cloud_working,
                                             "cloud_refl_snow.tif")
        if dict_of_input.get("Params").get("SnowBandAvailable"):
            tmp_snow_mask = os.path.join(cloud_working, "cloud_snow_mask.tif")
            param_snow = {
                "snowin":
                dict_of_output.get("SnowMask"),
                "edg":
                dict_of_input.get("L1Reader").get_value("IPEDGSubOutput"),
                "cldrefl":
                cloud_reflectance_image,
                "seradius":
                dict_of_input.get("L2COMM").get_value_i("SECloudRadius"),
                "refl":
                tmp_reflectance_image + ":uint8",
                "cldreflvar":
                cloud_reflectvar_image,
                "snow":
                tmp_snow_mask + ":uint8"
            }
            snow_app = OtbAppHandler("CloudSnowCorrection",
                                     param_snow,
                                     write_output=caching)
            self._apps.add_otb_app(snow_app)
            cloud_reflectance_image = snow_app.getoutput()["refl"]
            dict_of_output["cld_snow"] = snow_app.getoutput()["snow"]

        # ------------------- Snow app ---------------------------------
        # --------------------------------------------------------------

        # ---------------------------------------------------------------
        # ------------------- Extension app ---------------------------------
        compute_extension = False
        cloud_extension_filename = os.path.join(cloud_working,
                                                "cloud_extension.tif")
        if not init_Mode and compute_reflvar:
            compute_extension = True
            param_extension = {
                "tocr":
                dict_of_output.get("RayleighIPTOCR"),
                "edg":
                dict_of_input.get("L1Reader").get_value("IPEDGSubOutput"),
                "cldext":
                cloud_reflext_image,
                "cldrefl":
                cloud_reflectance_image,
                "cldreflvar":
                cloud_reflectvar_image,
                "l2rcr":
                dict_of_input.get("L2Reader").get_value("RCRImage"),
                "l2sto":
                dict_of_input.get("L2Reader").get_value("STOImage"),
                "l2ndt":
                dict_of_input.get("L2Reader").get_value("NDTImage"),
                "nodata":
                dict_of_input.get("Params").get("RealL2NoData"),
                "correlbandtocr":
                correlbandtocr_idx,
                "correlbandrcr":
                correlbandrcr_idx,
                "jday":
                dict_of_input.get("Params").get("JDay"),
                "minpixelcorrelation":
                dict_of_input.get("L2COMM").get_value_f("MinPixelCorrel"),
                "correlthreshold":
                float(
                    dict_of_input.get("L2COMM").get_value_f("CorrelThreshold"))
                / 100.0,
                "ncorrel":
                dict_of_input.get("L2COMM").get_value_f("NCorrel"),
                "discardedratiomin":
                float(
                    dict_of_input.get("L2COMM").get_value_f(
                        "DiscardedPixelsRatioMin")) / 100.0,
                "stolistofdates":
                dict_of_input.get("Params").get("StoListOfDates"),
                "ext":
                cloud_extension_filename + ":uint8"
            }
            extension_app = OtbAppHandler("CloudExtension",
                                          param_extension,
                                          write_output=caching)
            self._apps.add_otb_app(extension_app)
            cloud_extension_image = extension_app.getoutput()["ext"]
        else:
            cloud_extension_image = constant_mask

        # ------------------- Extension app ---------------------------------
        # ---------------------------------------------------------------

        # ---------------------------------------------------------------
        # ------------------- Cld all concatenate------------------------
        cloud_allnoext_filename = os.path.join(cloud_working,
                                               "cloud_all_noextension.tif")
        cloud_all_filename = cloud_allnoext_filename
        param_allnoext = {}
        if dict_of_input.get("Params").get("CirrusBandAvailable"):
            param_allnoext = {
                "il": [
                    cloud_reflectance_image, cloud_reflectvar_image,
                    dict_of_output.get("CLA_Sub"),
                    dict_of_output.get("CirrusMask")
                ],
                "exp":
                "(im1b1 !=0) || (im2b1!=0) || (im3b1 !=0) || (im4b1 !=0)",
                "out":
                cloud_allnoext_filename + ":uint8"
            }
        else:
            param_allnoext = {
                "il": [
                    cloud_reflectance_image, cloud_reflectvar_image,
                    dict_of_output.get("CLA_Sub")
                ],
                "exp":
                "(im1b1 !=0) || (im2b1!=0) || (im3b1 !=0)",
                "out":
                cloud_allnoext_filename + ":uint8"
            }
        allnoext_app = OtbAppHandler("BandMath",
                                     param_allnoext,
                                     write_output=caching)
        self._apps.add_otb_app(allnoext_app)
        cloud_allnoext_image = allnoext_app.getoutput()["out"]
        cloud_all_image = allnoext_app.getoutput()["out"]
        if not init_Mode:
            cloud_all_filename = os.path.join(cloud_working, "cloud_all.tif")
            param_all = {
                "il": [cloud_allnoext_image, cloud_extension_image],
                "exp": "(im1b1 !=0) || (im2b1!=0)",
                "out": cloud_all_filename + ":uint8"
            }
            all_app = OtbAppHandler("BandMath",
                                    param_all,
                                    write_output=caching)
            self._apps.add_otb_app(all_app)
            cloud_all_image = all_app.getoutput()["out"]
        # ------------------- Cld all concatenate------------------------
        # ---------------------------------------------------------------

        # ---------------------------------------------------------------
        # ------------------- Cld shadow ------------------------
        #caching of ShadowVIE that is know for causing troubles
        shadowvie_filename = os.path.join(cloud_working, "shadow_vie.tif")
        otb_copy_image_to_file(
            dict_of_input.get("L1Reader").get_value("ShadowVIEImage"),
            shadowvie_filename)

        cloud_shadow_filename = os.path.join(cloud_working, "cloud_shadow.tif")
        cloud_cla_filename = os.path.join(cloud_working, "cloud_cla.tif")
        grid_ref_alt = dict_of_input.get(
            "Plugin").ConfigUserCamera.get_Algorithms(
            ).get_GRID_Reference_Altitudes()
        param_shadow = {
            "tocr":
            dict_of_output.get("RayleighIPTOCR"),
            "edg":
            dict_of_input.get("L1Reader").get_value("IPEDGSubOutput"),
            "cldall":
            cloud_allnoext_image,
            "cla":
            dict_of_output.get("CLA_Sub"),
            "vie":
            shadowvie_filename,
            "dtm":
            dict_of_input.get("DEM").ALC,
            "sol1.in":
            dict_of_input.get("L1Reader").get_value("SOL1Image"),
            "sol1.h":
            grid_ref_alt.get_SOLH1(),
            "solhref":
            grid_ref_alt.get_SOLHRef(),
            "defaultalt":
            dict_of_input.get("L2COMM").get_value_i("DefaultAltitude"),
            "deltahmax":
            dict_of_input.get("L2COMM").get_value_i("DeltaHMax"),
            "deltahmin":
            dict_of_input.get("L2COMM").get_value_i("DeltaHMin"),
            "deltahstep":
            dict_of_input.get("L2COMM").get_value_i("DeltaHStep"),
            "shadbandtocr":
            shadowbandtocr_idx,
            "shadbandrcr":
            shadowbandrcr_idx,
            "ksigma":
            0,
            "viehref":
            grid_ref_alt.get_VIEHRef(),
            "nodata":
            dict_of_input.get("Params").get("RealL2NoData"),
            "shadow":
            cloud_shadow_filename + ":uint8"
        }

        if dict_of_input.get("Params").get("InitMode"):
            param_shadow["initmode"] = dict_of_input.get("Params").get(
                "InitMode")

        # With alt shadows
        if dict_of_input.get("Params").get("CloudMaskingKnownCloudsAltitude"):
            param_shadow["algo"] = "withalt"
            param_shadow["ksigma"] = int(
                dict_of_input.get("L2COMM").get_value("KsigmaAltitude"))
            param_shadow["l2cla"] = cloud_cla_filename + ":int16"
            param_shadow["algo.withalt.absnbpixthresh"] = dict_of_input.get(
                "L2COMM").get_value_f("AbsNbpixThreshold")
            param_shadow["algo.withalt.refinement"] = dict_of_input.get(
                "L2COMM").get_value("RefinementOption")
            param_shadow["algo.withalt.threshdiffim"] = dict_of_input.get(
                "L2COMM").get_value_f("ThresholdDiffImage")
            if dict_of_input.get(
                    "Plugin").GRIDReferenceAltitudesSOL2GridAvailable:
                param_shadow["algo.withalt.sol2.in"] = dict_of_input.get(
                    "L1Reader").get_value("SOL2Image")
                param_shadow["algo.withalt.sol2.h"] = grid_ref_alt.get_SOLH2()

        else:
            param_shadow["algo"] = "withoutalt"
            param_shadow["algo.withoutalt.cloudcovermult"] = dict_of_input.get(
                "L2COMM").get_value_f("CloudCoverMultFactor")
            param_shadow["algo.withoutalt.shadratiomax"] = dict_of_input.get(
                "L2COMM").get_value_f("ShadowCloudRatioMax")
            param_shadow["algo.withoutalt.shadratiomin"] = dict_of_input.get(
                "L2COMM").get_value_f("ShadowCloudRatioMin")
            param_shadow["algo.withoutalt.shadratiopixnb"] = dict_of_input.get(
                "L2COMM").get_value_i("ShadowCloudRatioPixNb")
            param_shadow["algo.withoutalt.maxdarkening"] = dict_of_input.get(
                "L2COMM").get_value_f("ProjShadDarkeningMax")
            param_shadow["algo.withoutalt.minpercentile"] = float(
                dict_of_input.get("L2COMM").get_value_f(
                    "DarkeningMinPercentile")) / 100.0
            param_shadow["algo.withoutalt.seradius"] = dict_of_input.get(
                "L2COMM").get_value_i("SECloudRadius")
            dict_of_output["cld_l2cla"] = None

        if not init_Mode:
            param_shadow["l2was"] = dict_of_input.get("L2Reader").get_value(
                "WASImage")
            param_shadow["l2rcr"] = dict_of_input.get("L2Reader").get_value(
                "RCRImage")
            param_shadow["l2ndt"] = dict_of_input.get("L2Reader").get_value(
                "NDTImage")

        shadow_app = OtbAppHandler("CloudShadow",
                                   param_shadow,
                                   write_output=caching)
        self._apps.add_otb_app(shadow_app)
        cloud_shadow_image = shadow_app.getoutput()["shadow"]
        if dict_of_input.get("Params").get("CloudMaskingKnownCloudsAltitude"):
            dict_of_output["cld_l2cla"] = shadow_app.getoutput()["l2cla"]

        # ------------------- Cld shadow ------------------------
        # -------------------------------------------------------

        # -------------------------------------------------------
        # ------------------- Cld shadvar ------------------------
        compute_shadvar = False
        cloud_shadvar_filename = os.path.join(cloud_working,
                                              "cloud_shadvar.tif")
        if not init_Mode:
            param_shadcount = {"im": cloud_shadow_image, "exclude": 1}
            shadcount_app = OtbAppHandler("Stats", param_shadcount)
            if shadcount_app.getoutput()["excludedcount"] > 0:
                compute_shadvar = True
                param_shadvar = {
                    "tocr":
                    dict_of_output.get("RayleighIPTOCR"),
                    "edg":
                    dict_of_input.get("L1Reader").get_value("IPEDGSubOutput"),
                    "cldall":
                    cloud_allnoext_image,
                    "cldshad":
                    cloud_shadow_image,
                    "vie":
                    dict_of_input.get("L1Reader").get_value("ShadowVIEImage"),
                    "dtm":
                    dict_of_input.get("DEM").ALC,
                    "sol":
                    dict_of_input.get("L1Reader").get_value("SOL1Image"),
                    "l2rcr":
                    dict_of_input.get("L2Reader").get_value("RCRImage"),
                    "l2was":
                    dict_of_input.get("L2Reader").get_value("WASImage"),
                    "l2ndt":
                    dict_of_input.get("L2Reader").get_value("NDTImage"),
                    "l2shad":
                    dict_of_input.get("L2Reader").get_value(
                        "VectorizedCLDSubOutput")[
                            constants.CLOUD_MASK_SHADOWS],
                    "l2shadvar":
                    dict_of_input.get("L2Reader").get_value(
                        "VectorizedCLDSubOutput")[
                            constants.CLOUD_MASK_SHADVAR],
                    "l2sto":
                    dict_of_input.get("L2Reader").get_value("STOImage"),
                    "shadbandtocr":
                    shadowbandtocr_idx,
                    "shadbandrcr":
                    shadowbandrcr_idx,
                    "viehref":
                    grid_ref_alt.get_VIEHRef(),
                    "solhref":
                    grid_ref_alt.get_SOLH1(),
                    "nodata":
                    dict_of_input.get("Params").get("RealL2NoData"),
                    "maxdarkening":
                    dict_of_input.get("L2COMM").get_value_f(
                        "ShadVarDarkeningMax"),
                    "minpercentile":
                    float(
                        dict_of_input.get("L2COMM").get_value_f(
                            "ShadVarPercentile")) / 100.0,
                    "maxcla":
                    dict_of_input.get("L2COMM").get_value_f(
                        "MaxCloudAltitude"),
                    "compositelabelratio":
                    dict_of_input.get("L2COMM").get_value_f(
                        "ShadVarCompositeLabelRatio"),
                    "minpixelcorrelation":
                    dict_of_input.get("L2COMM").get_value_f("MinPixelCorrel"),
                    "correlthreshold":
                    float(
                        dict_of_input.get("L2COMM").get_value_f(
                            "CorrelThreshold")) / 100.0,
                    "ncorrel":
                    dict_of_input.get("L2COMM").get_value_f("NCorrel"),
                    "stolistofdates":
                    dict_of_input.get("Params").get("StoListOfDates"),
                    "jday":
                    dict_of_input.get("Params").get("JDay"),
                    "shadvar":
                    cloud_shadvar_filename + ":uint8"
                }

                shadvar_app = OtbAppHandler("CloudShadVar",
                                            param_shadvar,
                                            write_output=caching)
                self._apps.add_otb_app(shadvar_app)
                cloud_shadvar_image = shadvar_app.getoutput()["shadvar"]

        if not compute_shadvar:
            cloud_shadvar_image = constant_mask
        # ------------------- Cld shadvar ------------------------
        # -------------------------------------------------------

        # -------------------------------------------------------
        # ------------------- Cld Sum build ---------------------
        cloud_sum_filename = os.path.join(cloud_working, "cloud_sum.tif")
        param_sum = {}
        if not compute_shadvar:
            param_sum = {
                "il": [cloud_all_image, cloud_shadow_image],
                "exp": "(im1b1 !=0) || (im2b1!=0)",
                "out": cloud_sum_filename + ":uint8"
            }
        else:
            param_sum = {
                "il":
                [cloud_all_image, cloud_shadow_image, cloud_shadvar_image],
                "exp": "(im1b1 !=0) || (im2b1!=0) || (im3b1!=0)",
                "out": cloud_sum_filename + ":uint8"
            }
        sum_app = OtbAppHandler("BandMath", param_sum, write_output=caching)
        self._apps.add_otb_app(sum_app)
        cloud_sum_image = sum_app.getoutput()["out"]
        # ------------------- Cld Sum build ---------------------
        # -------------------------------------------------------

        # -------------------------------------------------------
        # ------------------- Cld dilate masks ---------------------

        caching_dilate = True
        if caching_dilate:
            cloud_working = dict_of_input.get(
                "AppHandler").get_directory_manager().get_temporary_directory(
                    "CloudMaskingProc_", do_always_remove=True)
        cloud_reflectance_dilated_filename = os.path.join(
            cloud_working, "cloud_refl_dilated.tif")
        cloud_reflvar_dilated_filename = os.path.join(
            cloud_working, "cloud_reflvar_dilated.tif")
        cloud_extension_dilated_filename = os.path.join(
            cloud_working, "cloud_extension_dilated.tif")
        cloud_all_dilated_filename = os.path.join(cloud_working,
                                                  "cloud_all_dilated.tif")
        cloud_shadow_dilated_filename = os.path.join(
            cloud_working, "cloud_shadow_dilated.tif")
        cloud_shadvar_dilated_filename = os.path.join(
            cloud_working, "cloud_shadvar_dilated.tif")
        cloud_sum_dilated_filename = os.path.join(cloud_working,
                                                  "cloud_sum_dilated.tif")
        cloud_alt_dilated_filename = os.path.join(cloud_working,
                                                  "cloud_alt_dilated.tif")
        cloud_cirrus_dilated_filename = os.path.join(
            cloud_working, "cloud_cirrus_dilated.tif")
        cloud_reflectance_dilated_masked_filename = os.path.join(
            cloud_working, "cloud_refl_dilated_masked.tif")
        cloud_reflvar_dilated_masked_filename = os.path.join(
            cloud_working, "cloud_reflvar_dilated_masked.tif")
        cloud_extension_dilated_masked_filename = os.path.join(
            cloud_working, "cloud_extension_dilated_masked.tif")
        cloud_all_dilated_masked_filename = os.path.join(
            cloud_working, "cloud_all_dilated_masked.tif")
        cloud_shadow_dilated_masked_filename = os.path.join(
            cloud_working, "cloud_shadow_dilated_masked.tif")
        cloud_shadvar_dilated_masked_filename = os.path.join(
            cloud_working, "cloud_shadvar_dilated_masked.tif")
        cloud_sum_dilated_masked_filename = os.path.join(
            cloud_working, "cloud_sum_dilated_masked.tif")
        cloud_alt_dilated_masked_filename = os.path.join(
            cloud_working, "cloud_alt_dilated_masked.tif")
        cloud_cirrus_dilated_masked_filename = os.path.join(
            cloud_working, "cloud_cirrus_dilated_masked.tif")
        mask = dict_of_input.get("L1Reader").get_value("IPEDGSubOutput")
        radius = dict_of_input.get("L2COMM").get_value_i("SECloudRadius")
        cloud_reflectance_dilated_masked_app = MajaCloudMaskComputation._dilate_and_mask(
            cloud_reflectance_image, cloud_reflectance_dilated_filename,
            cloud_reflectance_dilated_masked_filename, mask, radius,
            caching_dilate)
        cloud_reflectance_dilated_masked_image = cloud_reflectance_dilated_masked_app.getoutput(
        )["out"]
        self._apps.add_otb_app(cloud_reflectance_dilated_masked_app)
        if compute_reflvar:
            cloud_reflvar_dilated_masked_app = MajaCloudMaskComputation._dilate_and_mask(
                cloud_reflectvar_image, cloud_reflvar_dilated_filename,
                cloud_reflvar_dilated_masked_filename, mask, radius,
                caching_dilate)
            cloud_reflvar_dilated_masked_image = cloud_reflvar_dilated_masked_app.getoutput(
            )["out"]
            self._apps.add_otb_app(cloud_reflvar_dilated_masked_app)
        if compute_extension:
            cloud_extension_dilated_masked_app = MajaCloudMaskComputation._dilate_and_mask(
                cloud_extension_image, cloud_extension_dilated_filename,
                cloud_extension_dilated_masked_filename, mask, radius,
                caching_dilate)
            cloud_extension_dilated_masked_image = cloud_extension_dilated_masked_app.getoutput(
            )["out"]
            self._apps.add_otb_app(cloud_extension_dilated_masked_app)
        cloud_all_dilated_masked_app = MajaCloudMaskComputation._dilate_and_mask(
            cloud_all_image, cloud_all_dilated_filename,
            cloud_all_dilated_masked_filename, mask, radius, caching_dilate)
        cloud_all_dilated_masked_image = cloud_all_dilated_masked_app.getoutput(
        )["out"]
        self._apps.add_otb_app(cloud_all_dilated_masked_app)
        cloud_shadow_dilated_masked_app = MajaCloudMaskComputation._dilate_and_mask(
            cloud_shadow_image, cloud_shadow_dilated_filename,
            cloud_shadow_dilated_masked_filename, mask, radius, caching_dilate)
        cloud_shadow_dilated_masked_image = cloud_shadow_dilated_masked_app.getoutput(
        )["out"]
        self._apps.add_otb_app(cloud_shadow_dilated_masked_app)
        if compute_shadvar:
            cloud_shadvar_dilated_masked_app = MajaCloudMaskComputation._dilate_and_mask(
                cloud_shadvar_image, cloud_shadvar_dilated_filename,
                cloud_shadvar_dilated_masked_filename, mask, radius,
                caching_dilate)
            cloud_shadvar_dilated_masked_image = cloud_shadvar_dilated_masked_app.getoutput(
            )["out"]
            self._apps.add_otb_app(cloud_shadvar_dilated_masked_app)
        cloud_sum_dilated_masked_app = MajaCloudMaskComputation._dilate_and_mask(
            cloud_sum_image, cloud_sum_dilated_filename,
            cloud_sum_dilated_masked_filename, mask, radius, caching_dilate)
        cloud_sum_dilated_masked_image = cloud_sum_dilated_masked_app.getoutput(
        )["out"]
        self._apps.add_otb_app(cloud_sum_dilated_masked_app)
        cloud_alt_dilated_masked_app = MajaCloudMaskComputation._dilate_and_mask(
            dict_of_output.get("CLALT_Sub"), cloud_alt_dilated_filename,
            cloud_alt_dilated_masked_filename, mask, radius, caching_dilate)
        cloud_alt_dilated_masked_image = cloud_alt_dilated_masked_app.getoutput(
        )["out"]
        self._apps.add_otb_app(cloud_alt_dilated_masked_app)
        if dict_of_input.get("Params").get("CirrusBandAvailable"):
            cloud_cirrus_dilated_masked_app = MajaCloudMaskComputation._dilate_and_mask(
                dict_of_output.get("CirrusMask"),
                cloud_cirrus_dilated_filename,
                cloud_cirrus_dilated_masked_filename, mask, radius,
                caching_dilate)
            cloud_cirrus_dilated_masked_image = cloud_cirrus_dilated_masked_app.getoutput(
            )["out"]
            self._apps.add_otb_app(cloud_cirrus_dilated_masked_app)
        else:
            cloud_cirrus_dilated_masked_image = constant_mask

        # ------------------- Cld dilate masks ---------------------
        # -------------------------------------------------------

        # -------------------------------------------------------
        # ------------------- Register outputs ------------------
        # Concatenation to generate a vector image of the cloud masks
        # Concatenation of all Mono band images to the vector image
        # *************************************************************************************************
        # *************************************************************************************************
        # ATTENTION : The order of the PushBack define the order of the data in the L2 Product
        #             For ChecktoolProcessorQuickLookL2::Launch method, we use index of these bands
        # *************************************************************************************************
        # *************************************************************************************************
        # AVANT MEMORY IN CHAIN CORE ALGORITHMS - DEPRECATED
        #                    Bit 1 - Cloud_Mask.all : summary Logical or of All cloud, extension and shadow masks
        #                    Bit 2 - Cloud_Mask.all clouds: Logical or of All cloud masks and extension
        #                    Bit 3 - Cloud_Mask.refl : reflectance threshold
        #                    Bit 4 - Cloud_Mask.refl_var : reflectance variation threshold
        #                    Bit 5 - Cloud_Mask.extension : extension of the cloud mask
        #                    Bit 6 - Cloud_Mask.alt : stereoscopic mask  =>  VENUS et vide pour les autres
        #                    Bit 7 - Cloud_Mask.shadows : shadows mask from clouds within image
        #                    Bit 8 - Cloud_Mask.shadvar: shadows mask from clouds outside image bit 1 : Cloud_Mask.all
        #                    Bit 9 - Cirrus => L8 et S2

        # APRES MEMORY IN CHAIN CORE ALGORITHMS : V 4-1-0
        #                    Bit 1 - Cloud_Mask.all : summary Logical or of All cloud, extension and shadow masks
        #                    Bit 2 - Cloud_Mask.all clouds: Logical or of All cloud masks and extension
        #                    Bit 3 - Cloud_Mask.shadows : shadows mask from clouds within image
        #                    Bit 4 - Cloud_Mask.shadvar: shadows mask from clouds outside image bit 1 : Cloud_Mask.all
        #                    Bit 5 - Cloud_Mask.refl : reflectance threshold
        #                    Bit 6 - Cloud_Mask.refl_var : reflectance variation threshold
        #                    Bit 7 - Cloud_Mask.extension : extension of the cloud mask
        #                    Bit 8 - Cloud_Mask.alt : stereoscopic mask  =>  VENUS et vide pour les autres
        #                    Bit 9 - Cirrus : Pour  L8 et S2 et vide pour les autres

        # FORMAT DISK
        #                    Bit 1 - Cloud_Mask.all : summary Logical or of All cloud and shadow masks
        #                    Bit 2 - Cloud_Mask.all clouds: Logical or of All cloud masks
        #                    Bit 3 - Cloud_Mask.shadows : shadows mask from clouds within image
        #                    Bit 4 - Cloud_Mask.shadvar: shadows mask from clouds outside image bit 1 : Cloud_Mask.all
        #                    Bit 5 - Cloud_Mask.refl : reflectance threshold
        #                    Bit 6 - Cloud_Mask.refl_var : reflectance variation threshold
        #                    Bit 7 - Cloud_Mask.extension : extension of the cloud mask
        #                    Bit 8 - VENUS : Cloud_Mask.alt : stereoscopic mask
        #                    Bit 8 - L8 et S2 : Bit 9 - Cirrus
        #                    Bit 8 - Vide pour les autres
        cld_list = []

        dict_of_output[
            constants.CLOUD_MASK_ALL] = cloud_sum_dilated_masked_image
        cld_list.append(dict_of_output[constants.CLOUD_MASK_ALL])
        dict_of_output[
            constants.CLOUD_MASK_ALL_CLOUDS] = cloud_all_dilated_masked_image
        cld_list.append(dict_of_output[constants.CLOUD_MASK_ALL_CLOUDS])
        dict_of_output[
            constants.CLOUD_MASK_SHADOWS] = cloud_shadow_dilated_masked_image
        cld_list.append(dict_of_output[constants.CLOUD_MASK_SHADOWS])
        if compute_shadvar:
            dict_of_output[
                constants.
                CLOUD_MASK_SHADVAR] = cloud_shadvar_dilated_masked_image
        else:
            dict_of_output[constants.CLOUD_MASK_SHADVAR] = cloud_shadvar_image
        cld_list.append(dict_of_output[constants.CLOUD_MASK_SHADVAR])
        dict_of_output[
            constants.CLOUD_MASK_REFL] = cloud_reflectance_dilated_masked_image
        cld_list.append(dict_of_output[constants.CLOUD_MASK_REFL])
        if compute_reflvar:
            dict_of_output[
                constants.
                CLOUD_MASK_REFL_VAR] = cloud_reflvar_dilated_masked_image
        else:
            dict_of_output[
                constants.CLOUD_MASK_REFL_VAR] = cloud_reflectvar_image
        cld_list.append(dict_of_output[constants.CLOUD_MASK_REFL_VAR])
        if compute_extension:
            dict_of_output[
                constants.
                CLOUD_MASK_EXTENSION] = cloud_extension_dilated_masked_image
        else:
            dict_of_output[
                constants.CLOUD_MASK_EXTENSION] = cloud_extension_image
        cld_list.append(dict_of_output[constants.CLOUD_MASK_EXTENSION])
        dict_of_output[
            constants.CLOUD_MASK_ALT] = cloud_alt_dilated_masked_image
        cld_list.append(dict_of_output[constants.CLOUD_MASK_ALT])
        dict_of_output[
            constants.CLOUD_MASK_CIRRUS] = cloud_cirrus_dilated_masked_image
        cld_list.append(dict_of_output[constants.CLOUD_MASK_CIRRUS])

        dict_of_output["CLDList"] = cld_list

        LOGGER.debug(cld_list)
Ejemplo n.º 18
0
class MajaAthmosphericAbsorption(MajaModule):

    """
    classdocs

    """
    NAME = "AthmosphericAbsorption"

    def __init__(self):
        """
        Constructor
        """
        super(MajaAthmosphericAbsorption, self).__init__()
        self._coarse_pipeline = OtbPipelineManager()
        self._l2_pipeline = OtbPipelineManager()
        self.in_keys_to_check = ["Params.WriteL2ProductToL2Resolution", "Params.RealL2NoData",
                                 "Params.OzoneAmount",
                                 "AppHandler", "Plugin", "L1Reader", "L1Info" ,
                                 "L2COMM", "DEM"]
        self.out_keys_to_check = []
        self.out_keys_provided = ["AtmoAbsIPTOAC"]

    def run(self, dict_of_input, dict_of_output):
        LOGGER.info("AthmosphericAbsorption start")
        atm_working = dict_of_input.get("AppHandler").get_directory_manager().get_temporary_directory("AtmoProc_",
                                            do_always_remove=True)
        l_writeL2 = dict_of_input.get("Params").get("WriteL2ProductToL2Resolution")
        bands_definition = dict_of_input.get("Plugin").BandsDefinitions
        # Get some datas

        pressure_image_sub = os.path.join(atm_working, "atmo_pressure_sub.tif")
        param_pressure = {"dtm": dict_of_input.get("DEM").ALC,
                          "pressure": pressure_image_sub}
        pressure_app_sub = OtbAppHandler("PressureFilter", param_pressure,
                                         write_output=True)
        self._coarse_pipeline.add_otb_app(pressure_app_sub)
        viewing_zenith = dict_of_input.get("L1Info").ListOfViewingZenithAnglesPerBandAtL2CoarseResolution
        water_amount_image_sub = os.path.join(atm_working, "atmo_wateramount_sub.tif")
        if dict_of_input.get("Plugin").WaterVapourDetermination and not as_bool(
           dict_of_input.get("L2COMM").get_value("GIP_L2COMM_UseDefaultConstantWaterAmount")):
            watervaporreferencebandid = bands_definition.get_band_id_in_l2_coarse(
                dict_of_input.get("L2COMM").get_value("WaterVaporReferenceBandCode"))
            watervaporbandid = bands_definition.get_band_id_in_l2_coarse(
                dict_of_input.get("L2COMM").get_value("WaterVaporBandCode"))

            viewing_zenith_vapor_band = float(viewing_zenith[watervaporbandid])
            param_watervapour = {"toa": dict_of_input.get("L1Reader").get_value("IPTOASubOutput"),
                                 "watervaporreferencebandid": watervaporreferencebandid,
                                 "watervaporbandid": watervaporbandid,
                                 "vapnodatavalue": float(dict_of_input.get("L2COMM").get_value("VAPNodataValue")),
                                 "watervapormaxthreshold": float(
                                     dict_of_input.get("L2COMM").get_value("WaterVaporMaxThreshold")),
                                 "solarzenith": float(dict_of_input.get("L1Info").SolarAngle["sun_zenith_angle"]),
                                 "viewingzenith": viewing_zenith_vapor_band,
                                 "wateramount": water_amount_image_sub,
                                 "gipwatv": dict_of_input.get("L2WATV").new_gipp_filename}
            water_vapour_app_sub = OtbAppHandler("WaterAmountGeneratorFilter", param_watervapour,
                                                 write_output=False)
            self._coarse_pipeline.add_otb_app(water_vapour_app_sub)
            dict_of_output["VAP_Sub"] = water_vapour_app_sub.getoutput()["wateramount"]

        toac_image_sub = os.path.join(atm_working, "atmo_toac_sub.tif")
        param_toa_correction = {"toa": dict_of_input.get("L1Reader").get_value("IPTOASubOutput"),
                                "pressure": pressure_app_sub.getoutput()["pressure"],
                                "smac": dict_of_input.get("L2SMAC").new_gipp_filename,
                                "wateramountdefault": float(
                                    dict_of_input.get("L2COMM").get_value("WaterAmountDefaultValue")),
                                "nodata": dict_of_input.get("Params").get("RealL2NoData"),
                                "ozoneamount": dict_of_input.get("Params").get("OzoneAmount"),
                                "thetas": float(dict_of_input.get("L1Info").SolarAngle["sun_zenith_angle"]),
                                "thetav": viewing_zenith,
                                "bandlist": bands_definition.get_list_of_band_id_in_l2_coarse(),
                                "toac": toac_image_sub}
        if (dict_of_input.get("Plugin").WaterVapourDetermination and
                dict_of_input.get("L2COMM").get_value("GIP_L2COMM_UseDefaultConstantWaterAmount")):
            param_toa_correction["wateramount"] = dict_of_output["VAP_Sub"]

        toa_correction_app_sub = OtbAppHandler("TOACorrection", param_toa_correction, write_output=l_writeL2)
        if not l_writeL2:
            self._coarse_pipeline.add_otb_app(toa_correction_app_sub)

        dict_of_output["AtmoAbsIPTOAC"] = toa_correction_app_sub.getoutput()["toac"]

        if dict_of_input.get("Params").get("WriteL2ProductToL2Resolution"):
            l_nbRes = len(bands_definition.ListOfL2Resolution)
            for r in range(0, l_nbRes):
                l_res = bands_definition.ListOfL2Resolution[r]
                pressure_image = os.path.join(atm_working, "atmo_pressure_" + l_res + ".tif")
                param_pressure["dtm"] = dict_of_input.get("DEM").ALTList[r]
                param_pressure["pressure"] = pressure_image
                pressure_app = OtbAppHandler("PressureFilter", param_pressure,write_output=False)
                self._l2_pipeline.add_otb_app(pressure_app)
                water_image = os.path.join(atm_working, "atmo_wateramount_" + l_res + ".tif")
                if (dict_of_input.get("Plugin").WaterVapourDetermination and
                        dict_of_input.get("L2COMM").get_value("GIP_L2COMM_UseDefaultConstantWaterAmount")):
                    param_resamp = {"dtm": dict_of_input.get("DEM").ALTList[r],
                                    "im": dict_of_output["VAP_Sub"],
                                    "interp": "linear",
                                    "padradius": 4.0,
                                    "out": water_image}
                    water_app = OtbAppHandler("Resampling", param_resamp, write_output=False)
                    self._l2_pipeline.add_otb_app(water_app)
                    param_toa_correction["wateramount"] = water_app.getoutput().get("out")
                toac_image = os.path.join(atm_working, "atmo_toa_" + l_res + ".tif")
                param_toa_correction["toa"] = dict_of_input.get("L1Reader").get_value("L2TOAImageList")[r]
                param_toa_correction["pressure"] = pressure_app.getoutput().get("pressure")
                band_list = bands_definition.get_list_of_l2_band_id(l_res)
                LOGGER.debug("Athmo band_list")
                LOGGER.debug(band_list)

                viewing_zenith_l2 = []
                band_list_l2 = []
                for i in band_list:
                    viewing_zenith_l2.append(viewing_zenith[i])
                    band_list_l2.append(str(i))
                param_toa_correction["bandlist"] = band_list_l2
                param_toa_correction["thetav"] = viewing_zenith_l2
                param_toa_correction["toac"] = toac_image
                toa_app = OtbAppHandler("TOACorrection", param_toa_correction,write_output=False)
                self._l2_pipeline.add_otb_app(toa_app)
                dict_of_output["AtmoAbsIPTOA_" + l_res] = toa_app.getoutput().get("toac")
                dict_of_output["L2TOA_" + l_res] = toa_app.getoutput().get("toac")
class MajaWaterVaporPostProcessing(MajaModule):
    """
    classdocs
    """

    NAME = "WaterVaporPostProcessing"

    def __init__(self):
        """
        Constructor
        """
        super(MajaWaterVaporPostProcessing, self).__init__()
        self.in_keys_to_check = [
            "Params.Caching", "AppHandler", "Plugin", "L1Reader", "L2Reader",
            "L2COMM", "DEM"
        ]
        self.out_keys_to_check = ["RayleighIPTOCR", "dtm_shd", "SunglintFlag"]
        self.out_keys_provided = ["L2VAPList", "L2VAPMaskList"]
        self._l2_pipeline = OtbPipelineManager()

    def run(self, dict_of_input, dict_of_output):
        LOGGER.info("Water vapor post processing Correction start")
        caching = dict_of_input.get("Params").get("Caching")
        wvpp_working = dict_of_input.get(
            "AppHandler").get_directory_manager().get_temporary_directory(
                "WaterVaporPPProc_", do_always_remove=True)
        vap_default = float(
            dict_of_input.get("L2COMM").get_value("WaterAmountDefaultValue"))
        bands_definition = dict_of_input.get("Plugin").BandsDefinitions
        l_nbRes = len(bands_definition.ListOfL2Resolution)
        # Does the user choose to compute the VAP image ? (GIP_L2COMM_UseDefaultConstantWaterAmount)
        l_UseDefaultConstantWaterAmount = False
        if not dict_of_input.get("Plugin").WaterVapourDetermination or as_bool(
                dict_of_input.get("L2COMM").get_value(
                    "GIP_L2COMM_UseDefaultConstantWaterAmount")):
            l_UseDefaultConstantWaterAmount = True

        vap_list = []
        vapmask_list = []
        if l_UseDefaultConstantWaterAmount:
            for r in range(0, l_nbRes):
                l_res = bands_definition.ListOfL2Resolution[r]
                vap_image_filename = os.path.join(wvpp_working,
                                                  "vap_" + l_res + ".tif")
                vap_mask_filename = os.path.join(
                    wvpp_working, "vapmask_" + l_res + ".tif:uint8")
                vap_image = constant_image(dict_of_input.get("DEM").ALTList[r],
                                           vap_default,
                                           vap_image_filename,
                                           write_output=False)
                self._l2_pipeline.add_otb_app(vap_image)
                dict_of_output["VAP_" + l_res] = vap_image.getoutput()["out"]
                vap_mask = constant_image(dict_of_input.get("DEM").ALTList[r],
                                          0,
                                          vap_mask_filename,
                                          write_output=False)
                self._l2_pipeline.add_otb_app(vap_mask)
                dict_of_output["VAPMASK_" +
                               l_res] = vap_mask.getoutput()["out"]
                vap_list.append(dict_of_output["VAP_" + l_res])
                vapmask_list.append(dict_of_output["VAPMASK_" + l_res])
        else:
            l_refbandcode = dict_of_input.get("L2COMM").get_value(
                "WaterVaporReferenceBandCode")
            l_bandcode = dict_of_input.get("L2COMM").get_value(
                "WaterVaporBandCode")
            vap_subimage_filename = os.path.join(wvpp_working, "vap_sub.tif")
            vap_submask_filename = os.path.join(wvpp_working,
                                                "vapmask_sub.tif")
            param_watervpp = {
                "tocr":
                dict_of_output["RayleighIPTOCR"],
                "vapin":
                dict_of_output["VAP_Sub"],
                "cldsum":
                dict_of_output[constants.CLOUD_MASK_ALL],
                "defaultwatervapor":
                vap_default,
                "threshold":
                dict_of_input.get("L2COMM").get_value_f(
                    "WaterVaporReflectanceThreshold"),
                "thresholdref":
                dict_of_input.get("L2COMM").get_value_f(
                    "WaterVaporReflectanceThresholdRef"),
                "referencebandcode":
                bands_definition.get_band_id_in_l2_coarse(l_refbandcode),
                "bandcode":
                bands_definition.get_band_id_in_l2_coarse(l_bandcode),
                "nodata":
                dict_of_input.get("L2COMM").get_value_f("VAPNodataValue"),
                "sevalidradius":
                dict_of_input.get("L2COMM").get_value_i(
                    "WaterVaporSEValidRadius"),
                "initwindowradius":
                dict_of_input.get("L2COMM").get_value_i(
                    "WaterVaporInitWindowRadius"),
                "maxwindowradius":
                dict_of_input.get("L2COMM").get_value_i(
                    "WaterVaporMaxWindowRadius"),
                "mask":
                vap_submask_filename + ":uint8",
                "vap":
                vap_subimage_filename
            }
            watervpp_app = OtbAppHandler("WaterVaporPostPro",
                                         param_watervpp,
                                         write_output=False)
            self._l2_pipeline.add_otb_app(watervpp_app)

            for r in range(0, l_nbRes):
                l_res = bands_definition.ListOfL2Resolution[r]
                vap_image_filename = os.path.join(wvpp_working,
                                                  "vap_" + l_res + ".tif")
                vap_mask_filename = os.path.join(wvpp_working,
                                                 "vapmask_" + l_res + ".tif")
                param_subresampling = {
                    "dtm": dict_of_input.get("DEM").ALTList[r],
                    "im": watervpp_app.getoutput()["vap"],
                    "interp": "linear",
                    "out": vap_image_filename
                }
                subresampling_app = OtbAppHandler("Resampling",
                                                  param_subresampling,
                                                  write_output=False)
                self._l2_pipeline.add_otb_app(subresampling_app)

                param_maskresampling = {
                    "dtm": dict_of_input.get("DEM").ALTList[r],
                    "im": watervpp_app.getoutput()["mask"],
                    "interp": "linear",
                    "out": vap_mask_filename + ":uint8",
                    "threshold": 0.25
                }
                maskresampling_app = OtbAppHandler("Resampling",
                                                   param_maskresampling,
                                                   write_output=False)
                self._l2_pipeline.add_otb_app(maskresampling_app)
                if is_croco_on("watervaporpostprocessing"):
                    write_images([
                        subresampling_app.getoutput()["out"],
                        maskresampling_app.getoutput()["out"]
                    ], [vap_image_filename, vap_mask_filename])
                    dict_of_output["VAP_" + l_res] = vap_image_filename
                    dict_of_output["VAPMASK_" + l_res] = vap_mask_filename
                else:
                    dict_of_output[
                        "VAP_" + l_res] = subresampling_app.getoutput()["out"]
                    dict_of_output[
                        "VAPMASK_" +
                        l_res] = maskresampling_app.getoutput()["out"]
                vap_list.append(dict_of_output["VAP_" + l_res])
                vapmask_list.append(dict_of_output["VAPMASK_" + l_res])
        dict_of_output["L2VAPList"] = vap_list
        dict_of_output["L2VAPMaskList"] = vapmask_list
Ejemplo n.º 20
0
class MajaScatteringCorrection(MajaModule):
    """
    classdocs
    """

    NAME = "ScatteringCorrection"

    def __init__(self):
        """
        Constructor
        """
        super(MajaScatteringCorrection, self).__init__()
        self._scattering_sub_app = None
        self.in_keys_to_check = [
            "Params.Caching", "AppHandler", "Plugin", "L1Reader", "L2COMM",
            "DEM", "Params.RealL2NoData"
        ]
        self.out_keys_to_check = ["AtmoAbsIPTOAC", "hr_lutmap", "AOT_Sub"]
        self.out_keys_provided = ["TOC_sub"]
        self._l2_pipeline = OtbPipelineManager()

    def run(self, dict_of_input, dict_of_output):
        LOGGER.info("Scattering Correction start")
        scat_working = dict_of_input.get(
            "AppHandler").get_directory_manager().get_temporary_directory(
                "ScatteringProc_", do_always_remove=True)
        l_caching = dict_of_input.get("Params").get("Caching")
        l_writeL2 = dict_of_input.get("Params").get(
            "WriteL2ProductToL2Resolution")
        tocr_sub_image = os.path.join(scat_working, "tocr_sub.tif")
        bands_definition = dict_of_input.get("Plugin").BandsDefinitions
        #  Coarse scattering correction
        param_scattering = {
            "lutmap": dict_of_output["hr_lutmap"],
            "toac": dict_of_output["AtmoAbsIPTOAC"],
            "aot": dict_of_output["AOT_Sub"],
            "edg": dict_of_input.get("L1Reader").get_value("IPEDGSubOutput"),
            "dtm": dict_of_input.get("DEM").ALC,
            "l2nodata": dict_of_input.get("Params").get("RealL2NoData"),
            "l2bandincoarse":
            bands_definition.get_list_of_band_id_in_l2_coarse(),
            "tocr": tocr_sub_image
        }
        self._scattering_sub_app = OtbAppHandler("ScatteringCorrection",
                                                 param_scattering,
                                                 write_output=False)
        dict_of_output["TOC_sub"] = self._scattering_sub_app.getoutput(
        )["tocr"]
        # l2 scattering correction
        tocr_list = []
        if l_writeL2:
            l_nbRes = len(bands_definition.ListOfL2Resolution)
            for r in range(0, l_nbRes):
                l_res = bands_definition.ListOfL2Resolution[r]
                tocr_image = os.path.join(scat_working,
                                          "tocr_" + l_res + ".tif")
                if dict_of_input.get("Plugin").WideFieldSensor:
                    param_scattering["anglezone"] = dict_of_input.get(
                        "L1Reader").get_value("AngleZoneMaskList")[r]
                param_scattering["dtm"] = dict_of_input.get("DEM").ALTList[r]
                param_scattering["edg"] = dict_of_input.get(
                    "L1Reader").get_value("L2EDGOutputList")[r]
                param_scattering["aot"] = dict_of_output["AOT_" + l_res]
                param_scattering["toac"] = dict_of_output["L2TOA_" + l_res]
                param_scattering["tocr"] = tocr_image
                l_l2bandids = bands_definition.get_list_of_l2_coarse_band_id_associated_to_l2_band_code(
                    bands_definition.get_list_of_l2_band_code(l_res))
                param_scattering["l2bandincoarse"] = [
                    str(b) for b in l_l2bandids
                ]
                scat_app = OtbAppHandler(
                    "ScatteringCorrection",
                    param_scattering,
                    write_output=is_croco_on("scatteringcorrection"))
                self._l2_pipeline.add_otb_app(scat_app)
                dict_of_output["TOC_" +
                               l_res] = scat_app.getoutput().get("tocr")
                tocr_list.append(dict_of_output["TOC_" + l_res])
            dict_of_output["L2TOCList"] = tocr_list
class MajaCirrusCorrection(MajaModule):
    """
    classdocs
    """
    NAME = "CirrusCorrection"

    def __init__(self):
        """
        Constructor
        """
        super(MajaCirrusCorrection, self).__init__()
        self.in_keys_to_check = [
            "Params.Caching", "AppHandler", "Plugin", "L1Reader", "L2COMM",
            "DEM"
        ]
        self.out_keys_to_check = []
        self.out_keys_provided = []
        self._l2_pipeline = OtbPipelineManager()

    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
        ]
    def generate_mask_rasters(self, satPixFileNames, defectivPixFileNames,
                              zoneMaskFileNames, noDataMaskFileNames,
                              p_ListOfTOABandCode, working):
        """

        :param satPixFileNames: ListOfStrings
        :param defectivPixFileNames: ListOfStrings
        :param zoneMaskFileNames: ListOfStrings
        :param noDataMaskFileNames: ListOfStrings
        :param p_ListOfTOABandCode: ListOfStrings
        :param working: string
        :return:
        """

        # *******************************************************************************************************
        # Generate mask rasters by rasterizing the gml mask per L2 resolution per band
        # *******************************************************************************************************
        LOGGER.info("Starting GenerateMaskRasters")

        l_BandsDefinitions = self._plugin.BandsDefinitions
        l2Area = None
        l_ListOfL2Resolution = l_BandsDefinitions.ListOfL2Resolution  # ListOfStrings
        l_NbL2Res = len(l_ListOfL2Resolution)
        l_ListOfL1Resolution = l_BandsDefinitions.ListOfL1Resolution  # ListOfStrings
        l_NbL1Res = len(l_ListOfL1Resolution)
        l_NbL1Band = len(defectivPixFileNames)
        dtm_coarse = self._dem.ALC

        # Set a constant image if the gml masks are empty
        tmp_constant_filename = os.path.join(working, "Masks_const.tif")
        #constant_image(dtm_coarse, 0, tmp_constant_filename, write_output=True)

        # Initialize the L2 Elements
        for l2res in range(l_NbL2Res):
            self._l2defectmasklist.append([])
            self._l2zonemasklist.append([])
            self._l2satimagelist.append([])
            self._l2dfpimagelist.append(None)
            self._l2zoneimagelist.append(None)
        # Init the coarse elements
        for coarseband in p_ListOfTOABandCode:
            self._satmasksublist.append(None)
            self._nodatamasksublist.append(None)
            self._zonemasksublist.append(None)
            self._l2satmasklist.append(None)

        # Loop on L1Res
        for l1res in range(l_NbL1Res):
            # Current resolution: "R1" or "R2" or "R3"
            curL1Res = l_ListOfL1Resolution[l1res]

            # Get the list of band of the current resolution
            listOfL1Bands = l_BandsDefinitions.get_list_of_l1_band_code(
                curL1Res)
            nbL1Bands = len(listOfL1Bands)
            # For each band of the current resolution
            l_l2zone_pipeline = OtbPipelineManager()
            firstBandIdx = l_BandsDefinitions.get_band_id_in_l1(
                listOfL1Bands[-1])

            # Verify if we can optimize the work if its the same file for all bands of
            # the resolution and if the bands are in correct bit order
            l_strDefectFileNameRef = defectivPixFileNames[firstBandIdx]
            l_isDefectSameFilesForBands = True
            l_strSatFileNameRef = satPixFileNames[firstBandIdx]
            l_isSatSameFilesForBands = True
            l_strNoDataFileNameRef = noDataMaskFileNames[firstBandIdx]
            l_isNoDataSameFilesForBands = True
            for l_BandIdxL1 in range(len(listOfL1Bands)):
                # Get the L1 band index associated to the L2 band code
                l_StrBandIdL1 = listOfL1Bands[l_BandIdxL1]
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l_StrBandIdL1)
                # Filenameverify
                if l_strDefectFileNameRef != defectivPixFileNames[l1BandIdx]:
                    l_isDefectSameFilesForBands = False
                if l_strSatFileNameRef != satPixFileNames[l1BandIdx]:
                    l_isSatSameFilesForBands = False
                if l_strNoDataFileNameRef != noDataMaskFileNames[l1BandIdx]:
                    l_isNoDataSameFilesForBands = False
            LOGGER.debug("l_isDefectSameFilesForBands = " +
                         str(l_isDefectSameFilesForBands))
            LOGGER.debug("l_isSatSameFilesForBands = " +
                         str(l_isSatSameFilesForBands))
            LOGGER.debug("l_isNoDataSameFilesForBands = " +
                         str(l_isSatSameFilesForBands))

            # Defective PIX (only in L2 resolution)
            if l_isDefectSameFilesForBands:
                if curL1Res in l_ListOfL2Resolution:
                    l_StrBandIdL1 = listOfL1Bands[0]
                    l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(
                        l_StrBandIdL1)
                    LOGGER.debug("l_StrBandIdL1 : ")
                    LOGGER.debug(l_StrBandIdL1)
                    self._l2piximagelist.append(
                        defectivPixFileNames[l1BandIdx])
                    dfp_mask = os.path.join(
                        working, "L1_DFP_Masks_{}.tif".format(curL1Res))
                    param_bintovec_dfp = {
                        "im": defectivPixFileNames[l1BandIdx],
                        "out": dfp_mask + ":uint8",
                        "nbcomp": nbL1Bands
                    }
                    dfp_mask_app = OtbAppHandler("BinaryToVector",
                                                 param_bintovec_dfp,
                                                 write_output=False)
                    self._l2_dfp_pipeline.add_otb_app(dfp_mask_app)
                    self._l2dfpimagelist[l_ListOfL2Resolution.index(
                        curL1Res)] = dfp_mask_app.getoutput().get("out")
            else:
                raise MajaExceptionPluginSentinel2Muscate(
                    "Product format not supported : not the same file for band on PIX"
                )

            # SAT Mask generation
            if l_isSatSameFilesForBands:
                # Sat Masks generation
                l_StrBandIdL1 = listOfL1Bands[0]
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l_StrBandIdL1)
                l_SATFFilename = satPixFileNames[l1BandIdx]
                sat_mask = os.path.join(working,
                                        "L1_SAT_Masks_{}.tif".format(curL1Res))
                param_bintovec_dfp = {
                    "im": l_SATFFilename,
                    "out": sat_mask + ":uint8",
                    "nbcomp": nbL1Bands
                }
                sat_mask_app = OtbAppHandler("BinaryToVector",
                                             param_bintovec_dfp,
                                             write_output=True)
                # self._l2_sat_pipeline.add_otb_app(sat_mask_app)
                if curL1Res in l_ListOfL2Resolution:
                    self._l2satmasklist[l_ListOfL2Resolution.index(
                        curL1Res)] = sat_mask_app.getoutput().get("out")
                tmp_sat_resample = os.path.join(
                    working,
                    "tmp_extract_roi_sat_resample_{}.tif".format(curL1Res))
                sat_resamp_app = resample(sat_mask_app.getoutput().get("out"),
                                          dtm_coarse,
                                          tmp_sat_resample,
                                          OtbResampleType.LINEAR,
                                          write_output=False)
                self._sub_sat_pipeline.add_otb_app(sat_resamp_app)
                for l1band in listOfL1Bands:
                    l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l1band)
                    tmp_sat_roi = os.path.join(
                        working, "tmp_extract_roi_sat_{}.tif".format(l1band))
                    tmp_sat_roi_app = extract_roi(
                        sat_resamp_app.getoutput().get("out"), [
                            self.m_headerHandler.get_l1_sat_image_index(
                                l1BandIdx) - 1
                        ],
                        tmp_sat_roi,
                        write_output=False)
                    self._sub_sat_pipeline.add_otb_app(tmp_sat_roi_app)
                    self._satmasksublist[
                        l1BandIdx] = tmp_sat_roi_app.getoutput().get("out")
            else:
                raise MajaExceptionPluginSentinel2Muscate(
                    "Product format not supported : not the same file for band on SAT"
                )

            # No_data mask at L2 coarse
            if l_isNoDataSameFilesForBands:
                ndt_mask = os.path.join(
                    working, "L2_NDT_VecMasks_{}.tif".format(curL1Res))
                l_StrBandIdL1 = listOfL1Bands[0]
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l_StrBandIdL1)
                l_NoDataFilename = noDataMaskFileNames[l1BandIdx]
                param_bintovec_ndt = {
                    "im": l_NoDataFilename,
                    "out": ndt_mask + ":uint8",
                    "nbcomp": nbL1Bands
                }
                ndt_mask_app = OtbAppHandler("BinaryToVector",
                                             param_bintovec_ndt,
                                             write_output=False)
                self._subedg_pipeline.add_otb_app(ndt_mask_app)
                tmp_ndt_resample = os.path.join(
                    working,
                    "tmp_extract_roi_ndt_resample_{}.tif".format(curL1Res))
                ndt_resamp_app = resample(ndt_mask_app.getoutput().get("out"),
                                          dtm_coarse,
                                          tmp_ndt_resample,
                                          OtbResampleType.LINEAR,
                                          write_output=False)
                self._subedg_pipeline.add_otb_app(ndt_resamp_app)
                for l1band in listOfL1Bands:
                    l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l1band)
                    tmp_ndt_roi = os.path.join(
                        working, "tmp_extract_roi_ndt_{}.tif".format(l1band))
                    tmp_ndt_roi_app = extract_roi(
                        ndt_resamp_app.getoutput().get("out"), [
                            self.m_headerHandler.get_l1_ndt_image_index(
                                l1BandIdx) - 1
                        ],
                        tmp_ndt_roi,
                        write_output=False)
                    self._subedg_pipeline.add_otb_app(tmp_ndt_roi_app)
                    self._nodatamasksublist[
                        l1BandIdx] = tmp_ndt_roi_app.getoutput().get("out")
            else:
                raise MajaExceptionPluginSentinel2Muscate(
                    "Product format not supported : not the same file for band on NoData"
                )

            # Detectors FootPrint Masks Generation
            # Get all the detectors files realted to this resolution
            # Test if they all refers to the same files
            tmp_res_det_filenames = None
            all_same_det_for_bands = True
            for l_BandIdxL1 in range(len(listOfL1Bands)):
                # Get the L1 band index associated to the L2 band code
                l_StrBandIdL1 = listOfL1Bands[l_BandIdxL1]
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l_StrBandIdL1)
                LOGGER.debug(
                    "Sentinel2MuscateL1ImageFileReader::GenerateMaskRasters: CurrentResol = %s, reading the "
                    "BandId L1 (associated) <%s> with index <%s>.", curL1Res,
                    l_StrBandIdL1, l1BandIdx)
                # Detectors FootPrint Masks
                l_bandDetFnames = zoneMaskFileNames[l1BandIdx]
                if tmp_res_det_filenames is not None:
                    if len(tmp_res_det_filenames) != len(l_bandDetFnames):
                        all_same_det_for_bands = False
                        break
                else:
                    tmp_res_det_filenames = l_bandDetFnames
            #Construct file and det number list
            tmp_list_of_detf_filenames = []
            tmp_list_of_detf_num = []
            tmp_list_of_band_idx = []
            if all_same_det_for_bands:
                l_ListOfZone = self.m_headerHandler.get_list_of_zones(
                    listOfL1Bands[0])
                nbDetector = len(l_ListOfZone)
                # For each detector of the current band
                for det in range(nbDetector):
                    tmp_list_of_detf_filenames.append(
                        tmp_res_det_filenames[l_ListOfZone[det]])
                    tmp_list_of_detf_num.append(str(int(l_ListOfZone[det])))
            else:
                #some bands are not in all det rare case
                tmp_det_info_map = {}
                for l_BandIdxL1 in range(len(listOfL1Bands)):
                    # Get the L1 band index associated to the L2 band code
                    l_StrBandIdL1 = listOfL1Bands[l_BandIdxL1]
                    l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(
                        l_StrBandIdL1)
                    LOGGER.debug(
                        "Sentinel2MuscateL1ImageFileReader::GenerateMaskRasters: CurrentResol = %s, reading the "
                        "BandId L1 (associated) <%s> with index <%s>.",
                        curL1Res, l_StrBandIdL1, l1BandIdx)
                    # Detectors FootPrint Masks
                    l_bandDetFnames = zoneMaskFileNames[l1BandIdx]
                    l_ListOfZone = self.m_headerHandler.get_list_of_zones(
                        l_StrBandIdL1)
                    nbDetector = len(l_ListOfZone)
                    # For each detector of the current band
                    for det in range(nbDetector):
                        det_num = l_ListOfZone[det]
                        if det_num not in tmp_det_info_map.keys():
                            tmp_det_info_map[det_num] = (
                                zoneMaskFileNames[l1BandIdx][det_num],
                                [0] * len(listOfL1Bands))
                        tmp_det_info_map[det_num][1][l_BandIdxL1] = \
                            self.m_headerHandler.get_l1_dtf_image_index(l1BandIdx, det_num)[0]
                #once the info map is done
                for det in tmp_det_info_map.keys():
                    det_info = tmp_det_info_map[det]
                    tmp_list_of_detf_filenames.append(det_info[0])
                    tmp_list_of_detf_num.append(str(int(det)))
                    for x in det_info[1]:
                        tmp_list_of_band_idx.append(str(x))
            #create params
            detf_mask = os.path.join(working,
                                     "L1_DETF_Masks_{}.tif".format(curL1Res))
            param_dispacth_zone = {
                "il": tmp_list_of_detf_filenames,
                "out": detf_mask + ':uint8',
                "nbcomp": len(listOfL1Bands),
                "outvals": tmp_list_of_detf_num
            }
            #handle not all det/band case
            if not all_same_det_for_bands:
                param_dispacth_zone["outindexes"] = tmp_list_of_band_idx
            #Call the app
            dispatch_app = OtbAppHandler("DispatchZonesToVector",
                                         param_dispacth_zone,
                                         write_output=True)
            #This is the L2 output
            if curL1Res in l_ListOfL2Resolution:
                self._l2zoneimagelist[l_ListOfL2Resolution.index(
                    curL1Res)] = dispatch_app.getoutput().get("out")
            #extract the coarse bands
            for l1band in listOfL1Bands:
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l1band)
                tmp_zone_roi = os.path.join(
                    working, "tmp_extract_roi_ndt_{}.tif".format(l1band))
                tmp_zone_roi_app = extract_roi(
                    dispatch_app.getoutput().get("out"), [
                        self.m_headerHandler.get_l1_ndt_image_index(l1BandIdx)
                        - 1
                    ],
                    tmp_zone_roi,
                    write_output=False)
                self._subedg_pipeline.add_otb_app(tmp_zone_roi_app)
                tmp_zone_with_nodata = os.path.join(
                    working, "tmp_zone_with_nodata_{}".format(curL1Res))
                masterExpr = "( im1b1 > 0 ) ? im1b1 : -10000"
                param_bandmath_zone = {
                    "il": [tmp_zone_roi_app.getoutput().get("out")],
                    "exp": masterExpr,
                    "out": tmp_zone_with_nodata
                }
                zone_thresh_bandmath_app = OtbAppHandler("BandMathDouble",
                                                         param_bandmath_zone,
                                                         write_output=False)
                # LAIG-FA-MAC-1652-CNES : probleme reech detecteur en unsigned char : detecteur 1 devient 0.....
                tmp_zone_resample = os.path.join(
                    working,
                    "tmp_extract_roi_zone_resample_{}.tif".format(l1BandIdx))
                zone_resample_app = resample(
                    zone_thresh_bandmath_app.getoutput().get("out"),
                    dtm_coarse,
                    tmp_zone_resample,
                    OtbResampleType.LINEAR,
                    write_output=False)
                # threshold everything negative to 0
                Thresholdexpr = "im1b1 > 0 ? im1b1 : 0"
                tmp_zone_threshold = os.path.join(
                    working, "tmp_zone_threshold_{}".format(l1BandIdx))
                param_bandmath_zone_threshold = {
                    "il": [zone_resample_app.getoutput().get("out")],
                    "exp": Thresholdexpr,
                    "out": tmp_zone_threshold
                }
                zone_bandmath_threshold_app = OtbAppHandler(
                    "BandMathDouble",
                    param_bandmath_zone_threshold,
                    write_output=False)
                # Rounding
                tmp_zone_round = os.path.join(
                    working, "tmp_zone_round_{}".format(l1BandIdx))
                param_bandmath_zone_round = {
                    "im": zone_bandmath_threshold_app.getoutput().get("out"),
                    "out": tmp_zone_round
                }
                zone_round_app = OtbAppHandler("RoundImage",
                                               param_bandmath_zone_round,
                                               write_output=True)
                # Add to the official output
                self._zonemasksublist[l1BandIdx] = zone_round_app.getoutput(
                ).get("out")
                # Log current loop
                LOGGER.debug("band loop: " + str(l1BandIdx + 1) + " / " +
                             str(nbL1Bands) + " (" + curL1Res + ")")
            # band loop
            LOGGER.debug("band loop: END")
            self._l2_detf_pipeline.free_otb_app()
class Sentinel2L1ImageFileReaderBase(L1ImageReaderBase):
    def __init__(self):
        super(Sentinel2L1ImageFileReaderBase, self).__init__()
        self._toa_scalar_list = []
        self._toa_sub_list = []
        self._l2toaimagelist = []
        self._sol1image = ""
        self._sub_toa = ""
        self._l2satmasklist = []
        self._l2satimagelist = []
        self._subsatimage = ""
        self._l2zonemasklist = []
        self._l2defectmasklist = []
        self._l2edgmasklist = []
        self._l2piximagelist = []
        self._l2dfpimagelist = []
        self._l2zoneimagelist = []
        self._satmasksublist = []
        self._zonemasksublist = []
        self._nodatamasksublist = []
        self._edgsubmask = ""
        self._claimage = ""
        self._vieimagelist = []
        self._meanZenithMap = {}
        self._meanAzimuthMap = {}

        # Store the apps
        self._pipeline = OtbPipelineManager()
        self._subedg_pipeline = OtbPipelineManager()

    def get_l1_toa_cirrus_image(self):
        """
        Get the L1 TOA reflectance image for Cirrus Band
        :return:
        """
        LOGGER.debug("Start L1 reading for L1 Cirrus band ...")
        # TODO: GetCheckXMLFilesWithSchema TBD ConfigUserSystem.GetInstance()
        l_BandsDefinitions = self._plugin.BandsDefinitions  # BandsDefinitions

        l_CirrusBandCode = self._GIPPL2COMMHandler.get_cirrus_band_code(
        )  # string
        LOGGER.debug("Cirrus Viewing band code: %s", l_CirrusBandCode)
        # ---------------------------------------------------------------
        # get the index of the cirrus band in the list of the L1 bands
        # curRes = "R2", bd = 1 <=> "B6" => i = 5
        cirrusBandId = l_BandsDefinitions.L1BandMap.get(
            l_CirrusBandCode, None)  # int
        LOGGER.debug("Cirrus BandId index: %s with nb index = %s %s )",
                     cirrusBandId, len(self._toa_scalar_list),
                     len(self._toa_scalar_list))
        return self._toa_scalar_list[cirrusBandId]

    def get_dtm_vie_image(self):
        """
        Get DTMVIE Image
        :return:
        """
        l_DTMBandCode = self._GIPPL2COMMHandler.l2_comm_values.get(
            "DTMViewingDirectionBandCode", None)[0]
        LOGGER.debug("DTM Viewing band code: %s", l_DTMBandCode)
        # TODO; check GetL2CoarseResolution grep L2CoarseResolution
        l_DTMBandId = self._plugin.BandsDefinitions.get_band_id_in_l2_coarse(
            l_DTMBandCode)
        return self._vieimagelist[l_DTMBandId]

    def get_shadow_vie_image(self):
        """
        Get ShadowVIE Image
        :return:
        """
        l_CLDBandCode = self._GIPPL2COMMHandler.get_cld_viewing_direction_band_code(
        )
        l_CLDBandId = self._plugin.BandsDefinitions.get_band_id_in_l2_coarse(
            l_CLDBandCode)
        return self._vieimagelist[l_CLDBandId]

    def generate_toa_caching(self, listOfTOAImageFileNames,
                             reflectanceMultiplicationValues, working):
        """

        :param listOfTOAImageFileNames: ListOfStrings
        :param reflectanceMultiplicationValues: ListOfDoubles
        :return:
        """
        if len(reflectanceMultiplicationValues) != len(
                listOfTOAImageFileNames):
            raise MajaDataException(
                "Not the same number of band images and coefficients")

        # ---------------------------------------------------------------
        # Get the number of band with the number of TOA image files set in the input product directory
        l_NbBand = len(listOfTOAImageFileNames)  # int

        # Convert the input jp2 images in tif
        for i in range(l_NbBand):
            toaFilename = listOfTOAImageFileNames[i]
            LOGGER.debug("Caching the <%s> image filename...", toaFilename)
            LOGGER.debug("Reflectance quantification value: %s",
                         reflectanceMultiplicationValues[i])
            # Initialize the TOA reader
            l_ImageFilename = os.path.join(working,
                                           "toaconverted_" + str(i) + ".tif")
            # extract_roi(toaFilename,[0],l_ImageFilename,working)
            app = multiply_by_scalar(toaFilename,
                                     reflectanceMultiplicationValues[i],
                                     output_image=l_ImageFilename,
                                     write_output=True)
            self._pipeline.add_otb_app(app)
            self._toa_scalar_list.append(app.getoutput()["out"])

    def generate_toa_sub_images(self, working):
        dtm_coarse = self._dem.ALC

        # For each band of the input product
        tmp_sub_toa_pipe = OtbPipelineManager()
        for i, toa in enumerate(self._toa_scalar_list):
            # undersampling at L2CoarseResolution
            toa_sub_image = os.path.join(working, "aot_sub_{}.tif".format(i))
            app = resample(toa,
                           dtm_coarse,
                           toa_sub_image,
                           OtbResampleType.LINEAR_WITH_RADIUS,
                           write_output=False)
            self._toa_sub_list.append(app.getoutput()["out"])
            tmp_sub_toa_pipe.add_otb_app(app)
        # end band loop

        # *******************************************************************************************************
        # TOA Sub image pipeline connection
        # *******************************************************************************************************
        toa_sub_image = os.path.join(working, "aot_sub.tif")
        param_concatenate = {"il": self._toa_sub_list, "out": toa_sub_image}
        OtbAppHandler("ConcatenateDoubleImages", param_concatenate)
        self._sub_toa = toa_sub_image
        tmp_sub_toa_pipe.free_otb_app()

    def rasterize_gml_masks(self, l1Resolution, l2res, l2Area, projectionRef,
                            l1Band, satFilename, defectFilename, zoneFilename,
                            boundingBox, gdalRasterizeMaskCmd,
                            gdalRasterizeDetCmd, tmp_constant_image, working):
        """

        :param l1Resolution: string
        :param l2res: int
        :param l2Area: AreaType
        :param projectionRef: string
        :param l1Band: int
        :param satFilename: string
        :param defectFilename: string
        :param zoneFilename: string
        :param boundingBox: BoundingBoxType
        :param gdalRasterizeMaskCmd: string
        :param gdalRasterizeDetCmd: string
        :return:
        """

        # convert the band index in string
        l1BandStr = str(l1Band)

        LOGGER.debug(
            "RasterizeGmlMasks mask for band: %s\n"
            " - for l1Resolution  = %s"
            "\n - l2res             = %s \n \n - l2Area    = %s"
            "\n - satFilename       = %s \n - defectFilename    = %s"
            "\n - zoneFilename      = %s \n", l1Band, l1Resolution, l2res,
            l2Area, satFilename, defectFilename, zoneFilename)

        # TODO: la generation d'une image constante cots.otb.otb_constant_image
        # ------------------------------------------------------------

        # -----------------------------------------------------------------------------------
        # Rasterize gml masks at L2 resolution with gdal_rasterize system command
        # -----------------------------------------------------------------------------------

        # -----------------------------------------------------------------------------------
        # Detectors FootPrint
        # check if the gml mask contains features
        count_zone = self.get_mask_feature_count(zoneFilename)
        LOGGER.debug("MaskFeatureCount for " + zoneFilename + ": " +
                     str(count_zone))

        if count_zone > 0:
            # Get the shift between the detector index and the feature index
            shift_res = self.get_detfoo_index_shift(zoneFilename)

            if shift_res[0]:
                sqlRequest = gdalRasterizeDetCmd
                sqlRequest = sqlRequest + """-a fid2 -sql \'select fid + """ + \
                    str(shift_res[1]) + """ as fid2, * from MaskFeature \'"""
                l_image_raster_filename = os.path.join(
                    working, "L2ZoneMaskReaders_Resol_" + l1Resolution +
                    "_band_id_" + l1BandStr + ".tif")
                GdalRasterize().internal_rasterize_gml_macro(
                    zoneFilename, boundingBox.xmin, boundingBox.ymin,
                    boundingBox.xmax, boundingBox.ymax, l2Area.size[0],
                    l2Area.size[1], projectionRef, l_image_raster_filename,
                    sqlRequest)
                self._l2zonemasklist[l2res].append(l_image_raster_filename)
            else:
                LOGGER.debug("Bad Order DETFOO detected")
                sqlRequest = gdalRasterizeDetCmd
                sqlRequest = sqlRequest + """-a fid2 -sql \'select fid + 1 as fid2, * from MaskFeature \'"""
                l_image_raster_filename = os.path.join(
                    working, "L2ZoneMaskReaders_Resol_" + l1Resolution +
                    "_band_id_" + l1BandStr + ".tif")
                GdalRasterize().internal_rasterize_gml_macro(
                    zoneFilename, boundingBox.xmin, boundingBox.ymin,
                    boundingBox.xmax, boundingBox.ymax, l2Area.size[0],
                    l2Area.size[1], projectionRef, l_image_raster_filename,
                    sqlRequest)
                l_fid_dets = self.get_detfoo_index_detector_list(
                    zoneFilename, 1)
                l_image_changed_filename = os.path.join(
                    working, "L2ZoneMaskReadersChanged_Resol_" + l1Resolution +
                    "_band_id_" + l1BandStr + ".tif")
                change_values_param = {
                    "im": l_image_raster_filename,
                    "out": l_image_changed_filename,
                    "invals": [str(a) for a in l_fid_dets.keys()],
                    "outvals": [str(a) for a in l_fid_dets.values()]
                }
                change_values_app = OtbAppHandler("ChangeValues",
                                                  change_values_param)
                self._l2zonemasklist[l2res].append(
                    change_values_app.getoutput().get("out"))

        else:
            self._l2zonemasklist[l2res].append(tmp_constant_image)

        # -----------------------------------------------------------------------------------
        # Saturated SAT
        # check if the gml mask contains features
        count_sat = self.get_mask_feature_count(satFilename)
        LOGGER.debug("MaskFeatureCount for " + satFilename + ": " +
                     str(count_sat))
        if count_sat > 0:
            l_image_raster_filename = os.path.join(
                working, "L2SatPixReaders_Resol_" + l1Resolution +
                "_band_id_" + l1BandStr + ".tif")
            GdalRasterize().internal_rasterize_gml_macro(
                satFilename, boundingBox.xmin, boundingBox.ymin,
                boundingBox.xmax, boundingBox.ymax, l2Area.size[0],
                l2Area.size[1], projectionRef, l_image_raster_filename,
                gdalRasterizeMaskCmd)
            self._l2satimagelist[l2res].append(l_image_raster_filename)
        else:

            self._l2satimagelist[l2res].append(tmp_constant_image)

        # -----------------------------------------------------------------------------------
        # Defectiv PIX
        # check if the gml mask contains features
        count_pix = self.get_mask_feature_count(defectFilename)
        LOGGER.debug("MaskFeatureCount for " + defectFilename + ": " +
                     str(count_pix))
        if count_pix > 0:
            l_image_raster_filename = os.path.join(
                working, "L2DefectivPixReaders_Resol_" + l1Resolution +
                "_band_id_" + l1BandStr + ".tif")
            GdalRasterize().internal_rasterize_gml_macro(
                defectFilename, boundingBox.xmin, boundingBox.ymin,
                boundingBox.xmax, boundingBox.ymax, l2Area.size[0],
                l2Area.size[1], projectionRef, l_image_raster_filename,
                gdalRasterizeMaskCmd)
            self._l2defectmasklist[l2res].append(l_image_raster_filename)
        else:
            self._l2defectmasklist[l2res].append(tmp_constant_image)

        return count_zone, count_sat, count_pix

    def generate_mask_rasters_gml(self, boundingBoxMap, l2Areas, projectionRef,
                                  satPixFileNames, defectivPixFileNames,
                                  zoneMaskFileNames, gdalRasterizeMaskCmd,
                                  gdalRasterizeDetCmd, working):
        """

        :param boundingBoxMap: BoundingBoxMapType
        :param projectionRef: string
        :param satPixFileNames: ListOfStrings
        :param defectivPixFileNames: ListOfStrings
        :param zoneMaskFileNames: ListOfStrings
        :param gdalRasterizeMaskCmd: string
        :param gdalRasterizeDetCmd: string
        :param working: string
        :return:
        """

        # *******************************************************************************************************
        # Generate mask rasters by rasterizing the gml mask per L2 resolution per band
        # *******************************************************************************************************
        LOGGER.debug("Start GML mask rasterization ...")
        l_BandsDefinitions = self._plugin.BandsDefinitions
        l2Area = None
        l_ListOfL2Resolution = l_BandsDefinitions.ListOfL2Resolution  # ListOfStrings
        l_NbL2Res = len(l_ListOfL2Resolution)

        for l2res in range(l_NbL2Res):
            self._l2defectmasklist.append([])
            self._l2zonemasklist.append([])
            self._l2satimagelist.append([])

        for l2res in range(l_NbL2Res):
            # Current resolution: "R1" or "R2"
            curRes = l_ListOfL2Resolution[l2res]

            # Get the list of band of the current resolution
            listOfL2Bands = l_BandsDefinitions.get_list_of_l2_band_code(curRes)
            nbBand = len(listOfL2Bands)
            l2Area = l2Areas[l2res]
            counts = (0, 0, 0)
            # Generate a constant image that will be used if the gml masks are empty (no feature)
            tmp_constant_filename = os.path.join(
                working, "const_{}.tif:uint8".format(l2res))
            tmp_constant_image_app = constant_image(self._dem.ALTList[l2res],
                                                    0,
                                                    tmp_constant_filename,
                                                    write_output=True)
            tmp_constant_image = tmp_constant_image_app.getoutput()["out"]
            # For each band of the current resolution
            for l_StrBandIdL2 in listOfL2Bands:
                # Get the L1 band index associated to the L2 band code
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l_StrBandIdL2)
                LOGGER.debug(
                    "Sentinel2L1ImageFileReaderBase::GenerateMaskRasters: CurrentResol = %s, reading the "
                    "BandId L1 (associated) <%s> with index <%s>.", curRes,
                    l_StrBandIdL2, l1BandIdx)

                # Read the bounding box for the resolution  "l_L1Resolution"
                l_BoundingBox = boundingBoxMap.get(curRes)

                # =======> RASTERIZE GML MASKS
                new_counts = self.rasterize_gml_masks(
                    curRes, l2res, l2Area, projectionRef, l1BandIdx,
                    satPixFileNames[l1BandIdx],
                    defectivPixFileNames[l1BandIdx],
                    zoneMaskFileNames[l1BandIdx], l_BoundingBox,
                    gdalRasterizeMaskCmd, gdalRasterizeDetCmd,
                    tmp_constant_image, working)
                counts = tuple(map(operator.add, counts, new_counts))

            # band loop

            # *******************************************************************************************************
            # L2 Zone mask pipeline connection
            # *******************************************************************************************************
            if counts[0] != 0:
                zone_mask = os.path.join(working,
                                         "Masks_Zone_{}.tif".format(l2res))
                param_concatenate = {
                    "il": self._l2zonemasklist[l2res],
                    "out": zone_mask + ":uint8"
                }
                l2zoneimage_app = OtbAppHandler(
                    "ConcatenateDoubleImages",
                    param_concatenate,
                    write_output=(False
                                  or is_croco_on("sentinel2.l1reader.l2zone")))
                self._l2zoneimagelist.append(
                    l2zoneimage_app.getoutput().get("out"))
                self._pipeline.add_otb_app(l2zoneimage_app)
            else:
                self._l2zoneimagelist.append(self._l2zonemasklist[l2res][0])
            # *******************************************************************************************************
            # PIX image pipeline connection (DEFECTIV PIX)
            # *******************************************************************************************************
            if counts[2] != 0:
                # Compress (concatenate the vector image to binary image)
                pix_vector_mask = os.path.join(
                    working, "Masks_Defect_Vector_{}.tif".format(l2res))
                param_concatenate = {
                    "il": self._l2defectmasklist[l2res],
                    "out": pix_vector_mask + ":uint8"
                }
                pix_vector = OtbAppHandler("ConcatenateDoubleImages",
                                           param_concatenate)
                pix_mask = os.path.join(working,
                                        "Masks_Defect_{}.tif".format(l2res))
                param_binconcatenate = {
                    "im": pix_vector.getoutput().get("out"),
                    "out": pix_mask + ":uint16"
                }
                pix = OtbAppHandler(
                    "BinaryConcatenate",
                    param_binconcatenate,
                    write_output=(False
                                  or is_croco_on("sentinel2.l1reader.l2pix")))
                self._pipeline.add_otb_app(pix)
                self._l2piximagelist.append(pix.getoutput().get("out"))
            else:
                self._l2piximagelist.append(self._l2defectmasklist[l2res][0])
            # end res loop
        LOGGER.debug("End GML mask rasterization ...")

    def get_solar_grids(self, dtm, solarAnglesFile, solH1, working):

        solar_grid_filename = os.path.join(working, "solar_grid.tif")

        # angle_list_to_image()
        solarangle_grid_app = angle_list_to_image(dtm,
                                                  solarAnglesFile,
                                                  solar_grid_filename,
                                                  write_output=False)
        # Multiply by the solar reference altitude
        solar_grid_mult_filename = os.path.join(working, "solar_grid_mult.tif")
        param_scaled_solar = {
            "im": solarangle_grid_app.getoutput().get("out"),
            "coef": float(solH1),
            "out": solar_grid_mult_filename
        }
        rta_scal_app = OtbAppHandler("MultiplyByScalar",
                                     param_scaled_solar,
                                     write_output=False)
        # Expand at L2Coarse.
        solar_grid_resamp_filename = os.path.join(working,
                                                  "solar_grid_resamp.tif")
        resample(rta_scal_app.getoutput().get("out"), dtm,
                 solar_grid_resamp_filename, OtbResampleType.LINEAR)
        self._sol1image = solar_grid_resamp_filename

    def get_viewing_grids(self, band, l2CoarseArea, projectionRef, vieHRef,
                          satFilename, zoneFilename, nodataFilename,
                          listOfZone, boundingBox, viewing_angles,
                          gdalRasterizeMaskCmd, gdalRasterizeDetCmd,
                          gdalRasterizeNdtCmd, nbCoarseBands, working):
        """

        :param band: int
        :param l2CoarseArea: AreaType
        :param projectionRef: string
        :param vieHRef: double
        :param satFilename: string
        :param zoneFilename: string
        :param nodataFilename: string
        :param listOfZone: ListOfUIntegers
        :param boundingBox: BoundingBoxType
        :param viewing_angles:
        :param gdalRasterizeMaskCmd: string
        :param gdalRasterizeDetCmd: string
        :param gdalRasterizeNdtCmd: string
        :return:
        """
        dtm_coarse = self._dem.ALC

        # Set a constant image if the gml masks are empty
        tmp_constant_filename = os.path.join(working, "Masks_sat_const.tif")
        constant_image(dtm_coarse,
                       0,
                       tmp_constant_filename + ":uint8",
                       write_output=True)

        # -----------------------------------------------------------------------------------
        # Rasterize all the gml maks at L2 coarse resolution
        # to generate the viewing grids
        # -----------------------------------------------------------------------------------

        # -----------------------------------------------------------------------------------
        # Detectors FootPrint
        # check if the gml mask contains features
        count = self.get_mask_feature_count(zoneFilename)

        if count > 0:
            # Get the shift between the detector index and the feature index
            shift_res = self.get_detfoo_index_shift(zoneFilename)

            if shift_res[0]:
                l_image_raster_filename = os.path.join(
                    working, "SubZoneMask_band_id_{}.tif".format(band))
                # Additional parameters of the gdal_rasterize system command
                sqlRequest = gdalRasterizeDetCmd + \
                    "-a fid2 -sql 'select fid + {} as fid2, * from MaskFeature'".format(shift_res[1])

                GdalRasterize().internal_rasterize_gml_macro(
                    zoneFilename, boundingBox.xmin, boundingBox.ymin,
                    boundingBox.xmax, boundingBox.ymax, l2CoarseArea.size[0],
                    l2CoarseArea.size[1], projectionRef,
                    l_image_raster_filename, sqlRequest)

                submask_resamp_filename = os.path.join(
                    working,
                    "SubZoneMask_resampled_band_id_{}.tif".format(band))
                resample(l_image_raster_filename, dtm_coarse,
                         submask_resamp_filename, OtbResampleType.LINEAR)

                self._zonemasksublist.append(submask_resamp_filename)
            else:
                LOGGER.debug("Bad Order DETFOO detected")
                l_image_raster_filename = os.path.join(
                    working, "SubZoneMask_band_id_{}.tif".format(band))
                # Additional parameters of the gdal_rasterize system command
                sqlRequest = gdalRasterizeDetCmd + \
                             "-a fid2 -sql 'select fid + 1 as fid2, * from MaskFeature'"

                GdalRasterize().internal_rasterize_gml_macro(
                    zoneFilename, boundingBox.xmin, boundingBox.ymin,
                    boundingBox.xmax, boundingBox.ymax, l2CoarseArea.size[0],
                    l2CoarseArea.size[1], projectionRef,
                    l_image_raster_filename, sqlRequest)
                l_fid_dets = self.get_detfoo_index_detector_list(
                    zoneFilename, 1)
                l_image_changed_filename = os.path.join(
                    working, "SubZoneMaskChanged_band_id_{}.tif".format(band))
                change_values_param = {
                    "im": l_image_raster_filename,
                    "out": l_image_changed_filename + ":uint8",
                    "invals": [str(a) for a in l_fid_dets.keys()],
                    "outvals": [str(a) for a in l_fid_dets.values()]
                }
                change_values_app = OtbAppHandler("ChangeValues",
                                                  change_values_param)

                submask_resamp_filename = os.path.join(
                    working,
                    "SubZoneMask_resampled_band_id_{}.tif".format(band))
                resample(change_values_app.getoutput().get("out"), dtm_coarse,
                         submask_resamp_filename, OtbResampleType.LINEAR)

                self._zonemasksublist.append(submask_resamp_filename)

        else:
            submask_resamp_filename = os.path.join(
                working, "SubZoneMask_resampled_band_id_{}.tif".format(band))
            resample(tmp_constant_filename, dtm_coarse,
                     submask_resamp_filename, OtbResampleType.LINEAR)
            self._zonemasksublist.append(submask_resamp_filename)

        # -----------------------------------------------------------------------------------
        # Saturated pixel mask at L2 coarse
        count = self.get_mask_feature_count(satFilename)

        if count > 0:
            l_image_raster_filename = os.path.join(
                working, "SubSatMask_band_id_{}.tif".format(band))
            GdalRasterize().internal_rasterize_gml_macro(
                satFilename, boundingBox.xmin, boundingBox.ymin,
                boundingBox.xmax, boundingBox.ymax, l2CoarseArea.size[0],
                l2CoarseArea.size[1], projectionRef, l_image_raster_filename,
                gdalRasterizeMaskCmd)
            self._satmasksublist.append(l_image_raster_filename)
        else:
            self._satmasksublist.append(tmp_constant_filename)

        # -----------------------------------------------------------------------------------
        # No_data mask at L2 coarse
        count = self.get_mask_feature_count(nodataFilename, "NODATA")

        if count > 0:
            l_image_raster_filename = os.path.join(
                working, "SubNoDataMask_band_id_{}.tif".format(band))
            GdalRasterize().internal_rasterize_gml_macro(
                nodataFilename, boundingBox.xmin, boundingBox.ymin,
                boundingBox.xmax, boundingBox.ymax, l2CoarseArea.size[0],
                l2CoarseArea.size[1], projectionRef, l_image_raster_filename,
                gdalRasterizeNdtCmd)
            self._nodatamasksublist.append(l_image_raster_filename)
        else:
            self._nodatamasksublist.append(tmp_constant_filename)

        l_VieAnglesGridList = []
        l_nbDetectors = len(viewing_angles)

        # Detector loop
        LOGGER.debug("For each detectors (nb=%s) ...", l_nbDetectors)
        for angle in viewing_angles:
            l_vieAngleFile = angle.write(working)
            # ---------------------------------------------------------------------------------
            # Generate an image with the list of viewing angle values set in the header file
            # ---------------------------------------------------------------------------------
            viewing_grid_filename = os.path.join(
                working,
                "viewing_grid_{}_{}.tif".format(angle.detector_id, band))

            # angle_list_to_image()
            viewing_angle_app = angle_list_to_image(dtm_coarse,
                                                    l_vieAngleFile,
                                                    viewing_grid_filename,
                                                    write_output=False,
                                                    extrapolation=True)

            # Expand at L2Coarse.
            viewing_grid_resamp_filename = os.path.join(
                working,
                "viewing_grid_resamp_{}_{}.tif".format(angle.detector_id,
                                                       band))
            resample(viewing_angle_app.getoutput().get("out"), dtm_coarse,
                     viewing_grid_resamp_filename, OtbResampleType.LINEAR)

            # add images in a list
            l_VieAnglesGridList.append(viewing_grid_resamp_filename)

        # end detector loop
        LOGGER.debug(
            "Start ConcatenatePerZoneVectorImageFilter for band id [%s]...",
            band)

        # -----------------------------------------------------------------------------------
        # Generate the angle images using the zone (detector) mask
        # -----------------------------------------------------------------------------------
        # Concatenate all the detectors
        viewing_concat_filename = os.path.join(
            working, "viewing_concat_{}.tif".format(band))
        param_concat_perzone = {
            "mask": self._zonemasksublist[-1],
            "il": l_VieAnglesGridList,
            "zonelist": listOfZone,
            "out": viewing_concat_filename
        }
        concat_perzone = OtbAppHandler("ConcatenatePerZone",
                                       param_concat_perzone)
        # Multiply by reference altitude
        viewing_grid_mult_filename = os.path.join(
            working, "viewing_grid_mult_{}.tif".format(band))
        param_scaled_solar = {
            "im": viewing_concat_filename,
            "coef": float(vieHRef),
            "out": viewing_grid_mult_filename
        }
        view_scale_app = OtbAppHandler("MultiplyByScalar",
                                       param_scaled_solar,
                                       write_output=True)
        self._vieimagelist.append(view_scale_app.getoutput().get("out"))

        l_nbZones = len(listOfZone)
        LOGGER.debug("Start Loop for Zone (nb=" + str(l_nbZones) + ")...")
        for d in range(l_nbZones):
            l_zone = listOfZone[d]
            # -----------------------------------------------------------------------------------
            # Compute average values of zenithal and azimuthal angles grid per zone (detector in level1B)
            # -----------------------------------------------------------------------------------
            # VAP Reader connection (from ATB)
            tmp_azi = os.path.join(working,
                                   "tmp_azi_{}_{}.tif".format(band, l_zone))
            tmp_azi_image = extract_roi(l_VieAnglesGridList[d], [1], tmp_azi)
            param_stats = {
                "im": tmp_azi,
                "exclude": 1,
                "mask": self._zonemasksublist[band],
                "maskforeground": int(l_zone)
            }
            l2_stat = OtbAppHandler("Stats", param_stats)

            azi_mean = l2_stat.getoutput().get("mean")
            tmp_zen = os.path.join(working,
                                   "tmp_zen_{}_{}.tif".format(band, l_zone))
            tmp_zen_image = extract_roi(l_VieAnglesGridList[d], [0], tmp_zen)
            param_stats = {
                "im": tmp_zen,
                "exclude": 1,
                "mask": self._zonemasksublist[band],
                "maskforeground": int(l_zone)
            }
            l2_stat = OtbAppHandler("Stats", param_stats)
            zen_mean = l2_stat.getoutput().get("mean")
            tmp_mean = (zen_mean, azi_mean)
            l_ViewingAngleMean = grid_to_angle(tmp_mean)
            l_ViewingAngleMeanDeg = (l_ViewingAngleMean[0] * 180.0 / math.pi,
                                     l_ViewingAngleMean[1] * 180.0 / math.pi)
            # Add a vector to mean maps
            if l_zone not in self._meanZenithMap:
                self._meanZenithMap[listOfZone[d]] = ["0"] * nbCoarseBands
            if l_zone not in self._meanAzimuthMap:
                self._meanAzimuthMap[listOfZone[d]] = ["0"] * nbCoarseBands
            self._meanZenithMap[listOfZone[d]][band] = str(
                l_ViewingAngleMeanDeg[0])
            self._meanAzimuthMap[listOfZone[d]][band] = str(
                l_ViewingAngleMeanDeg[1])
            LOGGER.debug(" For BandId[" + str(band) + "], zone [" +
                         str(listOfZone[d]) + "]  . Mean 'GRID View angles'=" +
                         str(tmp_mean) + " . Mean 'View angles'=" +
                         str(l_ViewingAngleMean[0]) + ":" +
                         str(l_ViewingAngleMean[1]) + " rad. ou  " +
                         str(l_ViewingAngleMeanDeg[0]) + ":" +
                         str(l_ViewingAngleMeanDeg[1]) + " deg.")
        LOGGER.debug("Start Loop for Zone done.")

    def generate_edg_images(self, working_dir):
        """

        :param working_dir: String
        :return:
        """
        dtm_coarse = self._dem.ALC

        list_of_binary_threshold = []
        m_OrFilter1List = []
        m_OrFilter2List = []

        # *******************************************************************************************************
        # IPEDGSub pipeline connection
        # *******************************************************************************************************
        LOGGER.debug("Start IPEDGSub ...")
        # At L2 coarse resolution

        # Set to 0 the pixel that are not edges in the zone (detector) mask image raster
        out_thresh_0 = os.path.join(working_dir, "IPEDGOrFilter1SubMask_0.tif")
        out_binary_threshold_ipedg_image_b1 = binary_threshold(
            input_image=self._zonemasksublist[0],
            inside_value=0,
            outside_value=1,
            output_image=out_thresh_0 + ":uint8",
            lower_threshold=1,
            write_output=False)

        # Concatenate the zone image and the nodata one
        m_OrFilter2List.append(
            out_binary_threshold_ipedg_image_b1.getoutput()["out"])
        m_OrFilter2List.append(self._nodatamasksublist[0])
        l_NbBand = len(self._zonemasksublist)
        # band loop
        for l_band in range(l_NbBand - 1):
            out_thresh_1 = os.path.join(
                working_dir,
                "IPEDGThreshFilter1SubMask_{}.tif".format(l_band + 1))
            out_binary_threshold_ipedg_image = binary_threshold(
                input_image=self._zonemasksublist[l_band + 1],
                lower_threshold=1,
                inside_value=0,
                outside_value=1,
                output_image=out_thresh_1 + ":uint8",
                write_output=False)
            self._subedg_pipeline.add_otb_app(out_binary_threshold_ipedg_image)
            m_OrFilter2List.append(
                out_binary_threshold_ipedg_image.getoutput().get("out"))
            m_OrFilter2List.append(self._nodatamasksublist[l_band + 1])

        #OR filter
        out_edg = os.path.join(working_dir, "IPEDGubMask.tif")
        or_edg_sub_app = band_math_or(m_OrFilter2List,
                                      out_edg + ":uint8",
                                      write_output=True)
        # Allocation of 7 Go in S2 MUSCATE case
        self._edgsubmask = or_edg_sub_app.getoutput().get("out")
        self._subedg_pipeline.free_otb_app()
        LOGGER.debug("Start IPEDGSub done.")

        # *******************************************************************************************************
        # L2EDG pipeline connection
        # *******************************************************************************************************
        LOGGER.debug("Start L2EDG ...")

        l_BandsDefinitions = self._plugin.BandsDefinitions
        l_ListOfL2Resolution = l_BandsDefinitions.ListOfL2Resolution  # ListOfStrings
        # At L2 resolution
        l_NbL2Res = len(l_ListOfL2Resolution)

        for r in range(l_NbL2Res):
            res_str = l_ListOfL2Resolution[r]
            # Set 1000 to edge pixels to identify the pixel contaminated by an edge pixel after resampling
            out_thresh = os.path.join(working_dir,
                                      "EDGThreshL2_{}.tif".format(res_str))
            #m_L2EDGThreshold_app = binary_threshold(self._edgsubmask,
            #                                         lower_threshold=0,
            #                                         inside_value=0,
            #                                         outside_value=1000,
            #                                         output_image=out_thresh + ":uint8",
            #                                         write_output=False)
            #self._pipeline.add_otb_app(m_L2EDGThreshold_app)
            # ExpandFilterPointer => PadAndResampleImageFilter => app ressampling
            out_ressampling = os.path.join(
                working_dir, "IPEDGRealL2_{}.tif".format(res_str))
            resamp_app = resample(self._edgsubmask,
                                  self._dem.ALTList[r],
                                  out_ressampling + ":uint8",
                                  OtbResampleType.LINEAR,
                                  threshold=0.000001,
                                  write_output=False)
            self._pipeline.add_otb_app(resamp_app)

            # Set Threshold value to one because the expand filter interpolates values set to 0
            # or 1000 in the first threshold and adds systematically CONST_EPSILON to the output value.
            #m_L2EDGThresholdImage2_out = os.path.join(working_dir, "IPEDGMaskL2_{}.tif".format(res_str))
            #m_L2EDGThresholdImageApp2 = binary_threshold(
            #    resamp_app.getoutput().get("out"),
            #    lower_threshold=0.,
            #    inside_value=0,
            #    outside_value=1,
            #    output_image=m_L2EDGThresholdImage2_out + ":uint8",
            #    write_output=False)
            #self._pipeline.add_otb_app(m_L2EDGThresholdImageApp2)
            self._l2edgmasklist.append(resamp_app.getoutput().get("out"))

    def generate_l2_toa_images(self, working_dir):
        """
        :param working_dir:
        :return:
        """
        l_BandsDefinitions = self._plugin.BandsDefinitions
        l_ListOfL2Resolution = l_BandsDefinitions.ListOfL2Resolution  # ListOfStrings
        l_NbL2Res = len(l_ListOfL2Resolution)

        for l2res in range(l_NbL2Res):
            # Current resolution: "R1" or "R2"
            curRes = l_ListOfL2Resolution[l2res]

            # Get the list of band of the current resolution
            listOfL2Bands = l_BandsDefinitions.get_list_of_l2_band_code(curRes)
            nbBand = len(listOfL2Bands)
            list_of_image = []
            # For each band of the current resolution
            for l_StrBandIdL2 in listOfL2Bands:
                # Get the L1 band index associated to the L2 band code
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l_StrBandIdL2)
                # Generate the list of L2 TOA images per resolution
                list_of_image.append(self._toa_scalar_list[l1BandIdx])
            out_concatenate = os.path.join(
                working_dir, "L2TOAImageListVector_" + curRes + ".tif")
            param_concatenate = {"il": list_of_image, "out": out_concatenate}
            l2toa_concat_app = OtbAppHandler(
                "ConcatenateDoubleImages",
                param_concatenate,
                write_output=(False
                              or is_croco_on("sentinel2.l1reader.l2toa")))
            self._pipeline.add_otb_app(l2toa_concat_app)
            self._l2toaimagelist.append(
                l2toa_concat_app.getoutput().get("out"))

    def generate_sat_images(self, working_dir):
        """

        :return:
        """

        # *******************************************************************************************************
        # IPSAT Sub image pipeline connection
        # *******************************************************************************************************
        out_concatenate = os.path.join(working_dir, "SubSatVector.tif")
        param_concatenate = {
            "il": self._satmasksublist,
            "out": out_concatenate + ":uint8"
        }
        concat_app = OtbAppHandler("ConcatenateDoubleImages",
                                   param_concatenate)
        self._subsatimage = concat_app.getoutput().get("out")
        # *******************************************************************************************************
        # L2SAT image pipeline connection
        # *******************************************************************************************************
        l_BandsDefinitions = self._plugin.BandsDefinitions
        l_ListOfL2Resolution = l_BandsDefinitions.ListOfL2Resolution
        # At L2 resolution
        l_NbL2Res = len(l_ListOfL2Resolution)
        for i in range(l_NbL2Res):
            str_res = l_ListOfL2Resolution[i]
            out_concatenate = os.path.join(
                working_dir, "L2SATVector_{}.tif".format(str_res))
            param_concatenate = {
                "il": self._l2satimagelist[i],
                "out": out_concatenate + ":uint8"
            }
            sat_image = OtbAppHandler("ConcatenateDoubleImages",
                                      param_concatenate,
                                      write_output=False)
            self._pipeline.add_otb_app(sat_image)
            self._l2satmasklist.append(sat_image.getoutput().get("out"))

    def generate_cla_images(self, realL1Nodata, working):
        cla_filename = os.path.join(working, "cla_constant_sub.tif")
        cla_image = constant_image(self._dem.ALC,
                                   realL1Nodata,
                                   cla_filename,
                                   write_output=True).getoutput()["out"]
        self._claimage = cla_image

    @staticmethod
    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

    @staticmethod
    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

    # Get the shift between the detector index and the feature index in the MSK_DETFOO mask
    @staticmethod
    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
Ejemplo n.º 24
0
 def __init__(self):
     super(Sentinel2L1ImageFileReader, self).__init__()
     self._l2edg_pipeline = OtbPipelineManager()
     self._Satellite = "SENTINEL2"
     self._plugin = MajaSentinel2Plugin()
Ejemplo n.º 25
0
    def generate_edg_images_from_toa(self, listOfTOAImageFileNames, working):
        """

        :param listOfTOAImageFileNames: list
        :param working: path
        :return:
        """
        # Get the number of band with the number of TOA image files set in the input product directory
        l_NbBand = len(listOfTOAImageFileNames)  # int

        # *******************************************************************************************************
        # L2SubEDG pipeline connection
        # *******************************************************************************************************
        LOGGER.debug("Start IPEDGSub")
        m_OneBandFilterList = []
        m_ResamplingList = []
        m_OrFilterList = []
        tmp_edg_pipe = OtbPipelineManager()
        for i in range(2):
            toaFilename = listOfTOAImageFileNames[i]
            LOGGER.debug(("toaFilename : ", toaFilename))
            out_oneBandValue = os.path.join(working,
                                            "OneBandValue" + str(i) + ".tif")
            band_math_OneBand = one_band_equal_value(
                self._toa_scalar_list[i],
                output_image=out_oneBandValue + ":uint8",
                threshold=0.0,
                write_output=False)
            tmp_edg_pipe.add_otb_app(band_math_OneBand)
            m_OneBandFilterList.append(band_math_OneBand.getoutput()["out"])
            out_resample = os.path.join(working,
                                        "mask_resample" + str(i) + ".tif")
            resample_mask = resample(band_math_OneBand.getoutput()["out"],
                                     self._dem.ALC,
                                     out_resample + ":uint8",
                                     OtbResampleType.LINEAR_WITH_RADIUS,
                                     threshold=0.5,
                                     write_output=False)
            tmp_edg_pipe.add_otb_app(resample_mask)
            m_ResamplingList.append(resample_mask.getoutput()["out"])

        for i in range(l_NbBand - 2):
            out_oneBandValue = os.path.join(
                working, "OneBandValue" + str(i + 2) + ".tif")
            band_math_OneBand = one_band_equal_value(
                self._toa_scalar_list[i + 2],
                output_image=out_oneBandValue + ":uint8",
                threshold=0.0,
                write_output=False)
            tmp_edg_pipe.add_otb_app(band_math_OneBand)
            m_OneBandFilterList.append(band_math_OneBand.getoutput()["out"])

            out_resample = os.path.join(working,
                                        "mask_resample" + str(i + 2) + ".tif")
            resample_mask = resample(band_math_OneBand.getoutput()["out"],
                                     self._dem.ALC,
                                     out_resample + ":uint8",
                                     OtbResampleType.LINEAR_WITH_RADIUS,
                                     threshold=0.5,
                                     write_output=False)
            tmp_edg_pipe.add_otb_app(resample_mask)
            m_ResamplingList.append(resample_mask.getoutput()["out"])

        out_concat = os.path.join(working, "ConcatSubEdgOneBand.tif")
        param_oneband_concat = {
            "il": m_ResamplingList,
            "out": out_concat + ":uint8"
        }
        qoth_concat_app = OtbAppHandler("ConcatenateMaskImages",
                                        param_oneband_concat,
                                        write_output=False)
        tmp_edg_pipe.add_otb_app(qoth_concat_app)
        out_or0 = os.path.join(working, "MaskOrMask_0.tif")
        band_math_or_b1 = one_band_equal_value(
            qoth_concat_app.getoutput().get("out"),
            output_image=out_or0 + ":uint8",
            threshold=1)
        self._edgsubmask = band_math_or_b1.getoutput().get("out")
        tmp_edg_pipe.add_otb_app(band_math_or_b1)
        tmp_edg_pipe.free_otb_app()
        LOGGER.debug("End IPEDGSub.")

        # *******************************************************************************************************
        # L2EDG pipeline connection
        # *******************************************************************************************************
        LOGGER.debug("Start L2EDG ...")

        l_BandsDefinitions = self._plugin.BandsDefinitions
        LOGGER.debug("BANDS DEFINITION")
        LOGGER.debug(l_BandsDefinitions)

        l_ListOfL2Resolution = l_BandsDefinitions.ListOfL2Resolution  # ListOfStrings
        # At L2 resolution
        l_NbL2Res = len(l_ListOfL2Resolution)

        for r in range(l_NbL2Res):
            res_str = l_ListOfL2Resolution[r]
            # Set the threshold to 0.0.001 so that all pixel above 1/1000 to edge pixels
            # to identify the pixel contaminated by an edge pixel after resampling
            # ExpandFilterPointer => PadAndResampleImageFilter => app ressampling
            out_ressampling = os.path.join(
                working, "IPEDGRealL2_{}.tif".format(res_str))
            l2edg_resamp_app = resample(
                self._edgsubmask,
                self._dem.ALTList[r],
                out_ressampling + ":uint8",
                OtbResampleType.LINEAR,
                threshold=0.0,
                write_output=(False
                              or is_croco_on("sentinel2.l1reader.l2edg")))
            self._l2edg_pipeline.add_otb_app(l2edg_resamp_app)
            self._l2edgmasklist.append(l2edg_resamp_app.getoutput().get("out"))
        LOGGER.debug("End L2EDG ...")
Ejemplo n.º 26
0
class Sentinel2L1ImageFileReader(Sentinel2L1ImageFileReaderBase):
    def __init__(self):
        super(Sentinel2L1ImageFileReader, self).__init__()
        self._l2edg_pipeline = OtbPipelineManager()
        self._Satellite = "SENTINEL2"
        self._plugin = MajaSentinel2Plugin()

    def can_read(self, plugin_name):
        return plugin_name == "SENTINEL2"

    def generate_toa(self, listOfTOAImageFileNames,
                     reflectanceMultiplicationValues, working):
        """

        :param listOfTOAImageFileNames: ListOfStrings
        :param reflectanceMultiplicationValues: ListOfDoubles
        :return:
        :rtype: string
        """

        # Initialization
        l_ProjectionRef = ""

        # =======> GENERATE TOA CACHING
        l_ProjectionRef = self.generate_toa_caching(
            listOfTOAImageFileNames, reflectanceMultiplicationValues, working)

        LOGGER.debug("Caching TOA images done ...")

        return l_ProjectionRef

    def generate_edg_images_from_toa(self, listOfTOAImageFileNames, working):
        """

        :param listOfTOAImageFileNames: list
        :param working: path
        :return:
        """
        # Get the number of band with the number of TOA image files set in the input product directory
        l_NbBand = len(listOfTOAImageFileNames)  # int

        # *******************************************************************************************************
        # L2SubEDG pipeline connection
        # *******************************************************************************************************
        LOGGER.debug("Start IPEDGSub")
        m_OneBandFilterList = []
        m_ResamplingList = []
        m_OrFilterList = []
        tmp_edg_pipe = OtbPipelineManager()
        for i in range(2):
            toaFilename = listOfTOAImageFileNames[i]
            LOGGER.debug(("toaFilename : ", toaFilename))
            out_oneBandValue = os.path.join(working,
                                            "OneBandValue" + str(i) + ".tif")
            band_math_OneBand = one_band_equal_value(
                self._toa_scalar_list[i],
                output_image=out_oneBandValue + ":uint8",
                threshold=0.0,
                write_output=False)
            tmp_edg_pipe.add_otb_app(band_math_OneBand)
            m_OneBandFilterList.append(band_math_OneBand.getoutput()["out"])
            out_resample = os.path.join(working,
                                        "mask_resample" + str(i) + ".tif")
            resample_mask = resample(band_math_OneBand.getoutput()["out"],
                                     self._dem.ALC,
                                     out_resample + ":uint8",
                                     OtbResampleType.LINEAR_WITH_RADIUS,
                                     threshold=0.5,
                                     write_output=False)
            tmp_edg_pipe.add_otb_app(resample_mask)
            m_ResamplingList.append(resample_mask.getoutput()["out"])

        for i in range(l_NbBand - 2):
            out_oneBandValue = os.path.join(
                working, "OneBandValue" + str(i + 2) + ".tif")
            band_math_OneBand = one_band_equal_value(
                self._toa_scalar_list[i + 2],
                output_image=out_oneBandValue + ":uint8",
                threshold=0.0,
                write_output=False)
            tmp_edg_pipe.add_otb_app(band_math_OneBand)
            m_OneBandFilterList.append(band_math_OneBand.getoutput()["out"])

            out_resample = os.path.join(working,
                                        "mask_resample" + str(i + 2) + ".tif")
            resample_mask = resample(band_math_OneBand.getoutput()["out"],
                                     self._dem.ALC,
                                     out_resample + ":uint8",
                                     OtbResampleType.LINEAR_WITH_RADIUS,
                                     threshold=0.5,
                                     write_output=False)
            tmp_edg_pipe.add_otb_app(resample_mask)
            m_ResamplingList.append(resample_mask.getoutput()["out"])

        out_concat = os.path.join(working, "ConcatSubEdgOneBand.tif")
        param_oneband_concat = {
            "il": m_ResamplingList,
            "out": out_concat + ":uint8"
        }
        qoth_concat_app = OtbAppHandler("ConcatenateMaskImages",
                                        param_oneband_concat,
                                        write_output=False)
        tmp_edg_pipe.add_otb_app(qoth_concat_app)
        out_or0 = os.path.join(working, "MaskOrMask_0.tif")
        band_math_or_b1 = one_band_equal_value(
            qoth_concat_app.getoutput().get("out"),
            output_image=out_or0 + ":uint8",
            threshold=1)
        self._edgsubmask = band_math_or_b1.getoutput().get("out")
        tmp_edg_pipe.add_otb_app(band_math_or_b1)
        tmp_edg_pipe.free_otb_app()
        LOGGER.debug("End IPEDGSub.")

        # *******************************************************************************************************
        # L2EDG pipeline connection
        # *******************************************************************************************************
        LOGGER.debug("Start L2EDG ...")

        l_BandsDefinitions = self._plugin.BandsDefinitions
        LOGGER.debug("BANDS DEFINITION")
        LOGGER.debug(l_BandsDefinitions)

        l_ListOfL2Resolution = l_BandsDefinitions.ListOfL2Resolution  # ListOfStrings
        # At L2 resolution
        l_NbL2Res = len(l_ListOfL2Resolution)

        for r in range(l_NbL2Res):
            res_str = l_ListOfL2Resolution[r]
            # Set the threshold to 0.0.001 so that all pixel above 1/1000 to edge pixels
            # to identify the pixel contaminated by an edge pixel after resampling
            # ExpandFilterPointer => PadAndResampleImageFilter => app ressampling
            out_ressampling = os.path.join(
                working, "IPEDGRealL2_{}.tif".format(res_str))
            l2edg_resamp_app = resample(
                self._edgsubmask,
                self._dem.ALTList[r],
                out_ressampling + ":uint8",
                OtbResampleType.LINEAR,
                threshold=0.0,
                write_output=(False
                              or is_croco_on("sentinel2.l1reader.l2edg")))
            self._l2edg_pipeline.add_otb_app(l2edg_resamp_app)
            self._l2edgmasklist.append(l2edg_resamp_app.getoutput().get("out"))
        LOGGER.debug("End L2EDG ...")

    # Can read method
    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 GetViewingGrids(self, band, nbL1Bands, vieHRef, satFilename,
                        zoneFilenames, nodataFilename, listOfZone,
                        view_angle_col_step, view_angle_row_step,
                        viewing_angles_zenith, viewing_angles_azimuth,
                        working):
        LOGGER.debug("GetViewingGrids - Band: " + band)

        dtm_coarse = self._dem.ALC
        l_BandsDefinitions = self._plugin.BandsDefinitions
        l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(band)

        # ---- Viewing angle Grid --------------------------------------------------------------------
        l_VieAnglesGridList = []
        l_nbDetectors = len(viewing_angles_azimuth)
        # Detector loop
        LOGGER.debug("For each detectors (nb=%s) ...", l_nbDetectors)
        view_resamp_pipeline = OtbPipelineManager()
        for detId in range(len(viewing_angles_azimuth)):
            # Generate an image with the list of viewing angle values set in the header file
            det = listOfZone[detId]
            LOGGER.debug("ZenithViewingAngles for band " + band + " and det " +
                         det + " ,  nb values: " +
                         str(len(viewing_angles_zenith[detId])))
            LOGGER.debug(viewing_angles_zenith[detId])
            LOGGER.debug("AzimuthViewingAngles " + band + " and det " + det +
                         " nb values: " +
                         str(len(viewing_angles_azimuth[detId])))
            LOGGER.debug(viewing_angles_azimuth[detId])
            output_filename = "/tmp/internal_angles_test_{}_{}.xml".format(
                band, det)
            LOGGER.debug("Angles output_filename : %s", output_filename)
            writer = MajaInternalXmlInputAngles(viewing_angles_zenith[detId],
                                                viewing_angles_azimuth[detId],
                                                view_angle_col_step,
                                                view_angle_row_step,
                                                output_filename)
            writer.write()
            if not os.path.exists(output_filename):
                raise MajaExceptionPluginSentinel2Muscate(
                    "File does not exist " + output_filename)

            viewing_grid_filename = os.path.join(
                working, "viewing_grid_{}_{}.tif".format(det, band))

            # angle_list_to_image()
            viewing_angle_app = angle_list_to_image(dtm_coarse,
                                                    output_filename,
                                                    viewing_grid_filename,
                                                    extrapolation=False,
                                                    write_output=False)
            view_resamp_pipeline.add_otb_app(viewing_angle_app)
            # Expand at L2Coarse.
            viewing_grid_resamp_filename = os.path.join(
                working, "viewing_grid_resamp_{}_{}.tif".format(detId, band))
            viewing_grid_resamp_app = resample(
                viewing_angle_app.getoutput().get("out"),
                dtm_coarse,
                viewing_grid_resamp_filename,
                OtbResampleType.LINEAR,
                write_output=False)
            view_resamp_pipeline.add_otb_app(viewing_grid_resamp_app)
            # add images in a list
            l_VieAnglesGridList.append(
                viewing_grid_resamp_app.getoutput().get("out"))
            # end detector loop

        # Generate the angle images using the zone (detector) mask
        LOGGER.debug(
            "Start ConcatenatePerZoneVectorImageFilter for band id [" + band +
            "]...")

        # Concatenate all the detectors
        viewing_concat_filename = os.path.join(
            working, "viewing_concat_{}.tif".format(band))
        param_concat_perzone = {
            "mask": self._zonemasksublist[l1BandIdx],
            "il": l_VieAnglesGridList,
            "zonelist": listOfZone,
            "out": viewing_concat_filename
        }
        concat_perzone_app = OtbAppHandler("ConcatenatePerZone",
                                           param_concat_perzone,
                                           write_output=False)
        # Multiply by reference altitude
        viewing_grid_mult_filename = os.path.join(
            working, "viewing_grid_mult_{}.tif".format(band))
        param_scaled_solar = {
            "im": concat_perzone_app.getoutput().get("out"),
            "coef": float(vieHRef),
            "out": viewing_grid_mult_filename
        }
        view_scale_app = OtbAppHandler("MultiplyByScalar",
                                       param_scaled_solar,
                                       write_output=True)
        self._vieimagelist.append(view_scale_app.getoutput().get("out"))

        l_nbZones = len(listOfZone)
        LOGGER.debug("Start Loop for Zone (nb=" + str(l_nbZones) + ")...")
        for d in range(l_nbZones):
            l_zone = listOfZone[d]
            # -----------------------------------------------------------------------------------
            # Compute average values of zenithal and azimuthal angles grid per zone (detector in level1B)
            # -----------------------------------------------------------------------------------
            # VAP Reader connection (from ATB)
            tmp_azi = os.path.join(working,
                                   "tmp_azi_{}_{}.tif".format(band, l_zone))
            tmp_azi_image = extract_roi(l_VieAnglesGridList[d], [1],
                                        tmp_azi,
                                        write_output=False)
            param_stats = {
                "im": tmp_azi_image.getoutput().get("out"),
                "exclude": 1,
                "mask": self._zonemasksublist[l1BandIdx],
                "maskforeground": int(l_zone)
            }
            l2_stat = OtbAppHandler("Stats", param_stats)

            azi_mean = l2_stat.getoutput().get("mean")
            tmp_zen = os.path.join(working,
                                   "tmp_zen_{}_{}.tif".format(band, l_zone))
            tmp_zen_app = extract_roi(l_VieAnglesGridList[d], [0],
                                      tmp_zen,
                                      write_output=False)
            param_stats = {
                "im": tmp_zen_app.getoutput().get("out"),
                "exclude": 1,
                "mask": self._zonemasksublist[l1BandIdx],
                "maskforeground": int(l_zone)
            }
            l2_stat = OtbAppHandler("Stats", param_stats)
            zen_mean = l2_stat.getoutput().get("mean")
            tmp_mean = (zen_mean, azi_mean)
            l_ViewingAngleMean = grid_to_angle(tmp_mean)
            l_ViewingAngleMeanDeg = (l_ViewingAngleMean[0] * 180.0 / math.pi,
                                     l_ViewingAngleMean[1] * 180.0 / math.pi)
            # Add a vector to mean maps
            if l_zone not in self._meanZenithMap:
                self._meanZenithMap[listOfZone[d]] = []
            if l_zone not in self._meanAzimuthMap:
                self._meanAzimuthMap[listOfZone[d]] = []
            self._meanZenithMap[listOfZone[d]].append(
                str(l_ViewingAngleMeanDeg[0]))
            self._meanAzimuthMap[listOfZone[d]].append(
                str(l_ViewingAngleMeanDeg[1]))
            LOGGER.debug(" For BandId[" + str(band) + "], zone [" +
                         str(listOfZone[d]) + "]  . Mean 'GRID View angles'=" +
                         str(tmp_mean) + " . Mean 'View angles'=" +
                         str(l_ViewingAngleMean[0]) + ":" +
                         str(l_ViewingAngleMean[1]) + " rad. ou  " +
                         str(l_ViewingAngleMeanDeg[0]) + ":" +
                         str(l_ViewingAngleMeanDeg[1]) + " deg.")
        LOGGER.debug("Start Loop for Zone done.")
        view_resamp_pipeline.free_otb_app()
class ModuleAOTEstimationComputation(MajaModule):

    NAME = "AOTEstimation"

    def __init__(self):
        super(ModuleAOTEstimationComputation, self).__init__()
        self._aot_pipeline = OtbPipelineManager()

        self.in_keys_to_check = [
            "Params.Caching", "Params.WriteL2ProductToL2Resolution",
            "Params.DarkBandIndex_DateD", "Params.DarkBandIndex_DateD",
            "Params.AOTMethod", "Params.InitMode", "Params.MTAOTbandsDateD",
            "AppHandler", "Plugin", "L1Reader", "L2COMM", "DEM", "L2TOCR",
            "L2SITE"
        ]

        self.out_keys_to_check = ["AtmoAbsIPTOAC", "dtm_shd", "cr_lut"]
        self.out_keys_provided = ["AOT_Sub"]

    def cleanup(self):
        self._aot_pipeline.free_otb_app()

    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
class Sentinel2MuscateL1ImageFileReader(Sentinel2L1ImageFileReaderBase):
    def __init__(self):
        super(Sentinel2MuscateL1ImageFileReader, self).__init__()
        self._Satellite = "SENTINEL2"
        self._plugin = MajaSentinel2MuscatePlugin()
        self._toa_pipeline = OtbPipelineManager()
        self._l2_dfp_pipeline = OtbPipelineManager()
        self._l2_sat_pipeline = OtbPipelineManager()
        self._sub_sat_pipeline = OtbPipelineManager()
        self._l2_detf_pipeline = OtbPipelineManager()
        self._l2_zone_pipeline = OtbPipelineManager()
        self._l2_edg_pipeline = OtbPipelineManager()
        self.m_headerHandler = None
        self._band_zone_map = {}

    def can_read(self, plugin_name):
        return plugin_name == "SENTINEL2_MUSCATE"

    def generate_toa(self, listOfTOAImageFileNames,
                     reflectanceMultiplicationValues, working):
        """
        :param listOfTOAImageFileNames: ListOfStrings
        :param reflectanceMultiplicationValues: ListOfDoubles
        :return:
        :rtype: string
        """
        if len(reflectanceMultiplicationValues) != len(
                listOfTOAImageFileNames):
            raise MajaDataException(
                "Not the same number of band images and coefficients")
        # =======> GENERATE TOA CACHING
        l_ProjectionRef = self.generate_toa_caching(
            listOfTOAImageFileNames, reflectanceMultiplicationValues, working)
        LOGGER.debug("Caching TOA images done ...")
        return l_ProjectionRef

    def generate_sat_images(self, working_dir):
        """
        :return:
        """
        # *******************************************************************************************************
        # IPSAT Sub image pipeline connection
        # *******************************************************************************************************
        out_concatenate = os.path.join(working_dir, "SubSatVector.tif")
        param_concatenate = {
            "il": self._satmasksublist,
            "out": out_concatenate + ":uint8"
        }
        concat_app = OtbAppHandler("ConcatenateDoubleImages",
                                   param_concatenate)
        self._subsatimage = concat_app.getoutput().get("out")
        self._sub_sat_pipeline.free_otb_app()

    def generate_mask_rasters(self, satPixFileNames, defectivPixFileNames,
                              zoneMaskFileNames, noDataMaskFileNames,
                              p_ListOfTOABandCode, working):
        """

        :param satPixFileNames: ListOfStrings
        :param defectivPixFileNames: ListOfStrings
        :param zoneMaskFileNames: ListOfStrings
        :param noDataMaskFileNames: ListOfStrings
        :param p_ListOfTOABandCode: ListOfStrings
        :param working: string
        :return:
        """

        # *******************************************************************************************************
        # Generate mask rasters by rasterizing the gml mask per L2 resolution per band
        # *******************************************************************************************************
        LOGGER.info("Starting GenerateMaskRasters")

        l_BandsDefinitions = self._plugin.BandsDefinitions
        l2Area = None
        l_ListOfL2Resolution = l_BandsDefinitions.ListOfL2Resolution  # ListOfStrings
        l_NbL2Res = len(l_ListOfL2Resolution)
        l_ListOfL1Resolution = l_BandsDefinitions.ListOfL1Resolution  # ListOfStrings
        l_NbL1Res = len(l_ListOfL1Resolution)
        l_NbL1Band = len(defectivPixFileNames)
        dtm_coarse = self._dem.ALC

        # Set a constant image if the gml masks are empty
        tmp_constant_filename = os.path.join(working, "Masks_const.tif")
        #constant_image(dtm_coarse, 0, tmp_constant_filename, write_output=True)

        # Initialize the L2 Elements
        for l2res in range(l_NbL2Res):
            self._l2defectmasklist.append([])
            self._l2zonemasklist.append([])
            self._l2satimagelist.append([])
            self._l2dfpimagelist.append(None)
            self._l2zoneimagelist.append(None)
        # Init the coarse elements
        for coarseband in p_ListOfTOABandCode:
            self._satmasksublist.append(None)
            self._nodatamasksublist.append(None)
            self._zonemasksublist.append(None)
            self._l2satmasklist.append(None)

        # Loop on L1Res
        for l1res in range(l_NbL1Res):
            # Current resolution: "R1" or "R2" or "R3"
            curL1Res = l_ListOfL1Resolution[l1res]

            # Get the list of band of the current resolution
            listOfL1Bands = l_BandsDefinitions.get_list_of_l1_band_code(
                curL1Res)
            nbL1Bands = len(listOfL1Bands)
            # For each band of the current resolution
            l_l2zone_pipeline = OtbPipelineManager()
            firstBandIdx = l_BandsDefinitions.get_band_id_in_l1(
                listOfL1Bands[-1])

            # Verify if we can optimize the work if its the same file for all bands of
            # the resolution and if the bands are in correct bit order
            l_strDefectFileNameRef = defectivPixFileNames[firstBandIdx]
            l_isDefectSameFilesForBands = True
            l_strSatFileNameRef = satPixFileNames[firstBandIdx]
            l_isSatSameFilesForBands = True
            l_strNoDataFileNameRef = noDataMaskFileNames[firstBandIdx]
            l_isNoDataSameFilesForBands = True
            for l_BandIdxL1 in range(len(listOfL1Bands)):
                # Get the L1 band index associated to the L2 band code
                l_StrBandIdL1 = listOfL1Bands[l_BandIdxL1]
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l_StrBandIdL1)
                # Filenameverify
                if l_strDefectFileNameRef != defectivPixFileNames[l1BandIdx]:
                    l_isDefectSameFilesForBands = False
                if l_strSatFileNameRef != satPixFileNames[l1BandIdx]:
                    l_isSatSameFilesForBands = False
                if l_strNoDataFileNameRef != noDataMaskFileNames[l1BandIdx]:
                    l_isNoDataSameFilesForBands = False
            LOGGER.debug("l_isDefectSameFilesForBands = " +
                         str(l_isDefectSameFilesForBands))
            LOGGER.debug("l_isSatSameFilesForBands = " +
                         str(l_isSatSameFilesForBands))
            LOGGER.debug("l_isNoDataSameFilesForBands = " +
                         str(l_isSatSameFilesForBands))

            # Defective PIX (only in L2 resolution)
            if l_isDefectSameFilesForBands:
                if curL1Res in l_ListOfL2Resolution:
                    l_StrBandIdL1 = listOfL1Bands[0]
                    l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(
                        l_StrBandIdL1)
                    LOGGER.debug("l_StrBandIdL1 : ")
                    LOGGER.debug(l_StrBandIdL1)
                    self._l2piximagelist.append(
                        defectivPixFileNames[l1BandIdx])
                    dfp_mask = os.path.join(
                        working, "L1_DFP_Masks_{}.tif".format(curL1Res))
                    param_bintovec_dfp = {
                        "im": defectivPixFileNames[l1BandIdx],
                        "out": dfp_mask + ":uint8",
                        "nbcomp": nbL1Bands
                    }
                    dfp_mask_app = OtbAppHandler("BinaryToVector",
                                                 param_bintovec_dfp,
                                                 write_output=False)
                    self._l2_dfp_pipeline.add_otb_app(dfp_mask_app)
                    self._l2dfpimagelist[l_ListOfL2Resolution.index(
                        curL1Res)] = dfp_mask_app.getoutput().get("out")
            else:
                raise MajaExceptionPluginSentinel2Muscate(
                    "Product format not supported : not the same file for band on PIX"
                )

            # SAT Mask generation
            if l_isSatSameFilesForBands:
                # Sat Masks generation
                l_StrBandIdL1 = listOfL1Bands[0]
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l_StrBandIdL1)
                l_SATFFilename = satPixFileNames[l1BandIdx]
                sat_mask = os.path.join(working,
                                        "L1_SAT_Masks_{}.tif".format(curL1Res))
                param_bintovec_dfp = {
                    "im": l_SATFFilename,
                    "out": sat_mask + ":uint8",
                    "nbcomp": nbL1Bands
                }
                sat_mask_app = OtbAppHandler("BinaryToVector",
                                             param_bintovec_dfp,
                                             write_output=True)
                # self._l2_sat_pipeline.add_otb_app(sat_mask_app)
                if curL1Res in l_ListOfL2Resolution:
                    self._l2satmasklist[l_ListOfL2Resolution.index(
                        curL1Res)] = sat_mask_app.getoutput().get("out")
                tmp_sat_resample = os.path.join(
                    working,
                    "tmp_extract_roi_sat_resample_{}.tif".format(curL1Res))
                sat_resamp_app = resample(sat_mask_app.getoutput().get("out"),
                                          dtm_coarse,
                                          tmp_sat_resample,
                                          OtbResampleType.LINEAR,
                                          write_output=False)
                self._sub_sat_pipeline.add_otb_app(sat_resamp_app)
                for l1band in listOfL1Bands:
                    l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l1band)
                    tmp_sat_roi = os.path.join(
                        working, "tmp_extract_roi_sat_{}.tif".format(l1band))
                    tmp_sat_roi_app = extract_roi(
                        sat_resamp_app.getoutput().get("out"), [
                            self.m_headerHandler.get_l1_sat_image_index(
                                l1BandIdx) - 1
                        ],
                        tmp_sat_roi,
                        write_output=False)
                    self._sub_sat_pipeline.add_otb_app(tmp_sat_roi_app)
                    self._satmasksublist[
                        l1BandIdx] = tmp_sat_roi_app.getoutput().get("out")
            else:
                raise MajaExceptionPluginSentinel2Muscate(
                    "Product format not supported : not the same file for band on SAT"
                )

            # No_data mask at L2 coarse
            if l_isNoDataSameFilesForBands:
                ndt_mask = os.path.join(
                    working, "L2_NDT_VecMasks_{}.tif".format(curL1Res))
                l_StrBandIdL1 = listOfL1Bands[0]
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l_StrBandIdL1)
                l_NoDataFilename = noDataMaskFileNames[l1BandIdx]
                param_bintovec_ndt = {
                    "im": l_NoDataFilename,
                    "out": ndt_mask + ":uint8",
                    "nbcomp": nbL1Bands
                }
                ndt_mask_app = OtbAppHandler("BinaryToVector",
                                             param_bintovec_ndt,
                                             write_output=False)
                self._subedg_pipeline.add_otb_app(ndt_mask_app)
                tmp_ndt_resample = os.path.join(
                    working,
                    "tmp_extract_roi_ndt_resample_{}.tif".format(curL1Res))
                ndt_resamp_app = resample(ndt_mask_app.getoutput().get("out"),
                                          dtm_coarse,
                                          tmp_ndt_resample,
                                          OtbResampleType.LINEAR,
                                          write_output=False)
                self._subedg_pipeline.add_otb_app(ndt_resamp_app)
                for l1band in listOfL1Bands:
                    l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l1band)
                    tmp_ndt_roi = os.path.join(
                        working, "tmp_extract_roi_ndt_{}.tif".format(l1band))
                    tmp_ndt_roi_app = extract_roi(
                        ndt_resamp_app.getoutput().get("out"), [
                            self.m_headerHandler.get_l1_ndt_image_index(
                                l1BandIdx) - 1
                        ],
                        tmp_ndt_roi,
                        write_output=False)
                    self._subedg_pipeline.add_otb_app(tmp_ndt_roi_app)
                    self._nodatamasksublist[
                        l1BandIdx] = tmp_ndt_roi_app.getoutput().get("out")
            else:
                raise MajaExceptionPluginSentinel2Muscate(
                    "Product format not supported : not the same file for band on NoData"
                )

            # Detectors FootPrint Masks Generation
            # Get all the detectors files realted to this resolution
            # Test if they all refers to the same files
            tmp_res_det_filenames = None
            all_same_det_for_bands = True
            for l_BandIdxL1 in range(len(listOfL1Bands)):
                # Get the L1 band index associated to the L2 band code
                l_StrBandIdL1 = listOfL1Bands[l_BandIdxL1]
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l_StrBandIdL1)
                LOGGER.debug(
                    "Sentinel2MuscateL1ImageFileReader::GenerateMaskRasters: CurrentResol = %s, reading the "
                    "BandId L1 (associated) <%s> with index <%s>.", curL1Res,
                    l_StrBandIdL1, l1BandIdx)
                # Detectors FootPrint Masks
                l_bandDetFnames = zoneMaskFileNames[l1BandIdx]
                if tmp_res_det_filenames is not None:
                    if len(tmp_res_det_filenames) != len(l_bandDetFnames):
                        all_same_det_for_bands = False
                        break
                else:
                    tmp_res_det_filenames = l_bandDetFnames
            #Construct file and det number list
            tmp_list_of_detf_filenames = []
            tmp_list_of_detf_num = []
            tmp_list_of_band_idx = []
            if all_same_det_for_bands:
                l_ListOfZone = self.m_headerHandler.get_list_of_zones(
                    listOfL1Bands[0])
                nbDetector = len(l_ListOfZone)
                # For each detector of the current band
                for det in range(nbDetector):
                    tmp_list_of_detf_filenames.append(
                        tmp_res_det_filenames[l_ListOfZone[det]])
                    tmp_list_of_detf_num.append(str(int(l_ListOfZone[det])))
            else:
                #some bands are not in all det rare case
                tmp_det_info_map = {}
                for l_BandIdxL1 in range(len(listOfL1Bands)):
                    # Get the L1 band index associated to the L2 band code
                    l_StrBandIdL1 = listOfL1Bands[l_BandIdxL1]
                    l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(
                        l_StrBandIdL1)
                    LOGGER.debug(
                        "Sentinel2MuscateL1ImageFileReader::GenerateMaskRasters: CurrentResol = %s, reading the "
                        "BandId L1 (associated) <%s> with index <%s>.",
                        curL1Res, l_StrBandIdL1, l1BandIdx)
                    # Detectors FootPrint Masks
                    l_bandDetFnames = zoneMaskFileNames[l1BandIdx]
                    l_ListOfZone = self.m_headerHandler.get_list_of_zones(
                        l_StrBandIdL1)
                    nbDetector = len(l_ListOfZone)
                    # For each detector of the current band
                    for det in range(nbDetector):
                        det_num = l_ListOfZone[det]
                        if det_num not in tmp_det_info_map.keys():
                            tmp_det_info_map[det_num] = (
                                zoneMaskFileNames[l1BandIdx][det_num],
                                [0] * len(listOfL1Bands))
                        tmp_det_info_map[det_num][1][l_BandIdxL1] = \
                            self.m_headerHandler.get_l1_dtf_image_index(l1BandIdx, det_num)[0]
                #once the info map is done
                for det in tmp_det_info_map.keys():
                    det_info = tmp_det_info_map[det]
                    tmp_list_of_detf_filenames.append(det_info[0])
                    tmp_list_of_detf_num.append(str(int(det)))
                    for x in det_info[1]:
                        tmp_list_of_band_idx.append(str(x))
            #create params
            detf_mask = os.path.join(working,
                                     "L1_DETF_Masks_{}.tif".format(curL1Res))
            param_dispacth_zone = {
                "il": tmp_list_of_detf_filenames,
                "out": detf_mask + ':uint8',
                "nbcomp": len(listOfL1Bands),
                "outvals": tmp_list_of_detf_num
            }
            #handle not all det/band case
            if not all_same_det_for_bands:
                param_dispacth_zone["outindexes"] = tmp_list_of_band_idx
            #Call the app
            dispatch_app = OtbAppHandler("DispatchZonesToVector",
                                         param_dispacth_zone,
                                         write_output=True)
            #This is the L2 output
            if curL1Res in l_ListOfL2Resolution:
                self._l2zoneimagelist[l_ListOfL2Resolution.index(
                    curL1Res)] = dispatch_app.getoutput().get("out")
            #extract the coarse bands
            for l1band in listOfL1Bands:
                l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(l1band)
                tmp_zone_roi = os.path.join(
                    working, "tmp_extract_roi_ndt_{}.tif".format(l1band))
                tmp_zone_roi_app = extract_roi(
                    dispatch_app.getoutput().get("out"), [
                        self.m_headerHandler.get_l1_ndt_image_index(l1BandIdx)
                        - 1
                    ],
                    tmp_zone_roi,
                    write_output=False)
                self._subedg_pipeline.add_otb_app(tmp_zone_roi_app)
                tmp_zone_with_nodata = os.path.join(
                    working, "tmp_zone_with_nodata_{}".format(curL1Res))
                masterExpr = "( im1b1 > 0 ) ? im1b1 : -10000"
                param_bandmath_zone = {
                    "il": [tmp_zone_roi_app.getoutput().get("out")],
                    "exp": masterExpr,
                    "out": tmp_zone_with_nodata
                }
                zone_thresh_bandmath_app = OtbAppHandler("BandMathDouble",
                                                         param_bandmath_zone,
                                                         write_output=False)
                # LAIG-FA-MAC-1652-CNES : probleme reech detecteur en unsigned char : detecteur 1 devient 0.....
                tmp_zone_resample = os.path.join(
                    working,
                    "tmp_extract_roi_zone_resample_{}.tif".format(l1BandIdx))
                zone_resample_app = resample(
                    zone_thresh_bandmath_app.getoutput().get("out"),
                    dtm_coarse,
                    tmp_zone_resample,
                    OtbResampleType.LINEAR,
                    write_output=False)
                # threshold everything negative to 0
                Thresholdexpr = "im1b1 > 0 ? im1b1 : 0"
                tmp_zone_threshold = os.path.join(
                    working, "tmp_zone_threshold_{}".format(l1BandIdx))
                param_bandmath_zone_threshold = {
                    "il": [zone_resample_app.getoutput().get("out")],
                    "exp": Thresholdexpr,
                    "out": tmp_zone_threshold
                }
                zone_bandmath_threshold_app = OtbAppHandler(
                    "BandMathDouble",
                    param_bandmath_zone_threshold,
                    write_output=False)
                # Rounding
                tmp_zone_round = os.path.join(
                    working, "tmp_zone_round_{}".format(l1BandIdx))
                param_bandmath_zone_round = {
                    "im": zone_bandmath_threshold_app.getoutput().get("out"),
                    "out": tmp_zone_round
                }
                zone_round_app = OtbAppHandler("RoundImage",
                                               param_bandmath_zone_round,
                                               write_output=True)
                # Add to the official output
                self._zonemasksublist[l1BandIdx] = zone_round_app.getoutput(
                ).get("out")
                # Log current loop
                LOGGER.debug("band loop: " + str(l1BandIdx + 1) + " / " +
                             str(nbL1Bands) + " (" + curL1Res + ")")
            # band loop
            LOGGER.debug("band loop: END")
            self._l2_detf_pipeline.free_otb_app()

            # L2 Zone mask pipeline connection
            # if curL1Res in l_ListOfL2Resolution:
            #     l2_zone_image = os.path.join(working, "l2_zone_mask_{}.tif".format(curL1Res))
            #     param_l2zone_concatenate = {"il": self._l2zonemasklist[l_ListOfL2Resolution.index(curL1Res)],
            #                                 "out": l2_zone_image
            #                                 }
            #     l2_zone_app = OtbAppHandler("ConcatenateImages", param_l2zone_concatenate,write_output=True)
            #     self._l2zoneimagelist[l_ListOfL2Resolution.index(curL1Res)] = l2_zone_app.getoutput().get("out")

            # end res loop

    def GetViewingGrids(self, band, nbL1Bands, vieHRef, satFilename,
                        zoneFilenames, nodataFilename, listOfZone,
                        view_angle_col_step, view_angle_row_step,
                        viewing_angles_zenith, viewing_angles_azimuth,
                        working):
        LOGGER.debug("GetViewingGrids - Band: " + band)

        dtm_coarse = self._dem.ALC
        l_BandsDefinitions = self._plugin.BandsDefinitions
        l1BandIdx = l_BandsDefinitions.get_band_id_in_l1(band)

        # ---- Viewing angle Grid --------------------------------------------------------------------
        l_VieAnglesGridList = []
        l_nbDetectors = len(viewing_angles_azimuth)
        # Detector loop
        LOGGER.debug("For each detectors (nb=%s) ...", l_nbDetectors)
        view_resamp_pipeline = OtbPipelineManager()
        for detId in range(len(viewing_angles_azimuth)):
            # Generate an image with the list of viewing angle values set in the header file
            det = listOfZone[detId]
            LOGGER.debug("ZenithViewingAngles for band " + band + " and det " +
                         det + " ,  nb values: " +
                         str(len(viewing_angles_zenith[detId])))
            LOGGER.debug(viewing_angles_zenith[detId])
            LOGGER.debug("AzimuthViewingAngles " + band + " and det " + det +
                         " nb values: " +
                         str(len(viewing_angles_azimuth[detId])))
            LOGGER.debug(viewing_angles_azimuth[detId])
            output_filename = "/tmp/internal_angles_test_{}_{}.xml".format(
                band, det)
            LOGGER.debug("Angles output_filename : %s", output_filename)
            writer = MajaInternalXmlInputAngles(viewing_angles_zenith[detId],
                                                viewing_angles_azimuth[detId],
                                                view_angle_col_step,
                                                view_angle_row_step,
                                                output_filename)
            writer.write()
            if not os.path.exists(output_filename):
                raise MajaExceptionPluginSentinel2Muscate(
                    "File does not exist " + output_filename)

            viewing_grid_filename = os.path.join(
                working, "viewing_grid_{}_{}.tif".format(det, band))

            # angle_list_to_image()
            viewing_angle_app = angle_list_to_image(dtm_coarse,
                                                    output_filename,
                                                    viewing_grid_filename,
                                                    extrapolation=False,
                                                    write_output=False)
            view_resamp_pipeline.add_otb_app(viewing_angle_app)
            # Expand at L2Coarse.
            viewing_grid_resamp_filename = os.path.join(
                working, "viewing_grid_resamp_{}_{}.tif".format(detId, band))
            viewing_grid_resamp_app = resample(
                viewing_angle_app.getoutput().get("out"),
                dtm_coarse,
                viewing_grid_resamp_filename,
                OtbResampleType.LINEAR,
                write_output=False)
            view_resamp_pipeline.add_otb_app(viewing_grid_resamp_app)
            # add images in a list
            l_VieAnglesGridList.append(
                viewing_grid_resamp_app.getoutput().get("out"))
            # end detector loop

        # Generate the angle images using the zone (detector) mask
        LOGGER.debug(
            "Start ConcatenatePerZoneVectorImageFilter for band id [" + band +
            "]...")

        # Concatenate all the detectors
        viewing_concat_filename = os.path.join(
            working, "viewing_concat_{}.tif".format(band))
        param_concat_perzone = {
            "mask": self._zonemasksublist[l1BandIdx],
            "il": l_VieAnglesGridList,
            "zonelist": listOfZone,
            "out": viewing_concat_filename
        }
        concat_perzone_app = OtbAppHandler("ConcatenatePerZone",
                                           param_concat_perzone,
                                           write_output=False)
        # Multiply by reference altitude
        viewing_grid_mult_filename = os.path.join(
            working, "viewing_grid_mult_{}.tif".format(band))
        param_scaled_solar = {
            "im": concat_perzone_app.getoutput().get("out"),
            "coef": float(vieHRef),
            "out": viewing_grid_mult_filename
        }
        view_scale_app = OtbAppHandler("MultiplyByScalar",
                                       param_scaled_solar,
                                       write_output=True)
        self._vieimagelist.append(view_scale_app.getoutput().get("out"))

        l_nbZones = len(listOfZone)
        LOGGER.debug("Start Loop for Zone (nb=" + str(l_nbZones) + ")...")
        for d in range(l_nbZones):
            l_zone = listOfZone[d]
            # -----------------------------------------------------------------------------------
            # Compute average values of zenithal and azimuthal angles grid per zone (detector in level1B)
            # -----------------------------------------------------------------------------------
            # VAP Reader connection (from ATB)
            tmp_azi = os.path.join(working,
                                   "tmp_azi_{}_{}.tif".format(band, l_zone))
            tmp_azi_image = extract_roi(l_VieAnglesGridList[d], [1],
                                        tmp_azi,
                                        write_output=False)
            param_stats = {
                "im": tmp_azi_image.getoutput().get("out"),
                "exclude": 1,
                "mask": self._zonemasksublist[l1BandIdx],
                "maskforeground": int(l_zone)
            }
            l2_stat = OtbAppHandler("Stats", param_stats)

            azi_mean = l2_stat.getoutput().get("mean")
            tmp_zen = os.path.join(working,
                                   "tmp_zen_{}_{}.tif".format(band, l_zone))
            tmp_zen_app = extract_roi(l_VieAnglesGridList[d], [0],
                                      tmp_zen,
                                      write_output=False)
            param_stats = {
                "im": tmp_zen_app.getoutput().get("out"),
                "exclude": 1,
                "mask": self._zonemasksublist[l1BandIdx],
                "maskforeground": int(l_zone)
            }
            l2_stat = OtbAppHandler("Stats", param_stats)
            zen_mean = l2_stat.getoutput().get("mean")
            tmp_mean = (zen_mean, azi_mean)
            l_ViewingAngleMean = grid_to_angle(tmp_mean)
            l_ViewingAngleMeanDeg = (l_ViewingAngleMean[0] * 180.0 / math.pi,
                                     l_ViewingAngleMean[1] * 180.0 / math.pi)
            # Add a vector to mean maps
            if l_zone not in self._meanZenithMap:
                self._meanZenithMap[listOfZone[d]] = []
            if l_zone not in self._meanAzimuthMap:
                self._meanAzimuthMap[listOfZone[d]] = []
            self._meanZenithMap[listOfZone[d]].append(
                str(l_ViewingAngleMeanDeg[0]))
            self._meanAzimuthMap[listOfZone[d]].append(
                str(l_ViewingAngleMeanDeg[1]))
            LOGGER.debug(" For BandId[" + str(band) + "], zone [" +
                         str(listOfZone[d]) + "]  . Mean 'GRID View angles'=" +
                         str(tmp_mean) + " . Mean 'View angles'=" +
                         str(l_ViewingAngleMean[0]) + ":" +
                         str(l_ViewingAngleMean[1]) + " rad. ou  " +
                         str(l_ViewingAngleMeanDeg[0]) + ":" +
                         str(l_ViewingAngleMeanDeg[1]) + " deg.")
        LOGGER.debug("Start Loop for Zone done.")
        view_resamp_pipeline.free_otb_app()

    # Can read method

    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
Ejemplo n.º 30
0
class DEMBase(object):
    def __init__(self):
        self.ALTList = []
        self.ALT_Mean = 0
        self.ALT_Min = 0
        self.ALT_Max = 0
        self.ALT_Stdv = 0
        self.ALT_LogicalName = ""
        self.__ASPListInternal = []
        self.ASPList = []
        self.__SLPListInternal = []
        self.SLPList = []
        self.ALC = ""
        self.MSK = ""
        self.ASC = None
        self.__SLCInternal = ""
        self.SLC = ""
        self.Satellite = ""
        self._coeff = 0.01
        self._resList = []
        self._expr = "im1b1 * "
        self.CoarseArea = None
        self.L2Areas = []
        self.ProjRef = ""
        self.ProjCode = ""
        self.ProjType = ""
        self.ProjName = ""
        self.Site = ""
        self._apps = OtbPipelineManager()

    def initialize(self, filename, working_dir, has_snow):
        file_hdr = os.path.splitext(filename)[0] + ".HDR"
        file_dbl = os.path.splitext(filename)[0] + ".DBL"
        file_dbldir = os.path.splitext(filename)[0] + ".DBL.DIR"
        LOGGER.info("AUX_REFDE2 filename: " + filename)
        # uncompress dbl
        uncompress_dbl_product(file_dbl)

        # DEM filenames provider
        list_of_file = os.listdir(file_dbldir)
        nbresol = 0
        for f in list_of_file:
            if "_ALT" in f and "TIF" in os.path.splitext(f)[1]:
                nbresol = nbresol + 1
        LOGGER.info("Nb resolution found " + str(nbresol))
        self.initialize_res_list(nbresol)

        LOGGER.info(
            "DEMFilenamesProvider::Initialize. Nb resolution computed:" +
            str(len(self._resList)))
        for resol in self._resList:
            LOGGER.debug("DEMFilenamesProvider::Initialize. Prefix resol : " +
                         resol)

        handler = EarthExplorerXMLFileHandler(file_hdr)
        list_of_dbl_files = handler.get_list_of_packaged_dbl_files(True, False)
        LOGGER.info("DEMFileNames found " + str(len(list_of_dbl_files)) +
                    " files")

        for i in range(0, len(list_of_dbl_files)):
            if list_of_dbl_files[i].split('.TIF')[-1]:
                raise MajaDataException(
                    "Wrong file extension detected. Delete the file: " +
                    str(list_of_dbl_files[i]))

        # --------------------------------------
        # Find the correct filename
        for fi in list_of_dbl_files:
            # LAIG - FA - MAC - 1610 - CNES
            # ../ CONTEXTES_ANOMALIES / TMA_VENUS_maccs_errors / 4398 / VE_TEST_AUX_REFDE2_BRASCHAT_0001.DBL.DIR / VE_TEST_AUX_REFDE2_BRASCHAT_0001_SLP.TIF
            # Extract the last value -> SLP
            # ../ CONTEXTES_ANOMALIES / TMA_VENUS_maccs_errors / 4398 / VE_TEST_AUX_REFDE2_BRASCHAT_0001.DBL.DIR / VE_TEST_AUX_REFDE2_BRASCHAT_0001_ALT_R1.TIF
            # Extract the last value -> ALT
            l_splitted = (os.path.splitext(os.path.basename(fi))[0]).split("_")
            l_lenghtlistfilenamename = len(l_splitted)
            # Extract the tow last values -> ex: 0001 _SLP or ALT_R1
            l_keytype = l_splitted[-1]
            if l_lenghtlistfilenamename > 2:
                l_keytype = l_splitted[-2] + "_" + l_keytype
            # --------------------------------------
            # Test if the filename is ALC
            if "ALC" in l_keytype:
                self.ALC = fi
            # --------------------------------------
            # Test if the filename is MSK
            elif "MSK" in l_keytype:
                self.MSK = fi
            # --------------------------------------
            # Test if the filename is ASC
            elif "ASC" in l_keytype:
                self.ASC = fi
            # --------------------------------------
            # Test if the filename is SLC
            elif "SLC" in l_keytype:
                self.__SLCInternal = fi
            else:
                # --------------------------------------
                # Lop under resolutions
                for res in self._resList:
                    # --------------------------------------
                    # Test if the filename is SLP
                    if "SLP" in l_keytype:
                        if res in l_keytype:
                            self.__SLPListInternal.append(fi)
                    # --------------------------------------
                    # Test if the filename is ALT
                    elif "ALT" in l_keytype:
                        if res in l_keytype:
                            self.ALTList.append(fi)
                    # --------------------------------------
                    # Test if the filename is ASP
                    elif "ASP" in l_keytype:
                        if res in l_keytype:
                            self.__ASPListInternal.append(fi)
                    else:
                        LOGGER.debug(
                            "Unknown Filename and associated product type.")
                # endloop resol
        # --------------------------------------
        # Check existent of ALC filename
        if not os.path.exists(self.ALC):
            raise MajaDataException("The ALC file '" + self.ALC +
                                    "' of the DTM doesn't exist !")

        # --------------------------------------
        # Check existent of MSK filename
        if not os.path.exists(self.MSK):
            raise MajaDataException("The MSK file '" + self.MSK +
                                    "' of the DTM doesn't exist !")

        # --------------------------------------
        # Check existent of SLC filename
        if not os.path.exists(self.__SLCInternal):
            raise MajaDataException("The SLC file '" + self.__SLCInternal +
                                    "' of the DTM doesn't exist !")
        else:
            LOGGER.debug("Starting multiply " + self.__SLCInternal + " * " +
                         str(self._coeff))
            self.SLC = os.path.join(
                working_dir, "Mul_" + os.path.basename(self.__SLCInternal))
            self._apps.add_otb_app(
                multiply_by_scalar(self.__SLCInternal,
                                   self._coeff,
                                   output_image=self.SLC))
            mtdat = GdalDatasetInfo(self.__SLCInternal)
            self.CoarseArea = Area()
            self.CoarseArea.size = mtdat.size
            self.CoarseArea.origin = mtdat.origin
            self.CoarseArea.spacing = mtdat.pixel_size
            LOGGER.debug("Done")

        # --------------------------------------
        for resol in range(0, len(self._resList)):
            # --------------------------------------
            # Check existent of SLP filename
            if not os.path.exists(self.__SLPListInternal[resol]):
                raise MajaDataException("One of the SLP file '" +
                                        self.__SLPListInternal[resol] +
                                        "' of the DTM doesn't exist !")
            else:
                LOGGER.debug("Starting multiply " +
                             self.__SLPListInternal[resol] + " * " +
                             str(self._coeff))
                tmp = os.path.join(
                    working_dir,
                    "Mul_" + os.path.basename(self.__SLPListInternal[resol]))
                slp_mul_app = multiply_by_scalar(self.__SLPListInternal[resol],
                                                 self._coeff,
                                                 output_image=tmp,
                                                 write_output=False)
                self._apps.add_otb_app(slp_mul_app)
                mtdat = GdalDatasetInfo(self.__SLPListInternal[resol])
                l2area = Area()
                l2area.size = mtdat.size
                l2area.origin = mtdat.origin
                l2area.spacing = mtdat.pixel_size
                self.ProjRef = mtdat.dataset.GetProjectionRef()
                self.L2Areas.append(l2area)
                LOGGER.debug("Done")
                self.SLPList.append(slp_mul_app.getoutput().get("out"))
            # --------------------------------------
            # Check existent of ALT filename
            if not os.path.exists(self.ALTList[resol]):
                raise MajaDataException("One of the ALT file '" +
                                        self.ALTList[resol] +
                                        "' of the DTM doesn't exist !")
            # --------------------------------------
            # Check existent of ASP filename
            if not os.path.exists(self.__ASPListInternal[resol]):
                raise MajaDataException("One of the ASP file '" +
                                        self.__ASPListInternal[resol] +
                                        "' of the DTM doesn't exist !")
            else:
                LOGGER.debug("Starting multiply " +
                             self.__ASPListInternal[resol] + " * " +
                             str(self._coeff))
                tmp = os.path.join(
                    working_dir,
                    "Mul_" + os.path.basename(self.__ASPListInternal[resol]))
                asp_mul_app = multiply_by_scalar(self.__ASPListInternal[resol],
                                                 self._coeff,
                                                 output_image=tmp,
                                                 write_output=False)
                self._apps.add_otb_app(asp_mul_app)
                LOGGER.debug("Done")
                self.ASPList.append(asp_mul_app.getoutput().get("out"))

        # end loop resol

        LOGGER.debug(nbresol)

        l_cartoCode = xml_tools.get_only_value(
            handler.root,
            "//DEM_Information/Cartographic/Coordinate_Reference_System/Code",
            namespaces=handler.nss,
            check=True)
        l_geoCode = xml_tools.get_only_value(
            handler.root,
            "//DEM_Information/Geographic/Coordinate_Reference_System/Code",
            namespaces=handler.nss,
            check=True)
        if l_cartoCode is not None:
            self.ProjCode = l_cartoCode.text
            self.ProjType = "PROJECTED"
        elif l_geoCode is not None:
            self.ProjCode = l_geoCode.text
            self.ProjType = "GEOGRAPHIC"
        else:
            raise MajaDataException("Unknown DEM type")

        LOGGER.debug("DEM Projection Code: " + self.ProjCode)
        LOGGER.debug("DEM Projection Type: " + self.ProjType)

        self.Site = xml_tools.get_xml_string_value(
            handler.root,
            "//Specific_Product_Header/Instance_Id/Applicable_Site_Nick_Name",
            namespaces=handler.nss)

        if nbresol != 0:
            param_stats = {"im": self.ALTList[0]}
            stat_app = stats(self.ALTList[0])
            self.ALT_Mean = stat_app.getoutput().get("mean")
            self.ALT_Max = stat_app.getoutput().get("max")
            self.ALT_Min = stat_app.getoutput().get("min")
            self.ALT_Stdv = stat_app.getoutput().get("stdv")
            self.ALT_LogicalName = "LOCAL=" + os.path.splitext(
                os.path.basename(file_hdr))[0]
            LOGGER.info("DEM Mean : " + str(self.ALT_Mean))
            LOGGER.info("DEM Max : " + str(self.ALT_Max))
            LOGGER.info("DEM Min : " + str(self.ALT_Min))
            LOGGER.info("DEM Stdv : " + str(self.ALT_Stdv))

    def initialize_res_list(self, nb_resol):
        if nb_resol <= 1:
            self._resList.append("")
        else:
            for i in range(0, nb_resol):
                self._resList.append("_R" + str(i + 1))

    def __del__(self):
        self._apps.free_otb_app()