Commit a9f7d27e authored by Jeannie Backer's avatar Jeannie Backer
Browse files

pds4 updates.

parent e275807d
Loading
Loading
Loading
Loading
+248 −38
Original line number Diff line number Diff line
@@ -24,8 +24,10 @@

#include <QDomDocument>
#include <QMap>
#include <QRegularExpression>
#include <QString>

#include "Application.h"
#include "FileName.h"
#include "IException.h"
#include "Projection.h"
@@ -43,6 +45,9 @@ namespace Isis {
   *
   */
  ProcessExportPds4::ProcessExportPds4() {

    m_lid = "";

    qSetGlobalQHashSeed(1031); // hash seed to force consistent output

    m_domDoc = new QDomDocument("");
@@ -104,19 +109,28 @@ namespace Isis {


  /**
   * Create a standard PDS label for type IMAGE. The image label will be
   * Creates a PDS4 label. The image label will be
   * stored internally in the class. 
   *  
   * This method has a similar function to 
   * ProcessExportPds::CreateImageLabel. However, it will create 
   * images of object type Array_3D_Image, Array_2D_Image, or 
   * Array_3D_Spectrum. 
   */
  void ProcessExportPds4::CreateImageLabel() {
  void ProcessExportPds4::CreateImageLabel() {//??? todo - should we bother to match parent class name???

    try {
      // <Product_Observational>
      //   <Identification_Area>
      identificationArea();
    }
    catch (IException &e) {
      QString msg = "Unable to translate and export identification information.";
      throw IException(e, IException::Programmer, msg, _FILEINFO_);
    }
    try {
    try {//ONLY DO THIS IF NOT MOSAIC??? how do pep3 do it???
      // <Product_Observational>
      //   <Observation_Area>
      standardInstrument();
    }
    catch (IException &e) {
@@ -124,25 +138,34 @@ namespace Isis {
      throw IException(e, IException::Programmer, msg, _FILEINFO_);
    }
    try {
      // <Product_Observational>
      //   <Observation_Area>
      //     <Discipline_Area>
      //       <disp:Display_Settings>
      displaySettings();
    }
    catch (IException &e) {
      QString msg = "Unable to translate and export display settings.";
      throw IException(e, IException::Programmer, msg, _FILEINFO_);
    }
// Temporarily removed spectral processing because it needs further work. 
// 
//    try {
//      standardBandBin();
//    } 
//    catch (IException &e) {
//      QString msg = "Unable to translate and export spectral information.";
//      throw IException(e, IException::Programmer, msg, _FILEINFO_);
//    }

    try {
      // <Product_Observational>
      //   <Observation_Area>
      //     <Discipline_Area>
      // display settings, and cartography handled in this method:
      //       <sp:Spectral_Characteristics> OR <img:Imaging>
      standardBandBin();
    } 
    catch (IException &e) {
      QString msg = "Unable to translate and export spectral information.";
      throw IException(e, IException::Programmer, msg, _FILEINFO_);
    }

    try { 
      // <Product_Observational>
      //   <Observation_Area>
      //     <Discipline_Area>
      //       <card:Cartography>
      StandardAllMapping();
    }
    catch (IException &e) {
@@ -150,8 +173,9 @@ namespace Isis {
      throw IException(e, IException::Programmer, msg, _FILEINFO_);
    }
    try {
      // file observation area
      StandardImageImage();
      // <Product_Observational>
      //   <File_Area_Observational>
      fileAreaObservational();
    }
    catch (IException &e) {
      QString msg = "Unable to translate and export standard image information.";
@@ -166,11 +190,11 @@ namespace Isis {
   */
  void ProcessExportPds4::standardInstrument() {
    Pvl *inputLabel = InputCubes[0]->label(); 
    FileName transfile;
    FileName translationFileName;

    // Translate the Instrument group
    transfile = "$base/translations/pds4ExportInstrument.trn";
    PvlToXmlTranslationManager instXlator(*inputLabel, transfile.expanded());
    translationFileName = "$base/translations/pds4ExportInstrument.trn";
    PvlToXmlTranslationManager instXlator(*inputLabel, translationFileName.expanded());
    instXlator.Auto(*m_domDoc);

    // If instrument and spacecraft values were translated, create the combined name
@@ -233,14 +257,14 @@ namespace Isis {

    // Translate the Target name
    try {
      transfile = "$base/translations/pds4ExportTargetFromInstrument.trn"; 
      PvlToXmlTranslationManager targXlator(*inputLabel, transfile.expanded());
      translationFileName = "$base/translations/pds4ExportTargetFromInstrument.trn"; 
      PvlToXmlTranslationManager targXlator(*inputLabel, translationFileName.expanded());
      targXlator.Auto(*m_domDoc);
    } 
    catch (IException &e1) {
      try {
        transfile = "$base/translations/pds4ExportTargetFromMapping.trn"; 
        PvlToXmlTranslationManager targXlator(*inputLabel, transfile.expanded());
        translationFileName = "$base/translations/pds4ExportTargetFromMapping.trn"; 
        PvlToXmlTranslationManager targXlator(*inputLabel, translationFileName.expanded());
        targXlator.Auto(*m_domDoc);
      }
      catch (IException &e2) {
@@ -253,16 +277,96 @@ namespace Isis {
  }


  /**
   * Allows mission specific programs to set logical_identifier 
   * required for PDS4 labels. This value is added to the xml file 
   * by the identificationArea() method. 
   *  
   * The input string should be colon separated string with 6 
   * identifiers: 
   *  
   * <ol> 
   *   <li> urn </li>
   *   <li> space_agency (ususally nasa) </li>
   *   <li> archiving_organization (usually pds) </li>
   *   <li> bundle_id </li>
   *   <li> collection_id </li>
   *   <li> product_id </li>
   * </ol> 
   *  
   * Example: 
   * urn:esa:psa:em16_tgo_frd:data_raw:frd_raw_sc_d_20150625T133700-20150625T135700 
   * 
   * @author 2018-05-21 Jeannie Backer
   * 
   * @param lid The logical identifier value required for PDS4 
   *            compliant labels.
   */
  void ProcessExportPds4::setLogicalId(QString lid) {
    m_lid = lid;
  }


  /**
   * Allows mission specific programs to use specified 
   * versions of dictionaries. 
   * 
   * @author 2018-05-21 Jeannie Backer
   *  
   * @param schema The string of schema to be set.
   */
  void ProcessExportPds4::setSchemaLocation(QString schema) {
    m_schemaLocation = schema;
  }


  /**
   * This method writes the identification information to the PDS4
   * labels. 
   */
  void ProcessExportPds4::identificationArea() {
    Pvl *inputLabel = InputCubes[0]->label(); 
    FileName transfile;
    transfile = "$base/translations/pds4ExportIdentificationArea.trn";
    PvlToXmlTranslationManager xlator(*inputLabel, transfile.expanded());
    FileName translationFileName;
    translationFileName = "$base/translations/pds4ExportIdentificationArea.trn";
    PvlToXmlTranslationManager xlator(*inputLabel, translationFileName.expanded());
    xlator.Auto(*m_domDoc);

    if (!m_lid.isEmpty()) {
      QDomElement identificationElement;
      QStringList identificationPath;
      identificationPath.append("Product_Observational");
      identificationPath.append("Identification_Area");
      try {
        identificationElement = getElement(identificationPath);
        if( identificationElement.isNull() ) {
          throw IException(IException::Unknown, "", _FILEINFO_);
        }
      }
      catch(IException &e) {
        QString msg = "Could not find Identification_Area element "
                      "to add modification history under.";
        throw IException(IException::Programmer, msg, _FILEINFO_);
      }

      // Check if the "Modification_History" element exists yet.
      // If not, create one.
      QDomElement lidElement = identificationElement.firstChildElement("logical_identifier");
      PvlToXmlTranslationManager::resetElementValue(lidElement, m_lid);



    }
    // This regular expression matches the pipe followed by the date from
    // the ISIS version string that Application returns.
    QRegularExpression versionRegex(" \\| \\d{4}\\-\\d{2}\\-\\d{2}");
    QString historyDescription = "Created PDS4 output product from ISIS cube with tgocassisrdrgen "
                                 "application from ISIS version "
                                 + Application::Version().remove(versionRegex) + ".";
    // This regular expression matches the time from the date and time string
    // that Application returns.
    QRegularExpression dateRegex("T\\d{2}:\\d{2}:\\d{2}");
    QString historyDate = Application::DateTime().remove(dateRegex);
    addHistory(historyDescription, historyDate);// ??? should above be in process.addHistory???
  }

  
@@ -273,9 +377,9 @@ namespace Isis {
  void ProcessExportPds4::displaySettings() {

    Pvl *inputLabel = InputCubes[0]->label(); 
    FileName transfile;
    transfile = "$base/translations/pds4ExportDisplaySettings.trn";
    PvlToXmlTranslationManager xlator(*inputLabel, transfile.expanded());
    FileName translationFileName;
    translationFileName = "$base/translations/pds4ExportDisplaySettings.trn";
    PvlToXmlTranslationManager xlator(*inputLabel, translationFileName.expanded());
    xlator.Auto(*m_domDoc);

    // Add header info
@@ -294,12 +398,14 @@ namespace Isis {
    // Spectra
    // Get the input Isis cube label and find the BandBin group if it has one
    Pvl *inputLabel = InputCubes[0]->label();
    if(inputLabel->hasObject("IsisCube") &&
        !(inputLabel->findObject("IsisCube").hasGroup("BandBin"))) return;
    QString imageObject = imageObjectType(*inputLabel);

    FileName transfile;
    transfile = "$base/translations/pds4ExportBandBin.trn";
    PvlToXmlTranslationManager xlator(*inputLabel, transfile.expanded());
    QString translationFile = "$base/translations/pds4ExportBandBin";
    translationFile += imageObject.remove(0,9); // remove first 9 characters: Array_2D_ or Array_3D_
    translationFile += ".trn";
    FileName translationFileName(translationFile);

    PvlToXmlTranslationManager xlator(*inputLabel, translationFileName.expanded());
    xlator.Auto(*m_domDoc);

    // Add header info
@@ -316,10 +422,10 @@ namespace Isis {
   */
  void ProcessExportPds4::StandardImageImage() {
    Pvl *inputLabel = InputCubes[0]->label(); 
    FileName transfile;
    FileName translationFileName;

    transfile = "$base/translations/pds4ExportArray3DImage.trn"; 
    PvlToXmlTranslationManager xlator(*inputLabel, transfile.expanded());
    translationFileName = "$base/translations/pds4ExportArray3DImage.trn"; 
    PvlToXmlTranslationManager xlator(*inputLabel, translationFileName.expanded());
    xlator.Auto(*m_domDoc);

    QDomElement rootElement = m_domDoc->documentElement();
@@ -389,6 +495,110 @@ namespace Isis {
  }


  /**
   * Create and internalize an image output label from the input 
   * image. This method has a similar function to 
   * ProcessExportPds::StandardImageImage. 
   */
  void ProcessExportPds4::fileAreaObservational() {
    Pvl *inputLabel = InputCubes[0]->label(); 
    QString imageObject = imageObjectType(*inputLabel);

    QString translationFile = "$base/translations/pds4Export";
    translationFile += imageObject.remove('_');
    translationFile += ".trn";
    FileName translationFileName(translationFile);

    PvlToXmlTranslationManager xlator(*inputLabel, translationFileName.expanded());
    xlator.Auto(*m_domDoc);

    QDomElement rootElement = m_domDoc->documentElement();
    QDomElement fileAreaObservationalElement =
                    rootElement.firstChildElement("File_Area_Observational");

    // Calculate the core base/mult for the output cube
    double base = 0.0;
    double multiplier = 1.0;
    double outputMin, outputMax;

    double inputMin = (p_inputMinimum.size()) ? p_inputMinimum[0] : 0.0;
    double inputMax = (p_inputMaximum.size()) ? p_inputMaximum[0] : 0.0;

    for(unsigned int i = 0; i < p_inputMinimum.size(); i ++) {
      inputMin = std::min(inputMin, p_inputMinimum[i]);
      inputMax = std::max(inputMax, p_inputMaximum[i]);
    }

    outputMin = p_outputMinimum;
    outputMax = p_outputMaximum;

    if(p_inputMinimum.size() && ( p_pixelType == Isis::UnsignedByte ||
                                  p_pixelType == Isis::SignedWord   ||
                                  p_pixelType == Isis::UnsignedWord ) ) {
      multiplier = (inputMax - inputMin) / (outputMax - outputMin);
      base = inputMin - multiplier * outputMin;
    }

    if (!fileAreaObservationalElement.isNull()) {
      QDomElement array3DImageElement =
                      fileAreaObservationalElement.firstChildElement(imageObject);

      if (!array3DImageElement.isNull()) {

        // reorder axis elements. 
        // Translation order:  elements, axis_name, sequence_number
        // Correct order:      axis_name, elements, sequence_number
        QDomElement axisArrayElement = array3DImageElement.firstChildElement("Axis_Array");
        while( !axisArrayElement.isNull() ) {
          QDomElement axisNameElement = axisArrayElement.firstChildElement("axis_name");
          axisArrayElement.insertBefore(axisNameElement, 
                                        axisArrayElement.firstChildElement("elements"));
          axisArrayElement = axisArrayElement.nextSiblingElement("Axis_Array");
        }

        QDomElement elementArrayElement = m_domDoc->createElement("Element_Array");
        array3DImageElement.insertBefore(elementArrayElement,
                                         array3DImageElement.firstChildElement("Axis_Array"));

        QDomElement dataTypeElement = m_domDoc->createElement("data_type");
        PvlToXmlTranslationManager::setElementValue(dataTypeElement,
                                                    PDS4PixelType(p_pixelType, p_endianType));
        elementArrayElement.appendChild(dataTypeElement);

        QDomElement scalingFactorElement = m_domDoc->createElement("scaling_factor");
        PvlToXmlTranslationManager::setElementValue(scalingFactorElement,
                                                    toString(multiplier));
        elementArrayElement.appendChild(scalingFactorElement);

        QDomElement offsetElement = m_domDoc->createElement("value_offset");
        PvlToXmlTranslationManager::setElementValue(offsetElement,
                                                    toString(base));
        elementArrayElement.appendChild(offsetElement);
      }
    }
  }


  QString ProcessExportPds4::imageObjectType(Pvl &inputLabel) {
    // not sure how to easily determine whether an isis3 cube should be 
    // exported as spectral. for now, we will only export image arrays
    #if 0
    if (inputLabel.findObject("IsisCube").hasGroup("BandBin")) {
      return "Array_3D_Spectrum";
    }
    #endif

    int bands = (int) inputLabel.findObject("IsisCube")
                                .findObject("Core")
                                .findGroup("Dimensions")
                                .findKeyword("Bands");
    if (bands > 1) {
      return "Array_3D_Image";
    }
    return "Array_2D_Image";
  }


  /**
   * Adds necessary information to the xml header for a pds4 class. 
   * 
+7 −2
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ namespace Isis {
      void WritePds4(QString outFile);
      QDomElement getElement(QStringList xmlPath, QDomElement parent=QDomElement());
      void addHistory(QString description, QString date = "tbd", QString version = "1.0");
      void setLogicalId(QString lid);
      void setSchemaLocation(QString schema);

      static void translateUnits(QDomDocument &label,
                                 QString transMapFile = "$base/translations/pds4ExportUnits.pvl");
@@ -103,12 +105,15 @@ namespace Isis {
      void standardInstrument();
      void standardBandBin(); 
      void displaySettings();
      void fileAreaObservational();
      QString imageObjectType(Pvl &inputLabel);
      QString PDS4PixelType(PixelType pixelType, ByteOrder endianType);
      static QMap<QString, QString> createUnitMap(Pvl configPvl);
      static void translateChildUnits(QDomElement parent, QMap<QString, QString> transMap);

      QDomDocument *m_domDoc;               //!< XML label
      QString m_schemaLocation;             //!< QString with all schema locations required
      QDomDocument *m_domDoc;               //!< XML label.
      QString m_schemaLocation;             //!< QString with all schema locations required.
      QString m_lid;                        //!< QString with specified logical identifier.

  };
}
+5 −20
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ void IsisMain() {
  Cube *icube = process.SetInputCube("FROM");

  PvlObject *label= icube->label();
  PvlKeyword &instrument = label->findObject("IsisCube").findGroup("Instrument").findKeyword("InstrumentId");
  PvlKeyword &instrument = label->findObject("IsisCube").findKeyword("InstrumentId", Pvl::Traverse);

  // Check if the cube is able to be translated into a CaSSIS xml file
  // This could very well be unnecessary
@@ -43,29 +43,14 @@ void IsisMain() {
    throw  IException(IException::User, msg, _FILEINFO_);
  }

/*
  * Add additional pds label data here
  */

  // std PDS4 label
  process.StandardPds4Label();
  // Add additional cassis label data here
  QDomDocument &pdsLabel = process.GetLabel();
  PvlToXmlTranslationManager cubeLab(*(icube->label()),
                                    "$tgo/translations/tgoCassisExport.trn");
  cubeLab.Auto(pdsLabel);

  process.StandardPds4Label();

  // This regular expression matches the pipe followed by the date from
  // the ISIS version string that Application returns.
  QRegularExpression versionRegex(" \\| \\d{4}\\-\\d{2}\\-\\d{2}");
  QString historyDescription = "Created PDS4 output product from ISIS cube with tgocassisrdrgen "
                               "application from ISIS version "
                               + Application::Version().remove(versionRegex) + ".";
  // This regular expression matches the time from the date and time string
  // that Application returns.
  QRegularExpression dateRegex("T\\d{2}:\\d{2}:\\d{2}");
  QString historyDate = Application::DateTime().remove(dateRegex);
  process.addHistory(historyDescription, historyDate);

  ProcessExportPds4::translateUnits(pdsLabel);
  
  QString outFile = ui.GetFileName("TO");