Commit df9fb212 authored by Cédric Traizet's avatar Cédric Traizet

ENH: add parsing for pleiades metadata from geom

parent 630f4fe7
adjustment_0.adj_param_0.center: 0
adjustment_0.adj_param_0.description: intrack_offset
adjustment_0.adj_param_0.lock_flag: 0
adjustment_0.adj_param_0.parameter: 0
adjustment_0.adj_param_0.sigma: 50
adjustment_0.adj_param_0.units: pixel
adjustment_0.adj_param_1.center: 0
adjustment_0.adj_param_1.description: crtrack_offset
adjustment_0.adj_param_1.lock_flag: 0
adjustment_0.adj_param_1.parameter: 0
adjustment_0.adj_param_1.sigma: 50
adjustment_0.adj_param_1.units: pixel
adjustment_0.adj_param_2.center: 0
adjustment_0.adj_param_2.description: intrack_scale
adjustment_0.adj_param_2.lock_flag: 0
adjustment_0.adj_param_2.parameter: 0
adjustment_0.adj_param_2.sigma: 50
adjustment_0.adj_param_2.units: unknown
adjustment_0.adj_param_3.center: 0
adjustment_0.adj_param_3.description: crtrack_scale
adjustment_0.adj_param_3.lock_flag: 0
adjustment_0.adj_param_3.parameter: 0
adjustment_0.adj_param_3.sigma: 50
adjustment_0.adj_param_3.units: unknown
adjustment_0.adj_param_4.center: 0
adjustment_0.adj_param_4.description: map_rotation
adjustment_0.adj_param_4.lock_flag: 0
adjustment_0.adj_param_4.parameter: 0
adjustment_0.adj_param_4.sigma: 0.1
adjustment_0.adj_param_4.units: degrees
adjustment_0.description: Initial adjustment
adjustment_0.dirty_flag: 0
adjustment_0.number_of_params: 5
bias_error: 0
ce90_absolute: 0
ce90_relative: 0
current_adjustment: 0
height_off: 1545
height_scale: 1435
image_id: 559102101-002
lat_off: -21.1087301331719
lat_scale: 0.0704553286149459
line_den_coeff_00: 1
line_den_coeff_01: -0.00208784896080109
line_den_coeff_02: -0.0022394121088751
line_den_coeff_03: 1.52979837061491e-05
line_den_coeff_04: -4.63747139573611e-06
line_den_coeff_05: -1.72079709901999e-06
line_den_coeff_06: 2.25642810511542e-06
line_den_coeff_07: -3.39661337239182e-05
line_den_coeff_08: 1.84653898714239e-05
line_den_coeff_09: -4.65310678969581e-05
line_den_coeff_10: -5.43911042179134e-07
line_den_coeff_11: 9.64383994759896e-08
line_den_coeff_12: -2.53310739393562e-05
line_den_coeff_13: 1.83763819696057e-07
line_den_coeff_14: -9.18452145752219e-07
line_den_coeff_15: -0.000303216222418777
line_den_coeff_16: -1.35416723467531e-07
line_den_coeff_17: -3.07223166874633e-09
line_den_coeff_18: -9.75393859394075e-06
line_den_coeff_19: -2.4200360497773e-09
line_num_coeff_00: -0.00517955616370615
line_num_coeff_01: -0.0237791184004102
line_num_coeff_02: -1.03496089821104
line_num_coeff_03: -0.0111724997647484
line_num_coeff_04: -0.00190769288124836
line_num_coeff_05: -2.04569280615788e-05
line_num_coeff_06: 6.82055333965413e-05
line_num_coeff_07: 0.000531395750990351
line_num_coeff_08: 0.00324755686759663
line_num_coeff_09: 3.12014473510082e-06
line_num_coeff_10: 1.73873098702642e-06
line_num_coeff_11: 1.68072346597447e-06
line_num_coeff_12: -3.60829706806423e-06
line_num_coeff_13: 1.1305018388573e-06
line_num_coeff_14: 2.30630398147363e-05
line_num_coeff_15: 2.76079749873855e-05
line_num_coeff_16: 4.81457792658454e-05
line_num_coeff_17: 2.88619029525836e-07
line_num_coeff_18: -3.21946619769831e-07
line_num_coeff_19: 5.19261801580877e-07
line_off: 3628.5
line_scale: 3628.5
ll_lat: -21.1761546496637
ll_lon: 55.3361820080128
long_off: 55.379004045894
long_scale: 0.107479361921552
lr_lat: -21.1772268212327
lr_lon: 55.4217197328727
meters_per_pixel_x: 2.07836248989021
meters_per_pixel_y: 2.07748424063427
number_lines: 7235
number_of_adjustments: 1
number_samples: 4289
polynomial_format: B
rand_error: 0
rect: 0 0 4288 7234
ref_point_hgt: 1545
ref_point_lat: -21.1088750520256
ref_point_line: 3617
ref_point_lon: 55.378917411815
ref_point_samp: 2144
samp_den_coeff_00: 1
samp_den_coeff_01: 0.000654449833577695
samp_den_coeff_02: 0.000213843174719518
samp_den_coeff_03: -0.00110310320675886
samp_den_coeff_04: -2.68935983230003e-05
samp_den_coeff_05: -8.81547406009463e-06
samp_den_coeff_06: 1.37438399454632e-05
samp_den_coeff_07: -2.98576093541842e-05
samp_den_coeff_08: -0.00094184598120703
samp_den_coeff_09: -6.21322345667692e-05
samp_den_coeff_10: -8.05214678414999e-08
samp_den_coeff_11: 1.72216588880331e-07
samp_den_coeff_12: 4.13783059018304e-06
samp_den_coeff_13: 2.48687256689273e-07
samp_den_coeff_14: -3.94041826173385e-07
samp_den_coeff_15: 2.7724685428418e-06
samp_den_coeff_16: -7.27126458629283e-08
samp_den_coeff_17: 3.0260429442832e-08
samp_den_coeff_18: 2.11128718894305e-06
samp_den_coeff_19: 1.28548969806379e-07
samp_num_coeff_00: -0.00571750098332861
samp_num_coeff_01: 1.03789735997475
samp_num_coeff_02: 0.000360594114086057
samp_num_coeff_03: -0.03665106866224
samp_num_coeff_04: -0.000705071876953317
samp_num_coeff_05: 0.000865156381425534
samp_num_coeff_06: -0.000346559714000292
samp_num_coeff_07: 0.00511584830313226
samp_num_coeff_08: -0.00100145894084082
samp_num_coeff_09: -3.23760905794259e-05
samp_num_coeff_10: 7.42293070343201e-06
samp_num_coeff_11: -2.24866194430823e-05
samp_num_coeff_12: -0.00100961173052394
samp_num_coeff_13: -6.29778164960812e-05
samp_num_coeff_14: 6.97330238769708e-06
samp_num_coeff_15: -0.000293808153145129
samp_num_coeff_16: -7.36857981217554e-07
samp_num_coeff_17: 6.99721596099962e-06
samp_num_coeff_18: 2.68058434585531e-05
samp_num_coeff_19: 2.22039097455653e-06
samp_off: 2178
samp_scale: 5187
sensor: PHR 1A
support_data.across_track_incidence_angle: """15.5053146594264 15.3626255402908 15.2247250482884 """
support_data.along_track_incidence_angle: """3.59821466135206 3.6249508899685 3.62234561700206 """
support_data.azimuth_angle: """32.4715316086963 32.4440294202269 32.4164722984247 """
support_data.band_name_list: """B2 B1 B0 B3 """
support_data.elevation_angle: """39.2603853118654 39.2072431471418 39.1542270478631 """
support_data.image_date: 2012-06-05T06:30:06.4Z
support_data.image_id: 559102101-002
support_data.image_size: 4289 7235
support_data.incident_angle: """15.8790393545957 15.7459904684335 15.6115981628452 """
support_data.instrument: PHR
support_data.instrument_index: 1A
support_data.line_period: 0.2968
support_data.ll_ground_point: -21.175850612249 55.3347328208722 0 WGE
support_data.lr_ground_point: -21.1774050264981 55.4225413829229 0 WGE
support_data.number_bands: 4
support_data.number_of_across_track_incidence_angle: 3
support_data.number_of_along_track_incidence_angle: 3
support_data.number_of_azimuth_angle: 3
support_data.number_of_elevation_angle: 3
support_data.number_of_incident_angle: 3
support_data.number_of_scene_orientation: 3
support_data.number_of_viewing_angle: 3
support_data.physical_bias: """0 0 0 0 """
support_data.physical_gain: """9.55 9.15 10.2 15.49 """
support_data.processing_level: SENSOR
support_data.production_date: 2012-06-20T08:39:43.745
support_data.reference_ground_point: -21.1086786271728 55.3782731567389 0 WGE
support_data.reference_image_point: 2144.5 3617.5
support_data.scene_orientation: """180.176824961336 179.965398614103 179.860914643547 """
support_data.sensorID: PHR 1A
support_data.solar_irradiance: """999 999 999 999 """
support_data.swath_first_col: 3010
support_data.swath_last_col: 7298
support_data.time_range_end: 2012-06-05T06:30:08.7180512Z
support_data.time_range_start: 2012-06-05T06:30:06.5710000Z
support_data.type: ossimPleiadesDimapSupportData
support_data.ul_ground_point: -21.0399305707828 55.3348345957548 0 WGE
support_data.ur_ground_point: -21.0415282991612 55.4209838274057 0 WGE
support_data.viewing_angle: """14.2903129322935 14.1714238876625 14.0513265494621 """
type: ossimPleiadesModel
ul_lat: -21.0402120081118
ul_lon: 55.3360918175061
ur_lat: -21.041721788044
ur_lon: 55.4217698993144
......@@ -25,20 +25,22 @@ namespace otb
string_view lstrip(string_view const& v, string_view const& c )
{
string_view::const_iterator pos = std::find_first_of(
v.cbegin(), v.cend(), c.cbegin(), c.cend(),
[](char c1, char c2) -> bool { return bool(c1 != c2) ;});
string_view::const_iterator pos = std::find_if(
v.cbegin(), v.cend(),
[&v, &c](char in) -> bool {return std::find(c.cbegin(),c.cend(),in) == c.cend();});
// Beware: returned string_view may be empty
return string_view(pos, v.cend());
}
string_view rstrip(string_view const& v, string_view const& c )
{
string_view::const_reverse_iterator pos = std::find_first_of(
v.crbegin(), v.crend(), c.cbegin(), c.cend(),
[](char c1, char c2) -> bool { return bool(c1 != c2) ;});
string_view::const_reverse_iterator pos = std::find_if(
v.crbegin(), v.crend(),
[&v, &c](char in) -> bool {return std::find(c.cbegin(),c.cend(),in) == c.cend();});
// Beware: returned string_view may be empty
return string_view(v.cbegin(),&*pos - &(*v.cbegin()));
return string_view(v.cbegin(), &*pos - &(*v.cbegin()) + 1);
}
} // end namespace otb
......@@ -105,11 +105,28 @@ public:
( std::istream_iterator<double>() ) );
};
m_Data.mission = mds.GetAs<std::string>("sensor");
auto sensorName = mds.GetAs<std::string>("sensor");
std::vector<std::string> parts;
boost::split(parts, sensorName, boost::is_any_of(" "));
m_Data.mission = parts[0];
if (parts.size() > 1)
{
m_Data.missionIndex = parts[1];
}
m_Data.ImageID = mds.GetAs<std::string>("support_data.image_id");
m_Data.ProcessingLevel = mds.GetAs<std::string>("", "support_data.processing_level");
// Band name list might not be present in the dimap
auto bandNameListStr = mds.GetAs<std::string>("", "support_data.band_name_list");
if (!bandNameListStr.empty())
{
bandNameListStr.erase(std::remove(bandNameListStr.begin(), bandNameListStr.end(), '\"'), bandNameListStr.end());
boost::trim(bandNameListStr);
boost::split(m_Data.BandIDs, bandNameListStr, boost::is_any_of(" "));
}
m_Data.ProductionDate = mds.GetAs<std::string>("support_data.production_date");
// Convert YYYY-MM-DD HH:mm:ss to YYYY-MM-DDTHH:mm:ss
......@@ -127,11 +144,11 @@ public:
m_Data.AcquisitionDate.replace(pos,1,"T");
}
m_Data.SunAzimuth = {mds.GetAs<double>("support_data.azimuth_angle")};
m_Data.SunElevation = {mds.GetAs<double>("support_data.elevation_angle")};
m_Data.SunAzimuth = readVector("support_data.azimuth_angle");
m_Data.SunElevation = readVector("support_data.elevation_angle");
m_Data.IncidenceAngle = {mds.GetAs<double>("support_data.incident_angle") };
m_Data.SceneOrientation = {mds.GetAs<double>("support_data.scene_orientation")};
m_Data.IncidenceAngle = readVector("support_data.incident_angle");
m_Data.SceneOrientation = readVector("support_data.scene_orientation");
m_Data.StepCount = mds.GetAs<int>(0, "support_data.step_count");
......@@ -154,6 +171,17 @@ public:
{
m_Data.AlongTrackViewingAngle.push_back(std::stod("alongTrackViewingAngle"));
}
if (mds.HasValue("support_data.along_track_incidence_angle"))
{
m_Data.AlongTrackIncidenceAngle = readVector("support_data.along_track_incidence_angle");
}
if (mds.HasValue("support_data.across_track_incidence_angle"))
{
m_Data.AcrossTrackIncidenceAngle = readVector("support_data.across_track_incidence_angle");
}
}
......@@ -283,7 +311,7 @@ public:
}
void Parse(const MetadataSupplierInterface & mds)
void ParseDimapV2(const MetadataSupplierInterface & mds)
{
std::vector<std::string> missionVec;
ParseVector(mds, "IMD/Dataset_Sources.Source_Identification"
......
......@@ -162,23 +162,30 @@ struct OTBMetadata_EXPORT RPCParam
return oss.str();
};
// Equality comparison with tolerance
template <class BinaryPredicate>
bool Compare(const RPCParam & other, const BinaryPredicate & p) const
{
return p(LineOffset, other.LineOffset)
&& p(SampleOffset, other.SampleOffset)
&& p(LatOffset, other.LatOffset)
&& p(LonOffset, other.LonOffset)
&& p(HeightOffset, other.HeightOffset)
&& p(LineScale, other.LineScale)
&& p(SampleScale, other.SampleScale)
&& p(LatScale, other.LatScale)
&& p(LonScale, other.LonScale)
&& p(HeightScale, other.HeightScale)
&& std::equal(std::begin(LineNum), std::end(LineNum), std::begin(other.LineNum),p)
&& std::equal(std::begin(LineDen), std::end(LineDen), std::begin(other.LineDen),p)
&& std::equal(std::begin(SampleNum), std::end(SampleNum), std::begin(other.SampleNum),p)
&& std::equal(std::begin(SampleDen), std::end(SampleDen), std::begin(other.SampleDen),p);
}
// Equality comparison operator (hidden friend idiom)
friend bool operator==(const RPCParam & lhs, const RPCParam & rhs)
{
return lhs.LineOffset == rhs.LineOffset
&& lhs.SampleOffset == rhs.SampleOffset
&& lhs.LatOffset == rhs.LatOffset
&& lhs.LonOffset == rhs.LonOffset
&& lhs.HeightOffset == rhs.HeightOffset
&& lhs.LineScale == rhs.LineScale
&& lhs.SampleScale == rhs.SampleScale
&& lhs.LatScale == rhs.LatScale
&& lhs.LonScale == rhs.LonScale
&& lhs.HeightScale == rhs.HeightScale
&& std::equal(std::begin(lhs.LineNum), std::end(lhs.LineNum), std::begin(rhs.LineNum))
&& std::equal(std::begin(lhs.LineDen), std::end(lhs.LineDen), std::begin(rhs.LineDen))
&& std::equal(std::begin(lhs.SampleNum), std::end(lhs.SampleNum), std::begin(rhs.SampleNum))
&& std::equal(std::begin(lhs.SampleDen), std::end(lhs.SampleDen), std::begin(rhs.SampleDen));
return lhs.Compare(rhs, [](double rhs, double lhs){return rhs == lhs;});
}
};
......
......@@ -116,6 +116,7 @@ ImageMetadataInterfaceFactory
{
// silent catch of MissingMetadataException
// just means that this IMI can't parse the file
std::cout << e.what() << std::endl;
}
}
else
......
......@@ -23,7 +23,7 @@
namespace otb
{
bool MetadataSupplierInterface::HasValue(std::string const& path, int band)
bool MetadataSupplierInterface::HasValue(std::string const& path, int band) const
{
bool hasValue;
const std::string ret = GetMetadataValue(path, hasValue, band);
......
......@@ -1857,7 +1857,7 @@ void PleiadesImageMetadataInterface::FetchTabulatedPhysicalGain(const MetaData::
}
else
{
itkExceptionMacro(<< "Invalid metadata, bad sensor id");
otbGenericExceptionMacro(MissingMetadataException, << "Invalid metadata, bad sensor id");
}
for (auto & band: m_Imd.Bands)
......@@ -1865,7 +1865,7 @@ void PleiadesImageMetadataInterface::FetchTabulatedPhysicalGain(const MetaData::
auto gain = bandNameToPhysicalGain.find(band[MDStr::BandName]);
if (gain == bandNameToPhysicalGain.end())
{
itkExceptionMacro(<< "Cannot find the physical gain associated with " << band[MDStr::BandName]);
otbGenericExceptionMacro(MissingMetadataException, << "Cannot find the physical gain associated with " << band[MDStr::BandName]);
}
else
{
......@@ -1881,6 +1881,7 @@ void PleiadesImageMetadataInterface::FetchSolarIrradiance(const std::vector<doub
std::unordered_map<std::string, double> defaultSolarIrradiance;
const auto & sensorID = m_Imd[MDStr::SensorID];
if (sensorID == "PHR 1A")
{
defaultSolarIrradiance = { {"P", 1548.71},
......@@ -1893,7 +1894,8 @@ void PleiadesImageMetadataInterface::FetchSolarIrradiance(const std::vector<doub
}
else
{
itkExceptionMacro(<< "Invalid metadata, bad sensor id");
otbGenericExceptionMacro(MissingMetadataException,
<< "Invalid metadata, bad sensor id")
}
......@@ -2215,25 +2217,42 @@ void PleiadesImageMetadataInterface::FetchSpectralSensitivity(const std::string
void PleiadesImageMetadataInterface::Parse(const MetadataSupplierInterface & mds)
{
bool hasValue = false;
auto metadatatype = mds.GetMetadataValue("METADATATYPE", hasValue);
auto dimapV1Filename = itksys::SystemTools::GetParentDirectory(mds.GetResourceFile()) + "/PHRDIMAP.XML";
//auto dimapV1Filename = itksys::SystemTools::GetParentDirectory(mds.GetResourceFile()) + "/PHRDIMAP.XML";
DimapMetadataHelper helper;
helper.Parse(mds);
const auto & dimapData = helper.GetDimapData();
// Satellite ID is either PHR 1A or PHR 1B
// DimapV2 case
if (mds.GetAs<std::string>("", "IMAGERY/SATELLITEID").find("PHR") != std::string::npos)
{
helper.ParseDimapV2(mds);
m_Imd.Add(MDStr::GeometricLevel, helper.GetDimapData().ProcessingLevel);
if (dimapData.mission == "PHR")
// fill RPC model
if (m_Imd[MDStr::GeometricLevel] == "SENSOR")
{
FetchRPC(mds);
}
}
// Geom case
else if (mds.GetAs<std::string>("", "support_data.sensorID").find("PHR") != std::string::npos)
{
m_Imd.Add(MDStr::SensorID, dimapData.mission + " " +dimapData.missionIndex);
m_Imd.Add(MDStr::Mission, "Pléiades");
helper.ParseGeom(mds);
m_Imd.Add(MDStr::GeometricLevel, helper.GetDimapData().ProcessingLevel);
}
else
{
otbGenericExceptionMacro(MissingMetadataException,<<"Sensor ID doesn't start with PHR : '"<<dimapData.mission<<"'")
otbGenericExceptionMacro(MissingMetadataException,<<"Sensor ID doesn't start with PHR")
}
const auto & dimapData = helper.GetDimapData();
m_Imd.Add(MDStr::SensorID, dimapData.mission + " " +dimapData.missionIndex);
m_Imd.Add(MDStr::Mission, "Pléiades");
if (dimapData.BandIDs.size() == m_Imd.Bands.size())
{
auto bandId = dimapData.BandIDs.begin();
......@@ -2280,14 +2299,6 @@ void PleiadesImageMetadataInterface::Parse(const MetadataSupplierInterface & mds
otbGenericExceptionMacro(MissingMetadataException,
<< "The number of bands in image metadatas is incoherent with the DIMAP product")
}
m_Imd.Add(MDStr::GeometricLevel, dimapData.ProcessingLevel);
// fill RPC model
if (m_Imd[MDStr::GeometricLevel] == "SENSOR")
{
FetchRPC(mds);
}
}
} // end namespace otb
......@@ -1698,7 +1698,7 @@ void Spot6ImageMetadataInterface::Parse(const MetadataSupplierInterface & mds)
{
DimapMetadataHelper helper;
helper.Parse(mds);
helper.ParseDimapV2(mds);
const auto & dimapData = helper.GetDimapData();
if (dimapData.mission == "SPOT")
......
......@@ -457,6 +457,7 @@ set(Sentinel1_filename LARGEINPUT{SENTINEL1/S1A_S6_SLC__1SSV_20150619T195043})
set(spot5_2_geom_file ${INPUTDATA}/spot5/spot5-1.geom)
set(formosat_geom_file ${INPUTDATA}/FORMOSAT_ROI_1000_100.geom)
set(pleiades_geom_file ${INPUTDATA}/pleiades/maido.geom)
foreach(sensor ${sensor_list})
......@@ -465,7 +466,7 @@ otb_add_test(NAME ioTvImageMetadataInterfaceTest_${sensor} COMMAND otbMetadataTe
--compare-ascii 0
${BASELINE_FILES}/ioTvImageMetadataInterfaceTest_${sensor}.txt
${TEMP}/ioTvImageMetadataInterfaceTest_${sensor}.txt
--compare-metadata 0
--compare-metadata ${EPSILON_9}
${${sensor}_filename}
${${sensor}_filename}?&geom=${${sensor}_geom_file}
otbImageMetadataInterfaceTest
......
......@@ -486,12 +486,14 @@ void ImageFileReader<TOutputImage, ConvertPixelTraits>::GenerateOutputInformatio
{
GeomMetadataSupplier geomSupplier(m_FilenameHelper->GetExtGEOMFileName());
UpdateImdWithImiAndMds(imd, geomSupplier);
geomSupplier.FetchRPC(imd);
}
// Case 2: attached geom (if present)
else if (!m_FilenameHelper->GetSkipGeom() && itksys::SystemTools::FileExists(attachedGeom))
{
GeomMetadataSupplier geomSupplier(attachedGeom);
UpdateImdWithImiAndMds(imd, geomSupplier);
geomSupplier.FetchRPC(imd);
}
// Case 3: tags in file
else
......
......@@ -1723,7 +1723,7 @@ int TestHelper::RegressionTestMetaData(const char* testImageFilename, const char
errcount += CompareMetadataDict(baselineImageMetadata.ExtraKeys,
testImageMetadata.ExtraKeys,
m_ReportErrors,
untestedExtra);
untestedExtra);
if (baselineImageMetadata.Has(MDGeom::RPC))
......@@ -1737,8 +1737,10 @@ int TestHelper::RegressionTestMetaData(const char* testImageFilename, const char
}
}
if (!(boost::any_cast<Projection::RPCParam>(baselineImageMetadata[MDGeom::RPC])
== boost::any_cast<Projection::RPCParam>(testImageMetadata[MDGeom::RPC])))
//if (!(boost::any_cast<Projection::RPCParam>(baselineImageMetadata[MDGeom::RPC])
// == boost::any_cast<Projection::RPCParam>(testImageMetadata[MDGeom::RPC])))
if (! ( boost::any_cast<Projection::RPCParam>(baselineImageMetadata[MDGeom::RPC]).Compare(
boost::any_cast<Projection::RPCParam>(testImageMetadata[MDGeom::RPC]), compareDouble)))
{
errcount++;
if (m_ReportErrors)
......
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