Commit 6e85bdc9 authored by Cédric Traizet's avatar Cédric Traizet

Merge branch 'refactor_optical_calibration' into 'develop'

Refactor the OpticalCalibration application

See merge request !773
parents 6683c484 abbf275c
Pipeline #6464 passed with stages
in 5 minutes and 6 seconds
......@@ -10,9 +10,9 @@ SatAzimuth -74.1736
AcquisitionDate 2009-03-16T11:03:49.972847Z
ProductionDate 2009-03-26T11:56:45Z
BandName XS1
PhysicalGain 2.24793
PhysicalGain 3.04029
PhysicalBias 0
SolarIrradiance 1858
SolarIrradiance 1043
SpectralSensitivity LUT1D.DIM0.SIZE = 541
LUT1D.DIM0.ORIGIN = 0.45
LUT1D.DIM0.SPACING = 0.0025
......@@ -26,9 +26,9 @@ LUT1D.DIM0.ORIGIN = 0.45
LUT1D.DIM0.SPACING = 0.0025
LUT1D.ARRAY = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000767371 0.00153474 0.0104196 0.0193045 0.0615428 0.103781 0.200796 0.297811 0.412078 0.526345 0.620393 0.71444 0.780931 0.847421 0.886912 0.926403 0.95094 0.975478 0.985468 0.995459 0.997729 1 0.993748 0.987495 0.974977 0.962458 0.943181 0.923905 0.899244 0.874583 0.844649 0.814715 0.768634 0.722553 0.65867 0.594786 0.516931 0.439075 0.366208 0.293341 0.235793 0.178245 0.1414 0.104555 0.082136 0.0597166 0.0472382 0.0347598 0.0272426 0.0197255 0.0155478 0.01137 0.0090188 0.00666756 0.00509771 0.00352787 0.0028316 0.00213534 0.00106767 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BandName XS3
PhysicalGain 3.04029
PhysicalGain 2.24793
PhysicalBias 0
SolarIrradiance 1043
SolarIrradiance 1858
SpectralSensitivity LUT1D.DIM0.SIZE = 541
LUT1D.DIM0.ORIGIN = 0.45
LUT1D.DIM0.SPACING = 0.0025
......
......@@ -11,9 +11,9 @@ AcquisitionDate 2003-07-23T07:27:43.889716Z
ProductionDate 2003-12-05T08:21:19Z
GCP <GCPParam>
BandName XS1
PhysicalGain 1.0032
PhysicalGain 1.3812
PhysicalBias 0
SolarIrradiance 1858
SolarIrradiance 1047
SpectralSensitivity LUT1D.DIM0.SIZE = 541
LUT1D.DIM0.ORIGIN = 0.45
LUT1D.DIM0.SPACING = 0.0025
......@@ -27,9 +27,9 @@ LUT1D.DIM0.ORIGIN = 0.45
LUT1D.DIM0.SPACING = 0.0025
LUT1D.ARRAY = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000767371 0.00153474 0.0104196 0.0193045 0.0615428 0.103781 0.200796 0.297811 0.412078 0.526345 0.620393 0.71444 0.780931 0.847421 0.886912 0.926403 0.95094 0.975478 0.985468 0.995459 0.997729 1 0.993748 0.987495 0.974977 0.962458 0.943181 0.923905 0.899244 0.874583 0.844649 0.814715 0.768634 0.722553 0.65867 0.594786 0.516931 0.439075 0.366208 0.293341 0.235793 0.178245 0.1414 0.104555 0.082136 0.0597166 0.0472382 0.0347598 0.0272426 0.0197255 0.0155478 0.01137 0.0090188 0.00666756 0.00509771 0.00352787 0.0028316 0.00213534 0.00106767 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BandName XS3
PhysicalGain 1.3812
PhysicalGain 1.0032
PhysicalBias 0
SolarIrradiance 1047
SolarIrradiance 1858
SpectralSensitivity LUT1D.DIM0.SIZE = 541
LUT1D.DIM0.ORIGIN = 0.45
LUT1D.DIM0.SPACING = 0.0025
......
......@@ -394,36 +394,32 @@ private:
// Check if valid metadata information are available to compute ImageToRadiance and RadianceToReflectance
FloatVectorImageType::Pointer inImage = GetParameterFloatVectorImage("in");
itk::MetaDataDictionary dict = inImage->GetMetaDataDictionary();
OpticalImageMetadataInterface::Pointer lImageMetadataInterface = OpticalImageMetadataInterfaceFactory::CreateIMI(dict);
const auto & metadata = inImage->GetImageMetadata();
//TODO : Remove, this is an Ossim compatibility layer
lImageMetadataInterface->SetImageMetadata(inImage->GetImageMetadata());
std::string IMIName(lImageMetadataInterface->GetNameOfClass()), IMIOptDfltName("OpticalDefaultImageMetadataInterface");
if ((IMIName != IMIOptDfltName))
if ((otb::HasOpticalSensorMetadata(metadata)))
{
ossOutput << "Sensor detected: " << lImageMetadataInterface->GetSensorID() << std::endl;
ossOutput << "Sensor detected: " << metadata[MDStr::SensorID]<< std::endl;
itk::VariableLengthVector<double> vlvector;
std::stringstream ss;
ossOutput << "Parameters extract from input image: " << std::endl
<< "\tAcquisition Day: " << lImageMetadataInterface->GetDay() << std::endl
<< "\tAcquisition Month: " << lImageMetadataInterface->GetMonth() << std::endl
<< "\tAcquisition Year: " << lImageMetadataInterface->GetYear() << std::endl
<< "\tAcquisition Sun Elevation Angle: " << lImageMetadataInterface->GetSunElevation() << std::endl
<< "\tAcquisition Sun Azimuth Angle: " << lImageMetadataInterface->GetSunAzimuth() << std::endl
<< "\tAcquisition Viewing Elevation Angle: " << lImageMetadataInterface->GetSatElevation() << std::endl
<< "\tAcquisition Viewing Azimuth Angle: " << lImageMetadataInterface->GetSatAzimuth() << std::endl;
vlvector = lImageMetadataInterface->GetPhysicalGain();
<< "\tAcquisition Day: " << metadata[MDTime::AcquisitionDate].GetDay() << std::endl
<< "\tAcquisition Month: " << metadata[MDTime::AcquisitionDate].GetMonth() << std::endl
<< "\tAcquisition Year: " << metadata[MDTime::AcquisitionDate].GetYear() << std::endl
<< "\tAcquisition Sun Elevation Angle: " << metadata[MDNum::SunElevation] << std::endl
<< "\tAcquisition Sun Azimuth Angle: " << metadata[MDNum::SunAzimuth] << std::endl
<< "\tAcquisition Viewing Elevation Angle: " << metadata[MDNum::SatElevation] << std::endl
<< "\tAcquisition Viewing Azimuth Angle: " << metadata[MDNum::SatAzimuth] << std::endl;
vlvector = metadata.GetAsVector(MDNum::PhysicalGain);
ossOutput << "\tAcquisition gain (per band): ";
for (unsigned int k = 0; k < vlvector.Size(); k++)
ossOutput << vlvector[k] << " ";
ossOutput << std::endl;
vlvector = lImageMetadataInterface->GetPhysicalBias();
vlvector = metadata.GetAsVector(MDNum::PhysicalBias);
ossOutput << "\tAcquisition bias (per band): ";
for (unsigned int k = 0; k < vlvector.Size(); k++)
ossOutput << vlvector[k] << " ";
......@@ -431,7 +427,7 @@ private:
DisableParameter("acqui.gainbias");
MandatoryOff("acqui.gainbias");
vlvector = lImageMetadataInterface->GetSolarIrradiance();
vlvector = metadata.GetAsVector(MDNum::SolarIrradiance);
ossOutput << "\tSolar Irradiance (per band): ";
for (unsigned int k = 0; k < vlvector.Size(); k++)
ossOutput << vlvector[k] << " ";
......@@ -443,21 +439,21 @@ private:
ossOutput << "Acquisition Minute already set by user: no overload" << std::endl;
else
{
SetParameterInt("acqui.minute", lImageMetadataInterface->GetMinute());
SetParameterInt("acqui.minute", metadata[MDTime::AcquisitionDate].GetMinute());
}
if (HasUserValue("acqui.hour"))
ossOutput << "Acquisition Hour already set by user: no overload" << std::endl;
else
{
SetParameterInt("acqui.hour", lImageMetadataInterface->GetHour());
SetParameterInt("acqui.hour", metadata[MDTime::AcquisitionDate].GetHour());
}
if (HasUserValue("acqui.day"))
ossOutput << "Acquisition Day already set by user: no overload" << std::endl;
else
{
SetParameterInt("acqui.day", lImageMetadataInterface->GetDay());
SetParameterInt("acqui.day", metadata[MDTime::AcquisitionDate].GetDay());
if (IsParameterEnabled("acqui.fluxnormcoeff") || IsParameterEnabled("acqui.solardistance"))
DisableParameter("acqui.day");
}
......@@ -466,7 +462,7 @@ private:
ossOutput << "Acquisition Month already set by user: no overload" << std::endl;
else
{
SetParameterInt("acqui.month", lImageMetadataInterface->GetMonth());
SetParameterInt("acqui.month", metadata[MDTime::AcquisitionDate].GetMonth());
if (IsParameterEnabled("acqui.fluxnormcoeff") || IsParameterEnabled("acqui.solardistance"))
DisableParameter("acqui.month");
}
......@@ -475,40 +471,40 @@ private:
ossOutput << "Acquisition Year already set by user: no overload" << std::endl;
else
{
SetParameterInt("acqui.year", lImageMetadataInterface->GetYear());
SetParameterInt("acqui.year", metadata[MDTime::AcquisitionDate].GetYear());
}
if (HasUserValue("acqui.sun.elev"))
ossOutput << "Acquisition Sun Elevation Angle already set by user: no overload" << std::endl;
else
SetParameterFloat("acqui.sun.elev", lImageMetadataInterface->GetSunElevation());
SetParameterFloat("acqui.sun.elev", metadata[MDNum::SunElevation]);
if (HasUserValue("acqui.sun.azim"))
ossOutput << "Acquisition Sun Azimuth Angle already set by user: no overload" << std::endl;
else
SetParameterFloat("acqui.sun.azim", lImageMetadataInterface->GetSunAzimuth());
SetParameterFloat("acqui.sun.azim", metadata[MDNum::SunAzimuth]);
if (HasUserValue("acqui.view.elev"))
ossOutput << "Acquisition Viewing Elevation Angle already set by user: no overload" << std::endl;
else
SetParameterFloat("acqui.view.elev", lImageMetadataInterface->GetSatElevation());
SetParameterFloat("acqui.view.elev", metadata[MDNum::SatElevation]);
if (HasUserValue("acqui.view.azim"))
ossOutput << "Acquisition Viewing Azimuth Angle already set by user: no overload" << std::endl;
else
SetParameterFloat("acqui.view.azim", lImageMetadataInterface->GetSatAzimuth());
SetParameterFloat("acqui.view.azim", metadata[MDNum::SatAzimuth]);
// Set default value so that they are stored somewhere even if
// they are overloaded by user values
SetDefaultParameterInt("acqui.minute", lImageMetadataInterface->GetMinute());
SetDefaultParameterInt("acqui.hour", lImageMetadataInterface->GetHour());
SetDefaultParameterInt("acqui.day", lImageMetadataInterface->GetDay());
SetDefaultParameterInt("acqui.month", lImageMetadataInterface->GetMonth());
SetDefaultParameterInt("acqui.year", lImageMetadataInterface->GetYear());
SetDefaultParameterFloat("acqui.sun.elev", lImageMetadataInterface->GetSunElevation());
SetDefaultParameterFloat("acqui.sun.azim", lImageMetadataInterface->GetSunAzimuth());
SetDefaultParameterFloat("acqui.view.elev", lImageMetadataInterface->GetSatElevation());
SetDefaultParameterFloat("acqui.view.azim", lImageMetadataInterface->GetSatAzimuth());
SetDefaultParameterInt("acqui.minute", metadata[MDTime::AcquisitionDate].GetMinute());
SetDefaultParameterInt("acqui.hour", metadata[MDTime::AcquisitionDate].GetHour());
SetDefaultParameterInt("acqui.day", metadata[MDTime::AcquisitionDate].GetDay());
SetDefaultParameterInt("acqui.month", metadata[MDTime::AcquisitionDate].GetMonth());
SetDefaultParameterInt("acqui.year", metadata[MDTime::AcquisitionDate].GetYear());
SetDefaultParameterFloat("acqui.sun.elev", metadata[MDNum::SunElevation]);
SetDefaultParameterFloat("acqui.sun.azim", metadata[MDNum::SunAzimuth]);
SetDefaultParameterFloat("acqui.view.elev", metadata[MDNum::SatElevation]);
SetDefaultParameterFloat("acqui.view.azim", metadata[MDNum::SatAzimuth]);
}
else
{
......@@ -625,14 +621,8 @@ private:
FloatVectorImageType::Pointer inImage = GetParameterFloatVectorImage("in");
// Prepare a metadata interface on the input image.
itk::MetaDataDictionary dict = inImage->GetMetaDataDictionary();
OpticalImageMetadataInterface::Pointer lImageMetadataInterface = OpticalImageMetadataInterfaceFactory::CreateIMI(dict);
std::string IMIName(lImageMetadataInterface->GetNameOfClass());
std::string IMIOptDfltName("OpticalDefaultImageMetadataInterface");
//TODO : Remove, this is an Ossim compatibility layer
lImageMetadataInterface->SetImageMetadata(inImage->GetImageMetadata());
const auto & metadata = inImage->GetImageMetadata();
auto hasOpticalSensorMetadata = HasOpticalSensorMetadata(metadata);
// Set (Date and Day) OR FluxNormalizationCoef to corresponding filters OR solardistance
if (IsParameterEnabled("acqui.fluxnormcoeff"))
......@@ -723,13 +713,13 @@ private:
else
{
// Try to retrieve information from image metadata
if (IMIName != IMIOptDfltName)
if (hasOpticalSensorMetadata)
{
m_ImageToRadianceFilter->SetAlpha(lImageMetadataInterface->GetPhysicalGain());
m_RadianceToImageFilter->SetAlpha(lImageMetadataInterface->GetPhysicalGain());
m_ImageToRadianceFilter->SetAlpha(metadata.GetAsVector(MDNum::PhysicalGain));
m_RadianceToImageFilter->SetAlpha(metadata.GetAsVector(MDNum::PhysicalGain));
m_ImageToRadianceFilter->SetBeta(lImageMetadataInterface->GetPhysicalBias());
m_RadianceToImageFilter->SetBeta(lImageMetadataInterface->GetPhysicalBias());
m_ImageToRadianceFilter->SetBeta(metadata.GetAsVector(MDNum::PhysicalBias));
m_RadianceToImageFilter->SetBeta(metadata.GetAsVector(MDNum::PhysicalBias));
}
else
itkExceptionMacro(<< "Please, provide a type of sensor supported by OTB for automatic metadata extraction! ");
......@@ -781,10 +771,10 @@ private:
else
{
// Try to retrieve information from image metadata
if (IMIName != IMIOptDfltName)
if (hasOpticalSensorMetadata)
{
m_RadianceToReflectanceFilter->SetSolarIllumination(lImageMetadataInterface->GetSolarIrradiance());
m_ReflectanceToRadianceFilter->SetSolarIllumination(lImageMetadataInterface->GetSolarIrradiance());
m_RadianceToReflectanceFilter->SetSolarIllumination(metadata.GetAsVector(MDNum::SolarIrradiance));
m_ReflectanceToRadianceFilter->SetSolarIllumination(metadata.GetAsVector(MDNum::SolarIrradiance));
}
else
itkExceptionMacro(<< "Please, provide a type of sensor supported by OTB for automatic metadata extraction! ");
......@@ -873,10 +863,22 @@ private:
else
otbAppLogFATAL("Please, set a sensor relative spectral response file.");
}
else if (IMIName != IMIOptDfltName)
else if (hasOpticalSensorMetadata)
{
// Avoid to call GetSpectralSensitivity() multiple times
OpticalImageMetadataInterface::WavelengthSpectralBandVectorType spectralSensitivity = lImageMetadataInterface->GetSpectralSensitivity();
auto spectralSensitivity = AcquiCorrectionParametersType::InternalWavelengthSpectralBandVectorType::New();
for (const auto & band : metadata.Bands)
{
const auto & spectralSensitivityLUT = band[MDL1D::SpectralSensitivity];
const auto & axis = spectralSensitivityLUT.Axis[0];
auto filterFunction = FilterFunctionValues::New();
// LUT1D stores a double vector whereas FilterFunctionValues stores a float vector
std::vector<float> vec(spectralSensitivityLUT.Array.begin(), spectralSensitivityLUT.Array.end());
filterFunction->SetFilterFunctionValues(vec);
filterFunction->SetMinSpectralValue(axis.Origin);
filterFunction->SetMaxSpectralValue(axis.Origin + axis.Spacing * (axis.Size-1));
filterFunction->SetUserStep(axis.Spacing);
spectralSensitivity->PushBack(filterFunction);
}
if (spectralSensitivity->Size() > 0)
m_paramAcqui->SetWavelengthSpectralBand(spectralSensitivity);
......
......@@ -302,6 +302,15 @@ public:
/** Setter for numeric keys on each band*/
using ImageMetadataBase::Add;
void Add(const MDNum&, const MetaDataKey::VariableLengthVectorType);
/** Getter for numeric keys on each band*/
itk::VariableLengthVector<double> GetAsVector(const MDNum & key) const;
/** test wether the metadata corresponding to key is present on each band */
bool HasBandMetadata(const MDNum & key) const;
/** test wether the metadata corresponding to key is present on each band */
bool HasBandMetadata(const MDL1D & key) const;
};
extern OTBMetadata_EXPORT std::ostream& operator<<(std::ostream& os, const otb::ImageMetadataBase& imd);
......
......@@ -272,6 +272,17 @@ struct OTBMetadata_EXPORT Time : tm
return !(lhs < rhs);
}
/** @name Getters
* Getters on the date components
*/
///@{
int GetDay() const;
int GetMonth() const;
int GetYear() const;
int GetHour() const;
int GetMinute() const;
double GetSecond() const;
///@}
};
......
......@@ -1461,30 +1461,31 @@ void FormosatImageMetadataInterface::Parse(const MetadataSupplierInterface & mds
solarIrradianceVec = dimapData.SolarIrradiance;
}
if (dimapData.PhysicalBias.size() == nbBands
&& dimapData.PhysicalGain.size() == nbBands
&& solarIrradianceVec.size() == nbBands)
auto setDimapBandMetadata = [this](const MDNum & key, const std::vector<double> & input)
{
auto bias = dimapData.PhysicalBias.begin();
auto gain = dimapData.PhysicalGain.begin();
auto solarIrradiance = solarIrradianceVec.begin();
for (auto & band: m_Imd.Bands)
if (input.size() == 1)
{
band.Add(MDNum::PhysicalGain, *gain);
band.Add(MDNum::PhysicalBias, *bias);
band.Add(MDNum::SolarIrradiance, *solarIrradiance);
bias++;
gain++;
solarIrradiance++;
// this is a PAN image
m_Imd.Bands[0].Add(key, input[0]);
}
}
else
{
otbGenericExceptionMacro(MissingMetadataException,
else if (input.size() == 4)
{
// MS image, note the band ordering
m_Imd.Bands[0].Add(key, input[2]);
m_Imd.Bands[1].Add(key, input[1]);
m_Imd.Bands[2].Add(key, input[0]);
m_Imd.Bands[3].Add(key, input[3]);
}
else
{
otbGenericExceptionMacro(MissingMetadataException,
<< "The number of bands in image metadatas is incoherent with the DIMAP product")
}
}
};
setDimapBandMetadata(MDNum::PhysicalBias, dimapData.PhysicalBias);
setDimapBandMetadata(MDNum::PhysicalGain, dimapData.PhysicalGain);
setDimapBandMetadata(MDNum::SolarIrradiance, solarIrradianceVec);
FetchSpectralSensitivity();
......
......@@ -631,6 +631,33 @@ void ImageMetadata::Add(const MDNum& key, const MetaDataKey::VariableLengthVecto
}
}
itk::VariableLengthVector<double> ImageMetadata::GetAsVector(const MDNum& key) const
{
itk::VariableLengthVector<double> output(Bands.size());
int i = 0;
for (const auto & band : Bands)
{
output[i] = band[key];
i++;
}
return output;
}
bool ImageMetadata::HasBandMetadata(const MDNum & key) const
{
return std::all_of(Bands.begin(), Bands.end(),
[key](ImageMetadataBase band){return band.Has(key);});
}
bool ImageMetadata::HasBandMetadata(const MDL1D & key) const
{
return std::all_of(Bands.begin(), Bands.end(),
[key](ImageMetadataBase band){return band.Has(key);});
}
// printing
std::ostream& operator<<(std::ostream& os, const otb::ImageMetadataBase& imd)
{
......
......@@ -196,6 +196,37 @@ std::istream& operator>>(std::istream& is, Time& val)
#undef _OTB_ISTREAM_EXPECT
int Time::GetDay() const
{
return tm_mday;
}
int Time::GetMonth() const
{
return tm_mon + 1;
}
int Time::GetYear() const
{
return tm_year + 1900;
}
int Time::GetHour() const
{
return tm_hour;
}
int Time::GetMinute() const
{
return tm_min;
}
double Time::GetSecond() const
{
return tm_sec + frac_sec;
}
std::string LUTAxis::ToJSON(bool multiline) const
{
std::ostringstream oss;
......
......@@ -1806,31 +1806,39 @@ void SpotImageMetadataInterface::Parse(const MetadataSupplierInterface & mds)
m_Imd.Add(MDNum::SatAzimuth, dimapData.SceneOrientation[0] - 90);
}
auto nbBands = m_Imd.Bands.size();
if (dimapData.PhysicalBias.size() == nbBands
&& dimapData.PhysicalGain.size() == nbBands
&& dimapData.SolarIrradiance.size() == nbBands)
auto setDimapBandMetadata = [this](const MDNum & key, const std::vector<double> & input)
{
auto bias = dimapData.PhysicalBias.begin();
auto gain = dimapData.PhysicalGain.begin();
auto solarIrradiance = dimapData.SolarIrradiance.begin();
for (auto & band: m_Imd.Bands)
if (input.size() == 1)
{
band.Add(MDNum::PhysicalGain, *gain);
band.Add(MDNum::PhysicalBias, *bias);
band.Add(MDNum::SolarIrradiance, *solarIrradiance);
bias++;
gain++;
solarIrradiance++;
// this is a PAN image
m_Imd.Bands[0].Add(key, input[0]);
}
}
else
{
otbGenericExceptionMacro(MissingMetadataException,
else if (input.size() == 4)
{
// MS image, note the band ordering
m_Imd.Bands[0].Add(key, input[2]);
m_Imd.Bands[1].Add(key, input[1]);
m_Imd.Bands[2].Add(key, input[0]);
m_Imd.Bands[3].Add(key, input[3]);
}
else if (input.size() == 3)
{
m_Imd.Bands[0].Add(key, input[2]);
m_Imd.Bands[1].Add(key, input[1]);
m_Imd.Bands[2].Add(key, input[0]);
}
else
{
otbGenericExceptionMacro(MissingMetadataException,
<< "The number of bands in image metadatas is incoherent with the DIMAP product")
}
}
};
setDimapBandMetadata(MDNum::PhysicalBias, dimapData.PhysicalBias);
setDimapBandMetadata(MDNum::PhysicalGain, dimapData.PhysicalGain);
setDimapBandMetadata(MDNum::SolarIrradiance, dimapData.SolarIrradiance);
auto nbBands = m_Imd.Bands.size();
// band IDs is not parsed in geom files. There are two possible cases: panchromatic and multispectral
if (dimapData.BandIDs.empty())
......
......@@ -2202,7 +2202,7 @@ namespace
// In previous version of OTB the effective bandwith was tabulated
// because Ossim did not read this specific metadata.
outMetadata.effectiveBandwidth[bandName] = mds.GetAs<double>(prefix + "effectiveBandwidth");
outMetadata.effectiveBandwidth[bandName] = mds.GetAs<double>(0., prefix + "effectiveBandwidth");
outMetadata.absCalFactor[bandName] = mds.GetAs<double>(prefix + "absCalFactor");
......
......@@ -172,15 +172,16 @@ protected:
/** Update the functor list and input parameters */
void BeforeThreadedGenerateData(void) override
{
OpticalImageMetadataInterface::Pointer imageMetadataInterface = OpticalImageMetadataInterfaceFactory::CreateIMI(this->GetInput()->GetMetaDataDictionary());
if (m_Alpha.GetSize() == 0)
const auto & metadata = this->GetInput()->GetImageMetadata();
if (m_Alpha.GetSize() == 0 && metadata.HasBandMetadata(MDNum::PhysicalGain))
{
m_Alpha = imageMetadataInterface->GetPhysicalGain();
m_Alpha = metadata.GetAsVector(MDNum::PhysicalGain);
}
if (m_Beta.GetSize() == 0)
if (m_Beta.GetSize() == 0 && metadata.HasBandMetadata(MDNum::PhysicalBias))
{
m_Beta = imageMetadataInterface->GetPhysicalBias();
m_Beta = metadata.GetAsVector(MDNum::PhysicalBias);
}
otbMsgDevMacro(<< "Dimension: ");
......
......@@ -272,37 +272,39 @@ protected:
/** Update the functor list and input parameters */
void BeforeThreadedGenerateData(void) override
{
const auto & metadata = this->GetInput()->GetImageMetadata();
OpticalImageMetadataInterface::Pointer imageMetadataInterface = OpticalImageMetadataInterfaceFactory::CreateIMI(this->GetInput()->GetMetaDataDictionary());
if (m_Alpha.GetSize() == 0)
if (m_Alpha.GetSize() == 0 && metadata.HasBandMetadata(MDNum::PhysicalGain))
{
m_Alpha = imageMetadataInterface->GetPhysicalGain();
m_Alpha = metadata.GetAsVector(MDNum::PhysicalGain);
}
if (m_Beta.GetSize() == 0)
if (m_Beta.GetSize() == 0 && metadata.HasBandMetadata(MDNum::PhysicalBias))
{
m_Beta = imageMetadataInterface->GetPhysicalBias();
m_Beta = metadata.GetAsVector(MDNum::PhysicalBias);
}
if ((m_Day == 0) && (!m_IsSetFluxNormalizationCoefficient) && (!m_IsSetSolarDistance))
if (m_Day == 0 && (!m_IsSetFluxNormalizationCoefficient) && (!m_IsSetSolarDistance)
&& metadata.Has(MDTime::AcquisitionDate))
{
m_Day = imageMetadataInterface->GetDay();
m_Day = metadata[MDTime::AcquisitionDate].GetDay();
}
if ((m_Month == 0) && (!m_IsSetFluxNormalizationCoefficient) && (!m_IsSetSolarDistance))
if (m_Month == 0 && (!m_IsSetFluxNormalizationCoefficient) && (!m_IsSetSolarDistance)
&& metadata.Has(MDTime::AcquisitionDate))
{
m_Month = imageMetadataInterface->GetMonth();
m_Month = metadata[MDTime::AcquisitionDate].GetMonth();
}
if (m_SolarIllumination.GetSize() == 0)
if (m_SolarIllumination.GetSize() == 0 && metadata.HasBandMetadata(MDNum::SolarIrradiance))
{
m_SolarIllumination = imageMetadataInterface->GetSolarIrradiance();
m_SolarIllumination = metadata.GetAsVector(MDNum::SolarIrradiance);
}
if (m_ZenithalSolarAngle == 120.0)
if (m_ZenithalSolarAngle == 120.0 && metadata.Has(MDNum::SunElevation))
{
// the zenithal angle is the complementary of the elevation angle
m_ZenithalSolarAngle = 90.0 - imageMetadataInterface->GetSunElevation();
m_ZenithalSolarAngle = 90.0 - metadata[MDNum::SunElevation];
}