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()
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()
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()
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()
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 __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()
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)
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)
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
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
def __init__(self): super(Sentinel2L1ImageFileReader, self).__init__() self._l2edg_pipeline = OtbPipelineManager() self._Satellite = "SENTINEL2" self._plugin = MajaSentinel2Plugin()
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 ...")
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
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()