From 5a410338f706b2edd98b15eebc18be0464b5fda5 Mon Sep 17 00:00:00 2001
From: Rashad Kanavath <rashad.kanavath@c-s.fr>
Date: Wed, 7 Oct 2015 11:35:40 +0200
Subject: [PATCH] ENH: Radarsat2 image metadata interface

---
 .../otbRadarsat2ImageMetadataInterface.h      | 203 ++++++++++++
 ...tbRadarsat2ImageMetadataInterfaceFactory.h |  68 ++++
 Modules/Core/Metadata/src/CMakeLists.txt      |   3 +
 .../otbRadarsat2ImageMetadataInterface.cxx    | 291 ++++++++++++++++++
 ...Radarsat2ImageMetadataInterfaceFactory.cxx |  58 ++++
 .../otbRadarsat2ImageMetadataInterfaceNew.cxx |  32 ++
 6 files changed, 655 insertions(+)
 create mode 100644 Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterface.h
 create mode 100644 Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterfaceFactory.h
 create mode 100644 Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterface.cxx
 create mode 100644 Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterfaceFactory.cxx
 create mode 100644 Modules/Core/Metadata/test/otbRadarsat2ImageMetadataInterfaceNew.cxx

diff --git a/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterface.h b/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterface.h
new file mode 100644
index 0000000000..46439ca652
--- /dev/null
+++ b/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterface.h
@@ -0,0 +1,203 @@
+/*=========================================================================
+
+  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 __otbRadarsat2ImageMetadataInterface_h
+#define __otbRadarsat2ImageMetadataInterface_h
+
+#include "otbSarImageMetadataInterface.h"
+
+namespace otb
+{
+/** \class Radarsat2ImageMetadataInterface
+ *
+ * \brief Creation of an "otb" Radarsat2ImageMetadataInterface that gets metadata.
+ *
+ *
+ * \ingroup OTBMetadata
+ */
+
+class ITK_ABI_EXPORT Radarsat2ImageMetadataInterface : public SarImageMetadataInterface
+{
+public:
+
+  typedef Radarsat2ImageMetadataInterface    Self;
+  typedef SarImageMetadataInterface         Superclass;
+  typedef itk::SmartPointer<Self>         Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(Radarsat2ImageMetadataInterface, SarImageMetadataInterface);
+
+  typedef Superclass::ImageType                ImageType;
+  typedef Superclass::MetaDataDictionaryType   MetaDataDictionaryType;
+  typedef Superclass::VectorType               VectorType;
+  typedef Superclass::VariableLengthVectorType VariableLengthVectorType;
+  typedef Superclass::ImageKeywordlistType     ImageKeywordlistType;
+  typedef Superclass::LookupDataPointerType LookupDataPointerType;
+//  typedef Radarsat2CalibrationLookupData::Pointer          LookupDataPointerType;
+
+  /*ImageMetadataInterfaceBase pure virtuals */
+  /** Get the imaging production day from the ossim metadata : DATASET_PRODUCTION_DATE metadata variable */
+  int GetProductionDay() const;
+
+  /** Get the imaging production month from the ossim metadata : DATASET_PRODUCTION_DATE metadata variable */
+  int GetProductionMonth() const;
+
+  /** Get the imaging production year from the ossim metadata : DATASET_PRODUCTION_DATE metadata variable */
+  int GetProductionYear() const;
+
+  /** check sensor ID */
+  bool CanRead() const;
+
+  int GetDay() const;
+
+  int GetMonth() const;
+
+  int GetYear() const;
+
+  int GetHour() const;
+
+  int GetMinute() const;
+
+  UIntVectorType GetDefaultDisplay() const;
+
+  /*SarImageMetadataInterface pure virutals rituals */
+  double GetPRF() const;
+
+  double GetRSF() const;
+
+  double GetRadarFrequency() const;
+
+  double GetCenterIncidenceAngle() const;
+
+  /*get lookup data for calulating backscatter */
+  void CreateCalibrationLookupData(const short type);
+
+
+protected:
+  /* class constructor */
+  Radarsat2ImageMetadataInterface();
+
+  /* class desctructor */
+  virtual ~Radarsat2ImageMetadataInterface() {}
+
+private:
+  Radarsat2ImageMetadataInterface(const Self &); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+
+/* Helper function to parse date and time into a std::vector<std::string>
+ * using boost::split() expect date time in yyyy-mm-ddThh:mm:ss.ms
+ * the date-time string is to be found in keywordlist with key 'key'
+ * fills argument dateFields of type std::vector<std::string> which is mutable!
+ * TODO: move this method into base class
+ */
+  void ParseDateTime(const char* key, std::vector<int>& dateFields) const;
+
+  mutable std::vector<int> m_ProductionDateFields;
+  mutable std::vector<int> m_AcquisitionDateFields;
+
+};
+
+
+class Radarsat2CalibrationLookupData : public SarCalibrationLookupData
+{
+
+public:
+
+  /** Standard typedefs */
+  typedef Radarsat2CalibrationLookupData   Self;
+  typedef SarCalibrationLookupData         Superclass;
+  typedef itk::SmartPointer<Self>          Pointer;
+  typedef itk::SmartPointer<const Self>    ConstPointer;
+
+  /** Creation through the object factory */
+  itkNewMacro(Self);
+
+  /** RTTI */
+  itkTypeMacro(Radarsat2CalibrationLookupData, SarCalibrationLookupData);
+
+  typedef itk::IndexValueType IndexValueType;
+
+  typedef std::vector<float> GainListType;
+
+
+  Radarsat2CalibrationLookupData()
+    : m_Offset(0)
+  {
+
+  }
+
+  virtual ~Radarsat2CalibrationLookupData()
+  {
+
+  }
+
+  void InitParameters(short type, int offset,  GainListType gains)
+  {
+    this->SetType(type);
+    m_Offset = offset;
+    m_Gains = gains;
+  }
+
+  double GetValue(const IndexValueType x, const IndexValueType itkNotUsed(y))
+  {
+    double lutVal = 1.0;
+
+    const size_t pos =  x + m_Offset;
+    if(pos  < m_Gains.size())
+      {
+      lutVal = m_Gains[pos];
+      }
+    else
+      {
+      //itkExceptionMacro( << "error: (pos < list.size() )" << pos << " < " << list.size())
+      }
+    return lutVal;
+  }
+
+  void PrintSelf(std::ostream & os, itk::Indent indent) const
+  {
+    os << indent << " offset:'" << m_Offset << "'" << std::endl;
+    os <<  " referenceNoiseLevel.gain: " << std::endl;
+    std::vector<float>::const_iterator it = m_Gains.begin();
+    while (it != m_Gains.end())
+      {
+      os << (*it) << " ";
+      ++it;
+      }
+    os << std::endl;
+
+    Superclass::PrintSelf(os, indent);
+  }
+
+private:
+
+  Radarsat2CalibrationLookupData(const Self&); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+
+  GainListType m_Gains;
+  int m_Offset;
+
+
+};
+
+} // end namespace otb
+
+#endif
diff --git a/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterfaceFactory.h b/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterfaceFactory.h
new file mode 100644
index 0000000000..2aeb8a8f58
--- /dev/null
+++ b/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterfaceFactory.h
@@ -0,0 +1,68 @@
+/*=========================================================================
+
+  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 __otbRadarsat2ImageMetadataInterfaceFactory_h
+#define __otbRadarsat2ImageMetadataInterfaceFactory_h
+
+#include "itkObjectFactoryBase.h"
+
+namespace otb
+{
+/** \class Radarsat2ImageMetadataInterfaceFactory
+ * \brief Creating an instance of a ImageMetadataInterface object using object factory.
+ *
+ * \ingroup OTBMetadata
+ */
+class ITK_EXPORT Radarsat2ImageMetadataInterfaceFactory : public itk::ObjectFactoryBase
+{
+public:
+  /** Standard class typedefs. */
+  typedef Radarsat2ImageMetadataInterfaceFactory Self;
+  typedef itk::ObjectFactoryBase            Superclass;
+  typedef itk::SmartPointer<Self>           Pointer;
+  typedef itk::SmartPointer<const Self>     ConstPointer;
+
+  /** Class methods used to interface with the registered factories. */
+  virtual const char* GetITKSourceVersion(void) const;
+  virtual const char* GetDescription(void) const;
+
+  /** Method for class instantiation. */
+  itkFactorylessNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(Radarsat2ImageMetadataInterfaceFactory, itk::ObjectFactoryBase);
+
+  /** Register one factory of this type  */
+  static void RegisterOneFactory(void)
+  {
+    Pointer factory = Radarsat2ImageMetadataInterfaceFactory::New();
+    itk::ObjectFactoryBase::RegisterFactory(factory);
+  }
+
+protected:
+  Radarsat2ImageMetadataInterfaceFactory();
+  virtual ~Radarsat2ImageMetadataInterfaceFactory();
+
+private:
+  Radarsat2ImageMetadataInterfaceFactory(const Self &); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+
+};
+
+} // end namespace otb
+
+#endif
diff --git a/Modules/Core/Metadata/src/CMakeLists.txt b/Modules/Core/Metadata/src/CMakeLists.txt
index 77dad8c9f5..a81509ee9c 100644
--- a/Modules/Core/Metadata/src/CMakeLists.txt
+++ b/Modules/Core/Metadata/src/CMakeLists.txt
@@ -39,6 +39,9 @@ set(OTBMetadata_SRC
   otbSentinel1ImageMetadataInterfaceFactory.cxx
   otbSentinel1ImageMetadataInterface.cxx
 
+  otbRadarsat2ImageMetadataInterfaceFactory.cxx
+  otbRadarsat2ImageMetadataInterface.cxx
+
   otbNoDataHelper.cxx
   )
 
diff --git a/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterface.cxx b/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterface.cxx
new file mode 100644
index 0000000000..d2ebebf4dc
--- /dev/null
+++ b/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterface.cxx
@@ -0,0 +1,291 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+
+#include "otbSarImageMetadataInterface.h"
+#include "otbRadarsat2ImageMetadataInterface.h"
+
+#include "otbMacro.h"
+#include "itkMetaDataObject.h"
+#include "otbImageKeywordlist.h"
+
+//useful constants
+#include <otbMath.h>
+
+namespace otb
+{
+
+Radarsat2ImageMetadataInterface
+::Radarsat2ImageMetadataInterface()
+{
+
+}
+
+bool
+Radarsat2ImageMetadataInterface::CanRead() const
+{
+  std::string sensorID = GetSensorID();
+
+  if (sensorID.find("RADARSAT-2") != std::string::npos)
+    {
+    return true;
+    }
+  else
+    return false;
+}
+
+
+void
+Radarsat2ImageMetadataInterface::
+CreateCalibrationLookupData(const short type)
+  {
+   std::string lut = "SigmaNought";
+
+   switch (type)
+     {
+     case SarCalibrationLookupData::BETA:
+     {
+     lut = "BetaNought";
+     }
+     break;
+
+     case SarCalibrationLookupData::GAMMA:
+     {
+     lut = "GammaNought";
+     }
+     break;
+
+     case SarCalibrationLookupData::DN:
+     {
+     lut = "DN";
+     }
+     break;
+
+     case SarCalibrationLookupData::SIGMA:
+     default:
+     {
+     lut = "SigmaNought";
+     }
+     break;
+     }
+
+  const ImageKeywordlistType imageKeywordlist =  this->GetImageKeywordlist();
+  const std::string key = "referenceNoiseLevel[" + lut + "].gain";
+
+  Radarsat2CalibrationLookupData::GainListType glist;
+  int offset = 0;
+
+  Utils::ConvertStringToVector(imageKeywordlist.GetMetadataByKey("referenceNoiseLevel[" + lut + "].gain"), glist, "referenceNoiseLevel[" + lut + "].gain");
+
+  Utils::LexicalCast<int>(imageKeywordlist.GetMetadataByKey("referenceNoiseLevel[" + lut + "].offset"), "referenceNoiseLevel[" + lut + "].offset");
+
+  Radarsat2CalibrationLookupData::Pointer sarLut;
+  sarLut = Radarsat2CalibrationLookupData::New();
+  sarLut->InitParameters(type, offset, glist);
+  this->SetCalibrationLookupData(sarLut);
+
+}
+
+void
+Radarsat2ImageMetadataInterface
+::ParseDateTime(const char* key, std::vector<int>& dateFields) const
+{
+  if(dateFields.size() < 1 )
+    {
+    //parse from keyword list
+    if (!this->CanRead())
+      {
+      itkExceptionMacro(<< "Invalid Metadata, not a valid product");
+      }
+
+    const ImageKeywordlistType imageKeywordlist  = this->GetImageKeywordlist();
+    if (!imageKeywordlist.HasKey(key))
+      {
+      itkExceptionMacro( << "no key named " << key );
+      }
+
+    const std::string date_time_str = imageKeywordlist.GetMetadataByKey(key);
+    Utils::ConvertStringToVector(date_time_str, dateFields, " T:-.");
+    }
+}
+
+int
+Radarsat2ImageMetadataInterface::GetYear() const
+{
+  int value = 0;
+  ParseDateTime("support_data.image_date", m_AcquisitionDateFields);
+  if(m_AcquisitionDateFields.size() > 0 )
+    {
+    value = boost::lexical_cast<int>( m_AcquisitionDateFields[0] );
+    }
+  else
+    {
+    itkExceptionMacro( << "Invalid year" );
+    }
+  return value;
+}
+
+int
+Radarsat2ImageMetadataInterface::GetMonth() const
+{
+  int value = 0;
+  ParseDateTime("support_data.image_date", m_AcquisitionDateFields);
+  if(m_AcquisitionDateFields.size() > 1 )
+    {
+    value = boost::lexical_cast<int>( m_AcquisitionDateFields[1] );
+    }
+  else
+    {
+    itkExceptionMacro( << "Invalid month" );
+    }
+  return value;
+}
+
+int
+Radarsat2ImageMetadataInterface::GetDay() const
+{
+  int value = 0;
+  ParseDateTime("support_data.image_date", m_AcquisitionDateFields);
+  if(m_AcquisitionDateFields.size() > 2 )
+    {
+    value = boost::lexical_cast<int>( m_AcquisitionDateFields[2] );
+    }
+  else
+    {
+    itkExceptionMacro( << "Invalid day" );
+    }
+  return value;
+}
+
+int
+Radarsat2ImageMetadataInterface::GetHour() const
+{
+  int value = 0;
+  ParseDateTime("support_data.image_date", m_AcquisitionDateFields);
+  if(m_AcquisitionDateFields.size() > 3 )
+    {
+    value = boost::lexical_cast<int>( m_AcquisitionDateFields[3] );
+    }
+  else
+    {
+    itkExceptionMacro( << "Invalid hour" );
+    }
+  return value;
+}
+
+int
+Radarsat2ImageMetadataInterface::GetMinute() const
+{
+  int value = 0;
+  ParseDateTime("support_data.image_date", m_AcquisitionDateFields);
+  if(m_AcquisitionDateFields.size() > 4 )
+    {
+    value = boost::lexical_cast<int>( m_AcquisitionDateFields[4] );
+    }
+  else
+    {
+    itkExceptionMacro( << "Invalid minute" );
+    }
+  return value;
+}
+
+int
+Radarsat2ImageMetadataInterface::GetProductionYear() const
+{
+  int value = 0;
+  ParseDateTime("support_data.date", m_ProductionDateFields);
+  if(m_ProductionDateFields.size() > 0 )
+    {
+    value = boost::lexical_cast<int>( m_ProductionDateFields[0] );
+    }
+  else
+    {
+    itkExceptionMacro( << "Invalid production year" );
+    }
+  return value;
+
+}
+
+int
+Radarsat2ImageMetadataInterface::GetProductionMonth() const
+{
+  int value = 0;
+  ParseDateTime("support_data.date", m_ProductionDateFields);
+  if(m_ProductionDateFields.size() > 1 )
+    {
+    value = boost::lexical_cast<int>( m_ProductionDateFields[1] );
+    }
+  else
+    {
+    itkExceptionMacro( << "Invalid production month" );
+    }
+  return value;
+}
+
+int
+Radarsat2ImageMetadataInterface::GetProductionDay() const
+{
+  int value = 0;
+  ParseDateTime("support_data.date", m_ProductionDateFields);
+  if(m_ProductionDateFields.size() > 2 )
+    {
+    value = boost::lexical_cast<int>( m_ProductionDateFields[2] );
+    }
+  else
+    {
+    itkExceptionMacro( << "Invalid production day" );
+    }
+  return value;
+}
+
+
+double
+Radarsat2ImageMetadataInterface::GetPRF() const
+{
+  return 0;
+}
+
+double
+Radarsat2ImageMetadataInterface::GetRSF() const
+{
+  return 0;
+}
+
+double
+Radarsat2ImageMetadataInterface::GetRadarFrequency() const
+{
+  return 0;
+}
+
+double
+Radarsat2ImageMetadataInterface::GetCenterIncidenceAngle() const
+{
+  return 0;
+}
+
+Radarsat2ImageMetadataInterface::UIntVectorType
+Radarsat2ImageMetadataInterface::
+GetDefaultDisplay() const
+{
+  UIntVectorType rgb(3);
+  rgb[0] = 0;
+  rgb[1] = 0;
+  rgb[2] = 0;
+  return rgb;
+}
+
+} // end namespace otb
diff --git a/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterfaceFactory.cxx b/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterfaceFactory.cxx
new file mode 100644
index 0000000000..e9f656cfc1
--- /dev/null
+++ b/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterfaceFactory.cxx
@@ -0,0 +1,58 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+
+
+#include <typeinfo>
+#include <cassert>
+
+#include "otbRadarsat2ImageMetadataInterfaceFactory.h"
+#include "otbRadarsat2ImageMetadataInterface.h"
+
+#include "itkCreateObjectFunction.h"
+#include "itkVersion.h"
+
+namespace otb
+{
+Radarsat2ImageMetadataInterfaceFactory
+::Radarsat2ImageMetadataInterfaceFactory()
+{
+  this->RegisterOverride("SarImageMetadataInterface",
+                         "otbRadarsat2ImageMetadataInterface",
+                         "Radarsat2 Metadata Interface",
+                         1,
+                         itk::CreateObjectFunction<Radarsat2ImageMetadataInterface>::New());
+}
+
+Radarsat2ImageMetadataInterfaceFactory
+::~Radarsat2ImageMetadataInterfaceFactory()
+{
+}
+
+const char*
+Radarsat2ImageMetadataInterfaceFactory::GetITKSourceVersion(void) const
+{
+  return ITK_SOURCE_VERSION;
+}
+
+const char*
+Radarsat2ImageMetadataInterfaceFactory::GetDescription() const
+{
+  return "Radarsat2 Metadata Interface Factory, handle Radarsat2 metadata in OTB";
+}
+
+} // end namespace otb
diff --git a/Modules/Core/Metadata/test/otbRadarsat2ImageMetadataInterfaceNew.cxx b/Modules/Core/Metadata/test/otbRadarsat2ImageMetadataInterfaceNew.cxx
new file mode 100644
index 0000000000..191ac66e7a
--- /dev/null
+++ b/Modules/Core/Metadata/test/otbRadarsat2ImageMetadataInterfaceNew.cxx
@@ -0,0 +1,32 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+
+
+
+#include "itkMacro.h"
+#include <iostream>
+#include "otbRadarsat2ImageMetadataInterface.h"
+
+int otbRadarsat2ImageMetadataInterfaceNew(int itkNotUsed(argc), char * itkNotUsed(argv) [])
+{
+  otb::Radarsat2ImageMetadataInterface::Pointer object = otb::Radarsat2ImageMetadataInterface::New();
+
+  std::cout << object << std::endl;
+
+  return EXIT_SUCCESS;
+}
-- 
GitLab