From c254bca3d97ef9d0471691c395d789051bd78eb3 Mon Sep 17 00:00:00 2001
From: Cyrille Valladeau <cyrille.valladeau@c-s.fr>
Date: Mon, 24 Aug 2009 17:55:14 +0200
Subject: [PATCH] ENH : radio correctio in progress

---
 Code/IO/otbDefaultImageMetadataInterface.h    |  13 ++
 Code/IO/otbIkonosImageMetadataInterface.cxx   |  89 ++++++++++
 Code/IO/otbIkonosImageMetadataInterface.h     |   6 +
 Code/IO/otbImageMetadataInterfaceBase.h       |   8 +
 .../IO/otbQuickBirdImageMetadataInterface.cxx |  95 +++++++++++
 Code/IO/otbQuickBirdImageMetadataInterface.h  |   6 +
 Code/IO/otbSpotImageMetadataInterface.cxx     | 102 ++++++++++++
 Code/IO/otbSpotImageMetadataInterface.h       |   6 +
 .../otbAtmosphericCorrectionParameters.cxx    |  61 +++++--
 .../otbAtmosphericCorrectionParameters.h      |  22 ++-
 ...arametersTo6SAtmosphericRadiativeTerms.cxx |   4 +-
 .../otbAtmosphericRadiativeTerms.cxx          |   9 ++
 ...flectanceToSurfaceReflectanceImageFilter.h |  25 +++
 ...ectanceToSurfaceReflectanceImageFilter.txx | 152 ++++++++++++++++++
 14 files changed, 583 insertions(+), 15 deletions(-)
 create mode 100644 Code/Radiometry/otbReflectanceToSurfaceReflectanceImageFilter.txx

diff --git a/Code/IO/otbDefaultImageMetadataInterface.h b/Code/IO/otbDefaultImageMetadataInterface.h
index 33d56ae6df..4c50d84104 100644
--- a/Code/IO/otbDefaultImageMetadataInterface.h
+++ b/Code/IO/otbDefaultImageMetadataInterface.h
@@ -130,6 +130,19 @@ public:
   {
   	itkExceptionMacro("GetSatElevation not implemented in DefaultImageMetadataInterface, no captor type found");
   };
+
+
+  /** Get the first wavelength for the spectral band definition */
+  VariableLengthVectorType GetFirstWavelengths( const MetaDataDictionaryType & dict ) const
+  {
+  	itkExceptionMacro("GetFirstWavelengths not implemented in DefaultImageMetadataInterface, no captor type found");
+  };
+
+  /** Get the last wavelength for the spectral band definition */
+  VariableLengthVectorType GetLastWavelengths( const MetaDataDictionaryType & dict ) const
+  {
+  	itkExceptionMacro("GetLastWavelengths not implemented in DefaultImageMetadataInterface, no captor type found");
+  };
    
   bool CanRead( const MetaDataDictionaryType & dict ) const
   {
diff --git a/Code/IO/otbIkonosImageMetadataInterface.cxx b/Code/IO/otbIkonosImageMetadataInterface.cxx
index 49792cd182..a11002f671 100755
--- a/Code/IO/otbIkonosImageMetadataInterface.cxx
+++ b/Code/IO/otbIkonosImageMetadataInterface.cxx
@@ -522,4 +522,93 @@ IkonosImageMetadataInterface::GetSatAzimuth( const MetaDataDictionaryType & dict
 }
 
 
+IkonosImageMetadataInterface::VariableLengthVectorType
+IkonosImageMetadataInterface
+::GetFirstWavelengths( const MetaDataDictionaryType & dict ) const
+{
+  if( !this->CanRead( dict ) )
+  {
+     itkExceptionMacro(<<"Invalid Metadata, no Ikonos Image");
+  }
+  
+  ImageKeywordlistType imageKeywordlist;
+
+  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
+  {
+    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
+  }
+  
+  VariableLengthVectorType wavel(1);
+  wavel.Fill(0.);
+
+  ossimKeywordlist kwl;
+  imageKeywordlist.convertToOSSIMKeywordlist(kwl);
+  std::string key= "support_data.number_bands";
+  int nbBands = ossimString(kwl.find(key.c_str())).toInt();
+
+  // Panchromatic case
+  if(nbBands==1)
+  {
+    wavel.SetSize(1);
+    wavel.Fill(0.526);
+  }
+  else if(nbBands==4)
+  {
+     wavel.SetSize(4);
+     wavel[0] = 0.445;
+     wavel[1] = 0.506;
+     wavel[2] = 0.632;
+     wavel[3] = 0.757;
+  }
+  else
+    itkExceptionMacro(<<"Invalid number of bands...");
+
+  return wavel;
+}
+
+
+IkonosImageMetadataInterface::VariableLengthVectorType
+IkonosImageMetadataInterface
+::GetLastWavelengths( const MetaDataDictionaryType & dict ) const
+{
+  if( !this->CanRead( dict ) )
+  {
+  	itkExceptionMacro(<<"Invalid Metadata, no Ikonos Image");
+  }
+  
+  ImageKeywordlistType imageKeywordlist;
+
+  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
+  {
+    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
+  }
+  
+  VariableLengthVectorType wavel(1);
+  wavel.Fill(0.);
+   
+  ossimKeywordlist kwl;
+  imageKeywordlist.convertToOSSIMKeywordlist(kwl);
+  std::string key= "support_data.number_bands";
+  int nbBands = ossimString(kwl.find(key.c_str())).toInt();
+
+  // Panchromatic case
+  if(nbBands==1)
+  {
+    wavel.SetSize(1);
+    wavel.Fill(0.929);
+  }
+  else if(nbBands==4)
+  {
+     wavel.SetSize(4);
+     wavel[0] = 0.516;
+     wavel[1] = 0.595;
+     wavel[2] = 0.698;
+     wavel[3] = 0.853;
+  }
+  else
+    itkExceptionMacro(<<"Invalid number of bands...");
+
+  return wavel;
+}
+
 } // end namespace otb
diff --git a/Code/IO/otbIkonosImageMetadataInterface.h b/Code/IO/otbIkonosImageMetadataInterface.h
index 161d9c7384..a8d091570d 100644
--- a/Code/IO/otbIkonosImageMetadataInterface.h
+++ b/Code/IO/otbIkonosImageMetadataInterface.h
@@ -93,6 +93,12 @@ public:
   /** Get the sat azimuth from the ossim metadata */
   double GetSatAzimuth( const MetaDataDictionaryType & dict ) const;
   
+  /** Get the first wavelength for the spectral band definition */
+  VariableLengthVectorType GetFirstWavelengths( const MetaDataDictionaryType & dict ) const;
+  
+  /** Get the last wavelength for the spectral band definition */
+  VariableLengthVectorType GetLastWavelengths( const MetaDataDictionaryType & dict ) const;
+  
   bool CanRead( const MetaDataDictionaryType & dict) const;
   
  
diff --git a/Code/IO/otbImageMetadataInterfaceBase.h b/Code/IO/otbImageMetadataInterfaceBase.h
index 3a95fc0e97..3ddc902354 100644
--- a/Code/IO/otbImageMetadataInterfaceBase.h
+++ b/Code/IO/otbImageMetadataInterfaceBase.h
@@ -194,6 +194,14 @@ public:
   virtual double GetSatAzimuth( const MetaDataDictionaryType & dict ) const =0;
   otbMetadataGetMacro(SatAzimuth, double);
 
+  /** Get the first wavelength for the spectral band definition */
+  virtual VariableLengthVectorType GetFirstWavelengths( const MetaDataDictionaryType & dict ) const =0;
+  otbMetadataGetMacro(FirstWavelengths, VariableLengthVectorType);
+
+  /** Get the last wavelength for the spectral band definition */
+  virtual VariableLengthVectorType GetLastWavelengths( const MetaDataDictionaryType & dict ) const =0;
+  otbMetadataGetMacro(LastWavelengths, VariableLengthVectorType);
+
   virtual bool CanRead( const MetaDataDictionaryType & dict ) const =0;
 
   virtual void PrintSelf(std::ostream& os, itk::Indent indent, const MetaDataDictionaryType & dict) const;
diff --git a/Code/IO/otbQuickBirdImageMetadataInterface.cxx b/Code/IO/otbQuickBirdImageMetadataInterface.cxx
index 26d74ae29f..b5dd89f1d6 100755
--- a/Code/IO/otbQuickBirdImageMetadataInterface.cxx
+++ b/Code/IO/otbQuickBirdImageMetadataInterface.cxx
@@ -625,6 +625,101 @@ QuickBirdImageMetadataInterface::GetSatAzimuth( const MetaDataDictionaryType & d
   return keywordString.toDouble();
 }
 
+QuickBirdImageMetadataInterface::VariableLengthVectorType
+QuickBirdImageMetadataInterface
+::GetFirstWavelengths( const MetaDataDictionaryType & dict ) const
+{
+  if( !this->CanRead( dict ) )
+  {
+  	itkExceptionMacro(<<"Invalid Metadata, no QuickBird Image");
+  }
+  
+  ImageKeywordlistType imageKeywordlist;
+
+  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
+  {
+    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
+  }
+  
+  VariableLengthVectorType wavel(1);
+  wavel.Fill(0.);
+  
+  ossimKeywordlist kwl;
+  imageKeywordlist.convertToOSSIMKeywordlist(kwl);
+  std::string key = "support_data.band_id";
+  ossimString keywordStringBId = kwl.find(key.c_str());
+
+  if (keywordStringBId != ossimString("P") && keywordStringBId != ossimString("Multi"))
+  {
+    itkExceptionMacro(<<"Invalid bandID "<<keywordStringBId);
+  }
+
+  // Panchromatic case
+  if (keywordStringBId == ossimString("P") )
+  {
+    wavel.SetSize(1);
+    wavel.Fill(0.450);
+  }
+  else
+  {
+     wavel.SetSize(4);
+     wavel[0] = 0.450;
+     wavel[1] = 0.520;
+     wavel[2] = 0.630;
+     wavel[3] = 0.760;
+  }
+
+  return wavel;
+}
+
+
+QuickBirdImageMetadataInterface::VariableLengthVectorType
+QuickBirdImageMetadataInterface
+::GetLastWavelengths( const MetaDataDictionaryType & dict ) const
+{
+  if( !this->CanRead( dict ) )
+  {
+  	itkExceptionMacro(<<"Invalid Metadata, no QuickBird Image");
+  }
+  
+  ImageKeywordlistType imageKeywordlist;
+
+  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
+  {
+    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
+  }
+  
+  VariableLengthVectorType wavel(1);
+  wavel.Fill(0.);
+  
+  ossimKeywordlist kwl;
+  imageKeywordlist.convertToOSSIMKeywordlist(kwl);
+  std::string key = "support_data.band_id";
+  ossimString keywordStringBId = kwl.find(key.c_str());
+
+  if (keywordStringBId != ossimString("P") && keywordStringBId != ossimString("Multi"))
+  {
+    itkExceptionMacro(<<"Invalid bandID "<<keywordStringBId);
+  }
+
+  // Panchromatic case
+  if (keywordStringBId == ossimString("P") )
+  {
+    wavel.SetSize(1);
+    wavel.Fill(0.900);
+  }
+  else
+  {
+     wavel.SetSize(4);
+     wavel[0] = 0.520;
+     wavel[1] = 0.600;
+     wavel[2] = 0.690;
+     wavel[3] = 0.900;
+  }
+
+  return wavel;
+}
+
 
 
 } // end namespace otb
diff --git a/Code/IO/otbQuickBirdImageMetadataInterface.h b/Code/IO/otbQuickBirdImageMetadataInterface.h
index 0c9000f92f..73c2c757a5 100644
--- a/Code/IO/otbQuickBirdImageMetadataInterface.h
+++ b/Code/IO/otbQuickBirdImageMetadataInterface.h
@@ -91,6 +91,12 @@ public:
   
   /** Get the sat azimuth from the ossim metadata */
   double GetSatAzimuth( const MetaDataDictionaryType & dict ) const;
+
+  /** Get the first wavelength for the spectral band definition */
+  VariableLengthVectorType GetFirstWavelengths( const MetaDataDictionaryType & dict ) const;
+  
+  /** Get the last wavelength for the spectral band definition */
+  VariableLengthVectorType GetLastWavelengths( const MetaDataDictionaryType & dict ) const;
   
   bool CanRead( const MetaDataDictionaryType & dict) const;
   
diff --git a/Code/IO/otbSpotImageMetadataInterface.cxx b/Code/IO/otbSpotImageMetadataInterface.cxx
index 2d03f6fa37..7b930df34e 100755
--- a/Code/IO/otbSpotImageMetadataInterface.cxx
+++ b/Code/IO/otbSpotImageMetadataInterface.cxx
@@ -532,5 +532,107 @@ SpotImageMetadataInterface::GetSatAzimuth( const MetaDataDictionaryType & dict )
   return satAz;
 }
 
+SpotImageMetadataInterface::VariableLengthVectorType
+SpotImageMetadataInterface
+::GetFirstWavelengths( const MetaDataDictionaryType & dict ) const
+{
+  if( !this->CanRead( dict ) )
+  {
+  	itkExceptionMacro(<<"Invalid Metadata, no Spot Image");
+  }
+  
+  ImageKeywordlistType imageKeywordlist;
+
+  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
+  {
+    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
+  }
+  
+  VariableLengthVectorType wavel(1);
+  wavel.Fill(0.);
+
+  
+  ossimKeywordlist kwl;
+  imageKeywordlist.convertToOSSIMKeywordlist(kwl);
+  std::string key= "support_data.number_bands";
+  int nbBands = ossimString(kwl.find(key.c_str())).toInt();
+  std::string sensorId = this->GetSensorID(dict);
+
+  // Panchromatic case
+  if(nbBands==1)
+  {
+    wavel.SetSize(1);
+    if(sensorId == "SPOT4")
+      wavel.Fill(0.610);
+    else if(sensorId == "SPOT5")
+      wavel.Fill(0.480);
+    else
+      itkExceptionMacro(<<"Invalid Spot Sensor ID");
+  }
+  else if(nbBands>1 && nbBands<5)
+  {
+     wavel.SetSize(4);
+     wavel[0] = 0.500;
+     wavel[1] = 0.610;
+     wavel[2] = 0.780;
+     wavel[3] = 1.580;
+  }
+  else
+    itkExceptionMacro(<<"Invalid number of bands...");
+
+  return wavel;
+}
+
+
+SpotImageMetadataInterface::VariableLengthVectorType
+SpotImageMetadataInterface
+::GetLastWavelengths( const MetaDataDictionaryType & dict ) const
+{
+  if( !this->CanRead( dict ) )
+  {
+  	itkExceptionMacro(<<"Invalid Metadata, no Spot Image");
+  }
+  
+  ImageKeywordlistType imageKeywordlist;
+
+  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
+  {
+    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
+  }
+  
+  VariableLengthVectorType wavel(1);
+  wavel.Fill(0.);
+
+  ossimKeywordlist kwl;
+  imageKeywordlist.convertToOSSIMKeywordlist(kwl);
+  std::string key= "support_data.number_bands";
+  int nbBands = ossimString(kwl.find(key.c_str())).toInt();
+  std::string sensorId = this->GetSensorID(dict);
+
+  // Panchromatic case
+  if(nbBands==1)
+  {
+    wavel.SetSize(1);
+    if(sensorId == "SPOT4")
+      wavel.Fill(0.680);
+    else if(sensorId == "SPOT5")
+      wavel.Fill(0.710);
+    else
+      itkExceptionMacro(<<"Invalid Spot Sensor ID");
+  }
+  else if(nbBands>1 && nbBands<5)
+  {
+     wavel.SetSize(4);
+     wavel[0] = 0.590;
+     wavel[1] = 0.680;
+     wavel[2] = 0.890;
+     wavel[3] = 1.750;
+  }
+  else
+    itkExceptionMacro(<<"Invalid number of bands...");
+
+  return wavel;
+}
+
 
 } // end namespace otb
diff --git a/Code/IO/otbSpotImageMetadataInterface.h b/Code/IO/otbSpotImageMetadataInterface.h
index f73e31e713..4d6b9672e1 100644
--- a/Code/IO/otbSpotImageMetadataInterface.h
+++ b/Code/IO/otbSpotImageMetadataInterface.h
@@ -93,6 +93,12 @@ public:
   /** Get the sat azimuth from the ossim metadata */
   double GetSatAzimuth( const MetaDataDictionaryType & dict ) const;
   
+  /** Get the first wavelength for the spectral band definition */
+  VariableLengthVectorType GetFirstWavelengths( const MetaDataDictionaryType & dict ) const;
+  
+  /** Get the last wavelength for the spectral band definition */
+  VariableLengthVectorType GetLastWavelengths( const MetaDataDictionaryType & dict ) const;
+
   bool CanRead( const MetaDataDictionaryType & dict) const;
 
   
diff --git a/Code/Radiometry/otbAtmosphericCorrectionParameters.cxx b/Code/Radiometry/otbAtmosphericCorrectionParameters.cxx
index f7539476f4..e99d56c0c3 100644
--- a/Code/Radiometry/otbAtmosphericCorrectionParameters.cxx
+++ b/Code/Radiometry/otbAtmosphericCorrectionParameters.cxx
@@ -18,6 +18,12 @@ PURPOSE.  See the above copyright notices for more information.
 
 #include "otbAtmosphericCorrectionParameters.h"
 
+#include "otbAeronetFileReader.h"
+#include <fstream>
+#include <iostream>
+
+
+
 namespace otb
 {
 /***********************      FilterFunctionValues **************************/
@@ -26,6 +32,7 @@ FilterFunctionValues
 {
   m_MinSpectralValue = 0;
   m_MaxSpectralValue = 0;
+  m_UserStep = 0.0025;
   m_FilterFunctionValues.clear();
 }
 
@@ -59,20 +66,56 @@ FilterFunctionValues
 AtmosphericCorrectionParameters
 ::AtmosphericCorrectionParameters()
 {
-  m_SolarZenithalAngle = 361.;
-  m_SolarAzimutalAngle = 361.;
+  m_SolarZenithalAngle   = 361.;
+  m_SolarAzimutalAngle   = 361.;
   m_ViewingZenithalAngle = 361.;
   m_ViewingAzimutalAngle = 361.;
-  m_Month = 0;
-  m_Day = 0;
-  m_AtmosphericPressure = 1030.;
-  m_WaterVaporAmount = 2.5;
-  m_OzoneAmount = 0.28;
-  m_AerosolModel = CONTINENTAL;
-  m_AerosolOptical = 0.2;
+  m_Month                = 0;
+  m_Day                  = 0;
+  m_AtmosphericPressure  = 1030.;
+  m_WaterVaporAmount     = 2.5;
+  m_OzoneAmount          = 0.28;
+  m_AerosolModel         = CONTINENTAL;
+  m_AerosolOptical       = 0.2;
+}
 
+/** Get data from aeronet file*/
+void
+AtmosphericCorrectionParameters
+::UpdateAeronetData( std::string file, int year, int month, int day, int hour, int minute, double epsi )
+{ 
+	if(file == "")
+	  itkExceptionMacro(<<"No Aeronet filename specified.");
+		
+    AeronetFileReader::Pointer reader = AeronetFileReader::New();
+    reader->SetFileName(file);
+    reader->SetDay(day);
+    reader->SetMonth(month);
+    reader->SetYear(year);
+    reader->SetHour(hour);
+    reader->SetMinute(minute);
+    reader->SetEpsilon(epsi);
+    std::cout<<day<<std::endl;
+    std::cout<<month<<std::endl;
+    std::cout<<year<<std::endl;
+    std::cout<<hour<<std::endl;
+    std::cout<<minute<<std::endl;
+    std::cout<<epsi<<std::endl;
+
+    std::cout<<reader->GetDay()<<std::endl;
+    std::cout<<reader->GetMonth()<<std::endl;
+    std::cout<<reader->GetYear()<<std::endl;
+    std::cout<<reader->GetHour()<<std::endl;
+    std::cout<<reader->GetMinute()<<std::endl;
+    std::cout<<reader->GetEpsilon()<<std::endl;
+                    
+    reader->Update();
+    
+    m_AerosolOptical = reader->GetOutput()->GetAerosolOpticalThickness();
+    m_WaterVaporAmount = reader->GetOutput()->GetWater();
 }
 
+
 /**PrintSelf method */
 void
 AtmosphericCorrectionParameters
diff --git a/Code/Radiometry/otbAtmosphericCorrectionParameters.h b/Code/Radiometry/otbAtmosphericCorrectionParameters.h
index 79fff9db12..353bbe6cc4 100644
--- a/Code/Radiometry/otbAtmosphericCorrectionParameters.h
+++ b/Code/Radiometry/otbAtmosphericCorrectionParameters.h
@@ -90,6 +90,7 @@ public:
   /** Get user step between each wavelenght spectral band values. */
   itkGetMacro(UserStep,WavelenghtSpectralBandType);
 
+
 protected:
   /** Constructor */
   FilterFunctionValues();
@@ -103,8 +104,7 @@ protected:
 private:
   FilterFunctionValues(const Self&); //purposely not implemented
   void operator=(const Self&); //purposely not implemented
-
-
+     
   /** Vector that contains the filter function value. */
   ValuesVectorType m_FilterFunctionValues;
   /** Vector that contains the filter function value in 6S format (step of 0.0025µm).
@@ -242,6 +242,22 @@ public:
     return &m_WavelenghtSpectralBand;
   };
 
+  /** Read the aeronet data and extract aerosol optical and water vapor amount. */
+  void UpdateAeronetData( std::string file, int year, int month, int day, int hour, int minute, double epsi );
+  void UpdateAeronetData( std::string file, int year, int month, int day, int hour, int minute )
+  {
+  	this->UpdateAeronetData( file, year, month, day, hour, minute, 0.4 );
+  };
+  void UpdateAeronetData( std::string file, int year, int hour, int minute, double epsi )
+  {
+  	this->UpdateAeronetData( file, year, m_Month, m_Day, hour, minute, epsi );
+  };
+  void UpdateAeronetData( std::string file, int year, int hour, int minute )
+  {
+  	this->UpdateAeronetData( file, year, m_Month, m_Day, hour, minute, 0.4 );
+  };
+    
+  
   /** Constructor */
   AtmosphericCorrectionParameters();
   /** Destructor */
@@ -278,10 +294,8 @@ private:
   AerosolModelType m_AerosolModel;
   /** The Aerosol optical (radiative impact of aerosol for the reference wavelenght 550-nm) */
   double m_AerosolOptical;
-
   /** Wavelenght for the each spectral band definition */
   WavelenghtSpectralBandVectorType m_WavelenghtSpectralBand;
-
 };
 
 } // end namespace otb
diff --git a/Code/Radiometry/otbAtmosphericCorrectionParametersTo6SAtmosphericRadiativeTerms.cxx b/Code/Radiometry/otbAtmosphericCorrectionParametersTo6SAtmosphericRadiativeTerms.cxx
index 8fc75cc5c7..05ee358b6f 100644
--- a/Code/Radiometry/otbAtmosphericCorrectionParametersTo6SAtmosphericRadiativeTerms.cxx
+++ b/Code/Radiometry/otbAtmosphericCorrectionParametersTo6SAtmosphericRadiativeTerms.cxx
@@ -155,10 +155,10 @@ AtmosphericCorrectionParametersTo6SAtmosphericRadiativeTerms
   double upwardDirectTransmittance(0.);
   double upwardDiffuseTransmittanceForRayleigh(0.);
   double upwardDiffuseTransmittanceForAerosol(0.);
-
+  
   for (unsigned int i=0; i<NbBand; ++i)
   {
-    atmosphericReflectance = 0.;
+  	atmosphericReflectance = 0.;
     atmosphericSphericalAlbedo = 0.;
     totalGaseousTransmission = 0.;
     downwardTransmittance = 0.;
diff --git a/Code/Radiometry/otbAtmosphericRadiativeTerms.cxx b/Code/Radiometry/otbAtmosphericRadiativeTerms.cxx
index e3540908cf..9f615440d7 100644
--- a/Code/Radiometry/otbAtmosphericRadiativeTerms.cxx
+++ b/Code/Radiometry/otbAtmosphericRadiativeTerms.cxx
@@ -505,6 +505,15 @@ AtmosphericRadiativeTerms
   {
     os << indent << "Channel "<< i << " : "<< std::endl;
     //ValueType::(os,indent);
+    os << indent << "Intrinsic Atmospheric Reflectance        : " << m_Values[i]->GetIntrinsicAtmosphericReflectance() << std::endl;
+    os << indent << "Shperical Albedo of the Atmosphere       : " << m_Values[i]->GetSphericalAlbedo() << std::endl;
+    os << indent << "Total Gaseous Transmission               : " << m_Values[i]->GetTotalGaseousTransmission() << std::endl;
+    os << indent << "Downward Transmittance of the Atmospher  : " << m_Values[i]->GetDownwardTransmittance() << std::endl;
+    os << indent << "Upward Transmittance of the Atmospher    : " << m_Values[i]->GetUpwardTransmittance() << std::endl;
+    os << indent << "Upward diffuse transmittance             : " << m_Values[i]->GetUpwardDiffuseTransmittance() << std::endl;
+    os << indent << "Upward direct transmittance              : " << m_Values[i]->GetUpwardDirectTransmittance() << std::endl;
+    os << indent << "Upward diffuse transmittance for rayleigh: " << m_Values[i]->GetUpwardDiffuseTransmittanceForRayleigh() << std::endl;
+    os << indent << "Upward diffuse transmittance for aerosols: " << m_Values[i]->GetUpwardDiffuseTransmittanceForAerosol() << std::endl;
   }
 }
 
diff --git a/Code/Radiometry/otbReflectanceToSurfaceReflectanceImageFilter.h b/Code/Radiometry/otbReflectanceToSurfaceReflectanceImageFilter.h
index 7c2a41be29..8111427e48 100644
--- a/Code/Radiometry/otbReflectanceToSurfaceReflectanceImageFilter.h
+++ b/Code/Radiometry/otbReflectanceToSurfaceReflectanceImageFilter.h
@@ -158,6 +158,10 @@ public:
   typedef AtmosphericCorrectionParameters::Pointer                      CorrectionParametersPointerType;
   typedef AtmosphericRadiativeTerms::Pointer                            AtmosphericRadiativeTermsPointerType;
 
+  typedef FilterFunctionValues                                          FilterFunctionValuesType;
+  typedef FilterFunctionValuesType::ValuesVectorType                    CoefVectorType;
+  typedef std::vector<CoefVectorType>                                   FilterFunctionCoefVectorType;
+  
   typedef itk::MetaDataDictionary                                       MetaDataDictionaryType;
 
   /** Get/Set Atmospheric Radiative Terms. */
@@ -177,6 +181,21 @@ public:
   itkSetMacro(AeronetFileName, std::string);
   itkGetMacro(AeronetFileName, std::string);
 
+  /** Get/Set Aeronet file name. */
+  itkSetMacro(FilterFunctionValuesFileName, std::string);
+  itkGetMacro(FilterFunctionValuesFileName, std::string);
+
+  /** Get/Set Filter function coef. */
+  void SetFilterFunctionCoef( FilterFunctionCoefVectorType vect )
+  {
+  	m_FilterFunctionCoef = vect;
+  	this->Modified();
+  }
+  FilterFunctionCoefVectorType GetFilterFunctionCoef()
+  {
+  	return m_FilterFunctionCoef;
+  }
+
 protected:
   /** Constructor */
   ReflectanceToSurfaceReflectanceImageFilter();
@@ -199,6 +218,12 @@ private:
   bool m_IsSetAtmosphericRadiativeTerms;
   /** Path to an Aeronet data file, allows to compute aerosol optical and water vapor amounts. */
   std::string m_AeronetFileName;
+  /** Path to an filter function values file. */
+  std::string m_FilterFunctionValuesFileName;
+  /** Contains the filter function values (each element is a vector and represnts the values for each channel) */
+  FilterFunctionCoefVectorType m_FilterFunctionCoef;
+  /** BeforeThreadedGenerateData executed once or not */
+  bool m_BeforeDone;
 };
 
 } // end namespace otb
diff --git a/Code/Radiometry/otbReflectanceToSurfaceReflectanceImageFilter.txx b/Code/Radiometry/otbReflectanceToSurfaceReflectanceImageFilter.txx
new file mode 100644
index 0000000000..dfd308f360
--- /dev/null
+++ b/Code/Radiometry/otbReflectanceToSurfaceReflectanceImageFilter.txx
@@ -0,0 +1,152 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef __otbReflectanceToSurfaceReflectanceImageFilter_txx
+#define __otbReflectanceToSurfaceReflectanceImageFilter_txx
+
+#include "otbReflectanceToSurfaceReflectanceImageFilter.h"
+#include "otbImageMetadataInterfaceFactory.h"
+#include "otbImageMetadataInterfaceBase.h"
+#include "otbAeronetFileReader.h"
+
+namespace otb
+{
+
+/**
+ * Constructor
+ */
+template <class TInputImage, class TOutputImage>
+ReflectanceToSurfaceReflectanceImageFilter<TInputImage,TOutputImage>
+::ReflectanceToSurfaceReflectanceImageFilter()
+{
+  m_AtmosphericRadiativeTerms = AtmosphericRadiativeTerms::New();
+  m_CorrectionParameters      = AtmosphericCorrectionParameters::New();
+  m_IsSetAtmosphericRadiativeTerms = false;
+  m_BeforeDone = false;
+  m_AeronetFileName = "";
+  m_FilterFunctionValuesFileName = "";
+  m_FilterFunctionCoef.clear();
+}
+
+
+template <class TInputImage, class TOutputImage>
+void
+ReflectanceToSurfaceReflectanceImageFilter<TInputImage,TOutputImage>
+::UpdateAtmosphericRadiativeTerms( const MetaDataDictionaryType dict )
+{
+	 ImageMetadataInterfaceBase::Pointer imageMetadataInterface = ImageMetadataInterfaceFactory::CreateIMI(dict);
+	 
+    if ((m_CorrectionParameters->GetDay() == 0))
+    {
+      m_CorrectionParameters->SetDay(imageMetadataInterface->GetDay(dict));
+    }
+
+    if ((m_CorrectionParameters->GetMonth() == 0))
+    {
+      m_CorrectionParameters->SetMonth(imageMetadataInterface->GetMonth(dict));
+    }
+
+    if ((m_CorrectionParameters->GetSolarZenithalAngle() == 361.))
+    {
+      m_CorrectionParameters->SetSolarZenithalAngle(90. - imageMetadataInterface->GetSunElevation(dict));
+    }
+    
+    if ((m_CorrectionParameters->GetSolarAzimutalAngle() == 361.))
+    {
+      m_CorrectionParameters->SetSolarAzimutalAngle(imageMetadataInterface->GetSunAzimuth(dict));
+    }
+
+    if ((m_CorrectionParameters->GetViewingZenithalAngle() == 361.))
+    {
+      m_CorrectionParameters->SetViewingZenithalAngle(90. - imageMetadataInterface->GetSatElevation(dict));
+    }
+    
+    if ((m_CorrectionParameters->GetViewingAzimutalAngle() == 361.))
+    {
+      m_CorrectionParameters->SetViewingAzimutalAngle(imageMetadataInterface->GetSatAzimuth(dict));
+    }
+    
+    if(m_AeronetFileName != "")
+      m_CorrectionParameters->UpdateAeronetData( m_AeronetFileName, 
+      											 imageMetadataInterface->GetYear(dict),
+      											 imageMetadataInterface->GetHour(dict),
+      											 imageMetadataInterface->GetMinute(dict) );    
+      
+    Parameters2RadiativeTermsPointerType param2Terms = Parameters2RadiativeTermsType::New();
+    
+    if( m_FilterFunctionCoef.size() != this->GetInput()->GetNumberOfComponentsPerPixel() )
+    	itkExceptionMacro(<<"Filter Function and image channels mismatch.");
+   
+    for(unsigned int i=0; i<this->GetInput()->GetNumberOfComponentsPerPixel(); i++)
+    {
+	  FilterFunctionValuesType::Pointer functionValues = FilterFunctionValuesType::New();
+	  functionValues->SetFilterFunctionValues(m_FilterFunctionCoef[i]);
+      functionValues->SetMinSpectralValue(imageMetadataInterface->GetFirstWavelengths(dict)[i]);
+      functionValues->SetMaxSpectralValue(imageMetadataInterface->GetLastWavelengths(dict)[i]);
+
+      m_CorrectionParameters->SetWavelenghtSpectralBandWithIndex(i, functionValues);
+    }
+   
+    param2Terms->SetInput(m_CorrectionParameters);
+    param2Terms->Update();
+   
+    m_AtmosphericRadiativeTerms = param2Terms->GetOutput();
+}
+
+
+template <class TInputImage, class TOutputImage>
+void
+ReflectanceToSurfaceReflectanceImageFilter<TInputImage,TOutputImage>
+::BeforeThreadedGenerateData()
+{
+  if(m_BeforeDone == true)
+	return;
+	
+  std::cout<<"BeforeThreadedGenerateData "<<this->GetNumberOfThreads()<<std::endl;
+  if(m_IsSetAtmosphericRadiativeTerms==false)
+    this->UpdateAtmosphericRadiativeTerms(this->GetInput()->GetMetaDataDictionary());
+  
+      std::cout<<"m_CorrectionParameters: "<<std::endl;
+    std::cout<<m_CorrectionParameters<<std::endl;
+    std::cout<<"m_AtmosphericRadiativeTerms: "<<std::endl;    
+    std::cout<<m_AtmosphericRadiativeTerms<<std::endl;
+  
+  this->GetFunctorVector().clear();
+  for (unsigned int i = 0;i<this->GetInput()->GetNumberOfComponentsPerPixel();++i)
+  {
+    double coef;
+    double res;
+    coef = static_cast<double>(m_AtmosphericRadiativeTerms->GetTotalGaseousTransmission(i)
+                                 * m_AtmosphericRadiativeTerms->GetDownwardTransmittance(i)
+                                 * m_AtmosphericRadiativeTerms->GetUpwardTransmittance(i)     );
+    coef = 1. / coef;
+    res = -m_AtmosphericRadiativeTerms->GetIntrinsicAtmosphericReflectance(i) * coef;
+
+    FunctorType functor;
+    functor.SetCoefficient(coef);
+    functor.SetResidu(res);
+    functor.SetSphericalAlbedo(static_cast<double>(m_AtmosphericRadiativeTerms->GetSphericalAlbedo(i)));
+
+    this->GetFunctorVector().push_back(functor);
+  }
+  m_BeforeDone = true;
+  std::cout<<"BeforeThreadedGenerateData FIN"<<std::endl;
+}
+  
+}
+
+#endif
-- 
GitLab