Commit a6a93638 authored by Ian Humphrey's avatar Ian Humphrey
Browse files

Removed SpacecraftInstrumentId methods from SerialNumberList. Updated its...

Removed SpacecraftInstrumentId methods from SerialNumberList. Updated its documentation, testing, and coding standards compliance. Fixes #3967. Updated documentation and testing for ObservationNumberList. Fixes #3990.

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/branches/ipce@6769 41f8697f-d340-4b68-9986-7bafba869bb8
parent 799a0330
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