def test_granule_xml_file_getter(self): """ Test of the method granule_xml_file """ self.maja_oject = MajaSentinel2L1MainXmlReader(self.input_product_mtd) self.assertEqual(os.path.basename(self.maja_oject.granule_xml_file), A_PRODUCT_S2_L1.get("granule_xml_basename"))
def test_granule(self): """ Assertion on the extracted granule name TODO: create a general test for a general function extract_info which should return a {} """ self.maja_oject = MajaSentinel2L1MainXmlReader(self.input_product_mtd) self.assertEqual(self.maja_oject.granule_id, A_PRODUCT_S2_L1.get("granule_id")) self.assertEqual(self.maja_oject.granule_id, A_PRODUCT_S2_L1.get("granule_id"))
def detect_l1_products(self, input_directory, product_list, tile_id=None): LOGGER.info("Start Sentinel2 L1 DetectL1Products in " + input_directory) """ LAIG - FA - MAC - 1482 - CNES Example of the header filename of the S2 L1C product PSD < 14 -> S2A_OPER_PRD_MSIL1C_PDMC_20150507T132817_R065_V20091211T165913_20091211T165959.SAFE / S2A_OPER_MTD_SAFL1C_PDMC_20150507T132817_R065_V20091211T165913_20091211T165959.xml Example of the header filename of the S2 L1C product PSD >= 14 -> L1C_T36JTT_A006424_20160914T081456 / MTD_TL.xml Get the list of subdirectories of the input product""" listOfSubDirectories = maja_get_subdirectories(input_directory) # For each directory for dir in listOfSubDirectories: # Get this name: S2A_OPER_PRD_MSIL1C_PDMC_20150507T132817_R065_V20091211T165913_20091211T165959.SAFE l_ShortDirectoryFilename = os.path.basename(dir) LOGGER.info("Short dirfilename : " + l_ShortDirectoryFilename) # PSD < 14: Detect S2A or S2B, MSIL1C and the extension SAFE # PSD >= 14: Detect L1C_T if "_MSIL1C_" in l_ShortDirectoryFilename and ( "S2A_" in l_ShortDirectoryFilename or "S2B_"in l_ShortDirectoryFilename) and ".SAFE" in l_ShortDirectoryFilename: # Get the list of files in the current subdirectory listOfFilenames = [ os.path.join( dir, f) for f in os.listdir(dir) if os.path.isfile( os.path.join( dir, f))] for fi in listOfFilenames: l_ShortFilename = os.path.basename(fi) LOGGER.info("Short filename : " + l_ShortFilename) # Detect the file type of the xml header file only for user product SAFE formatted # PSD < 14: _MTD_SAFL1C_ -- > Not supported # PSD >= 14: MTD_TL if (("MTD_MSIL1C" in l_ShortFilename) or ("_MTD_SAFL1C" in l_ShortFilename)) \ and os.path.splitext(l_ShortFilename)[1] == ".xml": # Load the xml header file and get the satellite l_CanLoad = xml_tools.can_load_file(fi) if l_CanLoad: try: s2xml = MajaSentinel2L1MainXmlReader(fi,tile_id=tile_id) if s2xml.satellite_name == "Sentinel-2A" or s2xml.satellite_name == "Sentinel-2B": product_list.append(fi) LOGGER.info("Append " + fi) except Exception as e: LOGGER.debug("Not compatible with SENTINEL2") LOGGER.debug(e)
def test_object(self): """ Assert the initialization of the object do not fail """ self.maja_oject = MajaSentinel2L1MainXmlReader(self.input_product_mtd) self.assertIsNotNone(self.maja_oject)
def initialize(self, product_filename, validate=False, schema_path=None, tile_id=None): self.ProductFileName = product_filename self.PluginName = "SENTINEL2" LOGGER.info("Start Sentinel2 L1 ImageInformationProvider " + product_filename + "...") # detect correctly formatted if (("_MTD_SAFL1C_" not in product_filename and "MTD_MSIL1C" not in product_filename) or os.path.splitext(product_filename)[1] != ".xml"): return False try: headerHandler = MajaSentinel2L1MainXmlReader(product_filename, validate, schema_path,tile_id=tile_id) except Exception as e: LOGGER.info(e) return False self.HeaderHandler = headerHandler self.Satellite = headerHandler.satellite_name.upper() self.SatelliteID = self.Satellite.upper().replace("-","") self.UniqueSatellite = "SENTINEL-2_" self.LevelType = "L1VALD" self.FileCategory = "SSC" granule_id_split = headerHandler.granule_id.split("_") self.FileClass = granule_id_split[1] self.HeaderFilename = headerHandler.main_xml_file self.Prefix = granule_id_split[0] self.L1NoData = headerHandler.get_no_data() self.ReflectanceQuantification = 1.0 / headerHandler.quantification_value self.RealL1NoData = self.L1NoData * self.ReflectanceQuantification self.xmlTileFilename = headerHandler.XmlTileFileName LOGGER.info("Tile xml filename : " + self.xmlTileFilename) tile_handler = MajaSentinel2L1GranuleXmlReader(self.xmlTileFilename) self.TileHandler = tile_handler LOGGER.debug("TileId: " + self.HeaderHandler.TileId) self.Site = maja_utils.get_formated_site(self.HeaderHandler.TileId) self.TileHandler.TileId = self.Site self.ProductDate = date_utils.get_datetime_from_utc("UTC=" + tile_handler.sensing_time) self.ProductDateStr = self.ProductDate.strftime('%Y%m%d') LOGGER.debug("Product Date: " + self.ProductDateStr) self.ProductId = headerHandler.get_string_value_of("ProductURI") LOGGER.debug("ProductID: "+self.ProductId) self.GenerationDateStr = headerHandler.get_string_value_of("GenerationTime") self.AcquisitionStart = headerHandler.get_string_value_of("ProductStartTime") self.OrbitNumber = headerHandler.get_string_value_of("OrbitNumber") l_datastrip_split = tile_handler.datastrip_id.split("_") l_start_date_str = l_datastrip_split[-3] l_stop_date_str = l_datastrip_split[-2][1:] l_start_date_time = date_utils.get_datetime_from_yyyymmddthhmmss(l_start_date_str) l_stop_date_time = date_utils.get_datetime_from_yyyymmddthhmmss(l_stop_date_str) self.UTCValidityStart = date_utils.get_utc_from_datetime(l_start_date_time) LOGGER.debug("UTCValidityStart : " + self.UTCValidityStart) self.UTCValidityStop = date_utils.get_utc_from_datetime(l_stop_date_time) LOGGER.debug("UTCValidityStop : " + self.UTCValidityStop) self.ReferenceSiteDefinitionId = "UNKNOWN" # Not available in S2 self.SOLHeaderFileName = "" self.SOLImageFileName = "" self.VIEHeaderFileName = "" self.VIEImageFileName = "" self.ListOfViewingAnglesPerBandAtL2Resolution = [] self.ListOfViewingAnglesPerBandAtL2CoarseResolution = [] self.ListOfViewingZenithAnglesPerBandAtL2CoarseResolution = [] self.ListOfViewingAzimuthAnglesPerBandAtL2CoarseResolution = [] l_MeanViewingZenithalAngles = [] l_MeanViewingAzimuthalAngles = [] for f in range(0, len(tile_handler.angles.viewing_incidence_angle.incidence_angles_mean)): angles = tile_handler.angles.viewing_incidence_angle.incidence_angles_mean[str(f)] self.ListOfViewingAnglesPerBandAtL2CoarseResolution.append(angles) self.ListOfViewingZenithAnglesPerBandAtL2CoarseResolution.append(angles["incidence_zenith_angle"]) self.ListOfViewingAzimuthAnglesPerBandAtL2CoarseResolution.append(angles["incidence_azimuth_angle"]) l_MeanViewingZenithalAngles.append(float(angles["incidence_zenith_angle"])) l_MeanViewingAzimuthalAngles.append(float(angles["incidence_azimuth_angle"])) self.ViewingAngle = { "incidence_zenith_angle": str(statistics.mean(l_MeanViewingZenithalAngles)), "incidence_azimuth_angle": str(statistics.mean(l_MeanViewingAzimuthalAngles)) } l_bandsdefinition = MajaSentinel2Plugin().BandsDefinitions l_nbRes = len(l_bandsdefinition.ListOfL2Resolution) for r in range(0, l_nbRes): l_res = l_bandsdefinition.ListOfL2Resolution[r] l_l2bandcodes = l_bandsdefinition.get_list_of_l2_band_code(l_res) l_l2bandidx = [l_bandsdefinition.get_band_id_in_l2_coarse(b) for b in l_l2bandcodes] for b in l_l2bandidx: self.ListOfViewingAnglesPerBandAtL2Resolution.append( self.ListOfViewingAnglesPerBandAtL2CoarseResolution[b]) self.ViewingAngleGrids = [] for grid in tile_handler.angles.viewing_incidence_angle.list_of_viewing_angles_grid: self.ViewingAngleGrids.append({ "StepUnit":grid.step_unit, "ColStep":grid.col_step, "RowStep":grid.row_step, "Band":grid.band_id, "Detector":grid.detector_id, "Azimuth":grid.azimuth_values, "Zenith":grid.zenith_values }) self.SolarAngle = tile_handler.angles.sun_angles.sun_angles_mean self.SolarAngleGrid["StepUnit"] = tile_handler.angles.sun_angles.step_unit self.SolarAngleGrid["ColStep"] = tile_handler.angles.sun_angles.col_step self.SolarAngleGrid["RowStep"] = tile_handler.angles.sun_angles.row_step self.SolarAngleGrid["Azimuth"] = tile_handler.angles.sun_angles.azimuth_angle_list_string_values self.SolarAngleGrid["Zenith"] = tile_handler.angles.sun_angles.zenith_angle_list_string_values # Area by resolution self.AreaByResolution = [] for res in l_bandsdefinition.ListOfL2Resolution: res_m = l_bandsdefinition.get_l1_resolution(res) l_ul = tile_handler.get_geoposition_upperleftcorner(res_m) l_spa = tile_handler.get_geoposition_dims(res_m) l_size = tile_handler.get_size(res_m) curArea = Area() curArea.origin = ( str(l_ul.x), str(l_ul.y)) curArea.spacing = ( str(l_spa.x), str(l_spa.y)) curArea.size = ( str(l_size.x), str(l_size.y)) self.AreaByResolution.append(curArea) # Spectral information self.SpectralInfo = [] l_pathGain = "//Product_Image_Characteristics/PHYSICAL_GAINS[@bandId='{}']" l_pathRadiance = "//Solar_Irradiance_List/SOLAR_IRRADIANCE[@bandId='{}']" l_pathWavelength = "//Spectral_Information_List/Spectral_Information[@bandId='{}']/Wavelength/{}" l_pathResponse = "//Spectral_Information_List/Spectral_Information[@bandId='{}']/Spectral_Response/{}" for b, bidx in l_bandsdefinition.L1BandMap.items(): self.SpectralInfo.append({ "Band":b, "PhysicalGain":float(headerHandler.get_string_value(l_pathGain.format(bidx))), "SolarIrradiance":headerHandler.get_string_value(l_pathRadiance.format(bidx)), "WavelengthMin":headerHandler.get_string_value(l_pathWavelength.format(bidx, "MIN")), "WavelengthMax":headerHandler.get_string_value(l_pathWavelength.format(bidx, "MAX")), "WavelengthCentral":headerHandler.get_string_value(l_pathWavelength.format(bidx, "CENTRAL")), "ResponseStep":headerHandler.get_string_value(l_pathResponse.format(bidx, "STEP")), "ResponseValues":headerHandler.get_string_value(l_pathResponse.format(bidx, "VALUES")) }) # TODO CenterCorner l_resolution = 10 l_boundingbox = tile_handler.get_geoposition_boundingbox(l_resolution) LOGGER.info("Geoposition BoundingBox computed: xmin, ymin, xmax, ymax: " + str(l_boundingbox.xmin) + ", " + str(l_boundingbox.ymin) + ", " + str(l_boundingbox.xmax) + ", " + str(l_boundingbox.ymax) + ".") # Transform in Lat / Long coordinates # ------------------------------------------------------------------------- # CSCode = EPSG:32615 cs_code = tile_handler.reference_system_code cs_code = maja_utils.split_string(cs_code, ':')[-1] # Estimation of the coordinate of the central point l_inputpoint_0 = l_boundingbox.xmin + (l_boundingbox.xmax - l_boundingbox.xmin) / 2.0 l_inputpoint_1 = l_boundingbox.ymin + (l_boundingbox.ymax - l_boundingbox.ymin) / 2.0 LOGGER.debug( "Geoposition BoundingBox central point computed: x, y: " + str(l_inputpoint_0) + ", " + str(l_inputpoint_1)) LOGGER.debug("Start Conversion ToWKT with the EPSG '" + cs_code + "'...") param_conv = {"carto.x": l_inputpoint_0, "carto.y": l_inputpoint_1, "mapproj": "epsg", "mapproj.epsg.code": int(cs_code) } conv_app = OtbAppHandler("ConvertCartoToGeoPoint", param_conv) LOGGER.debug("Start Conversion ToWKT done.") self.CenterCorner.longitude = conv_app.getoutput()["long"] self.CenterCorner.latitude = conv_app.getoutput()["lat"] self.CenterCorner.column = 0 self.CenterCorner.line = 0 conv_app = None return True
def write(self): # 4.3 self.preprocessing() if self.plugin is None: raise MajaException( "Internal error: the variable m_PluginBasePointer is NULL!") # Replace L2VALD by L2NOTV # Note: do in the L2Proefssor lCurrentDate = datetime.datetime.now().strftime( EarthExplorerXMLFileHandler.XML_FORMAT_DATE) l_FileType = "SSC_L2VALD" if not self.productisvalid: # TODO #self.l2imagefilenamesprovider.InvalidateTheFilenames() l_FileType = "SSC_L2NOTV" file_utils.create_directory( self.l2imagefilenamesprovider.get_public_directory()) file_utils.create_directory( self.l2imagefilenamesprovider.get_private_filenames( ).get_private_directory()) # --------------------------------------------------------------------------------------------------- # Write LTC Private Header # Note necessary for Backward mode # --------------------------------------------------------------------------------------------------- # Write LTC Private Header # Note necessary for Backward mode if self.writeltc: # --------------------------------------------------------------------------------------------- # Create the LTC directory if don't exist file_utils.create_directory( self.l2imagefilenamesprovider.get_private_filenames( ).get_ltc_image_dir_filename()) # TODO else: # System::RemoveDirectory(self.l2imagefilenamesprovider.GetPrivateFileNames().GetLTCImageDirFileName()) # itksys::SystemTools::RemoveFile(self.l2imagefilenamesprovider.GetPrivateFileNames().GetLTCHeaderFileName().c_str()) # Create the .DBL file (zero) file_utils.touch_file(self.l2imagefilenamesprovider.get_dbl_filename()) LOGGER.debug("Start Sentinel2L2HeaderFileWriterProvider::Write() ...") # Get the "share/config" directory root_template_directory = self.apphandler.get_share_config_directory() LOGGER.debug("Root template install directory '" + root_template_directory + "'") root_shemas_directory = self.apphandler.get_schemas_root_install_dir() LOGGER.debug("Root shemas install directory '" + root_shemas_directory + "'") lSchemaLocationDirectory = root_shemas_directory + self.plugin.MAJA_INSTALL_SCHEMAS_DIR LOGGER.debug("Root SENTIENL2 install directory '" + lSchemaLocationDirectory + "'") # Read the main header l1_input_handler = MajaSentinel2L1MainXmlReader( self.l1imageinformationsproviderbase.ProductFileName, tile_id=self.apphandler.get_tile_id()) # Get the xml tile header filename tileFilename = self.l1imageinformationsproviderbase.xmlTileFilename LOGGER.info("Tile xml filename: " + tileFilename) l1_input_tile_handler = MajaSentinel2L1GranuleXmlReader(tileFilename) # Write Headers ? # MACCS 4.7.2 - correction pour FA 1572 if self.writel2products or self.backwardmode: if self.enablewriteearthexplorerheaders: # --------------------------------------------------------------------------------------------- # Writes the PUBLIC headers files if self.writel2products: self.write_public_xml_handler( self.l2imagefilenamesprovider, self.dem, self.l1imageinformationsproviderbase.UTCValidityStart, self.l1imageinformationsproviderbase.UTCValidityStop, self.l1imageinformationsproviderbase.Satellite, root_template_directory, lSchemaLocationDirectory, lCurrentDate) # --------------------------------------------------------------------------------------------- # Writes the PRIVATE others headers self.write_private_others_xmlhandler( self.l2imagefilenamesprovider.get_private_filenames(), self.l2imagefilenamesprovider. get_reference_product_header_id(), self.l2imagefilenamesprovider. get_reference_product_instance(), self.dem, self.l1imageinformationsproviderbase.UTCValidityStart, self.l1imageinformationsproviderbase.UTCValidityStop, self.l1imageinformationsproviderbase.Satellite, root_template_directory, lSchemaLocationDirectory, lCurrentDate) # --------------------------------------------------------------------------------------------- # Writes the PRIVATE TEC headers self.write_private_tec_xmlhandler( self.l2imagefilenamesprovider.get_private_filenames( ).get_hdr_private_filename(), self.l2imagefilenamesprovider. get_reference_product_header_id(), self.l1imageinformationsproviderbase.UTCValidityStart, self.l1imageinformationsproviderbase.UTCValidityStop, self.l1imageinformationsproviderbase.Satellite, self.l1imageinformationsproviderbase.Site, self.l1imageinformationsproviderbase.ProductDateStr, root_template_directory, lSchemaLocationDirectory, lCurrentDate) # --------------------------------------------------------------------------------------------- # Writes the PRIVATE STO header self.write_private_sto_xmlhandler( self.l2imagefilenamesprovider.get_private_filenames( ).get_sto_header_filename(), self.l2imagefilenamesprovider.get_reference_product_header_id( ), self.l2imagefilenamesprovider.get_reference_product_instance(), self.dem, self.l1imageinformationsproviderbase.UTCValidityStart, self.l1imageinformationsproviderbase.UTCValidityStop, self.l1imageinformationsproviderbase.Satellite, root_template_directory, lSchemaLocationDirectory, lCurrentDate) # --------------------------------------------------------------------------------------------- # Writes the PRIVATE reflectances headers (RCR, RTA, RTC) self.write_private_reflectances_xmlhandler( self.l2imagefilenamesprovider.get_private_filenames(), self.l2imagefilenamesprovider.get_reference_product_header_id( ), self.l2imagefilenamesprovider.get_reference_product_instance(), self.dem, self.l1imageinformationsproviderbase.UTCValidityStart, self.l1imageinformationsproviderbase.UTCValidityStop, self.l1imageinformationsproviderbase.Satellite, root_template_directory, lSchemaLocationDirectory, lCurrentDate) # --------------------------------------------------------------------------------------------------- # Write LTC Private Header (always, because rode in the Backward mode) # --------------------------------------------------------------------------------------------------- # Write LTC Private Header # Note necessary for Backward mode if self.writeltc: # --------------------------------------------------------------------------------------------------- # Get solar Angles #l_solarAngles = self.l1imageinformationsproviderbase.SolarAngle l_solarAngles = [ float(item) for item in list(self.l1imageinformationsproviderbase. SolarAngle.values()) ] # --------------------------------------------------------------------------------------------------- # Get viewing Angles l_viewingAngles = [] l_MeanViewingAzimuthalAngle = self.l1imageinformationsproviderbase.ListOfViewingAzimuthAnglesPerBandAtL2CoarseResolution l_MeanViewingZenithalAngles = self.l1imageinformationsproviderbase.ListOfViewingZenithAnglesPerBandAtL2CoarseResolution l_viewingAngles.append( statistics.mean( [float(a) for a in l_MeanViewingZenithalAngles])) l_viewingAngles.append( statistics.mean( [float(a) for a in l_MeanViewingAzimuthalAngle])) # --------------------------------------------------------------------------------------------------- # Write LTC Handler self.write_private_ltc_xmlhandler( self.inputl2imagefilereader, self.l2imagefilenamesprovider. get_reference_product_header_id(), self.l2imagefilenamesprovider. get_reference_product_instance(), os.path.join(root_template_directory, self.plugin.TEMPLATE_PDTANX_PRIVATE_LTC_HDR), self.l2imagefilenamesprovider.get_private_filenames(), lSchemaLocationDirectory, lCurrentDate, self.l1imageinformationsproviderbase.UTCValidityStart, self.l1imageinformationsproviderbase.UTCValidityStop, l_solarAngles, l_viewingAngles, False) # LAIG-DM-MAC-975-CNES # Copy the detector footprint (DETFOO gml files) from the L1C product to # the L2 product, in the sub directory "MSK_DETFOO" l_ZoneMaskFileNames = l1_input_tile_handler.ListOfDetFootPrintHeaderFileName l_FullPathDetfoo_subdir = os.path.join( self.l2imagefilenamesprovider.get_public_directory(), "MSK_DETFOO") file_utils.create_directory(l_FullPathDetfoo_subdir) for f in l_ZoneMaskFileNames: file_utils.copy_file_to_directory(f, l_FullPathDetfoo_subdir) self.write_global_xmlhandler( os.path.join(root_template_directory, self.plugin.TEMPLATE_GLOBAL_HDR), l1_input_handler, l1_input_tile_handler, self.l2imagefilenamesprovider.get_hdr_filename(), l_FileType, lSchemaLocationDirectory)