Commit 9a2f20c2 authored by Tracie Sucharski's avatar Tracie Sucharski
Browse files

Save/Restore of BundleSolutionInfo to project and restore on the project tree. Fixes #4822.

parent 34d176ff
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -484,7 +484,7 @@ namespace Isis {
   * Prints out information about which tier the solution is in and the status of the residuals.
   */
  void BundleResults::printMaximumLikelihoodTierInformation() {
    printf("Maximum Likelihood Tier: %d\n", m_maximumLikelihoodIndex);
//  printf("Maximum Likelihood Tier: %d\n", m_maximumLikelihoodIndex);
    if (numberMaximumLikelihoodModels() > m_maximumLikelihoodIndex) {
      // if maximum likelihood estimation is being used
      // at the end of every iteration
@@ -494,7 +494,7 @@ namespace Isis {
      m_maximumLikelihoodFunctions[m_maximumLikelihoodIndex].first.setTweakingConstant(tc);
      //  print meadians of residuals
      m_maximumLikelihoodMedianR2Residuals = m_cumPro->value(0.5);
      printf("Median of R^2 residuals:  %lf\n", m_maximumLikelihoodMedianR2Residuals);
//    printf("Median of R^2 residuals:  %lf\n", m_maximumLikelihoodMedianR2Residuals);

      //restart the dynamic calculation of the cumulative probility distribution of |R^2 residuals|
      // so it will be up to date for the next iteration
+199 −147
Original line number Diff line number Diff line
@@ -155,44 +155,6 @@ namespace Isis {
  }


  /**
   * Saves the BundleSolutionInfo to the project
   *
   * @param stream The stream to which the BundleSolutionInfo will be saved
   * @param project The project to which this BundleSolutionInfo will be saved
   */
  void BundleSolutionInfo::save(QXmlStreamWriter &stream, const Project *project) const {

    stream.writeStartElement("bundleSolutionInfo");
    // save ID, cnet file name, and run time to stream
    stream.writeStartElement("generalAttributes");
    stream.writeTextElement("id", m_id->toString());
    stream.writeTextElement("runTime", runTime());
    stream.writeTextElement("fileName", m_controlNetworkFileName->expanded());
    stream.writeTextElement("imagesCSV", m_csvSavedImagesFilename);
    stream.writeTextElement("pointsCSV", m_csvSavedPointsFilename);
    stream.writeTextElement("residualsCSV", m_csvSavedResidualsFilename);
    stream.writeEndElement(); // end general attributes

    // save settings to stream
    m_settings->save(stream, project);

    // save statistics to stream
    m_statisticsResults->save(stream, project);

    // save image lists to stream
    if ( m_images && !m_images->isEmpty() ) {
      stream.writeStartElement("imageLists");

      for (int i = 0; i < m_images->count(); i++) {
        m_images->at(i)->save(stream, project, "");
      }

      stream.writeEndElement();
    }
    stream.writeEndElement(); //end bundleSolutionInfo
  }

  /**
   * Change the on-disk file name for the control network used to be where the control network
   * ought to be in the given project.
@@ -214,115 +176,6 @@ namespace Isis {
  }



  /**
   * Create an XML Handler (reader) that can populate the BundleSolutionInfo class data. See
   *   BundleSolutionInfo::save() for the expected format.
   *
   * @param bundleSolutionInfo The bundle solution we're going to be initializing
   * @param project The project we are working in
   */
  BundleSolutionInfo::XmlHandler::XmlHandler(BundleSolutionInfo *bundleSolutionInfo,
                                             Project *project) {
    m_xmlHandlerBundleSolutionInfo = bundleSolutionInfo;
    m_xmlHandlerProject = project;
    m_xmlHandlerCharacters = "";
  }


  /**
   * Destructor
   */
  BundleSolutionInfo::XmlHandler::~XmlHandler() {
  }


  /**
   * Handle an XML start element. This expects <image/> and <displayProperties/> elements.
   *
   * @param namespaceURI ???
   * @param localName The keyword name given to the member variable in the XML.
   * @param qName ???
   * @param atts The attribute containing the keyword value for the given local name.
   *
   * @return @b bool True if we should continue reading the XML.
   */
  bool BundleSolutionInfo::XmlHandler::startElement(const QString &namespaceURI,
                                                    const QString &localName,
                                                    const QString &qName,
                                                    const QXmlAttributes &atts) {
    m_xmlHandlerCharacters = "";

    if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {

      if (localName == "bundleSettings") {
        m_xmlHandlerBundleSolutionInfo->m_settings =
            BundleSettingsQsp(new BundleSettings(m_xmlHandlerProject, reader()));
      }
      else if (localName == "bundleResults") {
        m_xmlHandlerBundleSolutionInfo->m_statisticsResults = new BundleResults(m_xmlHandlerProject, reader());
      }
      else if (localName == "imageList") {
        m_xmlHandlerBundleSolutionInfo->m_images->append(new ImageList(m_xmlHandlerProject, reader()));
      }
    }
    return true;
  }


  /**
   * Adds characters to m_xmlHandlerCharacters
   *
   * @param ch QString of characters to add
   *
   * @return @b bool Almost always true. Only false if the characters cannot be read
   */
  bool BundleSolutionInfo::XmlHandler::characters(const QString &ch) {
    m_xmlHandlerCharacters += ch;
    return XmlStackedHandler::characters(ch);
  }


  /**
   * Handle an XML end element.
   *
   * @param namespaceURI ???
   * @param localName The keyword name given to the member variable in the XML.
   * @param qName ???
   *
   * @return @b bool Returns XmlStackedHandler's endElement()
   */
  bool BundleSolutionInfo::XmlHandler::endElement(const QString &namespaceURI,
                                                  const QString &localName,
                                                  const QString &qName) {
    if (localName == "id") {
      // all constructors assign a Uuid - we need to give it a one from the XML
      assert(m_xmlHandlerBundleSolutionInfo->m_id);
      delete m_xmlHandlerBundleSolutionInfo->m_id;
      m_xmlHandlerBundleSolutionInfo->m_id = new QUuid(m_xmlHandlerCharacters);
    }
    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(m_xmlHandlerCharacters);
    }
    else if (localName == "imagesCSV") {
      m_xmlHandlerBundleSolutionInfo->m_csvSavedImagesFilename = m_xmlHandlerCharacters;
    }
    else if (localName == "pointsCSV") {
      m_xmlHandlerBundleSolutionInfo->m_csvSavedPointsFilename = m_xmlHandlerCharacters;
    }
    else if (localName == "residualsCSV") {
      m_xmlHandlerBundleSolutionInfo->m_csvSavedResidualsFilename = m_xmlHandlerCharacters;
    }

    m_xmlHandlerCharacters = "";
    return XmlStackedHandler::endElement(namespaceURI, localName, qName);
  }


  /**
   * Get a unique, identifying string associated with this BundleSolutionInfo object.
   *
@@ -1545,4 +1398,203 @@ namespace Isis {

    return true;
  }


  /**
   * Saves the BundleSolutionInfo to the project
   *
   * Output format:
   *
   *
   * <image id="..." fileName="...">
   *   ...
   * </image>
   *
   * (fileName attribute is just the base name)
   *
   * @param stream The stream to which the BundleSolutionInfo will be saved
   * @param project The project to which this BundleSolutionInfo will be saved
   * @param newProjectRoot The location of the project root directory. This is not used.
   */
  void BundleSolutionInfo::save(QXmlStreamWriter &stream, const Project *project,
                                FileName newProjectRoot) const {

    stream.writeStartElement("bundleSolutionInfo");
    // save ID, cnet file name, and run time to stream
    stream.writeStartElement("generalAttributes");
    stream.writeTextElement("id", m_id->toString());
    stream.writeTextElement("runTime", runTime());
    stream.writeTextElement("fileName", m_controlNetworkFileName->expanded());
    stream.writeTextElement("imagesCSV", m_csvSavedImagesFilename);
    stream.writeTextElement("pointsCSV", m_csvSavedPointsFilename);
    stream.writeTextElement("residualsCSV", m_csvSavedResidualsFilename);
    stream.writeEndElement(); // end general attributes

    // save settings to stream
    m_settings->save(stream, project);

    // save statistics to stream
    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";
      for (int i = 0; i < m_images->count(); i++) {
        m_images->at(i)->save(stream, project, "");
      }

      stream.writeEndElement();
    }
    stream.writeEndElement(); //end bundleSolutionInfo
  }

#if 0
  /**
   * Saves the BundleSolutionInfo to the project
   *
   * @param stream The stream to which the BundleSolutionInfo will be saved
   * @param project The project to which this BundleSolutionInfo will be saved
   */
  void BundleSolutionInfo::save(QXmlStreamWriter &stream, const Project *project) const {

    stream.writeStartElement("bundleSolutionInfo");
    // save ID, cnet file name, and run time to stream
    stream.writeStartElement("generalAttributes");
    stream.writeTextElement("id", m_id->toString());
    stream.writeTextElement("runTime", runTime());
    stream.writeTextElement("fileName", m_controlNetworkFileName->expanded());
    stream.writeTextElement("imagesCSV", m_csvSavedImagesFilename);
    stream.writeTextElement("pointsCSV", m_csvSavedPointsFilename);
    stream.writeTextElement("residualsCSV", m_csvSavedResidualsFilename);
    stream.writeEndElement(); // end general attributes

    // save settings to stream
    m_settings->save(stream, project);

    // save statistics to stream
    m_statisticsResults->save(stream, project);

    // save image lists to stream
    if ( m_images && !m_images->isEmpty() ) {
      stream.writeStartElement("imageLists");

      for (int i = 0; i < m_images->count(); i++) {
        m_images->at(i)->save(stream, project, "");
      }

      stream.writeEndElement();
    }
    stream.writeEndElement(); //end bundleSolutionInfo
  }
#endif

  /**
   * Create an XML Handler (reader) that can populate the BundleSolutionInfo class data. See
   *   BundleSolutionInfo::save() for the expected format.
   *
   * @param bundleSolutionInfo The bundle solution we're going to be initializing
   * @param project The project we are working in
   */
  BundleSolutionInfo::XmlHandler::XmlHandler(BundleSolutionInfo *bundleSolutionInfo,
                                             Project *project) {
    m_xmlHandlerBundleSolutionInfo = bundleSolutionInfo;
    m_xmlHandlerProject = project;
    m_xmlHandlerCharacters = "";
  }


  /**
   * Destructor
   */
  BundleSolutionInfo::XmlHandler::~XmlHandler() {
  }


  /**
   * Adds characters to m_xmlHandlerCharacters
   *
   * @param ch QString of characters to add
   *
   * @return @b bool Almost always true. Only false if the characters cannot be read
   */
  bool BundleSolutionInfo::XmlHandler::characters(const QString &ch) {
    m_xmlHandlerCharacters += ch;
    return XmlStackedHandler::characters(ch);
  }


  /**
   * Handle an XML start element. This expects <image/> and <displayProperties/> elements.
   *
   * @param namespaceURI ???
   * @param localName The keyword name given to the member variable in the XML.
   * @param qName ???
   * @param atts The attribute containing the keyword value for the given local name.
   *
   * @return @b bool True if we should continue reading the XML.
   */
  bool BundleSolutionInfo::XmlHandler::startElement(const QString &namespaceURI,
                                                    const QString &localName,
                                                    const QString &qName,
                                                    const QXmlAttributes &atts) {
    m_xmlHandlerCharacters = "";

    if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {

      if (localName == "bundleSettings") {
        m_xmlHandlerBundleSolutionInfo->m_settings =
            BundleSettingsQsp(new BundleSettings(m_xmlHandlerProject, reader()));
      }
      else if (localName == "bundleResults") {
        m_xmlHandlerBundleSolutionInfo->m_statisticsResults = new BundleResults(m_xmlHandlerProject, reader());
      }
      else if (localName == "imageList") {
        m_xmlHandlerBundleSolutionInfo->m_images->append(new ImageList(m_xmlHandlerProject, reader()));
      }
    }
    return true;
  }


  /**
   * Handle an XML end element.
   *
   * @param namespaceURI ???
   * @param localName The keyword name given to the member variable in the XML.
   * @param qName ???
   *
   * @return @b bool Returns XmlStackedHandler's endElement()
   */
  bool BundleSolutionInfo::XmlHandler::endElement(const QString &namespaceURI,
                                                  const QString &localName,
                                                  const QString &qName) {
    if (localName == "id") {
      // all constructors assign a Uuid - we need to give it a one from the XML
      assert(m_xmlHandlerBundleSolutionInfo->m_id);
      delete m_xmlHandlerBundleSolutionInfo->m_id;
      m_xmlHandlerBundleSolutionInfo->m_id = new QUuid(m_xmlHandlerCharacters);
    }
    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(m_xmlHandlerCharacters);
    }
    else if (localName == "imagesCSV") {
      m_xmlHandlerBundleSolutionInfo->m_csvSavedImagesFilename = m_xmlHandlerCharacters;
    }
    else if (localName == "pointsCSV") {
      m_xmlHandlerBundleSolutionInfo->m_csvSavedPointsFilename = m_xmlHandlerCharacters;
    }
    else if (localName == "residualsCSV") {
      m_xmlHandlerBundleSolutionInfo->m_csvSavedResidualsFilename = m_xmlHandlerCharacters;
    }

    m_xmlHandlerCharacters = "";
    return XmlStackedHandler::endElement(namespaceURI, localName, qName);
  }
}
+5 −2
Original line number Diff line number Diff line
@@ -98,6 +98,9 @@ namespace Isis {
   *                           project tree under results/bundle/<runtime> and will keep the same
   *                           structure as the input on the project tree. Fixes #4818.
   *   @history 2017-05-02 J Bonn - Fixed XML serialzation and code cleanup.  #4835
   *   @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.
   */
  class BundleSolutionInfo : public QObject {
    Q_OBJECT
@@ -132,8 +135,8 @@ namespace Isis {
      bool outputPointsCSV();
      bool outputResiduals();

       //void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const;
      void save(QXmlStreamWriter &stream, const Project *project) const;
      void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const;
//    void save(QXmlStreamWriter &stream, const Project *project) const;

    public slots:
      void updateFileName(Project *);
+3 −3
Original line number Diff line number Diff line
@@ -158,7 +158,7 @@ int main(int argc, char *argv[]) {
    writer.setAutoFormatting(true);
    writer.writeStartDocument();
    Project *project = NULL;
    results.save(writer, project);
    results.save(writer, project, "");
    writer.writeEndDocument();
    qXmlFile1.close();

@@ -303,7 +303,7 @@ int main(int argc, char *argv[]) {
    QXmlStreamWriter writer2(&qXmlFile2);
    writer2.setAutoFormatting(true);
    writer2.writeStartDocument();
    results.save(writer2, project);
    results.save(writer2, project, "");
    writer2.writeEndDocument();
    qXmlFile2.close();

@@ -349,7 +349,7 @@ void printXml(const BundleSolutionInfo &printable) {
  QString output;
  QXmlStreamWriter writer(&output);
  writer.setAutoFormatting(true);
  printable.save(writer, NULL);
  printable.save(writer, NULL, "");
  // Note Statistics class does not serialize/restore properly as of 2017-04-27
  output.remove(QRegExp("<statistics>.*</statistics>"));
  output.remove(QRegExp("<id>[^<]*</id>"));
+31 −46
Original line number Diff line number Diff line
@@ -418,8 +418,6 @@ namespace Isis {

      connect( result, SIGNAL( destroyed(QObject *) ),
               this, SLOT( imageListDeleted(QObject *) ) );
      //TODO  07-29-14  Kim & Tracie commented this out.  Didn't seem like it was necessary.
      //      If problems, need to understand this code better.
      m_images->append(result);
    }
    return result;
@@ -499,22 +497,11 @@ namespace Isis {
//  stream.writeAttribute("state", layout_data.toString());


    // if ( !m_bundleSolutionInfo->isEmpty() ) {
    //   stream.writeStartElement("bundleSolutionInfo");
    //
    //   for (int i = 0; i < m_bundleSolutionInfo->count(); i++) {
    //     m_bundleSolutionInfo->at(i)->save(stream, this, newProjectRoot);
    //   }
    //
    //   stream.writeEndElement();
    // }

    // should we write the runtimes of the runs here???
    if ( !m_bundleSolutionInfo->isEmpty() ) {
      stream.writeStartElement("bundleRuns");
      stream.writeStartElement("results");

      for (int i = 0; i < m_bundleSolutionInfo->count(); i++) {
        m_bundleSolutionInfo->at(i)->runTime();
        m_bundleSolutionInfo->at(i)->save(stream, this, newProjectRoot);
      }

      stream.writeEndElement();
@@ -621,27 +608,6 @@ namespace Isis {
  }


  /**
   * Create and return the name of a folder for placing BundleSolutionInfo.
   *
   * TODO: don't know if sentence below is accurate.
   * This can be called from multiple threads, but should only be called by one thread at a time.
   */
  QDir Project::addBundleSolutionInfoFolder(QString folder) {
    QDir bundleSolutionInfoFolder(bundleSolutionInfoRoot());

    if (!bundleSolutionInfoFolder.mkpath(folder)) {
      throw IException(IException::Io,
                       tr("Could not create bundle results directory [%1] in [%2].")
                       .arg(folder).arg(bundleSolutionInfoFolder.absolutePath()),
                       _FILEINFO_);
    }

    bundleSolutionInfoFolder.cd(folder);
    return bundleSolutionInfoFolder;
  }


  /**
   * Create and return the name of a folder for placing control networks.
   *
@@ -817,13 +783,33 @@ namespace Isis {
  }


  /**
   * Create and return the name of a folder for placing BundleSolutionInfo.
   *
   * TODO: don't know if sentence below is accurate.
   * This can be called from multiple threads, but should only be called by one thread at a time.
   */
  QDir Project::addBundleSolutionInfoFolder(QString folder) {
    QDir bundleSolutionInfoFolder(bundleSolutionInfoRoot());

    if (!bundleSolutionInfoFolder.mkpath(folder)) {
      throw IException(IException::Io,
                       tr("Could not create bundle results directory [%1] in [%2].")
                       .arg(folder).arg(bundleSolutionInfoFolder.absolutePath()),
                       _FILEINFO_);
    }

    bundleSolutionInfoFolder.cd(folder);
    return bundleSolutionInfoFolder;
  }


  /**
   * Add the given BundleSolutionInfo to the current project. This will cause the
   * BundleSolutionInfo to be saved/restored from disk, Project-related GUIs to display the
   * BundleSolutionInfo, and enable access to the BundleSolutionInfo given access to the project.
   */
  void Project::addBundleSolutionInfo(BundleSolutionInfo *bundleSolutionInfo) {

    connect(bundleSolutionInfo, SIGNAL(destroyed(QObject *)),
            this, SLOT(bundleSolutionInfoClosed(QObject *)));//???
    connect(this, SIGNAL(projectRelocated(Project *)),
@@ -1724,6 +1710,7 @@ namespace Isis {
    saveWarnings(warningsWriter);
    warningsWriter.writeEndDocument();

    //  Save the Directory structure
    QFile directoryStateFile(newPath.toString() + "/directory.xml");
    if (!directoryStateFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
      throw IException(IException::Io,
@@ -2184,12 +2171,8 @@ namespace Isis {
//    restoreState(layout_data);
      }

      else if (localName == "bundleSettings") {
        BundleSettings *bundleSettings = m_project->bundleSettings();
        if (!bundleSettings) {
          // throw error???
        }
//      bundleSettings = new BundleSettings(m_project, reader());
      else if (localName == "bundleSolutionInfo") {
        m_bundleSolutionInfos.append(new BundleSolutionInfo(m_project, reader()));
      }
      else if (localName == "activeImageList") {
        QString displayName = atts.value("displayName");
@@ -2243,8 +2226,10 @@ namespace Isis {
      }
      m_controls.clear();
    }
    else if (localName == "bundleSettings") {
      // TODO: what to do here????
    else if (localName == "results") {
      foreach (BundleSolutionInfo *bundleInfo, m_bundleSolutionInfos) {
        m_project->addBundleSolutionInfo(bundleInfo);
      }
    }

    return XmlStackedHandler::endElement(namespaceURI, localName, qName);
Loading