diff --git a/isis/src/base/objs/Application/Application.cpp b/isis/src/base/objs/Application/Application.cpp
index 1e32f38704b48ee16bec4c6827898ffd2a6add48..b4b26ff8ab3a5d41330a3de74e287e943c45eff9 100644
--- a/isis/src/base/objs/Application/Application.cpp
+++ b/isis/src/base/objs/Application/Application.cpp
@@ -102,14 +102,6 @@ namespace Isis {
     strncpy(env, "LANG=en_US", 1023);
     putenv(env);
 
-    // Verify ISISROOT was set
-    if (getenv("ISISROOT") == NULL || QString(getenv("ISISROOT")) == "") {
-      QString message = "Please set ISISROOT before running any Isis "
-          "applications";
-      cerr << message << endl;
-      abort();
-    }
-
     // Get the starting cpu time, direct I/Os, page faults, and swaps
     //p_startClock = clock();
     p_startDirectIO = DirectIO();
diff --git a/isis/src/base/objs/EmbreeShapeModel/EmbreeShapeModel.cpp b/isis/src/base/objs/EmbreeShapeModel/EmbreeShapeModel.cpp
index 273a98178d190508edb8e9bfc05081b34c56eb95..ca78a550ed5cc83cee8ac067c5853fdcc15540ed 100644
--- a/isis/src/base/objs/EmbreeShapeModel/EmbreeShapeModel.cpp
+++ b/isis/src/base/objs/EmbreeShapeModel/EmbreeShapeModel.cpp
@@ -593,50 +593,6 @@ namespace Isis {
   }
 
 
-  /**
-   * Computes and returns emission angle, in degrees, given the observer
-   * position. The surface normal vector is calculated using an ellipsoid, not
-   * the local normal of the actual target shape.
-   *
-   * Emission Angle: The angle between the surface normal vector at the
-   * intersection point and the vector from the intersection point to the
-   * observer (usually the spacecraft). The emission angle varies from 0 degrees
-   * when the observer is viewing the sub-spacecraft point (nadir viewing) to 90
-   * degrees when the intercept is tangent to the surface of the target body.
-   * Thus, higher values of emission angle indicate more oblique viewing of the
-   * target.
-   *
-   * @param observerBodyFixedPosition  Three dimensional position of the observer,
-   *                                   in the coordinate system of the target body.
-   *
-   * @return The emission angle, in decimal degrees.
-   *
-   */
-  double EmbreeShapeModel::emissionAngle(const std::vector<double> &observerBodyFixedPosition) {
-
-    // If there is already a normal save it, because it's probably the local normal
-    std::vector<double> localNormal;
-    bool hadNormal = hasNormal();
-    if ( hadNormal ) {
-      localNormal = normal();
-    }
-
-    // Calculate the ellipsoid surface normal
-    calculateDefaultNormal();
-    
-    // Use ShapeModel to calculate the ellipsoid emission angle
-    double ellipsoidEmission = ShapeModel::emissionAngle(observerBodyFixedPosition);
-
-    // If there's a saved normal, reset it
-    if ( hadNormal ) {
-      setNormal(localNormal);
-    }
-
-    // Return the ellipsoid emission angle
-    return ellipsoidEmission;
-  }
-
-
   /**
    * Computes and returns incidence angle, in degrees, given the illuminator position.
    * The surface normal vector is calculated using an ellipsoid, not the local
diff --git a/isis/src/base/objs/EmbreeShapeModel/EmbreeShapeModel.h b/isis/src/base/objs/EmbreeShapeModel/EmbreeShapeModel.h
index 1d0d66320c14c3b6685724096b9006fa9cd9e7ab..e11f615b77ff036d862da99ded9c26900e4469e2 100644
--- a/isis/src/base/objs/EmbreeShapeModel/EmbreeShapeModel.h
+++ b/isis/src/base/objs/EmbreeShapeModel/EmbreeShapeModel.h
@@ -47,6 +47,8 @@ namespace Isis {
    *
    * @internal
    *   @history 2017-04-22 Jesse Mapel and Jeannie Backer - Original Version
+   *   @history 2018-05-01 Christopher Combs - Removed emissionAngle function to
+   *                fix issues with using ellipsoids to find normals. Fixes #5387.
    */
   class EmbreeShapeModel : public ShapeModel {
     public:
@@ -84,10 +86,8 @@ namespace Isis {
       virtual void calculateSurfaceNormal();
       QVector<double> ellipsoidNormal();
 
-      virtual double emissionAngle(const std::vector<double> &sB);
       virtual double incidenceAngle(const std::vector<double> &uB);
 
-
       virtual Distance localRadius(const Latitude &lat, const Longitude &lon);
 
       // Determine if the internal intercept is occluded from the observer/lookdir
diff --git a/isis/src/base/objs/Isis/Isis.h b/isis/src/base/objs/Isis/Isis.h
index df6889d3e23bc4f64fde2b2f67a5cfaf2bf9cce3..2e6e8d87e2fc3d96758bf22d3b87ffb7d079811f 100644
--- a/isis/src/base/objs/Isis/Isis.h
+++ b/isis/src/base/objs/Isis/Isis.h
@@ -107,6 +107,14 @@ void InterruptSignal(int);
  * @return int
  */
 int main(int argc, char *argv[]) {
+  // Verify ISISROOT was set
+  // Note: as printing and logging IExceptions requires ISISROOT to be set (for preferences),
+  //       The case below cannot be handled with IExceptions
+  if (getenv("ISISROOT") == NULL || QString(getenv("ISISROOT")) == "") {
+    std::cerr << "Please set ISISROOT before running any Isis applications" << std::endl;
+    exit(1);
+  }
+
 #ifdef CWDEBUG
   startMonitoringMemory();
   signal(SIGSEGV, SegmentationFault);
@@ -119,7 +127,7 @@ int main(int argc, char *argv[]) {
 #ifdef USE_GUI_QAPP
   Isis::Application::p_applicationForceGuiApp = true;
 #endif
-
+    
   // Add the plugin directory so QT looks at the Isis plugin dir
   Isis::FileName qtpluginpath("$ISISROOT/3rdParty/plugins");
   QCoreApplication::addLibraryPath(qtpluginpath.expanded());
diff --git a/isis/src/base/objs/ProcessImport/ProcessImport.cpp b/isis/src/base/objs/ProcessImport/ProcessImport.cpp
index c6ccd306bdc488d40e98b29101ba3214d9fb2a4f..7ae955ad9b51b02baf71d25ade870600ae7d7456 100644
--- a/isis/src/base/objs/ProcessImport/ProcessImport.cpp
+++ b/isis/src/base/objs/ProcessImport/ProcessImport.cpp
@@ -725,7 +725,7 @@ namespace Isis {
    * This method returns the number of data trailer bytes
    */
   int ProcessImport::DataTrailerBytes() const {
-    return p_dataTrailerBytes; 
+    return p_dataTrailerBytes;
   }
 
 
@@ -1847,11 +1847,6 @@ namespace Isis {
    */
   void ProcessImport::ProcessBip(void funct(Isis::Buffer &out)) {
 
-    // Figure out the number of bytes to read for a single line
-    int readBytes = Isis::SizeOf(p_pixelType);
-    readBytes = readBytes * p_ns * p_nb;
-    char *in = new char [readBytes];
-
     // Set up an Isis::EndianSwapper object
     QString tok(Isis::ByteOrderName(p_byteOrder));
     tok = tok.toUpper();
@@ -1902,6 +1897,11 @@ namespace Isis {
     p_progress->SetMaximumSteps(p_nl);
     p_progress->CheckStatus();
 
+    // Figure out the number of bytes to read for a single line
+    int sampleBytes = Isis::SizeOf(p_pixelType) * p_nb + p_dataPreBytes + p_dataPostBytes;
+    int readBytes = p_ns * sampleBytes;
+    char *in = new char [readBytes];
+
     // Loop for each line
     for(int line = 0; line < p_nl; line++) {
       // Check the last io
@@ -1915,16 +1915,6 @@ namespace Isis {
       // Space for storing prefix and suffix data pointers
       vector<char *> tempPre, tempPost;
 
-      // Handle any line prefix bytes
-      pos = fin.tellg();
-      if (p_saveDataPre) {
-        tempPre.push_back(new char[p_dataPreBytes]);
-        fin.read(tempPre.back(), p_dataPreBytes);
-      }
-      else {
-        fin.seekg(p_dataPreBytes, ios_base::cur);
-      }
-
       // Check the last io
       if (!fin.good()) {
         QString msg = "Cannot read file [" + p_inFile + "]. Position [" +
@@ -1960,31 +1950,32 @@ namespace Isis {
         // to special pixels
         int osamp = 0;
 
-        for(int samp = band; samp < p_ns * p_nb; samp += p_nb) {
+        for(int samp = 0; samp < p_ns; samp++) {
+          int bufferIndex = p_dataPreBytes + Isis::SizeOf(p_pixelType)*band + samp*sampleBytes;
           switch(p_pixelType) {
             case Isis::UnsignedByte:
-              (*out)[osamp] = (double)((unsigned char *)in)[samp];
+              (*out)[osamp] = (double)((unsigned char *)in)[bufferIndex];
               break;
             case Isis::UnsignedWord:
               (*out)[osamp] =
-                (double)swapper.UnsignedShortInt((unsigned short int *)in+samp);
+                (double)swapper.UnsignedShortInt(&in[bufferIndex]);
               break;
             case Isis::SignedWord:
-              (*out)[osamp] = (double)swapper.ShortInt((short int *)in+samp);
+              (*out)[osamp] = (double)swapper.ShortInt(&in[bufferIndex]);
               break;
             case Isis::SignedInteger:
-              (*out)[samp] = (double)swapper.Int((int *)in+samp);
+              (*out)[samp] = (double)swapper.Int(&in[bufferIndex]);
               break;
             case Isis::Real:
               if(p_vax_convert) {
-                (*out)[osamp]= VAXConversion( (float *)in+samp );
+                (*out)[osamp]= VAXConversion(&in[bufferIndex]);
               }
               else {
-                (*out)[osamp] = (double)swapper.Float((float *)in+samp);
+                (*out)[osamp] = (double)swapper.Float(&in[bufferIndex]);
               }
               break;
             case Isis::Double:
-              (*out)[osamp] = (double)swapper.Double((double *)in+samp);
+              (*out)[osamp] = (double)swapper.Double(&in[bufferIndex]);
               break;
             default:
               break;
@@ -2008,47 +1999,38 @@ namespace Isis {
           funct(*out);
         }
 
-        // Handle any line suffix bytes
-        pos = fin.tellg();
-        if (p_saveDataPost) {
-          tempPost.push_back(new char[p_dataPostBytes]);
-          fin.read(tempPost.back(), p_dataPostBytes);
-        }
-        else {
-          fin.seekg(p_dataPostBytes, ios_base::cur);
-        }
-
-        // Check the last io
-        if (!fin.good()) {
-          QString msg = "Cannot read file [" + p_inFile + "]. Position [" +
-                       toString((int)pos) + "]. Byte count [" +
-                       toString(p_dataPreBytes) + "]" ;
-          throw IException(IException::Io, msg, _FILEINFO_);
-        }
-
-
-        // Save off the prefix bytes vector
-        if (p_saveDataPre) {
-          p_dataPre.push_back(tempPre);
-          tempPre.clear();
-        }
+      } // End band loop
 
-        // Save off the suffix bytes vector
-        if (p_saveDataPost) {
-          p_dataPost.push_back(tempPost);
-          tempPost.clear();
+      // Handle record prefix and suffix
+      if (p_saveDataPre) {
+        for(int samp = 0; samp < p_ns; samp++) {
+          char *samplePrefix = new char[p_dataPreBytes];
+          memcpy(samplePrefix, &in[samp*sampleBytes], p_dataPreBytes);
+          tempPre.push_back(samplePrefix);
         }
-
-        // Check the last io
-        if (!fin.good()) {
-          QString msg = "Cannot read file [" + p_inFile + "]. Position [" +
-                       toString((int)pos) + "]. Byte count [" +
-                       toString(p_fileHeaderBytes) + "]" ;
-          throw IException(IException::Io, msg, _FILEINFO_);
+        p_dataPre.push_back(tempPre);
+        tempPre.clear();
+      }
+      if (p_saveDataPost) {
+        for(int samp = 0; samp < p_ns; samp++) {
+          char *sampleSuffix = new char[p_dataPostBytes];
+          int suffixIndex = p_dataPreBytes + Isis::SizeOf(p_pixelType)*p_nb + samp*sampleBytes;
+          memcpy(sampleSuffix, &in[suffixIndex], p_dataPostBytes);
+          tempPost.push_back(sampleSuffix);
         }
+        p_dataPost.push_back(tempPost);
+        tempPost.clear();
+      }
 
-      } // End band loop
+      // Check the last io
+      if (!fin.good()) {
+        QString msg = "Cannot read file [" + p_inFile + "]. Position [" +
+                     toString((int)pos) + "]. Byte count [" +
+                     toString(p_dataPreBytes) + "]" ;
+        throw IException(IException::Io, msg, _FILEINFO_);
+      }
 
+      // Handle the data trailer
       pos = fin.tellg();
       if (p_saveDataTrailer) {
         p_dataTrailer.push_back(new char[p_dataTrailerBytes]);
diff --git a/isis/src/base/objs/ProcessImport/ProcessImport.h b/isis/src/base/objs/ProcessImport/ProcessImport.h
index 1e47db453f8d68ae86fcfc2da5a27114102f6043..33a3cd3fa5818b194f325f0b1f16a556698f53fb 100644
--- a/isis/src/base/objs/ProcessImport/ProcessImport.h
+++ b/isis/src/base/objs/ProcessImport/ProcessImport.h
@@ -150,8 +150,19 @@ namespace Isis {
    *                           imports. Brought code closer to coding standards.
    *   @history 2016-04-21 Makayla Shepherd - Added UnsignedWord pixel type handling.
    *   @history 2017-05-29 Kristin Berry - Added support for data trailers in BIP files and fixed
-   *                            a typo so that DataTrailerBytes() will return the correct value.
-   *                            References #3888.
+   *                           a typo so that DataTrailerBytes() will return the correct value.
+   *                           References #3888.
+   *   @history 2018-05-01 Jesse Mapel - Changed data suffix and prefix in BIP files. Previously,
+   *                           data suffixes and prefixes were for each band before/after each line.
+   *                           Now, data suffixes and prefixes are before/after each sample. For a
+   *                           RGB, 3-band image with n samples a line of data was previously
+   *                           | Header | R prefix | G prefix | B prefix | R 1 | G 1 | B 1| ...
+   *                           | R n | G n | B n| R suffix | G suffix | B suffix | Trailer |. Now
+   *                           it is | Header | Prefix 1 | R 1 | G 1 | B 1 | Suffix 1 | ...
+   *                           | Prefix n | R n | G n | B n | Suffix n | Trailer |. This change
+   *                           was made to accomodate Rosetta VIRTIS-m calibrated data files and
+   *                           has no impact on other supported BIP files.
+   *                           Fixes #5398.
    *
    */
   class ProcessImport : public Isis::Process {
diff --git a/isis/src/base/objs/PushFrameCameraCcdLayout/PushFrameCameraCcdLayout.truth b/isis/src/base/objs/PushFrameCameraCcdLayout/PushFrameCameraCcdLayout.truth
index f36198413ae088b2edefa59d47bc2ce4d430c34f..d54562e565205f3c9b2224bc8e6e3ca24c196527 100644
--- a/isis/src/base/objs/PushFrameCameraCcdLayout/PushFrameCameraCcdLayout.truth
+++ b/isis/src/base/objs/PushFrameCameraCcdLayout/PushFrameCameraCcdLayout.truth
@@ -31,7 +31,7 @@ Get the METHANE filter layout
 METHANE filter ID: -61504
 METHANE filter name: "METHANE"
 METHANE filter start sample: 1
-METHANE filter start line: 291
+METHANE filter start line: 285
 METHANE filter samples: 1648
 METHANE filter lines: 128
 
@@ -39,7 +39,7 @@ Get the METHANE filter layout but give it a different name
 METHANE filter ID: -61504
 METHANE filter name: "methane"
 METHANE filter start sample: 1
-METHANE filter start line: 291
+METHANE filter start line: 285
 METHANE filter samples: 1648
 METHANE filter lines: 128
 
diff --git a/isis/src/base/objs/PvlToPvlTranslationManager/PvlToPvlTranslationManager.cpp b/isis/src/base/objs/PvlToPvlTranslationManager/PvlToPvlTranslationManager.cpp
index 2db7ad7c4d3c1a823f9d5680147d8fd6b6887276..95ee570ca43ebdaeeedf12c5c14bcf2a38922a56 100644
--- a/isis/src/base/objs/PvlToPvlTranslationManager/PvlToPvlTranslationManager.cpp
+++ b/isis/src/base/objs/PvlToPvlTranslationManager/PvlToPvlTranslationManager.cpp
@@ -40,7 +40,7 @@ namespace Isis {
    * set the input label before translating. This may be done by using
    * SetLabel(Pvl inputLabel) or Auto(Pvl inputLabel, Pvl outputLabel).
    *
-   * @param transFile The translation file to be used to tranlate keywords in
+   * @param transFile The translation file to be used to translate keywords in
    *                  the input label.
    */
   PvlToPvlTranslationManager::PvlToPvlTranslationManager(const QString &transFile)
@@ -53,8 +53,8 @@ namespace Isis {
    * input label before translating. This may be done by using SetLabel(Pvl
    * inputLabel) or Auto(Pvl inputLabel, Pvl outputLabel).
    *
-   * @param transStrm A stream containing the tranlation table to be used to
-   *                  tranlate keywords in the input label.
+   * @param transStrm A stream containing the translation table to be used to
+   *                  translate keywords in the input label.
    */
   PvlToPvlTranslationManager::PvlToPvlTranslationManager(std::istream &transStrm)
       : LabelTranslationManager(transStrm) {
@@ -66,7 +66,7 @@ namespace Isis {
    *
    * @param inputLabel The Pvl holding the input label.
    *
-   * @param transFile The translation file to be used to tranlate keywords in
+   * @param transFile The translation file to be used to translate keywords in
    *                  the input label.
    */
   PvlToPvlTranslationManager::PvlToPvlTranslationManager(Pvl &inputLabel,
@@ -81,8 +81,8 @@ namespace Isis {
    *
    * @param inputLabel The Pvl holding the input label.
    *
-   * @param transStrm A stream containing the tranlation table to be used to
-   *                  tranlate keywords in the input label.
+   * @param transStrm A stream containing the translation table to be used to
+   *                  translate keywords in the input label.
    */
   PvlToPvlTranslationManager::PvlToPvlTranslationManager(Pvl &inputLabel,
       std::istream &transStrm)
@@ -103,34 +103,37 @@ namespace Isis {
 
   /**
    * Returns a translated value. The output name is used to find the input
-   * group, keyword, default and tranlations in the translation table. If the
+   * group, keyword, default and translations in the translation table. If the
    * keyword does not exist in the input label and an input default is available,
    * then this default will be used as the input value. This input value is
    * then used to search all of the translations. If a match is found the
    * translated value is returned. 
    *
-   * @param nName The output name used to identify the input keyword to be
-   *              translated.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    *
    * @param findex The index into the input keyword array.  Defaults to 0
    *
    * @return string
    */
-  QString PvlToPvlTranslationManager::Translate(QString nName, int findex) {
+  QString PvlToPvlTranslationManager::Translate(QString translationGroupName, int findex) {
     const PvlContainer *con;
     int inst = 0;
     PvlKeyword grp;
 
-    while((grp = InputGroup(nName, inst++)).name() != "") {
+    while((grp = InputGroup(translationGroupName, inst++)).name() != "") {
       if((con = GetContainer(grp)) != NULL) {
-        if(con->hasKeyword(InputKeywordName(nName))) {
-          return PvlTranslationTable::Translate(nName,
-                                                (*con)[InputKeywordName(nName)][findex]);
+        if(con->hasKeyword(InputKeywordName(translationGroupName))) {
+          return PvlTranslationTable::Translate(translationGroupName,
+                                                (*con)[InputKeywordName(translationGroupName)][findex]);
         }
       }
     }
 
-    return PvlTranslationTable::Translate(nName);
+    return PvlTranslationTable::Translate(translationGroupName);
   }
 
 
@@ -143,12 +146,15 @@ namespace Isis {
    *  
    * @see Auto().
    *
-   * @param nName The output name used to identify the input keyword to be
-   *              translated.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    *
    * @return PvlKeyword
    */
-   PvlKeyword PvlToPvlTranslationManager::DoTranslation(const QString nName) {
+   PvlKeyword PvlToPvlTranslationManager::DoTranslation(const QString translationGroupName) {
      const PvlContainer *con = NULL;
      PvlKeyword key;
 
@@ -156,9 +162,9 @@ namespace Isis {
      PvlGroup transGroup;
      PvlKeyword grp;
 
-     while((grp = InputGroup(nName, inst++)).name() != "") {
+     while((grp = InputGroup(translationGroupName, inst++)).name() != "") {
        if((con = GetContainer(grp)) != NULL) {
-         transGroup = TranslationTable().findGroup(nName);
+         transGroup = TranslationTable().findGroup(translationGroupName);
          Pvl::ConstPvlKeywordIterator it = transGroup.findKeyword("InputKey",
                                            transGroup.begin(),
                                            transGroup.end());
@@ -167,10 +173,10 @@ namespace Isis {
          while(it != transGroup.end()) {
            const PvlKeyword &result = *it;
            if(con->hasKeyword(result[0])) {
-             key.setName(OutputName(nName));
+             key.setName(OutputName(translationGroupName));
 
              for(int v = 0; v < (*con)[(result[0])].size(); v++) {
-               key.addValue(PvlTranslationTable::Translate(nName,
+               key.addValue(PvlTranslationTable::Translate(translationGroupName,
                                                            (*con)[result[0]][v]),
                             (*con)[result[0]].unit(v));
              }
@@ -182,8 +188,8 @@ namespace Isis {
        }
      }
 
-     return PvlKeyword(OutputName(nName),
-                       PvlTranslationTable::Translate(nName, ""));
+     return PvlKeyword(OutputName(translationGroupName),
+                       PvlTranslationTable::Translate(translationGroupName, ""));
    }
 
 
@@ -227,16 +233,20 @@ namespace Isis {
   /**
    * Returns the ith input value associated with the output name argument.
    *
-   * @param nName The output name used to identify the input keyword.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    *
    * @param findex The index into the input keyword array.  Defaults to 0
    *
    * @throws IException::Programmer
    */
-  const PvlKeyword &PvlToPvlTranslationManager::InputKeyword(const QString nName) const {
+  const PvlKeyword &PvlToPvlTranslationManager::InputKeyword(const QString translationGroupName) const {
 
     int instanceNumber = 0;
-    PvlKeyword inputGroupKeyword = InputGroup(nName, instanceNumber);
+    PvlKeyword inputGroupKeyword = InputGroup(translationGroupName, instanceNumber);
     bool anInputGroupFound = false;
 
     while(inputGroupKeyword.name() != "") {
@@ -244,31 +254,31 @@ namespace Isis {
       if(containingGroup != NULL) {
         anInputGroupFound = true;
 
-        if(containingGroup->hasKeyword(InputKeywordName(nName))) {
-          return containingGroup->findKeyword(InputKeywordName(nName));
+        if(containingGroup->hasKeyword(InputKeywordName(translationGroupName))) {
+          return containingGroup->findKeyword(InputKeywordName(translationGroupName));
         }
       }
 
       instanceNumber ++;
-      inputGroupKeyword = InputGroup(nName, instanceNumber);
+      inputGroupKeyword = InputGroup(translationGroupName, instanceNumber);
     }
 
     if(anInputGroupFound) {
-      QString msg = "Unable to find input keyword [" + InputKeywordName(nName) +
-                   "] for output name [" + nName + "] in file [" + TranslationTable().fileName() + "]";
+      QString msg = "Unable to find input keyword [" + InputKeywordName(translationGroupName) +
+                   "] for output name [" + translationGroupName + "] in file [" + TranslationTable().fileName() + "]";
       throw IException(IException::Programmer, msg, _FILEINFO_);
     }
     else {
       QString container = "";
 
-      for(int i = 0; i < InputGroup(nName).size(); i++) {
+      for(int i = 0; i < InputGroup(translationGroupName).size(); i++) {
         if(i > 0) container += ",";
 
-        container += InputGroup(nName)[i];
+        container += InputGroup(translationGroupName)[i];
       }
 
       QString msg = "Unable to find input group [" + container +
-                   "] for output name [" + nName + "] in file [" + TranslationTable().fileName() + "]";
+                   "] for output name [" + translationGroupName + "] in file [" + TranslationTable().fileName() + "]";
       throw IException(IException::Programmer, msg, _FILEINFO_);
     }
   }
@@ -278,21 +288,25 @@ namespace Isis {
    * Indicates if the input keyword corresponding to the output name exists in
    * the label
    *
-   * @param nName The output name used to identify the input keyword.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    */
-  bool PvlToPvlTranslationManager::InputHasKeyword(const QString nName) {
+  bool PvlToPvlTranslationManager::InputHasKeyword(const QString translationGroupName) {
 
     // Set the current position in the input label pvl
     // by finding the input group corresponding to the output group
     const PvlContainer *con;
     int inst = 0;
-    //while ((con = GetContainer(InputGroup(nName, inst++))) != NULL) {
-    //if ((con = GetContainer (InputGroup(nName))) != NULL) {
+    //while ((con = GetContainer(InputGroup(translationGroupName, inst++))) != NULL) {
+    //if ((con = GetContainer (InputGroup(translationGroupName))) != NULL) {
 
     PvlKeyword grp;
-    while((grp = InputGroup(nName, inst++)).name() != "") {
+    while((grp = InputGroup(translationGroupName, inst++)).name() != "") {
       if((con = GetContainer(grp)) != NULL) {
-        if(con->hasKeyword(InputKeywordName(nName))) return true;
+        if(con->hasKeyword(InputKeywordName(translationGroupName))) return true;
       }
     }
 
@@ -340,10 +354,17 @@ namespace Isis {
 
   /**
    * Create the requsted container and any containers above it and
-   * return a reference to the container
-   * list is an PvlKeyword with an array of container types an their names
+   * return a reference to the container. List is a PvlKeyword 
+   * with an array of container types and their names. 
+   *  
+   * @param translationGroupName The name of the PVL translation 
+   *                        group used to identify the
+   *                        input/output keywords to be
+   *                        translated. Often, this is the
+   *                        same as the output keyword name.
+   * @param pvl Pvl 
    */
-  PvlContainer *PvlToPvlTranslationManager::CreateContainer(const QString nName, Pvl &pvl) {
-    return LabelTranslationManager::CreateContainer(nName, pvl);
+  PvlContainer *PvlToPvlTranslationManager::CreateContainer(const QString translationGroupName, Pvl &pvl) {
+    return LabelTranslationManager::CreateContainer(translationGroupName, pvl);
   }
 } // end namespace isis
diff --git a/isis/src/base/objs/PvlToPvlTranslationManager/PvlToPvlTranslationManager.h b/isis/src/base/objs/PvlToPvlTranslationManager/PvlToPvlTranslationManager.h
index 842d475e87f11846fb43da1f16a6e6d99f3716ff..fcc4c70d5434272ea809f4400dfa36a6a42fccea 100644
--- a/isis/src/base/objs/PvlToPvlTranslationManager/PvlToPvlTranslationManager.h
+++ b/isis/src/base/objs/PvlToPvlTranslationManager/PvlToPvlTranslationManager.h
@@ -71,7 +71,8 @@ namespace Isis {
    *                          PvlToPvlTranslationManager. Fixes #4901.
    *  @history 2018-01-10 Christopher Combs - Changed ProcessDataFilePointer call to reflect 
    *                          changes made to voy2isis. Fixes #4345, #4421.
-   *  @history 2018-04-16 Jeannie Backer - Fixed indentation of history comments.
+   *  @history 2018-04-16 Jeannie Backer - Fixed indentation of history comments and
+   *                          brought code closer to coding standards.
    *  @todo 2005-02-15 Stuart Sides - add coded example and implementation example
    *                          to class documentation, and finish
    *                          documentation.
@@ -92,24 +93,24 @@ namespace Isis {
 
       // Attempt to translate the requested output name to output value
       // using the input name and value/default value
-      virtual QString Translate(QString nName, int findex = 0);
+      virtual QString Translate(QString translationGroupName, int findex = 0);
 
       // Translate all translation table groups which contain "Auto"
       void Auto(Pvl &outputLabel);
       void Auto(Pvl &inputLabel, Pvl &outputLabel);
 
       // Return the ith input value associated with a output name
-      virtual const PvlKeyword &InputKeyword(const QString nName) const;
+      virtual const PvlKeyword &InputKeyword(const QString translationGroupName) const;
 
       // Return true if the input lable contains the translated group and key names
-      virtual bool InputHasKeyword(const QString nName);
+      virtual bool InputHasKeyword(const QString translationGroupName);
 
       void SetLabel(Pvl &inputLabel);
 
     protected:
-      virtual PvlKeyword DoTranslation(const QString nName);
+      virtual PvlKeyword DoTranslation(const QString translationGroupName);
       virtual const PvlContainer *GetContainer(const PvlKeyword &inputGroup) const;
-      virtual PvlContainer *CreateContainer(const QString nName, Pvl &pvl);
+      virtual PvlContainer *CreateContainer(const QString translationGroupName, Pvl &pvl);
     private:
       Pvl p_fLabel; //!< A Pvl object for the input label file
   };
diff --git a/isis/src/base/objs/PvlTranslationTable/PvlTranslationTable.cpp b/isis/src/base/objs/PvlTranslationTable/PvlTranslationTable.cpp
index 80d9b7379101a94c817de085cd56b565b1c5254a..06882220e51ba8ba07c7fc4337b15cad6ce53883 100644
--- a/isis/src/base/objs/PvlTranslationTable/PvlTranslationTable.cpp
+++ b/isis/src/base/objs/PvlTranslationTable/PvlTranslationTable.cpp
@@ -214,9 +214,11 @@ namespace Isis {
    * Translates a single output value from the given translation 
    * group name and input value. 
    *
-   * @param translationGroupName The name of the pvl translation 
-   *                             group. Often, this is the same
-   *                             as the output keyword name.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    * @param inputKeyValue The value to be translated, from the 
    *                      input keyword.
    *
@@ -283,7 +285,11 @@ namespace Isis {
    * Returns the input group name from the translation table corresponding to
    * the output name argument.
    *
-   * @param translationGroupName The output name to be used to search the translation table.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    * @param inst The occurence number of the "InputGroup" keyword
    *             (first one is zero)
    *
@@ -357,9 +363,15 @@ namespace Isis {
    * Returns the input keyword name from the translation table corresponding to
    * the output name argument.
    *
-   * @param translationGroupName The output name to be used to search the translation table.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
+   *  
+   * @return QString The input keyword name
    *
-   * @return QString The input keyword name.
+   * @throws IException::Programmer
    */
   QString PvlTranslationTable::InputKeywordName(const QString translationGroupName) const {
 
@@ -375,7 +387,11 @@ namespace Isis {
    * Returns the input default value from the translation table corresponding
    * to the output name argument.
    *
-   * @param translationGroupName The output name to be used to search the translation table.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    *
    * @return QString The input default value.
    */
@@ -395,7 +411,11 @@ namespace Isis {
    * PvlKeyword with the name "InputDefault". Note: no value needs
    * to be assigned to this keyword. 
    *  
-   * @param translationGroupName The name of the PVL translation group.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    * 
    * @return bool Indicates whether the given group has an 
    *         InputDefault keyword.
@@ -416,7 +436,11 @@ namespace Isis {
    * group contains a PvlKeyword with the name "Auto". Note: 
    * no value is assigned to this keyword. 
    *  
-   * @param translationGroupName The name of the PVL translation group.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    * 
    * @return bool Indicates whether the given group has an Auto 
    *         keyword.
@@ -437,7 +461,11 @@ namespace Isis {
    * PvlKeyword with the name "Optional". Note: no value is 
    * assigned to this keyword. 
    *  
-   * @param translationGroupName The name of the PVL translation group.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    * 
    * @return bool Indicates whether the given group has an 
    *         Optional keyword.
@@ -456,7 +484,11 @@ namespace Isis {
    * Retrieves the OutputPosition PvlKeyword for the translation 
    * group with the given name. 
    *  
-   * @param translationGroupName The name of the PVL translation group.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    * 
    * @return PvlKeyword The OutputPosition keyword from the given 
    *         translation group.
@@ -483,7 +515,11 @@ namespace Isis {
    * Retrieves a string containing the value of the OutputName 
    * keyword for the translation group with the given name. 
    *  
-   * @param translationGroupName The name of the PVL translation group.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    * 
    * @return @b QString The value of the OutputName keyword from 
    *         the given translation group.
@@ -504,7 +540,11 @@ namespace Isis {
    *  
    * @see PvlObject::findGroup() 
    *  
-   * @param translationGroupName Name of the PVL group to search for.
+   * @param translationGroupName The name of the PVL translation 
+   *                             group used to identify the
+   *                             input/output keywords to be
+   *                             translated. Often, this is the
+   *                             same as the output keyword name.
    * 
    * @return const PvlGroup& The first PVL group with the given name.
    *  
diff --git a/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp b/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp
index ceb4e7cd1095eeaf2249baea31a7782b1df1ea9a..a7cebd130f3cf70bcea0fde53eb82015c6923e3a 100644
--- a/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp
+++ b/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp
@@ -149,7 +149,7 @@ namespace Isis {
     p_timeBias = rotToCopy.p_timeBias;
 
     p_et = rotToCopy.p_et;
-    p_quaternion = rotToCopy.p_quaternion; 
+    p_quaternion = rotToCopy.p_quaternion;
     p_matrixSet = rotToCopy.p_matrixSet;
     p_source = rotToCopy.p_source;
     p_axisP = rotToCopy.p_axisP;
@@ -159,8 +159,8 @@ namespace Isis {
     p_timeScale = rotToCopy.p_timeScale;
     p_degreeApplied = rotToCopy.p_degreeApplied;
 
-//    for (std::vector<double>::size_type i = 0; i < rotToCopy.p_coefficients[0].size(); i++) 
-    for (int i = 0; i < 3; i++) 
+//    for (std::vector<double>::size_type i = 0; i < rotToCopy.p_coefficients[0].size(); i++)
+    for (int i = 0; i < 3; i++)
       p_coefficients[i] = rotToCopy.p_coefficients[i];
 
     p_noOverride = rotToCopy.p_noOverride;
@@ -180,43 +180,43 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Destructor for SpiceRotation object.
-   */ 
-  SpiceRotation::~SpiceRotation() { 
+   */
+  SpiceRotation::~SpiceRotation() {
   }
 
 
-  /** 
+  /**
    * Change the frame to the given frame code.  This method has no effect if
-   * spice is cached. 
+   * spice is cached.
    *
-   * @param frameCode The integer-valued frame code 
-   */ 
+   * @param frameCode The integer-valued frame code
+   */
   void SpiceRotation::SetFrame(int frameCode) {
     p_constantFrames[0] = frameCode;
   }
 
 
-  /** 
-   * Accessor method that returns the frame code. This is the first value of the 
-   * constant frames member variable. 
-   *  
-   * @return @b int An integer value indicating the frame code. 
-   */ 
+  /**
+   * Accessor method that returns the frame code. This is the first value of the
+   * constant frames member variable.
+   *
+   * @return @b int An integer value indicating the frame code.
+   */
   int SpiceRotation::Frame() {
     return p_constantFrames[0];
   }
 
 
-  /** 
+  /**
    * Apply a time bias when invoking SetEphemerisTime method.
    *
    * The bias is used only when reading from NAIF kernels.  It is added to the
    * ephermeris time passed into SetEphemerisTime and then the body
    * position is read from the NAIF kernels and returned.  When the cache
-   * is loaded from a table the bias is ignored as it is assumed to have 
-   * already been applied.  If this method is never called the default bias is 
+   * is loaded from a table the bias is ignored as it is assumed to have
+   * already been applied.  If this method is never called the default bias is
    * 0.0 seconds.
    *
    * @param timeBias time bias in seconds
@@ -226,7 +226,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the J2000 to reference frame quaternion at given time.
    *
    * This method returns the J2000 to reference frame rotational matrix at a
@@ -280,11 +280,11 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Accessor method to get current ephemeris time.
    *
    * @return @b double The current ephemeris time.
-   */ 
+   */
   double SpiceRotation::EphemerisTime() const {
     return p_et;
   }
@@ -301,16 +301,16 @@ namespace Isis {
 
 
   /**
-   * Set the downsize status to minimize cache. 
+   * Set the downsize status to minimize cache.
    *
-   * @param status The DownsizeStatus enumeration value. 
-   */ 
+   * @param status The DownsizeStatus enumeration value.
+   */
   void SpiceRotation::MinimizeCache(DownsizeStatus status) {
     p_minimizeCache = status;
   }
 
 
-  /** 
+  /**
    * Cache J2000 rotation quaternion over a time range.
    *
    * This method will load an internal cache with frames over a time
@@ -384,7 +384,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Cache J2000 to frame rotation for a time.
    *
    * This method will load an internal cache with a rotation for a single
@@ -402,7 +402,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Cache J2000 rotations using a table file.
    *
    * This method will load either an internal cache with rotations (quaternions)
@@ -423,7 +423,7 @@ namespace Isis {
    * @param table   An ISIS table blob containing valid J2000 to reference
    *                quaternion/time values
    *
-   * @throws IException::Programmer "Expecting either three, five, or eight fields in the 
+   * @throws IException::Programmer "Expecting either three, five, or eight fields in the
    *                                 SpiceRotation table"
    */
   void SpiceRotation::LoadCache(Table &table) {
@@ -476,7 +476,7 @@ namespace Isis {
       p_fullCacheSize = toInt(table.Label().findKeyword("CkTableOriginalSize")[0]);
     }
 
-    // Load FrameTypeCode from labels if available and the planetary constants keywords 
+    // Load FrameTypeCode from labels if available and the planetary constants keywords
     if (table.Label().hasKeyword("FrameTypeCode")) {
       m_frameType = (FrameType) toInt(table.Label().findKeyword("FrameTypeCode")[0]);
     }
@@ -582,7 +582,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Cache J2000 rotation over existing cached time range using polynomials
    *
    * This method will reload an internal cache with matrices
@@ -601,7 +601,7 @@ namespace Isis {
       p_cacheTime.clear();
       p_cache.clear();
 
-      // Clear the angular velocity cache if we can calculate it instead.  It can't be calculated 
+      // Clear the angular velocity cache if we can calculate it instead.  It can't be calculated
       //  for functions of degree 0 (framing cameras), so keep the original av.  It is better than
       //  nothing.
       if (p_degree > 0 && p_cacheAv.size() > 1)  p_cacheAv.clear();
@@ -644,7 +644,7 @@ namespace Isis {
         if (p_hasAngularVelocity) p_cacheAv.push_back(tempRot.AngularVelocity());
       }
     }
-    else { //(p_source < PolyFunction) 
+    else { //(p_source < PolyFunction)
       QString msg = "The SpiceRotation has not yet been fit to a function";
       throw IException(IException::Programmer, msg, _FILEINFO_);
     }
@@ -657,7 +657,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return a table with J2000 to reference rotations.
    *
    * Return a table containing the cached pointing with the given
@@ -668,7 +668,7 @@ namespace Isis {
    *
    * @throws IException::Programmer "Only cached rotations can be returned as a line cache of
    *                                 quaternions and time"
-   * 
+   *
    * @return @b Table Table with given name that contains the cached pointing
    */
   Table SpiceRotation::LineCache(const QString &tableName) {
@@ -685,7 +685,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return a table with J2000 to reference rotations.
    *
    * Return a table containing the cached pointing with the given
@@ -703,7 +703,7 @@ namespace Isis {
    * @param tableName    Name of the table to create and return
    *
    * @throws IException::Programmer "To create table source of data must be either Memcache or
-   *                                 PolyFunction" 
+   *                                 PolyFunction"
    *
    * @return @b Table Table with given name that contains the cached pointing
    */
@@ -812,8 +812,8 @@ namespace Isis {
   }
 
 
-  /** 
-   * Initialize planetary orientation constants from Spice PCK 
+  /**
+   * Initialize planetary orientation constants from Spice PCK
    *
    * Retrieve planetary orientation constants from a Spice PCK and store them in the class.
    *
@@ -825,12 +825,12 @@ namespace Isis {
 
     // Retrieve the frame class from Naif.  We distinguish PCK types into text PCK,
     // binary PCK, and PCK not referenced to J2000.  Isis binary PCK can
-    // not be used to solve for target body orientation because of the variety and 
+    // not be used to solve for target body orientation because of the variety and
     // complexity models used with binary PCK.  Currently ISIS does not solve for
     // target body orientation on bodies not referenced to J2000, but it could be
     // changed to handle that case.
     checkForBinaryPck();
-    
+
     if (m_frameType == PCK) {
       // Make sure the reference frame is J2000.  We will need to modify FrameTrace and
       // the pck methods in this class to handle this case.  At the time this method was
@@ -848,13 +848,13 @@ namespace Isis {
       if (found) {
         // Go get the frame name if it is not the default J2000
         SpiceDouble relativeFrameCode;
-        bodvcd_c(centerBodyCode, "CONSTANTS_REF_FRAME", 1, 
+        bodvcd_c(centerBodyCode, "CONSTANTS_REF_FRAME", 1,
                         &numReturned, &relativeFrameCode);
-      } 
+      }
 
       if (!found || relativeFrameCode == 1) {  // We only work with J2000 relative frames for now
 
-        // Make sure the standard coefficients are available for the body code by 
+        // Make sure the standard coefficients are available for the body code by
         // checking for ra
         naifKeyword = "BODY" + toString(centerBodyCode) + "_POLE_RA" ;
         dtpool_c(naifKeyword.toLatin1().data(), &found, &numExpected, &naifType);
@@ -899,7 +899,7 @@ namespace Isis {
             m_raNutPrec.resize(numExpected, 0.);
             m_decNutPrec.resize(numExpected, 0.);
             m_pmNutPrec.resize(numExpected, 0.);
-            
+
             std::vector<SpiceDouble> angles(numExpected);
             bodvcd_c(centerBodyCode, "NUT_PREC_RA", numExpected,  &numReturned, &m_raNutPrec[0]);
             bodvcd_c(centerBodyCode, "NUT_PREC_DEC", numExpected,  &numReturned, &m_decNutPrec[0]);
@@ -924,7 +924,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Initialize planetary orientation constants from an cube body rotation label
    *
    * Retrieve planetary orientation constants from a cube body rotation label if they are present.
@@ -998,12 +998,12 @@ namespace Isis {
         m_sysNutPrec1.push_back(Angle(toDouble(labelCoeffs[i]), Angle::Degrees));
       }
     }
- 
+
     NaifStatus::CheckErrors();
   }
 
 
-  /** 
+  /**
    * Add labels to a SpiceRotation table.
    *
    * Return a table containing the labels defining the rotation.
@@ -1052,7 +1052,7 @@ namespace Isis {
 
  // Begin section added 06-20-2015 DAC
     table.Label() += PvlKeyword("FrameTypeCode");
-    table.Label()["FrameTypeCode"].addValue(toString(m_frameType)); 
+    table.Label()["FrameTypeCode"].addValue(toString(m_frameType));
 
     if (m_frameType == PCK) {
       // Write out all the body orientation constants
@@ -1113,7 +1113,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the camera angles at the center time of the observation
    *
    * @return @b vector<double> Camera angles at center time
@@ -1127,9 +1127,9 @@ namespace Isis {
   }
 
 
-  /** 
-   * Return the camera angles (right ascension, declination, and twist) for the 
-   * time-based matrix CJ 
+  /**
+   * Return the camera angles (right ascension, declination, and twist) for the
+   * time-based matrix CJ
    *
    * @param axis3 The rotation axis for the third angle
    * @param axis2 The rotation axis for the second angle
@@ -1154,8 +1154,8 @@ namespace Isis {
 
 
 
-  /** 
-   * Set the rotation angles (phi, delta, and w) for the current time to define the 
+  /**
+   * Set the rotation angles (phi, delta, and w) for the current time to define the
    * time-based matrix CJ. This method was created for unitTests and should not
    * be used otherwise.  It only works for cached data with a cache size of 1.
    *
@@ -1167,54 +1167,54 @@ namespace Isis {
   void SpiceRotation::SetAngles(std::vector<double> angles, int axis3, int axis2, int axis1) {
     eul2m_c(angles[2], angles[1], angles[0], axis3, axis2, axis1, (SpiceDouble (*)[3]) &(p_CJ[0]));
     p_cache[0] = p_CJ;
-    // Reset to get the new values 
+    // Reset to get the new values
     p_et = -DBL_MAX;
     SetEphemerisTime(p_et);
   }
 
 
-  /** 
-   * Accessor method to get the angular velocity 
+  /**
+   * Accessor method to get the angular velocity
    *
    * @return @b vector<double> Angular velocity
-   */ 
+   */
   std::vector<double> SpiceRotation::AngularVelocity() {
     return p_av;
   }
 
 
-  /** 
-   * Accessor method to get the frame chain for the constant part of the 
-   * rotation (ends in target) 
+  /**
+   * Accessor method to get the frame chain for the constant part of the
+   * rotation (ends in target)
    *
-   * @return @b vector<int> The frame chain for the constant part of the rotation. 
-   */ 
+   * @return @b vector<int> The frame chain for the constant part of the rotation.
+   */
   std::vector<int> SpiceRotation::ConstantFrameChain() {
     return p_constantFrames;
   }
 
 
-  /** 
+  /**
    * Accessor method to get the frame chain for the rotation (begins in J2000).
-   * 
+   *
    * @return @b vector<int> The frame chain for the rotation.
-   */ 
+   */
   std::vector<int> SpiceRotation::TimeFrameChain() {
     return p_timeFrames;
   }
 
 
-  /** 
-   * Checks whether the rotation has angular velocities.  
+  /**
+   * Checks whether the rotation has angular velocities.
    *
    * @return @b bool Indicates whether the rotation has angular velocities.
-   */ 
+   */
   bool SpiceRotation::HasAngularVelocity() {
     return p_hasAngularVelocity;
   }
 
 
-  /** 
+  /**
    * Given a direction vector in the reference frame, return a J2000 direction.
    *
    * @param[in] rVec A direction vector in the reference frame
@@ -1223,7 +1223,7 @@ namespace Isis {
    */
   std::vector<double> SpiceRotation::J2000Vector(const std::vector<double> &rVec) {
     NaifStatus::CheckErrors();
-    
+
     std::vector<double> jVec;
 
     if (rVec.size() == 3) {
@@ -1232,7 +1232,7 @@ namespace Isis {
       jVec.resize(3);
       mtxv_c(TJ, (SpiceDouble *) &rVec[0], (SpiceDouble *) &jVec[0]);
     }
-    
+
     else if (rVec.size() == 6) {
       // See Naif routine frmchg for the format of the state matrix.  The constant rotation, TC,
       // has a derivative with respect to time of I.
@@ -1257,7 +1257,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the coefficients used to calculate the target body pole ra
    *
    * Return the coefficients used to calculate the target body right
@@ -1267,7 +1267,7 @@ namespace Isis {
    * right ascension (usually the same as the most recent IAU Report)
    * the trignometric terms to account for nutation/precession need to
    * be added.
-   * 
+   *
    * pole ra = ra0 + ra1*T + ra2*T**2 + sum(racoef[i]i*sin(angle[i]))
    *
    * @return @b vector<double> A vector of length 3 containing the pole ra coefficients
@@ -1277,7 +1277,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the coefficients used to calculate the target body pole dec
    *
    * Return the coefficients used to calculate the target body declination
@@ -1287,7 +1287,7 @@ namespace Isis {
    * declination (usually the same as the most recent IAU Report)
    * the trignometric terms to account for nutation/precession need to
    * be added.
-   * 
+   *
    * pole dec = dec0 + dec1*T + dec2*T**2 + sum(racoef[i]i*sin(angle[i]))
    *
    * @return @b vector<double> A vector of length 3 containing the pole declination coefficients.
@@ -1297,16 +1297,16 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the coefficients used to calculate the target body prime meridian
    *
    * Return the coefficients used to calculate the target body prime
    * meridian without nutation/precession.  The model is a standard
-   * quadratic polynomial in time in days from the standard epoch 
+   * quadratic polynomial in time in days from the standard epoch
    * (usually J2000).  To match the Naif PCK prime meridian, (usually
    * the same as the most recent IAU Report) the trignometric terms
    * to account for nutation/precession need to be added.
-   * 
+   *
    * pm = pm0 + pm1*d + pm2*d**2 + sum(pmcoef[i]i*sin(angle[i]))
    *
    * @return @b vector<double> A vector of length 3 containing the prime meridian coefficients.
@@ -1316,7 +1316,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the coefficients used to calculate the target body pole ra nut/prec coefficients
    *
    * Return the coefficients used to calculate the target body right
@@ -1324,7 +1324,7 @@ namespace Isis {
    * sum of the products of the coefficients returned by this method
    * with the sin of the corresponding angles associated with the
    * barycenter related to the target body.
-   * 
+   *
    * pole ra = ra0 + ra1*T + ra2*T**2 + sum(raCoef[i]i*sin(angle[i]))
    *
    * @return @b vector<double> A vector containing the pole ra nut/prec coefficients.
@@ -1334,14 +1334,14 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the coefficients used to calculate the target body pole dec nut/prec coefficients
    *
    * Return the coefficients used to calculate the target body declination
-   * nutation/precession contribution.  The model is the sum of the products 
-   * of the coefficients returned by this method with the sin of the corresponding 
+   * nutation/precession contribution.  The model is the sum of the products
+   * of the coefficients returned by this method with the sin of the corresponding
    * angles associated with the barycenter related to the target body.
-   * 
+   *
    * pole dec = dec0 + dec1*T + dec2*T**2 + sum(decCoef[i]i*sin(angle[i]))
    *
    * @return @b vector<double> A vector containing the pole dec nut/prec coeffcients.
@@ -1351,14 +1351,14 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the coefficients used to calculate the target body pm nut/prec coefficients
    *
    * Return the coefficients used to calculate the target body prime meridian
-   * nutation/precession contribution.  The model is the sum of the products 
-   * of the coefficients returned by this method with the sin of the corresponding 
+   * nutation/precession contribution.  The model is the sum of the products
+   * of the coefficients returned by this method with the sin of the corresponding
    * angles associated with the barycenter related to the target body.
-   * 
+   *
    * prime meridian = pm0 + pm1*T + pm2*d**2 + sum(pmCoef[i]i*sin(angle[i]))
    *
    * @return @b vector<double> A vector containing the pm nut/prec coeffcients.
@@ -1368,14 +1368,14 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the constants used to calculate the target body system nut/prec angles
    *
    * Return the constant terms used to calculate the target body system (barycenter)
    * nutation/precession angles (periods).  The model for the angles is linear in
-   * time in Julian centuries since the standard epoch (usually J2000). 
+   * time in Julian centuries since the standard epoch (usually J2000).
    * angles associated with the barycenter related to the target body.
-   *  
+   *
    * angle[i] = constant[i] + coef[i]*T
    *
    * @return @b vector<Angle> A vector containing the system nut/prec constant terms.
@@ -1385,15 +1385,15 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the coefficients used to calculate the target body system nut/prec angles
    *
-   * Return the linear coefficients used to calculate the target body system 
-   * (barycenter) nutation/precession angles (periods).  The model for the 
-   * angles is linear in time in Julian centuries since the standard epoch 
-   * (usually J2000). angles associated with the barycenter related to the 
+   * Return the linear coefficients used to calculate the target body system
+   * (barycenter) nutation/precession angles (periods).  The model for the
+   * angles is linear in time in Julian centuries since the standard epoch
+   * (usually J2000). angles associated with the barycenter related to the
    * target body.
-   *  
+   *
    * angle[i] = constant[i] + coef[i]*T
    *
    * @return @b vector<Angle> A vector containing the system nut/prec linear coefficients.
@@ -1403,9 +1403,9 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Given a direction vector in the reference frame, compute the derivative
-   * with respect to one of the coefficients in the angle polynomial fit 
+   * with respect to one of the coefficients in the angle polynomial fit
    * equation of a vector rotated from the reference frame to J2000.
    * TODO - merge this method with ToReferencePartial
    *
@@ -1416,14 +1416,14 @@ namespace Isis {
    * @throws IException::User "Body rotation uses a binary PCK. Solutions for this model are not
    *                           supported"
    * @throws IException::User "Body rotation uses a PCK not referenced to J2000. Solutions for this
-   *                           model are not supported" 
+   *                           model are not supported"
    * @throws IException::User "Solutions are not supported for this frame type."
    *
-   * @return @b vector<double>   A direction vector rotated by derivative 
+   * @return @b vector<double>   A direction vector rotated by derivative
    *                             of reference to J2000 rotation.
    */
-  std::vector<double> SpiceRotation::toJ2000Partial(const std::vector<double> &lookT, 
-                                                    SpiceRotation::PartialType partialVar, 
+  std::vector<double> SpiceRotation::toJ2000Partial(const std::vector<double> &lookT,
+                                                    SpiceRotation::PartialType partialVar,
                                                     int coeffIndex) {
     NaifStatus::CheckErrors();
 
@@ -1459,7 +1459,7 @@ namespace Isis {
        break;
      case NOTJ2000PCK:
        msg = "Body rotation uses a PCK not referenced to J2000. "
-             "Solutions for this model are not supported";    
+             "Solutions for this model are not supported";
        throw IException(IException::User, msg, _FILEINFO_);
        break;
      default:
@@ -1497,7 +1497,7 @@ namespace Isis {
     double dTJ[3][3];
     mxm_c((SpiceDouble *) &p_TC[0], dCJ[0], dTJ);
 
-    // Finally rotate the target vector with the transpose of the 
+    // Finally rotate the target vector with the transpose of the
     // derivative matrix, dTJ to get a J2000 vector
     std::vector<double> lookdJ(3);
 
@@ -1508,7 +1508,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Given a direction vector in J2000, return a reference frame direction.
    *
    * @param[in] jVec A direction vector in J2000
@@ -1543,7 +1543,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Set the coefficients of a polynomial fit to each
    * of the three camera angles for the time period covered by the
    * cache, angle = a + bt + ct**2, where t = (time - p_baseTime)/ p_timeScale.
@@ -1691,7 +1691,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Set the coefficients of a polynomial fit to each of the
    * three camera angles for the time period covered by the
    * cache, angle = c0 + c1*t + c2*t**2 + ... + cn*t**n,
@@ -1745,10 +1745,10 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Set the coefficients of a polynomial fit to each
    * of the three planet angles for the time period covered by the
-   * cache, ra = ra0 + ra1*t + ra2*t**2 + raTrig, 
+   * cache, ra = ra0 + ra1*t + ra2*t**2 + raTrig,
    *            dec = dec0 + dec1*t + dec2*t**2 + decTrig,
    *            pm = pm0 + pm1*d + pm2*t**2 + pmTrig,
    * where t = time / (seconds per day). for time = et
@@ -1764,7 +1764,7 @@ namespace Isis {
    */
   void SpiceRotation::usePckPolynomial() {
 
-    // Check to see if rotation is already stored as a polynomial 
+    // Check to see if rotation is already stored as a polynomial
     if (p_source == PckPolyFunction) {
       p_hasAngularVelocity = true;
       return;
@@ -1780,7 +1780,7 @@ namespace Isis {
     // Set the scales
     p_dscale =  0.000011574074074;   // seconds to days conversion
     p_tscale = 3.1688087814029D-10; // seconds to Julian centuries conversion
-    //Set the quadratic part of the equations  
+    //Set the quadratic part of the equations
     //TODO consider just hard coding this part in evaluate
     Isis::PolynomialUnivariate functionRa(p_degree);  // Basis function fit to target body pole ra
     Isis::PolynomialUnivariate functionDec(p_degree);  // Basis function fit to target body pole dec
@@ -1793,7 +1793,7 @@ namespace Isis {
 
     int numNutPrec = p_sysNutPrec0.size;
     if (numNutPrec > 0) {
-      // Set the trigonometric part of the equation 
+      // Set the trigonometric part of the equation
       Isis::TrigBasis functionRaNutPrec("raNutPrec", Isis::TrigBasis::Sin, numNutPrec);
       Isis::TrigBasis functionRaNutPrec("decNutPrec", Isis::TrigBasis::Cos, numNutPrec);
       Isis::TrigBasis functionRaNutPrec("pmNutPrec", Isis::TrigBasis::Sin, numNutPrec);
@@ -1811,9 +1811,9 @@ namespace Isis {
     */
 
     // Set the flag indicating p_degree has been applied to the planet angles, the
-    // coefficients of the polynomials have been saved, and the cache reloaded from  
+    // coefficients of the polynomials have been saved, and the cache reloaded from
     // TODO cache reloaded???
-    // the polynomials.  
+    // the polynomials.
     // ****At least for the planet angles, I don't think we want to reload the cache until just
     // before we write out the table
     p_degreeApplied = true;
@@ -1823,10 +1823,10 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Set the coefficients of a polynomial fit to each
    * of the three planet angles for the time period covered by the
-   * cache, ra = ra0 + ra1*t + ra2*t**2 + raTrig, 
+   * cache, ra = ra0 + ra1*t + ra2*t**2 + raTrig,
    *            dec = dec0 + dec1*t + dec2*t**2 + decTrig,
    *            pm = pm0 + pm1*d + pm2*t**2 + pmTrig,
    * where t = time / (seconds per day). for time = et
@@ -1853,7 +1853,7 @@ namespace Isis {
     // Apply new function parameters
     setEphemerisTimePckPolyFunction();
   }
-                               
+
 
   /**
    * Return the coefficients of a polynomial fit to each of the
@@ -1939,7 +1939,7 @@ namespace Isis {
    *
    * @param coeffIndex The index of the coefficient to differentiate
    *
-   * @throws IException::Programmer "Unable to evaluate the derivative of the SPICE rotation fit 
+   * @throws IException::Programmer "Unable to evaluate the derivative of the SPICE rotation fit
    *                                 polynomial for the given coefficient index. Index is negative
    *                                 or exceeds degree of polynomial"
    *
@@ -1974,7 +1974,7 @@ namespace Isis {
    * @param partialVar Variable derivative is to be with respect to
    * @param coeffIndex The index of the coefficient to differentiate
    *
-   * @throws IException::Programmer "Unable to evaluate the derivative of the SPICE rotation fit 
+   * @throws IException::Programmer "Unable to evaluate the derivative of the SPICE rotation fit
    *                                 polynomial for the given coefficient index. Index is negative
    *                                 or exceeds degree of polynomial"
    *
@@ -1983,7 +1983,7 @@ namespace Isis {
   double SpiceRotation::DPckPolynomial(SpiceRotation::PartialType partialVar,
                                        const int coeffIndex) {
     const double p_dayScale = 86400; // number of seconds in a day
- // Number of 24 hour days in a Julian century = 36525    
+ // Number of 24 hour days in a Julian century = 36525
     const double p_centScale = p_dayScale * 36525;
     double time = 0.;
 
@@ -2104,7 +2104,7 @@ namespace Isis {
     double dTJ[3][3];
     mxm_c((SpiceDouble *) &p_TC[0], dCJ[0], dTJ);
 
-    // Finally rotate the J2000 vector with the derivative matrix, dTJ to 
+    // Finally rotate the J2000 vector with the derivative matrix, dTJ to
     // get the vector in the targeted reference frame.
     std::vector<double> lookdT(3);
 
@@ -2115,7 +2115,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Wrap the input angle to keep it within 2pi radians of the angle to compare.
    *
    * @param[in]  compareAngle Look vector in J2000 frame
@@ -2139,7 +2139,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Set the degree of the polynomials to be fit to the
    * three camera angles for the time period covered by the
    * cache, angle = c0 + c1*t + c2*t**2 + ... + cn*t**n,
@@ -2195,8 +2195,8 @@ namespace Isis {
   }
 
 
-  /** 
-   * Accessor method to get the rotation frame type. 
+  /**
+   * Accessor method to get the rotation frame type.
    *
    * @return @b SpiceRotation::FrameType The frame type of the rotation.
    */
@@ -2205,8 +2205,8 @@ namespace Isis {
   }
 
 
-  /** 
-   * Accessor method to get the rotation source. 
+  /**
+   * Accessor method to get the rotation source.
    *
    * @return @b SpiceRotation::Source The source of the rotation.
    */
@@ -2216,9 +2216,9 @@ namespace Isis {
 
 
   /**
-   * Resets the source of the rotation to the given value. 
+   * Resets the source of the rotation to the given value.
    *
-   * @param source The rotation source to be set.  
+   * @param source The rotation source to be set.
    */
   void SpiceRotation::SetSource(Source source) {
     p_source = source;
@@ -2227,7 +2227,7 @@ namespace Isis {
 
 
   /**
-   * Accessor method to get the rotation base time. 
+   * Accessor method to get the rotation base time.
    *
    * @return @b double The base time for the rotation.
    */
@@ -2237,7 +2237,7 @@ namespace Isis {
 
 
   /**
-   * Accessor method to get the rotation time scale. 
+   * Accessor method to get the rotation time scale.
    *
    * @return @b double The time scale for the rotation.
    */
@@ -2246,7 +2246,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Set the axes of rotation for decomposition of a rotation
    * matrix into 3 angles.
    *
@@ -2269,15 +2269,15 @@ namespace Isis {
   }
 
 
-  /** 
-   * Load the time cache.  This method should works with the LoadCache(startTime, endTime, size) 
+  /**
+   * Load the time cache.  This method should works with the LoadCache(startTime, endTime, size)
    * method to load the time cache.
    *
    * @throws IException::Programmer "Full cache size does NOT match cache size in LoadTimeCache --
    *                                 should never happen"
-   * @throws IException::Programmer "Observation crosses segment boundary--unable to interpolate 
+   * @throws IException::Programmer "Observation crosses segment boundary--unable to interpolate
    *                                 pointing"
-   * @throws IException::User "No camera kernels loaded...Unable to determine time cache to 
+   * @throws IException::User "No camera kernels loaded...Unable to determine time cache to
    *                           downsize"
    */
   void SpiceRotation::LoadTimeCache() {
@@ -2311,7 +2311,7 @@ namespace Isis {
       SpiceDouble quats[p_fullCacheSize][4];
       double avvs[p_fullCacheSize][3];// Angular velocity vector
 
-      // We will treat et as the sclock time and avoid converting back and forth 
+      // We will treat et as the sclock time and avoid converting back and forth
      for (int r = 0; r < p_fullCacheSize; r++) {
         timeSclkdp[r] = p_cacheTime[r];
         SpiceDouble CJ[9] = { p_cache[r][0], p_cache[r][1], p_cache[r][2],
@@ -2332,7 +2332,7 @@ namespace Isis {
       SpiceInt intarr[p_fullCacheSize]; // Integer work array
       SpiceInt sizOut = p_fullCacheSize; // Size of downsized cache
 
-      ck3sdn(radTol, avflag, (int *) &sizOut, timeSclkdp, (doublereal *) quats, 
+      ck3sdn(radTol, avflag, (int *) &sizOut, timeSclkdp, (doublereal *) quats,
              (SpiceDouble *) avvs, nints, &cubeStarts, dparr, (int *) intarr);
 
       // Clear full cache and load with downsized version
@@ -2398,7 +2398,7 @@ namespace Isis {
 
         // Don't read type 5 ck here
         if (ic[2] == 5) break;
-//      
+//
         // Check times for type 3 ck segment if spacecraft matches
         if (ic[0] == spCode && ic[2] == 3) {
           sct2e_c((int) spCode / 1000, dc[0], &segStartEt);
@@ -2409,7 +2409,7 @@ namespace Isis {
           // Get times for this segment
           if (currentTime >= segStartEt  &&  currentTime <= segStopEt) {
 
-            // Check for a gap in the time coverage by making sure the time span of the observation 
+            // Check for a gap in the time coverage by making sure the time span of the observation
             //  does not cross a segment unless the next segment starts where the current one ends
             if (observationSpansToNextSegment && currentTime > segStartEt) {
               QString msg = "Observation crosses segment boundary--unable to interpolate pointing";
@@ -2476,7 +2476,7 @@ namespace Isis {
       throw IException(IException::User, msg, _FILEINFO_);
     }
 
-    // Load times according to cache size (body rotations) -- handle first round of type 5 ck case 
+    // Load times according to cache size (body rotations) -- handle first round of type 5 ck case
     //   and multiple ck case --Load a time for every line scan line and downsize later
     if (!timeLoaded) {
       double cacheSlope = 0.0;
@@ -2490,7 +2490,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return full listing (cache) of original time coverage requested.
    *
    * @throws IException::User "Time cache not availabe -- rerun spiceinit"
@@ -2518,7 +2518,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Compute frame trace chain from target frame to J2000
    *
    * @param et Ephemeris time
@@ -2611,7 +2611,7 @@ namespace Isis {
 
       else {
         QString msg = "The frame " + toString(frameCodes[frmidx]) +
-            " has a type " + toString(type) + " not supported by your version of Naif Spicelib." 
+            " has a type " + toString(type) + " not supported by your version of Naif Spicelib."
             + "You need to update.";
         throw IException(IException::Programmer, msg, _FILEINFO_);
 
@@ -2649,7 +2649,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the full rotation TJ as a matrix
    *
    * @return @b vector<double> Returned matrix.
@@ -2664,9 +2664,9 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the constant 3x3 rotation TC matrix as a quaternion.
-   *  
+   *
    * @return @b vector<double> Constant rotation quaternion, TC.
    */
   std::vector<double> SpiceRotation::ConstantRotation() {
@@ -2679,9 +2679,9 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return the constant 3x3 rotation TC matrix as a vector of length 9.
-   *  
+   *
    * @return @b vector<double> Constant rotation matrix, TC.
    */
   std::vector<double> &SpiceRotation::ConstantMatrix() {
@@ -2689,9 +2689,9 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Set the constant 3x3 rotation TC matrix from a vector of length 9.
-   *  
+   *
    * @param constantMatrix Constant rotation matrix, TC.
    */
   void SpiceRotation::SetConstantMatrix(std::vector<double> constantMatrix) {
@@ -2699,9 +2699,9 @@ namespace Isis {
     return;
   }
 
-  /** 
+  /**
    * Return time-based 3x3 rotation CJ matrix as a quaternion.
-   *  
+   *
    * @return @b vector<double> Time-based rotation quaternion, CJ.
    */
   std::vector<double> SpiceRotation::TimeBasedRotation() {
@@ -2714,9 +2714,9 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Return time-based 3x3 rotation CJ matrix as a vector of length 9.
-   *  
+   *
    * @return @b vector<double> Time-based rotation matrix, CJ.
    */
   std::vector<double> &SpiceRotation::TimeBasedMatrix() {
@@ -2724,9 +2724,9 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Set the time-based 3x3 rotation CJ matrix from a vector of length 9.
-   *  
+   *
    * @param timeBasedMatrix Time-based rotation matrix, TC.
    */
   void SpiceRotation::SetTimeBasedMatrix(std::vector<double> timeBasedMatrix) {
@@ -2735,7 +2735,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Initialize the constant rotation
    *
    * @param et Ephemeris time.
@@ -2752,7 +2752,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Compute the angular velocity from the time-based functions fit to the pointing angles
    * This method computes omega = angular velocity matrix, and extracts the angular velocity.
    * See comments in the Naif Spicelib routine xf2rav_c.c.
@@ -2810,7 +2810,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Compute the derivative of the 3x3 rotation matrix CJ with respect to time.
    * The derivative is computed based on p_CJ (J2000 to first constant frame).
    *
@@ -2877,7 +2877,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Compute & return the rotation matrix that rotates vectors from J2000 to the targeted frame.
    *
    * @return @b vector<double> Returned rotation matrix.
@@ -2900,7 +2900,7 @@ namespace Isis {
       for (int col = 0; col < 3; col++) {
         jcol  =  col + 3;
         // Fill the upper left corner
-        stateTJ[irow*6 + col] = p_TC[vpos] * stateCJ[0][col] + p_TC[vpos+1] * stateCJ[1][col] 
+        stateTJ[irow*6 + col] = p_TC[vpos] * stateCJ[0][col] + p_TC[vpos+1] * stateCJ[1][col]
                                               + p_TC[vpos+2] * stateCJ[2][col];
         // Fill the lower left corner
         stateTJ[row*6 + col]  =  p_TC[vpos] * stateCJ[3][col] + p_TC[vpos+1] * stateCJ[4][col]
@@ -2915,7 +2915,7 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
    * Extrapolate pointing for a given time assuming a constant angular velocity.
    * The pointing and angular velocity at the current time will be used to
    * extrapolate pointing at the input time.  If angular velocity does not
@@ -2934,7 +2934,7 @@ namespace Isis {
     std::vector<double> CJ(9, 0.0);
     double dmat[3][3];
 
-    // Create a rotation matrix for the axis and magnitude of the angular velocity multiplied by  
+    // Create a rotation matrix for the axis and magnitude of the angular velocity multiplied by
     //   the time difference
     axisar_c((SpiceDouble *) &p_av[0], diffTime*vnorm_c((SpiceDouble *) &p_av[0]), dmat);
 
@@ -2945,7 +2945,7 @@ namespace Isis {
    }
 
 
-   /** 
+   /**
     * Set the full cache time parameters.
     *
     * @param[in]   startTime The earliest time of the full cache coverage
@@ -2960,7 +2960,7 @@ namespace Isis {
    }
 
 
-  /** 
+  /**
    * Check loaded pck to see if any are binary and set frame type to indicate binary pck.
    *
    * This is strictly a local method to be called only when the source is Spice.  Its purpose is
@@ -2971,7 +2971,7 @@ namespace Isis {
     // Get a count of all the loaded kernels
     SpiceInt count;
     ktotal_c("PCK", &count);
-    
+
     // Define some Naif constants
     int FILESIZ = 128;
     int TYPESIZ = 32;
@@ -2981,7 +2981,7 @@ namespace Isis {
     SpiceChar source[SOURCESIZ];
     SpiceInt handle;
     SpiceBoolean found;
-       
+
     // Get the name of each loaded kernel.  The accuracy of this test depends on the use of the
     // "bpc" suffix to name a binary pck.  If a binary bpc does not have the "bpc" suffix, it will not
     // be found by this test.  This test was suggested by Boris Semenov at Naif.
@@ -2994,9 +2994,9 @@ namespace Isis {
       }
     }
   }
-  
 
-  /** 
+
+  /**
    * Set the frame type (m_frameType).
    *
    * This is strictly a local method to be called only when the source is Spice.  Its purpose is
@@ -3012,7 +3012,7 @@ namespace Isis {
     frinfo_c(frameCode, &centerBodyCode, &frameClass, &classId, &found);
 
     if (found) {
-      if (frameClass == 2  ||  centerBodyCode > 0) {
+      if (frameClass == 2  ||  (centerBodyCode > 0 && frameClass != 3)) {
         m_frameType = PCK;
         // Load the PC information while it is available and set member values
         loadPCFromSpice(centerBodyCode);
@@ -3043,7 +3043,7 @@ namespace Isis {
           m_frameType = UNKNOWN;
         }
       }
-    }      
+    }
   }
 
 
@@ -3102,7 +3102,7 @@ namespace Isis {
       SpiceDouble delta[3][3];
       axisar_c(axis, angle * (SpiceDouble)mult, delta);
       mxmt_c((SpiceDouble *) &CJ1[0], delta, (SpiceDouble( *) [3]) &p_CJ[0]);
- 
+
       if (p_hasAngularVelocity) {
         double v1[3], v2[3]; // Vectors surrounding desired time
         vequ_c((SpiceDouble *) &p_cacheAv[cacheIndex][0], v1);
@@ -3154,7 +3154,7 @@ namespace Isis {
    * When setting the ephemeris time, updates the rotation state based on data read directly
    * from NAIF kernels using NAIF Spice routines
    *
-   * @throws IException::Io "[framecode] is an unrecognized reference frame code. Has the mission 
+   * @throws IException::Io "[framecode] is an unrecognized reference frame code. Has the mission
    *                         frames kernel been loaded?"
    * @throws IException::Io "No pointing is availabe at request time for frame code"
    *
@@ -3294,7 +3294,7 @@ namespace Isis {
 
   /**
    * When setting the ephemeris time, updates the rotation state based on a polynomial fit
-   * over spice kernel data. 
+   * over spice kernel data.
    *
    * @see SpiceRotation::SetEphemerisTime
    */
@@ -3308,7 +3308,7 @@ namespace Isis {
     setEphemerisTimePolyFunction();
     std::vector<double> polyAngles(3);
     // The decomposition fails because the angles are outside the valid range for Naif
-    // polyAngles = Angles(p_axis3, p_axis2, p_axis1); 
+    // polyAngles = Angles(p_axis3, p_axis2, p_axis1);
     polyAngles = EvaluatePolyFunction();
     std::vector<double> polyVelocity(3);
     polyVelocity = p_av;
@@ -3358,14 +3358,14 @@ namespace Isis {
     Angle dra = (m_raPole[1] + 2.*m_raPole[2]*centTime) / secondsPerJulianCentury;
     Angle ddec = (m_decPole[1] + 2.*m_decPole[2]*centTime) / secondsPerJulianCentury;
     Angle dpm = (m_pm[1] + 2.*m_pm[2]*dTime) / 86400;
-    
+
     // Now add the nutation/precession (trig part) adjustment to the expression if any
     int numNutPrec = (int) m_raNutPrec.size();
     Angle theta;
     double dtheta;
     double costheta;
     double sintheta;
-    
+
     for (int ia = 0;  ia < numNutPrec; ia++) {
       theta = m_sysNutPrec0[ia] + m_sysNutPrec1[ia]*centTime;
       dtheta = m_sysNutPrec1[ia].degrees() * DEG2RAD;
@@ -3408,7 +3408,7 @@ namespace Isis {
     SpiceDouble angsDangs[6];
     SpiceDouble BJs[6][6];
     vpack_c(w, delta, phi, angsDangs);
-    vpack_c(dw, ddelta, dphi, &angsDangs[3]); 
+    vpack_c(dw, ddelta, dphi, &angsDangs[3]);
     eul2xf_c (angsDangs, p_axis3, p_axis2, p_axis1, BJs);
 
     // Decompose the state matrix to the rotation and its angular velocity
diff --git a/isis/src/base/objs/SpiceRotation/SpiceRotation.h b/isis/src/base/objs/SpiceRotation/SpiceRotation.h
index 74b842f046b383e2652822decea6b2970c8f11a2..9523b64c1f1a72305a746092e9a1c66ae53a72da 100644
--- a/isis/src/base/objs/SpiceRotation/SpiceRotation.h
+++ b/isis/src/base/objs/SpiceRotation/SpiceRotation.h
@@ -187,31 +187,37 @@ namespace Isis {
    *   @history 2015-02-20 Jeannie Backer - Improved error messages.
    *   @history 2015-07-21 Kristin Berry - Added additional NaifStatus::CheckErrors() calls to see if
    *                           any NAIF errors were signaled. References #2248.
-   *   @history 2015-08-05 Debbie A. Cook - Programmer notes - Modified LoadCache, 
+   *   @history 2015-08-05 Debbie A. Cook - Programmer notes - Modified LoadCache,
    *                           and ComputeAv.
-   *                           Added new methods 
+   *                           Added new methods
    *                           loadPCFromSpice, loadPCFromTable, toJ2000Partial, poleRaCoefs,
-   *                           poleDecCoefs, pmCoefs, poleRaNutPrecCoefs, poleDecNutPrecCoefs, 
+   *                           poleDecCoefs, pmCoefs, poleRaNutPrecCoefs, poleDecNutPrecCoefs,
    *                           pmNutPrecCoefs, sysNutPrecConstants, sysNutPrecCoefs,
    *                           usePckPolynomial, setPckPolynomial(raCoef, decCoef, pmCoef),
    *                           getPckPolynomial, setEphemerisTimePckPolyFunction, getFrameType
-   *                           and members m_frameType, m_tOrientationAvailable, 
+   *                           and members m_frameType, m_tOrientationAvailable,
    *                           m_raPole, m_decPole, m_pm, m_raNutPrec, m_decNutPrec, m_pmNutPrec,
-   *                           m_sysNutPrec0, m_sysNutPrec1, m_dscale, m_Tscale to support request for 
+   *                           m_sysNutPrec0, m_sysNutPrec1, m_dscale, m_Tscale to support request for
    *                           solving for target body parameters.
-   *                           Also added a new enumerated value for Source, PckPolyFunction, 
+   *                           Also added a new enumerated value for Source, PckPolyFunction,
    *                           and PartialType, WRT_RotationRate.
    *   @history 2016-02-15 Debbie A. Cook - Programmer notes - Added private method
-   *                           setFrameType to set the frame type.  It also loads the planetary 
-   *                           constants for a PCK type. 
+   *                           setFrameType to set the frame type.  It also loads the planetary
+   *                           constants for a PCK type.
    *   @history 2016-06-28 Ian Humphrey - Updated documentation and coding standards. Added new
    *                           tests to unit test. Fixes #3972.
    *   @history 2017-12-13 Ken Edmundson - Added "case DYN:" to methods ToReferencePartial and toJ2000Partial. Fixes #5251.
    *                           This problem was found when trying to bundle M3 images that had been spiceinited with nadir
    *                           pointing. The nadir frame is defined as a Dynamic Frame by Naif.
+   *   @history 2018-04-21 Jesse Mapel - Modified frametype resolution to check if a body centered
+   *                           frame uses a CK or PCK definition. This only occurs for bodies
+   *                           where a pck cannot accurately define for the duration of a mission.
+   *                           The current example is the comet 67P/CHURYUMOV-GERASIMENKO
+   *                           imaged by Rosetta. Some future comet/astroid missions are expected
+   *                           to use a CK defined body fixed reference frame. Fixes #5408.
    *
    *  @todo Downsize using Hermite cubic spline and allow Nadir tables to be downsized again.
-   *  @todo Consider making this a base class with child classes based on frame type or 
+   *  @todo Consider making this a base class with child classes based on frame type or
    *              storage type (polynomial, polynomial over cache, cache, etc.)
    */
   class SpiceRotation {
@@ -236,66 +242,66 @@ namespace Isis {
       /**
        * The rotation can come from one of 3 places for an Isis cube.  The class
        * expects function to be after Memcache.
-       *       Spice - the rotation is calculated by Naif Spice routines with data 
+       *       Spice - the rotation is calculated by Naif Spice routines with data
        *                  read directly from Naif kernels.
-       *       Nadir - the rotation is calculated using the Naif routine twovec with 
+       *       Nadir - the rotation is calculated using the Naif routine twovec with
        *                  the position and velocity vectors of the spacecraft.
-       *       Memcache - the rotation is linearly interpolated from time-based 
+       *       Memcache - the rotation is linearly interpolated from time-based
        *                  values in a table.
-       *       PolyFunction - the rotation is calculated from an nth degree 
+       *       PolyFunction - the rotation is calculated from an nth degree
        *                  polynomial in one variable (time in scaled seconds)
        *       PolyFunctionOverSpice - the rotation is calculated from an nth
        *                  degree polynomial fit over the Naif Spice results.
-       *       PckPolyFunction - The rotation is calculated using the IAU fit 
+       *       PckPolyFunction - The rotation is calculated using the IAU fit
        *                  polynomials in one variable (time in Julian centuries and days).
        */
-      enum Source {            
-        Spice,                   //!< Directly from the kernels 
+      enum Source {
+        Spice,                   //!< Directly from the kernels
         Nadir,                   //!< Nadir pointing
         Memcache,                //!< From cached table
         PolyFunction,            //!< From nth degree polynomial
-        PolyFunctionOverSpice ,  //!< Kernels plus nth degree polynomial 
+        PolyFunctionOverSpice ,  //!< Kernels plus nth degree polynomial
         PckPolyFunction          //!< Quadratic polynomial function with linear trignometric terms
-      };            
+      };
 
-      /** 
-       * This enumeration indicates whether the partial derivative is taken with 
-       * respect to Right Ascension, Declination, or Twist (or Rotation). 
-       */ 
-      enum PartialType { 
+      /**
+       * This enumeration indicates whether the partial derivative is taken with
+       * respect to Right Ascension, Declination, or Twist (or Rotation).
+       */
+      enum PartialType {
         WRT_RightAscension, //!< With respect to Right Ascension
         WRT_Declination,    //!< With respect to Declination
         WRT_Twist           //!< With respect to Twist or Prime Meridian Rotation
       };
 
-      /** 
+      /**
        * Status of downsizing the cache
-       */ 
-      enum DownsizeStatus { 
-        Yes,  //!< Downsize the cache 
+       */
+      enum DownsizeStatus {
+        Yes,  //!< Downsize the cache
         Done, //!< Cache is downsized
-        No    //!< Do not downsize the cache 
+        No    //!< Do not downsize the cache
       };
 
-      /** 
-       * Enumeration for the frame type of the rotation  
-       */ 
+      /**
+       * Enumeration for the frame type of the rotation
+       */
       enum FrameType {
         UNKNOWN = 0,      //!< Isis specific code for unknown frame type
-        INERTL = 1,       //!< See Naif Frames.req document for 
+        INERTL = 1,       //!< See Naif Frames.req document for
         PCK  = 2,         //!< definitions
-        CK = 3,           //!< 
-        TK = 4,           //!< 
+        CK = 3,           //!<
+        TK = 4,           //!<
         DYN = 5,          //!<
         BPC = 6,          //!< Isis specific code for binary pck
         NOTJ2000PCK = 7   //!< PCK frame not referenced to J2000
-      };                                   
+      };
 
       void SetEphemerisTime(double et);
       double EphemerisTime() const;
 
       std::vector<double> GetCenterAngles();
-      
+
       std::vector<double> Matrix();
       std::vector<double> AngularVelocity();
 
@@ -422,9 +428,9 @@ namespace Isis {
       void setEphemerisTimePolyFunctionOverSpice();
       void setEphemerisTimePckPolyFunction();
       std::vector<double> p_cacheTime;  //!< iTime for corresponding rotation
-      std::vector<std::vector<double> > p_cache; /**< Cached rotations, stored as 
-                                                      rotation matrix from J2000 
-                                                      to 1st constant frame (CJ) or 
+      std::vector<std::vector<double> > p_cache; /**< Cached rotations, stored as
+                                                      rotation matrix from J2000
+                                                      to 1st constant frame (CJ) or
                                                       coefficients of polynomial
                                                       fit to rotation angles.*/
       int p_degree;                     //!< Degree of fit polynomial for angles
@@ -435,11 +441,11 @@ namespace Isis {
     private:
       // method
       void setFrameType();
-      std::vector<int> p_constantFrames;  /**< Chain of Naif frame codes in constant 
-                                               rotation TC. The first entry will always 
+      std::vector<int> p_constantFrames;  /**< Chain of Naif frame codes in constant
+                                               rotation TC. The first entry will always
                                                be the target frame code*/
-      std::vector<int> p_timeFrames;      /**< Chain of Naif frame codes in time-based 
-                                               rotation CJ. The last entry will always 
+      std::vector<int> p_timeFrames;      /**< Chain of Naif frame codes in time-based
+                                               rotation CJ. The last entry will always
                                                be 1 (J2000 code)*/
       double p_timeBias;                  //!< iTime bias when reading kernels
 
@@ -449,7 +455,7 @@ namespace Isis {
 
       bool p_matrixSet;                    //!< Flag indicating p_TJ has been set
       bool m_tOrientationAvailable;  //!< Target orientation constants are available
- 
+
 
       FrameType m_frameType;  //!< The type of rotation frame
       Source p_source;                    //!< The source of the rotation data
@@ -464,7 +470,7 @@ namespace Isis {
       bool p_degreeApplied;               /**< Flag indicating whether or not a polynomial
                                                of degree p_degree has been created and
                                                used to fill the cache*/
-      std::vector<double> p_coefficients[3];  /**< Coefficients defining functions fit 
+      std::vector<double> p_coefficients[3];  /**< Coefficients defining functions fit
                                                    to 3 pointing angles*/
       bool p_noOverride;                  //!< Flag to compute base time;
       double p_overrideBaseTime;          //!< Value set by caller to override computed base time
@@ -473,34 +479,34 @@ namespace Isis {
       double p_fullCacheStartTime;        //!< Initial requested starting time of cache
       double p_fullCacheEndTime;          //!< Initial requested ending time of cache
       int p_fullCacheSize;                //!< Initial requested cache size
-      std::vector<double> p_TC;           /**< Rotation matrix from first constant rotation 
+      std::vector<double> p_TC;           /**< Rotation matrix from first constant rotation
                                           (after all time-based rotations in frame chain from
                                            J2000 to target) to the target frame*/
-      std::vector<double> p_CJ;           /**< Rotation matrix from J2000 to first constant 
+      std::vector<double> p_CJ;           /**< Rotation matrix from J2000 to first constant
                                                rotation*/
       std::vector<std::vector<double> > p_cacheAv;
       //!< Cached angular velocities for corresponding rotactions in p_cache
       std::vector<double> p_av;           //!< Angular velocity for rotation at time p_et
-      bool p_hasAngularVelocity;          /**< Flag indicating whether the rotation 
+      bool p_hasAngularVelocity;          /**< Flag indicating whether the rotation
                                                includes angular velocity*/
-      std::vector<double> StateTJ();      /**< State matrix (6x6) for rotating state 
+      std::vector<double> StateTJ();      /**< State matrix (6x6) for rotating state
                                                vectors from J2000 to target frame*/
-      // The remaining items are only used for PCK frame types.  In this case the  
+      // The remaining items are only used for PCK frame types.  In this case the
       // rotation is  stored as a cache, but the coefficients are available for display
-      // or comparison, and the first three coefficient sets can be solved for and 
+      // or comparison, and the first three coefficient sets can be solved for and
       // updated in jigsaw.   The initial coefficient values are read from a Naif PCK.
       //
       // The general equation for the right ascension of the pole is
       //
       // raPole  =  raPole[0] + raPole[1]*Time  + raPole[2]*Time**2 + raNutPrec,
-      //    where 
-      //    raNutPrec  =  raNutPrec1[0]*sin(sysNutPrec[0][0] + sysNutPrec[0][1]*Time) + 
+      //    where
+      //    raNutPrec  =  raNutPrec1[0]*sin(sysNutPrec[0][0] + sysNutPrec[0][1]*Time) +
       //                  raNutPrec1[1]*sin(sysNutPrec[1][0] + sysNutPrec[1][1]*Time) + ...
       //                  raNutPrec1[N-1]*sin(sysNutPrec[N-1][0] + sysNutPrec[N-1][1]*Time) +
       // (optional for multiples of nutation precession angles)
       //                  raNutPrec2[0]*sin(2*(sysNutPrec[0][0] + sysNutPrec[0][1]*Time)) +
       //                  raNutPrec2[1]*sin(2*(sysNutPrec[1][0] + sysNutPrec[1][1]*Time)) + ...
-      //                  raNutPrec2[N-1]*sin(2*(sysNutPrec[N-1][0] + sysNutPrec[N-1][1]*Time)) + 
+      //                  raNutPrec2[N-1]*sin(2*(sysNutPrec[N-1][0] + sysNutPrec[N-1][1]*Time)) +
       //                  raNutPrecM[0]*sin(M*(sysNutPrec[0][0] + sysNutPrec[0][1]*Time)) +
       //                  raNutPrecM[1]*sin(M*(sysNutPrec[1][0] + sysNutPrec[1][1]*Time)) + ...
       //                  raNutPrecM[N-1]*sin(M*(sysNutPrec[N-1][0] + sysNutPrec[N-1][1]*Time)) +
@@ -508,8 +514,8 @@ namespace Isis {
       // The general equation for the declination of the pole is
       //
       // decPole  =  p_decPole[0] + p_decPole[1]*Time  + p_decPole[2]*Time**2 + decNutPrec,
-      //    where 
-      //    decNutPrec  =  decNutPrec1[0]*cos(sysNutPrec[0][0] + sysNutPrec[0][1]*Time) + 
+      //    where
+      //    decNutPrec  =  decNutPrec1[0]*cos(sysNutPrec[0][0] + sysNutPrec[0][1]*Time) +
       //                   decNutPrec1[1]*cos(sysNutPrec[1][0] + sysNutPrec[1][1]*Time) + ...
       //                   decNutPrec1[N-1]*cos(sysNutPrec[N-1][0] + sysNutPrec[N-1][1]*Time) +
       //                   decNutPrec2[0]*cos(2*(sysNutPrec[0][0] + sysNutPrec[0][1]*Time)) +
@@ -518,15 +524,15 @@ namespace Isis {
       // (optional for multiples of nutation precession angles)
       //                   decNutPrecM[0]*sin(M*(sysNutPrec[0][0] + sysNutPrec[0][1]*Time)) +
       //                   decNutPrecM[1]*sin(M*(sysNutPrec[1][0] + sysNutPrec[1][1]*Time)) + ...
-      //                   decNutPrecM[N-1]*sin(M*(sysNutPrec[N-1][0] + sysNutPrec[N-1][1]*Time)) 
+      //                   decNutPrecM[N-1]*sin(M*(sysNutPrec[N-1][0] + sysNutPrec[N-1][1]*Time))
       //
       //     and Time is julian centuries since J2000.
       //
       // The general equation for the prime meridian rotation is
       //
       // pm  =  p_pm[0] + p_pm[1]*Dtime  + p_pm[2]*Dtime**2 + pmNutPrec,
-      //    where 
-      //    pmNutPrec  =  pmNutPrec1[0]*sin(sysNutPrec[0][0] + sysNutPrec[0][1]*Time) + 
+      //    where
+      //    pmNutPrec  =  pmNutPrec1[0]*sin(sysNutPrec[0][0] + sysNutPrec[0][1]*Time) +
       //                  pmNutPrec1[1]*sin(sysNutPrec[1][0] + sysNutPrec[1][1]*Time) + ...
       //                  pmNutPrec1[N-1]*sin(sysNutPrec[N-1][0] + sysNutPrec[N-1][1]*Time) +
       // (optional for multiples of nutation precession angles)
@@ -535,24 +541,24 @@ namespace Isis {
       //                  pmNutPrec2[N-1]*sin(2*(sysNutPrec[N-1][0] + sysNutPrec[N-1][1]*Time)) +
       //                  pmNutPrecM[0]*sin(M*(sysNutPrec[0][0] + sysNutPrec[0][1]*Time)) +
       //                  pmNutPrecM[1]*sin(M*(sysNutPrec[1][0] + sysNutPrec[1][1]*Time)) + ...
-      //                  pmNutPrecM[N-1]*sin(M*(sysNutPrec[N-1][0] + sysNutPrec[N-1][1]*Time)) 
+      //                  pmNutPrecM[N-1]*sin(M*(sysNutPrec[N-1][0] + sysNutPrec[N-1][1]*Time))
       //
-      //     Time is interval in Julian centuries since the standard epoch, 
+      //     Time is interval in Julian centuries since the standard epoch,
       //     dTime is interval in days from the standard epoch (J2000),
       //
-      //     N is the number of nutation/precession terms for the planetary system of the target 
-      //     body,  (possibly including multiple angles as unique terms, 
+      //     N is the number of nutation/precession terms for the planetary system of the target
+      //     body,  (possibly including multiple angles as unique terms,
       //             ie. 2*sysNutPrec[0][0] + sysNutPrec[][1]*Time).
       //
       //     Many of the constants in this equation are 0. for a given body.
       //
-      //     M is included as an option for future improvements.  M = highest multiple (period) 
+      //     M is included as an option for future improvements.  M = highest multiple (period)
       //     of any of the nutation/precession angles included in the equations.
       //
-      //     ***NOTE*** Currently Naif stores multiples (amplitudes) as if they were additional 
-      //                nutation/precession terms (periods) in the equation.  This method works as 
-      //                long as jigsaw does not solve for those values.  In order to solve for 
-      //                those values, the multiples will need to be known so that the partial 
+      //     ***NOTE*** Currently Naif stores multiples (amplitudes) as if they were additional
+      //                nutation/precession terms (periods) in the equation.  This method works as
+      //                long as jigsaw does not solve for those values.  In order to solve for
+      //                those values, the multiples will need to be known so that the partial
       //                derivatives can be correctly calculated.  Some possible ways of doing this
       //                are 1) Convince Naif to change their data format indicating the relation
       //                      2) Make an Isis version of the PCK data and have Isis software to
@@ -561,7 +567,7 @@ namespace Isis {
       //                          and software to apply them when calculating the rotation and partials.
       //
       //                For now this software will handle any terms with the same period and different
-      //                amplitudes as unique terms in the equation (raNutPrec, decNutPrec, 
+      //                amplitudes as unique terms in the equation (raNutPrec, decNutPrec,
       //                and pmNutPrec).
       //
       // The next three vectors will have length 3 (for a quadratic polynomial) if used.
@@ -569,19 +575,19 @@ namespace Isis {
       std::vector<Angle>m_decPole;      //!< Coefficients of a quadratic polynomial fitting pole dec.
       std::vector<Angle>m_pm ;          //!< Coefficients of a quadratic polynomial fitting pole pm.
       //
-      // Currently multiples (terms with periods matching other terms but varying amplitudes) 
-      // are handled as additional terms added to the end of the vector as Naif does (see 
-      // comments in any of the standard Naif PCK. 
-      std::vector<double>m_raNutPrec;    //!< Coefficients of pole right ascension nut/prec terms.  
-      std::vector<double>m_decNutPrec;  //!< Coefficients of pole decliniation nut/prec terms. 
-      std::vector<double>m_pmNutPrec;   //!< Coefficients of prime meridian nut/prec terms.  
+      // Currently multiples (terms with periods matching other terms but varying amplitudes)
+      // are handled as additional terms added to the end of the vector as Naif does (see
+      // comments in any of the standard Naif PCK.
+      std::vector<double>m_raNutPrec;    //!< Coefficients of pole right ascension nut/prec terms.
+      std::vector<double>m_decNutPrec;  //!< Coefficients of pole decliniation nut/prec terms.
+      std::vector<double>m_pmNutPrec;   //!< Coefficients of prime meridian nut/prec terms.
 
       // The periods of bodies in the same system are modeled with a linear equation
       std::vector<Angle>m_sysNutPrec0; //!< Constants of planetary system nut/prec periods
       std::vector<Angle>m_sysNutPrec1; //!< Linear terms of planetary system nut/prec periods
 
       // The following scalars are used in the IAU equations to convert p_et to the appropriate time
-      // units for calculating target body ra, dec, and w.  These need to be initialized in every 
+      // units for calculating target body ra, dec, and w.  These need to be initialized in every
       // constructor.
       //! Seconds per Julian century for scaling time in seconds
       static const double m_centScale;
@@ -591,4 +597,3 @@ namespace Isis {
 };
 
 #endif
-
diff --git a/isis/src/base/objs/SpiceRotation/SpiceRotation.truth b/isis/src/base/objs/SpiceRotation/SpiceRotation.truth
index fa867d10df9e9f90a297d3df714a2da810503d26..695c9a31d7a0c46a531ff901237940c442da5114 100644
--- a/isis/src/base/objs/SpiceRotation/SpiceRotation.truth
+++ b/isis/src/base/objs/SpiceRotation/SpiceRotation.truth
@@ -624,6 +624,13 @@ Frame type is binary PCK and cannot be updated
 End of PCK testing
 
 
+Testing CK based body rotation with 67P/Churyumov–Gerasimenko data ...
+Time = 4.6285471e+08
+CJ = 0.93816333 -0.34618155 -0.002810256
+     0.30996014 0.84356223 -0.43855157
+     0.15418909 0.41056193 0.89870163
+
+
 Testing exceptions...
 
 **I/O ERROR** Cannot find [INS-99999_TRANSX] in text kernels.
diff --git a/isis/src/base/objs/SpiceRotation/unitTest.cpp b/isis/src/base/objs/SpiceRotation/unitTest.cpp
index 95f0c9749fa0f00555a56cc73518bf29acb33f7f..673da7149b2c927ac76bb8a1d50b292e7de66010 100644
--- a/isis/src/base/objs/SpiceRotation/unitTest.cpp
+++ b/isis/src/base/objs/SpiceRotation/unitTest.cpp
@@ -37,6 +37,8 @@ int main(int argc, char *argv[]) {
   QString mocbsp(dir + "moc.bsp");
   QString de(dir + "de405.bsp");
   QString pck("/usgs/cpkgs/isis3/data/base/kernels/pck/pck00009.tpc");
+  QString cgFK(dir + "ROS_V29.TF");
+  QString cgCK(dir + "CATT_DV_145_02_______00216.BC");
   //QString mocadd(dir+"mocAddendum.ti");
   QString mocspice(dir + "mocSpiceRotationUnitTest.ti");
   furnsh_c(naif.toLatin1().data());
@@ -47,6 +49,8 @@ int main(int argc, char *argv[]) {
   furnsh_c(de.toLatin1().data());
   furnsh_c(pck.toLatin1().data());
   furnsh_c(mocspice.toLatin1().data());
+  furnsh_c(cgFK.toLatin1().data());
+  furnsh_c(cgCK.toLatin1().data());
 
   double startTime = -69382819.0;
   double endTime = -69382512.0;
@@ -202,7 +206,7 @@ int main(int argc, char *argv[]) {
   lookC.push_back(1.);
   vector<double> lookJ = rot.J2000Vector(lookC);
   // Save a J2000 vector for testing target body partial methods later.
-  vector<double> testLookJ(lookJ);  
+  vector<double> testLookJ(lookJ);
   cout << " For lookJ = " << lookJ[0] << " " << lookJ[1] << " " << lookJ[2] << endl;
   vector<double> dAraLookC(3);
   dAraLookC = rot.ToReferencePartial(lookJ, SpiceRotation::WRT_RightAscension, 0);
@@ -385,11 +389,11 @@ int main(int argc, char *argv[]) {
   // Use Galileo Io image with product id = 21I0165 for testing nutation/precession terms.  Mars has none.
   //  tet = -15839262.24291
   // body frame code for Io = 10023
-  // Use Europa for exercising the code using nutation/precession terms.  Mars has none. 
+  // Use Europa for exercising the code using nutation/precession terms.  Mars has none.
   SpiceRotation targrot1(10014);   //Frame code for Mars
   // SpiceRotation targrotV1(10024);   //Frame code for Europa
   // targrotV1.LoadCache(-646009153.46723, -646009153.46723, 1); // This calls LoadPcFromSpice for Europa
-  SpiceRotation targrotV1(10023);   //Frame code for Io  
+  SpiceRotation targrotV1(10023);   //Frame code for Io
   targrotV1.LoadCache(-15839262.24291, -15839262.24291, 1); // This calls LoadPcFromSpice for Io
   targrot1.LoadCache(startTime, endTime, 2); // This calls LoadPcFromSpice for Mars
   cout << "Test CacheLabel for PCK data..." << endl;
@@ -397,8 +401,8 @@ int main(int argc, char *argv[]) {
   Table pcktabV = targrotV1.Cache("Planetary constants test table"); // This calls CacheLabel
   SpiceRotation targrot(10014);  // Mars
   // SpiceRotation targrotV(10024);  // Europa  --  The results for pm will differ slightly from TrigBasis because of the older PCK
-  SpiceRotation targrotV(10023);  // Io  -- 
-  cout << "Test LoadPCFromTable..." << endl; 
+  SpiceRotation targrotV(10023);  // Io  --
+  cout << "Test LoadPCFromTable..." << endl;
   targrot.LoadCache(pcktab);  // This calls LoadPcFromTable
   targrotV.LoadCache(pcktabV);  // This calls LoadPcFromTable
   // Now get the values
@@ -460,7 +464,7 @@ int main(int argc, char *argv[]) {
   // cout << "    Angles = " << pckanglesV[0]*dpr_c() <<","<< pckanglesV[1]*dpr_c() <<","
   //      << pckanglesV[2]*dpr_c() <<endl <<endl;
   // end Europa test
-  
+
   // For testing Io with the nutation/precession terms and a cache size of 1
   tet = -15839262.24291;  // time et for Io
   ibod = 501; // Io
@@ -471,8 +475,8 @@ int main(int argc, char *argv[]) {
        << pckanglesV[2]*dpr_c() <<endl <<endl;
   // end Io test
 
-  // For testing Mars with more than one value in the cache 
-  cout << endl << "  Mars original SPICE values for target body orientation unadjusted" 
+  // For testing Mars with more than one value in the cache
+  cout << endl << "  Mars original SPICE values for target body orientation unadjusted"
        << endl;
   cout << "  Source = " << targrot.GetSource() << endl;
   for (int i = 0; i < 10; i++) {
@@ -520,18 +524,18 @@ int main(int argc, char *argv[]) {
     cout << "         " << CJ[6] << " " << CJ[7] << " " << CJ[8] << endl;
   }
 
-    // Test angular velocities 
+    // Test angular velocities
   cout << endl << endl << "Testing angular velocity with Io data ..." << endl;
   if (targrotV.HasAngularVelocity()) {
     vector<double> av = targrotV.AngularVelocity();
     cout << "SpiceRotation av = " << av[0] << " " << av[1] << " " << av[2] << endl;
     SpiceDouble tsipm[6][6];
-    sxform_c ( "J2000", "IAU_IO", -15839262.24291, tsipm); 
-    // sxform_c ( "J2000", "IAU_EUROPA", -646009153.46723, tsipm); 
+    sxform_c ( "J2000", "IAU_IO", -15839262.24291, tsipm);
+    // sxform_c ( "J2000", "IAU_EUROPA", -646009153.46723, tsipm);
     SpiceDouble tipm[3][3];
     vector<SpiceDouble> nav(3,0.);
     xf2rav_c (tsipm, tipm, &(nav[0]) );
-    cout << "J2000 to body-fixed Naif av = " << nav[0] << " " << nav[1] << " " << nav[2] << endl; 
+    cout << "J2000 to body-fixed Naif av = " << nav[0] << " " << nav[1] << " " << nav[2] << endl;
   }
   cout << endl;
 
@@ -559,7 +563,7 @@ int main(int argc, char *argv[]) {
        << matchLookJ[1] << " " << matchLookJ[2] << endl;
 
   dLookB = targrot.ToReferencePartial(testLookJ, SpiceRotation::WRT_Twist, 1);
-  cout << endl << " dLookB with respect to rotation rate = " << dLookB[0] << " " << 
+  cout << endl << " dLookB with respect to rotation rate = " << dLookB[0] << " " <<
           dLookB[1] << " " << dLookB[2] << endl;
   //If I apply toJ2000Partial to dLookB, I get back lookJ(x,y,0) with roundoff  -- 05-12-2015 DAC
   matchLookJ = targrot.toJ2000Partial(dLookB, SpiceRotation::WRT_Twist, 1);
@@ -567,7 +571,7 @@ int main(int argc, char *argv[]) {
        << matchLookJ[1] << " " << matchLookJ[2] << endl;
 
   dLookB = targrot.ToReferencePartial(testLookJ, SpiceRotation::WRT_Twist, 0);
-  cout << endl << " dLookB with respect to rotation = " << dLookB[0] << " " << 
+  cout << endl << " dLookB with respect to rotation = " << dLookB[0] << " " <<
           dLookB[1] << " " << dLookB[2] << endl;
   //If I apply toJ2000Partial to dLookB, I get back lookJ(x,y,0) with roundoff  -- 05-12-2015 DAC
   matchLookJ = targrot.toJ2000Partial(dLookB, SpiceRotation::WRT_Twist, 0);
@@ -589,15 +593,28 @@ int main(int argc, char *argv[]) {
   if (frameType == SpiceRotation::BPC)
     cout << "Frame type is binary PCK and cannot be updated" << endl;
 
-  
+
   cout << "End of PCK testing" << endl;
 
-  
+  // Test CK based body rotation
+  cout << endl << endl << "Testing CK based body rotation with 67P/Churyumov–Gerasimenko data ..." << endl;
+
+  SpiceRotation cgRotation(-1000012000);
+  // Test time from Rosetta OSIRIS NAC image n20140901t144253568id30f22
+  double cgTestTime = 462854709.88606;
+  cgRotation.SetEphemerisTime(cgTestTime);
+  vector<double> cgCJ = cgRotation.Matrix();
+  cout << "Time = " << cgRotation.EphemerisTime() << endl;
+  cout << "CJ = " << cgCJ[0] << " " << cgCJ[1] << " " << cgCJ[2] << endl;
+  cout << "     " << cgCJ[3] << " " << cgCJ[4] << " " << cgCJ[5] << endl;
+  cout << "     " << cgCJ[6] << " " << cgCJ[7] << " " << cgCJ[8] << endl;
+
+
   //Test exceptions
   cout << endl << endl << "Testing exceptions..." << endl;
   SpiceRotation testRot(-94031); // MGS_MOC
 
-  // SpiceRotation(frameCode, targetCode) 
+  // SpiceRotation(frameCode, targetCode)
   //     "Cannot find [key] in text kernels
   try {
     cout << endl;
@@ -611,13 +628,13 @@ int main(int argc, char *argv[]) {
   //     "Argument cacheSize must not be less or equal to zero"
   try {
     cout << endl;
-    testRot.LoadCache(10, 20, -1); 
+    testRot.LoadCache(10, 20, -1);
   }
   catch (IException &e) {
     e.print();
   }
 
-  //     "Argument startTime must be less than or equal to endTime"   
+  //     "Argument startTime must be less than or equal to endTime"
   try {
     cout << endl;
     testRot.LoadCache(20, 10, 1);
@@ -639,7 +656,7 @@ int main(int argc, char *argv[]) {
   try {
     cout << endl;
     testRot.LoadCache(startTime, endTime, 2);
-    testRot.LoadCache(startTime, endTime - 1, 2); 
+    testRot.LoadCache(startTime, endTime - 1, 2);
   }
   catch (IException &e) {
     e.print();
@@ -656,7 +673,7 @@ int main(int argc, char *argv[]) {
   }
 
   // LineCache(tableName)
-  //     "Only cached rotations can be returned as a line cache of quaternions and time" 
+  //     "Only cached rotations can be returned as a line cache of quaternions and time"
   try {
     cout << endl;
     SpiceRotation sr(-94031);
@@ -665,7 +682,7 @@ int main(int argc, char *argv[]) {
   catch (IException &e) {
     e.print();
   }
-    
+
   // Cache(tableName)
   //     "To create table source of data must be either Memcache or PolyFunction"
   try {
@@ -690,10 +707,10 @@ int main(int argc, char *argv[]) {
     e.print();
   }
 
-  // DPolynomial(coeffIndex) 
-  //     "Unable to evaluate the derivative of the SPCIE rotation fit 
+  // DPolynomial(coeffIndex)
+  //     "Unable to evaluate the derivative of the SPCIE rotation fit
   //      polynomial for the given coefficient index. Index is negative
-  //      or exceeds degree of polynomial"    
+  //      or exceeds degree of polynomial"
   try {
     cout << endl;
     testRot.DPolynomial(-1);
@@ -703,7 +720,7 @@ int main(int argc, char *argv[]) {
   }
 
   // DPckPolynomial(partialVar, coeffIndex)
-  //     "Unable to evaluate the derivative of the SPCIE rotation fit 
+  //     "Unable to evaluate the derivative of the SPCIE rotation fit
   //      polynomial for the given coefficient index. Index is negative
   //      or exceeds degree of polynomial"
   try {
@@ -731,9 +748,9 @@ int main(int argc, char *argv[]) {
 
   // LoadTimeCache()
   //TODO test its 3 exceptions
-  
+
   // GetFullCacheTime()
-  //    "Time cache not availabe -- rerun spiceinit" 
+  //    "Time cache not availabe -- rerun spiceinit"
   try {
     cout << endl;
     SpiceRotation sr(-94031);
@@ -745,7 +762,7 @@ int main(int argc, char *argv[]) {
 
   // FrameTrace()
   //TODO test its 3 exceptions
-  
+
   // ComputeAv()
   //     "The SpiceRotation pointing angles must be fit to polynomials in order to
   //      compute angular velocity."
diff --git a/isis/src/base/objs/XmlToPvlTranslationManager/XmlToPvlTranslationManager.cpp b/isis/src/base/objs/XmlToPvlTranslationManager/XmlToPvlTranslationManager.cpp
index f4c5bee799abe90e7659985498f1066521ba8bc4..052ccc2c14581f4f47f6bb56c71101acb88f4b5b 100644
--- a/isis/src/base/objs/XmlToPvlTranslationManager/XmlToPvlTranslationManager.cpp
+++ b/isis/src/base/objs/XmlToPvlTranslationManager/XmlToPvlTranslationManager.cpp
@@ -142,19 +142,24 @@ namespace Isis {
 
 
   /**
-   * Returns a translated value. The output name is used to find the input
-   * group, keyword, default and tranlations in the translation table. If the
-   * keyword does not exist in the input label, the input default if
-   * available will be used as the input value. This input value
-   * is then used to search all of the translations. If a match is
-   * found the translated value is returned.
+   * Returns a translated value. The translation group name is 
+   * used to find the input group, keyword, default and 
+   * tranlations in the translation table. If the keyword does not 
+   * exist in the input label, the input default if available will 
+   * be used as the input value. This input value is then used to 
+   * search all of the translations. If a match is found the 
+   * translated value is returned. 
    *
-   * @param outputName The output name used to identify the input keyword to
-   *                   be translated.
+   * @param translationGroupName The name of the PVL translation 
+   *                        group used to identify the
+   *                        input/output keywords to be
+   *                        translated. Often, this is the
+   *                        same as the output keyword name.
    *
    * @param index The index into the input keyword array.  Defaults to 0
    *
-   * @return string The ISIS cube label value for the outputName.
+   * @return @b QString The translated output value to be 
+   *         placed in the ISIS3 cube label.
    *
    * @throws IException::Unknown "Failed to translate output value."
    * @throws IException::Unknown "Cannot translate value. Xml files can only
@@ -170,7 +175,7 @@ namespace Isis {
    * @throws IException::Unknown "Could not find an input value or default value."
    * @throws IException::Unknown "Input element does not have the named attribute."
    */
-  QString XmlToPvlTranslationManager::Translate(QString outputName, 
+  QString XmlToPvlTranslationManager::Translate(QString translationGroupName, 
                                                 int index) {
     try {
     if (index != 0) {
@@ -182,7 +187,7 @@ namespace Isis {
     const Pvl &transTable = TranslationTable();
     PvlGroup transGroup;
     try {
-      transGroup = transTable.findGroup(outputName);
+      transGroup = transTable.findGroup(translationGroupName);
     }
     catch (IException &e){
       QString msg = "Unable to retrieve translation group from translation table.";
@@ -228,7 +233,7 @@ namespace Isis {
     // Notify what we are translating and what the translating group is.
     if (isDebug) {
       cout << endl << "          ====================          " << endl;
-      cout << endl << "Translating output keyword: " << outputName << endl;
+      cout << endl << "Translating output keyword: " << translationGroupName << endl;
       cout << endl << "Translation group:" << endl;
       cout << transGroup << endl << endl;
     }
@@ -269,13 +274,13 @@ namespace Isis {
     }
      
     if (inputParentElement.isNull()) {
-      if (hasInputDefault(outputName)) {
+      if (hasInputDefault(translationGroupName)) {
         if (isDebug) {
           cout << endl << "Could not traverse input position, " <<
             "using default value: " <<
-            InputDefault(outputName) << endl;
+            InputDefault(translationGroupName) << endl;
         }
-        return PvlTranslationTable::Translate( outputName );
+        return PvlTranslationTable::Translate( translationGroupName );
       }
       else {
         QString msg = "Failed traversing input position. [" +
@@ -312,12 +317,12 @@ namespace Isis {
     // If the parent element is NULL at this point then we traversed every
     // potential input element and none of them satisfied the dependencies.
     if ( inputParentElement.isNull() ) {
-      if ( hasInputDefault(outputName) ) {
+      if ( hasInputDefault(translationGroupName) ) {
         if (isDebug) {
           cout << endl << "No input value found, using default value: " <<
-                          InputDefault(outputName) << endl;
+                          InputDefault(translationGroupName) << endl;
         }
-        return PvlTranslationTable::Translate( outputName );
+        return PvlTranslationTable::Translate( translationGroupName );
       }
       else {
         QString msg = "Could not find an input or default value that fits the given input "
@@ -333,12 +338,12 @@ namespace Isis {
       if ( inputKeyElement.hasAttribute(attributeName) ) {
         inputValue = inputKeyElement.attribute(attributeName);
       }
-      else if (hasInputDefault(outputName) ) {
+      else if (hasInputDefault(translationGroupName) ) {
         if (isDebug) {
           cout << endl << "No input value found, using default value: " <<
-                          InputDefault(outputName) << endl;
+                          InputDefault(translationGroupName) << endl;
         }
-        return PvlTranslationTable::Translate( outputName );
+        return PvlTranslationTable::Translate( translationGroupName );
       }
       else {
         QString msg = "Input element [" + inputKeyElement.tagName() +
@@ -350,10 +355,10 @@ namespace Isis {
     if (isDebug) {
           cout << endl << "Translating input value: " << inputValue << endl;
         }
-    return PvlTranslationTable::Translate( outputName, inputValue.trimmed() );
+    return PvlTranslationTable::Translate( translationGroupName, inputValue.trimmed() );
     }
     catch (IException &e){
-      QString msg = "Failed to translate output value for [" + outputName + "].";
+      QString msg = "Failed to translate output value for [" + translationGroupName + "].";
       throw IException(e, IException::Unknown, msg, _FILEINFO_);
     }
   }
diff --git a/isis/src/base/objs/XmlToPvlTranslationManager/XmlToPvlTranslationManager.h b/isis/src/base/objs/XmlToPvlTranslationManager/XmlToPvlTranslationManager.h
index 8f726fa2f82dde60f59a3d049fd8f2275402ca3d..1a7a6fa9a1908cae03a2339751bf59e69d512914 100644
--- a/isis/src/base/objs/XmlToPvlTranslationManager/XmlToPvlTranslationManager.h
+++ b/isis/src/base/objs/XmlToPvlTranslationManager/XmlToPvlTranslationManager.h
@@ -143,7 +143,7 @@ namespace Isis {
 
       // Attempt to translate the requested output name to output value
       // using the input name and value/default value
-      virtual QString Translate(QString nName, int findex = 0);
+      virtual QString Translate(QString translationGroupName, int findex = 0);
 
       // Translate all translation table groups which contain "Auto"
       using LabelTranslationManager::Auto;
diff --git a/isis/src/control/apps/deltack/deltack.cpp b/isis/src/control/apps/deltack/deltack.cpp
index 0b88d4aa5b7032df44603038281b07eb99e88f73..529c84a9a53adf2a90692890cec9820a5bf26868 100644
--- a/isis/src/control/apps/deltack/deltack.cpp
+++ b/isis/src/control/apps/deltack/deltack.cpp
@@ -267,12 +267,12 @@ void IsisMain() {
       QObject::connect( bundleAdjust, SIGNAL( statusUpdate(QString) ),
                         bundleAdjust, SLOT( outputBundleStatus(QString) ) );
 
-      BundleSolutionInfo bundleSolution = bundleAdjust->solveCholeskyBR();
+      BundleSolutionInfo *bundleSolution = bundleAdjust->solveCholeskyBR();
 
 
       // Output bundle adjust files
-      bundleSolution.outputText();
-      bundleSolution.outputResiduals();
+      bundleSolution->outputText();
+      bundleSolution->outputResiduals();
 
       Table cmatrix = bundleAdjust->cMatrix(0);
 
@@ -285,6 +285,9 @@ void IsisMain() {
       //cmatrix.Label().findObject("Table",Pvl::Traverse).addKeyword(description);
 
       c.write(cmatrix);
+      
+      delete bundleAdjust;
+      delete bundleSolution;
     }
 
     // Now do final clean up as the update was successful if we reach here...
diff --git a/isis/src/control/apps/deltack/deltack.xml b/isis/src/control/apps/deltack/deltack.xml
index 76122f369e7b9f61a4e0ad38d8c4cf269ebf9428..25f78dd1d424c2f6e2cb0e5e2d23f5750ca9122e 100644
--- a/isis/src/control/apps/deltack/deltack.xml
+++ b/isis/src/control/apps/deltack/deltack.xml
@@ -190,7 +190,11 @@
       method to apply. The default is METHOD=BUNDLE which chooses pre-existing 
       behavor. Updated documentation to reflect these new changes. Fixes #4868. 
     </change>
-    
+    <change name="Ken Edmundson" date="2018-05-23">
+      Modifed call to bundleAdjustment->solveCholeskyBR() to return a raw pointer to a
+      BundleSolutionInfo object. Am also deleting this pointer because jigsaw.cpp takes
+      ownership from BundleAdjust.
+    </change>    
   </history>
 
   <groups>
diff --git a/isis/src/control/apps/jigsaw/jigsaw.cpp b/isis/src/control/apps/jigsaw/jigsaw.cpp
index 66a0d84bfd9df5817486c2017d4c6e8eedcca348..daf0f46865a90dbff1cd075903daf5b540d1befc 100644
--- a/isis/src/control/apps/jigsaw/jigsaw.cpp
+++ b/isis/src/control/apps/jigsaw/jigsaw.cpp
@@ -80,24 +80,24 @@ void IsisMain() {
 
     QObject::connect( bundleAdjustment, SIGNAL( statusUpdate(QString) ),
                       bundleAdjustment, SLOT( outputBundleStatus(QString) ) );
-    BundleSolutionInfo bundleSolution = bundleAdjustment->solveCholeskyBR();
+    BundleSolutionInfo *bundleSolution = bundleAdjustment->solveCholeskyBR();
     
     cout << "\nGenerating report files\n" << endl;
 
     // write output files
     if (ui.GetBoolean("BUNDLEOUT_TXT")) {
-      bundleSolution.outputText();
+      bundleSolution->outputText();
     }
 
     if (ui.GetBoolean("IMAGESCSV")) {
-      bundleSolution.outputImagesCSV();
+      bundleSolution->outputImagesCSV();
     }
 
     if (ui.GetBoolean("OUTPUT_CSV")) {
-      bundleSolution.outputPointsCSV();
+      bundleSolution->outputPointsCSV();
     }
     if (ui.GetBoolean("RESIDUALS_CSV")) {
-      bundleSolution.outputResiduals();
+      bundleSolution->outputResiduals();
     }
     
     // write updated control net
@@ -147,6 +147,7 @@ void IsisMain() {
       gp += PvlKeyword("Status", "Camera pointing NOT updated");
     }
     Application::Log(gp);
+    delete bundleSolution;
   }
   catch(IException &e) {
     bundleAdjustment->controlNet()->Write(ui.GetFileName("ONET"));
diff --git a/isis/src/control/apps/jigsaw/jigsaw.xml b/isis/src/control/apps/jigsaw/jigsaw.xml
index ec0f2bb3d5907baa1d156ee3365c3b771ebe7d36..460aaad7a001949cea65154fcc46aa906ba45c45 100644
--- a/isis/src/control/apps/jigsaw/jigsaw.xml
+++ b/isis/src/control/apps/jigsaw/jigsaw.xml
@@ -252,6 +252,11 @@
     <change name="Summer Stapleton" date="2017-08-09">
       Fixed bug where an invalid control net was not throwing exception. Fixes #5068.
     </change>
+    <change name="Ken Edmundson" date="2018-05-23">
+      Modifed call to bundleAdjustment->solveCholeskyBR() to return a raw pointer to a
+      BundleSolutionInfo object. Am also deleting this pointer because jigsaw.cpp takes
+      ownership from BundleAdjust.
+    </change>
   </history>
 
   <groups>
diff --git a/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp b/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp
index 8c892e114cb8e5d137778a1f66c279b860f366db..2e3ef8cd5d06f392f5fc275da5cabe24b6af7c52 100644
--- a/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp
+++ b/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp
@@ -680,7 +680,7 @@ namespace Isis {
    *
    * @TODO make solveCholesky return a BundleSolutionInfo object and delete this placeholder ???
    */
-  BundleSolutionInfo BundleAdjust::solveCholeskyBR() {
+  BundleSolutionInfo* BundleAdjust::solveCholeskyBR() {
     solveCholesky();
     return bundleSolveInformation();
   }
@@ -976,8 +976,7 @@ namespace Isis {
       m_bundleResults.setObservations(m_bundleObservations);
       m_bundleResults.setBundleControlPoints(m_bundleControlPoints);
 
-      BundleSolutionInfo *results = new BundleSolutionInfo(bundleSolveInformation());
-      emit resultsReady(results);
+      emit resultsReady(bundleSolveInformation());
 
       emit statusUpdate("\nBundle Complete");
 
@@ -999,12 +998,18 @@ namespace Isis {
   /**
    * Create a BundleSolutionInfo containing the settings and results from the bundle adjustment.
    *
-   * @return @b BundleSolutionInfo A container with solve information from the adjustment.
+   * @return @b BundleSolutionInfo A container with solve information from the adjustment. NOTE:
+   *            Caller takes ownership and is responsible for memory management of returned
+   *            BundleSolutionInfo raw pointer.
+   *
    */
-  BundleSolutionInfo BundleAdjust::bundleSolveInformation() {
-    BundleSolutionInfo results(m_bundleSettings, FileName(m_cnetFileName), m_bundleResults, imageLists());
-    results.setRunTime("");
-    return results;
+  BundleSolutionInfo *BundleAdjust::bundleSolveInformation() {
+    BundleSolutionInfo *bundleSolutionInfo = new BundleSolutionInfo(m_bundleSettings,
+                                                                    FileName(m_cnetFileName),
+                                                                    m_bundleResults,
+                                                                    imageLists());
+    bundleSolutionInfo->setRunTime("");
+    return bundleSolutionInfo;
   }
 
 
diff --git a/isis/src/control/objs/BundleAdjust/BundleAdjust.h b/isis/src/control/objs/BundleAdjust/BundleAdjust.h
index 8c30664b4536254a1c923c6c670205ffb37efe57..428973b9b2a337af237e5ff3eeda156866b7022f 100644
--- a/isis/src/control/objs/BundleAdjust/BundleAdjust.h
+++ b/isis/src/control/objs/BundleAdjust/BundleAdjust.h
@@ -285,6 +285,13 @@ namespace Isis {
    *   @history 2017-08-09 Summer Stapleton - Added a try/catch around the m_controlNet assignment
    *                           in each of the constructors to verify valid control net input.
    *                           Fixes #5068.
+   *   @history 2018-05-22 Ken Edmundson - Modified methods bundleSolveInformation() and
+   *                           solveCholeskyBR() to return raw pointers to a BundleSolutionInfo object.
+   *                           Also modified resultsReady signal to take a raw pointer to a
+   *                           BundleSolutionInfo object. This was done to avoid using a copy
+   *                           constructor in the BundleSolutionInfo class because it is derived
+   *                           from QObject. Note that we ultimately want to return a QSharedPointer
+   *                           instead of a raw pointer.
    */
   class BundleAdjust : public QObject {
       Q_OBJECT
@@ -314,7 +321,7 @@ namespace Isis {
                    QList<ImageList *> imgList,
                    bool printSummary);
       ~BundleAdjust();
-      BundleSolutionInfo    solveCholeskyBR();
+      BundleSolutionInfo*    solveCholeskyBR();
 
       QList<ImageList *> imageLists();
 
@@ -350,7 +357,7 @@ namespace Isis {
       bool validateNetwork();
       bool solveSystem();
       void iterationSummary();
-      BundleSolutionInfo bundleSolveInformation();
+      BundleSolutionInfo* bundleSolveInformation();
       bool computeBundleStatistics();
       void applyParameterCorrections();
       bool errorPropagation();
diff --git a/isis/src/control/objs/BundleSettings/BundleSettings.cpp b/isis/src/control/objs/BundleSettings/BundleSettings.cpp
index 7434226a2a8acaf6a549dbb911ff4b3826e1a7da..b2e9d2ab97f9b97a847b3f8771e00be9cab765ea 100644
--- a/isis/src/control/objs/BundleSettings/BundleSettings.cpp
+++ b/isis/src/control/objs/BundleSettings/BundleSettings.cpp
@@ -10,10 +10,6 @@
 #include <QXmlStreamWriter>
 #include <QXmlInputSource>
 
-#include <H5Cpp.h>
-#include <hdf5_hl.h>
-#include <hdf5.h>
-
 #include "BundleObservationSolveSettings.h"
 //#include "FileName.h"currently only used in commented code
 #include "IException.h"
@@ -52,7 +48,7 @@ namespace Isis {
     m_solveRadius          = false;
     m_updateCubeLabel      = false;
     m_errorPropagation     = false;
-    m_createInverseMatrix  = true;
+    m_createInverseMatrix  = false;
 
     m_outlierRejection     = false;
     m_outlierRejectionMultiplier = 1.0;
diff --git a/isis/src/control/objs/BundleSettings/BundleSettings.h b/isis/src/control/objs/BundleSettings/BundleSettings.h
index 3475474b7f40e779fc0247de3bc46206a3ebd750..88db2ff4c71f2a978f9e1e8129ae2b717b7345d9 100644
--- a/isis/src/control/objs/BundleSettings/BundleSettings.h
+++ b/isis/src/control/objs/BundleSettings/BundleSettings.h
@@ -101,6 +101,11 @@ namespace Isis {
    *   @history 2016-10-17 Jesse Mapel - Removed m_SCPVLFilename parameter in accordance with
    *                           USEPVL being removed from jigsaw.  References #4316.
    *   @history 2017-04-24 Ian Humphrey - Removed pvlObject(). Fixes #4797.
+   *   @history 2018-03-20 Ken Edmundson
+   *                           1) Temporarily set default for m_createInverseMatrix to false. This
+   *                              is for creating and displaying the correlation matrix, which is
+   *                              currently not working.
+   *                           2) commented out hdf5 header includes in cpp
    *
    *   @todo Determine which XmlStackedHandlerReader constructor is preferred
    *   @todo Determine which XmlStackedHandler needs a Project pointer (see constructors)
diff --git a/isis/src/control/objs/BundleSettings/BundleSettings.truth b/isis/src/control/objs/BundleSettings/BundleSettings.truth
index 29abea63bdc5a8b29e789e0b127615d58d8b4688..853a4c351862bae73b2d739f7dac4dcd08c98de0 100644
--- a/isis/src/control/objs/BundleSettings/BundleSettings.truth
+++ b/isis/src/control/objs/BundleSettings/BundleSettings.truth
@@ -120,7 +120,7 @@ Testing mutator methods...
 <bundleSettings>
     <globalSettings>
         <validateNetwork>Yes</validateNetwork>
-        <solveOptions solveObservationMode="Yes" solveRadius="Yes" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="Yes"/>
+        <solveOptions solveObservationMode="Yes" solveRadius="Yes" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="No"/>
         <aprioriSigmas latitude="1000.0" longitude="2000.0" radius="3000.0"/>
         <outlierRejectionOptions rejection="Yes" multiplier="4.0"/>
         <convergenceCriteriaOptions convergenceCriteria="ParameterCorrections" threshold="0.25" maximumIterations="26"/>
@@ -170,7 +170,7 @@ Testing mutator methods...
 <bundleSettings>
     <globalSettings>
         <validateNetwork>Yes</validateNetwork>
-        <solveOptions solveObservationMode="Yes" solveRadius="No" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="Yes"/>
+        <solveOptions solveObservationMode="Yes" solveRadius="No" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="No"/>
         <aprioriSigmas latitude="N/A" longitude="N/A" radius="N/A"/>
         <outlierRejectionOptions rejection="No" multiplier="N/A"/>
         <convergenceCriteriaOptions convergenceCriteria="Sigma0" threshold="1.0e-10" maximumIterations="50"/>
@@ -198,7 +198,7 @@ Testing mutator methods...
 <bundleSettings>
     <globalSettings>
         <validateNetwork>Yes</validateNetwork>
-        <solveOptions solveObservationMode="Yes" solveRadius="No" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="Yes"/>
+        <solveOptions solveObservationMode="Yes" solveRadius="No" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="No"/>
         <aprioriSigmas latitude="N/A" longitude="N/A" radius="N/A"/>
         <outlierRejectionOptions rejection="No" multiplier="N/A"/>
         <convergenceCriteriaOptions convergenceCriteria="Sigma0" threshold="1.0e-10" maximumIterations="50"/>
@@ -275,7 +275,7 @@ Serializing test XML object to file:
 <bundleSettings>
     <globalSettings>
         <validateNetwork>Yes</validateNetwork>
-        <solveOptions solveObservationMode="Yes" solveRadius="No" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="Yes"/>
+        <solveOptions solveObservationMode="Yes" solveRadius="No" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="No"/>
         <aprioriSigmas latitude="N/A" longitude="N/A" radius="N/A"/>
         <outlierRejectionOptions rejection="No" multiplier="N/A"/>
         <convergenceCriteriaOptions convergenceCriteria="Sigma0" threshold="1.0e-10" maximumIterations="50"/>
@@ -304,7 +304,7 @@ Testing XML: Object deserialized as (should match object above):
 <bundleSettings>
     <globalSettings>
         <validateNetwork>Yes</validateNetwork>
-        <solveOptions solveObservationMode="Yes" solveRadius="No" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="Yes"/>
+        <solveOptions solveObservationMode="Yes" solveRadius="No" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="No"/>
         <aprioriSigmas latitude="N/A" longitude="N/A" radius="N/A"/>
         <outlierRejectionOptions rejection="No" multiplier="N/A"/>
         <convergenceCriteriaOptions convergenceCriteria="Sigma0" threshold="1.0e-10" maximumIterations="50"/>
@@ -334,7 +334,7 @@ Serializing test XML object to file:
 <bundleSettings>
     <globalSettings>
         <validateNetwork>Yes</validateNetwork>
-        <solveOptions solveObservationMode="Yes" solveRadius="Yes" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="Yes"/>
+        <solveOptions solveObservationMode="Yes" solveRadius="Yes" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="No"/>
         <aprioriSigmas latitude="1000.0" longitude="2000.0" radius="3000.0"/>
         <outlierRejectionOptions rejection="Yes" multiplier="4.0"/>
         <convergenceCriteriaOptions convergenceCriteria="ParameterCorrections" threshold="0.25" maximumIterations="26"/>
@@ -385,7 +385,7 @@ Testing XML: Object deserialized as (should match object above):
 <bundleSettings>
     <globalSettings>
         <validateNetwork>Yes</validateNetwork>
-        <solveOptions solveObservationMode="Yes" solveRadius="Yes" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="Yes"/>
+        <solveOptions solveObservationMode="Yes" solveRadius="Yes" updateCubeLabel="Yes" errorPropagation="Yes" createInverseMatrix="No"/>
         <aprioriSigmas latitude="1000.0" longitude="2000.0" radius="3000.0"/>
         <outlierRejectionOptions rejection="Yes" multiplier="4.0"/>
         <convergenceCriteriaOptions convergenceCriteria="ParameterCorrections" threshold="0.25" maximumIterations="26"/>
diff --git a/isis/src/control/objs/BundleSettings/unitTest.cpp b/isis/src/control/objs/BundleSettings/unitTest.cpp
index b8811df68fc3d583be0cfde31d8b88512443165a..54d3e40663e41d5d657980454c2bd5c0243682c4 100755
--- a/isis/src/control/objs/BundleSettings/unitTest.cpp
+++ b/isis/src/control/objs/BundleSettings/unitTest.cpp
@@ -47,6 +47,8 @@ void printXml(const T &);
   *                           most likely going to move to HDF5. Fixes #4327.
   *   @history 2017-04-24 Ian Humphrey - Removed pvlObject() and replaced with the XML save().
   *                           Fixes #4797.
+  *   @history 2018-05-24 Ken Edmundson - Updated truth data to indicate default value for
+  *                                       m_createInverseMatrix was changed from true to false.
   *
   *   @todo Truth updated so that the name of the BundleObservationSolveSettings object is Null,
   *         this should be fixed as part of #4292.
diff --git a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp
index a0a83357b193c837c607ce07dfa73a99b155afd6..d9c53bd6cb466e3acea682128ccb73ccd22f7535 100755
--- a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp
+++ b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp
@@ -10,6 +10,7 @@
 #include <QXmlStreamWriter>
 
 #include "BundleResults.h"
+#include "ControlList.h"
 #include "ControlMeasure.h"
 #include "ControlNet.h"
 #include "ControlPoint.h"
@@ -39,25 +40,19 @@ namespace Isis {
                                          QList<ImageList *> imgList,
                                          QObject *parent) : QObject(parent) {
     m_id = new QUuid(QUuid::createUuid());
-
     m_runTime = "";
-
     m_name = m_runTime;
-
-    m_controlNetworkFileName = new FileName(controlNetworkFileName);
-
+    m_inputControlNetFileName = new FileName(controlNetworkFileName);
+    m_outputControl = NULL;
     m_settings = inputSettings;
-
     m_statisticsResults = new BundleResults(outputStatistics);
-
     m_images = new QList<ImageList *>(imgList);
-
     m_adjustedImages = new QList<ImageList *>;
   }
 
 
   /**
-   * Constructor. Creates a BundleSolutionInfo.
+   * Constructor. Creates a BundleSolutionInfo from disk.
    *
    * @param project The current project
    * @param xmlReader An XML reader that's up to an <bundleSettings/> tag.
@@ -70,7 +65,8 @@ namespace Isis {
     m_id = new QUuid(QUuid::createUuid());
     m_runTime = "";
     m_name = m_runTime;
-    m_controlNetworkFileName = NULL;
+    m_inputControlNetFileName = NULL;
+    m_outputControl = NULL;
     m_statisticsResults = NULL;
     // what about the rest of the member data ? should we set defaults ??? CREATE INITIALIZE METHOD
     m_images = new QList<ImageList *>;
@@ -81,34 +77,17 @@ namespace Isis {
   }
 
 
-  /**
-   * Constructor. Creates a BundleSolutionInfo.
-   *
-   * @param src BundleSolutionInfo where the settings and BundleResults are read from.
-   */
-  BundleSolutionInfo::BundleSolutionInfo(const BundleSolutionInfo &src)
-      : m_id(new QUuid(QUuid::createUuid())),
-        m_name(src.m_name),
-        m_runTime(src.m_runTime),
-        m_controlNetworkFileName(new FileName(src.m_controlNetworkFileName->expanded())),
-        m_settings(new BundleSettings(*src.m_settings)),
-        m_statisticsResults(new BundleResults(*src.m_statisticsResults)),
-        m_images(new QList<ImageList *>(*src.m_images)),
-        m_adjustedImages(new QList<ImageList *>(*src.m_adjustedImages)),
-        m_csvSavedImagesFilename(src.m_csvSavedImagesFilename),
-        m_csvSavedPointsFilename(src.m_csvSavedPointsFilename),
-        m_csvSavedResidualsFilename(src.m_csvSavedResidualsFilename) {
-  }
-
-
   /**
    * Destructor
    */
   BundleSolutionInfo::~BundleSolutionInfo() {
     delete m_id;
 
-    delete m_controlNetworkFileName;
-    m_controlNetworkFileName = NULL;
+    delete m_inputControlNetFileName;
+    m_inputControlNetFileName = NULL;
+
+    delete m_outputControl;
+    m_outputControl = NULL;
 
     delete m_statisticsResults;
     m_statisticsResults = NULL;
@@ -128,53 +107,40 @@ namespace Isis {
 
 
   /**
-   * Creates an equal operator for BundleSolutionInfos.
-   *
-   * @param src the BundleSolutionInfo that we are comparing the current BundleSolutionInfo to.
+   * Returns bundleout text filename.
    *
-   * @return @b BundleSolutionInfo Reference to the current BundleSolutionInfo
+   * @return QString Bundleout text filename.
    */
-  BundleSolutionInfo &BundleSolutionInfo::operator=(const BundleSolutionInfo &src) {
-
-    if (&src != this) {
-
-      delete m_id;
-      m_id = new QUuid(QUuid::createUuid());
-
-      m_runTime = src.m_runTime;
-
-      if (src.m_name == "" || src.m_name == src.m_runTime) {
-        m_name = m_runTime;
-      }
-      else {
-        m_name = src.m_name;
-      }
-
-      delete m_controlNetworkFileName;
-      m_controlNetworkFileName = new FileName(src.m_controlNetworkFileName->expanded());
-
-      m_settings = src.m_settings;
-
-      delete m_statisticsResults;
-      m_statisticsResults = new BundleResults(*src.m_statisticsResults);
-
-      delete m_images;
-      m_images = new QList<ImageList *>(*src.m_images);
-
-      delete m_adjustedImages;
-      m_adjustedImages = new QList<ImageList *>(*src.m_adjustedImages);
-    }
-    return *this;
+  QString BundleSolutionInfo::savedBundleOutputFilename() {
+    return m_txtBundleOutputFilename;
   }
 
+
+  /**
+   * Returns filename of output bundle images csv file.
+   *
+   * @return QString filename of output bundle images csv file.
+   */
   QString BundleSolutionInfo::savedImagesFilename() {
     return m_csvSavedImagesFilename;
   }
 
+
+  /**
+   * Returns filename of output bundle points csv file.
+   *
+   * @return QString filename of output bundle points csv file.
+   */
   QString BundleSolutionInfo::savedPointsFilename() {
     return m_csvSavedPointsFilename;
   }
 
+
+  /**
+   * Returns filename of output bundle residuals csv file.
+   *
+   * @return QString filename of output bundle residuals csv file.
+   */
   QString BundleSolutionInfo::savedResidualsFilename() {
     return m_csvSavedResidualsFilename;
   }
@@ -203,6 +169,8 @@ namespace Isis {
 
 
   /**
+   * TODO: change description below to something more like english.
+   *
    * Change the on-disk file name for the control network used to be where the control network
    * ought to be in the given project.
    *
@@ -216,10 +184,19 @@ namespace Isis {
 
     //TODO do we need to close anything here?
 
-    FileName oldFileName(*m_controlNetworkFileName);
-    FileName newName(project->cnetRoot() + "/" +
-                     oldFileName.dir().dirName() + "/" + oldFileName.name());
-    *m_controlNetworkFileName = newName.expanded();
+    FileName oldInputFileName(*m_inputControlNetFileName);
+    FileName newInputFileName(project->cnetRoot() + "/" +
+                     oldInputFileName.dir().dirName() + "/" + oldInputFileName.name());
+    *m_inputControlNetFileName = newInputFileName.expanded();
+
+    FileName oldOutputFileName(m_outputControl->fileName());
+    FileName newOutputFileName(project->cnetRoot() + "/" +
+                     oldOutputFileName.dir().dirName() + "/" + oldOutputFileName.name());
+
+    if (m_outputControl) {
+      delete m_outputControl;
+    }
+    m_outputControl = new Control(newOutputFileName.expanded());
   }
 
 
@@ -277,19 +254,49 @@ namespace Isis {
 
 
   /**
-   * Returns the name of the control network.
+   * Returns the name of the input control network.
+   *
+   * @return @b QString The name of the input control network.
+   */
+  QString BundleSolutionInfo::inputControlNetFileName() const {
+    return m_inputControlNetFileName->expanded();
+  }
+
+
+  /**
+   * Returns the name of the output control network.
+   *
+   * @return @b QString The name of the output control network.
+   */
+  QString BundleSolutionInfo::outputControlNetFileName() const {
+    return m_outputControl->fileName();
+  }
+
+
+  /**
+   * Returns the name of the output control network.
+   *
+   * @return @b QString The name of the output control network.
+   */
+  void BundleSolutionInfo::setOutputControl(Control *outputControl) {
+    m_outputControl = outputControl;
+  }
+
+
+  /**
+   * Returns bundle output Control object.
    *
-   * @return @b QString The name of the control network.
+   * @return Control* Pointer to bundle output Control object.
    */
-  QString BundleSolutionInfo::controlNetworkFileName() const {
-    return m_controlNetworkFileName->expanded();
+  Control *BundleSolutionInfo::control() const {
+    return m_outputControl;
   }
 
 
   /**
-   * Returns the bundle settings.
+   * Returns bundle settings.
    *
-   * @return @b BundleSettingsQsp The bundle settings.
+   * @return BundleSettingsQsp Bundle settings.
    */
   BundleSettingsQsp BundleSolutionInfo::bundleSettings() {
     return m_settings;
@@ -538,7 +545,7 @@ namespace Isis {
                   Isis::iTime::CurrentLocalTime().toLatin1().data());
     fpOut << buf;
     sprintf(buf, "\n               Network Filename: %s",
-                  m_controlNetworkFileName->expanded().toLatin1().data());
+                  m_inputControlNetFileName->expanded().toLatin1().data());
     fpOut << buf;
     sprintf(buf, "\n                     Network Id: %s",
                   m_statisticsResults->outputControlNet()->GetNetworkId().toLatin1().data());
@@ -1116,6 +1123,8 @@ namespace Isis {
       return false;
     }
 
+    m_txtBundleOutputFilename = ofname;
+
     char buf[1056];
     BundleObservationQsp observation;
 
@@ -1311,19 +1320,16 @@ namespace Isis {
 
     // print column headers
     if (m_settings->errorPropagation()) {
-      sprintf(buf, "Point,Point,Accepted,Rejected,Residual,3-d,3-d,3-d,Sigma,"
-              "Sigma,Sigma,Correction,Correction,Correction,Coordinate,"
-              "Coordinate,Coordinate\nID,,,,,Latitude,Longitude,Radius,"
-              "Latitude,Longitude,Radius,Latitude,Longitude,Radius,X,Y,Z\n"
-              "Label,Status,Measures,Measures,RMS,(dd),(dd),(km),(m),(m),(m),"
-              "(m),(m),(m),(km),(km),(km)\n");
+      sprintf(buf, ",,,,,3-d,3-d,3-d,Sigma,Sigma,Sigma,Correction,Correction,Correction,Coordinate,"
+              "Coordinate,Coordinate\nPoint,Point,Accepted,Rejected,Residual,Latitude,Longitude,"
+              "Radius,Latitude,Longitude,Radius,Latitude,Longitude,Radius,X,Y,Z\nLabel,Status,"
+              "Measures,Measures,RMS,(dd),(dd),(km),(m),(m),(m),(m),(m),(m),(km),(km),(km)\n");
     }
     else {
-      sprintf(buf, "Point,Point,Accepted,Rejected,Residual,3-d,3-d,3-d,"
-              "Correction,Correction,Correction,Coordinate,Coordinate,"
-              "Coordinate\n,,,,,Latitude,Longitude,Radius,Latitude,"
-              "Longitude,Radius,X,Y,Z\nLabel,Status,Measures,Measures,"
-              "RMS,(dd),(dd),(km),(m),(m),(m),(km),(km),(km)\n");
+      sprintf(buf, ",,,,,3-d,3-d,3-d,Correction,Correction,Correction,Coordinate,Coordinate,"
+              "Coordinate\nPoint,Point,Accepted,Rejected,Residual,Latitude,Longitude,Radius,"
+              "Latitude,Longitude,Radius,X,Y,Z\nLabel,Status,Measures,Measures,RMS,(dd),(dd),(km),"
+              "(m),(m),(m),(km),(km),(km)\n");
     }
     fpOut << buf;
 
@@ -1502,7 +1508,10 @@ namespace Isis {
   void BundleSolutionInfo::save(QXmlStreamWriter &stream, const Project *project,
                                 FileName newProjectRoot) const {
 
+    // TODO: comment below not clear, why is this done?
     // This is done for unitTest which has no Project
+    // SHOULD WE BE CREATING A SERIALIZED PROJECT AS INPUT TO THIS UNIT TEST?
+    QString relativePath;
     QString relativeBundlePath;
     FileName bundleSolutionInfoRoot;
 
@@ -1521,14 +1530,20 @@ namespace Isis {
                              .arg(bundleSolutionInfoRoot.path()),
                            _FILEINFO_);
         }
-        QString oldFile = oldPath + "/" + m_controlNetworkFileName->name();
-        QString newFile = newPath + "/" + m_controlNetworkFileName->name();
-        //QString outputControlFile = m_statisticsResults->outputControlNet()->
+        QString oldFile = oldPath + "/" + FileName(m_outputControl->fileName()).name();
+        QString newFile = newPath + "/" + FileName(m_outputControl->fileName()).name();
         if (!QFile::copy(oldFile, newFile)) {
           throw IException(IException::Io,
                            QString("Failed to copy file [%1] to new file [%2]")
-                             .arg(m_controlNetworkFileName->name()).arg(newFile),
-                           _FILEINFO_);        
+                             .arg(m_outputControl->fileName()).arg(newFile),
+                           _FILEINFO_);
+        }
+        newFile = newPath + "/" + FileName(m_txtBundleOutputFilename).name();
+        if (!QFile::copy(m_txtBundleOutputFilename, newFile)) {
+          throw IException(IException::Io,
+                           QString("Failed to copy file [%1] to new file [%2]")
+                             .arg(m_txtBundleOutputFilename).arg(newFile),
+                           _FILEINFO_);
         }
         newFile = newPath + "/" + FileName(m_csvSavedImagesFilename).name();
         if (!QFile::copy(m_csvSavedImagesFilename, newFile)) {
@@ -1553,7 +1568,14 @@ namespace Isis {
         }
       }
 
-      // Create relative path for bundleSolutionInfo
+      // Create relativePath
+      relativePath = m_inputControlNetFileName->expanded().remove(project->newProjectRoot());
+      // Get rid of any preceding "/" , but add on ending "/"
+      if (relativePath.startsWith("/")) {
+        relativePath.remove(0,1);
+      }
+
+      // Create relativeBundlePath for bundleSolutionInfo
       relativeBundlePath = newPath.remove(project->newProjectRoot());
       // Get rid of any preceding "/" , but add on ending "/"
       if (relativeBundlePath.startsWith("/")) {
@@ -1562,14 +1584,19 @@ namespace Isis {
       relativeBundlePath += "/";
     }
 
+    // TODO: so, we can do the stuff below if project is NULL?
+
     stream.writeStartElement("bundleSolutionInfo");
     // save ID, cnet file name, and run time to stream
     stream.writeStartElement("generalAttributes");
     stream.writeTextElement("id", m_id->toString());
     stream.writeTextElement("name", m_name);
     stream.writeTextElement("runTime", runTime());
-    stream.writeTextElement("fileName",
-                            relativeBundlePath + m_controlNetworkFileName->name());
+
+    stream.writeTextElement("inputFileName",
+                            relativePath);
+    stream.writeTextElement("bundleOutTXT",
+                            relativeBundlePath + FileName(m_txtBundleOutputFilename).name());
     stream.writeTextElement("imagesCSV",
                             relativeBundlePath + FileName(m_csvSavedImagesFilename).name());
     stream.writeTextElement("pointsCSV",
@@ -1593,7 +1620,13 @@ namespace Isis {
         }
         stream.writeEndElement();
       }
+
+      // save output control
+      stream.writeStartElement("outputControl");
+      m_outputControl->save(stream, project, relativeBundlePath);
+      stream.writeEndElement();
     }
+
     stream.writeEndElement(); //end bundleSolutionInfo
   }
 
@@ -1660,10 +1693,15 @@ namespace Isis {
                                                                                 reader());
       }
       else if (localName == "imageList") {
-        // m_xmlHandlerBundleSolutionInfo->m_images->append(new ImageList(m_xmlHandlerProject, reader()));
         m_xmlHandlerBundleSolutionInfo->m_adjustedImages->append(
             new ImageList(m_xmlHandlerProject, reader()));
       }
+      else if (localName == "outputControl") {
+        FileName outputControlPath = FileName(m_xmlHandlerProject->bundleSolutionInfoRoot() + "/"
+                                              + m_xmlHandlerBundleSolutionInfo->runTime());
+
+        m_xmlHandlerBundleSolutionInfo->m_outputControl = new Control(outputControlPath, reader());
+      }
     }
     return true;
   }
@@ -1699,11 +1737,15 @@ namespace Isis {
     else if (localName == "runTime") {
       m_xmlHandlerBundleSolutionInfo->m_runTime = m_xmlHandlerCharacters;
     }
-    else if (localName == "fileName") {
-      assert(m_xmlHandlerBundleSolutionInfo->m_controlNetworkFileName == NULL);
-      m_xmlHandlerBundleSolutionInfo->m_controlNetworkFileName = new FileName(
+    else if (localName == "inputFileName") {
+      assert(m_xmlHandlerBundleSolutionInfo->m_inputControlNetFileName == NULL);
+      m_xmlHandlerBundleSolutionInfo->m_inputControlNetFileName = new FileName(
         projectRoot + m_xmlHandlerCharacters);
     }
+    else if (localName == "bundleOutTXT") {
+      m_xmlHandlerBundleSolutionInfo->m_txtBundleOutputFilename =
+        projectRoot + m_xmlHandlerCharacters;
+    }
     else if (localName == "imagesCSV") {
       m_xmlHandlerBundleSolutionInfo->m_csvSavedImagesFilename = 
         projectRoot + m_xmlHandlerCharacters;
diff --git a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h
index 1d63e18fc397341bf606187ec2457094b50cab59..1991c81fb5fa3c4e451fad00f8c74bec539c31ea 100755
--- a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h
+++ b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h
@@ -36,6 +36,7 @@ class QXmlStreamWriter;
 
 namespace Isis {
   class BundleResults;
+  class Control;
   class FileName;
   class ImageList;
   class Project;  //TODO does xml stuff need project???
@@ -119,6 +120,27 @@ namespace Isis {
    *   @history 2018-01-17 Tracie Sucharski - Added conditional code to check for null project in
    *                           xml serialization to allow the unitTest to use xml serialization
    *                           without having a project. References #5104.
+   *   @history 2018-03-21 Ken Edmundson - Added...
+   *                           1) member variable m_inputControlNetFileName, accessor method, and
+   *                              serialization support. Also added input control net filename to
+   *                              constructor.
+   *                           2) member variable m_outputControl, associated mutator/accessor, and
+   *                              serialization support.
+   *                           3) member variable m_txtBundleOutputFilename and associated accessor
+   *                              for bundleout.txt file.
+   *   @history 2018-03-23 Ken Edmundson - modified...
+   *                           1) removed serialization of output control filename
+   *                           2) serialization of output control to be more robust, ensuring that
+   *                              the control's id is added to project upon reading back in. Also
+   *                              ensures that an open cneteditor widget containing a
+   *                              bundlesolutioninfo's output control is serialized properly.
+   *   @history 2018-03-26 Ken Edmundson - modified save method to properly save output control
+   *                           network file.
+   *   @history 2018-05-22 Ken Edmundson - changed default and copy constructors and assignment
+   *                           operator to private to prevent developer from calling them. Done
+   *                           because BundleSolutionInfo is derived from QObject (see comment
+   *                           below). Removed copy constructor and assignment operator from cpp
+   *                           file.
    */
   class BundleSolutionInfo : public QObject {
     Q_OBJECT
@@ -131,22 +153,24 @@ namespace Isis {
       BundleSolutionInfo(Project *project,
                     XmlStackedHandlerReader *xmlReader,
                     QObject *parent = 0);  //TODO does xml stuff need project???
-      BundleSolutionInfo(const BundleSolutionInfo &src);
       ~BundleSolutionInfo();
-      BundleSolutionInfo &operator=(const BundleSolutionInfo &src);
 
+      QString savedBundleOutputFilename();
       QString savedImagesFilename();
       QString savedPointsFilename();
       QString savedResidualsFilename();
 
       void addAdjustedImages(ImageList *images);
       void setOutputStatistics(BundleResults statisticsResults);
+      void setOutputControl(Control *outputControl);
       void setRunTime(QString runTime);
       void setName(QString name);
 
       QList<ImageList *> adjustedImages() const;
       QString id() const;
-      QString controlNetworkFileName() const;
+      QString inputControlNetFileName() const;
+      QString outputControlNetFileName() const;
+      Control *control() const;
       BundleSettingsQsp bundleSettings();
       BundleResults bundleResults();
       QList<ImageList *> imageList();
@@ -198,28 +222,40 @@ namespace Isis {
       };
 
     private:
+      // NOTE: BundleSolutionInfo is derived from QObject as it has one slot (perhaps more signals
+      //       and slots in the future? As a child of QObject it should have no copy constructor or
+      //       assignment operator. See for example...
+      //
+      //       http://doc.qt.io/qt-5/qobject.html#no-copy-constructor
+      //
+      //       These methods are declared as private to prevent the developer from calling default
+      //       operators. These will generate a compiler error if the developer attempts to use
+      //       them.
       BundleSolutionInfo();
+      BundleSolutionInfo(const BundleSolutionInfo &src);
+      BundleSolutionInfo &operator=(const BundleSolutionInfo &src);
 
       //! A unique ID for this BundleSolutionInfo object (useful for others to reference this
       //! object when saving to disk).
       QUuid              *m_id;
-      QString             m_name; //!< The name of the bundle. Defaults to the id
-      QString             m_runTime; //!< The run time of the bundle adjust
-      FileName           *m_controlNetworkFileName; //!< The name of the control network
-      BundleSettingsQsp   m_settings; //!< The settings from the bundle adjust
-      BundleResults      *m_statisticsResults; //!< The results of the bundle adjust
-      QList<ImageList *> *m_images; //!< The list of images as input to the bundle
-      QList<ImageList *> *m_adjustedImages; //!< The list of images that were adjsuted
-
-      // In theory the path in the BundlesSettings can change while running.  So we save the
+      QString             m_name;                        //!< Name of the bundle. Defaults to the id
+      QString             m_runTime;                     //!< Run time of the bundle adjustment
+      FileName           *m_inputControlNetFileName;     //!< Input control network file name
+      Control            *m_outputControl;               //!< Output control
+      BundleSettingsQsp   m_settings;                    //!< Bundle settings
+      BundleResults      *m_statisticsResults;           //!< Bundle statistical results
+      QList<ImageList *> *m_images;                      //!< Input image list
+      QList<ImageList *> *m_adjustedImages;              //!< Adjusted image list
+
+      // In theory the path in the BundleSettings can change while running. So we save the
       // filenames actually used when the most recent save of the file was done.
+      QString m_txtBundleOutputFilename;
       QString m_csvSavedImagesFilename;
       QString m_csvSavedPointsFilename;
       QString m_csvSavedResidualsFilename;
 
   }; // end BundleSolutionInfo class
 
-
   void setStringAttribute(int locationId, QString locationName,
                           QString attributeName, QString attributeValue);
   QString getStringAttribute(int locationId, QString locationName, QString attributeName);
diff --git a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth
index 8bcf28baf2a7a29d516a7516b8135fdcff49aca3..d94fd75d91e90fb84e38433e3c1fdf0be65bbebf 100644
--- a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth
+++ b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth
@@ -1,12 +1,14 @@
 Unit test for BundleSolutionInfo...
 Serializing results from the settings/cnet/statistics constructor...
+Created new BundleSettings...
 
 <bundleSolutionInfo>
     <generalAttributes>
         
         <name></name>
         <runTime></runTime>
-        <fileName>cnetfile.net</fileName>
+        <inputFileName></inputFileName>
+        <bundleOutTXT></bundleOutTXT>
         <imagesCSV></imagesCSV>
         <pointsCSV></pointsCSV>
         <residualsCSV></residualsCSV>
@@ -99,7 +101,8 @@ Serializing test XML object to file...
         
         <name></name>
         <runTime></runTime>
-        <fileName>cnetfile.net</fileName>
+        <inputFileName></inputFileName>
+        <bundleOutTXT></bundleOutTXT>
         <imagesCSV></imagesCSV>
         <pointsCSV></pointsCSV>
         <residualsCSV></residualsCSV>
@@ -191,280 +194,8 @@ Testing XML: Object deserialized as (should match object above):
         
         <name></name>
         <runTime></runTime>
-        <fileName>cnetfile.net</fileName>
-        <imagesCSV></imagesCSV>
-        <pointsCSV></pointsCSV>
-        <residualsCSV></residualsCSV>
-    </generalAttributes>
-    <bundleSettings>
-        <globalSettings>
-            <validateNetwork>Yes</validateNetwork>
-            <solveOptions solveObservationMode="No" solveRadius="No" updateCubeLabel="No" errorPropagation="No" createInverseMatrix="No"/>
-            <aprioriSigmas latitude="N/A" longitude="N/A" radius="N/A"/>
-            <outlierRejectionOptions rejection="No" multiplier="N/A"/>
-            <convergenceCriteriaOptions convergenceCriteria="Sigma0" threshold="1.0e-10" maximumIterations="50"/>
-            <maximumLikelihoodEstimation/>
-            <outputFileOptions fileNamePrefix=""/>
-        </globalSettings>
-        <observationSolveSettingsList>
-            <bundleObservationSolveSettings>
-                
-                <instrumentId></instrumentId>
-                <instrumentPointingOptions solveOption="AnglesOnly" numberCoefSolved="1" degree="2" solveDegree="2" solveTwist="Yes" solveOverExisting="No" interpolationType="3">
-                    <aprioriPointingSigmas>
-                        <sigma>N/A</sigma>
-                    </aprioriPointingSigmas>
-                </instrumentPointingOptions>
-                <instrumentPositionOptions solveOption="None" numberCoefSolved="0" degree="2" solveDegree="2" solveOverHermiteSpline="No" interpolationType="3">
-                    <aprioriPositionSigmas/>
-                </instrumentPositionOptions>
-            </bundleObservationSolveSettings>
-        </observationSolveSettingsList>
-    </bundleSettings>
-    <bundleResults>
-        <correlationMatrix correlationFileName="" covarianceFileName="">
-            <imagesAndParameters/>
-        </correlationMatrix>
-        <generalStatisticsValues>
-            <numberFixedPoints>0</numberFixedPoints>
-            <numberIgnoredPoints>0</numberIgnoredPoints>
-            <numberHeldImages>0</numberHeldImages>
-            <rejectionLimit>0.0</rejectionLimit>
-            <numberRejectedObservations>0</numberRejectedObservations>
-            <numberObservations>0</numberObservations>
-            <numberImageParameters>0</numberImageParameters>
-            <numberConstrainedPointParameters>0</numberConstrainedPointParameters>
-            <numberConstrainedImageParameters>0</numberConstrainedImageParameters>
-            <numberConstrainedTargetParameters>0</numberConstrainedTargetParameters>
-            <numberUnknownParameters>0</numberUnknownParameters>
-            <degreesOfFreedom>-1</degreesOfFreedom>
-            <sigma0>0.0</sigma0>
-            <converged>No</converged>
-        </generalStatisticsValues>
-        <rms>
-            <residuals x="0.0" y="0.0" xy="0.0"/>
-            <sigmas lat="0.0" lon="0.0" rad="0.0"/>
-            <imageResidualsLists>
-                <residualsList listSize="0"/>
-                <sampleList listSize="0"/>
-                <lineList listSize="0"/>
-            </imageResidualsLists>
-            <imageSigmasLists>
-                <xSigmas listSize="0"/>
-                <ySigmas listSize="0"/>
-                <zSigmas listSize="0"/>
-                <raSigmas listSize="0"/>
-                <decSigmas listSize="0"/>
-                <twistSigmas listSize="0"/>
-            </imageSigmasLists>
-        </rms>
-        <elapsedTime time="0.0" errorProp="0.0"/>
-        <minMaxSigmas>
-            <minLat value="1000000000000.0" pointId=""/>
-            <maxLat value="0.0" pointId=""/>
-            <minLon value="1000000000000.0" pointId=""/>
-            <maxLon value="0.0" pointId=""/>
-            <minRad value="1000000000000.0" pointId=""/>
-            <maxRad value="0.0" pointId=""/>
-        </minMaxSigmas>
-        <maximumLikelihoodEstimation numberModels="0" maximumLikelihoodIndex="0" maximumLikelihoodMedianR2Residuals="0.0">
-            <cumulativeProbabilityCalculator/>
-            <residualsCumulativeProbabilityCalculator/>
-        </maximumLikelihoodEstimation>
-    </bundleResults>
-</bundleSolutionInfo> 
-
-
-Testing copy constructor...
-
-<bundleSolutionInfo>
-    <generalAttributes>
-        
-        <name></name>
-        <runTime></runTime>
-        <fileName>cnetfile.net</fileName>
-        <imagesCSV></imagesCSV>
-        <pointsCSV></pointsCSV>
-        <residualsCSV></residualsCSV>
-    </generalAttributes>
-    <bundleSettings>
-        <globalSettings>
-            <validateNetwork>Yes</validateNetwork>
-            <solveOptions solveObservationMode="No" solveRadius="No" updateCubeLabel="No" errorPropagation="No" createInverseMatrix="No"/>
-            <aprioriSigmas latitude="N/A" longitude="N/A" radius="N/A"/>
-            <outlierRejectionOptions rejection="No" multiplier="N/A"/>
-            <convergenceCriteriaOptions convergenceCriteria="Sigma0" threshold="1.0e-10" maximumIterations="50"/>
-            <maximumLikelihoodEstimation/>
-            <outputFileOptions fileNamePrefix=""/>
-        </globalSettings>
-        <observationSolveSettingsList>
-            <bundleObservationSolveSettings>
-                
-                <instrumentId></instrumentId>
-                <instrumentPointingOptions solveOption="AnglesOnly" numberCoefSolved="1" degree="2" solveDegree="2" solveTwist="Yes" solveOverExisting="No" interpolationType="3">
-                    <aprioriPointingSigmas>
-                        <sigma>N/A</sigma>
-                    </aprioriPointingSigmas>
-                </instrumentPointingOptions>
-                <instrumentPositionOptions solveOption="None" numberCoefSolved="0" degree="2" solveDegree="2" solveOverHermiteSpline="No" interpolationType="3">
-                    <aprioriPositionSigmas/>
-                </instrumentPositionOptions>
-            </bundleObservationSolveSettings>
-        </observationSolveSettingsList>
-    </bundleSettings>
-    <bundleResults>
-        <correlationMatrix correlationFileName="" covarianceFileName="">
-            <imagesAndParameters/>
-        </correlationMatrix>
-        <generalStatisticsValues>
-            <numberFixedPoints>0</numberFixedPoints>
-            <numberIgnoredPoints>0</numberIgnoredPoints>
-            <numberHeldImages>0</numberHeldImages>
-            <rejectionLimit>0.0</rejectionLimit>
-            <numberRejectedObservations>0</numberRejectedObservations>
-            <numberObservations>0</numberObservations>
-            <numberImageParameters>0</numberImageParameters>
-            <numberConstrainedPointParameters>0</numberConstrainedPointParameters>
-            <numberConstrainedImageParameters>0</numberConstrainedImageParameters>
-            <numberConstrainedTargetParameters>0</numberConstrainedTargetParameters>
-            <numberUnknownParameters>0</numberUnknownParameters>
-            <degreesOfFreedom>-1</degreesOfFreedom>
-            <sigma0>0.0</sigma0>
-            <converged>No</converged>
-        </generalStatisticsValues>
-        <rms>
-            <residuals x="0.0" y="0.0" xy="0.0"/>
-            <sigmas lat="0.0" lon="0.0" rad="0.0"/>
-            <imageResidualsLists>
-                <residualsList listSize="0"/>
-                <sampleList listSize="0"/>
-                <lineList listSize="0"/>
-            </imageResidualsLists>
-            <imageSigmasLists>
-                <xSigmas listSize="0"/>
-                <ySigmas listSize="0"/>
-                <zSigmas listSize="0"/>
-                <raSigmas listSize="0"/>
-                <decSigmas listSize="0"/>
-                <twistSigmas listSize="0"/>
-            </imageSigmasLists>
-        </rms>
-        <elapsedTime time="0.0" errorProp="0.0"/>
-        <minMaxSigmas>
-            <minLat value="1000000000000.0" pointId=""/>
-            <maxLat value="0.0" pointId=""/>
-            <minLon value="1000000000000.0" pointId=""/>
-            <maxLon value="0.0" pointId=""/>
-            <minRad value="1000000000000.0" pointId=""/>
-            <maxRad value="0.0" pointId=""/>
-        </minMaxSigmas>
-        <maximumLikelihoodEstimation numberModels="0" maximumLikelihoodIndex="0" maximumLikelihoodMedianR2Residuals="0.0">
-            <cumulativeProbabilityCalculator/>
-            <residualsCumulativeProbabilityCalculator/>
-        </maximumLikelihoodEstimation>
-    </bundleResults>
-</bundleSolutionInfo> 
-
-
-Testing assignment operator to set this equal to itself...
-
-<bundleSolutionInfo>
-    <generalAttributes>
-        
-        <name></name>
-        <runTime></runTime>
-        <fileName>cnetfile.net</fileName>
-        <imagesCSV></imagesCSV>
-        <pointsCSV></pointsCSV>
-        <residualsCSV></residualsCSV>
-    </generalAttributes>
-    <bundleSettings>
-        <globalSettings>
-            <validateNetwork>Yes</validateNetwork>
-            <solveOptions solveObservationMode="No" solveRadius="No" updateCubeLabel="No" errorPropagation="No" createInverseMatrix="No"/>
-            <aprioriSigmas latitude="N/A" longitude="N/A" radius="N/A"/>
-            <outlierRejectionOptions rejection="No" multiplier="N/A"/>
-            <convergenceCriteriaOptions convergenceCriteria="Sigma0" threshold="1.0e-10" maximumIterations="50"/>
-            <maximumLikelihoodEstimation/>
-            <outputFileOptions fileNamePrefix=""/>
-        </globalSettings>
-        <observationSolveSettingsList>
-            <bundleObservationSolveSettings>
-                
-                <instrumentId></instrumentId>
-                <instrumentPointingOptions solveOption="AnglesOnly" numberCoefSolved="1" degree="2" solveDegree="2" solveTwist="Yes" solveOverExisting="No" interpolationType="3">
-                    <aprioriPointingSigmas>
-                        <sigma>N/A</sigma>
-                    </aprioriPointingSigmas>
-                </instrumentPointingOptions>
-                <instrumentPositionOptions solveOption="None" numberCoefSolved="0" degree="2" solveDegree="2" solveOverHermiteSpline="No" interpolationType="3">
-                    <aprioriPositionSigmas/>
-                </instrumentPositionOptions>
-            </bundleObservationSolveSettings>
-        </observationSolveSettingsList>
-    </bundleSettings>
-    <bundleResults>
-        <correlationMatrix correlationFileName="" covarianceFileName="">
-            <imagesAndParameters/>
-        </correlationMatrix>
-        <generalStatisticsValues>
-            <numberFixedPoints>0</numberFixedPoints>
-            <numberIgnoredPoints>0</numberIgnoredPoints>
-            <numberHeldImages>0</numberHeldImages>
-            <rejectionLimit>0.0</rejectionLimit>
-            <numberRejectedObservations>0</numberRejectedObservations>
-            <numberObservations>0</numberObservations>
-            <numberImageParameters>0</numberImageParameters>
-            <numberConstrainedPointParameters>0</numberConstrainedPointParameters>
-            <numberConstrainedImageParameters>0</numberConstrainedImageParameters>
-            <numberConstrainedTargetParameters>0</numberConstrainedTargetParameters>
-            <numberUnknownParameters>0</numberUnknownParameters>
-            <degreesOfFreedom>-1</degreesOfFreedom>
-            <sigma0>0.0</sigma0>
-            <converged>No</converged>
-        </generalStatisticsValues>
-        <rms>
-            <residuals x="0.0" y="0.0" xy="0.0"/>
-            <sigmas lat="0.0" lon="0.0" rad="0.0"/>
-            <imageResidualsLists>
-                <residualsList listSize="0"/>
-                <sampleList listSize="0"/>
-                <lineList listSize="0"/>
-            </imageResidualsLists>
-            <imageSigmasLists>
-                <xSigmas listSize="0"/>
-                <ySigmas listSize="0"/>
-                <zSigmas listSize="0"/>
-                <raSigmas listSize="0"/>
-                <decSigmas listSize="0"/>
-                <twistSigmas listSize="0"/>
-            </imageSigmasLists>
-        </rms>
-        <elapsedTime time="0.0" errorProp="0.0"/>
-        <minMaxSigmas>
-            <minLat value="1000000000000.0" pointId=""/>
-            <maxLat value="0.0" pointId=""/>
-            <minLon value="1000000000000.0" pointId=""/>
-            <maxLon value="0.0" pointId=""/>
-            <minRad value="1000000000000.0" pointId=""/>
-            <maxRad value="0.0" pointId=""/>
-        </minMaxSigmas>
-        <maximumLikelihoodEstimation numberModels="0" maximumLikelihoodIndex="0" maximumLikelihoodMedianR2Residuals="0.0">
-            <cumulativeProbabilityCalculator/>
-            <residualsCumulativeProbabilityCalculator/>
-        </maximumLikelihoodEstimation>
-    </bundleResults>
-</bundleSolutionInfo> 
-
-
-Testing assignment operator to create a new results object...
-
-<bundleSolutionInfo>
-    <generalAttributes>
-        
-        <name></name>
-        <runTime></runTime>
-        <fileName>cnetfile.net</fileName>
+        <inputFileName></inputFileName>
+        <bundleOutTXT></bundleOutTXT>
         <imagesCSV></imagesCSV>
         <pointsCSV></pointsCSV>
         <residualsCSV></residualsCSV>
@@ -555,7 +286,8 @@ Testing mutator methods...
         
         <name>xxx</name>
         <runTime>xxx</runTime>
-        <fileName>cnetfile.net</fileName>
+        <inputFileName></inputFileName>
+        <bundleOutTXT></bundleOutTXT>
         <imagesCSV></imagesCSV>
         <pointsCSV></pointsCSV>
         <residualsCSV></residualsCSV>
@@ -657,7 +389,8 @@ Serializing test XML object to file...
         
         <name>xxx</name>
         <runTime>xxx</runTime>
-        <fileName>cnetfile.net</fileName>
+        <inputFileName></inputFileName>
+        <bundleOutTXT>bundleout.txt</bundleOutTXT>
         <imagesCSV>bundleout_images.csv</imagesCSV>
         <pointsCSV>bundleout_points.csv</pointsCSV>
         <residualsCSV>residuals.csv</residualsCSV>
@@ -760,7 +493,8 @@ Testing XML: Object deserialized as (should match object above):
         
         <name>xxx</name>
         <runTime>xxx</runTime>
-        <fileName>cnetfile.net</fileName>
+        <inputFileName></inputFileName>
+        <bundleOutTXT>bundleout.txt</bundleOutTXT>
         <imagesCSV>bundleout_images.csv</imagesCSV>
         <pointsCSV>bundleout_points.csv</pointsCSV>
         <residualsCSV>residuals.csv</residualsCSV>
diff --git a/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp b/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp
index 7b9c8932d2ccc8e388fc939aa0a83251c6490a23..b6f9a017bfd27af609c506bcc0efb91ea18fee38 100755
--- a/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp
+++ b/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp
@@ -76,8 +76,11 @@ namespace Isis {
  * @internal
  *   @history 2015-09-03 Jeannie Backer - Commented out xml code test until we determine whether
  *                           we will keep this code.
- *   @history 2016-10-13 Ian Humphrey - Changed addnew call to addNew(). References #4293.
- *   @history 2017-04-24 Ian Humphrey - Replaced pvlObject() with XML save(). Fixes #4797.
+ *   @history 2016-10-13 Ian Humphrey -  Changed addnew call to addNew(). References #4293.
+ *   @history 2017-04-24 Ian Humphrey -  Replaced pvlObject() with XML save(). Fixes #4797.
+ *   @history 2018-05-24 Ken Edmundson - Removed testing for copy constructor and assignment
+ *                                       operator because these have been removed from
+ *                                       BundleSolutionInfo.
  */
 int main(int argc, char *argv[]) {
   Preference::Preferences(true);
@@ -90,6 +93,8 @@ int main(int argc, char *argv[]) {
 
     // create default settings and statistics objects to pass into results object
     BundleSettingsQsp settings = BundleSettingsQsp(new BundleSettings);
+    qDebug() << "Created new BundleSettings...";
+
     settings->setOutputFilePrefix("");
     FileName cnetFile("cnetfile.net");
     BundleResults statistics;
@@ -132,16 +137,13 @@ int main(int argc, char *argv[]) {
                              "ObservationNumber1",
                              "Instrument1",
                              BundleSettingsQsp(new BundleSettings));
-
     statistics.setBundleControlPoints(bundleControlPointVector);
     statistics.setOutputControlNet(ControlNetQsp(new ControlNet(outNet)));
     statistics.setObservations(observationVector);
     QList<ImageList *> imgList;
     BundleSolutionInfo results(settings, cnetFile, statistics, imgList, parent);
-
     printXml(results);
 
-
     qDebug() << "";
     qDebug() << "Testing XML serialization 1: round trip serialization of BundleSolution object...";
     qDebug() << "Serializing test XML object to file...";
@@ -168,23 +170,6 @@ int main(int argc, char *argv[]) {
     qDebug() << "Testing XML: Object deserialized as (should match object above):";
     printXml(bsFromXml1);  // Save comparison output to log file
 
-
-
-    qDebug() << "Testing copy constructor...";
-
-    BundleSolutionInfo copySolutionInfo(results);
-    printXml(copySolutionInfo);
-
-    qDebug() << "Testing assignment operator to set this equal to itself...";
-    results = results;
-    printXml(results);
-
-    qDebug() << "Testing assignment operator to create a new results object...";
-
-    BundleSolutionInfo assignmentOpSolutionInfo = results;
-    assignmentOpSolutionInfo = results;
-    printXml(assignmentOpSolutionInfo);
-
     qDebug() << "Testing mutator methods...";
     statistics.setRejectionLimit(0.5);
     results.setOutputStatistics(statistics);
@@ -212,8 +197,6 @@ int main(int argc, char *argv[]) {
     }
     qDebug() << "";
 
-
-
     Statistics rmsStats;
     rmsStats.SetValidRange(0, 100);
     rmsStats.AddData(0);
diff --git a/isis/src/control/objs/ControlNet/ControlNet.cpp b/isis/src/control/objs/ControlNet/ControlNet.cpp
index 6c204b30eb716d7cf0cdc068a72652f8865f754b..9c3a06ebe3c344225ac88ac12f089b671b6e3587 100644
--- a/isis/src/control/objs/ControlNet/ControlNet.cpp
+++ b/isis/src/control/objs/ControlNet/ControlNet.cpp
@@ -237,14 +237,24 @@ namespace Isis {
    *                           parent prematurely to be able to set the radii
    *                           in ControlPoint.
    * @history 2017-12-21 Jesse Mapel - Modified to use the ControlNetVersioner.
-   *
+   * @history 2018-04-05 Adam Goins - Added a check to the versionedReader targetRadii
+   *                         group to set radii values to those ingested from the versioner
+   *                         if they exist. Otherwise, we call SetTarget with the targetname.
    */
   void ControlNet::ReadControl(const QString &filename, Progress *progress) {
 
     FileName cnetFileName(filename);
     ControlNetVersioner versionedReader(cnetFileName, progress);
-
-    SetTarget( versionedReader.targetName() );
+    if ( versionedReader.hasTargetRadii() ) {
+      p_targetName = versionedReader.targetName();
+      p_targetRadii.clear();
+      foreach (Distance distance, versionedReader.targetRadii()) {
+        p_targetRadii.push_back(distance);
+      }
+    }
+    else {
+      SetTarget( versionedReader.targetName() );
+    }
     p_networkId   = versionedReader.netId();
     p_userName    = versionedReader.userName();
     p_created     = versionedReader.creationDate();
@@ -346,8 +356,8 @@ namespace Isis {
 
 
  /**
-   * Adds a whole point to the control net graph. 
-   *    
+   * Adds a whole point to the control net graph.
+   *
    * @throws IException::Programmer "NULL measure passed to ControlNet::AddControlCubeGraphNode!"
    * @throws IException::Programmer "Control measure with NULL parent passed to
    *     ControlNet::AddControlCubeGraphNode!"
diff --git a/isis/src/control/objs/ControlNet/ControlNet.h b/isis/src/control/objs/ControlNet/ControlNet.h
index 56b9f3bead79667853001f1dea34bec2694ad7cd..5ae923fbb948664c0e450fae647fd12c126e3486 100644
--- a/isis/src/control/objs/ControlNet/ControlNet.h
+++ b/isis/src/control/objs/ControlNet/ControlNet.h
@@ -212,7 +212,11 @@ namespace Isis {
    *   @history 2017-01-19 Jesse Mapel - Added a method to get all of the valid measures in an
    *                           image. Previously, this had to be done throug the graph.
    *   @history 2018-01-26 Kristin Berry - Added pointAdded() function to eliminate redundant measure
-   *                           adds to the control network. 
+   *                           adds to the control network.
+   *   @history 2018-04-05 Adam Goins - Added a check to the versionedReader targetRadii
+   *                           group to set radii values to those ingested from the versioner
+   *                           if they exist. Otherwise, we call SetTarget with the targetname.
+   *                           Fixes #5361.
    */
   class ControlNet : public QObject {
       Q_OBJECT
diff --git a/isis/src/control/objs/ControlNet/ControlNet.truth b/isis/src/control/objs/ControlNet/ControlNet.truth
index 13ef6e7272d3f04b3b627134210ad082582a58b9..caa915ff646a406d8487be8b9ef4db5a01aeefe1 100644
--- a/isis/src/control/objs/ControlNet/ControlNet.truth
+++ b/isis/src/control/objs/ControlNet/ControlNet.truth
@@ -147,6 +147,7 @@ Object = ControlNetwork
   Created      = 2010-07-10T12:50:15
   LastModified = 2010-07-10T12:50:55
   Description  = "UnitTest of ControlNetwork"
+  TargetRadii  = (3396190.0, 3396190.0, 3376200.0)
   Version      = 5
 
   Object = ControlPoint
diff --git a/isis/src/control/objs/ControlNetVersioner/ControlNetFileHeaderV0005.proto b/isis/src/control/objs/ControlNetVersioner/ControlNetFileHeaderV0005.proto
index d04e6ca50192996502979d04aff06a18883fe063..424fad3c98ec62f99f7bbcd2f3bdc1b3ac92aafa 100644
--- a/isis/src/control/objs/ControlNetVersioner/ControlNetFileHeaderV0005.proto
+++ b/isis/src/control/objs/ControlNetVersioner/ControlNetFileHeaderV0005.proto
@@ -9,6 +9,6 @@ message ControlNetFileHeaderV0005 {
   optional string lastModified = 4;
   optional string description  = 5;
   optional string userName     = 6;
-  optional int32  numPoints    = 7; 
+  optional int32  numPoints    = 7;
+  repeated double targetRadii = 10;
 }
-
diff --git a/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.cpp b/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.cpp
index f02c607873ca0537c9562ce24ad9341501adb3cd..b261b4c94f5c1c6470c2950034fca9d34d43c030 100644
--- a/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.cpp
+++ b/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.cpp
@@ -63,6 +63,14 @@ namespace Isis {
     header.lastModified = net->GetLastModified();
     header.description = net->Description();
     header.userName = net->GetUserName();
+
+    std::vector<Distance> netRadii = net->GetTargetRadii();
+    if ( netRadii.size() >= 3 &&
+         netRadii[0].isValid() &&
+         netRadii[1].isValid() &&
+         netRadii[2].isValid() ) {
+           header.targetRadii = net->GetTargetRadii();
+         }
     createHeader(header);
   }
 
@@ -158,6 +166,25 @@ namespace Isis {
   }
 
 
+  /**
+  * Returns true if the targetRadii in the header has values.
+  *
+  * @return @b boolean True if the targetRadii in the header is populated.
+  */
+  bool ControlNetVersioner::hasTargetRadii() const {
+    return m_header.targetRadii.empty() ? false : true;
+  }
+
+  /**
+  * Returns the targetRadii Distance vector located in the header.
+  *
+  * @return @b std::vector<Distance> A vector containing the target body radii.
+  */
+  std::vector<Distance> ControlNetVersioner::targetRadii() const {
+    return m_header.targetRadii;
+  }
+
+
   /**
    * Returns the number of points that have been read in or are ready to write out.
    *
@@ -202,24 +229,20 @@ namespace Isis {
     network += PvlKeyword("Created", m_header.created);
     network += PvlKeyword("LastModified", m_header.lastModified);
     network += PvlKeyword("Description", m_header.description);
+
+    // Grab TargetRadii if they exist.
+    if (!m_header.targetRadii.empty()) {
+        PvlKeyword pvlRadii("TargetRadii");
+        for (uint i = 0; i < m_header.targetRadii.size(); i++) {
+          pvlRadii += toString(m_header.targetRadii[i].meters());
+        }
+        network += pvlRadii;
+      }
     // optionally add username to output?
 
     // This is the Pvl version we're converting to
     network += PvlKeyword("Version", "5");
 
-    //  Get Target Radii from naif kernel
-    PvlGroup pvlRadii;
-    QString target = (QString)network.findKeyword("TargetName",Pvl::Traverse);
-    if ( target != "" ) {
-      try {
-        NaifStatus::CheckErrors();
-        pvlRadii = Target::radiiGroup(target);
-      }
-      catch (IException) {
-        // leave pvlRadii empty if target is not recognized by NAIF
-      }
-    }
-
     foreach (ControlPoint *controlPoint, m_points) {
       PvlObject pvlPoint("ControlPoint");
 
@@ -341,11 +364,11 @@ namespace Isis {
           matrix += toString(aprioriCovarianceMatrix(1, 2));
           matrix += toString(aprioriCovarianceMatrix(2, 2));
 
-          if ( pvlRadii.hasKeyword("EquatorialRadius") && pvlRadii.hasKeyword("PolarRadius") ) {
+          if ( !m_header.targetRadii.empty() ) {
 
-            aprioriSurfacePoint.SetRadii( Distance(pvlRadii["EquatorialRadius"], Distance::Meters),
-                                          Distance(pvlRadii["EquatorialRadius"], Distance::Meters),
-                                          Distance(pvlRadii["PolarRadius"], Distance::Meters) );
+            aprioriSurfacePoint.SetRadii( m_header.targetRadii[0],
+                                          m_header.targetRadii[1],
+                                          m_header.targetRadii[2] );
 
             if ( aprioriSurfacePoint.GetLatSigmaDistance().meters() != Isis::Null
                  && aprioriSurfacePoint.GetLonSigmaDistance().meters() != Isis::Null
@@ -424,11 +447,11 @@ namespace Isis {
           matrix += toString(adjustedCovarianceMatrix(1, 2));
           matrix += toString(adjustedCovarianceMatrix(2, 2));
 
-          if ( pvlRadii.hasKeyword("EquatorialRadius") && pvlRadii.hasKeyword("PolarRadius") ) {
+          if ( !m_header.targetRadii.empty() ) {
 
-            adjustedSurfacePoint.SetRadii(Distance(pvlRadii["EquatorialRadius"], Distance::Meters),
-                                          Distance(pvlRadii["EquatorialRadius"], Distance::Meters),
-                                          Distance(pvlRadii["PolarRadius"], Distance::Meters) );
+            adjustedSurfacePoint.SetRadii( m_header.targetRadii[0],
+                                           m_header.targetRadii[1],
+                                           m_header.targetRadii[2] );
 
             if ( adjustedSurfacePoint.GetLatSigmaDistance().meters() != Isis::Null
                  && adjustedSurfacePoint.GetLonSigmaDistance().meters() != Isis::Null
@@ -716,6 +739,7 @@ namespace Isis {
       try {
         PvlObject pointObject = network.object(objectIndex);
         ControlPointV0002 point(pointObject);
+
         m_points.append( createPoint(point) );
 
         if (progress) {
@@ -847,6 +871,16 @@ namespace Isis {
       header.lastModified = network.findKeyword("LastModified")[0];
       header.description = network.findKeyword("Description")[0];
       header.userName = network.findKeyword("UserName")[0];
+      if (network.hasKeyword("TargetRadii")) {
+        header.targetRadii.clear();
+        for (int i = 0; i < network.findKeyword("TargetRadii").size(); i++) {
+          Distance distance = Distance(toDouble(network.findKeyword("TargetRadii")[i]),
+                                           Distance::Meters);
+          if ( distance.isValid() ) {
+            header.targetRadii.push_back(distance);
+          }
+        }
+      }
       createHeader(header);
     }
     catch (IException &e) {
@@ -1170,6 +1204,7 @@ namespace Isis {
   void ControlNetVersioner::readProtobufV0005(const Pvl &header,
                                               const FileName netFile,
                                               Progress *progress) {
+
     // read the header protobuf object
     const PvlObject &protoBufferInfo = header.findObject("ProtoBuffer");
     const PvlObject &protoBufferCore = protoBufferInfo.findObject("Core");
@@ -1228,6 +1263,15 @@ namespace Isis {
       header.lastModified = protoHeader.lastmodified().c_str();
       header.description = protoHeader.description().c_str();
       header.userName = protoHeader.username().c_str();
+      if ( protoHeader.targetradii_size() >= 3 ) {
+        header.targetRadii.clear();
+        for (int i = 0; i < protoHeader.targetradii_size(); i++) {
+          Distance distance = Distance(protoHeader.targetradii(i), Distance::Meters);
+          if ( distance.isValid() ) {
+            header.targetRadii.push_back(distance);
+          }
+        }
+      }
       createHeader(header);
     }
     catch (IException &e) {
@@ -1278,7 +1322,7 @@ namespace Isis {
 
         uint32_t size;
         pointCodedInStream.ReadRaw(reinterpret_cast<char *>(&size), sizeof(size));
-        
+
         size = lsb.Uint32_t(&size);
 
         CodedInputStream::Limit oldPointLimit = pointCodedInStream.PushLimit(size);
@@ -1357,6 +1401,7 @@ namespace Isis {
    * @return @b ControlPoint* The ControlPoint constructed from the given point.
    */
   ControlPoint *ControlNetVersioner::createPoint(ControlPointV0003 &point) {
+
     ControlPointFileEntryV0002 protoPoint = point.pointData();
     ControlPoint *controlPoint = new ControlPoint;
 
@@ -1521,16 +1566,19 @@ namespace Isis {
 
       controlPoint->SetAdjustedSurfacePoint(adjustedSurfacePoint);
     }
+    if (  !m_header.targetRadii.empty() &&
+          m_header.targetRadii[0].isValid() &&
+          m_header.targetRadii[1].isValid() &&
+          m_header.targetRadii[2].isValid() ) {
 
-    if ( m_header.equatorialRadius.isValid() && m_header.polarRadius.isValid() ) {
       SurfacePoint aprioriSurfacePoint = controlPoint->GetAprioriSurfacePoint();
       SurfacePoint adjustedSurfacePoint = controlPoint->GetAdjustedSurfacePoint();
-      aprioriSurfacePoint.SetRadii(m_header.equatorialRadius,
-                                   m_header.equatorialRadius,
-                                   m_header.polarRadius);
-      adjustedSurfacePoint.SetRadii(m_header.equatorialRadius,
-                                    m_header.equatorialRadius,
-                                    m_header.polarRadius);
+      aprioriSurfacePoint.SetRadii(m_header.targetRadii[0],
+                                   m_header.targetRadii[1],
+                                   m_header.targetRadii[2]);
+      adjustedSurfacePoint.SetRadii(m_header.targetRadii[0],
+                                    m_header.targetRadii[1],
+                                    m_header.targetRadii[2]);
       controlPoint->SetAdjustedSurfacePoint(adjustedSurfacePoint);
       controlPoint->SetAprioriSurfacePoint(aprioriSurfacePoint);
     }
@@ -1670,12 +1718,22 @@ namespace Isis {
       m_header.targetName = "Mars";
     }
 
-    if ( !m_header.targetName.isEmpty() ) {
+    if ( m_header.targetRadii.empty() ) {
       try {
-        // attempt to get target radii values...
-        PvlGroup pvlRadii = Target::radiiGroup(m_header.targetName);
-        m_header.equatorialRadius.setMeters(pvlRadii["EquatorialRadius"]);
-        m_header.polarRadius.setMeters(pvlRadii["PolarRadius"]);
+          // attempt to get target radii values...
+          // The target body raii values are read from the PvlV0005 and BinaryV0005
+          // Networks. In the event these values weren't read (from an older network)
+          // then we must grab them from the Target::radii group.
+          if ( !m_header.targetName.isEmpty() ) {
+
+            PvlGroup pvlRadii = Target::radiiGroup(m_header.targetName);
+            m_header.targetRadii.push_back(Distance(pvlRadii["EquatorialRadius"],
+                                             Distance::Meters));
+            m_header.targetRadii.push_back(Distance(pvlRadii["EquatorialRadius"],
+                                             Distance::Meters));
+            m_header.targetRadii.push_back(Distance(pvlRadii["PolarRadius"],
+                                             Distance::Meters));
+          }
        }
        catch (IException &e) {
          // do nothing
@@ -1725,6 +1783,12 @@ namespace Isis {
       protobufHeader.set_description(m_header.description.toLatin1().data());
       protobufHeader.set_username(m_header.userName.toLatin1().data());
 
+      if ( !m_header.targetRadii.empty() ) {
+        for (uint i = 0; i < m_header.targetRadii.size(); i++) {
+          protobufHeader.add_targetradii(m_header.targetRadii[i].meters());
+        }
+      }
+
       streampos coreHeaderSize = protobufHeader.ByteSize();
 
       Pvl p;
@@ -1748,12 +1812,20 @@ namespace Isis {
       netInfo.addComment("This group is for informational purposes only");
       netInfo += PvlKeyword("NetworkId", protobufHeader.networkid().c_str());
       netInfo += PvlKeyword("TargetName", protobufHeader.targetname().c_str());
+
+          // Grab TargetRadii if they exist.
+          if (!m_header.targetRadii.empty()) {
+              PvlKeyword pvlRadii("TargetRadii");
+              for (uint i = 0; i < m_header.targetRadii.size(); i++) {
+                pvlRadii += toString(m_header.targetRadii[i].meters());
+              }
+              netInfo += pvlRadii;
+            }
       netInfo += PvlKeyword("UserName", protobufHeader.username().c_str());
       netInfo += PvlKeyword("Created", protobufHeader.created().c_str());
       netInfo += PvlKeyword("LastModified", protobufHeader.lastmodified().c_str());
       netInfo += PvlKeyword("Description", protobufHeader.description().c_str());
       netInfo += PvlKeyword("NumberOfPoints", toString(numPoints));
-
       netInfo += PvlKeyword("NumberOfMeasures", toString(numMeasures));
       netInfo += PvlKeyword("Version", "5");
       protoObj.addGroup(netInfo);
@@ -1789,6 +1861,12 @@ namespace Isis {
     protobufHeader.set_description(m_header.description.toLatin1().data());
     protobufHeader.set_username(m_header.userName.toLatin1().data());
 
+    if ( !m_header.targetRadii.empty() ) {
+      for (uint i = 0; i < m_header.targetRadii.size(); i++) {
+        protobufHeader.add_targetradii(m_header.targetRadii[i].meters());
+      }
+    }
+
     // Write out the header
     if ( !protobufHeader.SerializeToOstream(output) ) {
       QString msg = "Failed to write output control network file.";
diff --git a/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.h b/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.h
index 14f15a7e01179b3b1e34dcaae323059ea7448e04..03f3484408a7559b50f5264ea696070a83f9dc74 100644
--- a/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.h
+++ b/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.h
@@ -403,6 +403,12 @@ namespace Isis {
    *                           describing the different file format versions.
    *   @history 2018-01-30 Adam Goins - Ensured point sizes are written/read as lsb by using
    *                           EndianSwapper.
+   *   @history 2018-03-28 Adam Goins - Added targetRadii groups to the header. Changed the
+   *                           versioner to write these values out in a targetRadii group for
+   *                           both binary V0005 and PvlV0005 networks. Fixes #5361.
+   *   @history 2018-04-05 Adam Goins - Added hasTargetRadii() and targetRadii() to the versioner
+   *                           so that these values can be grabbed from a ControlNet on read.
+   *                           Also Fixes #5361.
    */
   class ControlNetVersioner {
 
@@ -417,6 +423,8 @@ namespace Isis {
       QString lastModificationDate() const;
       QString description() const;
       QString userName() const;
+      bool hasTargetRadii() const;
+      std::vector<Distance> targetRadii() const;
 
       int numPoints() const;
       ControlPoint *takeFirstPoint();
@@ -471,12 +479,9 @@ namespace Isis {
          * The equatorial radius of the target body
          * used to convert from spherical to rectangular coordinates
          */
-        Distance equatorialRadius;
-        /**
-         * The equatorial radius of the target body
-         * used to convert from spherical to rectangular coordinates
-         */
-        Distance polarRadius;
+
+         std::vector<Distance> targetRadii;
+
       };
 
       //! Typedef for consistent naming of containers for version 2
diff --git a/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.truth b/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.truth
index 956be921b7b9d6f1a0aff1cb670ee89a19e4f8d2..af4a14e71a77d131815baea9b758b3ae5846130a 100644
--- a/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.truth
+++ b/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.truth
@@ -20,6 +20,7 @@ Object = ControlNetwork
   Created      = Null
   LastModified = Null
   Description  = Null
+  TargetRadii  = (3396190.0, 3396190.0, 3376200.0)
   Version      = 5
 
   Object = ControlPoint
@@ -76,6 +77,7 @@ Object = ControlNetwork
   Created      = Null
   LastModified = Null
   Description  = "Test Network"
+  TargetRadii  = (2575000.0, 2575000.0, 2575000.0)
   Version      = 5
 
   Object = ControlPoint
@@ -132,6 +134,7 @@ Object = ControlNetwork
   Created      = 2010-07-10T12:50:15
   LastModified = 2010-07-10T12:50:55
   Description  = "UnitTest of ControlNetwork"
+  TargetRadii  = (3396190.0, 3396190.0, 3376200.0)
   Version      = 5
 
   Object = ControlPoint
@@ -329,6 +332,7 @@ Object = ControlNetwork
   Created      = 2012-01-04T12:09:57
   LastModified = 2012-01-04T12:09:57
   Description  = "Themis Day IR Network: Lunae Palus, Lat(0,30) Lon(270-315)"
+  TargetRadii  = (3396190.0, 3396190.0, 3376200.0)
   Version      = 5
 
   Object = ControlPoint
@@ -559,7 +563,12 @@ After reading and writing to a binary form does Pvl match?
 Conversion to Pvl stays consistent
 Reading/Writing control network is consistent
 Check conversions between the binary format and the pvl format.
-The conversion methods for pvl->bin and bin->pvl are correct.
+8c8,9
+<   Version      = 3
+---
+>   TargetRadii  = (3396190.0, 3396190.0, 3376200.0)
+>   Version      = 5
+The conversion from pvl to binary is incorrect.
 
 Reading: $control/testData/unitTest_ControlNetVersioner_PvlNetwork5_PvlV0003.pvl...
 
diff --git a/isis/src/juno/apps/junocam2isis/junocam2isis.cpp b/isis/src/juno/apps/junocam2isis/junocam2isis.cpp
index b593686592c5628b99fb20bd1a4d72ea764f482b..bac45bad14b828da73aa0faa4e949f8319c01983 100644
--- a/isis/src/juno/apps/junocam2isis/junocam2isis.cpp
+++ b/isis/src/juno/apps/junocam2isis/junocam2isis.cpp
@@ -27,8 +27,10 @@ using namespace Isis;
 void translateLabel(Pvl &inputLabel, Pvl &outputLabel);
 void processFramelets(Buffer &in);
 void processFullFrames(Buffer &in);
+void openNextCube(int index);
 
 QList<Cube *> g_outputCubes;
+QList<QString> g_outputCubeFileNames;
 int g_frameletLines = 0;
 QStringList g_filterList;
 QList<int> g_filterOffsetList; 
@@ -125,6 +127,8 @@ void IsisMain() {
                                      + ".cub");
       fullFrameCube->create(fullFrameCubeFileName.expanded());
       g_outputCubes.append(fullFrameCube);
+      fullFrameCube->close();
+      g_outputCubeFileNames.append(fullFrameCubeFileName.expanded());
       allCubesListWriter << fullFrameCubeFileName.baseName() << ".cub\n";
     }
     progress.CheckStatus();
@@ -141,7 +145,10 @@ void IsisMain() {
     for (int i = 0; i < numFullFrames; i++) {
       progress.CheckStatus();
       for (int j = 0; j < outputLabel.findObject("IsisCube").groups(); j++) {
-        g_outputCubes[i]->putGroup(outputLabel.findObject("IsisCube").group(j));
+        if (!g_outputCubes[i]->isOpen()) {
+          g_outputCubes[i]->open(g_outputCubeFileNames[i], "rw");
+        }
+        g_outputCubes[i]->putGroup(outputLabel.findObject("IsisCube").group(j)); 
       }
       // Update the labels
       Pvl *fullFrameLabel = g_outputCubes[i]->label();
@@ -163,7 +170,6 @@ void IsisMain() {
     progress.CheckStatus();
   }
   else { 
-
     // Process individual framelets: For now, keep processing the "old" way.
     int numSubimages = importPds.Lines() / g_frameletLines;
     int frameletsPerFilter = numSubimages / g_filterList.size();
@@ -184,6 +190,7 @@ void IsisMain() {
     Progress progress;
     progress.SetText("Setting up output framelet cubes.");
     progress.SetMaximumSteps(numSubimages);
+
     for (int i = 0; i < numSubimages; i++) {
       progress.CheckStatus();
       Cube *frameletCube = new Cube();
@@ -196,10 +203,12 @@ void IsisMain() {
                                     + "_" + g_filterList[filterIndex] 
                                     + "_" + frameletNumString 
                                     + ".cub");
-      frameletCube->create(frameletCubeFileName.expanded());
 
+      frameletCube->create(frameletCubeFileName.expanded());
       g_outputCubes.append(frameletCube);
-
+      frameletCube->close();
+      g_outputCubeFileNames.append(frameletCubeFileName.expanded());
+      
       QFile filterListFile(outputBaseName + "_" + g_filterList[filterIndex] + ".lis");
       if ( (frameletNumber == 1 && !filterListFile.open(QFile::WriteOnly | QFile::Text))
            || (frameletNumber > 1 && !filterListFile.open(QFile::Append | QFile::Text)) ) {
@@ -212,6 +221,7 @@ void IsisMain() {
       filterListWriter << frameletCubeFileName.baseName() << ".cub\n";
       filterListFile.close();
     }
+
     progress.CheckStatus();
     allCubesListFile.close();
 
@@ -224,7 +234,12 @@ void IsisMain() {
     progress.SetText("Updating labels of output cubes.");
     progress.SetMaximumSteps(numSubimages);
     for (int i = 0; i < numSubimages; i++) {
-      // fix labels
+      // re-open cube
+      QString cubeFileName = g_outputCubes[i]->fileName(); 
+      if ( !g_outputCubes[i]->isOpen() ) {
+        g_outputCubes[i]->open(g_outputCubeFileNames[i], "rw"); 
+      }
+      // fromeix labels
       progress.CheckStatus();
       for (int j = 0; j < outputLabel.findObject("IsisCube").groups(); j++) {
         g_outputCubes[i]->putGroup(outputLabel.findObject("IsisCube").group(j));
@@ -349,6 +364,20 @@ void translateLabel(Pvl &inputLabel, Pvl &outputLabel) {
 
 }
 
+/**
+ * Opens cube from g_outputCubes at provided index, closes cube at index-1 (last cube) 
+ */
+void openNextCube(int nextCubeIndex) {
+  if (nextCubeIndex >= 1) {
+    if (g_outputCubes[nextCubeIndex-1]->isOpen()) {
+      g_outputCubes[nextCubeIndex - 1]->close(); 
+    }
+  }
+  if (!g_outputCubes[nextCubeIndex]->isOpen()) {
+    g_outputCubes[nextCubeIndex]->open(g_outputCubeFileNames[nextCubeIndex], "rw"); 
+  }
+}
+
 
 /**
  * Separates each of the individual frames into their own file. 
@@ -359,6 +388,12 @@ void processFramelets(Buffer &in) {
   // get the index for the correct output cube
   int outputCube = (in.Line() - 1) / g_frameletLines % g_outputCubes.size();
 
+  // When we move to a new framlet, close the old cube and open the next one to avoid
+  // having too many cubes open and hitting the open file limit. 
+  if( ((in.Line() - 1) % g_frameletLines) == 0 ) {
+    openNextCube(outputCube);
+  }
+
   LineManager mgr(*g_outputCubes[outputCube]);
   int outputCubeLineNumber = (in.Line()-1) % g_frameletLines + 1;
   mgr.SetLine(outputCubeLineNumber, 1);
@@ -379,6 +414,12 @@ void processFullFrames(Buffer &in) {
   // get the index for the correct output cube
   int outputCube = (in.Line() - 1) / g_fullFrameLines % g_outputCubes.size();
 
+  // When we move to a new framlet, close the old cube and open the next one to avoid
+  // having too many cubes open and hitting the open file limit. 
+  if( ((in.Line() - 1) % g_fullFrameLines) == 0 ) {
+    openNextCube(outputCube);
+  }
+
   LineManager mgr(*g_outputCubes[outputCube]);
   
   int outputCubeLineNumber = ((in.Line()-1) % g_fullFrameLines);
diff --git a/isis/src/juno/apps/junocam2isis/junocam2isis.xml b/isis/src/juno/apps/junocam2isis/junocam2isis.xml
index d23d0dcd183dc69d03d4c1675ce871a71276f1b5..b984d970c3753d9088b0234464a93d7fe22246a7 100644
--- a/isis/src/juno/apps/junocam2isis/junocam2isis.xml
+++ b/isis/src/juno/apps/junocam2isis/junocam2isis.xml
@@ -88,6 +88,9 @@ xsi:noNamespaceSchemaLocation="http://isis.astrogeology.usgs.gov/Schemas/Applica
     <change name="Kaitlyn Lee" date="2018-02-07">
       Added missionItem under category to classify the program under Juno.
     </change>
+    <change name="Kristin Berry" date="2018-03-27">
+      Fixed problem with having too many open files. See #5232 for more information. 
+    </change>
   </history>
 
   <category>
diff --git a/isis/src/juno/objs/JunoCamera/JunoCamera.cpp b/isis/src/juno/objs/JunoCamera/JunoCamera.cpp
index 3fbb754ec474c68d79728d9fbda49d81e4415121..f7c098c86486cc50eb85315b126d6b0cb2acda68 100644
--- a/isis/src/juno/objs/JunoCamera/JunoCamera.cpp
+++ b/isis/src/juno/objs/JunoCamera/JunoCamera.cpp
@@ -48,7 +48,7 @@ namespace Isis {
 
     m_spacecraftNameLong = "Juno";
     m_spacecraftNameShort = "Juno";
-    
+
     NaifStatus::CheckErrors();
 
     // Set up the camera characteristics
@@ -73,7 +73,7 @@ namespace Isis {
       detMap->SetDetectorSampleSumming(summing);
       detMap->SetDetectorLineSumming(summing);
     }
-    
+
     // Juno codes
     int junoCode = naifIkCode();
     QString juno = toString(junoCode);
@@ -111,7 +111,7 @@ namespace Isis {
 
     // get start et for this frame, in seconds
     double frameStartEt = observationStartEt + startTimeBias + (frameNumber - 1)
-                             * (exposureDur + interFrameDelay + interFrameDelayBias);
+                             * (interFrameDelay + interFrameDelayBias);
     // Set start time to center of exposure time to ensure the proper SPICE data is cached.
     setTime(frameStartEt + exposureDur / 2.0);
 
@@ -123,24 +123,24 @@ namespace Isis {
   /**
    * Destroys the JunoCamera object.
    */
-  JunoCamera::~JunoCamera() { 
+  JunoCamera::~JunoCamera() {
   }
 
 
   /**
    * Returns the shutter open and close times.  The user should pass in the
    * ExposureDuration keyword value, converted from milliseconds to seconds, and
-   * the SpacecraftClockCount keyword value, converted to ephemeris time. The 
-   * StartTime keyword value from the labels represents the shutter open time of 
-   * the observation. This method uses the FramingCamera class implementation, 
-   * returning the given time value as the shutter open and the sum of the time 
+   * the SpacecraftClockCount keyword value, converted to ephemeris time. The
+   * StartTime keyword value from the labels represents the shutter open time of
+   * the observation. This method uses the FramingCamera class implementation,
+   * returning the given time value as the shutter open and the sum of the time
    * value and exposure duration as the shutter close.
-   * 
+   *
    * @param exposureDuration Exposure duration value from the labels, converted
    *                         to seconds.
-   * @param time The SpacecraftClockCount value from the labels, converted to 
+   * @param time The SpacecraftClockCount value from the labels, converted to
    *             ephemeris time
-   * 
+   *
    * @return @b pair < @b iTime, @b iTime > The first value is the shutter
    *         open time and the second is the shutter close time.
    */
@@ -152,9 +152,9 @@ namespace Isis {
 
 
   /**
-   * Retrieves the CK frame ID for the JunoCam instrument. 
-   *  
-   * @return @b int The appropriate instrument code for the "Camera-matrix" 
+   * Retrieves the CK frame ID for the JunoCam instrument.
+   *
+   * @return @b int The appropriate instrument code for the "Camera-matrix"
    *                Kernel Frame ID.
    */
   int JunoCamera::CkFrameId() const {
@@ -162,9 +162,9 @@ namespace Isis {
   }
 
 
-  /** 
-    * Retrieves the J2000 CK Reference ID for the JunoCam instrument. 
-    * 
+  /**
+    * Retrieves the J2000 CK Reference ID for the JunoCam instrument.
+    *
     * @return @b int The appropriate instrument code for the "Camera-matrix"
     *                Kernel Reference ID.
     */
@@ -184,10 +184,10 @@ namespace Isis {
   }
 
 
-  /** 
+  /**
     * Retrieves the J2000 SPK Reference ID for the JunoCam instrument.
-    *  
-    * @return @b int The appropriate instrument code for the Spacecraft 
+    *
+    * @return @b int The appropriate instrument code for the Spacecraft
     *                Kernel Reference ID.
     */
   int JunoCamera::SpkReferenceId() const {
diff --git a/isis/src/juno/objs/JunoCamera/JunoCamera.h b/isis/src/juno/objs/JunoCamera/JunoCamera.h
index 142edd90c4ddaded2286a737382a35b65ae54372..a61108f25c785899452562f9d814fbe212dbca9a 100644
--- a/isis/src/juno/objs/JunoCamera/JunoCamera.h
+++ b/isis/src/juno/objs/JunoCamera/JunoCamera.h
@@ -34,20 +34,22 @@ namespace Isis {
    * framing instrument. This is
    * also a more flexible camera model since it will make controlling the
    * individual framelets alot easier.
-   * 
+   *
    * @ingroup SpiceInstrumentsAndCameras
    * @ingroup Juno
    * @author 2017-07-22 Jeannie Backer
    *
    * @internal
-   *   @history 2017-07-22 Jeannie Backer - Original version. 
+   *   @history 2017-07-22 Jeannie Backer - Original version.
+   *   @history 2018-04-25 Jesse Mapel - Modified frame start calculation to not
+   *                           use exposure duration. Fixes #5236.
    */
   class JunoCamera : public FramingCamera {
     public:
       JunoCamera(Cube &cube);
       ~JunoCamera();
 
-      virtual std::pair <iTime, iTime> ShutterOpenCloseTimes(double time, 
+      virtual std::pair <iTime, iTime> ShutterOpenCloseTimes(double time,
                                                              double exposureDuration);
       virtual int CkFrameId() const;
       virtual int CkReferenceId() const;
diff --git a/isis/src/qisis/apps/cneteditor/main.cpp b/isis/src/qisis/apps/cneteditor/main.cpp
index eb14ee5096183dbfbcf532e24baaa9c867e5078c..66ec01dbfbc1b5e41ab41af30b2e4638734df3c3 100644
--- a/isis/src/qisis/apps/cneteditor/main.cpp
+++ b/isis/src/qisis/apps/cneteditor/main.cpp
@@ -1,5 +1,7 @@
 #include "IsisDebug.h"
 
+#include <iostream>
+
 #include "CnetEditorWindow.h"
 #include "QIsisApplication.h"
 
@@ -7,6 +9,10 @@ using namespace Isis;
 
 int main(int argc, char ** argv)
 {
+  if (getenv("ISISROOT") == NULL || QString(getenv("ISISROOT")) == "") {
+    std::cerr << "Please set ISISROOT before running any Isis applications" << std::endl;
+    exit(1);
+  }
   QIsisApplication app(argc, argv);
   CnetEditorWindow window;
   window.show();
diff --git a/isis/src/qisis/apps/ipce/IpceMainWindow.cpp b/isis/src/qisis/apps/ipce/IpceMainWindow.cpp
index d33730594b8a1045e4acaf598a589b8a41f400d2..b16393e6c57490f3ba0ac1a3f3434069d34e1002 100644
--- a/isis/src/qisis/apps/ipce/IpceMainWindow.cpp
+++ b/isis/src/qisis/apps/ipce/IpceMainWindow.cpp
@@ -91,6 +91,7 @@ namespace Isis {
       m_directory = new Directory(this);
       connect(m_directory, SIGNAL( newWidgetAvailable(QWidget *) ),
               this, SLOT( addView(QWidget *) ) );
+      connect(m_directory, SIGNAL(viewClosed(QWidget *)), this, SLOT(removeView(QWidget *)));
       connect(m_directory, SIGNAL( directoryCleaned() ),
               this, SLOT( removeAllViews() ) );
       connect(m_directory->project(), SIGNAL(projectLoaded(Project *)),
@@ -231,6 +232,38 @@ namespace Isis {
       }
     }
   }
+
+
+  /**
+   * @description This slot is connected from Directory::viewClosed(QWidget *) signal.  It will 
+   * close the given QMdiSubWindow from the QMdiArea.  This will also delete the widget contained 
+   * within the subwindow which is an AbstractProjectItemView. 
+   * 
+   * @param view QWidget* 
+   *
+   */
+  void IpceMainWindow::removeView(QWidget *view) {
+
+    QMdiArea *mdiArea = qobject_cast<QMdiArea *>( centralWidget() );
+    if (mdiArea){
+      // Get all QMdiSubWindows, then find subwindow that hold widget
+      QList<QMdiSubWindow *> subWindowList = mdiArea->subWindowList();
+      foreach (QMdiSubWindow *sub, subWindowList) {
+        if (sub->widget() == view) {
+          sub->close();
+          break;
+        }
+      }
+//    QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(view);
+//    qDebug()<<"IpceMainWindow::removeView activewindow = "<<window;
+//    mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(view));
+//    qDebug()<<"IpceMainWindow::removeView";
+//    mdiArea->closeActiveSubWindow();
+      delete view;
+    }
+  }
+
+
   /**
    * Removes All Views in main window, connected to directory signal directoryCleaned()
    */
@@ -238,12 +271,12 @@ namespace Isis {
     setWindowTitle("ipce");
     QMdiArea *mdiArea = qobject_cast<QMdiArea *>( centralWidget() );
     if (mdiArea){
-      QMdiSubWindow* window = new QMdiSubWindow();
-      window->show();
-      window->activateWindow();
-      mdiArea->addSubWindow(window);
+//    QMdiSubWindow* window = new QMdiSubWindow();
+//    window->show();
+//    window->activateWindow();
+//    mdiArea->addSubWindow(window);
       mdiArea->closeAllSubWindows();
-      delete window;
+//    delete window;
     }
     if (!m_detachedViews.isEmpty()) {
       foreach ( QMainWindow* view, m_detachedViews ) {
@@ -411,7 +444,13 @@ namespace Isis {
       m_permToolBar->addAction(action);
     }
     foreach (QAction *action, m_permToolBarActions) {
-      m_permToolBar->addAction(action);
+      if (action->text() == "&Save Active Control Network") {
+        m_permToolBar->addSeparator();
+      }
+      m_permToolBar->addAction(action); 
+      if (action->text() == "&Save Active Control Network") {
+        m_permToolBar->addSeparator();
+      }
     }
     m_permToolBar->addSeparator();
     if (m_activeView) {
@@ -515,6 +554,30 @@ namespace Isis {
     m_fileMenuActions.append(exitAction);
     m_permToolBarActions.append(exitAction);
 
+    QAction *saveNet = new QAction("&Save Active Control Network", this);
+    saveNet->setIcon( QIcon::fromTheme("document-save") );
+    saveNet->setShortcut(Qt::CTRL + Qt::Key_S);
+    saveNet->setToolTip("Save current active control network");
+    saveNet->setStatusTip("Save current active control network");
+    QString whatsThis = "<b>Function:</b> Saves the current active<i>"
+                        "control network</i>";
+    saveNet->setWhatsThis(whatsThis);
+    connect(saveNet, SIGNAL(triggered()), m_directory, SLOT(saveActiveControl()));
+    m_permToolBarActions.append(saveNet);
+
+//  m_saveAsNet = new QAction(QPixmap(toolIconDir() + "/mActionFileSaveAs.png"),
+//                            "Save Control Network &As...",
+//                            m_matchTool);
+//  m_saveAsNet->setToolTip("Save current control network to chosen file");
+//  m_saveAsNet->setStatusTip("Save current control network to chosen file");
+//  whatsThis = "<b>Function:</b> Saves the current <i>"
+//      "control network</i> under chosen filename";
+//  m_saveAsNet->setWhatsThis(whatsThis);
+//  connect(m_saveAsNet, SIGNAL(triggered()), this, SLOT(saveAsNet()));
+
+
+
+
     QAction *undoAction = m_directory->undoAction();
     undoAction->setShortcut(Qt::Key_Z | Qt::CTRL);
 
@@ -806,7 +869,11 @@ namespace Isis {
    * state information before forwarding the event to the QMainWindow.
    */
   void IpceMainWindow::closeEvent(QCloseEvent *event) {
-    if (!m_directory->project()->isClean()) {
+
+    // The active control is checked here for modification because this was the simplest solution
+    // vs changing the project clean state every time the control is modified or saved.
+    if (!m_directory->project()->isClean() || (m_directory->project()->activeControl() &&
+                                               m_directory->project()->activeControl()->isModified())) {
       QMessageBox *box = new QMessageBox(QMessageBox::NoIcon, QString("Current Project Has Unsaved Changes"),
                              QString("Would you like to save your current project?"),
                              NULL, qobject_cast<QWidget *>(parent()), Qt::Dialog);
@@ -1045,7 +1112,7 @@ namespace Isis {
     menuBar->addMenu(viewMenu);
 
     if ( !view->settingsMenuActions().isEmpty() ) {
-      QMenu *settingsMenu = new QMenu("&Settings", newWindow);
+      QMenu *settingsMenu = new QMenu("S&ettings", newWindow);
       foreach ( QAction *action, view->settingsMenuActions() ) {
         settingsMenu->addAction(action);
       }
diff --git a/isis/src/qisis/apps/ipce/IpceMainWindow.h b/isis/src/qisis/apps/ipce/IpceMainWindow.h
index f65ab04bf6eee7cd0e52182f538bf487c8ca29d7..b56d732babaae7b345f0f0f71351546a769e7e3b 100644
--- a/isis/src/qisis/apps/ipce/IpceMainWindow.h
+++ b/isis/src/qisis/apps/ipce/IpceMainWindow.h
@@ -123,6 +123,13 @@ namespace Isis {
    *                           the history dock. Fixes #5151.
    *   @history 2018-03-02 Tracie Sucharski - added static keyword to the m_maxRecentProject member
    *                           variable, fixes OSX compile warning.  References #5341.
+   *   @history 2018-04-04 Tracie Sucharski - Added removeView slot which removes the view
+   *                           containing the given widget. In the closeEvent method check whether
+   *                           there is an active control and if it has been modified as additional
+   *                           test to determine whether project needs saving.
+   *   @history 2018-05-01 Tracie Sucharski - Code accidently left commented from previous checking.
+   *                           Fixes #5412.
+   *  
    */
   class IpceMainWindow : public QMainWindow {
       Q_OBJECT
@@ -132,6 +139,7 @@ namespace Isis {
 
     public slots:
       void addView(QWidget *newWidget);
+      void removeView(QWidget *view);
       void removeAllViews();
 
       void setActiveView(AbstractProjectItemView *view);
diff --git a/isis/src/qisis/apps/ipce/ipce.cpp b/isis/src/qisis/apps/ipce/ipce.cpp
index 39b482c1c2492dba8b92e5f7b89cb8eb151bc827..71d15134f7d5482f641515aad40b691e74eb22a9 100644
--- a/isis/src/qisis/apps/ipce/ipce.cpp
+++ b/isis/src/qisis/apps/ipce/ipce.cpp
@@ -26,6 +26,7 @@
 #include <QLocale>
 #include <QTranslator>
 
+#include "FileName.h"
 #include "Gui.h"
 #include "IException.h"
 #include "IpceMainWindow.h"
@@ -35,15 +36,27 @@ using namespace std;
 using namespace Isis;
 
 int main(int argc, char *argv[]) {
-
+  if (getenv("ISISROOT") == NULL || QString(getenv("ISISROOT")) == "") {
+    std::cerr << "Please set ISISROOT before running any Isis applications" << std::endl;
+    exit(1);
+  }
   Gui::checkX11();
 
   try {
+
+    // Add the Qt plugin directory to the library path
+    FileName qtpluginpath("$ISISROOT/3rdParty/plugins");
+    QCoreApplication::addLibraryPath(qtpluginpath.expanded());
+
     QApplication *app = new QIsisApplication(argc, argv);
     QApplication::setApplicationName("ipce");
 
     IpceMainWindow *mainWindow = new IpceMainWindow();
 
+    //  For OSX, had problems with cneteditor view because it has it's own menus, caused the
+    //  menubar on OSX to lockup
+    QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, true);
+
     // We do not want a showMaximized call, as that will negate the settings read during the main
     // window's initialization. References #4358.
     mainWindow->show();
diff --git a/isis/src/qisis/apps/qmos/qmos.cpp b/isis/src/qisis/apps/qmos/qmos.cpp
index b39bec5ef856d2005dec12459219cc3455b34878..2036d20443b9b74c36edf1c4e1e40049292e3eab 100644
--- a/isis/src/qisis/apps/qmos/qmos.cpp
+++ b/isis/src/qisis/apps/qmos/qmos.cpp
@@ -13,6 +13,10 @@ using namespace std;
 using namespace Isis;
 
 int main(int argc, char *argv[]) {
+  if (getenv("ISISROOT") == NULL || QString(getenv("ISISROOT")) == "") {
+    std::cerr << "Please set ISISROOT before running any Isis applications" << std::endl;
+    exit(1);
+  }
   Isis::Gui::checkX11();
 
   // Add the Qt plugin directory to the library path
diff --git a/isis/src/qisis/apps/qnet/qnet.cpp b/isis/src/qisis/apps/qnet/qnet.cpp
index cdcfe8ae6cbd232b5efd9dae69f2d27d81b49798..0783844c4ceccf9930131be06e6204ae3567585e 100644
--- a/isis/src/qisis/apps/qnet/qnet.cpp
+++ b/isis/src/qisis/apps/qnet/qnet.cpp
@@ -40,6 +40,10 @@ ToolClass *createTool(ViewportMainWindow *viewportMainWindow, ToolList *tools) {
 }
 
 int main(int argc, char *argv[]) {
+  if (getenv("ISISROOT") == NULL || QString(getenv("ISISROOT")) == "") {
+    std::cerr << "Please set ISISROOT before running any Isis applications" << std::endl;
+    exit(1);
+  }
   Isis::Gui::checkX11();
 
   try {
diff --git a/isis/src/qisis/apps/qtie/qtie.cpp b/isis/src/qisis/apps/qtie/qtie.cpp
index 852a869d11122f8acb1de8248fc08dec0e992dd1..004e928ad18b00a37af047148398751296ba616d 100644
--- a/isis/src/qisis/apps/qtie/qtie.cpp
+++ b/isis/src/qisis/apps/qtie/qtie.cpp
@@ -33,7 +33,10 @@ ToolClass *createTool(ViewportMainWindow *viewportMainWindow, ToolList *tools) {
 }
 
 int main(int argc, char *argv[]) {
-
+  if (getenv("ISISROOT") == NULL || QString(getenv("ISISROOT")) == "") {
+    std::cerr << "Please set ISISROOT before running any Isis applications" << std::endl;
+    exit(1);
+  }
   Isis::Gui::checkX11();
 
   try {
diff --git a/isis/src/qisis/apps/qview/qview.cpp b/isis/src/qisis/apps/qview/qview.cpp
index 95253f46c577b247fe09fe950cab6f20c2428e61..5dcf578b49f58c95c231db5204ff3296e263e249 100644
--- a/isis/src/qisis/apps/qview/qview.cpp
+++ b/isis/src/qisis/apps/qview/qview.cpp
@@ -60,6 +60,10 @@ ToolClass *createTool(ViewportMainWindow *viewportMainWindow, ToolList *tools) {
 }
 
 int main(int argc, char *argv[]) {
+  if (getenv("ISISROOT") == NULL || QString(getenv("ISISROOT")) == "") {
+    std::cerr << "Please set ISISROOT before running any Isis applications" << std::endl;
+    exit(1);
+  }
   Isis::Gui::checkX11();
 
   // Add the Qt plugin directory to the library path
diff --git a/isis/src/qisis/apps/qview/qview.xml b/isis/src/qisis/apps/qview/qview.xml
index 535a410b75762fa39694a31863a639cb60147b6f..3e7cd5c56aad197ab2db793dbcadddae4a54d50b 100644
--- a/isis/src/qisis/apps/qview/qview.xml
+++ b/isis/src/qisis/apps/qview/qview.xml
@@ -6,7 +6,103 @@
   </brief>
 
   <description>
-    This program will display cubes and allow for interactive analysis.
+    <p>
+      This program will display cubes and allow for interactive analysis. Although the program 
+      comprises a number of individual tools to perform analysis on your data, only the Spatial 
+      Plot Tool is discussed here until further notice.  
+    </p>
+    <h3>Spatial Plot Tool</h3>
+    <p>
+      This tool is used for analyzing manually selected pixel DN values. It works with two 
+      different modes: linear and rotated rectangle. It is also capable of handling three different 
+      modes of interpolation: Nearest Neighbor, BiLinear and Cubic Convolution. 
+    </p>
+    <h4>Linear</h4>
+    <p>
+      This mode involves drawing a 
+      line across an open cube. The selection is started by clicking and holding the mouse where 
+      you would like to start your calculations, at which point you may drag the mouse in any 
+      direction and release the click to establish the end of your selection.
+    </p>
+    <p>
+      The tool calculates the length of the line in pixels, rounding to the nearest full pixel 
+      value. It then divides the actual length of the line by this rounded length to achieve a 
+      step-size. <strong>Please note:</strong> This step size may be slightly bigger or smaller 
+      than a pixel length, but this difference becomes negligible for larger selections. For 
+      example, if the length of the drawn line was 2.91 pixels, the tool would round the length to 
+      3 and the step-size would be 2.91/3 (or 0.97).
+    </p>
+    <p>
+      A plot window will be generated with the calculated DN values of the pixels. The first value 
+      to be calculated is the value where the original mouse click was made. At each increment, 
+      according to step size, the tool calculates the value along the line until it reaches where the 
+      mouse-click was released. This means that for a line with a rounded length of 3, the plot would show a 
+      total of 4 plotted DN values. <strong>Please note:</strong> For a line with a rounded length of 
+      <i>n</i>, the tool will calculate <i>n</i> + 1 values.
+    </p>
+    <image src="assets/image/LinearSelection.png" height="400" />
+    <image src="assets/image/LinearPlot.png" height="400" />
+    <p>
+      The images above include an example of the line as drawn in the cube view and the 
+      associated plot window. Marking has been added to delineate where mouse clicks were made and 
+      the DN values were calculated. The mouse was first clicked at dileneation marked "1" on the 
+      cube, and was released at "4". The number from the cube view correlates with the "Pixel 
+      Number" on the plot.
+      
+    </p>
+    <h4>Rotated Rectangle</h4>
+    <p>
+      This mode of the Spatial Plot Tool involves drawing a 
+      rectangle across an open cube. The selection starts by clicking and holding the mouse 
+      where you would like to start your calculations, at which point you may drag the mouse in any 
+      direction and release the click to establish one edge of your selection. You may then 
+      drag the mouse away from this original line to expand in the other direction. A single mouse 
+      click establishes your final selection. <strong>Please note:</strong> The tool will lock 
+      angles to be perpendicular and so your selections will always be a perfect rectangle.
+    </p>
+
+    <p>
+      Similar to the linear mode of this tool, the lengths of the lines in pixels are rounded to the 
+      nearest full pixel value, and then the lengths are divided by their rounded lengths to establish 
+      a step-size. <strong>Please note:</strong>
+      The step-size along one edge of the selection may differ from the step-size of the 
+      perpendicular edge, this becomes negligible for larger selections. For 
+      example, if the length of the line in one direction was 2.91 pixels, the step-size would be 2.91/3 
+      (or 0.97), whereas if the length of the line in the perpendicular direction was 4.92, the step 
+      size would be 4.92/5 (0.98).
+    </p>
+    <p>
+      A plot window will be generated with the calculated DN values. This is done by calculating the 
+      value where the original mouse click was made, then continuing in the direction of that 
+      first-drawn line, calculating the DN value at each step-sized increment until it reaches where 
+      the original mouse-click was released. The tool will then calculate the average of these 
+      values. This average becomes the first value in the plot.
+    </p>
+    <p>
+      The tool will then shift a step-size along the perpendicular edge, and calculate the average DN 
+      value along a line running parallel to the first-drawn line. This average becomes the second 
+      value in the plot. The tool continues this pattern until it has reached the opposite edge of 
+      the rectangle as the first-drawn line.
+    </p>
+    <image src="assets/image/RRSelection.png" height="400" />
+    <image src="assets/image/RRSelectionMarked.png" height="400" />
+    <image src="assets/image/RRPlot.png" height="400" />
+    <p>
+      The first image is the original selection. The second image 
+      is the same view that has been marked for reference purposes. Finally, the last image 
+      is the associated plot window. The original mouse click was made at delineation 
+      "1" within the cube view, the original mouse release was made at "5", and the final 
+      mouse click was made at "15". The Spatial Plot Tool calculates the average of the DN values at 
+      delineations 1-5, and this value is stored as "Pixel Value" 1 in the plot window, while the 
+      averages of 6-10 are stored in 2, and 7-15 are stored in 3. 
+    </p>
+    <h4>Interpolations</h4>
+    <p>
+      Spatial Plot Tool makes use of Nearest Nieghbor, BiLinear and Cubic Convolution interpolations 
+      when calculating the DN values at particular points. <strong>Do be aware that when the tool is 
+      calculating a DN value at a particular point, it is calculating the interpolated DN value at 
+      that point.</strong>
+    </p>
   </description>
 
   <category>
@@ -164,5 +260,8 @@
       Readded help menu for the 2D and 3D plot tools. Now properly display in both tools.
       Fixes #2126.
     </change>
+    <change name="Summer Stapleton" date="2018-03-14">
+      Included documentation for Spatial Plot Tool in this .xml. References #5281.
+    </change>
   </history>
 </application>
diff --git a/isis/src/qisis/objs/BundleObservationView/AS15_16_test_bundleout_images.csv b/isis/src/qisis/objs/BundleObservationView/AS15_16_test_bundleout_images.csv
deleted file mode 100755
index d80600ac85f6d629ea8ecb138613fbb977055f1c..0000000000000000000000000000000000000000
--- a/isis/src/qisis/objs/BundleObservationView/AS15_16_test_bundleout_images.csv
+++ /dev/null
@@ -1,8 +0,0 @@
-Image,rms,rms,rms,X,X,X,X,X,Y,Y,Y,Y,Y,Z,Z,Z,Z,Z,RA,RA,RA,RA,RA,DEC,DEC,DEC,DEC,DEC,TWIST,TWIST,TWIST,TWIST,TWIST,
-Filename,sample res,line res,total res,Initial,Correction,Final,Apriori Sigma,Adj Sigma,Initial,Correction,Final,Apriori Sigma,Adj Sigma,Initial,Correction,Final,Apriori Sigma,Adj Sigma,Initial,Correction,Final,Apriori Sigma,Adj Sigma,Initial,Correction,Final,Apriori Sigma,Adj Sigma,Initial,Correction,Final,Apriori Sigma,Adj Sigma,
-/work/projects/ApolloMetric/METRIC/Calibrated/AS15/SUB4_MSK_InstrumentStartTime/Sub4-AS15-M-1757_msk.cub,0.51845694436147,0.97524424269876,0.78099261714619,-1676.1866244276,0.3170026774516,-1675.8696217502,500.0,0.1690797492717,776.01842700262,0.18308214004334,776.20150914267,500.0,0.17709880748748,190.83692567603,0.67934738703117,191.51627306306,500.0,0.16934724936719,-114.81847479623,0.14786430851052,-114.67061048772,0.5,0.097887257746279,84.286744189607,0.14301001677591,84.429754206383,0.5,0.085518977881851,135.10580640169,-0.073755435116957,135.03205096657,0.5,0.10209077775713
-/work/projects/ApolloMetric/METRIC/Calibrated/AS15/SUB4_MSK_InstrumentStartTime/Sub4-AS15-M-1758_msk.cub,0.48914157340128,0.96409831563102,0.76444262081337,-1661.0556247296,0.24305052799097,-1660.8125742016,500.0,0.17883341616719,800.60462193458,0.26766384701447,800.87228578159,500.0,0.17894270116668,219.62524418461,0.81713498430798,220.44237916892,500.0,0.17548613324839,-115.68927691479,0.15112876410579,-115.53814815068,0.5,0.097663328471951,83.287864615961,0.14571379590631,83.433578411867,0.5,0.085317156538059,135.24236174012,-0.081063071500818,135.16129866862,0.5,0.10243445718908
-/work/projects/ApolloMetric/METRIC/Calibrated/AS15/SUB4_MSK_InstrumentStartTime/Sub4-AS15-M-1759_msk.cub,0.3234786200299,1.0445725353158,0.77323030177063,-1645.118297281,0.18547301310201,-1644.9328242679,500.0,0.20684835804294,824.80203432912,0.37787280348465,825.17990713261,500.0,0.20520137756462,248.30682152756,0.97427898916589,249.28110051673,500.0,0.20458947672359,-116.55201321842,0.1414520464547,-116.41056117197,0.5,0.097506040940435,82.310079123292,0.14270993562181,82.452789058913,0.5,0.085163168400858,135.38610126297,-0.069324655588454,135.31677660738,0.5,0.10281378780214
-/work/projects/ApolloMetric/METRIC/Calibrated/AS16/SUB4_MSK_NewStartTime/Sub4-AS16-M-0392_msk.cub,0.49188485000562,1.1397636203373,0.8777846592159,1747.0424536016,-0.25503937331921,1746.7874142282,500.0,0.18429641470036,633.3492820035,0.49395906374671,633.84324106725,500.0,0.1830184566499,81.070798243394,-0.49125912498146,80.579539118413,500.0,0.19512758266095,110.34149860419,0.3735945369789,110.71509314116,0.5,0.088850090823099,87.09334362033,-0.10691005392567,86.986433566404,0.5,0.094783462079425,-149.90233460871,-0.036238357509029,-149.93857296621,0.5,0.10327678221121
-/work/projects/ApolloMetric/METRIC/Calibrated/AS16/SUB4_MSK_NewStartTime/Sub4-AS16-M-0393_msk.cub,0.745496019873,1.1426404871033,0.96472576373138,1760.2742054268,-0.034511936246684,1760.2396934906,500.0,0.17301063061067,597.66419620361,0.45091683878255,598.11511304239,500.0,0.1749682885975,58.98892575481,-0.51847411988065,58.47045163493,500.0,0.17712241769798,109.18883286426,0.37607709864275,109.56490996291,0.5,0.088840587895256,87.796840611543,-0.09134753252743,87.705493079016,0.5,0.094319465492397,-149.84701529934,-0.033154227141492,-149.88016952649,0.5,0.10364410342365
-/work/projects/ApolloMetric/METRIC/Calibrated/AS16/SUB4_MSK_NewStartTime/Sub4-AS16-M-0394_msk.cub,0.57994567220543,1.0445737373178,0.84482876235478,1772.5152690217,0.19274695792245,1772.7080159796,500.0,0.18900862793942,561.64149498279,0.39235269508021,562.03384767787,500.0,0.19507829017625,36.873141324453,-0.50650471222111,36.366636612232,500.0,0.18962962942032,108.01512683489,0.38747308139741,108.40259991629,0.5,0.088957785858698,88.534523650897,-0.1083766713918,88.426146979505,0.5,0.093815486035816,-149.80439189401,-0.018129130140166,-149.82252102415,0.5,0.10404865355201
diff --git a/isis/src/qisis/objs/BundleObservationView/BundleObservationView.cpp b/isis/src/qisis/objs/BundleObservationView/BundleObservationView.cpp
index cb3f0ec51c019781e501cd158d288526905bcb15..7b29484de477f96218e5f28bda24b5dbd3091b58 100755
--- a/isis/src/qisis/objs/BundleObservationView/BundleObservationView.cpp
+++ b/isis/src/qisis/objs/BundleObservationView/BundleObservationView.cpp
@@ -23,6 +23,7 @@
 
 #include <QDebug>
 #include <QFile>
+#include <QFontDatabase>
 #include <QHeaderView>
 #include <QSizePolicy>
 #include <QStandardItem>
@@ -30,71 +31,130 @@
 #include <QString>
 #include <QStringList>
 #include <QTableView>
+#include <QTextEdit>
 #include <QTextStream>
 #include <QVBoxLayout>
 
 
-
 namespace Isis {
 
-
-
   /** 
-   * Creates a view showing the CSV file from BundleObservation. 
+   * Creates a view showing the CSV or text files from BundleSolutionInfo.
    * 
-   * @param FileItemQsp fileItem  QSharedPointer to the fileItem from the ProjectItemModel
+   * @param FileItemQsp fileItem QSharedPointer to the fileItem from the ProjectItemModel
    */
   BundleObservationView::BundleObservationView(FileItemQsp fileItem, QWidget *parent):
                          AbstractProjectItemView(parent) {
 
+    if (fileItem->fileName().contains(".csv")) {
+      displayCsvFile(fileItem);
+    }
+    else if (fileItem->fileName().contains(".txt")) {
+      displayTextFile(fileItem);
+    }
+  }
+
+
+  /**
+   * Creates a view showing the CSV file from BundleSolutionInfo.
+   *
+   * @param FileItemQsp fileItem QSharedPointer to the fileItem from the ProjectItemModel
+   */
+  void BundleObservationView::displayCsvFile(FileItemQsp fileItem) {
     QStandardItemModel *model = new QStandardItemModel;
+
+    if (!QFile::exists(fileItem->fileName())) {
+      return;
+    }
+
     QFile file(fileItem->fileName());
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+      return;
+    }
 
-    if (file.open(QIODevice::ReadOnly)) {
+    int numHeaderLines = 3;
+    if (fileItem->fileName().contains("images")) {
+      numHeaderLines = 2;
+    }
 
-      int lineindex = 0;                     // file line counter
-      QTextStream in(&file);                 // read to text stream
+    QTextStream in(&file);                 // read to text stream
+
+    // read and populate header from first two or three lines
+    QString header1;
+    QString header2;
+    QString header3;
+    QStringList lineToken1;
+    QStringList lineToken2;
+    QStringList lineToken3;
+
+    header1 = in.readLine();
+    lineToken1 = header1.split(",");
+    header2 = in.readLine();
+    lineToken2 = header2.split(",");
+
+    if (numHeaderLines == 2) {
+      for (int i = 0; i < lineToken1.size(); i++) {
+        QString t1 = lineToken1.at(i);
+        QString t2 = lineToken2.at(i);
+        QString head = t1 + "\n" + t2;
+        QStandardItem *v1 = new QStandardItem(head);
+        model->setHorizontalHeaderItem(i,v1);
+      }
+    }
+    if (numHeaderLines == 3) {
+      header3 = in.readLine();
+      lineToken3 = header3.split(",");
+
+      lineToken1.append("");
+      lineToken2.append("");
+
+      for (int i = 0; i < lineToken3.size(); i++) {
+        QString t1 = lineToken1.at(i);
+        QString t2 = lineToken2.at(i);
+        QString t3 = lineToken3.at(i);
+        QString head = t1 + "\n" + t2 + "\n" + t3;
+        QStandardItem *v1 = new QStandardItem(head);
+        model->setHorizontalHeaderItem(i,v1);
+      }
+    }
 
-      while (!in.atEnd()) {
+    // populate remainder of table
+    int lineindex = 0;
+    while (!in.atEnd()) {
+      QString fileLine = in.readLine();
 
-        // read one line from textstream(separated by "\n")
-        QString fileLine = in.readLine();
+      // parse line into separate pieces(tokens) with "," as the delimiter
+      QStringList lineToken = fileLine.split(",", QString::SkipEmptyParts);
 
-        // parse the read line into separate pieces(tokens) with "," as the delimiter
-        QStringList lineToken = fileLine.split(",", QString::SkipEmptyParts);
+      bool rejected = false;
+      if (lineToken.at(lineToken.size()-1) == "*") {
+        rejected = true;
+      }
 
-        // load parsed data to model accordingly
-        for (int j = 0; j < lineToken.size(); j++) {
-          QString value = lineToken.at(j);
+      // load parsed data to model accordingly
+      for (int i = 0; i < lineToken.size(); i++) {
+        QString value = lineToken.at(i);
 
-          //  First 2 lines are header, load into model header data
-          if (lineindex < 2) {
-            //qDebug()<<"header = "<<value;
-            //model->setHeaderData(j, Qt::Horizontal, value);
-            //qDebug()<<"header = "<<value;
-            QStandardItem *v1 = new QStandardItem(value);
+        QStandardItem *item = new QStandardItem(value);
 
-            model->setHorizontalHeaderItem(j,v1);
-            //model->setHeaderData(j, Qt::Horizontal, value);
-          }
-          else {
-            QStandardItem *item = new QStandardItem(value);
-            model->setItem(lineindex, j, item);
-          }
+        if (rejected) {
+          item->setData(QColor(200,0,0), Qt::BackgroundRole);
         }
 
-        lineindex++;
+        model->setItem(lineindex, i, item);
       }
-
-      file.close();
+      lineindex++;
     }
 
+    file.close();
+
     QTableView *qtable=new QTableView();
     qtable->setModel(model);
     qtable->setSortingEnabled(true);
-    
-    QHeaderView *headerView = qtable->horizontalHeader();
-    headerView->setStretchLastSection(true);
+
+    // resizes to contents based on entire column
+    // NOTE: QHeaderView::ResizeToContents does not allow user to resize by dragging column divider
+    qtable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
 
     QVBoxLayout *layout = new QVBoxLayout;
     setLayout(layout);
@@ -104,17 +164,58 @@ namespace Isis {
     policy.setHorizontalPolicy(QSizePolicy::Expanding);
     policy.setVerticalPolicy(QSizePolicy::Expanding);
     setSizePolicy(policy);
-    }
+  }
 
 
   /**
-   * Destructor
+   * Creates a view showing a text file from BundleSolutionInfo.
+   *
+   * @param FileItemQsp fileItem QSharedPointer to the fileItem from the ProjectItemModel
    */
-  BundleObservationView::~BundleObservationView() {
+  void BundleObservationView::displayTextFile(FileItemQsp fileItem) {
+
+    if (!QFile::exists(fileItem->fileName())) {
+      return;
+    }
+
+    QFile file(fileItem->fileName());
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+      return;
+    }
 
+    QTextStream in(&file);
+    QTextEdit *qText=new QTextEdit();
+
+    // From QFontDatabase::systemFont(SystemFont type) method description: returns most adequate
+    //      font for a given typecase (here FixedFont) for proper integration with system's look and
+    //      feel.
+    const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+    qText->setFontFamily(fixedFont.family());
+
+    while (!in.atEnd()) {
+      qText->append(in.readLine());
+    }
+
+    file.close();
+
+    QVBoxLayout *layout = new QVBoxLayout;
+    setLayout(layout);
+    layout->addWidget(qText);
+
+    qText->moveCursor(QTextCursor::Start);
+
+    QSizePolicy policy = sizePolicy();
+    policy.setHorizontalPolicy(QSizePolicy::Expanding);
+    policy.setVerticalPolicy(QSizePolicy::Expanding);
+    setSizePolicy(policy);
   }
 
 
+  /**
+   * Destructor
+   */
+  BundleObservationView::~BundleObservationView() {
+  }
 }
 
 
diff --git a/isis/src/qisis/objs/BundleObservationView/BundleObservationView.h b/isis/src/qisis/objs/BundleObservationView/BundleObservationView.h
index 2a5b0f267f3547bd0ab15a5b74aec5da23b43950..6921c422ac902a4d41bd08703598d1ff8bc9c2ae 100755
--- a/isis/src/qisis/objs/BundleObservationView/BundleObservationView.h
+++ b/isis/src/qisis/objs/BundleObservationView/BundleObservationView.h
@@ -22,7 +22,6 @@
  */
 
 #include "AbstractProjectItemView.h"
-
 #include "FileItem.h"
 
 namespace Isis{
@@ -36,8 +35,18 @@ namespace Isis{
    * @internal
    *   @history 2017-05-01 Tyler Wilson - Original version.
    *   @history 2017-05-05 Tracie Sucharski - Changed for the serialization of BundleObservation
-   *                           files.  This was implemented create a new ProjectItem type called
+   *                           files. This was implemented create a new ProjectItem type called
    *                           FileItemQsp. Fixes #4839, #4840.
+   *   @history 2018-03-21 Ken Edmundson - Added capability to display either csv or text files.
+   *                           Fixed problem for display of multi-line headers for csv files.
+   *                           Set SectionResizeMode to QHeaderView::ResizeToContents so columns are
+   *                           displayed at the width of the maximum size of the column content.
+   *                           Fixes #4850.
+   *   @history 2018-03-26 Ken Edmundson - Modified displayTextFile method to query for system's
+   *                           fixed width font.
+   *   @history 2018-04-16 Ken Edmundson - Modified display of residuals.csv to properly show the
+   *                           rejected column if there are rejected measures. Also displays
+   *                           rejected measure row in red.
    */
 
   class BundleObservationView : public AbstractProjectItemView
@@ -45,8 +54,11 @@ namespace Isis{
     Q_OBJECT
     public:
       BundleObservationView(FileItemQsp fileItem, QWidget *parent=0);
-      //BundleObservationView(const BundleObservationView &other);
       ~BundleObservationView();
+
+    private:
+      void displayCsvFile(FileItemQsp fileItem);
+      void displayTextFile(FileItemQsp fileItem);
   };
 }
 #endif
diff --git a/isis/src/qisis/objs/CnetEditorView/CnetEditorView.cpp b/isis/src/qisis/objs/CnetEditorView/CnetEditorView.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eca23209c60b0dfd915fd4dfaec8dc7e3d71a19e
--- /dev/null
+++ b/isis/src/qisis/objs/CnetEditorView/CnetEditorView.cpp
@@ -0,0 +1,328 @@
+/**
+ * @file
+ * $Date$
+ * $Revision$
+ *
+ *   Unless noted otherwise, the portions of Isis written by the USGS are
+ *   public domain. See individual third-party library and package descriptions
+ *   for intellectual property information, user agreements, and related
+ *   information.
+ *
+ *   Although Isis has been used by the USGS, no warranty, expressed or
+ *   implied, is made by the USGS as to the accuracy and functioning of such
+ *   software and related material nor shall the fact of distribution
+ *   constitute any such warranty, and no responsibility is assumed by the
+ *   USGS in connection therewith.
+ *
+ *   For additional information, launch
+ *   $ISISROOT/doc//documents/Disclaimers/Disclaimers.html
+ *   in a browser or see the Privacy &amp; Disclaimers page on the Isis website,
+ *   http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on
+ *   http://www.usgs.gov/privacy.html.
+ */
+#include "IsisDebug.h"
+
+#include "CnetEditorView.h"
+
+#include <QAction>
+#include <QGridLayout>
+#include <QList>
+#include <QMap>
+#include <QMapIterator>
+#include <QMenu>
+#include <QMenuBar>
+#include <QSize>
+#include <QSizePolicy>
+#include <QString>
+#include <QTabWidget>
+#include <QToolBar>
+#include <QtXml>
+#include <QVBoxLayout>
+#include <QWidgetAction>
+
+#include "Control.h"
+#include "ControlNet.h"
+#include "CnetEditorWidget.h"
+#include "Directory.h"
+#include "FileName.h"
+#include "Project.h"
+#include "ToolPad.h"
+#include "XmlStackedHandlerReader.h"
+
+
+namespace Isis {
+  /**
+   * Constructor.
+   */
+  CnetEditorView::CnetEditorView(Directory *directory, Control *control, FileName configFile,
+                                 QWidget *parent) : AbstractProjectItemView(parent) {
+
+    // TODO: This layout should be inside of the cnet editor widget, but I put it here to not
+    //     conflict with current work in the cnet editor widget code.
+    //QWidget *result = new QWidget;
+    QGridLayout *resultLayout = new QGridLayout;
+    setLayout(resultLayout);
+
+    int row = 0;
+
+    QMenuBar *menuBar = new QMenuBar;
+    resultLayout->addWidget(menuBar, row, 0, 1, 2);
+    row++;
+
+    m_cnetEditorWidget = new CnetEditorWidget(control, configFile.expanded());
+    m_control = control;
+
+    resultLayout->addWidget(m_cnetEditorWidget, row, 0, 1, 2);
+    row++;
+
+    // Populate the menu...
+    QMap< QAction *, QList< QString > > actionMap = m_cnetEditorWidget->menuActions();
+    QMapIterator< QAction *, QList< QString > > actionMapIterator(actionMap);
+
+    QMap<QString, QMenu *> topLevelMenus;
+
+    while ( actionMapIterator.hasNext() ) {
+      actionMapIterator.next();
+      QAction *actionToAdd = actionMapIterator.key();
+      QList< QString > location = actionMapIterator.value();
+
+      QMenu *menuToPutActionInto = NULL;
+
+      if ( location.count() ) {
+        QString topLevelMenuTitle = location.takeFirst();
+        if (!topLevelMenus[topLevelMenuTitle]) {
+          topLevelMenus[topLevelMenuTitle] = menuBar->addMenu(topLevelMenuTitle);
+        }
+
+        menuToPutActionInto = topLevelMenus[topLevelMenuTitle];
+      }
+
+      foreach (QString menuName, location) {
+        bool foundSubMenu = false;
+        foreach ( QAction *possibleSubMenu, menuToPutActionInto->actions() ) {
+          if (!foundSubMenu &&
+              possibleSubMenu->menu() && possibleSubMenu->menu()->title() == menuName) {
+            foundSubMenu = true;
+            menuToPutActionInto = possibleSubMenu->menu();
+          }
+        }
+
+        if (!foundSubMenu) {
+          menuToPutActionInto = menuToPutActionInto->addMenu(menuName);
+        }
+      }
+
+      menuToPutActionInto->addAction(actionToAdd);
+    }
+
+    QTabWidget *treeViews = new QTabWidget;
+    treeViews->addTab( m_cnetEditorWidget->pointTreeView(), tr("Point View") );
+    treeViews->addTab( m_cnetEditorWidget->serialTreeView(), tr("Serial View") );
+    treeViews->addTab( m_cnetEditorWidget->connectionTreeView(), tr("Connection View") );
+    resultLayout->addWidget(treeViews, row, 0, 1, 1);
+
+    QTabWidget *filterViews = new QTabWidget;
+    filterViews->addTab( m_cnetEditorWidget->pointFilterWidget(), tr("Filter Points and Measures") );
+    filterViews->addTab( m_cnetEditorWidget->serialFilterWidget(), tr("Filter Images and Points") );
+    filterViews->addTab( m_cnetEditorWidget->connectionFilterWidget(), tr("Filter Connections") );
+    resultLayout->addWidget(filterViews, row, 1, 1, 1);
+    row++;
+
+
+
+
+
+    m_permToolBar = new QToolBar("Standard Tools", 0);
+    m_permToolBar->setObjectName("permToolBar");
+    m_permToolBar->setIconSize(QSize(22, 22));
+    //toolBarLayout->addWidget(m_permToolBar);
+
+    m_activeToolBar = new QToolBar("Active Tool", 0);
+    m_activeToolBar->setObjectName("activeToolBar");
+    m_activeToolBar->setIconSize(QSize(22, 22));
+    //toolBarLayout->addWidget(m_activeToolBar);
+
+    m_toolPad = new ToolPad("Tool Pad", 0);
+    m_toolPad->setObjectName("toolPad");
+    //toolBarLayout->addWidget(m_toolPad);
+
+
+//  m_cnetEditorWidget->addToPermanent(m_permToolBar);
+//  m_cnetEditorWidget->addTo(m_activeToolBar);
+//  m_cnetEditorWidget->addTo(m_toolPad);
+
+    m_activeToolBarAction = new QWidgetAction(this);
+    m_activeToolBarAction->setDefaultWidget(m_activeToolBar);
+
+    setAcceptDrops(true);
+
+    QSizePolicy policy = sizePolicy();
+    policy.setHorizontalPolicy(QSizePolicy::Expanding);
+    policy.setVerticalPolicy(QSizePolicy::Expanding);
+    setSizePolicy(policy);
+
+  }
+
+
+  /**
+   * Destructor
+   */
+  CnetEditorView::~CnetEditorView() {
+    
+    delete m_cnetEditorWidget;
+    delete m_permToolBar;
+    delete m_activeToolBar;
+    delete m_toolPad;
+
+    m_permToolBar = 0;
+    m_activeToolBar = 0;
+    m_toolPad = 0;
+  }
+
+
+  /**
+   * Returns the cnetEditorWidget.
+   *
+   * @return (cnetEditorWidget *) The cnetEditorWidget used to
+   *         display the footprints.
+   */
+  CnetEditorWidget *CnetEditorView::cnetEditorWidget() {
+    return m_cnetEditorWidget;
+  }
+
+
+  /**
+   * @description Returns the Control displayed in the CnetEditorWidget 
+   *  
+   * @return (Control *) The Control displayed in the CnetEditorWidget 
+   */
+  Control *CnetEditorView::control() {
+    return m_control;
+  }
+
+
+  /**
+   * Returns the suggested size for the widget.
+   *
+   * @return (QSize) The size
+   */
+  QSize CnetEditorView::sizeHint() const {
+    return QSize(800, 600);
+  }
+
+
+  /**
+   * Returns a list of actions for the permanent tool bar.
+   *
+   * @return (QList<QAction *>) The actions
+   */
+  QList<QAction *> CnetEditorView::permToolBarActions() {
+    return m_permToolBar->actions();
+  }
+
+
+  /**
+   * Returns a list of actions for the active tool bar.
+   *
+   * @return (QList<QAction *>) The actions
+   */
+  QList<QAction *> CnetEditorView::activeToolBarActions() {
+    QList<QAction *> actions;
+    actions.append(m_activeToolBarAction);
+    return actions;
+  }
+
+
+  /**
+   * Returns a list of actions for the tool pad.
+   *
+   * @return (QList<QAction *>) The actions
+   */
+  QList<QAction *> CnetEditorView::toolPadActions() {
+    return m_toolPad->actions();
+  }
+
+
+
+
+  /**
+   * This method pushes a new XmlHandler into the parser stack.
+   *
+   * @param xmlReader This is the parser stack.
+   */
+  void CnetEditorView::load(XmlStackedHandlerReader *xmlReader) {
+    xmlReader->pushContentHandler(new XmlHandler(this));
+  }
+
+
+  /**
+   * This method saves the Controls object ids to the stream.
+   *
+   * @param stream The stream that will output to directory.xml
+   * @param project The project to save the users settings to
+   * @param newProjectRoot New project's root directory
+   */
+  void CnetEditorView::save(QXmlStreamWriter &stream, Project *, FileName) const {
+
+    stream.writeStartElement("control");
+    stream.writeAttribute("id", m_control->id());
+    stream.writeEndElement();
+  }
+
+
+  /**
+   * Creates an XmlHandler for cnetEditor
+   *
+   * @param cnetEditor The widget to be serialized
+   */
+  CnetEditorView::XmlHandler::XmlHandler(CnetEditorView *cnetEditorView) {
+    m_cnetEditorView = cnetEditorView;
+  }
+
+
+  /**
+   * Destructor
+   */
+  CnetEditorView::XmlHandler::~XmlHandler() {
+    delete m_cnetEditorView;
+    m_cnetEditorView = NULL;
+  }
+
+
+  /**
+   * Placeholder for later serialization of CnetEditorViews
+   *
+   * @param cnetEditor The CnetEditorView to be serialized
+   * @param namespaceURI ???
+   * @param localName Determines what attributes to retrieve from atts.
+   * @param qName ???
+   * @param atts Stores the attributes.
+   *
+   * @return @b bool The result of XmlStackedHandler's startElement() method.
+   */
+  bool CnetEditorView::XmlHandler::startElement(const QString &namespaceURI,
+      const QString &localName, const QString &qName, const QXmlAttributes &atts) {
+
+    bool result = XmlStackedHandler::startElement(namespaceURI, localName, qName, atts);
+    return result;
+  }
+
+
+  /**
+   * This method calls XmlStackedHandler's endElement() and dereferences pointers according to
+   * the value of localName.
+   *
+   * @param namespaceURI ???
+   * @param localName Determines which pointers to dereference.
+   * @param qName ???
+   *
+   * @return @b bool The result of XmlStackedHandler's endElement() method.
+   */
+  bool CnetEditorView::XmlHandler::endElement(const QString &namespaceURI,
+      const QString &localName, const QString &qName) {
+
+    bool result = XmlStackedHandler::endElement(namespaceURI, localName, qName);
+    return result;
+  }
+}
+
diff --git a/isis/src/qisis/objs/CnetEditorView/CnetEditorView.h b/isis/src/qisis/objs/CnetEditorView/CnetEditorView.h
new file mode 100644
index 0000000000000000000000000000000000000000..21e98d307d8b70e01d33be604cbad736408612e6
--- /dev/null
+++ b/isis/src/qisis/objs/CnetEditorView/CnetEditorView.h
@@ -0,0 +1,113 @@
+#ifndef CnetEditorView_h
+#define CnetEditorView_h
+/**
+ * @file
+ * $Date$
+ * $Revision$
+ *
+ *   Unless noted otherwise, the portions of Isis written by the USGS are
+ *   public domain. See individual third-party library and package descriptions
+ *   for intellectual property information, user agreements, and related
+ *   information.
+ *
+ *   Although Isis has been used by the USGS, no warranty, expressed or
+ *   implied, is made by the USGS as to the accuracy and functioning of such
+ *   software and related material nor shall the fact of distribution
+ *   constitute any such warranty, and no responsibility is assumed by the
+ *   USGS in connection therewith.
+ *
+ *   For additional information, launch
+ *   $ISISROOT/doc//documents/Disclaimers/Disclaimers.html
+ *   in a browser or see the Privacy &amp; Disclaimers page on the Isis website,
+ *   http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on
+ *   http://www.usgs.gov/privacy.html.
+ */
+#include <QList>
+#include <QMap>
+#include <QPointer>
+#include <QSize>
+
+#include "AbstractProjectItemView.h"
+#include "FileName.h"
+#include "XmlStackedHandler.h"
+
+class QAction;
+class QToolBar;
+class QWidgetAction;
+class QXmlStreamWriter;
+
+namespace Isis {
+  class Control;
+  class CnetEditorWidget;
+  class Directory;
+  class FileName;
+  class Project;
+  class ToolPad;
+  class XmlStackedHandlerReader;
+
+  /**
+   * Ipce view containing the CnetEditorWidget
+   *
+   * @author 2018-04-04 Tracie Sucharski
+   *    
+   * @internal 
+   */
+
+class CnetEditorView : public AbstractProjectItemView {
+
+  Q_OBJECT
+
+  public:
+    CnetEditorView(Directory *directory, Control *control, FileName configFile, 
+                   QWidget *parent = 0);
+    ~CnetEditorView();
+
+    virtual QList<QAction *> permToolBarActions();
+    virtual QList<QAction *> activeToolBarActions();
+    virtual QList<QAction *> toolPadActions();
+
+    CnetEditorWidget *cnetEditorWidget();
+    Control *control();
+
+    QSize sizeHint() const;
+
+    void load(XmlStackedHandlerReader *xmlReader);
+    void save(QXmlStreamWriter &stream, Project *project, FileName newProjectRoot) const;
+
+
+    private:
+      /**
+       * @author 2012-09-?? Steven Lambright
+       *
+       * @internal
+       *   @history 2018-04-04 Tracie Sucharski - Implemented for CnetEditorView
+       */
+      class XmlHandler : public XmlStackedHandler {
+        public:
+          XmlHandler(CnetEditorView *cnetEditorView);
+          ~XmlHandler();
+
+          virtual bool startElement(const QString &namespaceURI, const QString &localName,
+                                    const QString &qName, const QXmlAttributes &atts);
+          virtual bool endElement(const QString &namespaceURI, const QString &localName,
+                                  const QString &qName);
+
+        private:
+          Q_DISABLE_COPY(XmlHandler);
+
+          CnetEditorView *m_cnetEditorView; //!< The view we are working with
+      };
+
+  private:
+    QPointer<CnetEditorWidget> m_cnetEditorWidget;
+    QPointer<Control> m_control;
+
+    QToolBar *m_permToolBar; //!< The permanent tool bar
+    QToolBar *m_activeToolBar; //!< The active tool bar
+    ToolPad *m_toolPad; //!< The tool pad
+
+    QWidgetAction *m_activeToolBarAction; //!< Stores the active tool bar
+  };
+}
+
+#endif // CNETEDITORVIEW_H
diff --git a/isis/src/qisis/objs/CnetEditorView/Makefile b/isis/src/qisis/objs/CnetEditorView/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..f122bc88227c5c7ebd108dea5d339d1d2e074d82
--- /dev/null
+++ b/isis/src/qisis/objs/CnetEditorView/Makefile
@@ -0,0 +1,7 @@
+ifeq ($(ISISROOT), $(BLANK))
+.SILENT:
+error:
+	echo "Please set ISISROOT";
+else
+	include $(ISISROOT)/make/isismake.objs
+endif
\ No newline at end of file
diff --git a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.cpp b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.cpp
index b55d7c57cc08ed2a1ec9de6a53d50a456abeb414..30dbba1a8c973bf8963801b298563b15286d0ab6 100644
--- a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.cpp
+++ b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.cpp
@@ -98,6 +98,7 @@ namespace Isis {
    * Destructor
    */
   CnetEditorWidget::~CnetEditorWidget() {
+
     writeSettings();
 
     delete m_workingVersion;
@@ -1040,82 +1041,4 @@ namespace Isis {
       m_connectionModel->setFrozen(false);
     }
   }
-
-
-  /**
-   * This method pushes a new XmlHandler into the parser stack.
-   *
-   * @param xmlReader This is the parser stack.
-   */
-  void CnetEditorWidget::load(XmlStackedHandlerReader *xmlReader) {
-    xmlReader->pushContentHandler(new XmlHandler(this));
-  }
-
-
-  /**
-   * This method saves the Controls object ids to the stream.
-   *
-   * @param stream The stream that will output to directory.xml
-   * @param project The project to save the users settings to
-   * @param newProjectRoot New project's root directory
-   */
-  void CnetEditorWidget::save(QXmlStreamWriter &stream, Project *project, FileName newProjectRoot) {
-    stream.writeStartElement("control");
-    stream.writeAttribute("id", m_control->id());
-    stream.writeEndElement();
-  }
-
-
-  /**
-   * Creates an XmlHandler for cnetEditor
-   *
-   * @param cnetEditor The widget to be serialized
-   */
-  CnetEditorWidget::XmlHandler::XmlHandler(CnetEditorWidget *cnetEditor) {
-    m_cnetEditor = cnetEditor;
-  }
-
-
-  /**
-   * Destructor
-   */
-  CnetEditorWidget::XmlHandler::~XmlHandler() {
-    delete m_cnetEditor;
-    m_cnetEditor = NULL;
-  }
-
-
-  /**
-   * Placeholder for later serialization of CnetEditorWidgets
-   *
-   * @param cnetEditor The widget to be serialized
-   * @param namespaceURI ???
-   * @param localName Determines what attributes to retrieve from atts.
-   * @param qName ???
-   * @param atts Stores the attributes.
-   *
-   * @return @b bool The result of XmlStackedHandler's startElement() method.
-   */
-  bool CnetEditorWidget::XmlHandler::startElement(const QString &namespaceURI,
-      const QString &localName, const QString &qName, const QXmlAttributes &atts) {
-    bool result = XmlStackedHandler::startElement(namespaceURI, localName, qName, atts);
-    return result;
-  }
-
-
-  /**
-   * This method calls XmlStackedHandler's endElement() and dereferences pointers according to
-   * the value of localName.
-   *
-   * @param namespaceURI ???
-   * @param localName Determines which pointers to dereference.
-   * @param qName ???
-   *
-   * @return @b bool The result of XmlStackedHandler's endElement() method.
-   */
-  bool CnetEditorWidget::XmlHandler::endElement(const QString &namespaceURI,
-      const QString &localName, const QString &qName) {
-    bool result = XmlStackedHandler::endElement(namespaceURI, localName, qName);
-    return result;
-  }
 }
diff --git a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.h b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.h
index bdbe010105569f0db7e73b2566a94e270f0fcc32..e66c559403d103365c789babd46b6e2cb814e7ec 100644
--- a/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.h
+++ b/isis/src/qisis/objs/CnetEditorWidget/CnetEditorWidget.h
@@ -71,6 +71,8 @@ namespace Isis {
    *                           a ControlNet. Added load and save methods as well as an XmlHandler
    *                           to allow for serialization of the widget into the project.
    *                           Fixes #4989.
+   *   @history 2018-04-11 Tracie Sucharski - Moved the Xml serialization to the newly created
+   *                           CnetEditorView class for ipce.
    */
   class CnetEditorWidget : public QWidget {
       Q_OBJECT
@@ -116,9 +118,6 @@ namespace Isis {
       void setPointTableSortingEnabled(bool enabled);
       void setPointTableSortLimit(int limit);
 
-      void load(XmlStackedHandlerReader *xmlReader);
-      void save(QXmlStreamWriter &stream, Project *project, FileName newProjectRoot);
-
 
     public slots:
       void configSorting();
@@ -191,34 +190,6 @@ namespace Isis {
       QMap< QString, QList< QAction * > > * m_toolBarActions;   //!< QMap of tool bar actions
 
       QString *m_settingsPath; //!< Path to read/write settings
-
-
-    private:
-      /**
-       * This class is a placeholder for future plans to serialize more of
-       * CnetEditorWidget's configurations when saving a project.
-       *  
-       * @author 2017-07-25 Christopher Combs
-       * @internal
-       *   @history 2017-07-25 Christopher Combs - Added Xml StackedHandler class
-       *                           to implement serialization of the CnetEditorWidget.
-       *                           References #4989.
-       */
-      class XmlHandler : public XmlStackedHandler {
-        public:
-          XmlHandler(CnetEditorWidget *cnetEditor);
-          ~XmlHandler();
-
-          virtual bool startElement(const QString &namespaceURI, const QString &localName,
-                                    const QString &qName, const QXmlAttributes &atts);
-          virtual bool endElement(const QString &namespaceURI, const QString &localName,
-                                  const QString &qName);
-
-        private:
-          Q_DISABLE_COPY(XmlHandler);
-
-          CnetEditorWidget *m_cnetEditor;
-      };
   };
 }
 
diff --git a/isis/src/qisis/objs/Control/Control.cpp b/isis/src/qisis/objs/Control/Control.cpp
index c71ac7db4dac83a9f4194d58a44faeca9096edc9..751cc3f83c62614fe951e2f4ec568e9aceafd58e 100644
--- a/isis/src/qisis/objs/Control/Control.cpp
+++ b/isis/src/qisis/objs/Control/Control.cpp
@@ -31,6 +31,7 @@ namespace Isis {
     m_controlNet = NULL;
     m_displayProperties = NULL;
     m_project = NULL;
+    m_modified = false;
 
     try {
       openControlNet();
@@ -59,6 +60,7 @@ namespace Isis {
     m_controlNet = NULL;
     m_displayProperties = NULL;
     m_project = project;
+    m_modified = false;
 
     m_displayProperties
         = new ControlDisplayProperties(FileName(m_fileName).name(), this);
@@ -82,6 +84,7 @@ namespace Isis {
     m_controlNet = controlNet;
     m_displayProperties = NULL;
     m_project = NULL;
+    m_modified = false;
 
     m_displayProperties
         = new ControlDisplayProperties(FileName(m_fileName).name(), this);
@@ -103,6 +106,7 @@ namespace Isis {
     m_displayProperties = NULL;
     m_id = NULL;
     m_project = NULL;
+    m_modified = false;
 
     xmlReader->pushContentHandler(new XmlHandler(this, cnetFolder));
   }
@@ -122,6 +126,9 @@ namespace Isis {
     //    destructor will take care of deleting the display props. See call to
     //    DisplayProperties' constructor.
     m_displayProperties = NULL;
+
+    // TODO: If control net is modified, prompt for save before destroying??
+
   }
 
 
@@ -154,6 +161,7 @@ namespace Isis {
         if (m_project) {
           m_controlNet->SetMutex(m_project->mutex());
         }
+        m_modified = false;
 
       }
       catch (IException &e) {
@@ -163,6 +171,33 @@ namespace Isis {
   }
 
 
+  /**
+   * @description Write control net to disk.  This method is used instead of calling 
+   * ControlNet::Write directly so that Control knows the modification state of the control net. 
+   * Note that if there is not a control net opened, there should no be any changes to write.
+   *  
+   * @return @b bool Returns false if there is not a control net open to write 
+   *  
+   * @throws IException::Programmer "Cannot write control net to disk" 
+   */
+  bool Control::write() {
+
+    if (!m_controlNet) {
+      return false;
+    }
+
+    try {
+      m_controlNet->Write(fileName());
+    }
+    catch (IException &e) {
+      throw IException(e, IException::Programmer, "Cannot write control net.", _FILEINFO_);
+    }
+
+    m_modified = false;
+    return true;
+  }
+
+
   /**
    * Cleans up the ControlNet pointer. This method should be called
    * once there is no more need for this network because the OS will limit
@@ -173,6 +208,31 @@ namespace Isis {
       delete m_controlNet;
       m_controlNet = NULL;
     }
+    m_modified = false;
+  }
+
+
+  /**
+   * @description Has this control been modified? 
+   *  
+   * @return @b bool Has this control been modified? 
+   *  
+   */
+  bool Control::isModified() {
+    return m_modified;
+  }
+
+
+  /**
+   * @description Sets the modification state of this control. This is needed for now since many 
+   * classes make changes to the control net contained in this object, but the control does not 
+   * know the state of the control net. 
+   * TODO:  Change this class to always know the state of the control Net.
+   *  
+   */
+  void Control::setModified(bool modified) {
+    
+    m_modified = modified;
   }
 
 
@@ -224,17 +284,35 @@ namespace Isis {
    *                       will be copied.
    */
   void Control::copyToNewProjectRoot(const Project *project, FileName newProjectRoot) {
-    if (FileName(newProjectRoot).toString() != FileName(project->projectRoot()).toString()) {
 
+    if (FileName(newProjectRoot).toString() != FileName(project->projectRoot()).toString()) {
+  
       QString newNetworkPath =  project->cnetRoot(newProjectRoot.toString()) + "/" +
                   FileName(m_fileName).dir().dirName() + "/" + FileName(m_fileName).name();
 
-      QString oldNetworkPath = project->cnetRoot(project->projectRoot()) + "/" +
-                  FileName(m_fileName).dir().dirName() + "/" + FileName(m_fileName).name();
-      if (!QFile::copy(oldNetworkPath,newNetworkPath) ) {
-        throw IException(IException::Io, "Error saving control net.", _FILEINFO_);
+      // If there is active control & it has been modified, write to disk instead of copying
+      //  Leave control net at old location in unmodified state
+      if (isModified()) {
+        controlNet()->Write(newNetworkPath);
+        setModified(false);
+      }
+      else {
+        QString oldNetworkPath = project->cnetRoot(project->projectRoot()) + "/" +
+                    FileName(m_fileName).dir().dirName() + "/" + FileName(m_fileName).name();
+        if (!QFile::copy(oldNetworkPath,newNetworkPath) ) {
+          throw IException(IException::Io, "Error saving control net.", _FILEINFO_);
+        }
+      }
+    }
+    //   Project "Save" to current location, if active control exists & is modified, write to disk
+    //  Note:  It does not look like this code is ever executed.  If project is saved with a
+    //         "Save" this method is not called.
+    else {
+      if (isModified()) {
+        write();
+        setModified(false);
       }
-    }//end outer-if
+    }
 
   }
 
@@ -256,6 +334,7 @@ namespace Isis {
     // If we're the last thing in the folder, remove the folder too.
     QDir dir;
     dir.rmdir(FileName(m_fileName).path());
+    m_modified = false;
   }
 
 
diff --git a/isis/src/qisis/objs/Control/Control.h b/isis/src/qisis/objs/Control/Control.h
index c1d21862789471ae4f73f3563bb0e518109f6b99..a3d10118410f9d358adad416c05b92721da7365d 100644
--- a/isis/src/qisis/objs/Control/Control.h
+++ b/isis/src/qisis/objs/Control/Control.h
@@ -67,13 +67,21 @@ namespace Isis {
    *                           to compare project roots. References #4804, #4849.
    *   @history 2018-01-19 Tracie Sucharski - Do not copy control unless the project root has
    *                           changed. References #5212.
+   *   @history 2018-03-30 Tracie Sucharski - Added setModified and is Modified methods to keep
+   *                           track of the modification state of the control net. Add write method
+   *                           to write the control net to disk.  This write method should be called
+   *                           by ipce classes instead of calling the ControlNet::Write directly so
+   *                           that control knows the state of the control net. If a project
+   *                           is performing a "Save As", and there is a modified active control,the
+   *                           cnet is written out to the new location, it is not save in the old
+   *                           project location.
    */
   class Control : public QObject {
     Q_OBJECT
     public:
       ControlNet *m_controlNet; /**< A pointer to the ControlNet object associated with this
                                                     Control object.*/
-    explicit Control(QString cnetFileName, QObject *parent = 0);
+      explicit Control(QString cnetFileName, QObject *parent = 0);
       explicit Control(Project *project, QString cnetFileName, QObject *parent = 0);
       explicit Control(ControlNet *controlNet, QString cnetFileName, QObject *parent = 0);
       Control(FileName cnetFolder, XmlStackedHandlerReader *xmlReader, QObject *parent = 0);
@@ -87,6 +95,10 @@ namespace Isis {
 
       QString id() const;
 
+      bool isModified();
+      void setModified(bool modified = true);
+      bool write();  
+
       void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const;
       void copyToNewProjectRoot(const Project *project, FileName newProjectRoot);
       void deleteFromDisk();
@@ -123,6 +135,8 @@ namespace Isis {
       Control(const Control &other);
       Control &operator=(const Control &rhs);
 
+      bool m_modified;
+
       ControlDisplayProperties *m_displayProperties; /**< Contains the display properties for this
                                                           Control object.*/
       Project *m_project; //! Project associated with this control
diff --git a/isis/src/qisis/objs/ControlNetTool/ControlNetTool.cpp b/isis/src/qisis/objs/ControlNetTool/ControlNetTool.cpp
index 6228df16ed397a8e44cf72db2d2e334f0fa2d851..221b544edaed81080d3a75e4191b638aae4a745c 100644
--- a/isis/src/qisis/objs/ControlNetTool/ControlNetTool.cpp
+++ b/isis/src/qisis/objs/ControlNetTool/ControlNetTool.cpp
@@ -35,9 +35,10 @@ using namespace std;
 
 namespace Isis {
   /**
-   * Ipce (Qnet) tool - Handles mouse button actions and drawing control points on viewports
+   * ControlNet tool - Handles mouse button actions and drawing control points on viewports in the
+   * CubeDnView for the ipce application. 
    *
-   * @param parent Pointer to the parent widget for the Ipce tool
+   * @param parent Pointer to the parent widget for the ControlNet tool
    *
    * @author 2016-09-01 Tracie Sucharski
    *
@@ -56,10 +57,10 @@ namespace Isis {
 
 
   /**
-    * Adds the Ipce tool action to the tool pad.
+    * Adds the ControlNet tool action to the tool pad.
     *
     * @param pad Tool pad
-    * @return @b QAction* Pointer to Tie tool action
+    * @return @b QAction* Pointer to ControlNet tool action
     *
     * @internal
     *   @history 2017-07-25 Tyler Wilson - Set the
@@ -73,6 +74,8 @@ namespace Isis {
      QAction *action = new QAction(this);
      action->setIcon(QPixmap(toolIconDir()+"/HILLBLU_molecola.png"));
      action->setToolTip("Control Point Editor (T)");
+     action->setStatusTip("If tool disabled, make sure you have a control net in your project and "
+                          "it is set to the active control.");
      action->setShortcut(Qt::Key_T);
 
      //The object name is being set and used as a key to search with for this action in
@@ -99,13 +102,16 @@ namespace Isis {
     */
    void ControlNetTool::setControlNet(ControlNet *cnet) {
      m_controlNet = cnet;
-     // TODO:  TLS 7-25-17  This method is called by Project::open before there are any viewports,
-     // so the following command seg faults.  Need to add check for viewports or ??
-     //paintAllViewports();
+     //  Cannot use Tool::cubeViewportList() because it does not properly return a NULL if viewports
+     //  don't exist.
+     if (workspace() && workspace()->cubeViewportList()) {
+       paintAllViewports();
+     }
    }
 
 
    void ControlNetTool::loadNetwork() {
+
      setControlNet(m_directory->project()->activeControl()->controlNet());
    }
 
@@ -122,7 +128,7 @@ namespace Isis {
    */
   void ControlNetTool::mouseButtonRelease(QPoint p, Qt::MouseButton s) {
     MdiCubeViewport *cvp = cubeViewport();
-    if (cvp  == NULL) return;
+    if (m_controlNet == NULL || cvp  == NULL) return;
 
     // Determine if the cvp is a Shape
     //  Get all ShapeLists from Project
diff --git a/isis/src/qisis/objs/ControlNetTool/ControlNetTool.h b/isis/src/qisis/objs/ControlNetTool/ControlNetTool.h
index 1bc0ab089ba5a01eb4cf76b5de9d2a285658052d..de4ce7b7bac7c87dc33526a6c5004aa1de688f77 100644
--- a/isis/src/qisis/objs/ControlNetTool/ControlNetTool.h
+++ b/isis/src/qisis/objs/ControlNetTool/ControlNetTool.h
@@ -29,8 +29,8 @@ namespace Isis {
   class UniversalGroundMap;
 
   /**
-   * @brief ControlNetTool operations ipce, handles mouse events on views for control point editing 
-   *        for the ipce app.
+   * @brief ControlNetTool Handles mouse events on CubeDnViews for control point editing for the 
+   *        ipce app.
    *
    * @ingroup Visualization Tools
    *
@@ -52,6 +52,12 @@ namespace Isis {
    *   @history 2017-08-08 Cole Neubauer - Renamed from IpceTool.  Fixes #5090. 
    *   @history 2017-08-09 Cole Neubauer - Added loadNetwork() for changing inbetween active
    *                           networks Fixes #4567
+   *   @history 2018-03-12 Tracie Sucharski - Fixed some documentation leftover from renaming from
+   *                           IpceTool.  References #5090.
+   *   @history 2018-03-27 Tracie Sucharski - Redraw cube viewports when a new control net is
+   *                           loaded.
+   *   @history 2018-04-13 Tracie Sucharski - In mouseButtonRelease method return if a control net
+   *                           has not been set.
    */
   class ControlNetTool : public Tool {
     Q_OBJECT
diff --git a/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.cpp b/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.cpp
index 0622c49712370aa9e965148b7929ae886cbd66e2..7e657d0df4cd2ed6c15f04f06afa22d7771a4012 100644
--- a/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.cpp
+++ b/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.cpp
@@ -579,21 +579,44 @@ namespace Isis {
   /**
    * New control network being edited
    *
-   * @param cnet (ControlNet *) The control network to edit
-   * @param filename (Qstring) Need filename to write to widget label.  ControlNet doesn't
-   *                       contain a filename.
+   * @param cnet (Control *) The control network to edit
+   *  
    * @internal
   */
   void ControlPointEditWidget::setControl(Control *control) {
     //  TODO  more error checking
+    m_control = control;
     m_controlNet = control->controlNet();
     m_cnetFileName = control->fileName();
+
+    m_cnetFileNameLabel->setText("Control Network: " + m_cnetFileName);
     setWindowTitle("Control Point Editor- Control Network File: " + m_cnetFileName);
 
     emit newControlNetwork(m_controlNet);
   }
 
 
+  /**
+   * New active control was set from ipce 
+   *  
+   * TODO:  This will need to be redesigned with the ::setControl method to better handle editing 
+   * points from different cnets. 
+   */
+  void ControlPointEditWidget::setControlFromActive() {
+
+    if (m_directory->project()->activeControl()) {
+      m_control = m_directory->project()->activeControl();
+      m_controlNet = m_control->controlNet();
+      m_cnetFileName = m_control->fileName();
+
+      m_cnetFileNameLabel->setText("Control Network: " + m_cnetFileName);
+      setWindowTitle("Control Point Editor- Control Network File: " + m_cnetFileName);
+
+      emit newControlNetwork(m_controlNet);    
+    }
+  }
+
+
   /**
    * @brief Create a temporary measure to hold the ground point info for ground source
    *
@@ -687,7 +710,6 @@ namespace Isis {
   FileName ControlPointEditWidget::findGroundFile() {
 
     FileName groundFile(m_editPoint->GetAprioriSurfacePointSourceFile());
-
     if (m_changeAllGroundLocation) {
       QFileInfo oldFile(groundFile.expanded());
       QFileInfo newFile(m_newGroundDir, oldFile.fileName());
@@ -782,17 +804,35 @@ namespace Isis {
     //  is selected
     if (controlPoint->Parent() == NULL) {
       m_editPoint = controlPoint;
+      // New point in editor, so colorize all save buttons
+      colorizeAllSaveButtons("red");
     }
     else {
       m_editPoint = new ControlPoint;
       *m_editPoint = *controlPoint;
+
+      // New point loaded, make sure all save button's text is default black color
+      colorizeAllSaveButtons("black");
     }
 
     loadPoint(serialNumber);
     loadTemplateFile(m_measureEditor->templateFileName());
+  }
+
+
+  void ControlPointEditWidget::colorizeAllSaveButtons(QString color) {
 
-    // New point loaded, make sure Save Measure Button text is default
+    if (color == "black") {
+      // Don't need to colorize save measure button, when loading new measure, the measure editor
+      // will set back to default palette.
     m_savePoint->setPalette(m_saveDefaultPalette);
+      m_saveNet->setPalette(m_saveDefaultPalette);
+    }
+    else if (color == "red") {
+      m_measureEditor->colorizeSaveButton(); 
+      colorizeSavePointButton();
+      colorizeSaveNetButton();
+    }
   }
 
 
@@ -1005,7 +1045,7 @@ namespace Isis {
 
     Camera *cam;
     for (int i = 0; i < m_serialNumberList->size(); i++) {
-//    if (m_serialNumberList->serialNumber(i) == m_groundSN) continue;
+      if (m_serialNumberList->serialNumber(i) == m_groundSN) continue;
       cam = m_controlNet->Camera(i);
       if (cam->SetUniversalGround(latitude, longitude)) {
         //  Make sure point is within image boundary
@@ -1159,7 +1199,7 @@ namespace Isis {
           }
         }
 
-        this->setVisible(false);
+        //this->setVisible(false);
         // remove this point from the control network
         if (m_controlNet->DeletePoint(m_editPoint->GetId()) ==
                                           ControlPoint::PointLocked) {
@@ -1168,8 +1208,8 @@ namespace Isis {
           return;
         }
         if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
-          delete m_editPoint;
-          m_editPoint = NULL;
+//        delete m_editPoint;
+//        m_editPoint = NULL;
         }
       }
 
@@ -1224,6 +1264,7 @@ namespace Isis {
 
       // emit a signal to alert user to save when exiting
       emit cnetModified();
+      emit saveControlNet();
 
       if (m_editPoint != NULL) {
         //  Change Save Point button text to red
@@ -2443,12 +2484,18 @@ namespace Isis {
    *
    * @author 2014-07-11 Tracie Sucharski
    */
-  void ControlPointEditWidget::colorizeSaveNetButton() {
+  void ControlPointEditWidget::colorizeSaveNetButton(bool reset) {
 
+    if (reset) {
+      //  Change Save Net button text back to default black
+      m_saveNet->setPalette(m_saveDefaultPalette);
+    }
+    else {
     QColor qc = Qt::red;
     QPalette p = m_savePoint->palette();
     p.setColor(QPalette::ButtonText,qc);
     m_saveNet->setPalette(p);
+    }
 
   }
 
@@ -2490,7 +2537,7 @@ namespace Isis {
   */
   void ControlPointEditWidget::saveNet() {
 
-    m_controlNet->Write(m_cnetFileName);
+    m_control->write();
 
     //  Change Save Measure button text back to default
     m_saveNet->setPalette(m_saveDefaultPalette);
@@ -2499,7 +2546,8 @@ namespace Isis {
   }
 
 
-  /**
+  /** 
+   * This was used when ipce used docked widgets. 
    * This method is called from the constructor so that when the
    * Main window is created, it know's it's size and location.
    *
diff --git a/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.h b/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.h
index 735120a675dd0124bc53903762fbb1725cb89b14..29e62dae70160a281975101be1f8090a28cf4048 100644
--- a/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.h
+++ b/isis/src/qisis/objs/ControlPointEditWidget/ControlPointEditWidget.h
@@ -49,7 +49,7 @@ namespace Isis {
   class UniversalGroundMap;
 
   /**
-   * @brief Gui for editing ControlPoint
+   * @brief Gui for editing ControlPoints in ipce application
    *
    * @ingroup Visualization Tools
    *
@@ -66,8 +66,8 @@ namespace Isis {
    *   @history 2017-08-02 Tracie Sucharski - Added methods to return the current editPoint and
    *                           current editPoint Id.  Removed measure table methods. Fixes #5007,
    *                           #5008.
-  *   @history 2017-08-09 Adam Goins - Changed method references of SerialNumberList.Delete() to
-  *                            SerialNumberList.remove()
+   *   @history 2017-08-09 Adam Goins - Changed method references of SerialNumberList.Delete() to
+   *                           SerialNumberList.remove()
    *   @history 2017-08-09 Christopher Combs - Added QPushButton and slot for reloading a point's
    *                           measures in the ChipViewports. Fixes #5070.
    *   @history 2017-08-09 Christopher Combs - Added Apriori Latitude, Longitude, and Radius to
@@ -78,6 +78,18 @@ namespace Isis {
    *                           Fixes #4984.
    *   @history 2017-08-15 Tracie Sucharski - When ControlPoint is deleted, set the visibility of
    *                           this widget to false, then to true in loadPoint().  Fixes #5073.
+   *   @history 2018-03-23 Tracie Sucharski - Update the cnet filename with current cnet when it is
+   *                           changed.
+   *   @history 2018-03-26 Tracie Sucharski - Added slot, setControlFromActive which update editor
+   *                           if a new active control net is set in ipce. References #4567.
+   *   @history 2018-03-30 Tracie Sucharski - Save Control in addition to the control net and use
+   *                           Control to write the control net so Control can keep track of the
+   *                           modification state of the control net.
+   *   @history 2018-04-25 Tracie Sucharski - Fix bug when creating a control point from CubeDnView
+   *                           or FootprintView if a ground source exists in the serial number list.
+   *                           Fixes #5399.
+   *   @history 2018-05-02 Tracie Sucharski - Colorize save buttons properly when creating new
+   *                           control point and loading a different control point. 
    */
   class ControlPointEditWidget : public QWidget {
     Q_OBJECT
@@ -99,11 +111,13 @@ namespace Isis {
       void newControlNetwork(ControlNet *);
       void stretchChipViewport(Stretch *, CubeViewport *);
       void measureChanged();
+      // temporary signal for quick & dirty autosave in Ipce
       void saveControlNet();
 
     public slots:
       void setSerialNumberList(SerialNumberList *snList);
       void setControl(Control *control);
+      void setControlFromActive();
       void setEditPoint(ControlPoint *controlPoint, QString serialNumber = "");
       void deletePoint(ControlPoint *controlPoint);
 
@@ -111,6 +125,11 @@ namespace Isis {
                               bool isGroundSource = false);
 
       void updatePointInfo(ControlPoint &updatedPoint);
+      // Changed colorizeSaveNetButton to public slot so it could be called from
+      // Directory::saveActiveControl().  This should be temporary until the modify/save functionality
+      // of active control is re-factored. Also added reset parameter, defaulting to false so button
+      // is red. This default was used so that current calls did not need to be changed.
+      void colorizeSaveNetButton(bool reset = false);
 
     protected:
       bool eventFilter(QObject *o,QEvent *e);
@@ -138,6 +157,8 @@ namespace Isis {
       void measureSaved();
       void checkReference();
       void savePoint();
+
+      void colorizeAllSaveButtons(QString color);
       void colorizeSavePointButton();
 
       void openTemplateFile();
@@ -150,8 +171,6 @@ namespace Isis {
       void writeTemplateFile(QString);
       void clearEditPoint();
 
-      void colorizeSaveNetButton();
-
     private:
       void createActions();
 
@@ -232,9 +251,10 @@ namespace Isis {
       QPointer<QMainWindow> m_measureWindow; //!< Main window for the the measure table widget
       QPointer<QTableWidget> m_measureTable; //!< Table widget for the measures
 
-      QPointer<ControlPoint> m_editPoint; //!< The control point being edited
+      QPointer<ControlPoint> m_editPoint;   //!< The control point being edited
       SerialNumberList *m_serialNumberList; //!< Serial number list for the loaded cubes
-      QPointer<ControlNet> m_controlNet; //!< Current control net
+      QPointer<ControlNet> m_controlNet;    //!< Current control net
+      QPointer<Control> m_control;          //!< Current Control
 
       QPointer<ControlPoint> m_newPoint; //!< New control point
       QString m_lastUsedPointId; //!< Point id of the last used control point
diff --git a/isis/src/qisis/objs/Directory/BundleObservationViewWorkOrder.cpp b/isis/src/qisis/objs/Directory/BundleObservationViewWorkOrder.cpp
index 65eb26e5229c9e497ee41a54a1248945b4ebca2a..cd553f2ac94a09d0347c431fea78948a476c80bd 100755
--- a/isis/src/qisis/objs/Directory/BundleObservationViewWorkOrder.cpp
+++ b/isis/src/qisis/objs/Directory/BundleObservationViewWorkOrder.cpp
@@ -25,6 +25,7 @@
 #include "Directory.h"
 #include "BundleObservationView.h"
 #include "Project.h"
+#include "ProjectItemModel.h"
 
 namespace Isis {
 
@@ -113,7 +114,7 @@ namespace Isis {
    *
    */
   void BundleObservationViewWorkOrder::execute() {
-    //ProjectItem * selectedItem = project()->directory()->model()->selectedItems();
+//    ProjectItem * selectedItem = project()->directory()->model()->selectedItems();
     project()->directory()->addBundleObservationView(fileItem());
     project()->setClean(false);
   }
diff --git a/isis/src/qisis/objs/Directory/CnetEditorViewWorkOrder.cpp b/isis/src/qisis/objs/Directory/CnetEditorViewWorkOrder.cpp
index e565f110bb79f06586fe155da4a3d0d03e65a18d..9553e11e2da820e17f2c283fe7dac81ca8a28537 100644
--- a/isis/src/qisis/objs/Directory/CnetEditorViewWorkOrder.cpp
+++ b/isis/src/qisis/objs/Directory/CnetEditorViewWorkOrder.cpp
@@ -24,17 +24,13 @@
 
 #include <QtDebug>
 
-#include <QFileDialog>
-#include <QInputDialog>
-#include <QMessageBox>
+#include <QAction>
+#include <QUndoCommand>
 
-#include "CnetEditorWidget.h"
+#include "CnetEditorView.h"
 #include "Control.h"
 #include "ControlList.h"
-#include "ControlDisplayProperties.h"
 #include "Directory.h"
-#include "MosaicSceneItem.h"
-#include "MosaicSceneWidget.h"
 #include "Project.h"
 
 namespace Isis {
diff --git a/isis/src/qisis/objs/Directory/CnetEditorViewWorkOrder.h b/isis/src/qisis/objs/Directory/CnetEditorViewWorkOrder.h
index ac70e046582035cc20e21a347b56bc6bac596621..b069b97d5fd403cd16e59013dd23714bb23a8676 100644
--- a/isis/src/qisis/objs/Directory/CnetEditorViewWorkOrder.h
+++ b/isis/src/qisis/objs/Directory/CnetEditorViewWorkOrder.h
@@ -25,6 +25,10 @@
 #include "WorkOrder.h"
 
 namespace Isis {
+class ControlList;
+class Directory;
+class Project;
+
   /**
    * @brief This work order allows the user to open a cnet editor (table) view of a single control network.
    * This workorder is synchronous and undoable.
@@ -42,6 +46,7 @@ namespace Isis {
    *   @history 2017-11-02  Tyler Wilson - Added a null pointer check on the ControList *controls
    *                          pointer in the isExecutable(...) function to prevent potential
    *                          segfaults.  References #4492.
+   *   @history 2018-04-07 Tracie Sucharski - Clean up includes.
    */
   class CnetEditorViewWorkOrder : public WorkOrder {
       Q_OBJECT
diff --git a/isis/src/qisis/objs/Directory/Directory.cpp b/isis/src/qisis/objs/Directory/Directory.cpp
index c7a2dafc82226e169dc4e2ae2eab30553eab94f7..ea9f9194872e92d948262d1d9f63bd5e047cc047 100644
--- a/isis/src/qisis/objs/Directory/Directory.cpp
+++ b/isis/src/qisis/objs/Directory/Directory.cpp
@@ -45,12 +45,14 @@
 #include "BundleObservationViewWorkOrder.h"
 #include "ChipViewportsWidget.h"
 #include "CloseProjectWorkOrder.h"
+#include "CnetEditorView.h"
 #include "CnetEditorViewWorkOrder.h"
 #include "CnetEditorWidget.h"
 #include "Control.h"
 #include "ControlDisplayProperties.h"
 #include "ControlList.h"
 #include "ControlNet.h"
+#include "ControlNetTool.h"
 #include "ControlPointEditView.h"
 #include "ControlPointEditWidget.h"
 #include "CubeDnView.h"
@@ -110,8 +112,6 @@ namespace Isis {
    * because the WorkOrders we are attempting to add to the Directory are corrupt.
    */
   Directory::Directory(QObject *parent) : QObject(parent) {
-    //qDebug()<<"Directory::Directory";
-
 
     try {
       m_project = new Project(*this);
@@ -131,17 +131,18 @@ namespace Isis {
     //connect( m_project, SIGNAL(guiCamerasAdded(GuiCameraList *) ),
              //this, SLOT(guiCamerasAddedToProject(GuiCameraList *) ) );
 
-     connect( m_project, SIGNAL(projectLoaded(Project *) ),
+    connect( m_project, SIGNAL(projectLoaded(Project *) ),
               this, SLOT(updateRecentProjects(Project *) ) );
 
+    connect(this, SIGNAL(cnetModified()), m_project, SLOT(activeControlModified()));
 
     connect(m_project, SIGNAL(activeControlSet(bool)), this, SLOT(newActiveControl(bool)));
+    connect(m_project, SIGNAL(discardActiveControlEdits()),
+            this, SLOT(reloadActiveControlInCnetEditorView()));
 
     m_projectItemModel = new ProjectItemModel(this);
     m_projectItemModel->addProject(m_project);
-    connect(m_projectItemModel, SIGNAL(cleanProject(bool)), SIGNAL(cleanProject(bool)));
-
-//  qDebug()<<"Directory::Directory  model row counter after addProject = "<<m_projectItemModel->rowCount();
+    connect(m_projectItemModel, SIGNAL(cleanProject(bool)), this, SIGNAL(cleanProject(bool)));
 
     try {
 
@@ -531,15 +532,46 @@ namespace Isis {
   }
 
 
+  /**
+   * @description This slot was created specifically for the CnetEditorWidgets when user chooses a 
+   * new active control and wants to discard any edits in the old active control.  The only view 
+   * which will not be updated with the new control are any CnetEditorViews showing the old active 
+   * control.  CnetEditorWidget classes do not have the ability to reload a control net, so the 
+   * CnetEditor view displaying the old control is removed, then recreated.
+   *  
+   */
+  void Directory::reloadActiveControlInCnetEditorView() {
+
+    foreach(CnetEditorView *cnetEditorView, m_cnetEditorViewWidgets) {
+      if (cnetEditorView->control() == project()->activeControl()) {
+        emit viewClosed(cnetEditorView);
+        project()->activeControl()->closeControlNet();
+        project()->activeControl()->openControlNet();
+        addCnetEditorView(project()->activeControl());
+      }
+    }
+  }
+
+
   void Directory::newActiveControl(bool newControl) {
-    foreach(CnetEditorWidget *cnetEditorView, m_cnetEditorViewWidgets) {
-      if (cnetEditorView->control() == project()->activeControl()->controlNet()) {
-        cnetEditorView->pointTableView()->content()->setActiveControlNet(true);
-        cnetEditorView->measureTableView()->content()->setActiveControlNet(true);
+
+//  if (newControl && m_controlPointEditViewWidget) {
+//    bool closed = m_controlPointEditViewWidget->close();
+//    qDebug()<<"Directory::newActiveControl  CPEditor closed = "<<closed;
+//    emit viewClosed(m_controlPointEditViewWidget);
+//    delete m_controlPointEditViewWidget;
+//  }
+
+    // If the new active control is the same as what is showing in the cnetEditorWidget, allow
+    // editing of control points from the widget, otherwise turnoff from context menu
+    foreach(CnetEditorView *cnetEditorView, m_cnetEditorViewWidgets) {
+      if (cnetEditorView->control() == project()->activeControl()) {
+        cnetEditorView->cnetEditorWidget()->pointTableView()->content()->setActiveControlNet(true);
+        cnetEditorView->cnetEditorWidget()->measureTableView()->content()->setActiveControlNet(true);
       }
       else {
-        cnetEditorView->pointTableView()->content()->setActiveControlNet(false);
-        cnetEditorView->measureTableView()->content()->setActiveControlNet(false);
+        cnetEditorView->cnetEditorWidget()->pointTableView()->content()->setActiveControlNet(false);
+        cnetEditorView->cnetEditorWidget()->measureTableView()->content()->setActiveControlNet(false);
       }
     }
   }
@@ -567,20 +599,34 @@ namespace Isis {
     m_bundleObservationViews.append(result);
 
     QString str = fileItem->fileName();
+    FileName fileName = fileItem->fileName();
+
+    // strip out bundle results name from fileName
+    QString path = fileName.originalPath();
+    int pos = path.lastIndexOf("/");
+    QString bundleResultsName = "";
+    if (pos != -1) {
+      bundleResultsName = path.remove(0,pos+1);
+    }
 
+    if (str.contains("bundleout")) {
+      result->setWindowTitle( tr("Summary (%1)").
+                              arg( bundleResultsName ) );
+      result->setObjectName( result->windowTitle() );
+    }
     if (str.contains("residuals")) {
-      result->setWindowTitle( tr("Measure Residuals").
-                              arg( m_bundleObservationViews.count() ) );
+      result->setWindowTitle( tr("Measure Residuals (%1)").
+                              arg( bundleResultsName ) );
       result->setObjectName( result->windowTitle() );
     }
     else if (str.contains("points")) {
-      result->setWindowTitle( tr("Control Points").
-                              arg( m_bundleObservationViews.count() ) );
+      result->setWindowTitle( tr("Control Points (%1)").
+                              arg( bundleResultsName ) );
       result->setObjectName( result->windowTitle() );
     }
     else if (str.contains("images")) {
-      result->setWindowTitle( tr("Images").
-                              arg( m_bundleObservationViews.count() ) );
+      result->setWindowTitle( tr("Images (%1)").
+                              arg( bundleResultsName ) );
       result->setObjectName( result->windowTitle() );
     }
 
@@ -592,92 +638,27 @@ namespace Isis {
 
   /**
    * @brief Add the widget for the cnet editor view to the window.
-   * @param network Control net to edit.
-   * @return @b (CnetEditorWidget *) The view to add to the window.
+   * @param Control to edit.
+   * @return @b (CnetEditorView *) The view to add to the window.
    */
-  CnetEditorWidget *Directory::addCnetEditorView(Control *network) {
-
-    QString title = tr("Cnet Editor View %1").arg( network->displayProperties()->displayName() );
+  CnetEditorView *Directory::addCnetEditorView(Control *control) {
 
+    QString title = tr("Cnet Editor View %1").arg( control->displayProperties()->displayName() );
     FileName configFile("$HOME/.Isis/" + QApplication::applicationName() + "/" + title + ".config");
 
-    // TODO: This layout should be inside of the cnet editor widget, but I put it here to not
-    //     conflict with current work in the cnet editor widget code.
-    QWidget *result = new QWidget;
-    QGridLayout *resultLayout = new QGridLayout;
-    result->setLayout(resultLayout);
-
-    int row = 0;
-
-    QMenuBar *menuBar = new QMenuBar;
-    resultLayout->addWidget(menuBar, row, 0, 1, 2);
-    row++;
-    CnetEditorWidget *mainWidget = new CnetEditorWidget(network, configFile.expanded());
-    resultLayout->addWidget(mainWidget, row, 0, 1, 2);
-    row++;
+    CnetEditorView *result = new CnetEditorView(this, control, configFile);
 
-    // Populate the menu...
-    QMap< QAction *, QList< QString > > actionMap = mainWidget->menuActions();
-    QMapIterator< QAction *, QList< QString > > actionMapIterator(actionMap);
-
-    QMap<QString, QMenu *> topLevelMenus;
-
-    while ( actionMapIterator.hasNext() ) {
-      actionMapIterator.next();
-      QAction *actionToAdd = actionMapIterator.key();
-      QList< QString > location = actionMapIterator.value();
-
-      QMenu *menuToPutActionInto = NULL;
-
-      if ( location.count() ) {
-        QString topLevelMenuTitle = location.takeFirst();
-        if (!topLevelMenus[topLevelMenuTitle]) {
-          topLevelMenus[topLevelMenuTitle] = menuBar->addMenu(topLevelMenuTitle);
-        }
-
-        menuToPutActionInto = topLevelMenus[topLevelMenuTitle];
-      }
-
-      foreach (QString menuName, location) {
-        bool foundSubMenu = false;
-        foreach ( QAction *possibleSubMenu, menuToPutActionInto->actions() ) {
-          if (!foundSubMenu &&
-              possibleSubMenu->menu() && possibleSubMenu->menu()->title() == menuName) {
-            foundSubMenu = true;
-            menuToPutActionInto = possibleSubMenu->menu();
-          }
-        }
-
-        if (!foundSubMenu) {
-          menuToPutActionInto = menuToPutActionInto->addMenu(menuName);
-        }
-      }
-
-      menuToPutActionInto->addAction(actionToAdd);
+    if (project()->activeControl() && (control == project()->activeControl())) {
+      result->cnetEditorWidget()->pointTableView()->content()->setActiveControlNet(true);
+      result->cnetEditorWidget()->measureTableView()->content()->setActiveControlNet(true);
     }
 
-    QTabWidget *treeViews = new QTabWidget;
-    treeViews->addTab( mainWidget->pointTreeView(), tr("Point View") );
-    treeViews->addTab( mainWidget->serialTreeView(), tr("Serial View") );
-    treeViews->addTab( mainWidget->connectionTreeView(), tr("Connection View") );
-    resultLayout->addWidget(treeViews, row, 0, 1, 1);
-
-    QTabWidget *filterViews = new QTabWidget;
-    filterViews->addTab( mainWidget->pointFilterWidget(), tr("Filter Points and Measures") );
-    filterViews->addTab( mainWidget->serialFilterWidget(), tr("Filter Images and Points") );
-    filterViews->addTab( mainWidget->connectionFilterWidget(), tr("Filter Connections") );
-    resultLayout->addWidget(filterViews, row, 1, 1, 1);
-    row++;
-
-    if (project()->activeControl() && mainWidget->control() == project()->activeControl()->controlNet()) {
-      mainWidget->pointTableView()->content()->setActiveControlNet(true);
-      mainWidget->measureTableView()->content()->setActiveControlNet(true);
-    }
-    connect( result, SIGNAL( destroyed(QObject *) ),
-             this, SLOT( cleanupCnetEditorViewWidgets(QObject *) ) );
+    // connect destroyed signal to cleanupCnetEditorViewWidgets slot
+    connect(result, SIGNAL( destroyed(QObject *) ),
+            this, SLOT( cleanupCnetEditorViewWidgets(QObject *) ) );
 
     //  Connections for control point editing between views
-    connect(mainWidget, SIGNAL(editControlPoint(ControlPoint *, QString)),
+    connect(result->cnetEditorWidget(), SIGNAL(editControlPoint(ControlPoint *, QString)),
             this, SLOT(modifyControlPoint(ControlPoint *, QString)));
 
     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -685,21 +666,21 @@ namespace Isis {
     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     //
     // Connection between cneteditor view & other views
-    connect(mainWidget, SIGNAL(cnetModified()), this, SIGNAL(cnetModified()));
+    connect(result->cnetEditorWidget(), SIGNAL(cnetModified()), this, SIGNAL(cnetModified()));
 
     // ControlPointEditWidget is only object that emits cnetModified when ControlPoint is
     // deleted or saved
-    connect(this, SIGNAL(cnetModified()), mainWidget, SLOT(rebuildModels()));
+    connect(this, SIGNAL(cnetModified()), result->cnetEditorWidget(), SLOT(rebuildModels()));
 
-    m_cnetEditorViewWidgets.append(mainWidget);
-    m_controlMap.insertMulti(network, result);
+    m_cnetEditorViewWidgets.append(result);
+    m_controlMap.insertMulti(control, result);
 
     result->setWindowTitle(title);
     result->setObjectName(title);
 
     emit newWidgetAvailable(result);
 
-    return mainWidget;
+    return result;
   }
 
 
@@ -735,16 +716,19 @@ namespace Isis {
     connect(this, SIGNAL(redrawMeasures()), result, SIGNAL(redrawMeasures()));
     connect(this, SIGNAL(cnetModified()), result, SIGNAL(redrawMeasures()));
 
-    if (!project()->activeControl()) {
-      QList<QAction *> toolbar = result->toolPadActions();
-      QAction* cnetAction = toolbar[0];
-      MosaicControlNetTool *cnetButton = static_cast<MosaicControlNetTool *>(cnetAction->parent());
+    // Note:  This assumes the Control Net tool is the 1st in the toolpad.
+    QList<QAction *> toolbar = result->toolPadActions();
+    QAction* cnetAction = toolbar[0];
+    ControlNetTool *cnetTool = static_cast<ControlNetTool *>(cnetAction->parent());
+
+    connect (project(), SIGNAL(activeControlSet(bool)),
+             cnetAction, SLOT(setEnabled(bool)));
+    connect (project(), SIGNAL(activeControlSet(bool)),
+             cnetTool, SLOT(loadNetwork()));
 
+    //  If an active control has not been set, make the control net tool inactive
+    if (!project()->activeControl()) {
       cnetAction->setEnabled(false);
-      connect (project(), SIGNAL(activeControlSet(bool)),
-              cnetAction, SLOT(setEnabled(bool)));
-      connect (project(), SIGNAL(activeControlSet(bool)),
-              cnetButton, SLOT(loadNetwork()));
     }
 
     return result;
@@ -788,18 +772,19 @@ namespace Isis {
     //  to be drawn with different color/shape.
     connect(this, SIGNAL(redrawMeasures()), result, SIGNAL(redrawMeasures()));
 
-    //  Control Net tool will only be active if the project has an active Control.  Note:  This
-    //  assumes the Control Net tool is the 4th in the toolpad.
-    if (!project()->activeControl()) {
-      QList<QAction *> toolbar = result->toolPadActions();
-      QAction* cnetAction = toolbar[3];
-      MosaicControlNetTool *cnetButton = static_cast<MosaicControlNetTool *>(cnetAction->parent());
+    // Note:  This assumes the Control Net tool is the 4th in the toolpad.
+    QList<QAction *> toolbar = result->toolPadActions();
+    QAction* cnetAction = toolbar[3];
+    MosaicControlNetTool *cnetTool = static_cast<MosaicControlNetTool *>(cnetAction->parent());
 
+    connect (project(), SIGNAL(activeControlSet(bool)),
+             cnetAction, SLOT(setEnabled(bool)));
+    connect (project(), SIGNAL(activeControlSet(bool)),
+             cnetTool, SLOT(loadNetwork()));
+
+    //  Control Net tool will only be active if the project has an active Control.
+    if (!project()->activeControl()) {
       cnetAction->setEnabled(false);
-      connect (project(), SIGNAL(activeControlSet(bool)),
-              cnetAction, SLOT(setEnabled(bool)));
-      connect (project(), SIGNAL(activeControlSet(bool)),
-              cnetButton, SLOT(loadNetwork()));
     }
 
     return result;
@@ -852,11 +837,17 @@ namespace Isis {
 
       //  Create connections between signals from control point edit view and equivalent directory
       //  signals that can then be connected to other views that display control nets.
+//      connect(mainWidget, SIGNAL(cnetModified()),
+//              this, SIGNAL(cnetModified()));
       connect(result->controlPointEditWidget(), SIGNAL(cnetModified()),
               this, SIGNAL(cnetModified()));
+      connect(result->controlPointEditWidget(), SIGNAL(cnetModified()),
+              m_project, SLOT(activeControlModified()));
 
       connect(result->controlPointEditWidget(), SIGNAL(saveControlNet()),
               this, SLOT(makeBackupActiveControl()));
+      connect (project(), SIGNAL(activeControlSet(bool)),
+               result->controlPointEditWidget(), SLOT(setControlFromActive()));
     }
 
     return controlPointEditView();
@@ -1053,25 +1044,44 @@ namespace Isis {
    * @brief Removes pointers to deleted CnetEditorWidget objects.
    */
   void Directory::cleanupCnetEditorViewWidgets(QObject *obj) {
-
-    CnetEditorWidget *cnetEditorWidget = static_cast<CnetEditorWidget *>(obj);
-    if (!cnetEditorWidget) {
+    
+    CnetEditorView *cnetEditorView = static_cast<CnetEditorView *>(obj);
+    if (!cnetEditorView) {
       return;
     }
 
-    Control *control = m_controlMap.key(cnetEditorWidget);
-
-    m_controlMap.remove(control, cnetEditorWidget);
+    Control *control = m_controlMap.key(cnetEditorView);
+    m_controlMap.remove(control, cnetEditorView);
 
-    if ( m_controlMap.count(control) == 0 && project()->activeControl() != control) {
+    if ( m_controlMap.count(control) == 0 && project()->activeControl() != control) {      
       control->closeControlNet();
     }
 
-    m_cnetEditorViewWidgets.removeAll(cnetEditorWidget);
+    m_cnetEditorViewWidgets.removeAll(cnetEditorView);
     m_project->setClean(false);
   }
 
 
+  /**
+   * @description Return true if control is not currently being viewed in a CnetEditorWidget 
+   *  
+   * @param Control * Control used to search current CnetEditorWidgets 
+   *  
+   * @return @b (bool) Returns true if control is currently being viewed in CnetEditorWidget 
+   */
+  bool Directory::controlUsedInCnetEditorWidget(Control *control) {
+
+    bool result;
+    if ( m_controlMap.count(control) == 0) {
+      result = false;
+    }
+    else {
+      result = true;
+    }
+    return result;
+  }
+
+
   /**
    * @brief Removes pointers to deleted CubeDnView objects.
    */
@@ -1123,6 +1133,7 @@ namespace Isis {
      if (!controlPointEditView) {
        return;
      }
+     m_controlPointEditViewWidget = NULL;
      m_project->setClean(false);
 
    }
@@ -1205,12 +1216,12 @@ namespace Isis {
 
   /**
    * @brief Returns a list of all the control network views for this directory.
-   * @return @b QList<CnetEditorWidget *> A pointer list of all the CnetEditorWidget objects.
+   * @return @b QList<CnetEditorView *> A pointer list of all the CnetEditorWidget objects.
    */
-  QList<CnetEditorWidget *> Directory::cnetEditorViews() {
-    QList<CnetEditorWidget *> results;
+  QList<CnetEditorView *> Directory::cnetEditorViews() {
+    QList<CnetEditorView *> results;
 
-    foreach (CnetEditorWidget *widget, m_cnetEditorViewWidgets) {
+    foreach (CnetEditorView *widget, m_cnetEditorViewWidgets) {
       results.append(widget);
     }
 
@@ -1421,7 +1432,7 @@ namespace Isis {
       stream.writeStartElement("footprintViews");
 
       foreach (Footprint2DView *footprint2DViewWidget, m_footprint2DViewWidgets) {
-        footprint2DViewWidget->mosaicSceneWidget()->save(stream, project(), newProjectRoot);
+        footprint2DViewWidget->save(stream, project(), newProjectRoot);
       }
 
       stream.writeEndElement();
@@ -1442,7 +1453,7 @@ namespace Isis {
     if ( !m_cnetEditorViewWidgets.isEmpty() ) {
       stream.writeStartElement("cnetEditorViews");
 
-      foreach (CnetEditorWidget *cnetEditorWidget, m_cnetEditorViewWidgets) {
+      foreach (CnetEditorView *cnetEditorWidget, m_cnetEditorViewWidgets) {
         cnetEditorWidget->save(stream, project(), newProjectRoot);
       }
 
@@ -1491,7 +1502,7 @@ namespace Isis {
 
     if (result) {
       if (localName == "footprint2DView") {
-        m_directory->addFootprint2DView()->mosaicSceneWidget()->load(reader());
+        m_directory->addFootprint2DView()->load(reader());
       }
       else if (localName == "imageFileList") {
         m_directory->addImageFileListView()->load(reader());
@@ -1780,6 +1791,22 @@ namespace Isis {
   }
 
 
+  /**
+   * Save the current active control.
+   *
+   */
+  void Directory::saveActiveControl() {
+
+    if (project()->activeControl()) {
+      project()->activeControl()->write();
+      // add to HistoryTreeWidget
+      QString saveCnetHistoryEntry = project()->activeControl()->fileName() +
+        "has been saved.";
+      m_historyTreeWidget->addToHistory(saveCnetHistoryEntry);
+    }
+  }
+
+
   /**
    * Autosave for control net.  The control net is auto saved to the same directory as the input
    * net.  It is saved to controlNetFilename.net.bak.
diff --git a/isis/src/qisis/objs/Directory/Directory.h b/isis/src/qisis/objs/Directory/Directory.h
index 4f10a760e3baaca1188be1dc86cc46455678ab74..938ff71c6aa8ff46d41c6db254857392b2c8abe6 100644
--- a/isis/src/qisis/objs/Directory/Directory.h
+++ b/isis/src/qisis/objs/Directory/Directory.h
@@ -49,6 +49,7 @@ namespace Isis {
   class BundleObservation;
   class BundleObservationView;
   class ChipViewportsWidget;
+  class CnetEditorView;
   class CnetEditorWidget;
   class Control;
   class ControlNet;
@@ -206,6 +207,35 @@ namespace Isis {
    *                           projects. Fixes #5216.
    *   @history 2017-12-05 Christopher Combs - Added support for TemplateEditorWidget and
    *                           TemplateEditViewWorkOrder. Fixes #5168.
+   *   @history 2018-03-14 Ken Edmundson - Modified m_controlMap value from QWidget to
+   *                           CnetEditorWidget and changed connection  to take signal from
+   *                           a CnetEditorWidget instead of a QWidget for destruction of
+   *                           CnetEditorWidgets. Added ability to view bundleout.txt file in method
+   *                           addBundleObservationView.
+   *   @history 2018-03-14 Tracie Sucharski - Changed MosaicControlNetTool to ControlNetTool in
+   *                           addCubeDnView. Added method controlUsedInCnetEditorWidget so Project
+   *                           knows whether it is safe to close a control net when a new active is
+   *                           set. References #5026.
+   *   @history 2018-03-30 Tracie Sucharski - Use the Control::write to write the control net to
+   *                           disk instead of directly calling ControlNet::Write, so that the
+   *                           Control can keep track of the modified status of the control net.
+   *                           Connect cnetModified signal to Project::activeControlModified so
+   *                           modified state of the active control can be set so project knows
+   *                           that control has unsaved changes.
+   *   @history 2018-04-02 Tracie Sucharski - Cleanup m_controlPointEditViewWidget pointer when
+   *                           the ControlPointEditView is deleted. Added slot to reload the active
+   *                           control net in cneteditor view, effectively discarding any edits.
+   *                           This was done because there is no way to re-load a control net in the
+   *                           CnetEditor widget classes.
+   *   @history 2018-04-04 Tracie Sucharski - Created CnetEditorView class to use to add to QMdiArea
+   *                           instead of a CnetEditorWidget. This way there is no longer a
+   *                           disconnect between what has been added to the QMdiArea and what is
+   *                           stored in m_cnetEditorViewWidgets.
+   *   @history 2018-05-08 Tracie Sucharski - When saving active control, reset the "Save Net"
+   *                           button to black in the ControlPointEditorWidget.
+   *   @history 2018-05-14 Tracie Sucharski - Serialize Footprint2DView rather than
+   *                           MosaicSceneWidget. This will allow all parts of Footprint2DView to be
+   *                           saved/restored including the ImageFileListWidget. Fixes #5422.
    */
   class Directory : public QObject {
     Q_OBJECT
@@ -220,7 +250,7 @@ namespace Isis {
       QStringList recentProjectsList();
 
       BundleObservationView *addBundleObservationView(FileItemQsp fileItem);
-      CnetEditorWidget *addCnetEditorView(Control *network);
+      CnetEditorView *addCnetEditorView(Control *control);
       CubeDnView *addCubeDnView();
       Footprint2DView *addFootprint2DView();
       MatrixSceneWidget *addMatrixView();
@@ -249,7 +279,7 @@ namespace Isis {
       QList<QAction *> toolPadActions();
 
       QList<BundleObservationView *> bundleObservationViews();
-      QList<CnetEditorWidget *> cnetEditorViews();
+      QList<CnetEditorView *> cnetEditorViews();
       QList<CubeDnView *> cubeDnViews();
       QList<Footprint2DView *> footprint2DViews();
       QList<MatrixSceneWidget *> matrixViews();
@@ -261,6 +291,8 @@ namespace Isis {
       ControlPointEditView *controlPointEditView();
 //      ChipViewportsWidget *controlPointChipViewports();
 
+      bool controlUsedInCnetEditorWidget(Control *control);
+
       // Return the control point Id currently in the ControlPointEditWidget, if it exists
       QString editPointId();
 
@@ -324,6 +356,8 @@ namespace Isis {
       void newWarning();
       void newWidgetAvailable(QWidget *newWidget);
 
+      void viewClosed(QWidget *widget);
+
       void cnetModified();
       void redrawMeasures();
 
@@ -343,6 +377,7 @@ namespace Isis {
       //void imagesAddedToProject(ImageList *images);
       void updateControlNetEditConnections();
 
+      void saveActiveControl();
       // TODO temporary slot until autosave is implemented
       void makeBackupActiveControl();
 
@@ -360,6 +395,7 @@ namespace Isis {
     private slots:
       void initiateRenameProjectWorkOrder(QString projectName);
       void newActiveControl(bool newControl);
+      void reloadActiveControlInCnetEditorView();
 
     private:
       /**
@@ -415,7 +451,7 @@ namespace Isis {
 
       //!< List of BundleObservationView
       QList< QPointer<BundleObservationView> > m_bundleObservationViews;
-      QList< QPointer<CnetEditorWidget> > m_cnetEditorViewWidgets;  //!< List of CnetEditorWidgets
+      QList< QPointer<CnetEditorView> > m_cnetEditorViewWidgets;  //!< List of CnetEditorViews
       QList< QPointer<CubeDnView> > m_cubeDnViewWidgets;  //!< List of CubeDnCiew obs
       QList< QPointer<ImageFileListWidget> > m_fileListWidgets;  //!< List of ImageFileListWidgets
       QList< QPointer<Footprint2DView> > m_footprint2DViewWidgets; //!< List of Footprint2DView objs
@@ -458,7 +494,7 @@ namespace Isis {
       QList<QAction *> m_activeToolBarActions; //!< List of active ToolBar actions
       QList<QAction *> m_toolPadActions; //!< List of ToolPad actions
 
-      QMultiMap<Control*, QWidget*> m_controlMap; //!< Map to hold every view with an open Control
+      QMultiMap<Control*, CnetEditorView *> m_controlMap; //!< Map to hold every view with an open Control
 
       QString m_editPointId; //!< Current control point that is in the ControlPointEditWidget
 
diff --git a/isis/src/qisis/objs/Directory/ExportControlNetWorkOrder.cpp b/isis/src/qisis/objs/Directory/ExportControlNetWorkOrder.cpp
index b0ccfce9e7ffe6521771b29f5ffa200581bad608..a7c43d919f8032c1075cc7ec1444b394529468a0 100644
--- a/isis/src/qisis/objs/Directory/ExportControlNetWorkOrder.cpp
+++ b/isis/src/qisis/objs/Directory/ExportControlNetWorkOrder.cpp
@@ -48,6 +48,7 @@ namespace Isis {
     m_isSynchronous = false;
     m_isUndoable = false;
     QAction::setText(tr("&Export Control Network..."));
+    QUndoCommand::setText(tr("Export Control Network..."));
   }
 
 
@@ -97,7 +98,6 @@ namespace Isis {
    * true indicates that there is one control list in the project.
    */
   bool ExportControlNetWorkOrder::isExecutable(ControlList *controls) {
-    // TODO: This shouldn't be executable (in the menu) if there are no imported control networks?
 
     if (controls) {
       return (controls->count() == 1);
@@ -123,21 +123,19 @@ namespace Isis {
       QStringList internalData;
 
       Control *control = NULL;
+
       // See if there are any other control lists in the project and give these to the user as
       // choices for control nets they can export.
-
-
-      if(project()) {
+      if (project()) {
 
         Project *proj = project();
 
         QList<ControlList *> controls = proj->controls();
         if (controls.count() > 0) {
-          ControlList *l=controls.first();
+          ControlList *l = controls.first();
           WorkOrder::setData(l);
           control = controlList()->first();
         }
-
         else {
 
           QMap<Control *, QString> cnetChoices;
@@ -156,8 +154,6 @@ namespace Isis {
 
           control = cnetChoices.key(choice);
           internalData.append(control->id());
-
-
         }
       }
 
@@ -201,11 +197,9 @@ namespace Isis {
       control = controlList()->first();
     }
 
-    try {
-      control->controlNet()->Write(destination);
-    }
-    catch (IException &e) {
-      m_warning = e.toString();
+    QString currentLocation = control->fileName();
+    if (!QFile::copy(currentLocation, destination) ) {
+      m_warning = "Error saving control net.";
     }
   }
 
diff --git a/isis/src/qisis/objs/Directory/ExportControlNetWorkOrder.h b/isis/src/qisis/objs/Directory/ExportControlNetWorkOrder.h
index cfef357b21be951c94e3dd97323a9d3155aa4df0..1a393d21a1862976b26ba1d4cf184a33e4ddaa19 100644
--- a/isis/src/qisis/objs/Directory/ExportControlNetWorkOrder.h
+++ b/isis/src/qisis/objs/Directory/ExportControlNetWorkOrder.h
@@ -26,7 +26,12 @@ namespace Isis {
    *                           it no longer causes a segmentation fault when the user attempts
    *                           to export a control network from the file menu.  Fixes #4760.
    *   @history 2017-11-02 Tyler Wilson - Added a null pointer check on the controls variable in
-   *                           isExecutable to prevent potential seg faults.  References #4492.
+   *                           isExecutable to prevent potential seg faults.  References #4760.
+   *   @history 2018-03-13 Tracie Sucharski - Added Undo text to prevent runtime warning. Also
+   *                           correct redmine ticket number in previous history entry.
+   *   @history 2018-03-30 Tracie Sucharski - Copy the control net instead of writing.  This will
+   *                           be faster and will prevent another control net from being read into
+   *                           memory.
    */
   class ExportControlNetWorkOrder : public WorkOrder {
       Q_OBJECT
diff --git a/isis/src/qisis/objs/Directory/ImportImagesWorkOrder.cpp b/isis/src/qisis/objs/Directory/ImportImagesWorkOrder.cpp
index dfacd50a17bdb5029132110b1950b16077f1151c..60137383daff0fa235591333b525fa59001b8952 100644
--- a/isis/src/qisis/objs/Directory/ImportImagesWorkOrder.cpp
+++ b/isis/src/qisis/objs/Directory/ImportImagesWorkOrder.cpp
@@ -412,7 +412,9 @@ namespace Isis {
           projectImage->relocateDnData(FileName(destination).name());
         }
 
-        //  Set new ecub to readOnly
+        //  Set new ecub to readOnly.  When closing cube, the labels were being re-written because
+        // the cube was read/write. This caused a segfault when imported large number of images
+        // because of a label template file being opened too many times. 
         projectImage->reopen();
 
         delete input;
diff --git a/isis/src/qisis/objs/Directory/ImportShapesWorkOrder.cpp b/isis/src/qisis/objs/Directory/ImportShapesWorkOrder.cpp
index 988209bcdfe51c195d3a19f2827b0ad51bcf735a..efbb6d0666dc3b888a63b609ffcc5b1a0acae537 100644
--- a/isis/src/qisis/objs/Directory/ImportShapesWorkOrder.cpp
+++ b/isis/src/qisis/objs/Directory/ImportShapesWorkOrder.cpp
@@ -318,6 +318,11 @@ namespace Isis {
           projectShape->relocateDnData(FileName(destination).name());
         }
 
+        //  Set new ecub to readOnly.  When closing cube, the labels were being re-written because
+        // the cube was read/write. This caused a segfault when imported large number of images
+        // because of a label template file being opened too many times. 
+        projectShape->reopen();
+
         delete input;
 
         result = projectShape;
diff --git a/isis/src/qisis/objs/Directory/ImportShapesWorkOrder.h b/isis/src/qisis/objs/Directory/ImportShapesWorkOrder.h
index a173d832446fce82235e76781551e14aded4bf19..5bdd5d3813efa5ef45fabfd63e51150dd440dec2 100644
--- a/isis/src/qisis/objs/Directory/ImportShapesWorkOrder.h
+++ b/isis/src/qisis/objs/Directory/ImportShapesWorkOrder.h
@@ -56,6 +56,10 @@ namespace Isis {
    *   @history 2017-11-02 Tyler Wilson - Added a  null pointer check on the ProjectItem *item
    *                           pointer in isExecutable to prevent potential seg faults.
    *                           References #4492.
+   *   @history 2018-04-19 Tracie Sucharski - Fixed bug when importing shapes without DN data. Ecub
+   *                           labels were not complete due to a resulting ecub not being closed
+   *                           properly in thread.  The resulting ecub needs to be re-opened as
+   *                           readOnly to prevent this problem.  Fixes #5274.
    */
   class ImportShapesWorkOrder : public WorkOrder {
       Q_OBJECT
diff --git a/isis/src/qisis/objs/Directory/JigsawWorkOrder.cpp b/isis/src/qisis/objs/Directory/JigsawWorkOrder.cpp
index 2df93cfc6bad805335d84ec652b3046eef2db7fd..f08ae306d9ede9efb0c013b05038bc9d8e8617de 100644
--- a/isis/src/qisis/objs/Directory/JigsawWorkOrder.cpp
+++ b/isis/src/qisis/objs/Directory/JigsawWorkOrder.cpp
@@ -30,6 +30,7 @@
 #include <QInputDialog>
 #include <QMessageBox>
 
+#include "BundleSolutionInfo.h"
 #include "Control.h"
 #include "Directory.h"
 #include "JigsawDialog.h"
@@ -114,12 +115,15 @@ namespace Isis {
     bool success = WorkOrder::setupExecution();
 
     if (success) {
+
+      QStringList internalData;
+
       // Create a blocking setup dialog initially and check to make sure we get valid info
       JigsawSetupDialog setup(project());
       if (setup.exec() == QDialog::Accepted) {
         m_bundleSettings = setup.bundleSettings();
         if (setup.selectedControl()) {
-          setInternalData(QStringList(setup.selectedControl()->id()));
+          internalData.append(QStringList(setup.selectedControl()->id()));
         }
         // This else should not happen, the work order should be disabled if there are no controls.
         else {
@@ -127,13 +131,22 @@ namespace Isis {
           QMessageBox::critical(qobject_cast<QWidget *>(parent()), "Error", msg);
           success = false;
         }
+        // set output control network file name
+        if (!setup.outputControlName().isEmpty()) {
+          internalData.append(setup.outputControlName());
+        }
+        else {
+          QString msg = "You must set an output control network filename.";
+          QMessageBox::critical(qobject_cast<QWidget *>(parent()), "Error", msg);
+          success = false;
+        }
       }
       else {
         success = false;
       }
+      setInternalData(internalData);
     }
 
-
     return success;
   }
 
@@ -159,9 +172,16 @@ namespace Isis {
    * @see WorkOrder::execute()
    */
   void JigsawWorkOrder::execute() {
+
+    Project *proj = project();
+
     // Get the selected control and bundle settings and give them to the JigsawDialog for now.
-    Control *selectedControl = project()->control(internalData().first());
-    JigsawDialog *runDialog = new JigsawDialog(project(), m_bundleSettings, selectedControl);
+    Control *selectedControl = proj->control(internalData().first());
+
+    QString outputControlFileName = internalData().at(1);
+
+    JigsawDialog *runDialog = new JigsawDialog(project(), m_bundleSettings, selectedControl,
+                                               outputControlFileName);
     runDialog->setAttribute(Qt::WA_DeleteOnClose);
     runDialog->show();
   }
diff --git a/isis/src/qisis/objs/Directory/JigsawWorkOrder.h b/isis/src/qisis/objs/Directory/JigsawWorkOrder.h
index 3d480e8149a1a9ea192ad66f08aef3c8b6387496..49f3d81f72ea6a554cda91310569c848638c07e0 100644
--- a/isis/src/qisis/objs/Directory/JigsawWorkOrder.h
+++ b/isis/src/qisis/objs/Directory/JigsawWorkOrder.h
@@ -48,7 +48,14 @@ namespace Isis {
    *   @history 2017-04-25 Ian Humphrey - Modified tool tip text. Fixes #4819.
    *   @history 2017-07-25 Cole Neubauer - Added project()->setClean call #4969
    *   @history 2017-07-25 Cole Neubauer - Moved project()->setClean call to JigsawDialog because
-   *                            the workorder does not actually execute the bundle adjustment #4960
+   *                           the workorder does not actually execute the bundle adjustment #4960
+   *   @history 2018-03-22 Ken Edmundson - Modified setupExecution method to append output control
+   *                           network filename to internalData. Modified execute method to look for
+   *                           input control network in BundleSolutionInfos if not found under main
+   *                           part of project tree.
+   *   @history 2018-03-23 Ken Edmundson - In execute method, removed search for input control
+   *                           network in BundleSolutionInfos. No longer needed as control is now
+   *                           properly saved in projects m_idToControlMap.
    */
   class JigsawWorkOrder : public WorkOrder {
       Q_OBJECT
diff --git a/isis/src/qisis/objs/Directory/SetActiveControlWorkOrder.cpp b/isis/src/qisis/objs/Directory/SetActiveControlWorkOrder.cpp
index a797cea008c21c06bee4ec3dec2c287dd5d7c2a0..e8885bf84ea3ed46437501f2efd7b0c52ec42d6a 100644
--- a/isis/src/qisis/objs/Directory/SetActiveControlWorkOrder.cpp
+++ b/isis/src/qisis/objs/Directory/SetActiveControlWorkOrder.cpp
@@ -80,6 +80,7 @@ namespace Isis {
    */
   bool SetActiveControlWorkOrder::isExecutable(ControlList *controls) {
 
+    // Return false if more than 1 control was selected or if selected is already active
     if (controls) {
       if (controls->size() != 1 || project()->activeControl() == controls->at(0)) {
         return false;
diff --git a/isis/src/qisis/objs/Directory/SetActiveImageListWorkOrder.cpp b/isis/src/qisis/objs/Directory/SetActiveImageListWorkOrder.cpp
index b70d7b41c0f873024243dee35879865203d4cdd0..36caf06e6f15fdb61d3c8537e5d624109dca6062 100644
--- a/isis/src/qisis/objs/Directory/SetActiveImageListWorkOrder.cpp
+++ b/isis/src/qisis/objs/Directory/SetActiveImageListWorkOrder.cpp
@@ -76,10 +76,9 @@ namespace Isis {
    * @return  @b bool True if  we can set as active, False otherwise.
    */
   bool SetActiveImageListWorkOrder::isExecutable(ImageList *imageList) {
-
-    if(!imageList)
+    if (imageList->name() == "") {
       return false;
-
+    }
     if (project()->activeImageList()) {
       if (project()->activeImageList()->name() == imageList->name()) {
         return false;
diff --git a/isis/src/qisis/objs/Directory/SetActiveImageListWorkOrder.h b/isis/src/qisis/objs/Directory/SetActiveImageListWorkOrder.h
index 6da70ad98ea68be87eb827505edb05138201bfa8..fc7b256adcc58fe76e508390f3a6bc05d748a035 100644
--- a/isis/src/qisis/objs/Directory/SetActiveImageListWorkOrder.h
+++ b/isis/src/qisis/objs/Directory/SetActiveImageListWorkOrder.h
@@ -45,8 +45,8 @@ namespace Isis {
    *   @history 2017-08-03 Cole Neubauer - Created a try catch around a previously unprotected
    *                           error to handle errors thrown in the workorder that halted
    *                           execution. Fixes #5026
-   *   @history 2017-11-02 Tyler Wilson - Added a null pointer reference check to imageList variable
-   *                           in isExecutable to prevent potential seg faults.  References #4492.
+   *   @history 2017-10-18 Adam Paquette - Added a logical check in the isExecutable function
+   *                           to check for single images vs image lists. Fixes #5138.
    */
 
   class SetActiveImageListWorkOrder : public WorkOrder {
diff --git a/isis/src/qisis/objs/Footprint2DView/Footprint2DView.cpp b/isis/src/qisis/objs/Footprint2DView/Footprint2DView.cpp
index c7d7ed814e0d869b4de0647390bd639381820093..6fda9c72a21f20347adc7c66ece8b6205dfd6834 100644
--- a/isis/src/qisis/objs/Footprint2DView/Footprint2DView.cpp
+++ b/isis/src/qisis/objs/Footprint2DView/Footprint2DView.cpp
@@ -41,17 +41,21 @@
 #include <QVBoxLayout>
 #include <QWidget>
 #include <QWidgetAction>
+#include <QXmlStreamWriter>
 
 #include "ControlPoint.h"
 #include "Cube.h"
+#include "Directory.h"
 #include "Image.h"
 #include "ImageFileListWidget.h"
 #include "MosaicGraphicsView.h"
 #include "MosaicSceneWidget.h"
+#include "Project.h"
 #include "ProjectItem.h"
 #include "ProjectItemModel.h"
 #include "Shape.h"
 #include "ToolPad.h"
+#include "XmlStackedHandlerReader.h"
 
 namespace Isis {
   /**
@@ -351,4 +355,92 @@ namespace Isis {
   QList<QAction *> Footprint2DView::toolPadActions() {
     return m_toolPad->actions();
   }
+
+
+  /**
+   * @brief Loads the Footprint2DView from an XML file.
+   * @param xmlReader  The reader that takes in and parses the XML file.
+   */
+  void Footprint2DView::load(XmlStackedHandlerReader *xmlReader) {
+    xmlReader->pushContentHandler( new XmlHandler(this) );
+  }
+
+
+  /**
+   * @brief Save the footprint view widgets (ImageFileListWidget and MosaicSceneWidget to an XML 
+   *        file.
+   * @param stream  The XML stream writer
+   * @param newProjectRoot The FileName of the project this Directory is attached to.
+   *
+   * @internal
+   *   @history 2016-11-07 Ian Humphrey - Restored saving of footprints (footprint2view).
+   *                           References #4486.
+   */
+  void Footprint2DView::save(QXmlStreamWriter &stream, Project *project,
+                             FileName newProjectRoot) const {
+
+    stream.writeStartElement("footprint2DView");
+
+    m_fileListWidget->save(stream, project, newProjectRoot);
+    m_sceneWidget->save(stream, project, newProjectRoot);
+
+    stream.writeEndElement();
+  }
+
+
+  /**
+   * @brief This function sets the Directory pointer for the Directory::XmlHandler class
+   * @param directory The new directory we are setting XmlHandler's member variable to.
+   */
+  Footprint2DView::XmlHandler::XmlHandler(Footprint2DView *footprintView) {
+
+    m_footprintView = footprintView;
+  }
+
+
+  /**
+   * @brief The Destructor for Directory::XmlHandler
+   */
+  Footprint2DView::XmlHandler::~XmlHandler() {
+  }
+
+
+  /**
+   * @brief The XML reader invokes this method at the start of every element in the
+   * XML document.  This method expects <footprint2DView/> and <imageFileList/>
+   * elements.
+   * A quick example using this function:
+   *     startElement("xsl","stylesheet","xsl:stylesheet",attributes)
+   *
+   * @param namespaceURI The Uniform Resource Identifier of the element's namespace
+   * @param localName The local name string
+   * @param qName The XML qualified string (or empty, if QNames are not available).
+   * @param atts The XML attributes attached to each element
+   * @return @b bool  Returns True signalling to the reader the start of a valid XML element.  If
+   * False is returned, something bad happened.
+   *
+   */
+  bool Footprint2DView::XmlHandler::startElement(const QString &namespaceURI, const QString &localName,
+                                           const QString &qName, const QXmlAttributes &atts) {
+    bool result = XmlStackedHandler::startElement(namespaceURI, localName, qName, atts);
+
+    if (result) {
+      if (localName == "mosaicScene") {
+        m_footprintView->mosaicSceneWidget()->load(reader());
+      }
+      if (localName == "imageFileList") {
+        m_footprintView->m_fileListWidget->load(reader());
+      }
+    }
+    return result;
+  }
+
+
+  bool Footprint2DView::XmlHandler::endElement(const QString &namespaceURI,
+      const QString &localName, const QString &qName) {
+    bool result = XmlStackedHandler::endElement(namespaceURI, localName, qName);
+
+    return result;
+  }
 }
+
diff --git a/isis/src/qisis/objs/Footprint2DView/Footprint2DView.h b/isis/src/qisis/objs/Footprint2DView/Footprint2DView.h
index d3a7a4e3942095111522e9a5761dd43bb60376d0..821fe9ae7049e1ad641c86c1f64838b79e124ba4 100644
--- a/isis/src/qisis/objs/Footprint2DView/Footprint2DView.h
+++ b/isis/src/qisis/objs/Footprint2DView/Footprint2DView.h
@@ -27,12 +27,15 @@
 #include <QSize>
 
 #include "AbstractProjectItemView.h"
+#include "FileName.h"
+#include "XmlStackedHandler.h"
 
 class QAction;
 class QEvent;
 class QMainWindow;
 class QToolBar;
 class QWidgetAction;
+class QXmlStreamWriter;
 
 namespace Isis {
 
@@ -41,7 +44,9 @@ namespace Isis {
   class Image;
   class ImageFileListWidget;
   class MosaicSceneWidget;
+  class Project;
   class ToolPad;
+  class XmlStackedHandlerReader;
 
   /**
    * View for displaying footprints of images in a QMos like way.
@@ -64,6 +69,9 @@ namespace Isis {
    *                           footprint. Fixes #5050.
    *   @history 2017-08-02 Tracie Sucharski - Fixed connections between views for control point
    *                           editing.  Fixes #5007, #5008.
+   *   @history 2018-05-14 Tracie Sucharski - Serialize Footprint2DView rather than
+   *                           MosaicSceneWidget. This will allow all parts of Footprint2DView to be
+   *                           saved/restored including the ImageFileListWidget. Fixes #5422.
    */
   class Footprint2DView : public AbstractProjectItemView {
 
@@ -80,6 +88,9 @@ namespace Isis {
 
       QSize sizeHint() const;
 
+      void load(XmlStackedHandlerReader *xmlReader);
+      void save(QXmlStreamWriter &stream, Project *project, FileName newProjectRoot) const;
+
     signals:
       void modifyControlPoint(ControlPoint *controlPoint);
       void deleteControlPoint(ControlPoint *controlPoint);
@@ -97,6 +108,28 @@ namespace Isis {
       void onQueueSelectionChanged();
       void onMosItemRemoved(Image *image);
 
+    private:
+      /**
+       * @author 2018-05-11 Tracie Sucharski
+       *
+       * @internal
+       */
+      class XmlHandler : public XmlStackedHandler {
+        public:
+          XmlHandler(Footprint2DView *footprintView);
+          ~XmlHandler();
+
+          virtual bool startElement(const QString &namespaceURI, const QString &localName,
+                                    const QString &qName, const QXmlAttributes &atts);
+          virtual bool endElement(const QString &namespaceURI, const QString &localName,
+                                  const QString &qName);
+
+        private:
+          Q_DISABLE_COPY(XmlHandler);
+
+          Footprint2DView *m_footprintView;      //!< The Footprint2DView
+      };
+
     private:
       MosaicSceneWidget *m_sceneWidget; //!< The scene widget
       ImageFileListWidget *m_fileListWidget; //!< The file list widget
diff --git a/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.cpp b/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.cpp
index bfadb7dd13d0afce1ea048cdd2c1d6b99f53b5da..eeb4b0cb8fce81c4daa0d2f5b61c95f33288c9dd 100644
--- a/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.cpp
+++ b/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.cpp
@@ -159,6 +159,43 @@ namespace Isis {
   }
 
 
+  /**
+   * Add a non-workorder history to the display.
+   *
+   * @param (QString) historyEntry The string displayed in the history tree
+   */
+  void HistoryTreeWidget::addToHistory(QString historyEntry) {
+
+    QString data = historyEntry;
+
+    QStringList columnData;
+    columnData.append(data);
+
+    QTreeWidgetItem *newItem = new QTreeWidgetItem(columnData);
+
+
+    // Do font for progress text
+    QFont progressFont = newItem->font(1);
+    progressFont.setItalic(true);
+    newItem->setFont(1, progressFont);
+    newItem->setForeground(1, Qt::gray);
+
+    this->insertTopLevelItem(0, newItem);
+//      invisibleRootItem()->addChild(newItem);
+
+    //Sometimes the pointer returned by this call is 0 (hence the check).
+    //So we are not creating a progress bar for every work order which would
+    //include those that do not need it.
+
+//    if(workOrder->progressBar() )  {
+//      setItemWidget(newItem, 1, new ProgressBar);
+////        this->setItemWidget(newItem, 1, workOrder->progressBar() );
+//    }
+    scrollToItem(newItem);
+    refit();
+  }
+
+
   /**
    * We need to manually manage these progress widgets because QTreeWidget does a poor job of it.
    *   This should be called when the progress bar instances have changed (new progress, lost a
diff --git a/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.h b/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.h
index e0867f806e8aa4ae17df611ecf467f6f0b8585c4..b32eaf7c56cf73dd1599cbfd9aaa41cced41dd55 100644
--- a/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.h
+++ b/isis/src/qisis/objs/HistoryTreeWidget/HistoryTreeWidget.h
@@ -40,6 +40,11 @@ namespace Isis {
    *   @history 2017-11-08 Tyler Wilson - Reverted the code change in #5096 to restore the 
    *                            ProgressBar, and changed code in OpenRecentProjectsWorkOrder.cpp
    *                            to prevent the segfault which #5096 was addressing.  Fixes #5149.
+   *   @history 2018-04-07 Tracie Sucharski - Added method to force a history entry using a string
+   *                            rather than a WorkOrder.  This should be a temporary method until
+   *                            saving a control is turned into a WorkOrder.  This was done for the
+   *                            alpha release simply to notify the user that the control was saved.
+   *                            However, this history entry is not saved/restored to a project.
    *
    */
   class HistoryTreeWidget : public QTreeWidget {
@@ -48,6 +53,8 @@ namespace Isis {
       HistoryTreeWidget(Project *project, QWidget *parent = 0);
       virtual ~HistoryTreeWidget();
 
+      void addToHistory(QString historyEntry);
+
     protected:
       int sizeHintForColumn(int column) const;
 
diff --git a/isis/src/qisis/objs/ImageFileListWidget/ImageFileListWidget.cpp b/isis/src/qisis/objs/ImageFileListWidget/ImageFileListWidget.cpp
index 40c1d94921d31b3475c5c349c98f0629481b8c4b..260afa2a5c8feb603666ca45dc9f090bd69af69b 100644
--- a/isis/src/qisis/objs/ImageFileListWidget/ImageFileListWidget.cpp
+++ b/isis/src/qisis/objs/ImageFileListWidget/ImageFileListWidget.cpp
@@ -217,15 +217,6 @@ namespace Isis {
     return output;
   }
 
-  /**
-   * This method pushes a new XmlHandler into the parser stack.
-   *
-   * @param xmlReader This is the parser stack.
-   */
-  void ImageFileListWidget::load(XmlStackedHandlerReader *xmlReader) {
-    xmlReader->pushContentHandler(new XmlHandler(this));
-  }
-
   /**
    * This method calls ImageTreeWidget::actions() which sets up a QAction
    * that sets a default for the file list columns and returns a QList of
@@ -611,6 +602,17 @@ namespace Isis {
     return result;
   }
 
+
+  /**
+   * This method pushes a new XmlHandler into the parser stack.
+   *
+   * @param xmlReader This is the parser stack.
+   */
+  void ImageFileListWidget::load(XmlStackedHandlerReader *xmlReader) {
+    xmlReader->pushContentHandler(new XmlHandler(this));
+  }
+
+
   /**
    * This method saves the FootprintColumns in the project and the settings associated
    * with every column.
@@ -621,10 +623,11 @@ namespace Isis {
    */
   void ImageFileListWidget::save(QXmlStreamWriter &stream, Project *project,
                                  FileName newProjectRoot) const {
+
     stream.writeStartElement("imageFileList");
 
     // Write QSettings
-    stream.writeStartElement("widgetGeometry");
+//  stream.writeStartElement("widgetGeometry");
 //  QString geom = saveGeometry();
 //  //qDebug()<<"ImageFileListWidget::save   geometry = "<<geom;
 //  stream.writeAttribute("value", saveGeometry());
@@ -672,6 +675,7 @@ namespace Isis {
     stream.writeEndElement();
   }
 
+
   /**
    * This method saves the QTreeWidgetItem and the settings associated with the QTreeWidgetItem
    * to the stream.
@@ -758,7 +762,7 @@ namespace Isis {
   bool ImageFileListWidget::XmlHandler::startElement(const QString &namespaceURI,
       const QString &localName, const QString &qName, const QXmlAttributes &atts) {
     bool result = XmlStackedHandler::startElement(namespaceURI, localName, qName, atts);
-  /*  //tjw
+
     if (result) {
 
 //    if (localName == "geometry") {
@@ -826,7 +830,6 @@ namespace Isis {
       }
 
     }
-    */
 
     return result;
   }
@@ -905,6 +908,4 @@ namespace Isis {
       }
     }
   }
-
-
 }
diff --git a/isis/src/qisis/objs/ImageFileListWidget/ImageFileListWidget.h b/isis/src/qisis/objs/ImageFileListWidget/ImageFileListWidget.h
index 0af97c7b8801c7bcbb02301481c62630db8988f3..2573dbbd910849ff0bf68cd29e4a54ef37e68bf4 100644
--- a/isis/src/qisis/objs/ImageFileListWidget/ImageFileListWidget.h
+++ b/isis/src/qisis/objs/ImageFileListWidget/ImageFileListWidget.h
@@ -52,6 +52,8 @@ namespace Isis {
    *   @history 2017-07-18 Cole Neubauer - Added removeImages slot to be able to remove from the
    *                           ImageFileList in IPCE Fixes #4996
    *   @history 2017-08-22 Cole Neuabuer - Added ability to search ImageFileListWidget. Fixes #1556
+   *   @history 2018-05-15 Tracie Sucharski - Fixed xml serialization for Ipce project saves.  Fixes
+   *                            #5422.
    */
   class ImageFileListWidget : public QWidget {
       Q_OBJECT
diff --git a/isis/src/qisis/objs/JigsawDialog/JigsawDialog.cpp b/isis/src/qisis/objs/JigsawDialog/JigsawDialog.cpp
index 00a725104ec47285a19670ed1663e0159ede079c..1494b1f4a75d3b2b3920fd09c506f5771a8226d0 100644
--- a/isis/src/qisis/objs/JigsawDialog/JigsawDialog.cpp
+++ b/isis/src/qisis/objs/JigsawDialog/JigsawDialog.cpp
@@ -56,12 +56,13 @@ namespace Isis {
   JigsawDialog::JigsawDialog(Project *project,
                              BundleSettingsQsp bundleSettings,
                              Control *selectedControl,
+                             QString outputControlFileName,
                              QWidget *parent) : QDialog(parent), m_ui(new Ui::JigsawDialog) {
-
     m_project = project;
     m_bundleSettings = bundleSettings;
     m_selectedControl = selectedControl;
     m_selectedControlName = FileName(selectedControl->fileName()).name();
+    m_outputControlName = outputControlFileName;
     init();
   }
 
@@ -108,7 +109,7 @@ namespace Isis {
            this, SLOT(rejectBundleResults()));
 
     m_bundleAdjust = NULL;
-    m_bundleSolutionInfo = NULL;
+//    m_bundleSolutionInfo = NULL;
 
     m_bRunning = false;
 
@@ -137,9 +138,9 @@ namespace Isis {
    * Destructor.
    */
   JigsawDialog::~JigsawDialog() {
-    if (m_bundleSolutionInfo) {
-      delete m_bundleSolutionInfo;
-    }
+//    if (m_bundleSolutionInfo) {
+//      delete m_bundleSolutionInfo;
+//    }
     if (m_bundleAdjust) {
       delete m_bundleAdjust;
       m_bundleAdjust = NULL;
@@ -147,7 +148,7 @@ namespace Isis {
     if (m_ui) {
       delete m_ui;
     }
-    m_bundleSolutionInfo = NULL;
+//    m_bundleSolutionInfo = NULL;
     m_ui = NULL;
   }
 
@@ -175,6 +176,7 @@ namespace Isis {
 
     if (setupdlg.exec() == QDialog::Accepted) {
       m_selectedControlName = setupdlg.selectedControlName();
+      m_outputControlName = setupdlg.outputControlName();
       m_selectedControl = setupdlg.selectedControl();
       m_bundleSettings = setupdlg.bundleSettings();
       // The settings have been modified, might be misleading to keep this check after setup.
@@ -209,7 +211,8 @@ namespace Isis {
          }
 
          // Grab the control name that was used in that bundle adjustment.
-         m_selectedControlName = FileName(bundleSolutionInfo.last()->controlNetworkFileName()).name();
+         m_selectedControlName
+             = FileName(bundleSolutionInfo.last()->inputControlNetFileName()).name();
       }
 
       // Clear the dialog displays.
@@ -379,12 +382,24 @@ namespace Isis {
     //  Write text summary file
     m_bundleSolutionInfo->outputText();
 
-    // create output control net
-    // Write the new jigged control net with correct path to results folder + runtime
-    FileName jiggedControlName(m_project->bundleSolutionInfoRoot() + "/" + runTime + "/" +
-                               FileName(m_bundleSolutionInfo->controlNetworkFileName()).name());
+    // create output control net file name
+    FileName outputControlName;
+    if (!m_outputControlName.isEmpty()) {
+      outputControlName
+          = FileName(m_project->bundleSolutionInfoRoot() + "/" + runTime + "/" +
+                     m_outputControlName);
+    }
+    else {
+      outputControlName
+          = FileName(m_project->bundleSolutionInfoRoot() + "/" + runTime + "/Out-" + runTime + "-" +
+                     FileName(m_bundleSolutionInfo->inputControlNetFileName()).name());
+    }
+
+    // Write output control net with correct path to results folder + runtime
+    m_bundleSolutionInfo->bundleResults().outputControlNet()->Write(outputControlName.toString());
 
-    m_bundleSolutionInfo->bundleResults().outputControlNet()->Write(jiggedControlName.toString());
+    // create Control with output control net and add to m_bundleSolutionInfo
+    m_bundleSolutionInfo->setOutputControl(new Control(m_project, outputControlName.expanded()));
 
     // Iterate through all of the image lists (the "imports" in the project).
     QList<ImageList *> imageLists = m_bundleSolutionInfo->imageList();
@@ -448,7 +463,8 @@ namespace Isis {
     }
 
     // Tell the project about the BundleSolutionInfo
-    m_project->addBundleSolutionInfo( new BundleSolutionInfo(*m_bundleSolutionInfo) );
+//    m_project->addBundleSolutionInfo( new BundleSolutionInfo(*m_bundleSolutionInfo) );
+    m_project->addBundleSolutionInfo(m_bundleSolutionInfo);
 
     // Make sure that when we add our results, we let the use last settings box be checkable.
     m_ui->useLastSettings->setEnabled(true);
@@ -486,8 +502,8 @@ namespace Isis {
     // Cleanup the results (bundle solution info)
     // How does this affect m_bundleSettings or m_bundleAdjustment?
     // How does this affect using the last (most recent) settings for the run?
-    delete m_bundleSolutionInfo;
-    m_bundleSolutionInfo = NULL;
+//    delete m_bundleSolutionInfo;
+//    m_bundleSolutionInfo = NULL;
   }
 
 
diff --git a/isis/src/qisis/objs/JigsawDialog/JigsawDialog.h b/isis/src/qisis/objs/JigsawDialog/JigsawDialog.h
index d120cdf7f5b8df602975a40ce458678d9c11daab..01fb118dadf009a124951bafa176fdb2e4c7b0b4 100644
--- a/isis/src/qisis/objs/JigsawDialog/JigsawDialog.h
+++ b/isis/src/qisis/objs/JigsawDialog/JigsawDialog.h
@@ -79,6 +79,15 @@ namespace Isis {
    *                           accepted. Fixes #4960
    *   @history 2017-11-01 Ian Humphrey - Create ecubs in the bundle results directory which contain
    *                           updated SPICE.  Fixes #4804, #4849.
+   *   @history 2018-03-22 Ken Edmundson - Added member variable QString m_outputControlName. Added
+   *                           argument QString outputControlFileName to constructor. Modified
+   *                           acceptBundleResults method to take output control network filename
+   *                           from the JigsawSetupDialog.
+   *   @history 2018-05-22 Ken Edmundson - Modified init() method to not set m_BundleSolutionInfo to
+   *                           NULL because JigsawDialog no longer owns it. Modified destructor to
+   *                           not delete m_BundleSolutionInfo or set it to NULL. Note this is NOT
+   *                           ideal, m_BundleSolutionInfo should be a QSharedPointer, not a raw
+   *                           pointer.
    */
   class JigsawDialog : public QDialog {
     Q_OBJECT
@@ -88,6 +97,7 @@ namespace Isis {
     explicit JigsawDialog(Project *project,
                           BundleSettingsQsp bundleSettings,
                           Control *selectedControl,
+                          QString outputControlFileName,
                           QWidget *parent = 0);
 
     ~JigsawDialog();
@@ -106,6 +116,7 @@ namespace Isis {
     Project *m_project;
     Control *m_selectedControl;
     QString m_selectedControlName;
+    QString m_outputControlName;
     BundleSettingsQsp m_bundleSettings;
 
   private:
diff --git a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp
index 1d5109eb27b7db142702882d65756bf49074c789..97cbd74ea632085f80aa1cc9950c24ff732bba91 100644
--- a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp
+++ b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp
@@ -60,6 +60,19 @@ namespace Isis {
         m_ui->controlNetworkComboBox->addItem(control->displayProperties()->displayName(), v);
       }
     }
+    // add control nets from bundle solutions, if any
+    int numBundles = project->bundleSolutionInfo().size();
+    for (int i = 0; i < numBundles; i++) {
+      Control *bundleControl = project->bundleSolutionInfo().at(i)->control();
+
+      QVariant v = qVariantFromValue((void*)bundleControl);
+
+      m_ui->controlNetworkComboBox->addItem(bundleControl->displayProperties()->displayName(), v);
+    }
+
+    // initialize default output control network filename
+    FileName fname = m_ui->controlNetworkComboBox->currentText();
+    m_ui->outputControlNet->setText(fname.baseName() + "-out.net");
 
     QList<BundleSolutionInfo *> bundleSolutionInfo = m_project->bundleSolutionInfo();
     if (useLastSettings && bundleSolutionInfo.size() > 0) {
@@ -67,7 +80,7 @@ namespace Isis {
      // Retrieve the control net name used in the last bundle adjustment.
      // Note that this returns a fully specified path and filename, while the cnet combo box
      // only stores file names.
-     selectControl(bundleSolutionInfo.last()->controlNetworkFileName());
+     selectControl(bundleSolutionInfo.last()->inputControlNetFileName());
      fillFromSettings(lastBundleSettings);
     }
 
@@ -86,8 +99,6 @@ namespace Isis {
 
     m_ui->pointingAprioriSigmaTable->setHorizontalHeaderLabels(tableHeaders);
 
-
-
     // initializations for target body tab
 
     // fill target combo box from project
@@ -679,6 +690,11 @@ namespace Isis {
   }
 
 
+  QString JigsawSetupDialog::outputControlName() {
+    return QString(m_ui->outputControlNet->text());
+  }
+
+
   void JigsawSetupDialog::makeReadOnly() {
     m_ui->controlNetworkComboBox->setEnabled(false);
     m_ui->observationModeCheckBox->setEnabled(false);
@@ -1100,4 +1116,9 @@ namespace Isis {
   void JigsawSetupDialog::hideTargetParametersGroupBox() {
     m_ui->targetParametersGroupBox->setEnabled(false);
   }
+
+  void Isis::JigsawSetupDialog::on_controlNetworkComboBox_currentTextChanged(const QString &arg1) {
+    FileName fname = arg1;
+    m_ui->outputControlNet->setText(fname.baseName() + "-out.net");
+  }
 }
diff --git a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.h b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.h
index ce80da8d40d0d4457eb4a445a9171921c19f221b..7cc6e2e5409562845c158a5c02d9f8db11660af9 100644
--- a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.h
+++ b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.h
@@ -50,6 +50,13 @@ namespace Isis {
    *                           allows for proper restoring of user defined weightings.
    *   @history 2017-08-14 Summer Stapleton - Updated icons/images to properly licensed or open 
    *                           source images. Fixes #5105.
+   *   @history 2018-03-19 Ken Edmundson - Added bundle output control network file name. Added
+   *                           method on_controlNetworkComboBox_currentTextChanged to update the
+   *                           output control network filename when the input control network
+   *                           selected filename changes. E.g. if input control net name is
+   *                           fred.net, the output filename QLineEdit is automatically changed to
+   *                           fred-out.net. The user can always manually change the output control
+   *                           net name to anything they choose.
    */
 
   class JigsawSetupDialog : public QDialog {
@@ -63,9 +70,10 @@ namespace Isis {
                                QWidget *parent = 0);
     ~JigsawSetupDialog();
 
-    Control *selectedControl();// TODO: return const references ???
-    QString selectedControlName();// TODO: return const references ???
-    BundleSettingsQsp bundleSettings();// TODO: return const references ???
+    Control *selectedControl();                                 // TODO: return const references ???
+    QString selectedControlName();                              // TODO: return const references ???
+    QString outputControlName();                                // TODO: return const references ???
+    BundleSettingsQsp bundleSettings();                         // TODO: return const references ???
 
     void loadSettings(const BundleSettingsQsp settings);
     void selectControl(const QString &controlName);
@@ -78,6 +86,7 @@ namespace Isis {
     // general tab
     void on_positionComboBox_currentIndexChanged(int index);
     void on_pointingComboBox_currentIndexChanged(int index);
+    void on_controlNetworkComboBox_currentTextChanged(const QString &arg1);
 
     // maximum liklihood tab
     void on_maximumLikelihoodModel1ComboBox_currentIndexChanged(int index);
diff --git a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.ui b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.ui
index ff00971a6f9a3ea9da5a95e695ae532880a26893..3fb99daa8bc32f6e9c8254a52c1872de1ae86963 100644
--- a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.ui
+++ b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.ui
@@ -43,7 +43,7 @@
           </sizepolicy>
          </property>
          <property name="currentIndex">
-          <number>5</number>
+          <number>3</number>
          </property>
          <widget class="QWidget" name="generalSettingsTab">
           <attribute name="title">
@@ -94,8 +94,13 @@
                  <property name="enabled">
                   <bool>false</bool>
                  </property>
+                 <property name="font">
+                  <font>
+                   <italic>false</italic>
+                  </font>
+                 </property>
                  <property name="text">
-                  <string>Multiplier</string>
+                  <string>&amp;Multiplier</string>
                  </property>
                  <property name="alignment">
                   <set>Qt::AlignCenter</set>
@@ -172,7 +177,7 @@
                <item row="11" column="0">
                 <widget class="QLabel" name="sigma0ThresholdLabel">
                  <property name="text">
-                  <string>Sigma0Threshold</string>
+                  <string>Sigma&amp;0 Threshold</string>
                  </property>
                  <property name="buddy">
                   <cstring>sigma0ThresholdLineEdit</cstring>
@@ -182,7 +187,7 @@
                <item row="12" column="0">
                 <widget class="QLabel" name="maximumIterationsLabel">
                  <property name="text">
-                  <string>Maximum Iterations</string>
+                  <string>Ma&amp;ximum Iterations</string>
                  </property>
                  <property name="buddy">
                   <cstring>maximumIterationsLineEdit</cstring>
@@ -264,64 +269,39 @@
              </item>
              <item>
               <layout class="QGridLayout" name="controlNetPositionAndPointingOptionsGridLayout">
-               <item row="12" column="0" colspan="2">
-                <widget class="QCheckBox" name="fitOverPointingCheckBox">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
-                   <horstretch>0</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>269</width>
-                   <height>0</height>
-                  </size>
-                 </property>
-                 <property name="text">
-                  <string>Fit Polynomial over Existing Pointing</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="6" column="0">
-                <widget class="QLabel" name="spkDegreeLabel">
+               <item row="10" column="0">
+                <widget class="QLabel" name="spkSolveDegreeLabel">
                  <property name="enabled">
                   <bool>true</bool>
                  </property>
                  <property name="text">
-                  <string>SPKDegree</string>
+                  <string>SPKSolveDegree</string>
                  </property>
                  <property name="buddy">
-                  <cstring>spkDegreeSpinBox</cstring>
+                  <cstring>spkSolveDegreeSpinBox</cstring>
                  </property>
                 </widget>
                </item>
-               <item row="9" column="0" colspan="2">
-                <widget class="QLabel" name="pointingSolveOptionsLabel">
+               <item row="9" column="1">
+                <widget class="QSpinBox" name="spkDegreeSpinBox">
+                 <property name="enabled">
+                  <bool>true</bool>
+                 </property>
                  <property name="sizePolicy">
-                  <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
                    <horstretch>0</horstretch>
                    <verstretch>0</verstretch>
                   </sizepolicy>
                  </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>269</width>
-                   <height>0</height>
-                  </size>
-                 </property>
-                 <property name="text">
-                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Instrument Pointing Solve Options&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                 </property>
-                 <property name="scaledContents">
-                  <bool>false</bool>
+                 <property name="minimum">
+                  <number>1</number>
                  </property>
-                 <property name="alignment">
-                  <set>Qt::AlignCenter</set>
+                 <property name="value">
+                  <number>2</number>
                  </property>
                 </widget>
                </item>
-               <item row="5" column="0" colspan="2">
+               <item row="8" column="0" colspan="2">
                 <widget class="QCheckBox" name="hermiteSplineCheckBox">
                  <property name="enabled">
                   <bool>false</bool>
@@ -337,56 +317,107 @@
                  </property>
                 </widget>
                </item>
-               <item row="7" column="0">
-                <widget class="QLabel" name="spkSolveDegreeLabel">
-                 <property name="enabled">
-                  <bool>true</bool>
+               <item row="5" column="0" colspan="2">
+                <spacer name="controlNetworkToSpkOptionsVerticalSpacer">
+                 <property name="orientation">
+                  <enum>Qt::Vertical</enum>
                  </property>
-                 <property name="text">
-                  <string>SPKSolveDegree</string>
+                 <property name="sizeType">
+                  <enum>QSizePolicy::Preferred</enum>
                  </property>
-                 <property name="buddy">
-                  <cstring>spkSolveDegreeSpinBox</cstring>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>20</width>
+                   <height>40</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+               <item row="15" column="0" colspan="2">
+                <widget class="QCheckBox" name="fitOverPointingCheckBox">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>269</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="text">
+                  <string>Fit Polynomial over Existing Pointing</string>
                  </property>
                 </widget>
                </item>
-               <item row="6" column="1">
-                <widget class="QSpinBox" name="spkDegreeSpinBox">
-                 <property name="enabled">
-                  <bool>true</bool>
+               <item row="3" column="0">
+                <widget class="QLabel" name="outputControlNet_2">
+                 <property name="text">
+                  <string>Output</string>
                  </property>
+                </widget>
+               </item>
+               <item row="13" column="0" colspan="2">
+                <widget class="QComboBox" name="pointingComboBox">
                  <property name="sizePolicy">
                   <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
                    <horstretch>0</horstretch>
                    <verstretch>0</verstretch>
                   </sizepolicy>
                  </property>
-                 <property name="minimum">
-                  <number>1</number>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Instrument Pointing Options&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
                  </property>
-                 <property name="value">
-                  <number>2</number>
+                 <property name="currentIndex">
+                  <number>0</number>
+                 </property>
+                 <property name="frame">
+                  <bool>true</bool>
                  </property>
+                 <item>
+                  <property name="text">
+                   <string>ANGLES</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>NONE</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>VELOCITIES</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>ACCELERATIONS</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>ALL</string>
+                  </property>
+                 </item>
                 </widget>
                </item>
-               <item row="8" column="0" colspan="2">
-                <spacer name="spkToCkOptionsverticalSpacer">
-                 <property name="orientation">
-                  <enum>Qt::Vertical</enum>
+               <item row="9" column="0">
+                <widget class="QLabel" name="spkDegreeLabel">
+                 <property name="enabled">
+                  <bool>true</bool>
                  </property>
-                 <property name="sizeType">
-                  <enum>QSizePolicy::Preferred</enum>
+                 <property name="text">
+                  <string>SPKDegree</string>
                  </property>
-                 <property name="sizeHint" stdset="0">
-                  <size>
-                   <width>20</width>
-                   <height>40</height>
-                  </size>
+                 <property name="buddy">
+                  <cstring>spkDegreeSpinBox</cstring>
                  </property>
-                </spacer>
+                </widget>
                </item>
-               <item row="1" column="0" colspan="2">
-                <widget class="QComboBox" name="controlNetworkComboBox">
+               <item row="3" column="1">
+                <widget class="QLineEdit" name="outputControlNet">
                  <property name="sizePolicy">
                   <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
                    <horstretch>0</horstretch>
@@ -395,63 +426,79 @@
                  </property>
                 </widget>
                </item>
-               <item row="3" column="0" colspan="2">
-                <widget class="QLabel" name="positionSolveOptionsLabel">
+               <item row="1" column="0">
+                <widget class="QLabel" name="inputControlNet">
                  <property name="text">
-                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Instrument Solve Options&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                 </property>
-                 <property name="scaledContents">
-                  <bool>false</bool>
+                  <string>Input</string>
                  </property>
                  <property name="alignment">
-                  <set>Qt::AlignCenter</set>
+                  <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
                  </property>
                 </widget>
                </item>
-               <item row="0" column="0" colspan="2">
-                <widget class="QLabel" name="controlNetworkLabel">
+               <item row="6" column="0" colspan="2">
+                <widget class="QLabel" name="positionSolveOptionsLabel">
                  <property name="text">
-                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Control Network&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Instrument Solve Options&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="scaledContents">
+                  <bool>false</bool>
                  </property>
                  <property name="alignment">
                   <set>Qt::AlignCenter</set>
                  </property>
                 </widget>
                </item>
-               <item row="14" column="1">
-                <widget class="QSpinBox" name="ckSolveDegreeSpinBox">
-                 <property name="enabled">
-                  <bool>true</bool>
-                 </property>
+               <item row="7" column="0" colspan="2">
+                <widget class="QComboBox" name="positionComboBox">
                  <property name="sizePolicy">
                   <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
                    <horstretch>0</horstretch>
                    <verstretch>0</verstretch>
                   </sizepolicy>
                  </property>
-                 <property name="minimum">
-                  <number>1</number>
-                 </property>
-                 <property name="value">
-                  <number>2</number>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Instrument Solve Options&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
                  </property>
+                 <item>
+                  <property name="text">
+                   <string>NONE</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>POSITIONS</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>VELOCITIES</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>ACCELERATIONS</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>ALL</string>
+                  </property>
+                 </item>
                 </widget>
                </item>
-               <item row="13" column="0">
-                <widget class="QLabel" name="ckDegreeLabel">
-                 <property name="enabled">
-                  <bool>true</bool>
-                 </property>
+               <item row="0" column="0" colspan="2">
+                <widget class="QLabel" name="controlNetworkHeader">
                  <property name="text">
-                  <string>CKDegree</string>
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Control Networks&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
                  </property>
-                 <property name="buddy">
-                  <cstring>ckDegreeSpinBox</cstring>
+                 <property name="alignment">
+                  <set>Qt::AlignCenter</set>
                  </property>
                 </widget>
                </item>
-               <item row="2" column="0" colspan="2">
-                <spacer name="controlNetworkToSpkOptionsVerticalSpacer">
+               <item row="11" column="0" colspan="2">
+                <spacer name="spkToCkOptionsverticalSpacer">
                  <property name="orientation">
                   <enum>Qt::Vertical</enum>
                  </property>
@@ -466,39 +513,74 @@
                  </property>
                 </spacer>
                </item>
-               <item row="7" column="1">
-                <widget class="QSpinBox" name="spkSolveDegreeSpinBox">
+               <item row="17" column="0">
+                <widget class="QLabel" name="ckSolveDegreeLabel">
                  <property name="enabled">
                   <bool>true</bool>
                  </property>
+                 <property name="text">
+                  <string>C&amp;KSolveDegree</string>
+                 </property>
+                 <property name="buddy">
+                  <cstring>ckSolveDegreeSpinBox</cstring>
+                 </property>
+                </widget>
+               </item>
+               <item row="16" column="0">
+                <widget class="QLabel" name="ckDegreeLabel">
+                 <property name="enabled">
+                  <bool>true</bool>
+                 </property>
+                 <property name="text">
+                  <string>CKDegree</string>
+                 </property>
+                 <property name="buddy">
+                  <cstring>ckDegreeSpinBox</cstring>
+                 </property>
+                </widget>
+               </item>
+               <item row="14" column="0" colspan="2">
+                <widget class="QCheckBox" name="twistCheckBox">
                  <property name="sizePolicy">
-                  <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
                    <horstretch>0</horstretch>
                    <verstretch>0</verstretch>
                   </sizepolicy>
                  </property>
-                 <property name="minimum">
-                  <number>1</number>
+                 <property name="text">
+                  <string>Twist</string>
                  </property>
-                 <property name="value">
-                  <number>2</number>
+                 <property name="checked">
+                  <bool>true</bool>
                  </property>
                 </widget>
                </item>
-               <item row="14" column="0">
-                <widget class="QLabel" name="ckSolveDegreeLabel">
-                 <property name="enabled">
-                  <bool>true</bool>
+               <item row="12" column="0" colspan="2">
+                <widget class="QLabel" name="pointingSolveOptionsLabel">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>269</width>
+                   <height>0</height>
+                  </size>
                  </property>
                  <property name="text">
-                  <string>CKSolveDegree</string>
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Instrument Pointing Solve Options&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
                  </property>
-                 <property name="buddy">
-                  <cstring>ckSolveDegreeSpinBox</cstring>
+                 <property name="scaledContents">
+                  <bool>false</bool>
+                 </property>
+                 <property name="alignment">
+                  <set>Qt::AlignCenter</set>
                  </property>
                 </widget>
                </item>
-               <item row="13" column="1">
+               <item row="16" column="1">
                 <widget class="QSpinBox" name="ckDegreeSpinBox">
                  <property name="enabled">
                   <bool>true</bool>
@@ -517,102 +599,52 @@
                  </property>
                 </widget>
                </item>
-               <item row="4" column="0" colspan="2">
-                <widget class="QComboBox" name="positionComboBox">
+               <item row="10" column="1">
+                <widget class="QSpinBox" name="spkSolveDegreeSpinBox">
+                 <property name="enabled">
+                  <bool>true</bool>
+                 </property>
                  <property name="sizePolicy">
                   <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
                    <horstretch>0</horstretch>
                    <verstretch>0</verstretch>
                   </sizepolicy>
                  </property>
-                 <property name="toolTip">
-                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Instrument Solve Options&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 <property name="minimum">
+                  <number>1</number>
+                 </property>
+                 <property name="value">
+                  <number>2</number>
                  </property>
-                 <item>
-                  <property name="text">
-                   <string>NONE</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>POSITIONS</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>VELOCITIES</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>ACCELERATIONS</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>ALL</string>
-                  </property>
-                 </item>
                 </widget>
                </item>
-               <item row="10" column="0" colspan="2">
-                <widget class="QComboBox" name="pointingComboBox">
+               <item row="17" column="1">
+                <widget class="QSpinBox" name="ckSolveDegreeSpinBox">
+                 <property name="enabled">
+                  <bool>true</bool>
+                 </property>
                  <property name="sizePolicy">
                   <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
                    <horstretch>0</horstretch>
                    <verstretch>0</verstretch>
                   </sizepolicy>
                  </property>
-                 <property name="toolTip">
-                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Instrument Pointing Options&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                 </property>
-                 <property name="currentIndex">
-                  <number>0</number>
+                 <property name="minimum">
+                  <number>1</number>
                  </property>
-                 <property name="frame">
-                  <bool>true</bool>
+                 <property name="value">
+                  <number>2</number>
                  </property>
-                 <item>
-                  <property name="text">
-                   <string>ANGLES</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>NONE</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>VELOCITIES</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>ACCELERATIONS</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>ALL</string>
-                  </property>
-                 </item>
                 </widget>
                </item>
-               <item row="11" column="0" colspan="2">
-                <widget class="QCheckBox" name="twistCheckBox">
+               <item row="1" column="1">
+                <widget class="QComboBox" name="controlNetworkComboBox">
                  <property name="sizePolicy">
-                  <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
                    <horstretch>0</horstretch>
                    <verstretch>0</verstretch>
                   </sizepolicy>
                  </property>
-                 <property name="text">
-                  <string>Twist</string>
-                 </property>
-                 <property name="checked">
-                  <bool>true</bool>
-                 </property>
                 </widget>
                </item>
               </layout>
@@ -644,7 +676,7 @@
                  <bool>true</bool>
                 </property>
                 <property name="text">
-                 <string>SPK Initialization Polynomial Degree</string>
+                 <string>SPK Initiali&amp;zation Polynomial Degree</string>
                 </property>
                 <property name="wordWrap">
                  <bool>true</bool>
@@ -785,7 +817,7 @@
                  <bool>true</bool>
                 </property>
                 <property name="text">
-                 <string>CK Initialization Polynomial Degree</string>
+                 <string>C&amp;K Initialization Polynomial Degree</string>
                 </property>
                 <property name="wordWrap">
                  <bool>true</bool>
@@ -839,7 +871,7 @@
                  <bool>true</bool>
                 </property>
                 <property name="text">
-                 <string>CK Solve Polynomial Degree</string>
+                 <string>CK Solve Polyno&amp;mial Degree</string>
                 </property>
                 <property name="wordWrap">
                  <bool>true</bool>
@@ -959,7 +991,7 @@
                 </size>
                </property>
                <property name="text">
-                <string>meters</string>
+                <string>&amp;meters</string>
                </property>
                <property name="buddy">
                 <cstring>pointLatitudeSigmaLineEdit</cstring>
@@ -1365,7 +1397,7 @@
                 </size>
                </property>
                <property name="text">
-                <string>meters per second squared</string>
+                <string>meters per second s&amp;quared</string>
                </property>
                <property name="buddy">
                 <cstring>accelerationSigmaLineEdit</cstring>
@@ -1404,7 +1436,7 @@
          </widget>
          <widget class="QWidget" name="maximumLikelihoodTab">
           <attribute name="title">
-           <string>Maximum Liklihood</string>
+           <string>Maximum Likelihood</string>
           </attribute>
           <layout class="QGridLayout" name="gridLayout_4">
            <item row="0" column="0">
@@ -1456,7 +1488,7 @@
                 </size>
                </property>
                <property name="text">
-                <string>Maximum Likelihood Estimator Model 1</string>
+                <string>&amp;Maximum Likelihood Estimator Model 1</string>
                </property>
                <property name="buddy">
                 <cstring>maximumLikelihoodModel1ComboBox</cstring>
@@ -1481,7 +1513,7 @@
                 </size>
                </property>
                <property name="text">
-                <string>Maximum Likelihood Estimator Model 3</string>
+                <string>Ma&amp;ximum Likelihood Estimator Model 3</string>
                </property>
                <property name="buddy">
                 <cstring>maximumLikelihoodModel3ComboBox</cstring>
@@ -1531,7 +1563,7 @@
                 </size>
                </property>
                <property name="text">
-                <string>Maximum Likelihood Estimator Model 2</string>
+                <string>Maximum &amp;Likelihood Estimator Model 2</string>
                </property>
                <property name="buddy">
                 <cstring>maximumLikelihoodModel2ComboBox</cstring>
@@ -1544,7 +1576,7 @@
                 <bool>false</bool>
                </property>
                <property name="text">
-                <string>Model 1 C Quantile</string>
+                <string>Model &amp;1 C Quantile</string>
                </property>
                <property name="buddy">
                 <cstring>maximumLikelihoodModel1QuantileLineEdit</cstring>
@@ -1573,7 +1605,7 @@
                 <bool>false</bool>
                </property>
                <property name="text">
-                <string>Model 2 C Quantile</string>
+                <string>Model &amp;2 C Quantile</string>
                </property>
                <property name="buddy">
                 <cstring>maximumLikelihoodModel2QuantileLineEdit</cstring>
@@ -1678,7 +1710,7 @@
                 <bool>false</bool>
                </property>
                <property name="text">
-                <string>Model 3 C Quantile</string>
+                <string>Model &amp;3 C Quantile</string>
                </property>
                <property name="buddy">
                 <cstring>maximumLikelihoodModel3QuantileLineEdit</cstring>
@@ -2296,7 +2328,7 @@
                    </font>
                   </property>
                   <property name="text">
-                   <string>mean radius</string>
+                   <string>&amp;mean radius</string>
                   </property>
                   <attribute name="buttonGroup">
                    <string notr="true">radiiButtonGroup</string>
@@ -2460,7 +2492,7 @@
                    </font>
                   </property>
                   <property name="text">
-                   <string>triaxial radii</string>
+                   <string>tria&amp;xial radii</string>
                   </property>
                   <attribute name="buttonGroup">
                    <string notr="true">radiiButtonGroup</string>
diff --git a/isis/src/qisis/objs/MosaicSceneWidget/MosaicSceneWidget.cpp b/isis/src/qisis/objs/MosaicSceneWidget/MosaicSceneWidget.cpp
index ccbae1ecd0d5d7254ffa19c802d89e9b463f6518..93322567126eec550eebde003b88a338310fdddd 100644
--- a/isis/src/qisis/objs/MosaicSceneWidget/MosaicSceneWidget.cpp
+++ b/isis/src/qisis/objs/MosaicSceneWidget/MosaicSceneWidget.cpp
@@ -623,9 +623,9 @@ namespace Isis {
   }
 
 
-  void MosaicSceneWidget::save(QXmlStreamWriter &stream, Project *, FileName) const {
+  void MosaicSceneWidget::save(QXmlStreamWriter &stream, Project *, FileName ) const {
     if (m_projection) {
-      stream.writeStartElement("footprint2DView");
+      stream.writeStartElement("mosaicScene");
 
       stream.writeStartElement("projection");
       PvlGroup mapping = m_projection->Mapping();
diff --git a/isis/src/qisis/objs/MosaicSceneWidget/MosaicSceneWidget.h b/isis/src/qisis/objs/MosaicSceneWidget/MosaicSceneWidget.h
index 5c95ec06c254560144646f78221f60bd7d754546..8c314e31009bcb57b0beb8252b58f7a913f618bd 100644
--- a/isis/src/qisis/objs/MosaicSceneWidget/MosaicSceneWidget.h
+++ b/isis/src/qisis/objs/MosaicSceneWidget/MosaicSceneWidget.h
@@ -143,6 +143,9 @@ namespace Isis {
    *                           was deleted or added to the control net.  Renamed deleteControlPoint
    *                           signal to controlPointDeleted.  Removed some unneeded connections.
    *                           Fixes #5007, #5008.
+   *   @history 2018-05-14 Tracie Sucharski - Change the xml tag from footprint2DView to
+   *                           mosaicScene. Reference #5422.
+   *  
    */
   class MosaicSceneWidget : public QWidget {
       Q_OBJECT
diff --git a/isis/src/qisis/objs/NewControlPointDialog/NewControlPointDialog.cpp b/isis/src/qisis/objs/NewControlPointDialog/NewControlPointDialog.cpp
index 1d288c8cac336737a51856f9d5fa6d00e9cfb9c4..fe9d667744bc84db07156373a9c6a30c966b7a82 100644
--- a/isis/src/qisis/objs/NewControlPointDialog/NewControlPointDialog.cpp
+++ b/isis/src/qisis/objs/NewControlPointDialog/NewControlPointDialog.cpp
@@ -20,9 +20,15 @@
 
 namespace Isis {
   /**
-   * NewControlPointDialog constructor
-   * @param parent The parent widget for the
-   *               cube points filter
+   * @description Create dialog for creating a new Control Point
+   *  
+   * @param controlNet               The control net the new control point will be contained in 
+   * @param serialNumberList         The serial number list corresponding to the controlNet 
+   * @param defaultPointId           The default pointID, usually empty string 
+   * @param parent                   Parent widget 
+   * @param pointType                Show the Point Type combo box, default = false 
+   * @param groundSource             Show the Ground Source list, default = false 
+   * @param subpixelRegisterMeasures Show the check box for sub-pixel registration option, default = false
    *
    * @internal
    *   @history 2008-11-26 Jeannie Walldren - Set lastPointIdValue
@@ -68,11 +74,12 @@ namespace Isis {
         m_pointTypeCombo->insertItem(i, ControlPoint::PointTypeToString(
                                      (ControlPoint::PointType) i));
       }
-      m_pointTypeCombo->setCurrentIndex(2);
-      QLabel *pointTypeLabel = new QLabel("PointType:");
+      m_pointTypeCombo->setCurrentText("Free");
+      QLabel *pointTypeLabel = new QLabel("Point Type:");
       pointTypeLayout->addWidget(pointTypeLabel);
       pointTypeLayout->addWidget(m_pointTypeCombo);
-      connect(m_pointTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(pointTypeChanged(int)));
+      connect(m_pointTypeCombo, SIGNAL(currentIndexChanged(QString)),
+              this, SLOT(pointTypeChanged(QString)));
     }
 
 
@@ -99,6 +106,7 @@ namespace Isis {
 
     //  Create OK & Cancel buttons
     m_okButton = new QPushButton("OK");
+
     //  If the last point id used was never saved to network, do not set ok
     //  button to faslse
     enableOkButton("");
@@ -147,7 +155,14 @@ namespace Isis {
 
 
   int NewControlPointDialog::pointType() const {
-    return m_pointTypeCombo->currentIndex();
+    int result = ControlPoint::Free;
+    if (m_pointTypeCombo->currentText() == "Constrained") {
+      result = ControlPoint::Constrained;
+    }
+    if (m_pointTypeCombo->currentText() == "Fixed") {
+      result = ControlPoint::Fixed;
+    }
+    return result;
   }
 
 
@@ -172,19 +187,33 @@ namespace Isis {
   }
 
 
-  void NewControlPointDialog::pointTypeChanged(int pointType) {
-    if (pointType == ControlPoint::Constrained || pointType == ControlPoint::Fixed) {
+  void NewControlPointDialog::pointTypeChanged(QString pointType) {
+    if (pointType == "Fixed" || pointType == "Constrained") {
       m_groundSourceCombo->setVisible(true);
     }
   }
 
 
   void NewControlPointDialog::setGroundSource(QStringList groundFiles, int numberShapesWithPoint) {
-    m_groundSourceCombo->addItems(groundFiles);
-    for (int i = 0; i < numberShapesWithPoint; i++) {
-      m_groundSourceCombo->setItemData(i, QColor(Qt::red), Qt::ForegroundRole);
+    //  If groundFiles not empty, add to the list widget for selection
+    if (groundFiles.count() != 0) {
+      m_groundSourceCombo->addItems(groundFiles); 
+      for (int i = 0; i < numberShapesWithPoint; i++) {
+        m_groundSourceCombo->setItemData(i, QColor(Qt::red), Qt::ForegroundRole);
+      }
+      m_groundSourceCombo->insertSeparator(numberShapesWithPoint);
+    }
+    // If groundFiles is empty, remove option to change point type to Constrained or Fixed, add a
+    // tooltip to give user hint as to why they don't have option to change point type and set
+    // default point type back to "Free".
+    else {
+      m_pointTypeCombo->setToolTip("The Point Type cannot be changed to \"Fixed\" or "
+                                   "\"Constrained\", because there are no shapes imported into "
+                                   "your project.");
+      m_pointTypeCombo->removeItem(m_pointTypeCombo->findText("Constrained"));
+      m_pointTypeCombo->removeItem(m_pointTypeCombo->findText("Fixed"));
+      m_pointTypeCombo->setCurrentText("Free");
     }
-    m_groundSourceCombo->insertSeparator(numberShapesWithPoint);
   }
 
 
@@ -227,7 +256,15 @@ namespace Isis {
    *            to the ptIdValue
    */
   void NewControlPointDialog::enableOkButton(const QString &) {
-    m_okButton->setEnabled(!m_ptIdEdit->text().isEmpty() &&
-                           !m_controlNet->ContainsPoint(m_ptIdEdit->text()));
+    bool enable = !m_ptIdEdit->text().isEmpty() &&
+                  !m_controlNet->ContainsPoint(m_ptIdEdit->text());
+    m_okButton->setEnabled(enable);
+    if (enable) {
+      m_okButton->setToolTip("");
+    }
+    else {
+      m_okButton->setToolTip("Cannot create point because Point Id is either empty or the active "
+                             "control net already contains a control point with this point Id.");
+    }
   }
 }
diff --git a/isis/src/qisis/objs/NewControlPointDialog/NewControlPointDialog.h b/isis/src/qisis/objs/NewControlPointDialog/NewControlPointDialog.h
index d2a287b693f7fc5b93d027e6f104681d3120ea46..77af7f7a8123c693553afa5df9b3304e6d6e53db 100644
--- a/isis/src/qisis/objs/NewControlPointDialog/NewControlPointDialog.h
+++ b/isis/src/qisis/objs/NewControlPointDialog/NewControlPointDialog.h
@@ -33,8 +33,16 @@ namespace Isis {
    *   @history 2016-10-18 Tracie Sucharski - Added method to return value of the
    *                          subpixelRegister radio button.  If set, all measures in the control
    *                          point created will be subpixel registered.
-   *   @history 2017-07-04 Christopher Combs - Added bools to toggle on specific elements of the
-   *                          dialog to remove similar classes like QnetNewPointDialog. Fixes #4383.
+   *   @history 2017-07-04 Christopher Combs - Combined functionality of dialogs from qnet,
+   *                          qview and ipce applications by adding bools to toggle on specific
+   *                          elements of the dialog to remove similar classes like
+   *                          QnetNewPointDialog. Fixes #4383.
+   *   @history 2018-05-02 Tracie Sucharski - If no shapes available remove option to change point
+   *                          type to "Constrained" or "Fixed". Because pointType combo dependent on
+   *                          having all 3 types to use ControlPoint's enum, change comparisons to
+   *                          check text instead of int values. Add tool tip explaining why point
+   *                          type cannot be changed.  Set tool tip on Ok button explaining why it
+   *                          is not enabled. Fixes #5087.
    */
   class NewControlPointDialog : public QDialog {
 
@@ -58,7 +66,7 @@ namespace Isis {
       bool subpixelRegisterPoint();
 
     private slots:
-      void pointTypeChanged(int pointType);
+      void pointTypeChanged(QString pointType);
       void enableOkButton(const QString &text);
 
     private:
diff --git a/isis/src/qisis/objs/Project/Project.cpp b/isis/src/qisis/objs/Project/Project.cpp
index d429037a86e051d48bfc9c103edf8b56fc9c19e1..b3f45a0882a13498fdfdb212e7ff6d75df8f58bb 100644
--- a/isis/src/qisis/objs/Project/Project.cpp
+++ b/isis/src/qisis/objs/Project/Project.cpp
@@ -66,6 +66,8 @@
 #include "ProjectItem.h"
 #include "ProjectItemModel.h"
 #include "SerialNumberList.h"
+#include "SetActiveControlWorkOrder.h"
+#include "SetActiveImageListWorkOrder.h"
 #include "Shape.h"
 #include "ShapeList.h"
 #include "ShapeReader.h"
@@ -109,7 +111,6 @@ namespace Isis {
     m_activeControl = NULL;
     m_activeImageList = NULL;
 
-
     m_numImagesCurrentlyReading = 0;
 
     m_mutex = NULL;
@@ -129,7 +130,6 @@ namespace Isis {
 
     m_name = "Project";
 
-
     // Look for old projects
     QDir tempDir = QDir::temp();
     QStringList nameFilters;
@@ -540,7 +540,7 @@ namespace Isis {
             tempDir.removeRecursively();
           }
         }
-
+        
         projectXml.close();
       }
 
@@ -569,7 +569,7 @@ namespace Isis {
     m_guiCameras->clear();
     m_bundleSolutionInfo->clear();
     m_workOrderHistory->clear();
-
+    
     directory()->clean();
     setClean(true);
   }
@@ -1100,13 +1100,18 @@ namespace Isis {
 
   /**
    * Loads bundle solution info into project
+   *
    * @param BundleSolutionInfo
    */
   void Project::loadBundleSolutionInfo(BundleSolutionInfo *bundleSolutionInfo) {
     m_bundleSolutionInfo->append(bundleSolutionInfo);
 
+    // add BundleSolutionInfo to project's m_idToBundleSolutionInfoMap
     (*m_idToBundleSolutionInfoMap)[bundleSolutionInfo->id()] = bundleSolutionInfo;
 
+    // add BundleSolutionInfo's control to project's m_idToControlMap
+    (*m_idToControlMap)[bundleSolutionInfo->control()->id()] = bundleSolutionInfo->control();
+
     emit bundleSolutionInfoAdded(bundleSolutionInfo);
   }
 
@@ -1570,6 +1575,7 @@ namespace Isis {
   /**
    * Change the project's name (GUI only, doesn't affect location on disk).
    */
+
   void Project::setName(QString newName) {
     m_name = newName;
     emit nameChanged(m_name);
@@ -1697,16 +1703,46 @@ namespace Isis {
    *                           being chosen Fixes #4969
    *  @history 2017-08-02 Cole Neubauer - Added functionality to switch between active controls
    *                           Fixes #4567
+   *  @history 2018-03-30 Tracie Sucharski - If current activeControl has been modified, prompt for
+   *                           saving. Emit signal to discardActiveControlEdits.
    *
    */
   void Project::setActiveControl(QString displayName) {
-    Control *previousControl = m_activeControl;
+    Control *previousControl = m_activeControl; 
     if (m_activeControl) {
+
+      // If the current active control has been modified, ask user if they want to save or discard
+      // changes.
+      if (m_activeControl->isModified()) {
+        QMessageBox msgBox;
+        msgBox.setText("Save current active control");
+        msgBox.setInformativeText("The current active control has been modified.  Do you want "
+                                  "to save before setting a new active control?");
+        msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
+        msgBox.setDefaultButton(QMessageBox::Save);
+        int ret = msgBox.exec();
+        switch (ret) {
+          // Save current active control
+          case QMessageBox::Save:
+            m_activeControl->write();
+            break;
+          // Discard any changes made to cnet
+          case QMessageBox::Discard:
+            emit discardActiveControlEdits();
+            break;
+          // Cancel operation
+          case QMessageBox::Cancel:
+            return;
+        }
+      }
       emit activeControlSet(false);
       ProjectItem *item = directory()->model()->findItemData(m_activeControl->
                           displayProperties()->displayName(), Qt::DisplayRole);
       item->setTextColor(Qt::black);
-      m_activeControl->closeControlNet();
+      // Make sure active not used in a CnetEditorWidget before closing
+      if (!directory()->controlUsedInCnetEditorWidget(m_activeControl)) {
+        m_activeControl->closeControlNet();
+      }
     }
 
     ProjectItem *item = directory()->model()->findItemData(displayName, Qt::DisplayRole);
@@ -1714,23 +1750,23 @@ namespace Isis {
       m_activeControl = item->control();
 
       try {
-        activeControl()->controlNet()->SetImages(*(activeImageList()->serialNumberList()));
-        item->setTextColor(Qt::darkGreen);
+          m_activeControl->controlNet()->SetImages(*(activeImageList()->serialNumberList()));
+          item->setTextColor(Qt::darkGreen);
       }
       catch(IException e){
-        if (previousControl) {
-          m_activeControl = previousControl;
-          item = directory()->model()->findItemData(m_activeControl->
-                              displayProperties()->displayName(), Qt::DisplayRole);
-          item->setTextColor(Qt::darkGreen);
-          activeControl()->controlNet()->SetImages(*(activeImageList()->serialNumberList()));
-        }
-        else {
-          m_activeControl = NULL;
+          if (previousControl) {
+            m_activeControl = previousControl;
+            item = directory()->model()->findItemData(m_activeControl->
+                                displayProperties()->displayName(), Qt::DisplayRole);
+            item->setTextColor(Qt::darkGreen);
+            m_activeControl->controlNet()->SetImages(*(activeImageList()->serialNumberList()));
+          }
+          else {
+            m_activeControl = NULL;
+          }
+          throw IException(e);
         }
-        throw IException(e);
       }
-    }
     emit activeControlSet(true);
   }
 
@@ -1738,9 +1774,12 @@ namespace Isis {
   /**
    * @brief Return the Active Control (control network)
    *
-   * Returns the active control (control network) for views which need to operate on
+   * @description Returns the active control (control network) for views which need to operate on
    * the same control, ie. Footprint2dView, CubeDnView, ControlPointEditView.
-   *
+   * IMPORTANT:  Returns NULL if no active Control. 
+   *  
+   * @return @b Control * Returns the active Control if set, otherwise returns NULL
+   *  
    * @internal
    *   @history 2016-06-23 Tracie Sucharski - Original version.
    *   @history 2017-05-17 Tracie Sucharski - If no active control set & there is only one control
@@ -1751,16 +1790,24 @@ namespace Isis {
    */
   Control *Project::activeControl() {
 
-    if (!m_activeControl && m_controls->count() == 1) {
-      if (m_controls->at(0)->count() == 1 && m_images->count() > 1) {
+    if (!m_activeControl && (m_controls->count() == 1 && m_controls->at(0)->count() ==1)) {
+      //  Can only set a default control if an active imageList exists or if a default can be set
+      if (activeImageList()) {
         QString controlName = m_controls->at(0)->at(0)->displayProperties()->displayName();
         setActiveControl(controlName);
       }
     }
+
     return m_activeControl;
   }
 
 
+  void Project::activeControlModified() {
+
+    m_activeControl->setModified(true);
+  }
+
+
   /**
    * @brief Set the Active ImageList from the displayName which is saved in project.xml
    *
@@ -1823,7 +1870,9 @@ namespace Isis {
    * @brief  Returns the active ImageList
    *
    * Returns the active ImageList for views which need to operate on the
-   * same list of images, ie. Footprint2dView, CubeDnView, ControlPointEditView.
+   * same list of images, ie. Footprint2dView, CubeDnView, ControlPointEditView. 
+   * IMPORTANT:  Returns NULL if active ImageList is not set and a default cannot be set if there 
+   *             are multiple image lists in the project. 
    *
    * @internal
    *   @history 2016-06-23 Tracie Sucharski - Original version.
@@ -1834,6 +1883,7 @@ namespace Isis {
 
     if (!m_activeImageList && m_images->count() == 1) {
       QString imageList = m_images->at(0)->name();
+      
       setActiveImageList(imageList);
     }
     return m_activeImageList;
@@ -2145,6 +2195,12 @@ namespace Isis {
         deleteAllProjectFiles();
         relocateProjectRoot(newDestination);
         m_isTemporaryProject = false;
+
+        // 2014-03-14 kle This is a lame kludge because we think that relocateProjectRoot is not
+        // working properly. For example, when we save a new project and try to view a control net
+        // the it thinks it's still in the /tmp area
+        // see ticket #5292
+        open(newDestination);
       }
       // Dialog was cancelled
       else {
@@ -2152,6 +2208,11 @@ namespace Isis {
       }
     }
     else {
+      //  Save current active control if it has been modified
+      if (activeControl() && activeControl()->isModified()) {
+        activeControl()->write();
+      }
+
       save(m_projectRoot->absolutePath(), false);
       // if (newDestination != )
     }
@@ -2282,7 +2343,7 @@ namespace Isis {
     //  TODO Set newpath member variable.  This is used for some of the data copy methods and is not
     //  the ideal way to handle this.  Maybe change the data copy methods to either take the new
     //  project root in addition to the data root or put the data root in the dataList (ImageList,
-    //  etc.).
+    //  etc.). If performing a "Save", m_newProjectRoot == m_projectRoot
     m_newProjectRoot = newPath.toString();
 
     //  For now set the member variable rather than calling setName which emits signal and updates
@@ -2794,7 +2855,7 @@ namespace Isis {
       else if (localName == "imageList") {
         m_imageLists.append(new ImageList(m_project, reader()));
       }
-      else if (localName == "shapeLists") {
+      else if (localName == "shapeList") {
         m_shapeLists.append(new ShapeList(m_project, reader()));
       }
       else if (localName == "templateList") {
@@ -2885,6 +2946,7 @@ namespace Isis {
     else if (localName == "results") {
       foreach (BundleSolutionInfo *bundleInfo, m_bundleSolutionInfos) {
         m_project->addBundleSolutionInfo(bundleInfo);
+
         // If BundleSolutionInfo contains adjusted images, add to the project id map.
         if (bundleInfo->adjustedImages().count()) {
           foreach (ImageList *adjustedImageList, bundleInfo->adjustedImages()) {
diff --git a/isis/src/qisis/objs/Project/Project.h b/isis/src/qisis/objs/Project/Project.h
index 367f7ba8c5d32e1b59e8b36786d417337fafa4f5..848fc6101296af47f31b18def7dc1b008135eced 100644
--- a/isis/src/qisis/objs/Project/Project.h
+++ b/isis/src/qisis/objs/Project/Project.h
@@ -150,15 +150,11 @@ namespace Isis {
    *                           imports, shape imports, and bundle solution info. Fixes #4855,
    *                           #4979, #4980.
    *   @history 2017-07-17 Cole Neubauer - Changed activeControl signal to emit a bool to be able
-   *
-   *   @history 2017-07-24 Cole Neubauer - Added isOpen, isClean, setClean, and clear functions to
-   *                           allow for opening of a new project. Fixes #4969.
-   *   @history 2017-07-17 Cole Neubauer - Changed activeControl signal to emit a bool to be able
    *                           to slot a setEnabled(bool) call to a QAction. This was necessary to
    *                           reenable the CNet Tool when a control net is made active.
    *                           Fixes #5046.
    *   @history 2017-07-24 Cole Neubauer - Added isOpen, isClean, setClean, and clear functions to
-   *                           allow for opening of a new project. Fixes #4969
+   *                           allow for opening of a new project. Fixes #4969.
    *   @history 2017-07-27 Cole Neubauer - Added check before emmiting workOrderStarting()
    *                           Fixes #4715.
    *   @history 2017-07-27 Cole Neubauer - Added a workordermutex to be used in workorder accessors
@@ -221,6 +217,43 @@ namespace Isis {
    *                           Corrected the setting of the project root when pening a project from
    *                           the command line. Removed m_projectPath, it is no longer needed since
    *                           m_projectRoot contains the correct path. References #5104.
+   *   @history 2018-03-14 Ken Edmundson - Modified save method to reopen project if we are saving
+   *                           a temporary project to ensure all project files are pointing to the
+   *                           correct directory. Note that this is NOT ideal, particularly it the
+   *                           project has many files.
+   *   @history 2018-03-14 Tracie Sucharski - Call the appropriate workorder from the methods
+   *                           activeControl and activeImageList when returning a default value.
+   *                           This ensures that all the proper error checking is handled and
+   *                           prevents duplicate code.
+   *   @history 2018-03-23 Ken Edmundson - Modified loadBundleSolutionInfo method to add the
+   *                           BundleSolutionInfo's output control id to the project member variable
+   *                           m_idToControlMap.
+   *   @history 2018-03-26 Tracie Sucharski - When setting a new active control do not close the old
+   *                           active control net if it is still being viewed in a CnetEditorWidget.
+   *                           References #5026.
+   *   @history 2018-03-27 Tracie Sucharski - Removed the calls to work orders from activeImageList
+   *                           and activeControl methods.  Additional errors checks needed for
+   *                           default values that are not in work orders.  Fixes #5256.
+   *   @history 2018-03-30 Tracie Sucharski - Added public slot, activeControlModified, which sets
+   *                           the modified state on the active Control. This was done, so that a
+   *                           Control knows if its control net has been modified. Also added
+   *                           signal, discardActiveControlEdits if user does not want to save
+   *                           edits.  This is needed for CnetEditorWidgets that are displaying
+   *                           the modified active control, it will effectively close that
+   *                           CnetEditorView and reload with the original control net.  It was
+   *                           done this way because there is no easy way to reload a control net in
+   *                           the CnetEditor widgets. When saving Project, if there is an active
+   *                           control and it has been modified, write active control to disk.
+   *                           Unfortunately this is done in 2 different places depending on whether
+   *                           a project "Save" or "Save As" is being done.  If "Save As", a
+   *                           modified active cnet is not written out to the original project only
+   *                           to the new project, so this had to be done in
+   *                           Control::copyToNewProjectRoot.  If simply saving current projct,
+   *                           the write is done here in the save method.
+   *  @history 2018-04-25 Tracie Sucharski - Fixed typo in XmlHandler::startElement reading
+   *                           imported shapes from a project which caused the shapes to be put in
+   *                           the wrong place on the project tree. Fixes #5274.
+   *  
    */
   class Project : public QObject {
     Q_OBJECT
@@ -462,9 +495,12 @@ namespace Isis {
 
       void templatesAdded(TemplateList *newTemplates);
 
+      void discardActiveControlEdits();
+
     public slots:
       void open(QString);
       void setClean(bool value);
+      void activeControlModified();
 
     private slots:
       void controlClosed(QObject *control);
diff --git a/isis/src/qisis/objs/ProjectItem/ProjectItem.cpp b/isis/src/qisis/objs/ProjectItem/ProjectItem.cpp
index 50df8540eea74890dae6f10fdabb8e3ddf2cdba8..acca2e2ac78a44ea474c1820b3d6658a51e83673 100644
--- a/isis/src/qisis/objs/ProjectItem/ProjectItem.cpp
+++ b/isis/src/qisis/objs/ProjectItem/ProjectItem.cpp
@@ -142,10 +142,7 @@ namespace Isis {
     setBundleSolutionInfo(bundleSolutionInfo);
 
     appendRow( new ProjectItem( bundleSolutionInfo->bundleSettings() ) );
-    QString cNetFileName = bundleSolutionInfo->controlNetworkFileName();
-    Control *control = new Control(cNetFileName);
-    appendRow( new ProjectItem(control) );
-
+    appendRow( new ProjectItem(bundleSolutionInfo->control()) );
     appendRow( new ProjectItem( bundleSolutionInfo->bundleResults() ) );
     appendRow( new ProjectItem( bundleSolutionInfo->adjustedImages() ) );
   }
diff --git a/isis/src/qisis/objs/ProjectItem/ProjectItem.h b/isis/src/qisis/objs/ProjectItem/ProjectItem.h
index fab1135a81b2494f3cc0ff5178f588ab97c911a7..9c648e60c05cb8b8d203159541725aea4c27349b 100644
--- a/isis/src/qisis/objs/ProjectItem/ProjectItem.h
+++ b/isis/src/qisis/objs/ProjectItem/ProjectItem.h
@@ -136,6 +136,9 @@ namespace Isis {
    *                             taking a BundleSolutionInfo.  Fixes #4849.
    *     @history 2017-11-03 Christopher Combs - Added support for new Template and TemplateList
    *                             classes. Fixes #5117.
+   *     @history 2018-03-22 Ken Edmundson - Modified constructor taking a BundleSolutionInfo to
+   *                             append a row for a Control object containing the output control
+   *                             net from the bundle adjustment.
    *
    */
   class ProjectItem : public QStandardItem {
diff --git a/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.cpp b/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.cpp
index 806cebafbbeedae3cd8e1dbc6ecf26883a073f0f..091c7508c96c57b487dd6b7b787f67c7979549b4 100644
--- a/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.cpp
+++ b/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.cpp
@@ -384,7 +384,13 @@ namespace Isis {
             ProjectItem *pItem = new ProjectItem(bundleSolutionInfo);
             resultsItem->appendRow( pItem );
 
-            // Append the CSV files to the Statistics in the project
+            // Append text bundle summary and CSV files to the Statistics in the project
+            ProjectItem *bundleSummaryItem = new ProjectItem(FileItemQsp(
+               new FileItem(bundleSolutionInfo->savedBundleOutputFilename())),
+                            "Summary", bundleSolutionInfo->savedBundleOutputFilename(),
+                            QIcon(FileName("$base/icons/office-chart-pie.png")
+                            .expanded()));
+            pItem->child(2)->appendRow(bundleSummaryItem);
             ProjectItem *residualsItem = new ProjectItem(FileItemQsp(
                new FileItem(bundleSolutionInfo->savedResidualsFilename())),
                             "Measure Residuals", bundleSolutionInfo->savedResidualsFilename(),
@@ -393,7 +399,7 @@ namespace Isis {
             pItem->child(2)->appendRow(residualsItem);
             ProjectItem *imagesItem = new ProjectItem(FileItemQsp(
                new FileItem(bundleSolutionInfo->savedImagesFilename())),
-                            "Images", bundleSolutionInfo->savedImagesFilename(),
+                            "Image", bundleSolutionInfo->savedImagesFilename(),
                             QIcon(FileName("$base/icons/office-chart-pie.png")
                             .expanded()));
             pItem->child(2)->appendRow(imagesItem);
diff --git a/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.h b/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.h
index 242f166cf9e9680da05a067e41c07859f6dda0af..820c7643b88ef48a08442d782c55ff78b96480b2 100644
--- a/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.h
+++ b/isis/src/qisis/objs/ProjectItemModel/ProjectItemModel.h
@@ -126,6 +126,10 @@ namespace Isis {
    *                           not clean. Fixes #5174.
    *   @history 2017-11-03 Christopher Combs - Added support for new Template and TemplateList
    *                           classes. Fixes #5117.
+   *   @history 2018-03-22 Ken Edmundson - Modified method onBundleSolutionInfoAdded to append the
+   *                           bundleoutput.txt (Summary) file to the BundleSolution Statistics
+   *                           node. Also changed the name of the Images node under Statistics to
+   *                           Image to prevent Import Images to appear on it's context menu.
    */
   class ProjectItemModel : public QStandardItemModel {
 
diff --git a/isis/src/qisis/objs/QIsisApplication/QIsisApplication.cpp b/isis/src/qisis/objs/QIsisApplication/QIsisApplication.cpp
index 6881dfa2c78d84605dd13b3e6bbe50a52661dab0..94598f1c237c0ee940e68e6c93394493c871440d 100644
--- a/isis/src/qisis/objs/QIsisApplication/QIsisApplication.cpp
+++ b/isis/src/qisis/objs/QIsisApplication/QIsisApplication.cpp
@@ -34,7 +34,6 @@ namespace Isis {
     QApplication(argc, argv) {
     // try to use US locale for numbers so we don't end up printing "," instead
     //   of "." where it might count.
-        
     
     for (int i = 1; i < argc; i++) {
         QString arg(argv[i]);
diff --git a/isis/src/qisis/objs/Workspace/Workspace.cpp b/isis/src/qisis/objs/Workspace/Workspace.cpp
index 108f8042f915493a92b115b4c200aedfb90c72a8..4a640bfbd6af9582b07f663447da709b5cc5f0dc 100644
--- a/isis/src/qisis/objs/Workspace/Workspace.cpp
+++ b/isis/src/qisis/objs/Workspace/Workspace.cpp
@@ -338,13 +338,13 @@ namespace Isis {
     QList<QString> cubesToOpen;
 
     // If the file is a cub file, we add the path to it to our list of cubes to open.
-    if ( cubeFileName.suffix() == "cub" || cubeFileName.suffix() == "cube" ) {
-       // cubesToOpen.append(cubeFileName.absoluteFilePath());
-       cubesToOpen.append(cubeFileName.filePath());
+    if ( cubeFileName.suffix() == "cub" || cubeFileName.suffix() == "cube" || cubeFileName.suffix() == "lbl") {
+      // cubesToOpen.append(cubeFileName.absoluteFilePath());
+      cubesToOpen.append(cubeFileName.filePath());
     }
     else {
-      // If the file received isn't a .cub, it has to be a cubelist. We read every cube in the cubelist
-      // And append it to the cubesToOpen QList so that we can open them.
+      // If the file received isn't a cube or label, it has to be a cubelist. We read every cube in
+      // the cubelist and append it to the cubesToOpen QList so that we can open them.
       QFile file(cubename);
       file.open(QIODevice::ReadOnly);
 
diff --git a/isis/src/qisis/objs/Workspace/Workspace.h b/isis/src/qisis/objs/Workspace/Workspace.h
index 63c131af08fb121985304e437b9bacfa755a3c22..3c1393d5030118e3e7e5ec9a554535877f944c00 100644
--- a/isis/src/qisis/objs/Workspace/Workspace.h
+++ b/isis/src/qisis/objs/Workspace/Workspace.h
@@ -79,6 +79,8 @@ namespace Isis {
   *                           class, Shape, which also contains a cube, but not an Image.
   *   @history 2017-09-11 Adam Goins - Added the ability to accept cubelists under any file format.
   *                           Fixes #5099.
+  *   @history 2018-04-13 Christopher Combs - Added .lbl files to the list of single-cube file-extensions
+  *                           to check before reading a cube list in addCubeViewport. Fixes #5350.
   */
   class Workspace : public QWidget {
       Q_OBJECT
diff --git a/isis/src/rosetta/apps/rosvirtis2isis/rosvirtis2isis.cpp b/isis/src/rosetta/apps/rosvirtis2isis/rosvirtis2isis.cpp
index 0b2760e1c44fd0e2ee43da914cd2bb0eb4f30661..a5591d78cb266cf580b8c6c8447c4dea3f514b0c 100644
--- a/isis/src/rosetta/apps/rosvirtis2isis/rosvirtis2isis.cpp
+++ b/isis/src/rosetta/apps/rosvirtis2isis/rosvirtis2isis.cpp
@@ -13,6 +13,7 @@
 
 #include "FileName.h"
 #include "ImportPdsTable.h"
+#include "LineManager.h"
 #include "ProcessImportPds.h"
 #include "Table.h"
 #include "UserInterface.h"
@@ -89,233 +90,261 @@ void IsisMain ()
     throw IException(IException::Unknown, msg, _FILEINFO_);
   }
 
+  int procLevel = (int) pdsLabel.findKeyword("PROCESSING_LEVEL_ID");
+
   // Override default DataTrailerBytes constructed from PDS header
   // Will this number ever change? Where did this # come from?
-  p.SetDataTrailerBytes(864);
+  if (procLevel == 2) {
+    p.SetDataTrailerBytes(864);
+  }
+  else if (procLevel == 3) {
+    p.SetDataTrailerBytes(0);
+    p.SetDataSuffixBytes(4);
+  }
 
   p.StartProcess();
 
-  // Retrieve HK settings file and read in HK values.
-  QList<VirtisHK> hk;
-
   // Get the directory where the Rosetta translation tables are.
   PvlGroup dataDir (Preference::Preferences().findGroup("DataDirectory"));
   QString transDir = (QString) dataDir["Rosetta"] + "/translations/";
 
-  FileName hkTranslationFile = transDir + "virtis_housekeeping.txt";
-  QFile hkFile(hkTranslationFile.toString());
+  if (procLevel == 2) {
 
-  if(!hkFile.open(QIODevice::ReadOnly)) {
-    QString msg = "Unable to open Virtis Housekeeping information file [" +
-                 hkFile.fileName() + "]";
-    throw IException(IException::Io,msg, _FILEINFO_);
-  }
+    // Retrieve HK settings file and read in HK values.
+    QList<VirtisHK> hk;
 
-  QTextStream in(&hkFile);
+    FileName hkTranslationFile = transDir + "virtis_housekeeping.txt";
+    QFile hkFile(hkTranslationFile.toString());
 
-  while(!in.atEnd()) {
-      QString line = in.readLine();
-      QStringList fields = line.split(",");
-      hk.append(VirtisHK(fields[0], fields[1], fields[2], fields[3], fields[4]));
-  }
+    if(!hkFile.open(QIODevice::ReadOnly)) {
+      QString msg = "Unable to open Virtis Housekeeping information file [" +
+                   hkFile.fileName() + "]";
+      throw IException(IException::Io,msg, _FILEINFO_);
+    }
 
-  hkFile.close();
+    QTextStream in(&hkFile);
 
-  // Construct HK (housekeeping) table
-  TableRecord rec;
+    while(!in.atEnd()) {
+        QString line = in.readLine();
+        QStringList fields = line.split(",");
+        hk.append(VirtisHK(fields[0], fields[1], fields[2], fields[3], fields[4]));
+    }
 
-  QList<TableField> tableFields;
+    hkFile.close();
 
-  for (int i=0; i < hk.size(); i++) {
-    tableFields.append(hk[i].tableField());
-  }
+    // Construct HK (housekeeping) table
+    TableRecord rec;
 
-  for (int i=0; i < tableFields.size(); i++) {
-    rec += tableFields[i];
-  }
+    QList<TableField> tableFields;
 
-  Table table("VIRTISHouseKeeping", rec);
+    for (int i=0; i < hk.size(); i++) {
+      tableFields.append(hk[i].tableField());
+    }
 
-  // VIRTIS-M (VIS and IR) Equations
-  // These are adapted from the VIRTIS IDL processing pipeline
-  // and pg. 66-67 of the VIRTIS-EAICD
-  QList<std::vector<double> > equationList;
-  for (int i=0; i < hk.size(); i++) {
-    equationList.append(hk[i].coefficients());
-  }
+    for (int i=0; i < tableFields.size(); i++) {
+      rec += tableFields[i];
+    }
 
-  QList<PolynomialUnivariate> equations;
+    Table table("VIRTISHouseKeeping", rec);
 
-  for (int s=0; s < equationList.size(); s++) {
-    equations.append(PolynomialUnivariate(2, equationList[s]));
-  }
+    // VIRTIS-M (VIS and IR) Equations
+    // These are adapted from the VIRTIS IDL processing pipeline
+    // and pg. 66-67 of the VIRTIS-EAICD
+    QList<std::vector<double> > equationList;
+    for (int i=0; i < hk.size(); i++) {
+      equationList.append(hk[i].coefficients());
+    }
 
-  // Populate the Housekeeping table
-  //
-  // There are 3 categories of VIRTIS HK Values, in terms of converting from input byte to output
-  // value:
-  //
-  // (1) SCET (many-to-one)
-  // (2) Physical Quantities (one-to-one)
-  // (3) Flags or Statistics (one-to-many)
-  //
-  // SCET values are made up of 3 VIRTIS HK 2-byte words. The output value can be calculated
-  // using the translateScet helper function.
-  //
-  // Physical values are made up of 1 VIRTIS HK 2-byte word, which is converted to a physical value
-  // using an equation specified as a series of coefficients in the associated "assets" file.
-  //
-  // For Flags or Statistics Values, 1 VIRTIS HK 2-byte word is associated with several (a varaible
-  // number of) output Flag or Statistics values. These are all treated as special cases.
-  //
-  // Additionally, Sine and Cosine HK Values need to be pre-processed before conversion, but are
-  // otherwise treated as a normal "Physical Quantity" HK.
-  //
-  std::vector< char * > hkData = p.DataTrailer();
-  for (unsigned int i=0; i < hkData.size() ; i++) {
-    const char *hk = hkData.at(i);
-    const unsigned short *uihk = reinterpret_cast<const unsigned short *> (hk);
-
-    // Each data trailer can contain multiple 82-word records, but we only need 1 / line
-    int start = 0;
-    int tableNum = 0;
-
-    // Loop through each 82-word record
-    // Each k is a byteNumber
-    for (int k=0; k<82*2; k=k+2) {
-      int temp = 0;
-
-      // Convert non-SCET records (1 two-byte word each) using the appropriate equations
-      if (k !=0 && k!=14 && k!=38 && k!=58 && k!=116) {
-        temp = word(hk[start + k], hk[start+k+1]);
-        if (temp != 65535) {
-
-          // If Sine or Cosine, pre-process before sending to conversion.
-          if (tableNum == 63) { // SIN
-            int HK_bit = (int) (((unsigned short int) temp) & 4095);
-            int HK_sign = (unsigned short int) (temp/4096.0) & 1;
-            rec[tableNum] = equations[tableNum].Evaluate((HK_sign * 1.0) * (HK_bit * 1.0));
-          } else if (tableNum == 64) { // COS
-            temp = (int) (temp) & 4095;
-            rec[tableNum] = equations[tableNum].Evaluate(temp * 1.0);
-          } else if (tableNum == 2) { // # of Subslices / first seial num 2-3
-            rec[tableNum] = hk[start+k]*1.0;
-            rec[tableNum+1] = hk[start+k+1]*1.0;
-            tableNum++;
-          } // Specical one-to-many cases (Flags or Statistics)
-          else if (tableNum == 4) { // Data Type 4-9
-            rec[tableNum] = (int)(temp/-32768) & 1;
-            rec[tableNum+1] = (int)(temp/16384) & 1;
-            rec[tableNum+2] = (int)(temp/8192) & 1;
-            rec[tableNum+3] = (int)(temp/1024) & 7;
-            rec[tableNum+4] = (int)(temp/256) & 3;
-            rec[tableNum+5] = (int)(temp/1) & 255;
-            tableNum+=5;
-          } else if (tableNum == 12) { // V_MODE 12-14
-            rec[tableNum] = 1.0* ((int)(temp/4096) & 15);
-            rec[tableNum+1] = 1.0* ((int)(temp/64) & 63);
-            rec[tableNum+2] = 1.0* ((int)(temp/1) & 63);
-            tableNum+=2;
-          } else if (tableNum == 15) { //ME_PWR_STAT 15 - 21
-            rec[tableNum] = 1.0* ((int)(temp/1) & 1);
-            rec[tableNum+1] = 1.0* ((int)(temp/2) & 1);
-            rec[tableNum+2] = 1.0* ((int)(temp/4) & 1);
-            rec[tableNum+3] = 1.0* ((int)(temp/8) & 1);
-            rec[tableNum+4] = 1.0* ((int)(temp/16) & 1);
-            rec[tableNum+5] = 1.0* ((int)(temp/32) & 1);
-            rec[tableNum+6] = 1.0* ((int)(temp/-32786) & 1);
-            tableNum+=6;
-          } else if (tableNum == 30){  // M_ECA_STAT 30-31
-            rec[tableNum] = 1.0* ((int)(temp/1) & 1);
-            rec[tableNum+1] = 1.0* ((int)(temp/256) & 1);
-            tableNum++;
-          } else if (tableNum == 32) { // M_COOL_STAT 32-34
-            rec[tableNum] = 1.0* ((int)(temp/1) & 1);
-            rec[tableNum+1] = 1.0* ((int)(temp/16) & 1);
-            rec[tableNum+2] = 1.0* ((int)(temp/256) & 1);
-            tableNum+=2;
-          }
+    QList<PolynomialUnivariate> equations;
 
-          else if (tableNum == 65) { // M_VIS_FLAG
-            rec[tableNum] = 1.0* ((int)(temp/1) & 1);
-            rec[tableNum+1] = 1.0* ((int)(temp/2) & 1);
-            rec[tableNum+2] = 1.0* ((int)(temp/4) & 1);
-            rec[tableNum+3] = 1.0* ((int)(temp/8) & 1);
-            rec[tableNum+4] = 1.0* ((int)(temp/16) & 1);
-            rec[tableNum+5] = 1.0* ((int)(temp/256) & 1);
-            tableNum+=5;
-          }
-          else if (tableNum == 91) { //M_IR_LAMP_SHUTTER
-            double lamp1 = 1.0* ((int)(temp/1) & 15);
-            rec[tableNum] = equations[tableNum].Evaluate(lamp1);
-            rec[tableNum+1] = 1.0* ((int)(temp/16) & 1);
-            double lamp2 = 1.0* ((int)(temp/256) & 15);
-            rec[tableNum+2] = equations[tableNum+1].Evaluate(lamp2);
-            rec[tableNum+3] = 1.0* ((int)(temp/4096) & 1);
-            tableNum+=3;
-          }
-          else if (tableNum == 95) { // M_IR_FLAG
-            rec[tableNum] = 1.0* ((int)(temp/1) & 1);
-            rec[tableNum+1] = 1.0* ((int)(temp/2) & 1);
-            rec[tableNum+2] = 1.0* ((int)(temp/4) & 1);
-            rec[tableNum+3] = 1.0* ((int)(temp/8) & 1);
-            rec[tableNum+4] = 1.0* ((int)(temp/16) & 1);
-            rec[tableNum+5] = 1.0* ((int)(temp/32) & 1);
-            rec[tableNum+6] = 1.0* ((int)(temp/64) & 1);
-            rec[tableNum+7] = 1.0* ((int)(temp/512) & 1);
-            rec[tableNum+8] = 1.0* ((int)(temp/4096) & 1);
-            rec[tableNum+9] = 1.0* ((int)(temp/8192) & 1);
-            rec[tableNum+10] = 1.0* ((int)(temp/16384) & 1);
-            tableNum+=10;
+    for (int s=0; s < equationList.size(); s++) {
+      equations.append(PolynomialUnivariate(2, equationList[s]));
+    }
+
+    // Populate the Housekeeping table
+    //
+    // There are 3 categories of VIRTIS HK Values, in terms of converting from input byte to output
+    // value:
+    //
+    // (1) SCET (many-to-one)
+    // (2) Physical Quantities (one-to-one)
+    // (3) Flags or Statistics (one-to-many)
+    //
+    // SCET values are made up of 3 VIRTIS HK 2-byte words. The output value can be calculated
+    // using the translateScet helper function.
+    //
+    // Physical values are made up of 1 VIRTIS HK 2-byte word, which is converted to a physical value
+    // using an equation specified as a series of coefficients in the associated "assets" file.
+    //
+    // For Flags or Statistics Values, 1 VIRTIS HK 2-byte word is associated with several (a varaible
+    // number of) output Flag or Statistics values. These are all treated as special cases.
+    //
+    // Additionally, Sine and Cosine HK Values need to be pre-processed before conversion, but are
+    // otherwise treated as a normal "Physical Quantity" HK.
+    //
+    std::vector< char * > hkData = p.DataTrailer();
+    for (unsigned int i=0; i < hkData.size() ; i++) {
+      const char *hk = hkData.at(i);
+      const unsigned short *uihk = reinterpret_cast<const unsigned short *> (hk);
+
+      // Each data trailer can contain multiple 82-word records, but we only need 1 / line
+      int start = 0;
+      int tableNum = 0;
+
+      // Loop through each 82-word record
+      // Each k is a byteNumber
+      for (int k=0; k<82*2; k=k+2) {
+        int temp = 0;
+
+        // Convert non-SCET records (1 two-byte word each) using the appropriate equations
+        if (k !=0 && k!=14 && k!=38 && k!=58 && k!=116) {
+          temp = word(hk[start + k], hk[start+k+1]);
+          if (temp != 65535) {
+
+            // If Sine or Cosine, pre-process before sending to conversion.
+            if (tableNum == 63) { // SIN
+              int HK_bit = (int) (((unsigned short int) temp) & 4095);
+              int HK_sign = (unsigned short int) (temp/4096.0) & 1;
+              rec[tableNum] = equations[tableNum].Evaluate((HK_sign * 1.0) * (HK_bit * 1.0));
+            } else if (tableNum == 64) { // COS
+              temp = (int) (temp) & 4095;
+              rec[tableNum] = equations[tableNum].Evaluate(temp * 1.0);
+            } else if (tableNum == 2) { // # of Subslices / first seial num 2-3
+              rec[tableNum] = hk[start+k]*1.0;
+              rec[tableNum+1] = hk[start+k+1]*1.0;
+              tableNum++;
+            } // Specical one-to-many cases (Flags or Statistics)
+            else if (tableNum == 4) { // Data Type 4-9
+              rec[tableNum] = (int)(temp/-32768) & 1;
+              rec[tableNum+1] = (int)(temp/16384) & 1;
+              rec[tableNum+2] = (int)(temp/8192) & 1;
+              rec[tableNum+3] = (int)(temp/1024) & 7;
+              rec[tableNum+4] = (int)(temp/256) & 3;
+              rec[tableNum+5] = (int)(temp/1) & 255;
+              tableNum+=5;
+            } else if (tableNum == 12) { // V_MODE 12-14
+              rec[tableNum] = 1.0* ((int)(temp/4096) & 15);
+              rec[tableNum+1] = 1.0* ((int)(temp/64) & 63);
+              rec[tableNum+2] = 1.0* ((int)(temp/1) & 63);
+              tableNum+=2;
+            } else if (tableNum == 15) { //ME_PWR_STAT 15 - 21
+              rec[tableNum] = 1.0* ((int)(temp/1) & 1);
+              rec[tableNum+1] = 1.0* ((int)(temp/2) & 1);
+              rec[tableNum+2] = 1.0* ((int)(temp/4) & 1);
+              rec[tableNum+3] = 1.0* ((int)(temp/8) & 1);
+              rec[tableNum+4] = 1.0* ((int)(temp/16) & 1);
+              rec[tableNum+5] = 1.0* ((int)(temp/32) & 1);
+              rec[tableNum+6] = 1.0* ((int)(temp/-32786) & 1);
+              tableNum+=6;
+            } else if (tableNum == 30){  // M_ECA_STAT 30-31
+              rec[tableNum] = 1.0* ((int)(temp/1) & 1);
+              rec[tableNum+1] = 1.0* ((int)(temp/256) & 1);
+              tableNum++;
+            } else if (tableNum == 32) { // M_COOL_STAT 32-34
+              rec[tableNum] = 1.0* ((int)(temp/1) & 1);
+              rec[tableNum+1] = 1.0* ((int)(temp/16) & 1);
+              rec[tableNum+2] = 1.0* ((int)(temp/256) & 1);
+              tableNum+=2;
+            }
+
+            else if (tableNum == 65) { // M_VIS_FLAG
+              rec[tableNum] = 1.0* ((int)(temp/1) & 1);
+              rec[tableNum+1] = 1.0* ((int)(temp/2) & 1);
+              rec[tableNum+2] = 1.0* ((int)(temp/4) & 1);
+              rec[tableNum+3] = 1.0* ((int)(temp/8) & 1);
+              rec[tableNum+4] = 1.0* ((int)(temp/16) & 1);
+              rec[tableNum+5] = 1.0* ((int)(temp/256) & 1);
+              tableNum+=5;
+            }
+            else if (tableNum == 91) { //M_IR_LAMP_SHUTTER
+              double lamp1 = 1.0* ((int)(temp/1) & 15);
+              rec[tableNum] = equations[tableNum].Evaluate(lamp1);
+              rec[tableNum+1] = 1.0* ((int)(temp/16) & 1);
+              double lamp2 = 1.0* ((int)(temp/256) & 15);
+              rec[tableNum+2] = equations[tableNum+1].Evaluate(lamp2);
+              rec[tableNum+3] = 1.0* ((int)(temp/4096) & 1);
+              tableNum+=3;
+            }
+            else if (tableNum == 95) { // M_IR_FLAG
+              rec[tableNum] = 1.0* ((int)(temp/1) & 1);
+              rec[tableNum+1] = 1.0* ((int)(temp/2) & 1);
+              rec[tableNum+2] = 1.0* ((int)(temp/4) & 1);
+              rec[tableNum+3] = 1.0* ((int)(temp/8) & 1);
+              rec[tableNum+4] = 1.0* ((int)(temp/16) & 1);
+              rec[tableNum+5] = 1.0* ((int)(temp/32) & 1);
+              rec[tableNum+6] = 1.0* ((int)(temp/64) & 1);
+              rec[tableNum+7] = 1.0* ((int)(temp/512) & 1);
+              rec[tableNum+8] = 1.0* ((int)(temp/4096) & 1);
+              rec[tableNum+9] = 1.0* ((int)(temp/8192) & 1);
+              rec[tableNum+10] = 1.0* ((int)(temp/16384) & 1);
+              tableNum+=10;
+            }
+            else {
+               // Convert a physical quantity to its output value (1 word -> 1 output physical value)
+               rec[tableNum] = equations[tableNum].Evaluate(temp * 1.0);
+            }
           }
           else {
-             // Convert a physical quantity to its output value (1 word -> 1 output physical value)
-             rec[tableNum] = equations[tableNum].Evaluate(temp * 1.0);
+            rec[tableNum] = 65535.0; // HK Data is Invalid
           }
         }
         else {
-          rec[tableNum] = 65535.0; // HK Data is Invalid
-        }
-      }
-      else {
-        // Convert SCET records (3 words -> one output SCET)
-        int uk = k/2;
-#if 0
-        int word1 = word(hk[start+k], hk[start+k+1]);
-        int word2 = word(hk[start+k+2], hk[start+k+3]);
-        int word3 = word(hk[start+k+4], hk[start+k+5]);
-#else
-        int word1 = swapb(uihk[uk]);
-        int word2 = swapb(uihk[uk+1]);
-        int word3 = swapb(uihk[uk+2]);
-#endif
-
-        double result;
-
-        // If any of the words comprising the SCET are invalid, the whole thing is invalid.
-        if (isValid(word1) && isValid(word2) && isValid(word3)) {
-          result = translateScet(word1, word2, word3);
-        }
-        else {
-          result = 65535;
-        }
+          // Convert SCET records (3 words -> one output SCET)
+          int uk = k/2;
+  #if 0
+          int word1 = word(hk[start+k], hk[start+k+1]);
+          int word2 = word(hk[start+k+2], hk[start+k+3]);
+          int word3 = word(hk[start+k+4], hk[start+k+5]);
+  #else
+          int word1 = swapb(uihk[uk]);
+          int word2 = swapb(uihk[uk+1]);
+          int word3 = swapb(uihk[uk+2]);
+  #endif
+
+          double result;
+
+          // If any of the words comprising the SCET are invalid, the whole thing is invalid.
+          if (isValid(word1) && isValid(word2) && isValid(word3)) {
+            result = translateScet(word1, word2, word3);
+          }
+          else {
+            result = 65535;
+          }
 
-        // If we don't have a valid SCET, the whole line of HK data is not valid, so we skip it.
-        if (result == 0 || result == 65535) {
-          break;
-        }
-        else{
-          rec[tableNum] = result*1.0;
+          // If we don't have a valid SCET, the whole line of HK data is not valid, so we skip it.
+          if (result == 0 || result == 65535) {
+            break;
+          }
+          else{
+            rec[tableNum] = result*1.0;
+          }
+          // We used 3 words
+          k=k+4;
         }
-        // We used 3 words
-        k=k+4;
+        tableNum++;
       }
-      tableNum++;
+      table += rec;
     }
-    table += rec;
-  }
 
-  outcube->write(table);
+    outcube->write(table);
+  }
+  else if (procLevel == 3) {
+    std::vector<char *> hkData = p.DataTrailer();
+    TableRecord rec;
+    TableField scETField("dataSCET", TableField::Double);
+    rec += scETField;
+    Table table("VIRTISHouseKeeping", rec);
+    for (unsigned int i=0; i < hkData.size() ; i++) {
+      const char *hk = hkData.at(i);
+      const unsigned short *uihk = reinterpret_cast<const unsigned short *> (hk);
+      int word1 = swapb(uihk[0]);
+      int word2 = swapb(uihk[1]);
+      int word3 = swapb(uihk[2]);
+      rec[0] = translateScet(word1, word2, word3);
+      table += rec;
+    }
+    outcube->write(table);
+  }
 
 
   // Create a PVL to store the translated labels in
@@ -354,6 +383,26 @@ void IsisMain ()
   }
   outcube->putGroup(kerns);
 
+  // NULL the dark current scans in level 2 images
+  if (procLevel == 2) {
+    const PvlKeyword &frameKey = outcube->group("Instrument").findKeyword("FrameParameter");
+    // The third frame key is always the number of scans in between dark current scans.
+    // So, we need to add one to that in order to get the number of lines to next dark current.
+    int darkRate = toInt(frameKey[3]) + 1;
+    LineManager darkLineManager(*outcube);
+
+    for (int band = 1; band <= outcube->bandCount(); band++) {
+      // The first line is always a dark current, so start there.
+      for (int line = 1; line <= outcube->lineCount(); line+=darkRate) {
+        darkLineManager.SetLine(line,band);
+        for (int sample = 0; sample < darkLineManager.size(); sample++) {
+          darkLineManager[sample] = Isis::Null;
+        }
+        outcube->write(darkLineManager);
+      }
+    }
+  }
+
   p.EndProcess ();
 }
 
diff --git a/isis/src/rosetta/apps/rosvirtis2isis/rosvirtis2isis.xml b/isis/src/rosetta/apps/rosvirtis2isis/rosvirtis2isis.xml
index 0513adad79b1b88c226b88904308735f49b1b1ff..ca797fd4b497a13aab1dadbadc7c25fd0c776be0 100644
--- a/isis/src/rosetta/apps/rosvirtis2isis/rosvirtis2isis.xml
+++ b/isis/src/rosetta/apps/rosvirtis2isis/rosvirtis2isis.xml
@@ -9,10 +9,10 @@
   <description>
     <p>
     This program will import and convert a PDS-formatted Rosetta VIRTIS-M or VIRTIS-H image into an ISIS cube.
-    This program is designed to work with data available in the draft data area on PDS as of 04/25/2016 and with any officially released data as of 11/01/2016. 
+    This program is designed to work with data available in the draft data area on PDS as of 04/25/2016 and with any officially released data as of 11/01/2016.
     </p>
     <p>
-      The output cube will contain a substantial housekeeping data table named "HK." It contains, in order, the HK values for each line of the cube as described on pg 66-67 of the VIRTIS EAICD. 
+      The output cube will contain a substantial housekeeping data table named "HK." It contains, in order, the HK values for each line of the cube as described on pg 66-67 of the VIRTIS EAICD.
     </p>
     <h3> Requirements </h3>
     <ul>
@@ -26,35 +26,41 @@
     <br/>
     <h2>Instrument Overview</h2>
    <p>
-     VIRTIS-M is a mapping spectrometer onboard the Rosetta mission comprised of two components: VIRTIS-M-VIS, and VIRTIS-M-IR. VIRTIS-M-VIS is the visible component, and VIRTIS-M-IR is the infrared component. 
+     VIRTIS-M is a mapping spectrometer onboard the Rosetta mission comprised of two components: VIRTIS-M-VIS, and VIRTIS-M-IR. VIRTIS-M-VIS is the visible component, and VIRTIS-M-IR is the infrared component.
      VIRTIS-H is a high resolution infrared spectrometer (1840-4990 nm).
    </p>
     <h2>Data Archive</h2>
     <p>
       The Rosetta data are available from the
-      <a href="http://pds-smallbodies.astro.umd.edu/data_sb/missions/rosetta/index.shtml">NASA PDS Small 
+      <a href="http://pds-smallbodies.astro.umd.edu/data_sb/missions/rosetta/index.shtml">NASA PDS Small
       Bodies Node</a>.
     </p>
 
     <h2>References</h2>
     <cite>
     </cite>
-    <br /> 
+    <br />
   </description>
 
   <history>
     <change name="Kristin Berry" date="2016-04-25">
-      Original version 
+      Original version
     </change>
     <change name="Kristin Berry" date="2016-11-01">
-       Add ability to ingest housekeeping data.  
+       Add ability to ingest housekeeping data.
     </change>
     <change name="Kaj Williams" date="2017-08-24">
-       Add ability to ingest VIRTIS-H files. References #5130.  
+       Add ability to ingest VIRTIS-H files. References #5130.
     </change>
     <change name="Kris Becker and Kaj Williams" date="2017-08-24">
        Fix issues with the translation of housekeeping data. Fixes #5131.
     </change>
+    <change name="Jesse Mapel" date="2018-05-14">
+       Fixed compiler warnings from new lvl3 ingestion code.
+    </change>
+    <change name="Jesse Mapel" date="2018-05-14">
+       Nulled dark current scans in level 2 data. Fixes #5421.
+    </change>
   </history>
 
   <category>
@@ -70,7 +76,7 @@
           Input PDS formatted Rosetta VIRTIS image file
         </brief>
         <description>
-          Use this parameter to select the Rosetta VIRTIS filename. 
+          Use this parameter to select the Rosetta VIRTIS filename.
         </description>
         <filter>
           *.qub
diff --git a/isis/src/system/apps/kerneldbgen/SpiceDbGen.cpp b/isis/src/system/apps/kerneldbgen/SpiceDbGen.cpp
index ab4949f2f8dbcea6543df32d957abc4eabb272ad..a7695155df4fa584f02d07fea5cc984efb502b09 100644
--- a/isis/src/system/apps/kerneldbgen/SpiceDbGen.cpp
+++ b/isis/src/system/apps/kerneldbgen/SpiceDbGen.cpp
@@ -40,7 +40,8 @@ const char *SpiceDbGen::calForm = "YYYY MON DD HR:MN:SC.###### TDB ::TDB";
 */
 SpiceDbGen::SpiceDbGen(QString type) {
   p_type = type;
-//  calForm = "YYYY MON DD HR:MN:SC.### TDB ::TDB";
+  m_coverageLevel = "SEGMENT"; // default
+  //  calForm = "YYYY MON DD HR:MN:SC.### TDB ::TDB";
 }
 
 
@@ -155,6 +156,17 @@ QStringList SpiceDbGen::GetFiles(FileName location, QString filter) {
 }
 
 
+/**
+ * Sets the desired time coverage level of the Spice database. 
+ * 
+ * @param level The desired time coverage level. May be either Segment or 
+ *              Interval.  
+ */
+void SpiceDbGen::setCoverageLevel(QString level) {
+  m_coverageLevel = level; 
+}
+
+
 /**
   * Format a single kernel file to include the file.
   *
@@ -227,10 +239,16 @@ PvlGroup SpiceDbGen::AddSelection(FileName fileIn, double startOffset, double en
         SPICEDOUBLE_CELL(cover, 200000);
         ssize_c(0, &cover);
         ssize_c(200000, &cover);
-        ckcov_c(tmp.toLatin1().data(), body, SPICEFALSE, "SEGMENT", 0.0, "TDB", &cover);
 
-        NaifStatus::CheckErrors();
+        // A SPICE SEGMENT is composed of SPICE INTERVALS
+        if (QString::compare(m_coverageLevel, "SEGMENT", Qt::CaseInsensitive) == 0 ) {
+          ckcov_c(tmp.toLatin1().data(), body, SPICEFALSE, "SEGMENT", 0.0, "TDB", &cover); 
+        }
+        else {
+          ckcov_c(tmp.toLatin1().data(), body, SPICEFALSE, "INTERVAL", 0.0, "TDB", &cover);
+        }
 
+        NaifStatus::CheckErrors();
         result = FormatIntervals(cover, currFile, startOffset, endOffset);
       }
     }
diff --git a/isis/src/system/apps/kerneldbgen/SpiceDbGen.h b/isis/src/system/apps/kerneldbgen/SpiceDbGen.h
index 616ff25a1993793043bb960cea165f6baf65f71e..9288a8c50548d9502ebdb7431ea0dbaf731907f5 100644
--- a/isis/src/system/apps/kerneldbgen/SpiceDbGen.h
+++ b/isis/src/system/apps/kerneldbgen/SpiceDbGen.h
@@ -47,6 +47,11 @@
  *   @history 2013-02-15 Steven Lambright - Added support for extra kernel dependencies
  *   @history 2018-01-10 Christopher Combs - Added passing startOffset and endOffset to allow
  *                           the passing of time offsets to to FormatIntervals. Fixes #5272.
+ *   @history 2018-05-09 Kristin Berry - Added information about the Spice time coverage level
+ *                            to this class: m_coverageLevel, setCoverageLevel, and this class will
+ *                            now select spice "time intervals" at the level specified. This is
+ *                            either a SPICE Segment (coarse) or a SPICE interval (fine.)
+ *                            Fixes #5410. 
  *
  */
 class SpiceDbGen {
@@ -57,6 +62,7 @@ class SpiceDbGen {
                            std::vector<QString> & filter, double startOffset, double endOffset);
     void FurnishDependencies(QList<Isis::FileName> sclks, QList<Isis::FileName> fks,
                              QList<Isis::FileName> extras);
+    void setCoverageLevel(QString level); 
 
   private:
     QStringList GetFiles(Isis::FileName location, QString filter);
@@ -65,6 +71,7 @@ class SpiceDbGen {
     Isis::PvlGroup GetIntervals(SpiceCell &cover);
     //private instance variables
     QString p_type;
+    QString m_coverageLevel; //! The time coverage level of the database: INTERVAL or SEGMENT
     static const char *calForm;
 };
 
diff --git a/isis/src/system/apps/kerneldbgen/kerneldbgen.cpp b/isis/src/system/apps/kerneldbgen/kerneldbgen.cpp
index fd69b7b53c4dea8b876a6394581b3a815718cd3b..af2a5d8ded458b3a8533222a831b1f04a094c9d6 100644
--- a/isis/src/system/apps/kerneldbgen/kerneldbgen.cpp
+++ b/isis/src/system/apps/kerneldbgen/kerneldbgen.cpp
@@ -15,19 +15,19 @@ void IsisMain() {
   UserInterface &ui = Application::GetUserInterface();
   PvlGroup dependency("Dependencies");
 
-  //create the database writer based on the kernel type
+  // Create the database writer based on the kernel type
   SpiceDbGen sdg(ui.GetString("TYPE"));
 
-  //Load the SCLK. If it exists, add its location to the dependency group
-  //If there is none, set a flag so that no file is searched for
+  // Load the SCLK. If it exists, add its location to the dependency group
+  // If there is none, set a flag so that no file is searched for
   QList<FileName> sclkFiles = evaluateDependencies(dependency, "SpacecraftClockKernel", "SCLK");
   QList<FileName> lskFiles = evaluateDependencies(dependency, "LeapsecondKernel", "LSK");
   QList<FileName> extraFiles = evaluateDependencies(dependency, "ExtraKernel", "EXTRA");
 
   sdg.FurnishDependencies(sclkFiles, lskFiles, extraFiles);
 
-  //Determine the type of kernel that the user wants a database for. This will
-  //eventually become the name of the object in the output PVL
+  // Determine the type of kernel that the user wants a database for. This will
+  // eventually become the name of the object in the output PVL
   QString kernelType;
   if (ui.GetString("TYPE") == "CK") {
     kernelType = "SpacecraftPointing";
@@ -37,6 +37,17 @@ void IsisMain() {
   }
   PvlObject selections(kernelType);
 
+  // Specify whether to use SPICE segments (made up of SPICE intervals) 
+  // or SPICE intervals for the SPICE database. Naif referes to this as "coverage level" 
+  QString coverageLevel; 
+  if (ui.GetString("LEVEL") == "SEGMENT") {
+    coverageLevel = "SEGMENT"; 
+  }
+  else if (ui.GetString("LEVEL") == "INTERVAL") {
+    coverageLevel = "INTERVAL"; 
+  }
+  sdg.setCoverageLevel(coverageLevel); 
+
   selections += PvlKeyword("RunTime", iTime::CurrentLocalTime());
   selections.addGroup(dependency);
 
diff --git a/isis/src/system/apps/kerneldbgen/kerneldbgen.xml b/isis/src/system/apps/kerneldbgen/kerneldbgen.xml
index e12f3e126f9c02ae1df5f72435d0901933fad840..7879eaf24534a65babd3abe1482584672eed51eb 100644
--- a/isis/src/system/apps/kerneldbgen/kerneldbgen.xml
+++ b/isis/src/system/apps/kerneldbgen/kerneldbgen.xml
@@ -152,6 +152,10 @@
       Added STARTOFFSET and ENDOFFSET parameters to allow for slight editing to start and end times.
       Fixes #5272.
     </change>
+    <change name="Kristin Berry" date="2018-05-09">
+      Added the LEVEL=(SEGMENT*, INTERVAL) option to specify the time coverage level to be used for the generated database. SPICE segements are made up of SPICE intervals. 
+      Segments (the only option in the past) are now the default, but interval can be selected if needed. Fixes #5410. 
+    </change>
   </history>
 
   <groups>
@@ -221,6 +225,37 @@
         </list>
       </parameter>
     </group>
+    <group name="Coverage Level">
+      <parameter name="LEVEL">
+        <type>string</type>
+        <default>
+          <item>SEGMENT</item>
+        </default>
+        <brief>
+           The level of time-granularity for the time-coverage interval to be output to the SPICE database. 
+        </brief>
+        <description>
+        </description>
+        <list>
+          <option value="SEGMENT">
+            <brief>
+              SPICE Segment             
+            </brief>
+            <description>
+              The coarsest level of time granularity, a SPICE segment is composed of SPICE intervals.              
+            </description>
+          </option>
+          <option value="INTERVAL">
+            <brief>
+              SPICE Interval 
+            </brief>
+            <description>
+              A finer level of time granularity. 
+            </description>
+          </option>
+        </list>
+      </parameter>
+    </group>
     <group name="Predict">
       <parameter name="PREDICTDIR">
         <type>string</type>
diff --git a/isis/src/system/apps/kerneldbgen/tsts/coverageLevel/Makefile b/isis/src/system/apps/kerneldbgen/tsts/coverageLevel/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..ea023286f7edbf8dcf789d42d07046a69be34165
--- /dev/null
+++ b/isis/src/system/apps/kerneldbgen/tsts/coverageLevel/Makefile
@@ -0,0 +1,38 @@
+# Coverage Level Test for kerneldbgen
+#
+# This test creates an output database file from the kernel in the input file
+# that follow the given filter for reconstructed ck file name patterns. A database
+# is output with time coverage at the SPICE segment level and at the SPICE interval 
+# level. (There will be one output entry for the spice segment, and several for the
+# SPICE interval because a SPICE segment is composed of SPICE intervals.) 
+#
+# After the output PVL is created, when compared, the DIFF file indicates to
+# ignore RunTime and File.  The File keyword is ignored since, depending on 
+# where the test is run, files may have different paths. These paths can not be 
+# removed since they may be long enough to take up multiple lines.
+# 
+# This test uses files from the TGO CaSSIS mission, as this is where the problem
+# was identified. 
+#
+# history 2018-05-09 Kristin Berry - Added test for newly added time coverage 
+#                                    LEVEL=(SEGMENT*, INTERVAL) option. See #5410
+APPNAME = kerneldbgen
+include $(ISISROOT)/make/isismake.tsts
+
+commands:
+	# Default output level=segment
+	$(APPNAME) to=$(OUTPUT)/kernel_segment.db.pvl \
+	  type=CK \
+	  recondir=$(INPUT) \
+	  reconfilter='em16_tgo_sc_??m_*.bc' \
+	  sclk=\$$tgo/kernels/sclk/em16_tgo_step_????????.tsc \
+          lsk=\$$base/kernels/lsk/naif0012.tls > /dev/null; 
+
+	# Output with level=interval, needed for CaSSIS kernels and potentially other type-6 kernels
+	$(APPNAME) to=$(OUTPUT)/kernel_interval.db.pvl \
+	  type=CK \
+	  level=INTERVAL \
+	  recondir=$(INPUT) \
+	  reconfilter='em16_tgo_sc_??m_*.bc' \
+ 	  sclk=\$$tgo/kernels/sclk/em16_tgo_step_????????.tsc \
+          lsk=\$$base/kernels/lsk/naif0012.tls > /dev/null;