def test_object_write(self): """ Test the initialisation of the object """ maja_object = MajaInternalXmlInputAngles(self.values_1, self.values_2, self.col_step, self.row_step, self.output_filename) maja_object.write()
def write(self, output_directory): """ Write in a internal xml format file """ output_filename = os.path.join(output_directory, "sun_angles.xml") LOGGER.debug("Angles output_filename : %s", output_filename) writer = MajaInternalXmlInputAngles( self.zenith_angle_list_string_values, self.azimuth_angle_list_string_values, self.col_step, self.row_step, output_filename) writer.write() return output_filename
def write(self, output_directory): """ Write in a internal xml format file """ output_filename = os.path.join( output_directory, "viewing_incidence_angle_b%s_d%s_" % (self.band_id, self.detector_id) + ".xml") LOGGER.debug("Angles output_filename : %s", output_filename) writer = MajaInternalXmlInputAngles(self.zenith_values, self.azimuth_values, self.col_step, self.row_step, output_filename) writer.write() return output_filename
def test_save_view_angles(self): self.maja_object = MuscateXMLFileHandler(self.xml_filename) view_angle_col_step = int( self.maja_object.get_string_value_of("SunAngleColStep")) view_angle_row_step = -1 * int( self.maja_object.get_string_value_of("SunAngleRowStep")) # ATTENTION : * -1 for compatibility negative spacing l_ListOfTOABandCode = self.maja_object.get_list_of_band_code( ) # ListOfStrings for l_band in l_ListOfTOABandCode: # Get the list of detectors (index) l_ListOfZone = self.maja_object.get_list_of_zones(l_band) LOGGER.debug("List of zone : ") LOGGER.debug(l_ListOfZone) # Get the list of viewing angles in the header file of the tile l_zenithVieAngles = self.maja_object.get_viewing_zenithal_angles( l_band) l_azimuthVieAngles = self.maja_object.get_viewing_azimuthal_angles( l_band) if len(l_zenithVieAngles) != len(l_azimuthVieAngles): raise Exception( "The number of detector for viewing zenithal angles and viewing azimuthal angles is different or null !" ) for detId in range(len(l_ListOfZone)): det = l_ListOfZone[detId] LOGGER.debug(("ZenithViewingAngles for band " + l_band + " and det " + det + " , nb values: " + str(len(l_zenithVieAngles[detId])))) LOGGER.debug(l_zenithVieAngles[detId]) LOGGER.debug( ("AzimuthViewingAngles " + l_band + " and det " + det + " nb values: " + str(len(l_azimuthVieAngles[detId])))) LOGGER.debug(l_azimuthVieAngles[detId]) output_filename = "/tmp/internal_angles_test_{}_{}.xml".format( l_band, det) LOGGER.debug(("Angles output_filename : %s", output_filename)) writer = MajaInternalXmlInputAngles(l_zenithVieAngles[detId], l_azimuthVieAngles[detId], view_angle_col_step, view_angle_row_step, output_filename) writer.write() self.assertTrue(os.path.exists(output_filename), "File does not exist " + output_filename)
def test_object(self): """ Test the initialisation of the object """ maja_object = MajaInternalXmlInputAngles(self.values_1, self.values_2, self.col_step, self.row_step, self.output_filename) self.assertIsNotNone(maja_object)
def test_save_sun_angles(self): self.maja_object = MuscateXMLFileHandler(self.xml_filename) sun_angle_col_step = int( self.maja_object.get_string_value_of("SunAngleColStep")) sun_angle_row_step = -1 * int( self.maja_object.get_string_value_of("SunAngleRowStep")) # ATTENTION : * -1 for compatibility negative spacing l_zenithSolarAngles = self.maja_object.get_sun_zenithal_angles() l_azimuthSolarAngles = self.maja_object.get_sun_azimuthal_angles() LOGGER.debug( ("ZenithSolarAngles nb values: " + str(len(l_zenithSolarAngles)))) LOGGER.debug(("AzimuthSolarAngles nb values: " + str(len(l_azimuthSolarAngles)))) LOGGER.debug(("Angles output_filename : %s", self.output_filename)) writer = MajaInternalXmlInputAngles(l_zenithSolarAngles, l_azimuthSolarAngles, sun_angle_col_step, sun_angle_row_step, self.output_filename) writer.write() self.assertTrue(os.path.exists(self.output_filename), "File does not exist")
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
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()