Commit 413e6191 authored by Ian Humphrey's avatar Ian Humphrey
Browse files

Merged revision 6769 from IPCE into trunk.

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/trunk@6782 41f8697f-d340-4b68-9986-7bafba869bb8
parent ebf6c1b4
Loading
Loading
Loading
Loading
+68 −44
Original line number Diff line number Diff line
#include "ObservationNumberList.h"
#include "IException.h"

#include "FileName.h"
#include "SerialNumberList.h"
#include "IString.h"
#include "IException.h"
#include "Pvl.h"
#include "SerialNumberList.h"

using namespace std;
namespace Isis {

  /**
   * Creates an ObservationNumberList from a filename
   *
@@ -20,30 +22,34 @@ namespace Isis {
    init(this);
  }


  /**
   * Creates an ObservationNumberList from a SerialNumberList
   *
   * @param snlist The serial number list from which to generate an observation number list
   */
  ObservationNumberList::ObservationNumberList(Isis::SerialNumberList *snlist) :
  ObservationNumberList::ObservationNumberList(SerialNumberList *snlist) :
      SerialNumberList(*snlist) {
    init(snlist);
  }


  /**
   * Initiates the ObservationNumberList
   *
   * @param snlist The already created SerialNumberList used to
   *               create the ObservationNumberList object
   *
   * @throws IException::User "Serial numberList is empty"
   */
  void ObservationNumberList::init(Isis::SerialNumberList *snlist) {
  void ObservationNumberList::init(SerialNumberList *snlist) {

    if (snlist->size() == 0) {
      QString msg = "Serial number list is empty";
      throw IException(IException::User, msg, _FILEINFO_);
    }

    std::map<QString, int> observationMap;
    map<QString, int> observationMap;
    QString observationNumber;
    int currentIndex = 0;
    int observationIndex;
@@ -53,7 +59,7 @@ namespace Isis {
      observationNumber = snlist->observationNumber(isn);

      if (observationMap.find(observationNumber) == observationMap.end()) {
        observationMap.insert(std::pair<QString, int>(observationNumber, currentIndex));
        observationMap.insert(pair<QString, int>(observationNumber, currentIndex));
        observationIndex = currentIndex++;
      }
      else {
@@ -62,42 +68,49 @@ namespace Isis {

      add(isn, observationIndex, observationNumber);
    }
    p_numberObservations = currentIndex;
    m_numberObservations = currentIndex;
  }


  /**
   * Destructor
   */
  ObservationNumberList::~ObservationNumberList() {
  }


  /**
   * Removes all of the listed serial numbers from the observation
   *
   * @param snlist The list of SerialNumbers to remove
   *
   * @throws IException::User "Cannot remove, serial number list is empty"
   */
  void ObservationNumberList::Remove(Isis::SerialNumberList *snlist) {
  void ObservationNumberList::remove(SerialNumberList *snlist) {

    if (snlist->size() == 0) {
      QString msg = "Removing serial number list is empty";
      QString msg = "Cannot remove, serial number list is empty";
      throw IException(IException::User, msg, _FILEINFO_);
    }

    p_sets.clear();
    p_indexMap.clear();
    m_sets.clear();
    m_indexMap.clear();

    std::map<QString, int> observationMap;
    map<QString, int> observationMap;
    QString observationNumber;
    int currentIndex = 0;
    int observationIndex;

    // Fill the temporary map to generate observation sets
    for (int isn = 0; isn < this->size(); isn++) {
      if((snlist->hasSerialNumber(this->serialNumber(isn)))) continue;
      if ( (snlist->hasSerialNumber(this->serialNumber(isn))) ) {
        continue;
      }

      observationNumber = this->observationNumber(isn);

      if (observationMap.find(observationNumber) == observationMap.end()) {
        observationMap.insert(std::pair<QString, int>(observationNumber, currentIndex));
        observationMap.insert(pair<QString, int>(observationNumber, currentIndex));
        observationIndex = currentIndex++;
      }
      else {
@@ -106,7 +119,7 @@ namespace Isis {

      add(isn, observationIndex, observationNumber);
    }
    p_numberObservations = currentIndex;
    m_numberObservations = currentIndex;
  }


@@ -115,9 +128,9 @@ namespace Isis {
   *
   * @param listfile The list of SerialNumbers to remove
   */
  void ObservationNumberList::Remove(const QString &listfile) {
    Isis::SerialNumberList snlist(listfile);
    Remove(&snlist);
  void ObservationNumberList::remove(const QString &listfile) {
    SerialNumberList snlist(listfile);
    remove(&snlist);
  }


@@ -140,17 +153,18 @@ namespace Isis {
    nextset.observationNumberIndex = observationIndex;
    nextset.observationNumber = observationNumber;

    p_sets.push_back(nextset);
    p_indexMap.insert(std::pair<int, int>(isn, observationIndex));
    m_sets.push_back(nextset);
    m_indexMap.insert(pair<int, int>(isn, observationIndex));
  }


  /**
   * How many unique observations are in the list?
   *
   * @return int Returns number of unique observations currently in the list
   * @return @b int Returns number of unique observations currently in the list
   */
  int ObservationNumberList::observationSize() const {
    return p_numberObservations;
    return m_numberObservations;
  }


@@ -160,28 +174,31 @@ namespace Isis {
   *
   * @param on The observation number to be checked for
   *
   * @return bool
   * @return @b bool
   */
  bool ObservationNumberList::hasObservationNumber(const QString &on) {
    for(unsigned index = 0; index < p_pairs.size(); index++) {
      if(p_pairs[index].observationNumber == on) {
    for (unsigned index = 0; index < m_pairs.size(); index++) {
      if (m_pairs[index].observationNumber == on) {
        return true;
      }
    }
    return false;
  }


  /**
   * Return a observation index given a serial number index
   *
   * @param serialNumberIndex The index of the serial number to map
   *
   * @return int The observation index mapped to the serial number
   * @throws IException::Programmer "Serial Number Index is invalid"
   *
   * @return @b int The observation index mapped to the serial number
   */
  int ObservationNumberList::observationNumberMapIndex(int serialNumberIndex) {
    //    if (serialNumberIndex >= 0 && serialNumberIndex < (int) p_indexMap.size()) {
    //    if (serialNumberIndex >= 0 && serialNumberIndex < (int) m_indexMap.size()) {
    if (serialNumberIndex >= 0) {
      return p_indexMap.find(serialNumberIndex)->second;
      return m_indexMap.find(serialNumberIndex)->second;
    }
    else {
      QString msg = "Serial Number Index [" + toString(serialNumberIndex) + "] is invalid";
@@ -191,34 +208,38 @@ namespace Isis {


  /**
   * return an observation number given a filename
   * Return an observation number given a filename
   *
   * @param filename The filename to be matched
   *
   * @return QString The observation number corresponding to
   * @throws IException::Programmer "Requested filename does not exist in the list"
   *
   * @return @b QString The observation number corresponding to
   *         the input filename
   */
  QString ObservationNumberList::observationNumber(const QString &filename) {
    if(p_fileMap.find(Isis::FileName(filename).expanded()) == p_fileMap.end()) {
      QString msg = "Requested filename [" +
                        Isis::FileName(filename).expanded() + "]";
    if (m_fileMap.find(FileName(filename).expanded()) == m_fileMap.end()) {
      QString msg = "Requested filename [" + FileName(filename).expanded() + "] ";
      msg += "does not exist in the list";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }
    int index = fileNameIndex(filename);
    return p_pairs[index].observationNumber;
    return m_pairs[index].observationNumber;
  }


  /**
   * Return a observation number given an index
   *
   * @param index The index of the desired observation number
   *
   * @return QString The observation number returned
   * @throws IException::Programmer "Index is invalid"
   *
   * @return @b QString The observation number returned
   */
  QString ObservationNumberList::observationNumber(int index) {
    if(index >= 0 && index < (int) p_pairs.size()) {
      return p_pairs[index].observationNumber;
    if (index >= 0 && index < (int) m_pairs.size()) {
      return m_pairs[index].observationNumber;
    }
    else {
      QString msg = "Index [" + toString(index) + "] is invalid";
@@ -226,19 +247,22 @@ namespace Isis {
    }
  }


  /**
   * Return possible filenames given an observation number
   *
   * @param on  The observation number of the desired filename
   *
   * @return vector<QString> The list of possible filenames
   * @throws IException::Programmer "Requested observation number does not exist in the list"
   *
   * @return @b vector<QString> The list of possible filenames
   *            matching the input observation number
   */
  std::vector<QString> ObservationNumberList::possibleFileNames(const QString &on) {
    std::vector<QString> filenames;
    for(unsigned index = 0; index < p_pairs.size(); index++) {
      if(p_pairs[index].observationNumber == on) {
        filenames.push_back(p_pairs[index].filename);
  vector<QString> ObservationNumberList::possibleFileNames(const QString &on) {
    vector<QString> filenames;
    for (unsigned index = 0; index < m_pairs.size(); index++) {
      if (m_pairs[index].observationNumber == on) {
        filenames.push_back(m_pairs[index].filename);
      }
    }
    if (filenames.size() > 0) {
+29 −19
Original line number Diff line number Diff line
@@ -24,37 +24,43 @@
 *
 */

#include <string>
#include <map>
#include <vector>

#include <QString>

#include "SerialNumberList.h"

namespace Isis {

  /**
   * @brief Needs Documentation
   * @brief Create a list of observation numbers from a file or serial number list
   *
   * Needs Documentation
   * @description This class allows for creating observation numbers from a provided file or
   * and existing non-empty SerialNumberList. Internally, it will map the observation numbers
   * that are created to the corresponding serial number for a given observation. 
   *
   * @author 2007-09-17 Debbie A. Cook
   *
   * @internal
   *   @history 2007-09-17 Debbie A. Cook - Original version
   *   @history 2008-01-11 Christopher Austin - Made class more
   *            general, inheriting SerialNumberList among others
   *   @history 2008-05-01 Debbie A. Cook - Removed upper bound check in
   *            ObservationNumberMapIndex because when entries are
   *            removed from the observation list, the serialNumberIndex
   *            may exceed the size of the map
   *   @history 2008-01-11 Christopher Austin - Made class more general, inheriting 
   *                           SerialNumberList among others
   *   @history 2008-05-01 Debbie A. Cook - Removed upper bound check in ObservationNumberMapIndex
   *                           because when entries are removed from the observation list, the 
   *                           serialNumberIndex may exceed the size of the map
   *   @history 2008-06-18 Steven Koechle - Fixed Documentation Errors
   *   @history 2008-10-30 Steven Lambright - Fixed problem with definition
   *            of struct quad, pointed out by "novus0x2a" (Support Board Member)
   *   @history 2008-10-30 Steven Lambright - Fixed problem with definition of struct quad, pointed
   *                           out by "novus0x2a" (Support Board Member)
   *   @history 2016-06-02 Ian Humphrey - Changed inherited protected members from p_ to m_.
   *                           References #3967.
   *   @history 2016-06-03 Ian Humphrey - Updated documentation and coding standards. Updated
   *                           unit test. Fixes #3990.
   */
  class ObservationNumberList : public Isis::SerialNumberList {
  class ObservationNumberList : public SerialNumberList {
    public:
      ObservationNumberList(const QString &list, bool checkTarget = true);
      ObservationNumberList(Isis::SerialNumberList *snlist);
      ObservationNumberList(SerialNumberList *snlist);
      ~ObservationNumberList();

      void add(int isn, const int observationIndex, QString observationNumber) ;
@@ -62,8 +68,8 @@ namespace Isis {

      int observationNumberMapIndex(const int serialNumberIndex);

      void Remove(Isis::SerialNumberList *snlist);
      void Remove(const QString &listfile);
      void remove(SerialNumberList *snlist);
      void remove(const QString &listfile);

      bool hasObservationNumber(const QString &on);

@@ -72,17 +78,21 @@ namespace Isis {
      std::vector<QString> possibleFileNames(const QString &on);

    private:
      /**
       * An observation consiting of a serial number index to the ObservationNumberList,
       * an observation number index to the ObservationNumberList, and the observation number.
       */  
      struct ObservationSet {
        int serialNumberIndex;
        int observationNumberIndex;
        QString observationNumber;
      };

      void init(Isis::SerialNumberList *snlist);
      void init(SerialNumberList *snlist);

      std::vector<ObservationSet> p_sets;
      std::multimap<int, int> p_indexMap;
      int p_numberObservations;
      std::multimap<int, int> m_indexMap;  //!< Maps serial number index to observation number index
      int m_numberObservations;       //!< Count of observations in the observation number list
      std::vector<ObservationSet> m_sets;  //!< List of observation sets
  };
};

+48 −0
Original line number Diff line number Diff line
size             = 4
observationSize  = 4
has XYZ          = 0
has LO3/HRC/3133 = 1
observationIndex for LO3/HRC/3133 = 2

ab102401.cub = MGS/561812335:32/MOC-WA
m0402852.cub = MGS/619971158:28/MOC-NA
3133_h1.cub = LO3/HRC/3133
@@ -16,3 +20,47 @@ SN->File (2): 3133_h1.cub
[NotAnObservation] is not an existing ObservationNumber


Removing a SerialNumberList that doesn't have any SNs in the ObservationNumberList
size            = 4
observationSize = 4

Removing a SerialNumberList with one SN that exists in the ObservationNumberList
size            = 4
observationSize = 3


Creating an observation list with two observations and three SNs
size            = 3
observationSize = 2
observationIndex for I008... = 0
observationIndex for 5106_h1 = 1
observationIndex for 5106_h2 = 1

Adding 5106_h3 to the list
size            = 3
observationSize = 2
observationIndex for 5106_h3 = 1

Removing 5106_h2 SN from the list
size            = 3
observationSize = 2


**USER ERROR** Serial number list is empty.


**USER ERROR** Cannot remove, serial number list is empty.


**PROGRAMMER ERROR** Serial Number Index [-1] is invalid.


**PROGRAMMER ERROR** Requested filename [.../I00824006RDR.lev2.cub] does not exist in the list.


**PROGRAMMER ERROR** Index [5] is invalid.


**PROGRAMMER ERROR** Requested observation number [DNE] does not exist in the list.

+179 −12
Original line number Diff line number Diff line
#include <iostream>

#include <QFile>

#include "FileName.h"
#include "IException.h"
#include "ObservationNumberList.h"
#include "Preference.h"
#include "SerialNumberList.h"
#include "IException.h"
#include "IString.h"
#include "FileName.h"

using namespace Isis;
using namespace std;

/**
 * Unit Test for ObservationNumberList
 *  
 * @internal
 *   @history 2010-07-02 Steven Lambright - Original version.
 *   @history 2016-06-03 Ian Humphrey - Improved test coverage. References #3990.
 */
int main(int argc, char *argv[]) {
  Preference::Preferences(true);

  try {
    SerialNumberList snl(false);

    // All of these are unique observations (i.e. 4 observation#'s, 4 serial#'s)
    snl.add("$mgs/testData/ab102401.cub");
    snl.add("$mgs/testData/m0402852.cub");
    snl.add("$lo/testData/3133_h1.cub");
    snl.add("$odyssey/testData/I00824006RDR.lev2.cub");

    // Testing constructor that takes SerialNumberList
    ObservationNumberList onl(&snl);

    // Testing observationSize, hasObservationNumber, observationNumberMapIndex
    cout << "size             = " << onl.size() << endl;
    cout << "observationSize  = " << onl.observationSize() << endl;
    // hasObservationNumber -> false
    cout << "has XYZ          = " << onl.hasObservationNumber("XYZ") << endl;
    // hasObservationNumber -> true
    cout << "has LO3/HRC/3133 = " << onl.hasObservationNumber("LO3/HRC/3133") << endl;
    // observationNumberMapIndex for 3rd SN
    cout << "observationIndex for LO3/HRC/3133 = " << onl.observationNumberMapIndex(2) << endl;
    cout << endl;

    // Testing observationNumber(int)
    for (int i = 0; i < onl.size(); i++) {
      cout << FileName(onl.fileName(i)).name() << " = " << onl.observationNumber(i) << endl;
      cout << FileName(onl.fileName(i)).name().toStdString() << " = " 
           << onl.observationNumber(i).toStdString() << endl;
    }

    cout << endl;
    // Testing possibleFileNames
    vector<QString> filenames = onl.possibleFileNames(onl.observationNumber(2));
    for (unsigned i = 0; i < filenames.size(); i++) {
      cout << "Possible filename for [" << onl.observationNumber(2)
           << "]: " << FileName(filenames[i]).name() << endl;
      cout << "Possible filename for [" << onl.observationNumber(2).toStdString()
           << "]: " << FileName(filenames[i]).name().toStdString() << endl;
    }
    // Testing possibleSerialNumbers
    vector<QString> serials = onl.possibleSerialNumbers(onl.observationNumber(2));
    for (unsigned i = 0; i < serials.size(); i++) {
      cout << "Possible serial number for [" << onl.observationNumber(2)
           << "]: " << serials[i] << endl;
      cout << "Possible serial number for [" << onl.observationNumber(2).toStdString()
           << "]: " << serials[i].toStdString() << endl;
    }

    cout << "File->ON:" << onl.observationNumber("$mgs/testData/ab102401.cub") << endl;
    // Testing observationNumber(QString)
    cout << "File->ON:" << onl.observationNumber("$mgs/testData/ab102401.cub").toStdString() 
         << endl;

    cout << endl << "SN->File (0): " << FileName(snl.fileName(0)).name() << endl;
    cout << "SN->File (1): " << FileName(snl.fileName(1)).name() << endl;
    cout << "SN->File (2): " << FileName(snl.fileName(2)).name() << endl << endl;
    cout << endl << "SN->File (0): " << FileName(snl.fileName(0)).name().toStdString() << endl;
    cout << "SN->File (1): " << FileName(snl.fileName(1)).name().toStdString() << endl;
    cout << "SN->File (2): " << FileName(snl.fileName(2)).name().toStdString() << endl << endl;

    if (onl.hasObservationNumber("NotAnObservation"))
      cout << "This line shouldn't be showing!" << endl;
    else
      cout << "[NotAnObservation] is not an existing ObservationNumber" << endl;

    // Test remove(QString) method (with a SN that doesn't exist in the list)
    cout << endl << endl;
    cout << "Removing a SerialNumberList that doesn't have any SNs in the ObservationNumberList"
         << endl;
    FileName temp1("$temporary/temp1list.txt");
    QFile tempFile1(temp1.expanded());
    tempFile1.open(QIODevice::WriteOnly | QIODevice::Text);
    tempFile1.write("$odyssey/testData/I56632006EDR.lev2.cub\n");
    tempFile1.close();

    onl.remove(temp1.expanded());
    cout << "size            = " << onl.size() << endl;
    cout << "observationSize = " << onl.observationSize() << endl;

    // Cleanup tempFile1
    tempFile1.remove();
  
    // Test remove(SerialNumberList *) (with a SN that exists in the list) -- Not sure if this is correct
    cout << endl << "Removing a SerialNumberList with one SN that exists in the "
         << "ObservationNumberList" << endl;
    SerialNumberList snlToRemove(false);
    snlToRemove.add("$mgs/testData/ab102401.cub");
    onl.remove(&snlToRemove);
    cout << "size            = " << onl.size() << endl;
    cout << "observationSize = " << onl.observationSize() << endl;
    cout << endl << endl;


    // Now, test where one observation has 2SN's
    SerialNumberList snl2(false);
    cout << "Creating an observation list with two observations and three SNs" << endl;
    snl2.add("$odyssey/testData/I00824006RDR.lev2.cub");
    snl2.add("$lo/testData/5106_h1.cropped.cub");
    snl2.add("$lo/testData/5106_h2.cropped.cub"); // Same observation as above
    
    ObservationNumberList onl2(&snl2);
    cout << "size            = " << onl2.size() << endl;
    cout << "observationSize = " << onl2.observationSize() << endl;
    cout << "observationIndex for I008... = " << onl2.observationNumberMapIndex(0) << endl;
    cout << "observationIndex for 5106_h1 = " << onl2.observationNumberMapIndex(1) << endl;
    // Should be same as above observation index
    cout << "observationIndex for 5106_h2 = " << onl2.observationNumberMapIndex(2) << endl;
    cout << endl;
    

    // Test add method -- Not sure if this is correct?
    cout << "Adding 5106_h3 to the list" << endl;
    onl2.add(onl2.size(), 1, "LO5/HRC/5106");
    cout << "size            = " << onl2.size() << endl;
    cout << "observationSize = " << onl2.observationSize() << endl;
    cout << "observationIndex for 5106_h3 = " << onl2.observationNumberMapIndex(3) << endl;
    cout << endl;

    // Test remove method on observation with 2 SNs -- Not sure if this is correct?
    cout << "Removing 5106_h2 SN from the list" << endl;
    SerialNumberList snlToRemove2(false);
    snlToRemove2.add("$lo/testData/5106_h2.cropped.cub");
    onl2.remove(&snlToRemove2);
    cout << "size            = " << onl2.size() << endl;
    cout << "observationSize = " << onl2.observationSize() << endl;
  
  }
  catch (IException &e) {
    e.print();
  }


  // Setup temp file - Need to cleanup later!
  FileName temp("$temporary/templist.txt");
  QFile tempFile(temp.expanded());
  tempFile.open(QIODevice::WriteOnly | QIODevice::Text);
  tempFile.write("$mgs/testData/ab102401.cub\n");
  tempFile.write("$mgs/testData/m0402852.cub\n");
  tempFile.write("$lo/testData/3133_h1.cub\n");
  tempFile.close();

  // Test 1st constructor
  ObservationNumberList onl(temp.expanded(), false);

  // Setup empty serial number list for exceptions
  SerialNumberList empty(false);

  // Test Exceptions
  try {
    cout << endl << endl;
    // Create ONL from empty SNL
    ObservationNumberList emptyONL(&empty);
  }
  catch (IException &e) {
    QString error = e.toString().replace(QRegExp("(\\[[^\\]]*/)([^\\]]*)"), "[.../\\2");
    cerr << error.toStdString() << endl;
  }

  try {
    cout << endl << endl;
    // Remove empty serial number list
    onl.remove(&empty);
  }
  catch (IException &e) {
    QString error = e.toString().replace(QRegExp("(\\[[^\\]]*/)([^\\]]*)"), "[.../\\2");
    cerr << error.toStdString() << endl;
  }

  try {
    cout << endl << endl;
    // Request observation number by providing invalid serial number index
    onl.observationNumberMapIndex(-1);
  }
  catch (IException &e) {
    QString error = e.toString().replace(QRegExp("(\\[[^\\]]*/)([^\\]]*)"), "[.../\\2");
    cerr << error.toStdString() << endl;
  }
 
  try {
    cout << endl << endl;
    // Request an observation number from a file that doesn't exist in the observation list
    onl.observationNumber("$odyssey/testData/I00824006RDR.lev2.cub");
  }
  catch (IException &e) {
    QString error = e.toString().replace(QRegExp("(\\[[^\\]]*/)([^\\]]*)"), "[.../\\2");
    cerr << error.toStdString() << endl;
  }

  try {
    cout << endl << endl;
    // Request observation number with an invalid index
    onl.observationNumber(5);
  }
  catch (IException &e) {
    QString error = e.toString().replace(QRegExp("(\\[[^\\]]*/)([^\\]]*)"), "[.../\\2");
    cerr << error.toStdString() << endl;
  } 

  try {
    cout << endl << endl;
    // Request possible file names for observation number that isn't in the list
    onl.possibleFileNames("DNE");
  }
  catch (IException &e) {
    QString error = e.toString().replace(QRegExp("(\\[[^\\]]*/)([^\\]]*)"), "[.../\\2");
    cerr << error.toStdString() << endl;
  }

  cout << endl << endl;

  // Cleanup the temp file
  tempFile.remove();

}
+161 −106

File changed.

Preview size limit exceeded, changes collapsed.

Loading