Commit bc432d66 authored by Julien Osman's avatar Julien Osman

WIP: Add parts of Sentinel1 Metadata reading process.

parent b75a3522
......@@ -22,6 +22,7 @@
#define otbGeometryMetadata_h
#include "OTBMetadataExport.h"
#include "otbMetaDataKey.h"
#include <string>
......@@ -71,6 +72,32 @@ public:
std::string ToJSON(bool multiline=false) const;
};
struct OTBMetadata_EXPORT OTB_azimuthFmRate
{
MetaData::Time azimuthTime;
double t0;
std::vector<double> azimuthFmRatePolynomial;
};
struct OTBMetadata_EXPORT OTB_calibrationVector
{
MetaData::Time azimuthTime;
int line;
std::vector<int> pixel;
std::vector<double> sigmaNought;
std::vector<double> betaNought;
std::vector<double> gamma;
std::vector<double> dn;
};
struct OTBMetadata_EXPORT OTB_dopplerCentroid
{
std::vector<double> dopCoef;
std::vector<double> geoDopCoef;
MetaData::Time geoDopCoefTime;
double slantRangeTime;
};
namespace Projection
{
......@@ -160,7 +187,24 @@ struct OTBMetadata_EXPORT RPCParam
};
// TODO : add SARParam to define a SAR sensor geometry
/** \struct SARParam
*
* \brief SAR sensors parameters
*
* \ingroup OTBMetadata
*/
struct OTBMetadata_EXPORT SARParam
{
std::vector<OTB_azimuthFmRate> azimuthFmRate;
double absoluteCalibrationConstant;
std::vector<OTB_calibrationVector> calibrationVectors;
MetaData::Time startTime;
MetaData::Time stopTime;
std::vector<OTB_dopplerCentroid> dopplerCentroid;
};
} // end namespace Projection
......
......@@ -131,6 +131,7 @@ enum class MDNum
TileHintY,
DataType,
NoData,
OrbitNumber,
// optical section
PhysicalGain,
PhysicalBias,
......@@ -161,6 +162,8 @@ enum class MDNum
RangeSpreadLossPolyDegY,
NoisePolyDegX,
NoisePolyDegY,
LineSpacing,
PixelSpacing,
END
};
......@@ -175,6 +178,11 @@ enum class MDStr
GeometricLevel,
RadiometricLevel,
Polarization,
Mode,
Swath,
OrbitDirection,
BeamMode,
BeamSwath,
// ...
END
};
......@@ -198,6 +206,8 @@ enum class MDTime
{
AcquisitionDate,
ProductionDate,
AcquisitionStartTime,
AcquisitionStopTime,
END
};
......
......@@ -22,7 +22,7 @@
#define otbSentinel1ImageMetadataInterface_h
#include "otbSarImageMetadataInterface.h"
#include "otbXMLMetadataSupplier.h"
namespace otb
{
......@@ -93,6 +93,12 @@ public:
/*get lookup data for calculating backscatter */
void CreateCalibrationLookupData(const short type) override;
std::vector<OTB_azimuthFmRate> GetAzimuthFmRate(XMLMetadataSupplier) const;
std::vector<OTB_calibrationVector> GetCalibrationVector(XMLMetadataSupplier) const;
void Parse(const MetadataSupplierInterface *) override;
protected:
/* class ctor */
Sentinel1ImageMetadataInterface();
......
......@@ -80,7 +80,7 @@ std::string GCPParam::ToJSON(bool multiline) const
<< "\"Projection\": \"" << GCPProjection << "\", " << sep
<< "[";
for (const auto& gcp : GCPs)
oss << gcp.ToJSON() << ", ";
oss << gcp.ToJSON() << ", " << sep;
oss << "]}";
return oss.str();
}
......
......@@ -318,6 +318,7 @@ MDNumBmType MDNumNames = bimapGenerator<MDNum>(std::map<MDNum, std::string> {
{MDNum::TileHintY,"TileHintY"},
{MDNum::DataType,"DataType"},
{MDNum::NoData, "NoData"},
{MDNum::OrbitNumber, "OrbitNumber"},
{MDNum::PhysicalGain,"PhysicalGain"},
{MDNum::PhysicalBias,"PhysicalBias"},
{MDNum::SolarIrradiance,"SolarIrradiance"},
......@@ -346,6 +347,8 @@ MDNumBmType MDNumNames = bimapGenerator<MDNum>(std::map<MDNum, std::string> {
{MDNum::RangeSpreadLossPolyDegY,"RangeSpreadLossPolyDegY"},
{MDNum::NoisePolyDegX,"NoisePolyDegX"},
{MDNum::NoisePolyDegY,"NoisePolyDegY"},
{MDNum::LineSpacing,"LineSpacing"},
{MDNum::PixelSpacing,"PixelSpacing"},
});
MDStrBmType MDStrNames = bimapGenerator<MDStr>(std::map<MDStr, std::string> {
......@@ -356,12 +359,19 @@ MDStrBmType MDStrNames = bimapGenerator<MDStr>(std::map<MDStr, std::string> {
{MDStr::GeometricLevel,"GeometricLevel"},
{MDStr::RadiometricLevel,"RadiometricLevel"},
{MDStr::Polarization,"Polarization"},
{MDStr::Mode, "Mode"},
{MDStr::Swath, "Swath"},
{MDStr::OrbitDirection, "OrbitDirection"},
{MDStr::BandName,"BandName"},
{MDStr::BeamMode, "BeamMode"},
{MDStr::BeamSwath, "BeamSwath"},
});
MDTimeBmType MDTimeNames = bimapGenerator<MDTime>(std::map<MDTime, std::string> {
{MDTime::AcquisitionDate,"AcquisitionDate"},
{MDTime::ProductionDate,"ProductionDate"},
{MDTime::AcquisitionStartTime,"AcquisitionStartTime"},
{MDTime::AcquisitionStopTime,"AcquisitionStopTime"},
});
MDL1DBmType MDL1DNames = bimapGenerator<MDL1D>(std::map<MDL1D, std::string> {
......
......@@ -25,6 +25,7 @@
#include "otbMacro.h"
#include "itkMetaDataObject.h"
#include "otbImageKeywordlist.h"
#include "otbXMLMetadataSupplier.h"
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
......@@ -33,6 +34,7 @@
#else
#include "ossim/ossimTimeUtilities.h"
#endif
#include "itksys/SystemTools.hxx"
// useful constants
#include <otbMath.h>
......@@ -350,4 +352,104 @@ double Sentinel1ImageMetadataInterface::GetCenterIncidenceAngle() const
return 0;
}
std::vector<OTB_azimuthFmRate> Sentinel1ImageMetadataInterface::GetAzimuthFmRate(XMLMetadataSupplier xmlMS) const
{
std::vector<OTB_azimuthFmRate> azimuthFmRateVector;
int listCount = xmlMS.GetAs<double>("product.generalAnnotation.azimuthFmRateList.count");
std::ostringstream oss;
for (int listId = 1 ; listId <= listCount ; ++listId)
{
oss.str("");
oss << listId;
std::string path_root = "product.generalAnnotation.azimuthFmRateList.azimuthFmRate_" + oss.str();
OTB_azimuthFmRate afr;
std::istringstream(xmlMS.GetMetadataValue((path_root + ".azimuthTime").c_str())) >> afr.azimuthTime;
afr.t0 = xmlMS.GetAs<double>((path_root + ".t0").c_str());
afr.azimuthFmRatePolynomial = xmlMS.GetAsVector<double>((path_root + ".azimuthFmRatePolynomial").c_str(),
' ', xmlMS.GetAs<int>((path_root + ".azimuthFmRatePolynomial.count").c_str()));
azimuthFmRateVector.push_back(afr);
}
return azimuthFmRateVector;
}
std::vector<OTB_calibrationVector> Sentinel1ImageMetadataInterface::GetCalibrationVector(XMLMetadataSupplier xmlMS) const
{
std::vector<OTB_calibrationVector> calibrationVector;
int listCount = xmlMS.GetAs<double>("calibration.calibrationVectorList.count");
std::ostringstream oss;
for (int listId = 1 ; listId <= listCount ; ++listId)
{
oss.str("");
oss << listId;
std::string path_root = "calibration.calibrationVectorList.calibrationVector_" + oss.str();
OTB_calibrationVector calVect;
std::istringstream(xmlMS.GetMetadataValue((path_root + ".azimuthTime").c_str())) >> calVect.azimuthTime;
calVect.line = xmlMS.GetAs<int>((path_root + ".line").c_str());
calVect.pixel = xmlMS.GetAsVector<int>((path_root + ".pixel").c_str(),
' ', xmlMS.GetAs<int>((path_root + ".pixel.count").c_str()));
calVect.sigmaNought = xmlMS.GetAsVector<double>((path_root + ".sigmaNought").c_str(),
' ', xmlMS.GetAs<int>((path_root + ".sigmaNought.count").c_str()));
calVect.betaNought = xmlMS.GetAsVector<double>((path_root + ".betaNought").c_str(),
' ', xmlMS.GetAs<int>((path_root + ".betaNought.count").c_str()));
calVect.gamma = xmlMS.GetAsVector<double>((path_root + ".gamma").c_str(),
' ', xmlMS.GetAs<int>((path_root + ".gamma.count").c_str()));
calVect.dn = xmlMS.GetAsVector<double>((path_root + ".dn").c_str(),
' ', xmlMS.GetAs<int>((path_root + ".dn.count").c_str()));
calibrationVector.push_back(calVect);
}
return calibrationVector;
}
void Sentinel1ImageMetadataInterface::Parse(const MetadataSupplierInterface *mds)
{
assert(mds);
assert(mds->GetNbBands() == this->m_Imd.GetNbBands());
// Metadata read by GDAL
//Fetch(MDTime::AcquisitionStartTime, mds, "ACQUISITION_START_TIME");
//Fetch(MDTime::AcquisitionStopTime, mds, "ACQUISITION_STOP_TIME");
Fetch(MDStr::BeamMode, mds, "BEAM_MODE");
Fetch(MDStr::BeamSwath, mds, "BEAM_SWATH");
Fetch("FACILITY_IDENTIFIER", mds, "FACILITY_IDENTIFIER");
Fetch(MDNum::LineSpacing, mds, "LINE_SPACING");
Fetch(MDStr::Mission, mds, "MISSION_ID");
Fetch(MDStr::Mode, mds, "MODE");
Fetch(MDStr::OrbitDirection, mds, "ORBIT_DIRECTION");
Fetch(MDNum::OrbitNumber, mds, "ORBIT_NUMBER");
Fetch(MDNum::PixelSpacing, mds, "PIXEL_SPACING");
Fetch(MDStr::ProductType, mds, "PRODUCT_TYPE");
Fetch(MDStr::Instrument, mds, "SATELLITE_IDENTIFIER");
Fetch(MDStr::SensorID, mds, "SENSOR_IDENTIFIER");
Fetch(MDStr::Swath, mds, "SWATH");
// Band metadata
for (int bandId = 0 ; bandId < mds->GetNbBands() ; ++bandId)
{
Projection::SARParam sarParam;
Fetch(MDStr::Polarization, mds, "POLARISATION", bandId);
std::string swath = Fetch(MDStr::Swath, mds, "SWATH", bandId);
// Annotation file
std::string AnnotationFilePath = mds->GetResourceFile(std::string("annotation[/\\\\]s1[ab].*-")
+ itksys::SystemTools::LowerCase(swath)
+ std::string("-.*\\.xml"));
if (!AnnotationFilePath.empty())
{
XMLMetadataSupplier xmlMS = XMLMetadataSupplier(AnnotationFilePath);
sarParam.azimuthFmRate = this->GetAzimuthFmRate(xmlMS);
// Calibration file
std::string CalibrationFilePath = itksys::SystemTools::GetFilenamePath(AnnotationFilePath)
+ "/calibration/calibration-"
+ itksys::SystemTools::GetFilenameName(AnnotationFilePath);
xmlMS = XMLMetadataSupplier(CalibrationFilePath);
sarParam.absoluteCalibrationConstant = xmlMS.GetAs<double>("calibration.calibrationInformation.absoluteCalibrationConstant");
sarParam.calibrationVectors = this->GetCalibrationVector(xmlMS);
std::istringstream(xmlMS.GetMetadataValue("calibration.adsHeader.startTime")) >> sarParam.startTime;
std::istringstream(xmlMS.GetMetadataValue("calibration.adsHeader.stopTime")) >> sarParam.stopTime;
}
m_Imd.Bands[bandId].Add(MDGeom::SAR, sarParam);
}
}
} // end namespace otb
......@@ -28,6 +28,7 @@ otbSarDefaultImageMetadataInterface.cxx
otbOpticalImageMetadataInterfaceTest.cxx
otbOpticalDefaultImageMetadataInterface.cxx
otbDefaultImageMetadataInterface.cxx
otbImageMetadataInterfaceTest.cxx
otbImageMetadataInterfaceTest2.cxx
otbNoDataHelperTest.cxx
otbSarCalibrationLookupDataTest.cxx
......@@ -81,6 +82,20 @@ otb_module_target_label(otbMetadataTestDriver)
#${TEMP}/ioTvSarImageMetadataInterface_TSX1PANGKALANBUUNUsingHHCosFile.txt
#)
#otb_add_test(NAME ioTvSentinel1ImageMetadataInterfaceTest COMMAND otbMetadataTestDriver
# otbSentinel1ImageMetadataInterfaceTest
# /home/julien/Bureau/S1Product/S1A_IW_GRDH_1SDV_20170819T001029_20170819T001054_017985_01E2E8_F302.SAFE
# ${TEMP}/ioTvSentinel1ImageMetadataInterfaceTest.txt
# )
otb_add_test(NAME ioTvImageMetadataInterfaceTest_Sentinel1 COMMAND otbMetadataTestDriver
--compare-ascii ${EPSILON_9} ${BASELINE_FILES}/ioTvImageMetadataInterfaceTest_Sentinel1.txt
${TEMP}/ioTvImageMetadataInterfaceTest_Sentinel1.txt
otbImageMetadataInterfaceTest
LARGEINPUT{SENTINEL1/S1A_S6_SLC__1SSV_20150619T195043}
${TEMP}/ioTvImageMetadataInterfaceTest_Sentinel1.txt
)
#otb_add_test(NAME ioTvImageMetadataInterfaceBaseTest_SENTINEL1 COMMAND otbMetadataTestDriver
#--compare-ascii ${EPSILON_9} ${BASELINE_FILES}/ioTvImageMetadataInterfaceBase_SENTINEL1.txt
#${TEMP}/ioTvImageMetadataInterfaceBase_SENTINEL1.txt
......
/*
* Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES)
*
* This file is part of Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "itkMacro.h"
#include <boost/any.hpp>
#include <fstream>
#include <iostream>
#include "otbImage.h"
#include "otbImageFileReader.h"
#include "otbImageMetadataInterfaceFactory.h"
#include "otbGDALImageIO.h"
#include "otbMetaDataKey.h"
#include "otbTestTools.h"
int otbImageMetadataInterfaceTest(int itkNotUsed(argc), char* argv[])
{
// Verify the number of parameters in the command line
const char* inputFilename = argv[1];
const char* outputFilename = argv[2];
typedef otb::Image<double, 2> InputImageType;
typedef otb::ImageFileReader<InputImageType> ImageReaderType;
ImageReaderType::Pointer reader = ImageReaderType::New();
reader->SetFileName(inputFilename);
reader->UpdateOutputInformation();
otb::ImageMetadata imd = reader->GetImageIO()->GetImageMetadata();
otb::MetadataSupplierInterface* mds = dynamic_cast<otb::MetadataSupplierInterface*>(reader->GetImageIO());
otb::ImageMetadataInterfaceBase::Pointer imi = otb::ImageMetadataInterfaceFactory::CreateIMI(imd, mds);
// Test the image interface
otb::GDALImageIO* mds2 = dynamic_cast<otb::GDALImageIO*>(mds);
imi->Parse(mds);
const otb::ImageMetadata& imd2 = imi->GetImageMetadata();
std::ofstream file;
file.open(outputFilename);
otb::testtools::PrintMetadata(imd2, file);
if (imd2.Has(otb::MDGeom::GCP))
file << boost::any_cast<otb::Projection::GCPParam>(imd2[otb::MDGeom::GCP]).ToJSON(true);
file.close();
std::cout << mds2->printSomething() << std::endl;;
return EXIT_SUCCESS;
}
......@@ -28,6 +28,7 @@ void RegisterTests()
REGISTER_TEST(otbOpticalImageMetadataInterfaceTest);
REGISTER_TEST(otbOpticalDefaultImageMetadataInterface);
REGISTER_TEST(otbDefaultImageMetadataInterface);
REGISTER_TEST(otbImageMetadataInterfaceTest);
REGISTER_TEST(otbImageMetadataInterfaceTest2);
REGISTER_TEST(otbNoDataHelperTest);
REGISTER_TEST(otbSarCalibrationLookupDataTest);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment