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

Updated BundleSolutionInfo, JigsawDialog to save bundled images in the correct...

Updated BundleSolutionInfo, JigsawDialog to save bundled images in the correct spot on disk and to support serialization of the result images. Images now restored correctly. Fixes #4804, #4837.

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/branches/ipce_FY17-Sprint1@7637 41f8697f-d340-4b68-9986-7bafba869bb8
parent 9a2f20c2
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -1437,13 +1437,13 @@ namespace Isis {
    m_statisticsResults->save(stream, project);

    // save image lists to stream
//  std::cout << "\nm_images->isEmpty() ? " << (m_images->isEmpty() ? "EMPTY" : "NOT EMPTY") << "\n\n";
    if ( !m_images->isEmpty() ) {
      stream.writeStartElement("imageLists");

//    std::cout << "m_images->count() " << m_images->count() << "\n\n";
      FileName newResultsRoot(Project::bundleSolutionInfoRoot(newProjectRoot.expanded()) +
                              "/" + runTime());
      for (int i = 0; i < m_images->count(); i++) {
        m_images->at(i)->save(stream, project, "");
        m_images->at(i)->save(stream, project, newResultsRoot);
      }

      stream.writeEndElement();
+3 −0
Original line number Diff line number Diff line
@@ -101,6 +101,9 @@ namespace Isis {
   *   @history 2017-05-02 Tracie Sucharski - Moved XMLHandler code to bottom of file for
   *                           consistency;  all other classes have the XmlHandler at end of file.
   *                           Fixes #4822.
   *   @history 2017-05-04 Ian Humphrey & Makayla Shepherd - Modified save() to write the bundle
   *                           solution info images to the correct directory in the project on disk.
   *                           Fixes #4804, #4837.
   */
  class BundleSolutionInfo : public QObject {
    Q_OBJECT
+69 −36
Original line number Diff line number Diff line
#include "JigsawDialog.h"

#include <QtConcurrent>
#include <QDebug>
#include <QDir>
#include <QFuture>
#include <QScrollBar>
#include <QThread>

@@ -8,9 +11,12 @@

#include "BundleAdjust.h"
#include "BundleSolutionInfo.h"
#include "Cube.h"
#include "Directory.h"
#include "FileName.h"
#include "IException.h"
#include "Image.h"
#include "ImageList.h"
#include "JigsawSetupDialog.h"
#include "Control.h"
#include "iTime.h"
@@ -273,6 +279,51 @@ namespace Isis {
  }


  /**
   * Constructs a image copier functor for copying images used in the bundle adjustment to the
   * bundle solution info results (when the bundle is accepted).
   */
  JigsawDialog::CopyImageToResultsFunctor::CopyImageToResultsFunctor(const QDir &destination) {
    m_destinationFolder = destination;
  }


  /**
   * Destructor.
   */
  JigsawDialog::CopyImageToResultsFunctor::~CopyImageToResultsFunctor() {
    m_destinationFolder = QDir();
  }


  /**
   * @brief Callable operator that copies an image to the bundle solution info results.
   *
   * This makes the functor callable - this will copy the passed FileName and return a pointer
   * to the newly copied external cube.
   *
   * @param const FileName &image File name of the image to create an external copy of.
   *
   * @return Cube* Returns a pointer to the external cube copy. Returns NULL if an error
   *               occurs.
   */
  Cube *JigsawDialog::CopyImageToResultsFunctor::operator()(const FileName &image) {
    try {
      // Get the destination folder and create that path.
      FileName destination(QFileInfo(m_destinationFolder, image.name()).absoluteFilePath());
      m_destinationFolder.mkpath(destination.path());

      Cube originalCube(image, "r");
      return originalCube.copy(destination, CubeAttributeOutput("+External"));
    }
    // Error tracking should be more robust, see ImportImagesWorkOrder.
    catch (IException &e) {
      std::cout << "\nerror: " << e.what();
      return NULL;
    }
  }


  /**
   * Accepts the bundle results and saves them to the project. The "Accept" and "Reject" buttons
   * will be disabled.
@@ -290,48 +341,30 @@ namespace Isis {
                               FileName(m_bundleSolutionInfo->controlNetworkFileName()).name());
    m_bundleSolutionInfo->bundleResults().outputControlNet()->Write(jiggedControlName.toString());


    // Iterate through all of the image lists (the "imports" in the project).
    QList<ImageList *> imageLists = m_bundleSolutionInfo->imageList();
    foreach (ImageList *imageList, imageLists) {
      int i = 0;
      // Keep track of the file names of the images that were used in the bundle.
      QStringList imagesToCopy;
      int temp = 1;
      if (!imageList->name().isEmpty()) {
        imageList->setName("import" + QString::number(temp));
      }
      // Now, we iterate through each image in the current image list ("import"), and we determine
      // the location of the image and where to copy it to (as an ecub).
      foreach (Image *image, *imageList) {
        FileName imageName(image->fileName());
        FileName imagesBundledFile(m_project->bundleSolutionInfoRoot() + "/" +
                                   m_bundleSolutionInfo->runTime() + "/" + imageName.name());
        imagesBundledFile = imagesBundledFile.setExtension("ecub");

        Cube *originalCube = new Cube(image->fileName(), "r");
        Cube *ecub = originalCube->copy(imagesBundledFile, CubeAttributeOutput("+External"));

        // Process p;
        // p.SetInputCube(ecub);
        // //check for existing polygon, if exists delete it
        // if (ecub->label()->hasObject("Polygon")) {
        //   ecub->label()->deleteObject("Polygon");
        // }
        //
        // // check for CameraStatistics Table, if exists, delete
        // for (int iobj = 0; iobj < ecub->label()->objects(); iobj++) {
        //   PvlObject obj = ecub->label()->object(iobj);
        //  if (obj.name() != "Table") continue;
        //  if (obj["Name"][0] != QString("CameraStatistics")) continue;
        //  ecub->label()->deleteObject(iobj);
        //  break;
        // }
        // //  Get Kernel group and add or replace LastModifiedInstrumentPointing keyword.
        // Table cmatrix = m_bundleAdjust->cMatrix(i);
        // QString jigComment = "Jigged = " + Isis::iTime::CurrentLocalTime();
        // cmatrix.Label().addComment(jigComment);
        // Table spvector = m_bundleAdjust->spVector(i);
        // spvector.Label().addComment(jigComment);
        // ecub->write(cmatrix);
        // ecub->write(spvector);
        // p.WriteHistory(*ecub);
        // i++;
        FileName original(image->fileName());
        // Update our list of tracked file names for the images we are going to copy.
        imagesToCopy.append(original.expanded());
      }
      // Concurrently copy the bundled images as ecub's to the bundle solution info results.
      CopyImageToResultsFunctor copyImage(m_project->bundleSolutionInfoRoot() + "/" +
                                          m_bundleSolutionInfo->runTime() + "/images/" +
                                          imageList->name());
      // Do we need to release the memory for these cubes?
      QFuture<Cube *> copiedCubes = QtConcurrent::mapped(imagesToCopy, copyImage);
    }


    // Make sure that when we add our results, we let the use last settings box be checkable.
    m_ui->useLastSettings->setEnabled(true);

+25 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
#define JigsawDialog_h

#include <QDialog>
#include <QDir>
#include <QPointer>
#include <QWidget>

@@ -18,7 +19,9 @@ namespace Isis {
  class BundleAdjust;
  class BundleSolutionInfo;
  class Control;
  class Cube;
  class Directory;
  class FileName;
  class Project;

  /**
@@ -57,6 +60,9 @@ namespace Isis {
   *                           dialog display anytime that a bundle adjust is re-ran. Fixes #4808.
   *   @history 2017-04-27 Ian Humphrey - Modified to track the last used control net to properly
   *                           update the jigsaw setup dialog's cnet combo box. References #4817.
   *   @history 2017-05-04 Ian Humphrey & Makayla Shepherd - Updated acceptBundleResults()
   *                           to concurrently save the bundled images (ecub's) to the project.
   *                           Fixes #4804, #4837.
   */
  class JigsawDialog : public QDialog {
    Q_OBJECT
@@ -92,6 +98,25 @@ namespace Isis {
    QPushButton *m_close; /**< Dialog's close button that is used to close the dialog. */
    QPushButton *m_reject; /**< Dialog's reject button that is used to discard the results. */

    /**
     * Functor used to copy images to a specified destination directory. This is used by
     * a QtConcurrent::mapped call in acceptBundleResults().
     *
     * @author 2017-05-04 Ian Humphrey
     *
     * @internal
     */
    class CopyImageToResultsFunctor :
        public std::unary_function<const FileName &, Cube *> {
      public:
        CopyImageToResultsFunctor(const QDir &destination);
        ~CopyImageToResultsFunctor();
        Cube *operator()(const FileName &image);
      private:
        CopyImageToResultsFunctor &operator=(const CopyImageToResultsFunctor &other);
        QDir m_destinationFolder; /**< Directory to copy the image to. */
    };

  private slots:
    void on_JigsawSetupButton_pressed();
    void on_JigsawRunButton_clicked();