/*
 * Copyright (C) 2005-2017 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.
 */


#include "otbQuickBirdImageMetadataInterface.h"

#include "otbStringUtils.h"
#include "itkMetaDataObject.h"
#include "otbImageKeywordlist.h"

namespace otb
{

QuickBirdImageMetadataInterface
::QuickBirdImageMetadataInterface()
{
}

bool
QuickBirdImageMetadataInterface::CanRead() const
{
  std::string sensorID = GetSensorID();
  if (sensorID.find("QB02") != std::string::npos) return true;
  else return false;
}

QuickBirdImageMetadataInterface::VariableLengthVectorType
QuickBirdImageMetadataInterface::GetSolarIrradiance() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  VariableLengthVectorType outputValuesVariableLengthVector;

  std::string keywordStringBId = imageKeywordlist.GetMetadataByKey("support_data.band_id");
  std::string panchro("P");
  std::string multi("Multi");
  if (keywordStringBId == panchro)
    {
    outputValuesVariableLengthVector.SetSize(1);
    outputValuesVariableLengthVector.Fill(1381.79);
    }
  else if (keywordStringBId == multi)
    {
    outputValuesVariableLengthVector.SetSize(4);
    outputValuesVariableLengthVector[0] = 1924.59;
    outputValuesVariableLengthVector[1] = 1843.08;
    outputValuesVariableLengthVector[2] = 1574.77;
    outputValuesVariableLengthVector[3] = 1113.71;
    }
  else
    {
    itkExceptionMacro(<< "Invalid bandID " << keywordStringBId);
    }

  return outputValuesVariableLengthVector;
}

int
QuickBirdImageMetadataInterface::GetDay() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  std::string key("support_data.tlc_date");
  if (!imageKeywordlist.HasKey(key))
    {
    return -1;
    }

  std::string valueString = imageKeywordlist.GetMetadataByKey(key);
  std::vector<std::string> outputValues;

  boost::split(outputValues, valueString, boost::is_any_of(" T:-"));

  if (outputValues.size() <= 2) itkExceptionMacro(<< "Invalid Day");

  int value = atoi(outputValues[2].c_str());
  return value;
}

int
QuickBirdImageMetadataInterface::GetMonth() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  std::string key("support_data.tlc_date");
  if (!imageKeywordlist.HasKey(key))
    {
    return -1;
    }

  std::string valueString = imageKeywordlist.GetMetadataByKey(key);
  std::vector<std::string> outputValues;

  boost::split(outputValues, valueString, boost::is_any_of(" T:-"));

  if (outputValues.size() <= 2) itkExceptionMacro(<< "Invalid Month");

  int value = atoi(outputValues[1].c_str());
  return value;
}

int
QuickBirdImageMetadataInterface::GetYear() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  std::string key("support_data.tlc_date");
  if (!imageKeywordlist.HasKey(key))
    {
    return -1;
    }

  std::string valueString = imageKeywordlist.GetMetadataByKey(key);
  std::vector<std::string> outputValues;

  boost::split(outputValues, valueString, boost::is_any_of(" T:-"));

  if (outputValues.size() <= 2) itkExceptionMacro(<< "Invalid Year");

  int value = atoi(outputValues[0].c_str());
  return value;
}

int
QuickBirdImageMetadataInterface::GetHour() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  std::string key("support_data.tlc_date");
  if (!imageKeywordlist.HasKey(key))
    {
    return -1;
    }

  std::string valueString = imageKeywordlist.GetMetadataByKey(key);
  std::vector<std::string> outputValues;

  boost::split(outputValues, valueString, boost::is_any_of(" T:-"));

  if (outputValues.size() <= 2) itkExceptionMacro(<< "Invalid Hour");

  int value = atoi(outputValues[3].c_str());
  return value;
}

int
QuickBirdImageMetadataInterface::GetMinute() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  std::string key("support_data.tlc_date");
  if (!imageKeywordlist.HasKey(key))
    {
    return -1;
    }

  std::string valueString = imageKeywordlist.GetMetadataByKey(key);
  std::vector<std::string> outputValues;

  boost::split(outputValues, valueString, boost::is_any_of(" T:-"));

  if (outputValues.size() <= 2) itkExceptionMacro(<< "Invalid Minute");

  int value = atoi(outputValues[4].c_str());
  return value;
}

int
QuickBirdImageMetadataInterface::GetProductionDay() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  std::string key("support_data.generation_date");
  if (!imageKeywordlist.HasKey(key))
    {
    return -1;
    }

  std::string valueString = imageKeywordlist.GetMetadataByKey(key);
  std::vector<std::string> outputValues;

  boost::split(outputValues, valueString, boost::is_any_of(" T:-"));

  if (outputValues.size() <= 2) itkExceptionMacro(<< "Invalid Day");

  int value = atoi(outputValues[2].c_str());
  return value;
}

int
QuickBirdImageMetadataInterface::GetProductionMonth() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  std::string key("support_data.generation_date");
  if (!imageKeywordlist.HasKey(key))
    {
    return -1;
    }

  std::string valueString = imageKeywordlist.GetMetadataByKey(key);
  std::vector<std::string> outputValues;

  boost::split(outputValues, valueString, boost::is_any_of(" T:-"));

  if (outputValues.size() <= 2) itkExceptionMacro(<< "Invalid Month");

  int value = atoi(outputValues[1].c_str());
  return value;
}

int
QuickBirdImageMetadataInterface::GetProductionYear() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  std::string key("support_data.generation_date");
  if (!imageKeywordlist.HasKey(key))
    {
    return -1;
    }

  std::string valueString = imageKeywordlist.GetMetadataByKey(key);
  std::vector<std::string> outputValues;

  boost::split(outputValues, valueString, boost::is_any_of(" T:-"));

  if (outputValues.size() <= 2) itkExceptionMacro(<< "Invalid Year");

  int value = atoi(outputValues[0].c_str());
  return value;
}

QuickBirdImageMetadataInterface::VariableLengthVectorType
QuickBirdImageMetadataInterface
::GetPhysicalBias() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  VariableLengthVectorType outputValuesVariableLengthVector;
  std::string keywordStringBId = imageKeywordlist.GetMetadataByKey("support_data.band_id");
  std::string panchro("P");
  std::string multi("Multi");
  if (keywordStringBId == panchro)
    {
    outputValuesVariableLengthVector.SetSize(1);
    outputValuesVariableLengthVector.Fill(0.0);
    }
  else if (keywordStringBId == multi)
    {
    outputValuesVariableLengthVector.SetSize(4);
    outputValuesVariableLengthVector.Fill(0.0);
    }
  else
    {
    itkExceptionMacro(<< "Invalid bandID " << keywordStringBId);
    }

  return outputValuesVariableLengthVector;
}

QuickBirdImageMetadataInterface::VariableLengthVectorType
QuickBirdImageMetadataInterface
::GetPhysicalGain() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  int  productionYear = this->GetProductionYear(); //keywordStrings[0].toInt();
  int  productionMonth = this->GetProductionMonth(); //keywordStrings[1].toInt();
  int  productionDay = this->GetProductionDay(); //keywordStrings[2].toInt();
  bool isPost20030606 = false;
  if (productionYear > 2003) isPost20030606 = true;
  else
    {
    if (productionYear == 2003)
      {
      if (productionMonth > 6) isPost20030606 = true;
      else
        if (productionDay >= 6) isPost20030606 = true;
      }
    }

  //Value computed from
  // Radiance Conversion of QuickBird Data - Technical Note.
  std::string keywordStringBitsPerPixel = imageKeywordlist.GetMetadataByKey("support_data.bits_per_pixel");
  int         bitsPerPixel = atoi(keywordStringBitsPerPixel.c_str());
  if (bitsPerPixel != 16 && bitsPerPixel != 8)
    {
    itkExceptionMacro(<< "Invalid bitsPerPixel " << bitsPerPixel);
    }

  std::string keywordStringBId = imageKeywordlist.GetMetadataByKey("support_data.band_id");
  std::string panchro("P");
  std::string multi("Multi");
  if (keywordStringBId != panchro && keywordStringBId != multi)
    {
    itkExceptionMacro(<< "Invalid bandID " << keywordStringBId);
    }

  std::string keywordStringTDILevel = imageKeywordlist.GetMetadataByKey("support_data.TDI_level");
  int         TDILevel = atoi(keywordStringTDILevel.c_str());
  if (keywordStringBId == panchro && TDILevel != 10 && TDILevel != 13 && TDILevel != 18 && TDILevel != 24 &&
      TDILevel != 32)
    {
    itkExceptionMacro(<< "Invalid TDILevel " << TDILevel);
    }

  VariableLengthVectorType outputValuesVariableLengthVector;
  if (keywordStringBId == panchro) outputValuesVariableLengthVector.SetSize(1);
  else outputValuesVariableLengthVector.SetSize(4);
  outputValuesVariableLengthVector.Fill(1.);

  if (!isPost20030606)
    {
    if (bitsPerPixel == 16)
      {
      if (keywordStringBId == panchro)
        {
        if (TDILevel != 10) outputValuesVariableLengthVector[0] = 0.08381880;
        else if (TDILevel != 13) outputValuesVariableLengthVector[0] = 0.06447600;
        else if (TDILevel != 18) outputValuesVariableLengthVector[0] = 0.04656600;
        else if (TDILevel != 24) outputValuesVariableLengthVector[0] = 0.03494440;
        else if (TDILevel != 32) outputValuesVariableLengthVector[0] = 0.02618840;
        }
      else
        {
        outputValuesVariableLengthVector[0] = 0.01604120;
        outputValuesVariableLengthVector[1] = 0.01438470;
        outputValuesVariableLengthVector[2] = 0.01267350;
        outputValuesVariableLengthVector[3] = 0.01542420;
        }

      }
    else
      {
      if (keywordStringBId == panchro)
        {
        if (TDILevel != 10) outputValuesVariableLengthVector[0] = 1.02681367;
        else if (TDILevel != 13) outputValuesVariableLengthVector[0] = 1.02848939;
        else if (TDILevel != 18) outputValuesVariableLengthVector[0] = 1.02794702;
        else if (TDILevel != 24) outputValuesVariableLengthVector[0] = 1.02989685;
        else if (TDILevel != 32) outputValuesVariableLengthVector[0] = 1.02739898;

        std::string keywordStringAbsCalFactor = imageKeywordlist.GetMetadataByKey("support_data.absCalFactor");
        double absCalFactor = atof(keywordStringAbsCalFactor.c_str());
        outputValuesVariableLengthVector[0] *= absCalFactor;
        }
      else
        {
        std::string keywordStringBCalFactor = imageKeywordlist.GetMetadataByKey("support_data.B_band_absCalFactor");
        double bCalFactor = atof(keywordStringBCalFactor.c_str());
        std::string keywordStringGCalFactor = imageKeywordlist.GetMetadataByKey("support_data.G_band_absCalFactor");
        double gCalFactor = atof(keywordStringGCalFactor.c_str());
        std::string keywordStringRCalFactor = imageKeywordlist.GetMetadataByKey("support_data.R_band_absCalFactor");
        double rCalFactor = atof(keywordStringRCalFactor.c_str());
        std::string keywordStringNCalFactor = imageKeywordlist.GetMetadataByKey("support_data.N_band_absCalFactor");
        double nCalFactor = atof(keywordStringNCalFactor.c_str());

        outputValuesVariableLengthVector[0] = 1.12097834 * bCalFactor;
        outputValuesVariableLengthVector[1] = 1.37652632 * gCalFactor;
        outputValuesVariableLengthVector[2] = 1.30954587 * rCalFactor;
        outputValuesVariableLengthVector[3] = 0.98368622 * nCalFactor;
        }
      }

    }
  else
    {
    if (keywordStringBId == panchro)
      {
      std::string keywordStringAbsCalFactor = imageKeywordlist.GetMetadataByKey("support_data.absCalFactor");
      double absCalFactor = atof(keywordStringAbsCalFactor.c_str());
      outputValuesVariableLengthVector[0] = absCalFactor;
      }
    else
      {
      std::string keywordStringBCalFactor = imageKeywordlist.GetMetadataByKey("support_data.B_band_absCalFactor");
      double bCalFactor = atof(keywordStringBCalFactor.c_str());
      std::string keywordStringGCalFactor = imageKeywordlist.GetMetadataByKey("support_data.G_band_absCalFactor");
      double gCalFactor = atof(keywordStringGCalFactor.c_str());
      std::string keywordStringRCalFactor = imageKeywordlist.GetMetadataByKey("support_data.R_band_absCalFactor");
      double rCalFactor = atof(keywordStringRCalFactor.c_str());
      std::string keywordStringNCalFactor = imageKeywordlist.GetMetadataByKey("support_data.N_band_absCalFactor");
      double nCalFactor = atof(keywordStringNCalFactor.c_str());

      outputValuesVariableLengthVector[0] = bCalFactor;
      outputValuesVariableLengthVector[1] = gCalFactor;
      outputValuesVariableLengthVector[2] = rCalFactor;
      outputValuesVariableLengthVector[3] = nCalFactor;
      }
    }

  if (keywordStringBId == panchro)
    {
    outputValuesVariableLengthVector[0] = 0.398 / outputValuesVariableLengthVector[0];
    }
  else
    {
    outputValuesVariableLengthVector[0] = 0.068 / outputValuesVariableLengthVector[0];
    outputValuesVariableLengthVector[1] = 0.099 / outputValuesVariableLengthVector[1];
    outputValuesVariableLengthVector[2] = 0.071 / outputValuesVariableLengthVector[2];
    outputValuesVariableLengthVector[3] = 0.114 / outputValuesVariableLengthVector[3];
    }

  return outputValuesVariableLengthVector;
}

double
QuickBirdImageMetadataInterface::GetSatElevation() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }
  std::string key("support_data.sat_elevation_angle");
  if (!imageKeywordlist.HasKey(key))
    {
    return -1;
    }

  std::string valueString = imageKeywordlist.GetMetadataByKey(key);
  double value = atof(valueString.c_str());
  return value;
}

double
QuickBirdImageMetadataInterface::GetSatAzimuth() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  std::string key("support_data.sat_azimuth_angle");
  if (!imageKeywordlist.HasKey(key))
    {
    return -1;
    }

  std::string valueString = imageKeywordlist.GetMetadataByKey(key);
  double value = atof(valueString.c_str());
  return value;
}

QuickBirdImageMetadataInterface::VariableLengthVectorType
QuickBirdImageMetadataInterface
::GetFirstWavelengths() const
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    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.);

  std::string keywordStringBId = imageKeywordlist.GetMetadataByKey("support_data.band_id");
  std::string panchro("P");
  std::string multi("Multi");
  if (keywordStringBId != panchro && keywordStringBId != multi)
    {
    itkExceptionMacro(<< "Invalid bandID " << keywordStringBId);
    }

  // Panchromatic case
  if (keywordStringBId == panchro)
    {
    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
{
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    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.);

  std::string keywordStringBId = imageKeywordlist.GetMetadataByKey("support_data.band_id");
  std::string panchro("P");
  std::string multi("Multi");
  if (keywordStringBId != panchro && keywordStringBId != multi)
    {
    itkExceptionMacro(<< "Invalid bandID " << keywordStringBId);
    }

  // Panchromatic case
  if (keywordStringBId == panchro)
    {
    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;
}

std::vector<unsigned int>
QuickBirdImageMetadataInterface
::GetDefaultDisplay() const
{
  std::vector<unsigned int> rgb(3);
  rgb[0] = 2;
  rgb[1] = 1;
  rgb[2] = 0;
  return rgb;
}

std::vector<std::string>
QuickBirdImageMetadataInterface
::GetEnhancedBandNames() const
{
  std::vector<std::string> enhBandNames;
  std::vector<std::string> rawBandNames = this->Superclass::GetBandName();

  //std::cout << rawBandNames.size() << std::endl;
  if(rawBandNames.size())
    {
    for (std::vector<std::string>::iterator it = rawBandNames.begin(); it != rawBandNames.end(); ++it)
      {
      //std::cout << *it << std::endl;

      // Manage Panchro case
      if ( (rawBandNames.size() == 1) && !(*it).compare("P") )
        {
        enhBandNames.push_back("PAN");
       break;
        }
      else if ((rawBandNames.size() != 1) && !(*it).compare("P"))
        {
        /* Launch exception situation not valid*/
        itkExceptionMacro(<< "Invalid Metadata, we cannot provide an consistent name to the band");
        }

      // Manage MS case
      if ( !(*it).compare("R") )
        {
        enhBandNames.push_back("Red");
        }
      else if ( !(*it).compare("G") )
        {
        enhBandNames.push_back("Green");
        }
      else if ( !(*it).compare("B") )
        {
        enhBandNames.push_back("Blue");
        }
      else if ( !(*it).compare("N") )
        {
        enhBandNames.push_back("NIR");
        }
      else
        {
        enhBandNames.push_back("Unknown");
        }
      }
    }

  return enhBandNames;

}

QuickBirdImageMetadataInterface::WavelengthSpectralBandVectorType
QuickBirdImageMetadataInterface
::GetSpectralSensitivity()  const
{
  WavelengthSpectralBandVectorType wavelengthSpectralBand = InternalWavelengthSpectralBandVectorType::New();

  std::list <std::vector<float> > tmpSpectralBandList;

  //Read sensor image type (panchromatic or multispectral)
  const MetaDataDictionaryType& dict = this->GetMetaDataDictionary();
  if (!this->CanRead())
    {
    itkExceptionMacro(<< "Invalid Metadata, no QuickBird Image");
    }

  ImageKeywordlistType imageKeywordlist;

  if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
    {
    itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
    }

  std::string keywordStringBId = imageKeywordlist.GetMetadataByKey("support_data.band_id");
  std::string panchro("P");
  std::string multi("Multi");

  if (keywordStringBId != panchro && keywordStringBId != multi)
    {
    itkExceptionMacro(<< "Invalid bandID " << keywordStringBId);
    }

  // Panchromatic case
  if (keywordStringBId == panchro)
    {
    const float b0[321] =
    {
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0007015f,   0.001403f,   0.001291f,   0.001179f,   0.0011415f,
     0.001104f,   0.00101145f,   0.0009189f,   0.00104845f,   0.001178f,   0.0016055f,
     0.002033f,   0.0044495f,   0.006866f,   0.008873f,   0.01088f,   0.013805f,
     0.01673f,   0.021325f,   0.02592f,   0.03106f,   0.0362f,   0.043415f,
     0.05063f,   0.05879f,   0.06695f,   0.075765f,   0.08458f,   0.09389f,
     0.1032f,   0.11255f,   0.1219f,   0.13345f,   0.145f,   0.1567f,
     0.1684f,   0.17895f,   0.1895f,   0.2011f,   0.2127f,   0.21625f,
     0.2198f,   0.2392f,   0.2586f,   0.26695f,   0.2753f,   0.2854f,
     0.2955f,   0.30545f,   0.3154f,   0.3259f,   0.3364f,   0.341f,
     0.3456f,   0.3501f,   0.3546f,   0.35785f,   0.3611f,   0.3648f,
     0.3685f,   0.3733f,   0.3781f,   0.3875f,   0.3969f,   0.4055f,
     0.4141f,   0.42755f,   0.441f,   0.4543f,   0.4676f,   0.4829f,
     0.4982f,   0.5167f,   0.5352f,   0.5532f,   0.5712f,   0.59245f,
     0.6137f,   0.6382f,   0.6627f,   0.6839f,   0.7051f,   0.7275f,
     0.7499f,   0.77045f,   0.791f,   0.81055f,   0.8301f,   0.8465f,
     0.8629f,   0.877f,   0.8911f,   0.9081f,   0.9251f,   0.9293f,
     0.9335f,   0.94265f,   0.9518f,   0.95695f,   0.9621f,   0.96095f,
     0.9598f,   0.97525f,   0.9907f,   0.9941f,   0.9975f,   0.9922f,
     0.9869f,   0.99345f,   1.0f,   0.9938f,   0.9876f,   0.9877f,
     0.9878f,   0.977f,   0.9662f,   0.95725f,   0.9483f,   0.934f,
     0.9197f,   0.919f,   0.9183f,   0.90635f,   0.8944f,   0.8912f,
     0.888f,   0.88305f,   0.8781f,   0.8865f,   0.8949f,   0.8921f,
     0.8893f,   0.8858f,   0.8823f,   0.88695f,   0.8916f,   0.8848f,
     0.878f,   0.8879f,   0.8978f,   0.8933f,   0.8888f,   0.8801f,
     0.8714f,   0.86905f,   0.8667f,   0.8677f,   0.8687f,   0.86995f,
     0.8712f,   0.86685f,   0.8625f,   0.87175f,   0.881f,   0.8814f,
     0.8818f,   0.8897f,   0.8976f,   0.9024f,   0.9072f,   0.91835f,
     0.9295f,   0.93105f,   0.9326f,   0.9198f,   0.907f,   0.91305f,
     0.9191f,   0.9173f,   0.9155f,   0.9097f,   0.9039f,   0.89875f,
     0.8936f,   0.88705f,   0.8805f,   0.8761f,   0.8717f,   0.8605f,
     0.8493f,   0.8475f,   0.8457f,   0.8505f,   0.8553f,   0.85675f,
     0.8582f,   0.85825f,   0.8583f,   0.8627f,   0.8671f,   0.8505f,
     0.8339f,   0.83895f,   0.844f,   0.847f,   0.85f,   0.85265f,
     0.8553f,   0.8447f,   0.8341f,   0.83675f,   0.8394f,   0.8235f,
     0.8076f,   0.8091f,   0.8106f,   0.785f,   0.7594f,   0.7616f,
     0.7638f,   0.749f,   0.7342f,   0.7204f,   0.7066f,   0.70035f,
     0.6941f,   0.67875f,   0.6634f,   0.65895f,   0.6545f,   0.63655f,
     0.6186f,   0.60945f,   0.6003f,   0.5961f,   0.5919f,   0.58315f,
     0.5744f,   0.55265f,   0.5309f,   0.5139f,   0.4969f,   0.48835f,
     0.4798f,   0.46305f,   0.4463f,   0.4305f,   0.4147f,   0.40975f,
     0.4048f,   0.3893f,   0.3738f,   0.3593f,   0.3448f,   0.3283f,
     0.3118f,   0.3035f,   0.2952f,   0.28405f,   0.2729f,   0.2648f,
     0.2567f,   0.24975f,   0.2428f,   0.2322f,   0.2216f,   0.21615f,
     0.2107f,   0.2039f,   0.1971f,   0.18735f,   0.1776f,   0.1703f,
     0.163f,   0.15575f,   0.1485f,   0.14215f,   0.1358f,   0.1299f,
     0.124f,   0.11625f,   0.1085f,   0.10197f,   0.09544f,   0.08927f,
     0.0831f,   0.077305f,   0.07151f,   0.06746f,   0.06341f,   0.05911f,
     0.05481f,   0.051195f,   0.04758f,   0.02882f,   0.01006f,   0.00503f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f
    };

    //add panchromatic band to the temporary list
    const std::vector<float> vb0 (b0, b0 + sizeof(b0) / sizeof(float) );
    tmpSpectralBandList.push_back(vb0);
    }
  else
    {
    const float b1[321] =
    {
     0.0f,   4.816e-11f,   9.632e-11f,   1.4606e-10f,   1.958e-10f,   2.4715e-10f,
     2.985e-10f,   3.514e-10f,   4.043e-10f,   0.000505f,   0.00101f,   0.0015305f,
     0.002051f,   0.002587f,   0.003123f,   0.0036745f,   0.004226f,   0.0043815f,
     0.004537f,   0.0049295f,   0.005322f,   0.0046895f,   0.004057f,   0.003661f,
     0.003265f,   0.002984f,   0.002703f,   0.002503f,   0.002303f,   0.0017815f,
     0.00126f,   0.0015305f,   0.001801f,   0.0020025f,   0.002204f,   0.0022995f,
     0.002395f,   0.0024735f,   0.002552f,   0.002512f,   0.002472f,   0.0026895f,
     0.002907f,   0.003455f,   0.004003f,   0.0052815f,   0.00656f,   0.00985f,
     0.01314f,   0.02076f,   0.02838f,   0.04826f,   0.06814f,   0.11167f,
     0.1552f,   0.2164f,   0.2776f,   0.35445f,   0.4313f,   0.5306f,
     0.6299f,   0.677f,   0.7241f,   0.75775f,   0.7914f,   0.81765f,
     0.8439f,   0.86675f,   0.8896f,   0.9037f,   0.9178f,   0.92355f,
     0.9293f,   0.94475f,   0.9602f,   0.9801f,   1.0f,   0.9958f,
     0.9916f,   0.95475f,   0.9179f,   0.84515f,   0.7724f,   0.6729f,
     0.5734f,   0.4787f,   0.384f,   0.32465f,   0.2653f,   0.21225f,
     0.1592f,   0.120415f,   0.08163f,   0.075435f,   0.06924f,   0.06627f,
     0.0633f,   0.055115f,   0.04693f,   0.03814f,   0.02935f,   0.023495f,
     0.01764f,   0.015185f,   0.01273f,   0.012595f,   0.01246f,   0.012675f,
     0.01289f,   0.012755f,   0.01262f,   0.011865f,   0.01111f,   0.0106f,
     0.01009f,   0.0098255f,   0.009561f,   0.0094225f,   0.009284f,   0.0095255f,
     0.009767f,   0.0102035f,   0.01064f,   0.010515f,   0.01039f,   0.0091415f,
     0.007893f,   0.006632f,   0.005371f,   0.004464f,   0.003557f,   0.0030945f,
     0.002632f,   0.0025675f,   0.002503f,   0.0024945f,   0.002486f,   0.0025155f,
     0.002545f,   0.002665f,   0.002785f,   0.0027235f,   0.002662f,   0.0027025f,
     0.002743f,   0.0030155f,   0.003288f,   0.003867f,   0.004446f,   0.006651f,
     0.008856f,   0.012518f,   0.01618f,   0.020175f,   0.02417f,   0.02563f,
     0.02709f,   0.02308f,   0.01907f,   0.0136865f,   0.008303f,   0.006957f,
     0.005611f,   0.0063045f,   0.006998f,   0.008584f,   0.01017f,   0.011135f,
     0.0121f,   0.0106205f,   0.009141f,   0.006401f,   0.003661f,   0.003178f,
     0.002695f,   0.002812f,   0.002929f,   0.0027945f,   0.00266f,   0.002858f,
     0.003056f,   0.0031515f,   0.003247f,   0.0034115f,   0.003576f,   0.003427f,
     0.003278f,   0.0034455f,   0.003613f,   0.0036285f,   0.003644f,   0.003367f,
     0.00309f,   0.003232f,   0.003374f,   0.003267f,   0.00316f,   0.0031495f,
     0.003139f,   0.003062f,   0.002985f,   0.003139f,   0.003293f,   0.0033135f,
     0.003334f,   0.00345f,   0.003566f,   0.003647f,   0.003728f,   0.003857f,
     0.003986f,   0.0040515f,   0.004117f,   0.004197f,   0.004277f,   0.004226f,
     0.004175f,   0.0045645f,   0.004954f,   0.0048685f,   0.004783f,   0.005318f,
     0.005853f,   0.005788f,   0.005723f,   0.00567f,   0.005617f,   0.00546f,
     0.005303f,   0.005252f,   0.005201f,   0.005183f,   0.005165f,   0.0051595f,
     0.005154f,   0.0052175f,   0.005281f,   0.00549f,   0.005699f,   0.0062505f,
     0.006802f,   0.007529f,   0.008256f,   0.0090055f,   0.009755f,   0.0101475f,
     0.01054f,   0.010745f,   0.01095f,   0.010137f,   0.009324f,   0.0084725f,
     0.007621f,   0.0068735f,   0.006126f,   0.0055815f,   0.005037f,   0.0046315f,
     0.004226f,   0.003881f,   0.003536f,   0.0032265f,   0.002917f,   0.002516f,
     0.002115f,   0.0019205f,   0.001726f,   0.001647f,   0.001568f,   0.0014765f,
     0.001385f,   0.001294f,   0.001203f,   0.001205f,   0.001207f,   0.0012145f,
     0.001222f,   0.0011705f,   0.001119f,   0.0011195f,   0.00112f,   0.001082f,
     0.001044f,   0.0010645f,   0.001085f,   0.001156f,   0.001227f,   0.001233f,
     0.001239f,   0.00135f,   0.001461f,   0.001648f,   0.001835f,   0.001667f,
     0.001499f,   0.001511f,   0.001523f,   0.0014645f,   0.001406f,   0.0013125f,
     0.001219f,   0.0006095f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0
    };

    const float b2[321] =
    {
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.001543f,   0.003086f,   0.0035565f,   0.004027f,   0.0031075f,
     0.002188f,   0.0022535f,   0.002319f,   0.001899f,   0.001479f,   0.0014535f,
     0.001428f,   0.00112715f,   0.0008263f,   0.00098315f,   0.00114f,   0.001191f,
     0.001242f,   0.0011965f,   0.001151f,   0.001195f,   0.001239f,   0.00119f,
     0.001141f,   0.001164f,   0.001187f,   0.001289f,   0.001391f,   0.0016425f,
     0.001894f,   0.0021145f,   0.002335f,   0.002574f,   0.002813f,   0.0032595f,
     0.003706f,   0.0046255f,   0.005545f,   0.0076825f,   0.00982f,   0.013835f,
     0.01785f,   0.02064f,   0.02343f,   0.026765f,   0.0301f,   0.03563f,
     0.04116f,   0.050415f,   0.05967f,   0.078915f,   0.09816f,   0.12738f,
     0.1566f,   0.1924f,   0.2282f,   0.2739f,   0.3196f,   0.36855f,
     0.4175f,   0.4726f,   0.5277f,   0.5928f,   0.6579f,   0.71385f,
     0.7698f,   0.8005f,   0.8312f,   0.83785f,   0.8445f,   0.8575f,
     0.8705f,   0.88935f,   0.9082f,   0.9271f,   0.946f,   0.96395f,
     0.9819f,   0.99095f,   1.0f,   0.9967f,   0.9934f,   0.9876f,
     0.9818f,   0.97545f,   0.9691f,   0.97325f,   0.9774f,   0.98215f,
     0.9869f,   0.97605f,   0.9652f,   0.93155f,   0.8979f,   0.84445f,
     0.791f,   0.72305f,   0.6551f,   0.56865f,   0.4822f,   0.3973f,
     0.3124f,   0.25785f,   0.2033f,   0.17055f,   0.1378f,   0.11394f,
     0.09008f,   0.072895f,   0.05571f,   0.046095f,   0.03648f,   0.032155f,
     0.02783f,   0.026995f,   0.02616f,   0.02677f,   0.02738f,   0.02745f,
     0.02752f,   0.02585f,   0.02418f,   0.02138f,   0.01858f,   0.016675f,
     0.01477f,   0.01398f,   0.01319f,   0.013215f,   0.01324f,   0.01321f,
     0.01318f,   0.01241f,   0.01164f,   0.0103975f,   0.009155f,   0.0076035f,
     0.006052f,   0.005198f,   0.004344f,   0.003775f,   0.003206f,   0.0030305f,
     0.002855f,   0.002863f,   0.002871f,   0.0034605f,   0.00405f,   0.0051125f,
     0.006175f,   0.006901f,   0.007627f,   0.007632f,   0.007637f,   0.006665f,
     0.005693f,   0.004709f,   0.003725f,   0.003184f,   0.002643f,   0.002404f,
     0.002165f,   0.002389f,   0.002613f,   0.0028265f,   0.00304f,   0.0029335f,
     0.002827f,   0.0029585f,   0.00309f,   0.003231f,   0.003372f,   0.0036625f,
     0.003953f,   0.003888f,   0.003823f,   0.004107f,   0.004391f,   0.004264f,
     0.004137f,   0.003973f,   0.003809f,   0.003648f,   0.003487f,   0.003354f,
     0.003221f,   0.0031325f,   0.003044f,   0.0030325f,   0.003021f,   0.0030705f,
     0.00312f,   0.0031665f,   0.003213f,   0.0032575f,   0.003302f,   0.0035005f,
     0.003699f,   0.0040635f,   0.004428f,   0.004754f,   0.00508f,   0.0059895f,
     0.006899f,   0.0073485f,   0.007798f,   0.008437f,   0.009076f,   0.0091385f,
     0.009201f,   0.0091225f,   0.009044f,   0.0088315f,   0.008619f,   0.0082995f,
     0.00798f,   0.00779f,   0.0076f,   0.007548f,   0.007496f,   0.007548f,
     0.0076f,   0.007711f,   0.007822f,   0.0079615f,   0.008101f,   0.008127f,
     0.008153f,   0.007961f,   0.007769f,   0.007238f,   0.006707f,   0.0061495f,
     0.005592f,   0.005117f,   0.004642f,   0.0042505f,   0.003859f,   0.0034755f,
     0.003092f,   0.00288f,   0.002668f,   0.0023465f,   0.002025f,   0.0018485f,
     0.001672f,   0.001577f,   0.001482f,   0.001362f,   0.001242f,   0.001247f,
     0.001252f,   0.001152f,   0.001052f,   0.00099725f,   0.0009425f,   0.0009543f,
     0.0009661f,   0.00091635f,   0.0008666f,   0.0008281f,   0.0007896f,   0.00083065f,
     0.0008717f,   0.00088005f,   0.0008884f,   0.00092515f,   0.0009619f,   0.00103995f,
     0.001118f,   0.001196f,   0.001274f,   0.0011625f,   0.001051f,   0.0010565f,
     0.001062f,   0.00096085f,   0.0008597f,   0.00091815f,   0.0009766f,   0.0009189f,
     0.0008612f,   0.0004306f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,
    };

    const float b3[321] =
    {
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0018575f,   0.003715f,   0.003079f,   0.002443f,   0.0020455f,
     0.001648f,   0.0017865f,   0.001925f,   0.001553f,   0.001181f,   0.001127f,
     0.001073f,   0.0009881f,   0.0009032f,   0.00093675f,   0.0009703f,   0.00094635f,
     0.0009224f,   0.0011177f,   0.001313f,   0.000995f,   0.000677f,   0.0009465f,
     0.001216f,   0.0012365f,   0.001257f,   0.001289f,   0.001321f,   0.0012365f,
     0.001152f,   0.00107375f,   0.0009955f,   0.00125725f,   0.001519f,   0.001803f,
     0.002087f,   0.002445f,   0.002803f,   0.0029485f,   0.003094f,   0.002991f,
     0.002888f,   0.0028545f,   0.002821f,   0.002901f,   0.002981f,   0.0032205f,
     0.00346f,   0.003574f,   0.003688f,   0.003422f,   0.003156f,   0.0026165f,
     0.002077f,   0.002126f,   0.002175f,   0.0022785f,   0.002382f,   0.002534f,
     0.002686f,   0.0028785f,   0.003071f,   0.003181f,   0.003291f,   0.0033965f,
     0.003502f,   0.003615f,   0.003728f,   0.004149f,   0.00457f,   0.00494f,
     0.00531f,   0.00563f,   0.00595f,   0.0061365f,   0.006323f,   0.006458f,
     0.006593f,   0.0067545f,   0.006916f,   0.007343f,   0.00777f,   0.008377f,
     0.008984f,   0.009607f,   0.01023f,   0.01101f,   0.01179f,   0.01283f,
     0.01387f,   0.015775f,   0.01768f,   0.020725f,   0.02377f,   0.028595f,
     0.03342f,   0.03993f,   0.04644f,   0.054755f,   0.06307f,   0.07513f,
     0.08719f,   0.107645f,   0.1281f,   0.16655f,   0.205f,   0.26755f,
     0.3301f,   0.41305f,   0.496f,   0.579f,   0.662f,   0.7337f,
     0.8054f,   0.8447f,   0.884f,   0.8976f,   0.9112f,   0.9265f,
     0.9418f,   0.9608f,   0.9798f,   0.9878f,   0.9958f,   0.9979f,
     1.0f,   0.99615f,   0.9923f,   0.97235f,   0.9524f,   0.9125f,
     0.8726f,   0.8128f,   0.753f,   0.6767f,   0.6004f,   0.51195f,
     0.4235f,   0.35205f,   0.2806f,   0.22285f,   0.1651f,   0.130405f,
     0.09571f,   0.07443f,   0.05315f,   0.041695f,   0.03024f,   0.026095f,
     0.02195f,   0.021015f,   0.02008f,   0.020405f,   0.02073f,   0.021105f,
     0.02148f,   0.02055f,   0.01962f,   0.01719f,   0.01476f,   0.0121415f,
     0.009523f,   0.0080775f,   0.006632f,   0.0058285f,   0.005025f,   0.004769f,
     0.004513f,   0.004338f,   0.004163f,   0.004345f,   0.004527f,   0.0047955f,
     0.005064f,   0.005541f,   0.006018f,   0.0063415f,   0.006665f,   0.006433f,
     0.006201f,   0.005328f,   0.004455f,   0.003759f,   0.003063f,   0.002884f,
     0.002705f,   0.00257f,   0.002435f,   0.002453f,   0.002471f,   0.0024775f,
     0.002484f,   0.0024255f,   0.002367f,   0.0024915f,   0.002616f,   0.00253f,
     0.002444f,   0.002528f,   0.002612f,   0.0025575f,   0.002503f,   0.00255f,
     0.002597f,   0.002551f,   0.002505f,   0.002426f,   0.002347f,   0.0023605f,
     0.002374f,   0.0022935f,   0.002213f,   0.002167f,   0.002121f,   0.002053f,
     0.001985f,   0.001928f,   0.001871f,   0.00194f,   0.002009f,   0.002071f,
     0.002133f,   0.002293f,   0.002453f,   0.0026255f,   0.002798f,   0.0027925f,
     0.002787f,   0.002651f,   0.002515f,   0.0020235f,   0.001532f,   0.001344f,
     0.001156f,   0.001118f,   0.00108f,   0.0010297f,   0.0009794f,   0.0009771f,
     0.0009748f,   0.0010049f,   0.001035f,   0.00092405f,   0.0008131f,   0.00082065f,
     0.0008282f,   0.0007723f,   0.0007164f,   0.00070735f,   0.0006983f,   0.00070225f,
     0.0007062f,   0.0006895f,   0.0006728f,   0.0006287f,   0.0005846f,   0.0006068f,
     0.000629f,   0.00065395f,   0.0006789f,   0.00071925f,   0.0007596f,   0.000719f,
     0.0006784f,   0.00066125f,   0.0006441f,   0.0007476f,   0.0008511f,   0.0008908f,
     0.0009305f,   0.0008436f,   0.0007567f,   0.0007948f,   0.0008329f,   0.000872f,
     0.0009111f,   0.00089545f,   0.0008798f,   0.0007618f,   0.0006438f,   0.00073805f,
     0.0008323f,   0.00041615f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f
    };

    const float b4[321] =
    {
     0.0f,   6.72e-11f,   1.344e-10f,   2.038e-10f,   2.732e-10f,   3.4475e-10f,
     4.163e-10f,   4.901e-10f,   5.639e-10f,   0.0007045f,   0.001409f,   0.002135f,
     0.002861f,   0.0036085f,   0.004356f,   0.0051255f,   0.005895f,   0.006112f,
     0.006329f,   0.0061655f,   0.006002f,   0.005693f,   0.005384f,   0.0044505f,
     0.003517f,   0.0028125f,   0.002108f,   0.002272f,   0.002436f,   0.002068f,
     0.0017f,   0.0019855f,   0.002271f,   0.0020705f,   0.00187f,   0.0017455f,
     0.001621f,   0.0017855f,   0.00195f,   0.0018905f,   0.001831f,   0.0016705f,
     0.00151f,   0.0015045f,   0.001499f,   0.001721f,   0.001943f,   0.0018305f,
     0.001718f,   0.002082f,   0.002446f,   0.002492f,   0.002538f,   0.002833f,
     0.003128f,   0.003589f,   0.00405f,   0.0043915f,   0.004733f,   0.0047405f,
     0.004748f,   0.004824f,   0.0049f,   0.004541f,   0.004182f,   0.004313f,
     0.004444f,   0.0046115f,   0.004779f,   0.005007f,   0.005235f,   0.005396f,
     0.005557f,   0.0054025f,   0.005248f,   0.0047195f,   0.004191f,   0.0035905f,
     0.00299f,   0.0028175f,   0.002645f,   0.0026115f,   0.002578f,   0.002558f,
     0.002538f,   0.0027f,   0.002862f,   0.002721f,   0.00258f,   0.002973f,
     0.003366f,   0.004324f,   0.005282f,   0.006576f,   0.00787f,   0.008871f,
     0.009872f,   0.010051f,   0.01023f,   0.0090465f,   0.007863f,   0.006367f,
     0.004871f,   0.0048565f,   0.004842f,   0.0055935f,   0.006345f,   0.0069985f,
     0.007652f,   0.0077885f,   0.007925f,   0.007197f,   0.006469f,   0.0054185f,
     0.004368f,   0.004082f,   0.003796f,   0.003768f,   0.00374f,   0.0036695f,
     0.003599f,   0.0036165f,   0.003634f,   0.0037785f,   0.003923f,   0.0042145f,
     0.004506f,   0.004688f,   0.00487f,   0.0052705f,   0.005671f,   0.005878f,
     0.006085f,   0.006441f,   0.006797f,   0.007044f,   0.007291f,   0.007926f,
     0.008561f,   0.0092905f,   0.01002f,   0.010625f,   0.01123f,   0.01174f,
     0.01225f,   0.012595f,   0.01294f,   0.01323f,   0.01352f,   0.01396f,
     0.0144f,   0.01499f,   0.01558f,   0.01641f,   0.01724f,   0.01842f,
     0.0196f,   0.021835f,   0.02407f,   0.026755f,   0.02944f,   0.03189f,
     0.03434f,   0.03751f,   0.04068f,   0.04483f,   0.04898f,   0.05445f,
     0.05992f,   0.066405f,   0.07289f,   0.081705f,   0.09052f,   0.10501f,
     0.1195f,   0.141f,   0.1625f,   0.20245f,   0.2424f,   0.3015f,
     0.3606f,   0.4268f,   0.493f,   0.564f,   0.635f,   0.71665f,
     0.7983f,   0.8726f,   0.9469f,   0.97345f,   1.0f,   0.99855f,
     0.9971f,   0.98365f,   0.9702f,   0.9526f,   0.935f,   0.91795f,
     0.9009f,   0.88535f,   0.8698f,   0.86065f,   0.8515f,   0.84485f,
     0.8382f,   0.8352f,   0.8322f,   0.8289f,   0.8256f,   0.823f,
     0.8204f,   0.8137f,   0.807f,   0.7957f,   0.7844f,   0.76695f,
     0.7495f,   0.72675f,   0.704f,   0.6911f,   0.6782f,   0.6638f,
     0.6494f,   0.6313f,   0.6132f,   0.59005f,   0.5669f,   0.5493f,
     0.5317f,   0.5117f,   0.4917f,   0.4644f,   0.4371f,   0.3943f,
     0.3515f,   0.3134f,   0.2753f,   0.24845f,   0.2216f,   0.191f,
     0.1604f,   0.1385f,   0.1166f,   0.1003f,   0.084f,   0.07559f,
     0.06718f,   0.054015f,   0.04085f,   0.030665f,   0.02048f,   0.017005f,
     0.01353f,   0.01178f,   0.01003f,   0.0089005f,   0.007771f,   0.007077f,
     0.006383f,   0.0058745f,   0.005366f,   0.0049605f,   0.004555f,   0.0040195f,
     0.003484f,   0.0031455f,   0.002807f,   0.002621f,   0.002435f,   0.0023315f,
     0.002228f,   0.002158f,   0.002088f,   0.001973f,   0.001858f,   0.001839f,
     0.00182f,   0.0018615f,   0.001903f,   0.001759f,   0.001615f,   0.0016735f,
     0.001732f,   0.0017285f,   0.001725f,   0.001884f,   0.002043f,   0.0020925f,
     0.002142f,   0.0020825f,   0.002023f,   0.001963f,   0.001903f,   0.0018045f,
     0.001706f,   0.0017565f,   0.001807f,   0.0017525f,   0.001698f,   0.001849f,
     0.002f,   0.001f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,
     0.0f,   0.0f,   0.0f
    };
    //Add multispectral bands to the temporary list
    const std::vector<float> vb1 (b1, b1 + sizeof(b1) / sizeof(float) );
    tmpSpectralBandList.push_back(vb1);
    const std::vector<float> vb2 (b2, b2 + sizeof(b2) / sizeof(float) );
    tmpSpectralBandList.push_back(vb2);
    const std::vector<float> vb3 (b3, b3 + sizeof(b3) / sizeof(float) );
    tmpSpectralBandList.push_back(vb3);
    const std::vector<float> vb4 (b4, b4 + sizeof(b4) / sizeof(float) );
    tmpSpectralBandList.push_back(vb4);
    }

  unsigned int j = 0;
  for (std::list <std::vector<float> >::const_iterator it = tmpSpectralBandList.begin(); it != tmpSpectralBandList.end(); ++it)
    {
    wavelengthSpectralBand->PushBack(FilterFunctionValues::New());
    wavelengthSpectralBand->GetNthElement(j)->SetFilterFunctionValues(*it);
    wavelengthSpectralBand->GetNthElement(j)->SetMinSpectralValue(0.300);
    wavelengthSpectralBand->GetNthElement(j)->SetMaxSpectralValue(1.1);
    wavelengthSpectralBand->GetNthElement(j)->SetUserStep(0.0025);
    ++j;
    }

  return wavelengthSpectralBand;
}

} // end namespace otb
