From 4a927475193ee5b3fa6f0206328b317f63fcaac7 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Thu, 28 Oct 2021 16:26:32 +0200 Subject: [PATCH 01/21] ENH: Add ImageMetadata to SWIG --- .../Core/Metadata/include/otbMetaDataEnum.h | 132 ++++++++++ .../Core/Metadata/include/otbMetaDataKey.h | 110 +------- Modules/Core/Metadata/src/otbMetaDataKey.cxx | 2 - Modules/Wrappers/SWIG/src/otbApplication.i | 18 +- Modules/Wrappers/SWIG/src/otbImageMetadata.i | 238 ++++++++++++++++++ 5 files changed, 377 insertions(+), 123 deletions(-) create mode 100644 Modules/Core/Metadata/include/otbMetaDataEnum.h create mode 100644 Modules/Wrappers/SWIG/src/otbImageMetadata.i diff --git a/Modules/Core/Metadata/include/otbMetaDataEnum.h b/Modules/Core/Metadata/include/otbMetaDataEnum.h new file mode 100644 index 0000000000..686013ed29 --- /dev/null +++ b/Modules/Core/Metadata/include/otbMetaDataEnum.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2005-2021 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. + */ + +#ifndef otbMetaDataEnum_h +#define otbMetaDataEnum_h + +namespace otb +{ +/** Metadata as double*/ +enum class MDNum +{ +// generic + TileHintX, + TileHintY, + DataType, + NoData, + OrbitNumber, + NumberOfLines, + NumberOfColumns, + AverageSceneHeight, +// Display + RedDisplayChannel, + GreenDisplayChannel, + BlueDisplayChannel, +// optical section + PhysicalGain, + PhysicalBias, + SolarIrradiance, + SunElevation, + SunAzimuth, + SatElevation, + SatAzimuth, + SpectralStep, + SpectralMin, + SpectralMax, +// SAR section + CalScale, + CalFactor, + PRF, + RSF, + RadarFrequency, + CenterIncidenceAngle, + RescalingFactor, + LineSpacing, + PixelSpacing, + RangeTimeFirstPixel, + RangeTimeLastPixel, + END +}; + +/** Metadata as std::string */ +enum class MDStr +{ + SensorID, + Mission, + Instrument, + InstrumentIndex, + BandName, + EnhancedBandName, + ProductType, + GeometricLevel, + RadiometricLevel, + Polarization, + Mode, + Swath, + OrbitDirection, + BeamMode, + BeamSwath, + AreaOrPoint, + LayerType, + MetadataType, + OtbVersion, + END +}; + +/** Metadata as LUT 1D */ +enum class MDL1D +{ + SpectralSensitivity, + END +}; + +/** Metadata as LUT 2D */ +enum class MDL2D +{ + // Sar calibration lut ... + END +}; + +/** Metadata as Time */ +enum class MDTime +{ + AcquisitionDate, + ProductionDate, + AcquisitionStartTime, + AcquisitionStopTime, + END +}; + +enum class MDGeom +{ + ProjectionWKT, // -> string + ProjectionEPSG, // -> int + ProjectionProj, // -> string + RPC, // -> RPCParam + SAR, // -> SARParam + SARCalib, // -> SARCalib + SensorGeometry, // -> boost::any + GCP, // -> GCPParam + Adjustment, // -> ? + END +}; +} + +#endif diff --git a/Modules/Core/Metadata/include/otbMetaDataKey.h b/Modules/Core/Metadata/include/otbMetaDataKey.h index 512698711e..b1414e23b4 100644 --- a/Modules/Core/Metadata/include/otbMetaDataKey.h +++ b/Modules/Core/Metadata/include/otbMetaDataKey.h @@ -24,17 +24,18 @@ #include #include #include +#include #include #include #include "itkDataObject.h" #include "itkVariableLengthVector.h" + #include "OTBMetadataExport.h" #include "otbStringUtils.h" #include "otbJoinContainer.h" - -#include +#include "otbMetaDataEnum.h" namespace otb { @@ -121,111 +122,6 @@ typedef std::vector BoolVectorType; typedef itk::VariableLengthVector VariableLengthVectorType; } -/** Metadata as double*/ -enum class MDNum -{ -// generic - TileHintX, - TileHintY, - DataType, - NoData, - OrbitNumber, - NumberOfLines, - NumberOfColumns, - AverageSceneHeight, -// Display - RedDisplayChannel, - GreenDisplayChannel, - BlueDisplayChannel, -// optical section - PhysicalGain, - PhysicalBias, - SolarIrradiance, - SunElevation, - SunAzimuth, - SatElevation, - SatAzimuth, - SpectralStep, - SpectralMin, - SpectralMax, -// SAR section - CalScale, - CalFactor, - PRF, - RSF, - RadarFrequency, - CenterIncidenceAngle, - RescalingFactor, - LineSpacing, - PixelSpacing, - RangeTimeFirstPixel, - RangeTimeLastPixel, - END -}; - -/** Metadata as std::string */ -enum class MDStr -{ - SensorID, - Mission, - Instrument, - InstrumentIndex, - BandName, - EnhancedBandName, - ProductType, - GeometricLevel, - RadiometricLevel, - Polarization, - Mode, - Swath, - OrbitDirection, - BeamMode, - BeamSwath, - AreaOrPoint, - LayerType, - MetadataType, - OtbVersion, - END -}; - -/** Metadata as LUT 1D */ -enum class MDL1D -{ - SpectralSensitivity, - END -}; - -/** Metadata as LUT 2D */ -enum class MDL2D -{ - // Sar calibration lut ... - END -}; - -/** Metadata as Time */ -enum class MDTime -{ - AcquisitionDate, - ProductionDate, - AcquisitionStartTime, - AcquisitionStopTime, - END -}; - -enum class MDGeom -{ - ProjectionWKT, // -> string - ProjectionEPSG, // -> int - ProjectionProj, // -> string - RPC, // -> RPCParam - SAR, // -> SARParam - SARCalib, // -> SARCalib - SensorGeometry, // -> boost::any - GCP, // -> GCPParam - Adjustment, // -> ? - END -}; - namespace MetaData { diff --git a/Modules/Core/Metadata/src/otbMetaDataKey.cxx b/Modules/Core/Metadata/src/otbMetaDataKey.cxx index 65f9afb66f..28610ac1b6 100644 --- a/Modules/Core/Metadata/src/otbMetaDataKey.cxx +++ b/Modules/Core/Metadata/src/otbMetaDataKey.cxx @@ -369,8 +369,6 @@ void LUT::FromString(std::string str) template class LUT<1>; template class LUT<2>; -// array > -// boost::flat_map<> MDNumBmType MDNumNames = bimapGenerator(std::map { {MDNum::TileHintX,"TileHintX"}, {MDNum::TileHintY,"TileHintY"}, diff --git a/Modules/Wrappers/SWIG/src/otbApplication.i b/Modules/Wrappers/SWIG/src/otbApplication.i index e23b06c64d..72188c5cb9 100644 --- a/Modules/Wrappers/SWIG/src/otbApplication.i +++ b/Modules/Wrappers/SWIG/src/otbApplication.i @@ -34,6 +34,8 @@ %include "itkMacro.i" %include "itkBase.i" +%include "otbImageMetadata.i" + #if OTB_SWIGNUMPY %include "numpy.i" @@ -146,20 +148,6 @@ public: // TODO : finish wrapping }; -class GCP -{ -public: - std::string m_Id; - std::string m_Info; - double m_GCPCol; - double m_GCPRow; - double m_GCPX; - double m_GCPY; - double m_GCPZ; - GCP(); - void Print(std::ostream& os) const; -}; - } // end of namespace otb #if SWIGPYTHON @@ -310,6 +298,8 @@ public: std::string GetImageProjection(const std::string & key, unsigned int idx = 0); unsigned long PropagateRequestedRegion(const std::string & key, itk::ImageRegion<2> region, unsigned int idx = 0); itk::ImageRegion<2> GetImageRequestedRegion(const std::string & key, unsigned int idx = 0); + const otb::ImageMetadata &GetImageMetadata(const std::string& key, unsigned int idx = 0); + void SetImageMetadata(const otb::ImageMetadata & imd, const std::string& key, unsigned int idx = 0); itkMetaDataDictionary GetImageMetaData(const std::string & key, unsigned int idx = 0); otb::Wrapper::ImagePixelType GetImageBasePixelType(const std::string & key, unsigned int idx = 0); diff --git a/Modules/Wrappers/SWIG/src/otbImageMetadata.i b/Modules/Wrappers/SWIG/src/otbImageMetadata.i new file mode 100644 index 0000000000..8e9abd7159 --- /dev/null +++ b/Modules/Wrappers/SWIG/src/otbImageMetadata.i @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2005-2021 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. + */ + +%module("threads"=1) otbImageMetadata + +%{ +#include "itkBase.includes" +#include "otbWrapperSWIGIncludes.h" +#include // std::string +#include +#include "otbMetaDataEnum.h" +#include "otbImageMetadata.h" +#define SWIG_FILE_WITH_INIT +%} + +// Language specific extension +%include "Python.i" +%include "itkMacro.i" +%include "itkBase.i" + +%include "otbMetaDataEnum.h" + +namespace otb +{ + +class GCP +{ +public: + std::string m_Id; + std::string m_Info; + double m_GCPCol; + double m_GCPRow; + double m_GCPX; + double m_GCPY; + double m_GCPZ; + GCP(); + void Print(std::ostream& os) const; +}; + +namespace MetaData +{ + +struct LUTAxis +{ + int Size; + double Origin; + double Spacing; + std::vector Values; + std::string ToJSON(bool multiline=false) const; +}; + +template class LUT +{ +public: + LUTAxis Axis[VDim]; + std::vector Array; + std::string ToJSON(bool multiline=false) const; + std::string ToString() const; + void FromString(std::string); +}; + +%template(lut1d) LUT<1>; +%template(lut2d) LUT<2>; +} // end namespace MetaData + +class ImageMetadataBase +{ +}; + +class ImageMetadata: public ImageMetadataBase +{ +public: + std::vector Bands; +}; + +}; + +%extend otb::ImageMetadataBase{ + + bool is_num(const std::string& key) { + auto it = otb::MetaData::MDNumNames.right.find(key); + return it != otb::MetaData::MDNumNames.right.end(); + } + + double get_num(const std::string& key) { + auto it = otb::MetaData::MDNumNames.right.find(key); + return $self->operator[](it->second); + } + + bool is_str(const std::string& key) { + auto it = otb::MetaData::MDStrNames.right.find(key); + return it != otb::MetaData::MDStrNames.right.end(); + } + + std::string get_str(const std::string& key) { + auto it = otb::MetaData::MDStrNames.right.find(key); + return $self->operator[](it->second); + } + + bool is_l1d(const std::string& key) { + auto it = otb::MetaData::MDL1DNames.right.find(key); + return it != otb::MetaData::MDL1DNames.right.end(); + } + + otb::MetaData::LUT1D get_l1d(const std::string& key) { + auto it = otb::MetaData::MDL1DNames.right.find(key); + return $self->operator[](it->second); + } + + bool is_l2d(const std::string& key) { + auto it = otb::MetaData::MDL2DNames.right.find(key); + return it != otb::MetaData::MDL2DNames.right.end(); + } + + otb::MetaData::LUT2D get_l2d(const std::string& key) { + auto it = otb::MetaData::MDL2DNames.right.find(key); + return $self->operator[](it->second); + } + + bool is_time(const std::string& key) { + auto it = otb::MetaData::MDTimeNames.right.find(key); + return it != otb::MetaData::MDTimeNames.right.end(); + } + + otb::MetaData::Time get_time(const std::string& key) { + auto it = otb::MetaData::MDTimeNames.right.find(key); + return $self->operator[](it->second); + } + + bool is_geom(const std::string& key) { + auto it = otb::MetaData::MDGeomNames.right.find(key); + return it != otb::MetaData::MDGeomNames.right.end(); + } + + bool has(const std::string& key) const { + auto it_num = otb::MetaData::MDNumNames.right.find(key); + if (it_num != otb::MetaData::MDNumNames.right.end()) + return $self->Has(it_num->second); + + auto it_str = otb::MetaData::MDStrNames.right.find(key); + if (it_str != otb::MetaData::MDStrNames.right.end()) + return $self->Has(it_str->second); + + auto it_l1d = otb::MetaData::MDL1DNames.right.find(key); + if (it_l1d != otb::MetaData::MDL1DNames.right.end()) + return $self->Has(it_l1d->second); + + auto it_l2d = otb::MetaData::MDL2DNames.right.find(key); + if (it_l2d != otb::MetaData::MDL2DNames.right.end()) + return $self->Has(it_l2d->second); + + auto it_time = otb::MetaData::MDTimeNames.right.find(key); + if (it_time != otb::MetaData::MDTimeNames.right.end()) + return $self->Has(it_time->second); + + /* TODO: the geom part of the Imagemetadata is not wrapped yet + auto it_geom = otb::MetaData::MDGeomNames.right.find(key); + if (it_geom != otb::MetaData::MDGeomNames.right.end()) + return $self->Has(it_geom->second);*/ + + return false; + } + + void __setitem__(const std::string& key, const double val) { + auto it = otb::MetaData::MDNumNames.right.find(key); + if (it != otb::MetaData::MDNumNames.right.end()) + $self->Add(it->second, val); + else + $self->Add(key, std::to_string(val)); + } + void __setitem__(const std::string& key, const std::string& val) { + auto it = otb::MetaData::MDStrNames.right.find(key); + if (it != otb::MetaData::MDStrNames.right.end()) + $self->Add(it->second, val); + else + $self->Add(key, val); + } + void __setitem__(const std::string& key, const otb::MetaData::LUT1D& val) { + auto it = otb::MetaData::MDL1DNames.right.find(key); + if (it != otb::MetaData::MDL1DNames.right.end()) + $self->Add(it->second, val); + else + $self->Add(key, val.ToString()); + } + void __setitem__(const std::string& key, const otb::MetaData::LUT2D& val) { + auto it = otb::MetaData::MDL2DNames.right.find(key); + if (it != otb::MetaData::MDL2DNames.right.end()) + $self->Add(it->second, val); + else + $self->Add(key, val.ToString()); + } + void __setitem__(const std::string& key, const otb::MetaData::Time& val) { + auto it = otb::MetaData::MDTimeNames.right.find(key); + if (it != otb::MetaData::MDTimeNames.right.end()) + $self->Add(it->second, val); + else + { + std::ostringstream timeStream; + timeStream << val; + $self->Add(key, timeStream.str()); + } + } + + %pythoncode { + def __getitem__(self, key): + if self.is_num(key): + return self.get_num(key) + elif self.is_str(key): + return self.get_str(key) + elif self.is_l1d(key): + return self.get_l1d(key) + elif self.is_l2d(key): + return self.get_l2d(key) + elif self.is_time(key): + return self.get_time(key) + elif self.is_geom(key): + return None # TODO: the geom part of the Imagemetadata is not wrapped yet + else: + return None + } +} -- GitLab From f0429ba56959411abdc133b27c0b3f623471b1fd Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Wed, 24 Nov 2021 06:39:33 +0100 Subject: [PATCH 02/21] ENH: Add Get/SetImageMetadata to otbWrapperApplication --- .../include/otbWrapperApplication.h | 5 +++++ .../ApplicationEngine/src/otbWrapperApplication.cxx | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h index 35330b327e..18879d3fc3 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h @@ -825,6 +825,11 @@ public: * the index of the largest possible region starts at (0,0).*/ ImageBaseType::RegionType GetImageRequestedRegion(const std::string& key, unsigned int idx = 0); + /** Get/Set the ImageMetadata of the image parameter 'key'. The optional 'idx' + * allows selecting the image in an InputImageList.*/ + const ImageMetadata &GetImageMetadata(const std::string& key, unsigned int idx = 0); + void SetImageMetadata(const ImageMetadata & imd, const std::string& key, unsigned int idx = 0); + /** Returns a copy of the metadata dictionary of the image */ itk::MetaDataDictionary GetImageMetaData(const std::string& key, unsigned int idx = 0); diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx index 021e763dde..c9a62a8bb0 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx @@ -1670,6 +1670,18 @@ ImageBaseType::RegionType Application::GetImageRequestedRegion(const std::string return requested; } +const otb::ImageMetadata& Application::GetImageMetadata(const std::string& key, unsigned int idx) +{ + ImageBaseType* image = this->GetParameterImageBase(key, idx); + return dynamic_cast(image)->GetImageMetadata(); +} + +void Application::SetImageMetadata(const ImageMetadata & imd, const std::string& key, unsigned int idx) +{ + ImageBaseType* image = this->GetParameterImageBase(key, idx); + dynamic_cast(image)->SetImageMetadata(imd); +} + itk::MetaDataDictionary Application::GetImageMetaData(const std::string& key, unsigned int idx) { ImageBaseType* image = this->GetParameterImageBase(key, idx); -- GitLab From ea860e81aebf8ed0f625055ce5c0fa9a0f0f7691 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Wed, 24 Nov 2021 11:46:30 +0100 Subject: [PATCH 03/21] FIX: Remove otbMetaDataEnum --- .../Core/Metadata/include/otbMetaDataEnum.h | 132 ------------------ .../Core/Metadata/include/otbMetaDataKey.h | 106 +++++++++++++- Modules/Wrappers/SWIG/src/otbImageMetadata.i | 4 +- 3 files changed, 106 insertions(+), 136 deletions(-) delete mode 100644 Modules/Core/Metadata/include/otbMetaDataEnum.h diff --git a/Modules/Core/Metadata/include/otbMetaDataEnum.h b/Modules/Core/Metadata/include/otbMetaDataEnum.h deleted file mode 100644 index 686013ed29..0000000000 --- a/Modules/Core/Metadata/include/otbMetaDataEnum.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2005-2021 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. - */ - -#ifndef otbMetaDataEnum_h -#define otbMetaDataEnum_h - -namespace otb -{ -/** Metadata as double*/ -enum class MDNum -{ -// generic - TileHintX, - TileHintY, - DataType, - NoData, - OrbitNumber, - NumberOfLines, - NumberOfColumns, - AverageSceneHeight, -// Display - RedDisplayChannel, - GreenDisplayChannel, - BlueDisplayChannel, -// optical section - PhysicalGain, - PhysicalBias, - SolarIrradiance, - SunElevation, - SunAzimuth, - SatElevation, - SatAzimuth, - SpectralStep, - SpectralMin, - SpectralMax, -// SAR section - CalScale, - CalFactor, - PRF, - RSF, - RadarFrequency, - CenterIncidenceAngle, - RescalingFactor, - LineSpacing, - PixelSpacing, - RangeTimeFirstPixel, - RangeTimeLastPixel, - END -}; - -/** Metadata as std::string */ -enum class MDStr -{ - SensorID, - Mission, - Instrument, - InstrumentIndex, - BandName, - EnhancedBandName, - ProductType, - GeometricLevel, - RadiometricLevel, - Polarization, - Mode, - Swath, - OrbitDirection, - BeamMode, - BeamSwath, - AreaOrPoint, - LayerType, - MetadataType, - OtbVersion, - END -}; - -/** Metadata as LUT 1D */ -enum class MDL1D -{ - SpectralSensitivity, - END -}; - -/** Metadata as LUT 2D */ -enum class MDL2D -{ - // Sar calibration lut ... - END -}; - -/** Metadata as Time */ -enum class MDTime -{ - AcquisitionDate, - ProductionDate, - AcquisitionStartTime, - AcquisitionStopTime, - END -}; - -enum class MDGeom -{ - ProjectionWKT, // -> string - ProjectionEPSG, // -> int - ProjectionProj, // -> string - RPC, // -> RPCParam - SAR, // -> SARParam - SARCalib, // -> SARCalib - SensorGeometry, // -> boost::any - GCP, // -> GCPParam - Adjustment, // -> ? - END -}; -} - -#endif diff --git a/Modules/Core/Metadata/include/otbMetaDataKey.h b/Modules/Core/Metadata/include/otbMetaDataKey.h index b1414e23b4..2cc23e3898 100644 --- a/Modules/Core/Metadata/include/otbMetaDataKey.h +++ b/Modules/Core/Metadata/include/otbMetaDataKey.h @@ -35,7 +35,6 @@ #include "OTBMetadataExport.h" #include "otbStringUtils.h" #include "otbJoinContainer.h" -#include "otbMetaDataEnum.h" namespace otb { @@ -122,6 +121,111 @@ typedef std::vector BoolVectorType; typedef itk::VariableLengthVector VariableLengthVectorType; } +/** Metadata as double*/ +enum class MDNum +{ +// generic + TileHintX, + TileHintY, + DataType, + NoData, + OrbitNumber, + NumberOfLines, + NumberOfColumns, + AverageSceneHeight, +// Display + RedDisplayChannel, + GreenDisplayChannel, + BlueDisplayChannel, +// optical section + PhysicalGain, + PhysicalBias, + SolarIrradiance, + SunElevation, + SunAzimuth, + SatElevation, + SatAzimuth, + SpectralStep, + SpectralMin, + SpectralMax, +// SAR section + CalScale, + CalFactor, + PRF, + RSF, + RadarFrequency, + CenterIncidenceAngle, + RescalingFactor, + LineSpacing, + PixelSpacing, + RangeTimeFirstPixel, + RangeTimeLastPixel, + END +}; + +/** Metadata as std::string */ +enum class MDStr +{ + SensorID, + Mission, + Instrument, + InstrumentIndex, + BandName, + EnhancedBandName, + ProductType, + GeometricLevel, + RadiometricLevel, + Polarization, + Mode, + Swath, + OrbitDirection, + BeamMode, + BeamSwath, + AreaOrPoint, + LayerType, + MetadataType, + OtbVersion, + END +}; + +/** Metadata as LUT 1D */ +enum class MDL1D +{ + SpectralSensitivity, + END +}; + +/** Metadata as LUT 2D */ +enum class MDL2D +{ + // Sar calibration lut ... + END +}; + +/** Metadata as Time */ +enum class MDTime +{ + AcquisitionDate, + ProductionDate, + AcquisitionStartTime, + AcquisitionStopTime, + END +}; + +enum class MDGeom +{ + ProjectionWKT, // -> string + ProjectionEPSG, // -> int + ProjectionProj, // -> string + RPC, // -> RPCParam + SAR, // -> SARParam + SARCalib, // -> SARCalib + SensorGeometry, // -> boost::any + GCP, // -> GCPParam + Adjustment, // -> ? + END +}; + namespace MetaData { diff --git a/Modules/Wrappers/SWIG/src/otbImageMetadata.i b/Modules/Wrappers/SWIG/src/otbImageMetadata.i index 8e9abd7159..33acb81fbd 100644 --- a/Modules/Wrappers/SWIG/src/otbImageMetadata.i +++ b/Modules/Wrappers/SWIG/src/otbImageMetadata.i @@ -25,7 +25,7 @@ #include "otbWrapperSWIGIncludes.h" #include // std::string #include -#include "otbMetaDataEnum.h" +#include "otbMetaDataKey.h" #include "otbImageMetadata.h" #define SWIG_FILE_WITH_INIT %} @@ -35,8 +35,6 @@ %include "itkMacro.i" %include "itkBase.i" -%include "otbMetaDataEnum.h" - namespace otb { -- GitLab From de5d23ff867a3eced7cf1cfab6cfe9f9095b40d9 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Wed, 24 Nov 2021 12:04:41 +0100 Subject: [PATCH 04/21] ENH: Changes GetImageMetadata's return value from a const reference to a reference --- .../ApplicationEngine/include/otbWrapperApplication.h | 2 +- .../Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx | 4 ++-- Modules/Wrappers/SWIG/src/otbApplication.i | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h index 18879d3fc3..d727fedf64 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h @@ -827,7 +827,7 @@ public: /** Get/Set the ImageMetadata of the image parameter 'key'. The optional 'idx' * allows selecting the image in an InputImageList.*/ - const ImageMetadata &GetImageMetadata(const std::string& key, unsigned int idx = 0); + ImageMetadata &GetImageMetadata(const std::string& key, unsigned int idx = 0); void SetImageMetadata(const ImageMetadata & imd, const std::string& key, unsigned int idx = 0); /** Returns a copy of the metadata dictionary of the image */ diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx index c9a62a8bb0..6676792ebf 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx @@ -1670,10 +1670,10 @@ ImageBaseType::RegionType Application::GetImageRequestedRegion(const std::string return requested; } -const otb::ImageMetadata& Application::GetImageMetadata(const std::string& key, unsigned int idx) +ImageMetadata &Application::GetImageMetadata(const std::string& key, unsigned int idx) { ImageBaseType* image = this->GetParameterImageBase(key, idx); - return dynamic_cast(image)->GetImageMetadata(); + return dynamic_cast(image)->m_Imd; } void Application::SetImageMetadata(const ImageMetadata & imd, const std::string& key, unsigned int idx) diff --git a/Modules/Wrappers/SWIG/src/otbApplication.i b/Modules/Wrappers/SWIG/src/otbApplication.i index 72188c5cb9..8495ff2bd6 100644 --- a/Modules/Wrappers/SWIG/src/otbApplication.i +++ b/Modules/Wrappers/SWIG/src/otbApplication.i @@ -298,7 +298,7 @@ public: std::string GetImageProjection(const std::string & key, unsigned int idx = 0); unsigned long PropagateRequestedRegion(const std::string & key, itk::ImageRegion<2> region, unsigned int idx = 0); itk::ImageRegion<2> GetImageRequestedRegion(const std::string & key, unsigned int idx = 0); - const otb::ImageMetadata &GetImageMetadata(const std::string& key, unsigned int idx = 0); + otb::ImageMetadata &GetImageMetadata(const std::string& key, unsigned int idx = 0); void SetImageMetadata(const otb::ImageMetadata & imd, const std::string& key, unsigned int idx = 0); itkMetaDataDictionary GetImageMetaData(const std::string & key, unsigned int idx = 0); otb::Wrapper::ImagePixelType GetImageBasePixelType(const std::string & key, unsigned int idx = 0); -- GitLab From 02b333c4b68d1e957f4be44e987a1f5e569d84e0 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Wed, 24 Nov 2021 13:39:55 +0100 Subject: [PATCH 05/21] ENH: Rename GetImageMetaData to GetMetadataDictionary --- .../ApplicationEngine/include/otbWrapperApplication.h | 2 +- .../Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx | 2 +- Modules/Wrappers/SWIG/src/otbApplication.i | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h index d727fedf64..48a39e856e 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h @@ -831,7 +831,7 @@ public: void SetImageMetadata(const ImageMetadata & imd, const std::string& key, unsigned int idx = 0); /** Returns a copy of the metadata dictionary of the image */ - itk::MetaDataDictionary GetImageMetaData(const std::string& key, unsigned int idx = 0); + itk::MetaDataDictionary GetMetadataDictionary(const std::string& key, unsigned int idx = 0); /** Find out what is the pixel type from an image parameter * This function assumes that the underlying object is either an otb::Image diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx index 6676792ebf..c8f6fb2e42 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx @@ -1682,7 +1682,7 @@ void Application::SetImageMetadata(const ImageMetadata & imd, const std::string& dynamic_cast(image)->SetImageMetadata(imd); } -itk::MetaDataDictionary Application::GetImageMetaData(const std::string& key, unsigned int idx) +itk::MetaDataDictionary Application::GetMetadataDictionary(const std::string& key, unsigned int idx) { ImageBaseType* image = this->GetParameterImageBase(key, idx); return image->GetMetaDataDictionary(); diff --git a/Modules/Wrappers/SWIG/src/otbApplication.i b/Modules/Wrappers/SWIG/src/otbApplication.i index 8495ff2bd6..a348391e48 100644 --- a/Modules/Wrappers/SWIG/src/otbApplication.i +++ b/Modules/Wrappers/SWIG/src/otbApplication.i @@ -300,7 +300,7 @@ public: itk::ImageRegion<2> GetImageRequestedRegion(const std::string & key, unsigned int idx = 0); otb::ImageMetadata &GetImageMetadata(const std::string& key, unsigned int idx = 0); void SetImageMetadata(const otb::ImageMetadata & imd, const std::string& key, unsigned int idx = 0); - itkMetaDataDictionary GetImageMetaData(const std::string & key, unsigned int idx = 0); + itkMetaDataDictionary GetMetadataDictionary(const std::string & key, unsigned int idx = 0); otb::Wrapper::ImagePixelType GetImageBasePixelType(const std::string & key, unsigned int idx = 0); itkProcessObject* GetProgressSource() const; @@ -887,7 +887,7 @@ class ApplicationProxy(object): output["spacing"] = self.GetImageSpacing(paramKey) output["size"] = self.GetImageSize(paramKey) output["region"] = self.GetImageRequestedRegion(paramKey) - output["metadata"] = self.GetImageMetaData(paramKey) + output["metadata"] = self.GetMetadataDictionary(paramKey) return output } -- GitLab From 8089441afea24e40a709a1445cfe552cd655e83a Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Thu, 25 Nov 2021 11:12:56 +0100 Subject: [PATCH 06/21] ENH: The python API provides an ImageMetadata in the image dictionary --- Modules/Wrappers/SWIG/src/otbApplication.i | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Wrappers/SWIG/src/otbApplication.i b/Modules/Wrappers/SWIG/src/otbApplication.i index a348391e48..a349854067 100644 --- a/Modules/Wrappers/SWIG/src/otbApplication.i +++ b/Modules/Wrappers/SWIG/src/otbApplication.i @@ -482,7 +482,7 @@ public: itk::Vector spacing, itk::Size<2> size, itk::ImageRegion<2> bufferRegion, - itkMetaDataDictionary metadata) + otb::ImageMetadata metadata) { img->SetOrigin(origin); otb::internal::SetSignedSpacing(img, spacing); @@ -496,7 +496,7 @@ public: } img->SetRequestedRegion(bufferRegion); img->SetBufferedRegion(bufferRegion); - img->SetMetaDataDictionary(metadata); + dynamic_cast(img)->SetImageMetadata(metadata); } } /* end of %extend */ #endif /* OTB_SWIGNUMPY */ @@ -887,7 +887,7 @@ class ApplicationProxy(object): output["spacing"] = self.GetImageSpacing(paramKey) output["size"] = self.GetImageSize(paramKey) output["region"] = self.GetImageRequestedRegion(paramKey) - output["metadata"] = self.GetMetadataDictionary(paramKey) + output["metadata"] = self.GetImageMetadata(paramKey) return output } -- GitLab From 3f83a2dee8a2a0ead46ab36c908c9378669033b4 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Thu, 25 Nov 2021 14:54:26 +0100 Subject: [PATCH 07/21] ENH: Wrapping of GetProjected* functions --- Modules/Wrappers/SWIG/src/otbImageMetadata.i | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Modules/Wrappers/SWIG/src/otbImageMetadata.i b/Modules/Wrappers/SWIG/src/otbImageMetadata.i index 33acb81fbd..c3996c1d3b 100644 --- a/Modules/Wrappers/SWIG/src/otbImageMetadata.i +++ b/Modules/Wrappers/SWIG/src/otbImageMetadata.i @@ -80,6 +80,10 @@ public: class ImageMetadataBase { +public: + std::string GetProjectedGeometry() const; + std::string GetProjectionWKT() const; + std::string GetProjectionProj() const; }; class ImageMetadata: public ImageMetadataBase @@ -168,10 +172,9 @@ public: if (it_time != otb::MetaData::MDTimeNames.right.end()) return $self->Has(it_time->second); - /* TODO: the geom part of the Imagemetadata is not wrapped yet auto it_geom = otb::MetaData::MDGeomNames.right.find(key); if (it_geom != otb::MetaData::MDGeomNames.right.end()) - return $self->Has(it_geom->second);*/ + return $self->Has(it_geom->second); return false; } @@ -215,6 +218,13 @@ public: $self->Add(key, timeStream.str()); } } + void __setitem__(const std::string& key, const boost::any val) { + auto it = otb::MetaData::MDGeomNames.right.find(key); + if (it != otb::MetaData::MDGeomNames.right.end()) + $self->Add(it->second, val); + else + throw std::runtime_error("[" + key + "] is not a valid geometric key"); + } %pythoncode { def __getitem__(self, key): -- GitLab From 412acd5e09c9f76e33fcfcd66f26864906c9dbaf Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Thu, 25 Nov 2021 15:20:39 +0100 Subject: [PATCH 08/21] FIX: Renamed GetImageMetaData to GetMetadataDictionary --- .../ApplicationEngine/test/otbWrapperImageInterface.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Wrappers/ApplicationEngine/test/otbWrapperImageInterface.cxx b/Modules/Wrappers/ApplicationEngine/test/otbWrapperImageInterface.cxx index 1d45e7e415..179b1f75f1 100644 --- a/Modules/Wrappers/ApplicationEngine/test/otbWrapperImageInterface.cxx +++ b/Modules/Wrappers/ApplicationEngine/test/otbWrapperImageInterface.cxx @@ -64,7 +64,7 @@ int otbWrapperImageInterface(int argc, char* argv[]) ofs << "ProjectionRef:" << std::endl; ofs << app1->GetImageProjection("out") << std::endl; - itk::MetaDataDictionary dict = app1->GetImageMetaData("out"); + itk::MetaDataDictionary dict = app1->GetMetadataDictionary("out"); ofs << "Dictionary keys:" << std::endl; for (auto& key : dict.GetKeys()) { -- GitLab From 3ed2a118ef1588a64ab56af411bca14d65d80ea7 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Thu, 25 Nov 2021 15:31:30 +0100 Subject: [PATCH 09/21] DOC: Update Python API's doc with renaming of GetImageMetaData and the new GetImageMetadata --- Documentation/Cookbook/rst/PythonAPI.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/Cookbook/rst/PythonAPI.rst b/Documentation/Cookbook/rst/PythonAPI.rst index fe93cf129b..818c5f933e 100644 --- a/Documentation/Cookbook/rst/PythonAPI.rst +++ b/Documentation/Cookbook/rst/PythonAPI.rst @@ -328,13 +328,15 @@ functions: +---------------------------------+---------------------------------------+ | ``GetImageProjection(...)`` | Projection WKT string | +---------------------------------+---------------------------------------+ -| ``GetImageMetaData(...)`` | the entire MetaDataDictionary | +| ``GetMetadataDictionary(...)`` | the entire MetaDataDictionary | +---------------------------------+---------------------------------------+ | ``GetImageRequestedRegion(...)``| requested region | +---------------------------------+---------------------------------------+ | ``GetImageBasePixelType(...)`` | pixel type of the underlying | | | Image/VectorImage. | +---------------------------------+---------------------------------------+ +| ``GetImageMetadata(...)`` | the ImateMetadata object | ++---------------------------------+---------------------------------------+ All these getters functions use the following arguments: -- GitLab From a0a1a8a31d02b9584073f6100610be0d15a55128 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Fri, 26 Nov 2021 06:10:04 +0100 Subject: [PATCH 10/21] DOC: Add the list of available keys in pyhton api documentation. --- Documentation/Cookbook/CMakeLists.txt | 10 +++ .../Scripts/otbGeneratePythonApiRstDoc.py | 46 +++++++++++++ .../rst/{ => templates}/PythonAPI.rst | 65 ++++++++++++++----- .../Core/Metadata/include/otbImageMetadata.h | 15 +++++ .../Core/Metadata/src/otbImageMetadata.cxx | 50 ++++++++++++++ Modules/Wrappers/SWIG/src/otbImageMetadata.i | 6 ++ 6 files changed, 177 insertions(+), 15 deletions(-) create mode 100644 Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py rename Documentation/Cookbook/rst/{ => templates}/PythonAPI.rst (91%) diff --git a/Documentation/Cookbook/CMakeLists.txt b/Documentation/Cookbook/CMakeLists.txt index 4bd1f02f4d..9969257000 100644 --- a/Documentation/Cookbook/CMakeLists.txt +++ b/Documentation/Cookbook/CMakeLists.txt @@ -118,6 +118,15 @@ add_custom_target(generate_otbapps_rst DEPENDS OTBSWIGWrapper-all ) +add_custom_target(generate_pythonapy_rst + COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/Scripts/otbGeneratePythonApiRstDoc.py + ${RST_BINARY_DIR} + WORKING_DIRECTORY ${RST_BINARY_DIR} + COMMENT "Auto-generating Python Api Documentation in RST" + DEPENDS OTBSWIGWrapper-all + ) + + add_custom_target(generate_examples_rst COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/Scripts/otbGenerateExamplesRstDoc.py ${RST_BINARY_DIR} @@ -144,6 +153,7 @@ add_custom_target(CookBookHTML -c ${SPHINX_CONF_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS generate_otbapps_rst + DEPENDS generate_pythonapy_rst DEPENDS generate_examples_rst COMMENT "Building RST documentation in html") diff --git a/Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py b/Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py new file mode 100644 index 0000000000..b9a6babfbf --- /dev/null +++ b/Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py @@ -0,0 +1,46 @@ +import argparse + +import otbApplication + + +def format_key_list(keys_str): + """ + Format the key list + :param keys_str: a string containing the keys separated by spaces + :return: a string containing the keys ordered and separated by a coma and a space + """ + key_list = keys_str.split(" ") + key_list.sort() + return ", ".join(key_list) + +def GenerateRstForPythonAPi(rst_dir): + " Generate the .rst file for the PythonAPI page" + + print("Generating rst for Python API") + + # Instenciate an ImageMetadata object to retrieve the keys + imd = otbApplication.ImageMetadata() + + # Render the page + output_python_api = template_python_api.format( + key_list_double=format_key_list(imd.GetKeyListNum()), + key_list_string=format_key_list(imd.GetKeyListStr()), + key_list_l1d=format_key_list(imd.GetKeyListL1D()), +# key_list_l2d=format_key_list(imd.GetKeyListL2D()), + key_list_time=format_key_list(imd.GetKeyListTime()) + ) + + # Write the page + with open(rst_dir + '/PythonAPI.rst', 'w',encoding='utf-8') as new_rst_file: + new_rst_file.write(output_python_api) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(usage="Export the PythonAPI doc page to rst file") + parser.add_argument("rst_dir", help="Directory where rst files are generated") + args = parser.parse_args() + + # Load rst template + template_python_api = open("templates/PythonAPI.rst").read() + + GenerateRstForPythonAPi(args.rst_dir) diff --git a/Documentation/Cookbook/rst/PythonAPI.rst b/Documentation/Cookbook/rst/templates/PythonAPI.rst similarity index 91% rename from Documentation/Cookbook/rst/PythonAPI.rst rename to Documentation/Cookbook/rst/templates/PythonAPI.rst index 818c5f933e..ff1f899f3b 100644 --- a/Documentation/Cookbook/rst/PythonAPI.rst +++ b/Documentation/Cookbook/rst/templates/PythonAPI.rst @@ -106,7 +106,7 @@ functions *SetParameters()* and *GetParameters()*. .. code-block:: python - params = {"in":"myInput.tif", "type.mean.radius":4} + params = {{"in":"myInput.tif", "type.mean.radius":4}} app.SetParameters(params) params2 = app.GetParameters() @@ -374,26 +374,61 @@ The Python dictionary used has the following entries: * ``'spacing'``: signed spacing of the image * ``'size'``: full size of the image * ``'region'``: region of the image present in the buffer - * ``'metadata'``: metadata dictionary (contains projection, sensor model,...) + * ``'metadata'``: metadata dictionary (contains projection,...) + +The metadata dictionary contains various type of data. Here are the available keys of the dictionnary, ordered by type: + +* double: + + {key_list_double} + +* string: + + {key_list_string} + +* LUT 1D: + + {key_list_l1d} + +* time object: + + {key_list_time} + +This dictionary also contains metadata related to projection and +sensor model. The coresponding keys are not accessible at the +moment. But the dictionary offers a few extra methods: + +* ``GetProjectedGeometry()`` returns a string representing the + projection. It can be a WKN, an EPSG or a PROJ string. + +* ``GetProjectionWKT()`` returns a string representing the projection + as a WKT. + +* ``GetProjectionProj()`` returns a string representing the projection + as a PROJ string. Now some basic Q&A about this interface: - Q: What portion of the image is exported to Numpy array? - A: By default, the whole image is exported. If you had a non-empty requested - region (the result of calling PropagateRequestedRegion()), then this region - is exported. + * **What portion of the image is exported to Numpy array?** + + By default, the whole image is exported. If you had a non-empty + requested region (the result of calling + PropagateRequestedRegion()), then this region is exported. - Q: What is the difference between ImportImage and ImportVectorImage? - A: The first one is here for Applications that expect a monoband otb::Image. - In most cases, you will use the second one: ImportVectorImage. + * **What is the difference between ImportImage and ImportVectorImage?** - Q: What kind of objects are there in this dictionary export? - A: The array is a numpy.ndarray. The other fields are wrapped - objects from the OTB library but you can interact with them in a - Python way: they support ``len()`` and ``str()`` operator, as well as - bracket operator ``[]``. Some of them also have a ``keys()`` function just like - dictionaries. + The first one is here for Applications that expect a monoband + otb::Image. In most cases, you will use the second one: + ImportVectorImage. + * **What kind of objects are there in this dictionary export?** + + The array is a numpy.ndarray. The other fields are wrapped objects + from the OTB library but you can interact with them in a Python + way: they support ``len()`` and ``str()`` operator, as well as + bracket operator ``[]``. Some of them also have a ``keys()`` + function just like dictionaries. + This interface allows you to export OTB images (or extracts) to Numpy array, process them by other means, and re-import them with preserved metadata. Please note that this is different from an in-memory connection. diff --git a/Modules/Core/Metadata/include/otbImageMetadata.h b/Modules/Core/Metadata/include/otbImageMetadata.h index a109db3cfb..507faa0e1e 100644 --- a/Modules/Core/Metadata/include/otbImageMetadata.h +++ b/Modules/Core/Metadata/include/otbImageMetadata.h @@ -145,6 +145,9 @@ public: /** Test if a key is available */ bool Has(const MDNum& key) const; + + /** Return the list of valid keys */ + std::string GetKeyListNum() const; // -------------------- String utility function ---------------------------- @@ -159,6 +162,9 @@ public: /** Test if a key is available */ bool Has(const MDStr& key) const; + + /** Return the list of valid keys */ + std::string GetKeyListStr() const; // -------------------- LUT1D utility function ---------------------------- @@ -173,6 +179,9 @@ public: /** Test if a key is available */ bool Has(const MDL1D& key) const; + + /** Return the list of valid keys */ + std::string GetKeyListL1D() const; // -------------------- 2D LUT utility function ---------------------------- @@ -187,6 +196,9 @@ public: /** Test if a key is available */ bool Has(const MDL2D& key) const; + + /** Return the list of valid keys */ +// std::string GetKeyListL2D() const; // -------------------- Time utility function ---------------------------- @@ -202,6 +214,9 @@ public: /** Test if a key is available */ bool Has(const MDTime& key) const; + /** Return the list of valid keys */ + std::string GetKeyListTime() const; + // -------------------- Extra keys utility function -------------------------- /** Read-only accessor to extra keys */ diff --git a/Modules/Core/Metadata/src/otbImageMetadata.cxx b/Modules/Core/Metadata/src/otbImageMetadata.cxx index d34555403e..061cdb90dc 100644 --- a/Modules/Core/Metadata/src/otbImageMetadata.cxx +++ b/Modules/Core/Metadata/src/otbImageMetadata.cxx @@ -166,6 +166,16 @@ bool ImageMetadataBase::Has(const MDNum& key) const return (NumericKeys.find(key) != NumericKeys.end()); } +std::string ImageMetadataBase::GetKeyListNum() const +{ + std::ostringstream oss; + for (const auto& kv : MetaData::MDNumNames.left) + oss << kv.second << " "; + auto returnString = oss.str(); + returnString.pop_back(); + return returnString; +} + // -------------------- String utility function ---------------------------- const std::string & ImageMetadataBase::operator[](const MDStr& key) const @@ -188,6 +198,16 @@ bool ImageMetadataBase::Has(const MDStr& key) const return (StringKeys.find(key) != StringKeys.end()); } +std::string ImageMetadataBase::GetKeyListStr() const +{ + std::ostringstream oss; + for (const auto& kv : MetaData::MDStrNames.left) + oss << kv.second << " "; + auto returnString = oss.str(); + returnString.pop_back(); + return returnString; +} + // -------------------- LUT1D utility function ---------------------------- const MetaData::LUT1D & ImageMetadataBase::operator[](const MDL1D& key) const @@ -210,6 +230,16 @@ bool ImageMetadataBase::Has(const MDL1D& key) const return (LUT1DKeys.find(key) != LUT1DKeys.end()); } +std::string ImageMetadataBase::GetKeyListL1D() const +{ + std::ostringstream oss; + for (const auto& kv : MetaData::MDL1DNames.left) + oss << kv.second << " "; + auto returnString = oss.str(); + returnString.pop_back(); + return returnString; +} + // -------------------- 2D LUT utility function ---------------------------- const MetaData::LUT2D & ImageMetadataBase::operator[](const MDL2D& key) const @@ -232,6 +262,16 @@ bool ImageMetadataBase::Has(const MDL2D& key) const return (LUT2DKeys.find(key) != LUT2DKeys.end()); } +//std::string ImageMetadataBase::GetKeyListL2D() const +//{ +// std::ostringstream oss; +// for (const auto& kv : MetaData::MDL2DNames.left) +// oss << kv.second << " "; +// auto returnString = oss.str(); +// returnString.pop_back(); +// return returnString; +//} + // -------------------- Time utility function ---------------------------- const MetaData::Time & ImageMetadataBase::operator[](const MDTime& key) const @@ -254,6 +294,16 @@ bool ImageMetadataBase::Has(const MDTime& key) const return (TimeKeys.find(key) != TimeKeys.end()); } +std::string ImageMetadataBase::GetKeyListTime() const +{ + std::ostringstream oss; + for (const auto& kv : MetaData::MDTimeNames.left) + oss << kv.second << " "; + auto returnString = oss.str(); + returnString.pop_back(); + return returnString; +} + // -------------------- Extra keys utility function -------------------------- const std::string & ImageMetadataBase::operator[](const std::string & key) const diff --git a/Modules/Wrappers/SWIG/src/otbImageMetadata.i b/Modules/Wrappers/SWIG/src/otbImageMetadata.i index c3996c1d3b..efb1fbe7e1 100644 --- a/Modules/Wrappers/SWIG/src/otbImageMetadata.i +++ b/Modules/Wrappers/SWIG/src/otbImageMetadata.i @@ -84,6 +84,12 @@ public: std::string GetProjectedGeometry() const; std::string GetProjectionWKT() const; std::string GetProjectionProj() const; + + std::string GetKeyListNum() const; + std::string GetKeyListStr() const; + std::string GetKeyListL1D() const; +// std::string GetKeyListL2D() const; + std::string GetKeyListTime() const; }; class ImageMetadata: public ImageMetadataBase -- GitLab From 5329f3df1408f9bc4674470b5a4407ca6f659867 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Fri, 26 Nov 2021 09:04:55 +0100 Subject: [PATCH 11/21] STYLE: Add copyright header --- .../Scripts/otbGeneratePythonApiRstDoc.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py b/Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py index b9a6babfbf..10ef2ed044 100644 --- a/Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py +++ b/Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py @@ -1,3 +1,24 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2005-2021 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. +# + import argparse import otbApplication -- GitLab From a3198511debafcc998ab4a0cfa9ec8278de2c5a6 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Fri, 26 Nov 2021 09:49:24 +0100 Subject: [PATCH 12/21] ENH: Wrappe the new time class in Python API --- Modules/Wrappers/SWIG/src/otbImageMetadata.i | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Modules/Wrappers/SWIG/src/otbImageMetadata.i b/Modules/Wrappers/SWIG/src/otbImageMetadata.i index efb1fbe7e1..98e59f96d3 100644 --- a/Modules/Wrappers/SWIG/src/otbImageMetadata.i +++ b/Modules/Wrappers/SWIG/src/otbImageMetadata.i @@ -55,6 +55,14 @@ public: namespace MetaData { +class TimePoint : private details::streamable, + private details::substractable_asym, + private boost::equality_comparable, + private boost::less_than_comparable +{ + +}; + struct LUTAxis { int Size; @@ -147,7 +155,7 @@ public: return it != otb::MetaData::MDTimeNames.right.end(); } - otb::MetaData::Time get_time(const std::string& key) { + otb::MetaData::TimePoint get_time(const std::string& key) { auto it = otb::MetaData::MDTimeNames.right.find(key); return $self->operator[](it->second); } @@ -213,7 +221,7 @@ public: else $self->Add(key, val.ToString()); } - void __setitem__(const std::string& key, const otb::MetaData::Time& val) { + void __setitem__(const std::string& key, const otb::MetaData::TimePoint& val) { auto it = otb::MetaData::MDTimeNames.right.find(key); if (it != otb::MetaData::MDTimeNames.right.end()) $self->Add(it->second, val); -- GitLab From 8e70e542d2570b0a825537b53ea1d6c6ccf5ba77 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Fri, 26 Nov 2021 11:09:13 +0100 Subject: [PATCH 13/21] ENH: Implement a __repr__ method for the TimePoint class --- Modules/Wrappers/SWIG/src/otbImageMetadata.i | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Modules/Wrappers/SWIG/src/otbImageMetadata.i b/Modules/Wrappers/SWIG/src/otbImageMetadata.i index 98e59f96d3..e051e422e1 100644 --- a/Modules/Wrappers/SWIG/src/otbImageMetadata.i +++ b/Modules/Wrappers/SWIG/src/otbImageMetadata.i @@ -23,7 +23,8 @@ %{ #include "itkBase.includes" #include "otbWrapperSWIGIncludes.h" -#include // std::string +#include +#include #include #include "otbMetaDataKey.h" #include "otbImageMetadata.h" @@ -55,12 +56,12 @@ public: namespace MetaData { -class TimePoint : private details::streamable, - private details::substractable_asym, - private boost::equality_comparable, - private boost::less_than_comparable +class TimePoint { +public: + double GetJulianDay() const; + double GetModifiedJulianDay() const; }; struct LUTAxis @@ -108,6 +109,14 @@ public: }; +%extend otb::MetaData::TimePoint{ + std::string __repr__() { + std::ostringstream oss; + oss << *$self; + return oss.str().c_str(); + } +} + %extend otb::ImageMetadataBase{ bool is_num(const std::string& key) { -- GitLab From 67f75e777c5c5c4c9cfe137f138e80520fcf302f Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Fri, 26 Nov 2021 14:10:26 +0100 Subject: [PATCH 14/21] ENH: Add test after dynamic_cast --- .../ApplicationEngine/src/otbWrapperApplication.cxx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx index c8f6fb2e42..caa2ce0b78 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx @@ -1673,13 +1673,20 @@ ImageBaseType::RegionType Application::GetImageRequestedRegion(const std::string ImageMetadata &Application::GetImageMetadata(const std::string& key, unsigned int idx) { ImageBaseType* image = this->GetParameterImageBase(key, idx); - return dynamic_cast(image)->m_Imd; + otb::ImageCommons* castedImage = dynamic_cast(image); + if (castedImage) + return castedImage->GetImageMetadata(); + throw std::runtime_error("Cannot retrieve metadata from the image parameter " + key); } void Application::SetImageMetadata(const ImageMetadata & imd, const std::string& key, unsigned int idx) { ImageBaseType* image = this->GetParameterImageBase(key, idx); - dynamic_cast(image)->SetImageMetadata(imd); + otb::ImageCommons* castedImage = dynamic_cast(image); + if (castedImage) + castedImage->SetImageMetadata(imd); + else + throw std::runtime_error("Cannot set metadata to the image parameter " + key); } itk::MetaDataDictionary Application::GetMetadataDictionary(const std::string& key, unsigned int idx) -- GitLab From 4d5e815432fd879152d8119c86f77c45d24fa2a3 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Fri, 26 Nov 2021 15:40:59 +0100 Subject: [PATCH 15/21] FIX: Add a script to set PYTHONPATH for Pythin API doc generation --- .../RunPythonApiRstGenerator.sh.cmake.in | 27 +++++++++++++++++++ Documentation/Cookbook/CMakeLists.txt | 12 ++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 Documentation/Cookbook/CMake/RunPythonApiRstGenerator.sh.cmake.in diff --git a/Documentation/Cookbook/CMake/RunPythonApiRstGenerator.sh.cmake.in b/Documentation/Cookbook/CMake/RunPythonApiRstGenerator.sh.cmake.in new file mode 100644 index 0000000000..929d381517 --- /dev/null +++ b/Documentation/Cookbook/CMake/RunPythonApiRstGenerator.sh.cmake.in @@ -0,0 +1,27 @@ +#!/bin/sh +# +# 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. +# + +#cmake builds with rpath in the binary dir, so we don't need to set LD_LIBRARY_PATH here +#export LD_LIBRARY_PATH=@CMAKE_BINARY_DIR@/lib:$LD_LIBRARY_PATH +export PYTHONPATH=@CMAKE_BINARY_DIR@/lib/otb/python:$PYTHONPATH +export OTB_APPLICATION_PATH=@CMAKE_BINARY_DIR@/lib/otb/applications + +python3 @CMAKE_CURRENT_SOURCE_DIR@/Scripts/otbGeneratePythonApiRstDoc.py "$1" diff --git a/Documentation/Cookbook/CMakeLists.txt b/Documentation/Cookbook/CMakeLists.txt index 9969257000..7b07ab8fc4 100644 --- a/Documentation/Cookbook/CMakeLists.txt +++ b/Documentation/Cookbook/CMakeLists.txt @@ -92,6 +92,12 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMake/RunApplicationsRstGenerator.sh. ${CMAKE_CURRENT_BINARY_DIR}/RunApplicationsRstGenerator.sh @ONLY) +execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_BINARY_DIR}/RunPythonApiRstGenerator.sh) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMake/RunPythonApiRstGenerator.sh.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/RunPythonApiRstGenerator.sh + @ONLY) + file(COPY ${RST_SOURCE_DIR} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/Art DESTINATION ${RST_BINARY_DIR}) @@ -118,8 +124,8 @@ add_custom_target(generate_otbapps_rst DEPENDS OTBSWIGWrapper-all ) -add_custom_target(generate_pythonapy_rst - COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/Scripts/otbGeneratePythonApiRstDoc.py +add_custom_target(generate_pythonapi_rst + COMMAND ${SH_INTERP} ${CMAKE_CURRENT_BINARY_DIR}/RunPythonApiRstGenerator.sh ${RST_BINARY_DIR} WORKING_DIRECTORY ${RST_BINARY_DIR} COMMENT "Auto-generating Python Api Documentation in RST" @@ -153,7 +159,7 @@ add_custom_target(CookBookHTML -c ${SPHINX_CONF_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS generate_otbapps_rst - DEPENDS generate_pythonapy_rst + DEPENDS generate_pythonapi_rst DEPENDS generate_examples_rst COMMENT "Building RST documentation in html") -- GitLab From 911e1a6bcfe3489ef754e37c44180d792e567102 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Wed, 1 Dec 2021 16:33:26 +0100 Subject: [PATCH 16/21] STYLE: Typo --- Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py b/Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py index 10ef2ed044..e009c8a5eb 100644 --- a/Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py +++ b/Documentation/Cookbook/Scripts/otbGeneratePythonApiRstDoc.py @@ -39,7 +39,7 @@ def GenerateRstForPythonAPi(rst_dir): print("Generating rst for Python API") - # Instenciate an ImageMetadata object to retrieve the keys + # Instentiate an ImageMetadata object to retrieve the keys imd = otbApplication.ImageMetadata() # Render the page -- GitLab From f8ec4f8f15b12f35c0ea8624ae89070855de9244 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Thu, 2 Dec 2021 10:37:30 +0100 Subject: [PATCH 17/21] ENH: Upgrade to SWIG 4.0.2 --- SuperBuild/CMake/External_swig.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SuperBuild/CMake/External_swig.cmake b/SuperBuild/CMake/External_swig.cmake index 0b9bd9374f..c61c49393c 100644 --- a/SuperBuild/CMake/External_swig.cmake +++ b/SuperBuild/CMake/External_swig.cmake @@ -33,8 +33,8 @@ if(MSVC) # Use pre-built swig executable (no linking is required, no install done) ExternalProject_Add(SWIG PREFIX SWIG - URL "https://downloads.sourceforge.net/project/swig/swigwin/swigwin-3.0.12/swigwin-3.0.12.zip" - URL_MD5 a49524dad2c91ae1920974e7062bfc93 + URL "https://downloads.sourceforge.net/project/swig/swigwin/swigwin-4.0.2/swigwin-4.0.2.zip" + URL_MD5 009926b512aee9318546bdd4c7eab6f9 INSTALL_DIR ${SB_INSTALL_PREFIX} DOWNLOAD_DIR ${DOWNLOAD_LOCATION} CONFIGURE_COMMAND "" @@ -52,8 +52,8 @@ else() ExternalProject_Add(SWIG PREFIX SWIG - URL "https://downloads.sourceforge.net/project/swig/swig/swig-3.0.12/swig-3.0.12.tar.gz" - URL_MD5 82133dfa7bba75ff9ad98a7046be687c + URL "https://downloads.sourceforge.net/project/swig/swig/swig-4.0.2/swig-4.0.2.tar.gz" + URL_MD5 7c3e46cb5af2b469722cafa0d91e127b BINARY_DIR ${SWIG_SB_BUILD_DIR} INSTALL_DIR ${SB_INSTALL_PREFIX} DOWNLOAD_DIR ${DOWNLOAD_LOCATION} -- GitLab From 516310cd54cb5df75ba67b751bd2451574d55867 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Mon, 20 Dec 2021 08:44:35 +0100 Subject: [PATCH 18/21] TEST: Add unit tests for python API Image Metadata --- Modules/Wrappers/SWIG/otb-module-init.cmake | 2 +- .../Wrappers/SWIG/test/python/CMakeLists.txt | 5 ++ .../test/python/PythonImageMetadataTest.py | 77 +++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 Modules/Wrappers/SWIG/test/python/PythonImageMetadataTest.py diff --git a/Modules/Wrappers/SWIG/otb-module-init.cmake b/Modules/Wrappers/SWIG/otb-module-init.cmake index 0730626d29..667532f626 100644 --- a/Modules/Wrappers/SWIG/otb-module-init.cmake +++ b/Modules/Wrappers/SWIG/otb-module-init.cmake @@ -50,4 +50,4 @@ if ( OTB_WRAP_PYTHON ) message( WARNING "OTB wrappers will be done without support for NumPy (not found).") endif() -endif() \ No newline at end of file +endif() diff --git a/Modules/Wrappers/SWIG/test/python/CMakeLists.txt b/Modules/Wrappers/SWIG/test/python/CMakeLists.txt index 968ec181ea..4970edf9e6 100644 --- a/Modules/Wrappers/SWIG/test/python/CMakeLists.txt +++ b/Modules/Wrappers/SWIG/test/python/CMakeLists.txt @@ -169,3 +169,8 @@ add_test( NAME pyTvNoUpdateParameter ${OTB_DATA_ROOT}/Input/training/training.shp ) +add_test( NAME pyTuImageMetadata + COMMAND ${TEST_DRIVER} Execute + ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/PythonTestDriver.py + PythonImageMetadataTest + ) diff --git a/Modules/Wrappers/SWIG/test/python/PythonImageMetadataTest.py b/Modules/Wrappers/SWIG/test/python/PythonImageMetadataTest.py new file mode 100644 index 0000000000..28f70078cc --- /dev/null +++ b/Modules/Wrappers/SWIG/test/python/PythonImageMetadataTest.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# +# 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. +# + +def test(otb, argv): + imd = otb.ImageMetadataBase() + + # Setters + imd["OrbitNumber"] = 2.0 + imd["SensorID"] = "PHR" + imd["ProjectionWKT"] = "UTM projRef" + imd["Comment"] = "Test extra keys" + + # is_xxx + assert imd.is_num("OrbitNumber") + assert not imd.is_num("SensorID") + + assert imd.is_str("SensorID") + assert not imd.is_str("OrbitNumber") + + assert imd.is_l1d("SpectralSensitivity") + assert not imd.is_l1d("SensorID") + + assert imd.is_time("ProductionDate") + assert not imd.is_time("SensorID") + + assert imd.is_geom("ProjectionWKT") + assert not imd.is_geom("SensorID") + + assert imd.is_extra("Comment") + assert not imd.is_extra("SensorID") + + # get_xxx + assert imd.get_num("OrbitNumber") == 2.0 + assert imd.get_str("SensorID") == "PHR" + assert imd.get_extra("Comment") == "Test extra keys" + + # Getters + assert imd["OrbitNumber"] == 2.0 + assert imd["SensorID"] == "PHR" + # assert imd["ProjectionWKT"] == "UTM projRef" # This getter is not implemented yet + assert imd["Comment"] == "Test extra keys" + + # has + assert imd.has("OrbitNumber") + assert imd.has("SensorID") + assert imd.has("Comment") + assert not imd.has("Comment2") + assert not imd.has("RadiometricLevel") + + # GetProjectedGeometry + assert imd.GetProjectedGeometry() == "UTM projRef" + + # GetProjectionProj + imd["ProjectionProj"] = "Proj String" + assert imd.GetProjectionProj() == "Proj String" + + # __repr__ + print(imd) + assert repr(imd) == "" -- GitLab From d733220ce6fb3e1a16f467e20fc453e53f3339df Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Mon, 20 Dec 2021 08:45:32 +0100 Subject: [PATCH 19/21] BUG: Fix the Python API --- .../BoostAdapters/include/otbJoinContainer.h | 26 +++++++++++++++++++ .../Core/Metadata/src/otbImageMetadata.cxx | 8 +++--- Modules/Wrappers/SWIG/src/otbImageMetadata.i | 23 +++++++++++++--- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/Modules/Adapters/BoostAdapters/include/otbJoinContainer.h b/Modules/Adapters/BoostAdapters/include/otbJoinContainer.h index 8c2cbea50d..18980e3f7c 100644 --- a/Modules/Adapters/BoostAdapters/include/otbJoinContainer.h +++ b/Modules/Adapters/BoostAdapters/include/otbJoinContainer.h @@ -58,6 +58,32 @@ inline std::ostream& Join(std::ostream& os, TRange const& range, std::string con } return os; } + +/** + * Joins elements from a map (second) into a stream. + * \tparam Tmap Map type + * \param os destination stream + * \param[in] range Range to print + * \param[in] separator Separator string to use between elements. + * + * \return the stream + * \throw None At least, this function is exception neutral. + */ +template +inline std::ostream& JoinMap(std::ostream& os, Tmap const& range, std::string const& separator) +{ + if (!boost::empty(range)) + { + typename boost::range_iterator::type first = boost::begin(range); + typename boost::range_iterator::type const last = boost::end(range); + os << first->second; + for (++first; first != last; ++first) + { + os << separator << first->second; + } + } + return os; +} } // end namespace otb #ifndef OTB_MANUAL_INSTANTIATION diff --git a/Modules/Core/Metadata/src/otbImageMetadata.cxx b/Modules/Core/Metadata/src/otbImageMetadata.cxx index 0e6f9da9f6..12ba4957b8 100644 --- a/Modules/Core/Metadata/src/otbImageMetadata.cxx +++ b/Modules/Core/Metadata/src/otbImageMetadata.cxx @@ -20,6 +20,7 @@ #include "otbImageMetadata.h" #include "otbSpatialReference.h" +#include "otbJoinContainer.h" namespace otb { @@ -201,11 +202,8 @@ bool ImageMetadataBase::Has(const MDStr& key) const std::string ImageMetadataBase::GetKeyListStr() const { std::ostringstream oss; - for (const auto& kv : MetaData::MDStrNames.left) - oss << kv.second << " "; - auto returnString = oss.str(); - returnString.pop_back(); - return returnString; + JoinMap(oss, MetaData::MDStrNames.left, " "); + return oss.str(); } // -------------------- LUT1D utility function ---------------------------- diff --git a/Modules/Wrappers/SWIG/src/otbImageMetadata.i b/Modules/Wrappers/SWIG/src/otbImageMetadata.i index e051e422e1..e6d5b2d292 100644 --- a/Modules/Wrappers/SWIG/src/otbImageMetadata.i +++ b/Modules/Wrappers/SWIG/src/otbImageMetadata.i @@ -91,7 +91,6 @@ class ImageMetadataBase { public: std::string GetProjectedGeometry() const; - std::string GetProjectionWKT() const; std::string GetProjectionProj() const; std::string GetKeyListNum() const; @@ -113,7 +112,7 @@ public: std::string __repr__() { std::ostringstream oss; oss << *$self; - return oss.str().c_str(); + return oss.str(); } } @@ -174,6 +173,14 @@ public: return it != otb::MetaData::MDGeomNames.right.end(); } + bool is_extra(const std::string& key) { + return $self->Has(key); + } + + std::string get_extra(const std::string& key) { + return $self->operator[](key); + } + bool has(const std::string& key) const { auto it_num = otb::MetaData::MDNumNames.right.find(key); if (it_num != otb::MetaData::MDNumNames.right.end()) @@ -199,7 +206,7 @@ public: if (it_geom != otb::MetaData::MDGeomNames.right.end()) return $self->Has(it_geom->second); - return false; + return $self->Has(key); } void __setitem__(const std::string& key, const double val) { @@ -214,7 +221,13 @@ public: if (it != otb::MetaData::MDStrNames.right.end()) $self->Add(it->second, val); else - $self->Add(key, val); + { + auto it2 = otb::MetaData::MDGeomNames.right.find(key); + if (it2 != otb::MetaData::MDGeomNames.right.end()) + $self->Add(it2->second, val); + else + $self->Add(key, val); + } } void __setitem__(const std::string& key, const otb::MetaData::LUT1D& val) { auto it = otb::MetaData::MDL1DNames.right.find(key); @@ -263,6 +276,8 @@ public: return self.get_time(key) elif self.is_geom(key): return None # TODO: the geom part of the Imagemetadata is not wrapped yet + elif self.is_extra(key): + return self.get_extra(key) else: return None } -- GitLab From 58e48c206af56f95a07772f58ccd25049ad9899d Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Mon, 20 Dec 2021 10:27:13 +0100 Subject: [PATCH 20/21] FIX: Remove irrevelent test --- Modules/Wrappers/SWIG/test/python/PythonImageMetadataTest.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Modules/Wrappers/SWIG/test/python/PythonImageMetadataTest.py b/Modules/Wrappers/SWIG/test/python/PythonImageMetadataTest.py index 28f70078cc..9b7ca9cfe4 100644 --- a/Modules/Wrappers/SWIG/test/python/PythonImageMetadataTest.py +++ b/Modules/Wrappers/SWIG/test/python/PythonImageMetadataTest.py @@ -71,7 +71,3 @@ def test(otb, argv): # GetProjectionProj imd["ProjectionProj"] = "Proj String" assert imd.GetProjectionProj() == "Proj String" - - # __repr__ - print(imd) - assert repr(imd) == "" -- GitLab From 97cff932f1ca0eee3eb1312bfbe52ec48bd5e0c4 Mon Sep 17 00:00:00 2001 From: Julien Osman Date: Tue, 21 Dec 2021 13:24:09 +0100 Subject: [PATCH 21/21] ENH: Set the getters as const functions --- Documentation/Cookbook/rst/CompilingOTBFromSource.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Documentation/Cookbook/rst/CompilingOTBFromSource.rst b/Documentation/Cookbook/rst/CompilingOTBFromSource.rst index 9edd6cacba..ea4b34e4fa 100644 --- a/Documentation/Cookbook/rst/CompilingOTBFromSource.rst +++ b/Documentation/Cookbook/rst/CompilingOTBFromSource.rst @@ -150,7 +150,7 @@ SuperBuild: Build OTB and all dependencies OTB’s compilation is customized by specifying configuration variables. The most important configuration variables are shown in the -table above. The simplest way to provide +table above. The simplest way to provide configuration variables is via the command line ``-D`` option: :: @@ -285,7 +285,7 @@ FindXXX.cmake scripts, or with the ``XXX_INCLUDEDIR`` and ``XXX_LIBRARY`` variables. Additionally, decide which module you wish to enable, together with tests and -examples. Refer to table above for the list of CMake variables. +examples. Refer to table above for the list of CMake variables. OTB is modular. It is possible to only build some modules instead of the whole set. To deactivate a module (and the ones that @@ -295,7 +295,7 @@ depend on it) switch off the CMake variable Some of the OTB capabilities are considered as optional, and you can deactivate the related modules thanks to a set of CMake variables -starting with ``OTB_USE_XXX``. The table below shows which modules +starting with ``OTB_USE_XXX``. The table below shows which modules are associated to these variables. It is very important to notice that these variable override the variable ``OTB_BUILD_DEFAULT_MODULES``. @@ -366,7 +366,8 @@ hours to run them all, depending on compilation options (release mode does make a difference) and hardware. To run the tests, first make sure to set the option -``BUILD_TESTING`` to ``ON`` before building the library. +``BUILD_TESTING`` to ``ON`` before building the library. If you want to run the tests for the +python API, you will also need to install the python module `pytest`. For some of the tests, you also need the test data and the baselines (~1GB). These files are stored using `git-lfs` in the `Data` folder at the root of otb sources. To download them, you have to make -- GitLab