Commit b1c95ce7 authored by Julien Osman's avatar Julien Osman

ENH: Read Sentinel1 metadata + add docstrings

parent 360b8f16
Pipeline #5262 failed with stages
in 87 minutes and 1 second
......@@ -14,6 +14,10 @@ OrbitNumber 6447
NumberOfLines 31106
NumberOfColumns 17663
AverageSceneHeight 19
CalScale 1
PRF 1663.48
RadarFrequency 5.405e+09
CenterIncidenceAngle 44.7171
LineSpacing 4.08568
PixelSpacing 3.19483
AcquisitionDate 2015-06-19T19:50:43.223221Z
......
......@@ -215,10 +215,9 @@ struct OTBMetadata_EXPORT SARParam
{
std::vector<OTB_azimuthFmRate> azimuthFmRate;
double absoluteCalibrationConstant;
std::vector<OTB_calibrationVector> calibrationVectors;
MetaData::Time startTime;
MetaData::Time stopTime;
MetaData::Time calibrationStartTime;
MetaData::Time calibrationStopTime;
std::vector<OTB_dopplerCentroid> dopplerCentroid;
......
......@@ -153,7 +153,7 @@ enum class MDNum
PRF,
RSF,
RadarFrequency,
CenterIndicenceAngle,
CenterIncidenceAngle,
RescalingFactor,
AntennaPatternNewGainPolyDegX,
AntennaPatternNewGainPolyDegY,
......
......@@ -93,30 +93,35 @@ public:
/*get lookup data for calculating backscatter */
void CreateCalibrationLookupData(const short type) override;
void Parse(const MetadataSupplierInterface *) override;
protected:
/* class ctor */
Sentinel1ImageMetadataInterface();
/* class dtor */
~Sentinel1ImageMetadataInterface() override
{
}
/* Fetch the AzimuthFmRate metadata */
std::vector<OTB_azimuthFmRate> GetAzimuthFmRate(XMLMetadataSupplier) const;
/* Fetch the DopplerCentroid metadata */
std::vector<OTB_dopplerCentroid> GetDopplerCentroid(XMLMetadataSupplier) const;
/* Fetch the Orbits metadata */
std::vector<OTB_Orbit> GetOrbits(XMLMetadataSupplier) const;
/* Fetch the Calibration metadata */
std::vector<OTB_calibrationVector> GetCalibrationVector(XMLMetadataSupplier) const;
/* fetch the noise LUTs */
/* Fetch the noise LUTs */
std::vector<OTB_SARNoise> GetNoiseVector(XMLMetadataSupplier) const;
/* Compute the mean terrain elevation */
double getBandTerrainHeight(XMLMetadataSupplier) const;
void Parse(const MetadataSupplierInterface *) override;
protected:
/* class ctor */
Sentinel1ImageMetadataInterface();
/* class dtor */
~Sentinel1ImageMetadataInterface() override
{
}
private:
Sentinel1ImageMetadataInterface(const Self&) = delete;
void operator=(const Self&) = delete;
......
......@@ -44,13 +44,40 @@ class OTBMetadata_EXPORT XMLMetadataSupplier
public:
XMLMetadataSupplier(const std::string &);
/** Get the metadata value corresponding to a given path
* Returns NULL when path is not found
* If band >= 0, the metadata value is looked in the specified band*/
/**
* @brief Get the metadata value corresponding to a given path
*
* @param path The path to look for
* @param hasValue True if path is found
* @param band not used
* @return The value corresponding to path. Empty string if not found.
*/
const std::string GetMetadataValue(const std::string path, bool& hasValue, int band=1) const override;
  • Since C++11, we should no longer return const objects. And no need to copy string parameters unless it's to stole the input

    =>

    std::string GetMetadataValue(const std::string &path, bool& hasValue, int band=1) const override;

    => parent and sibling declarations should be fixed as well.

Please register or sign in to reply
/**
* @brief Get the first metadata value corresponding to a given path
*
* @param path The path to look for
* @param hasValue True if path is found
* @return The value corresponding to path. Empty string if not found.
*/
const std::string GetFirstMetadataValue(const std::string paths, bool& hasValue) const;
/**
* @brief Get the metadata value corresponding to a given path
* converted to the given type
*
* This method can look for a value in a list, using the _# jocker. For exemple,
* looking for "value" in a dictionary like this :
* foo_1.bar=42
* foo_1.doo=99
* foo_2.value=8
* One can specify this path : foo_#.value, the method will then return 8.
*
* @param path The path to look for.
* @return The value corresponding to path.
* @raises otb::Error if path not found
*/
template <typename T> T GetFirstAs(std::string path) const
{
bool hasValue;
......@@ -73,6 +100,11 @@ public:
int GetNbBands() const override;
/**
* @brief Writes the content of the XML file into a string
*
* @return A std::string
*/
std::string PrintSelf();
protected:
......@@ -90,6 +122,15 @@ protected:
virtual char** ReadXMLToList(CPLXMLNode* psNode, char** papszList,
const char* pszName = "");
/**
* @brief In a StringList of “Name=Value” pairs, look for the values
* associated with a name containing the specified string
*
* @param papszStrList A StringList that will be searched
* @param pszName A string that will be looked for in the keys
* @return A StringList containing only the pairs from papszStrList whose key
* contain pszName
*/
char **CSLFetchPartialNameValueMultiple(char** papszStrList, const char *pszName) const;
private:
......
......@@ -338,7 +338,7 @@ MDNumBmType MDNumNames = bimapGenerator<MDNum>(std::map<MDNum, std::string> {
{MDNum::PRF,"PRF"},
{MDNum::RSF,"RSF"},
{MDNum::RadarFrequency,"RadarFrequency"},
{MDNum::CenterIndicenceAngle,"CenterIndicenceAngle"},
{MDNum::CenterIncidenceAngle,"CenterIncidenceAngle"},
{MDNum::RescalingFactor,"RescalingFactor"},
{MDNum::AntennaPatternNewGainPolyDegX,"AntennaPatternNewGainPolyDegX"},
{MDNum::AntennaPatternNewGainPolyDegY,"AntennaPatternNewGainPolyDegY"},
......
......@@ -355,12 +355,15 @@ double Sentinel1ImageMetadataInterface::GetCenterIncidenceAngle() const
std::vector<OTB_azimuthFmRate> Sentinel1ImageMetadataInterface::GetAzimuthFmRate(XMLMetadataSupplier xmlMS) const
{
std::vector<OTB_azimuthFmRate> azimuthFmRateVector;
// Number of entries in the vector
int listCount = xmlMS.GetAs<int>("product.generalAnnotation.azimuthFmRateList.count");
// This streams wild hold the iteration number
std::ostringstream oss;
for (int listId = 1 ; listId <= listCount ; ++listId)
{
oss.str("");
oss << listId;
// Base path to the data, that depends on the iteration number
std::string path_root = "product.generalAnnotation.azimuthFmRateList.azimuthFmRate_" + oss.str();
OTB_azimuthFmRate afr;
std::istringstream(xmlMS.GetAs<std::string>(path_root + ".azimuthTime")) >> afr.azimuthTime;
......@@ -375,12 +378,15 @@ std::vector<OTB_azimuthFmRate> Sentinel1ImageMetadataInterface::GetAzimuthFmRate
std::vector<OTB_dopplerCentroid> Sentinel1ImageMetadataInterface::GetDopplerCentroid(XMLMetadataSupplier xmlMS) const
{
std::vector<OTB_dopplerCentroid> dopplerCentroidVector;
// Number of entries in the vector
int listCount = xmlMS.GetAs<int>("product.dopplerCentroid.dcEstimateList.count");
// This streams wild hold the iteration number
std::ostringstream oss;
for (int listId = 1 ; listId <= listCount ; ++listId)
{
oss.str("");
oss << listId;
// Base path to the data, that depends on the iteration number
std::string path_root = "product.dopplerCentroid.dcEstimateList.dcEstimate_" + oss.str();
OTB_dopplerCentroid dopplerCent;
std::istringstream(xmlMS.GetAs<std::string>(path_root + ".azimuthTime")) >> dopplerCent.azimuthTime;
......@@ -397,12 +403,15 @@ std::vector<OTB_dopplerCentroid> Sentinel1ImageMetadataInterface::GetDopplerCent
std::vector<OTB_Orbit> Sentinel1ImageMetadataInterface::GetOrbits(XMLMetadataSupplier xmlMS) const
{
std::vector<OTB_Orbit> orbitVector;
// Number of entries in the vector
int listCount = xmlMS.GetAs<int>("product.generalAnnotation.orbitList.count");
// This streams wild hold the iteration number
std::ostringstream oss;
for (int listId = 1 ; listId <= listCount ; ++listId)
{
oss.str("");
oss << listId;
// Base path to the data, that depends on the iteration number
std::string path_root = "product.generalAnnotation.orbitList.orbit_" + oss.str();
OTB_Orbit orbit;
std::istringstream(xmlMS.GetAs<std::string>(path_root + ".time")) >> orbit.time;
......@@ -420,12 +429,15 @@ std::vector<OTB_Orbit> Sentinel1ImageMetadataInterface::GetOrbits(XMLMetadataSup
std::vector<OTB_calibrationVector> Sentinel1ImageMetadataInterface::GetCalibrationVector(XMLMetadataSupplier xmlMS) const
{
std::vector<OTB_calibrationVector> calibrationVector;
// Number of entries in the vector
int listCount = xmlMS.GetAs<int>("calibration.calibrationVectorList.count");
// This streams wild hold the iteration number
std::ostringstream oss;
for (int listId = 1 ; listId <= listCount ; ++listId)
{
oss.str("");
oss << listId;
// Base path to the data, that depends on the iteration number
std::string path_root = "calibration.calibrationVectorList.calibrationVector_" + oss.str();
OTB_calibrationVector calVect;
......@@ -469,12 +481,15 @@ std::vector<OTB_calibrationVector> Sentinel1ImageMetadataInterface::GetCalibrati
std::vector<OTB_SARNoise> Sentinel1ImageMetadataInterface::GetNoiseVector(XMLMetadataSupplier xmlMS) const
{
std::vector<OTB_SARNoise> noiseVector;
// Number of entries in the vector
int listCount = xmlMS.GetAs<int>("noise.noiseVectorList.count");
// This streams wild hold the iteration number
std::ostringstream oss;
for (int listId = 1 ; listId <= listCount ; ++listId)
{
oss.str("");
oss << listId;
// Base path to the data, that depends on the iteration number
std::string path_root = "noise.noiseVectorList.noiseVector_" + oss.str();
OTB_SARNoise noiseVect;
std::istringstream(xmlMS.GetAs<std::string>(path_root + ".azimuthTime")) >> noiseVect.azimuthTime;
......@@ -494,16 +509,19 @@ std::vector<OTB_SARNoise> Sentinel1ImageMetadataInterface::GetNoiseVector(XMLMet
double Sentinel1ImageMetadataInterface::getBandTerrainHeight(XMLMetadataSupplier xmlMS) const
{
double heightSum = 0.0;
// Number of entries in the vector
int listCount = xmlMS.GetAs<int>("product.generalAnnotation.terrainHeightList.count");
// This streams wild hold the iteration number
std::ostringstream oss;
for (int listId = 1 ; listId <= listCount ; ++listId)
{
oss.str("");
oss << listId;
// Base path to the data, that depends on the iteration number
std::string path_root = "product.generalAnnotation.terrainHeightList.terrainHeight_" + oss.str();
heightSum += xmlMS.GetAs<double>((path_root + ".value").c_str());
}
return heightSum / listCount;
return heightSum / (double)listCount;
}
void Sentinel1ImageMetadataInterface::Parse(const MetadataSupplierInterface *mds)
......@@ -559,6 +577,9 @@ void Sentinel1ImageMetadataInterface::Parse(const MetadataSupplierInterface *mds
m_Imd.Add(MDNum::NumberOfLines, AnnotationMS.GetAs<int>("product.imageAnnotation.imageInformation.numberOfLines"));
m_Imd.Add(MDNum::NumberOfColumns, AnnotationMS.GetAs<int>("product.imageAnnotation.imageInformation.numberOfSamples"));
m_Imd.Add(MDNum::AverageSceneHeight, this->getBandTerrainHeight(AnnotationFilePath));
m_Imd.Add(MDNum::RadarFrequency, AnnotationMS.GetAs<double>("product.generalAnnotation.productInformation.radarFrequency"));
m_Imd.Add(MDNum::PRF, AnnotationMS.GetAs<double>("product.imageAnnotation.imageInformation.azimuthFrequency"));
m_Imd.Add(MDNum::CenterIncidenceAngle, AnnotationMS.GetAs<double>("product.imageAnnotation.imageInformation.incidenceAngleMidSwath"));
// Calibration file
std::string CalibrationFilePath = itksys::SystemTools::GetFilenamePath(AnnotationFilePath)
......@@ -567,10 +588,10 @@ void Sentinel1ImageMetadataInterface::Parse(const MetadataSupplierInterface *mds
if (CalibrationFilePath.empty())
otbGenericExceptionMacro(MissingMetadataException,<<"Missing Calibration file for band '"<<swath<<"'");
XMLMetadataSupplier CalibrationMS = XMLMetadataSupplier(CalibrationFilePath);
sarParam.absoluteCalibrationConstant = CalibrationMS.GetAs<double>("calibration.calibrationInformation.absoluteCalibrationConstant");
m_Imd.Add(MDNum::CalScale, CalibrationMS.GetAs<double>("calibration.calibrationInformation.absoluteCalibrationConstant"));
sarParam.calibrationVectors = this->GetCalibrationVector(CalibrationMS);
std::istringstream(CalibrationMS.GetAs<std::string>("calibration.adsHeader.startTime")) >> sarParam.startTime;
std::istringstream(CalibrationMS.GetAs<std::string>("calibration.adsHeader.stopTime")) >> sarParam.stopTime;
std::istringstream(CalibrationMS.GetAs<std::string>("calibration.adsHeader.startTime")) >> sarParam.calibrationStartTime;
std::istringstream(CalibrationMS.GetAs<std::string>("calibration.adsHeader.stopTime")) >> sarParam.calibrationStopTime;
// Noise file
std::string NoiseFilePath = itksys::SystemTools::GetFilenamePath(AnnotationFilePath)
......
......@@ -27,12 +27,7 @@ XMLMetadataSupplier::XMLMetadataSupplier(const std::string & fileName)
{
CPLXMLNode* psNode = CPLParseXMLFile(m_FileName.c_str());
if(psNode != nullptr)
{
//if(std::string(psNode->pszValue) == "?xml")
// if(EQUAL(psNode->pszValue, "?xml"))
// psNode = psNode->psNext;
m_MetadataDic = ReadXMLToList(psNode, m_MetadataDic);
}
else
{
otbLogMacro(Warning, <<"Unable to parse XML file " << fileName);
......@@ -56,13 +51,19 @@ const std::string XMLMetadataSupplier::GetMetadataValue(const std::string path,
const std::string XMLMetadataSupplier::GetFirstMetadataValue(const std::string path, bool& hasValue) const
{
// Search for the first joker
std::size_t found = path.find("_#");
// Looking for the keys corresponding to the part of the path before the first joker
char ** values = this->CSLFetchPartialNameValueMultiple(m_MetadataDic, path.substr(0, found).c_str());
// Position of the beginning of the path after the joker
std::size_t start = found + 2;
// While a joker is found
while(found != std::string::npos)
{
found = path.find("_#", found + 2);
// Look for the next joker
found = path.find("_#", start);
// Look for the keys corresponding to the part of the path between the two jokers
values = this->CSLFetchPartialNameValueMultiple(values, path.substr(start, found).c_str());
start = found + 2;
}
......@@ -71,6 +72,7 @@ const std::string XMLMetadataSupplier::GetFirstMetadataValue(const std::string p
{
hasValue = true;
std::string ret = std::string(values[0]);
// Return the value part
return ret.substr(ret.find('=') + 1);
}
else
......
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