Commit f2d0218f authored by Jesse Mapel's avatar Jesse Mapel
Browse files

Added additional output statistics to the checkfit application.

parent e2cb6142
Loading
Loading
Loading
Loading
+114 −23
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <QPair>
#include <QString>
#include <QTextStream>
#include <QVector>

#include "Camera.h"
#include "Cube.h"
@@ -24,7 +25,8 @@
using namespace std;
using namespace Isis;

QPair<double, double> testFit(FileName inCubeFile, int positionDegree, int positionSegments,
QVector< QPair<double, double> > testFit(FileName inCubeFile,
                                         int positionDegree, int positionSegments,
                                         int pointingDegree, int pointingSegments);

void IsisMain() {
@@ -41,7 +43,7 @@ void IsisMain() {
  int pointingSegments = ui.GetInteger("CKSEGMENTS");

  // Setup the map for storing fit quality
  QMap<QString, QPair<double, double> > qualityMap;
  QMap<QString, QVector< QPair<double, double> > > qualityMap;

  // Setup the progress tracker
  Progress cubeProgress;
@@ -51,7 +53,7 @@ void IsisMain() {
  // Compute a test fit for each cube
  for (int cubeIndex = 0; cubeIndex < cubeList.size(); cubeIndex++) {
    FileName cubeFileName = cubeList[cubeIndex];
    QPair<double, double> fitQuality;
    QVector< QPair<double, double> > fitQuality;
    try {
      cubeProgress.CheckStatus();
      fitQuality = testFit(cubeFileName,
@@ -72,14 +74,30 @@ void IsisMain() {
  if (outFile.open(QFile::WriteOnly |QFile::Truncate)) {
    QTextStream outWriter(&outFile);
    // Output the header
    outWriter << "Cube, Position Error (km), Pointing Error (Rad)\n";
    outWriter << "Cube,"
              << "Position Segments,Position Fit Degree,Minimum Position Error,"
              << "Median Position Error,Maximum Position Error,RMS Position Error,"
              << "Mean Position Error,Standard Deviation of Position Error,"
              << "Chebyshev Minimum Position Error,Chebyshev Maximum Position Error,"
              << "Pointing Segments,Pointing Fit Degree,Minimum Pointing Error,"
              << "Median Pointing Error,Maximum Pointing Error,RMS Pointing Error,"
              << "Mean Pointing Error,Standard Deviation of Pointing Error,"
              << "Chebyshev Minimum Pointing Error,Chebyshev Maximum Pointing Error"
              << "\n";
    QList<QString> cubeNames = qualityMap.keys();
    for (int i = 0; i < cubeNames.size(); i++) {
      QString cubeName = cubeNames[i];
      QPair<double, double> fitQuality = qualityMap.value(cubeName);
      outWriter << cubeName << ", "
                << toString(fitQuality.first) << ", "
                << toString(fitQuality.second) << "\n";
      QVector< QPair<double, double> > fitQuality = qualityMap.value(cubeName);
      outWriter << cubeName;
      // Output Position Error Stats
      for (int j = 0; j < fitQuality.size(); j++) {
        outWriter  << "," << toString(fitQuality[j].first);
      }
      // Output Pointing Error Stats
      for (int j = 0; j < fitQuality.size(); j++) {
        outWriter  << "," << toString(fitQuality[j].second);
      }
      outWriter << "\n";
    }
  }
  else {
@@ -88,31 +106,104 @@ void IsisMain() {
  }
}

QPair<double, double> testFit(FileName inCubeFile, int positionDegree, int positionSegments,
/**
 * <p>
 * Computes the position and pointing fit error, then outputs statistics on
 * them. The statistics are output as a vector of pairs. Each element of the
 * vector contains a pair of values for a specific statistic. The first value
 * is the value of the statistic for position error in km. The second value is
 * the value of the statistic for pointing error in radians.
 * </p>
 * <p>
 * The output statistics are:
 * </p>
 * <ol>
 *   <li>Number of Segments</li>
 *   <li>Min Error</li>
 *   <li>Median Error</li>
 *   <li>Maximum Error</li>
 *   <li>RMS Error</li>
 *   <li>Mean Error</li>
 *   <li>Standard Deviation of the Error</li>
 *   <li>Chebyshev Minimum Error</li>
 *   <li>Chebyshev Maximum Error</li>
 * </ol>
 * 
 * @param inCubeFile The cube file to test
 * @param positionDegree The degree of the position fit
 * @param positionSegments The number of segments used in the position fit.
 * @param pointingDegree The degree of the pointing fit
 * @param pointingSegments The number of segments used in the pointing fit.
 * 
 * @return @b QVector<QPair<double,double>> A vector containing pairs of
 *                                          statistic values for the position
 *                                          and pointing error in km and
 *                                          radians respectively.
 */
QVector< QPair<double, double> > testFit(FileName inCubeFile,
                                         int positionDegree, int positionSegments,
                                         int pointingDegree, int pointingSegments) {
  // TODO validate these pointers
  Cube inCube(inCubeFile);
  Camera *inCam = inCube.camera();
  SpicePosition *instPosition = inCam->instrumentPosition();
  SpiceRotation *instRotation = inCam->instrumentRotation();

  // Fit the position
  instPosition->SetPolynomialDegree(positionDegree);
  instPosition->setPolynomialSegments(positionSegments);
  PiecewisePolynomial positionPoly = instPosition->fitPolynomial(positionDegree, positionSegments);
  PiecewisePolynomial positionPoly;
  try {
    positionPoly = instPosition->fitPolynomial(positionDegree, positionSegments);
  }
  catch (IException &e) {
    QString msg = "Failed Fitting Instrument Position.";
    throw IException(e, IException::Unknown, msg, _FILEINFO_);
  }

  // Fit the rotation
  instRotation->SetPolynomialDegree(pointingDegree);
  instRotation->setPolynomialSegments(pointingSegments);
  PiecewisePolynomial rotationPoly = instRotation->fitPolynomial(pointingDegree, pointingSegments);
  PiecewisePolynomial rotationPoly;
  try {
    rotationPoly = instRotation->fitPolynomial(pointingDegree, pointingSegments);
  }
  catch (IException &e) {
    QString msg = "Failed Fitting Instrument Pointing.";
    throw IException(e, IException::Unknown, msg, _FILEINFO_);
  }

  // Compute the position RMS
  // Calculate and store the error statistics
  QVector< QPair<double, double> > fitStats;
  Histogram positionHist = instPosition->computeError(positionPoly);
  double positionRMS = positionHist.Rms();

  // Compute the rotation RMS
  Histogram rotationHist = instRotation->computeError(rotationPoly);
  double rotationRMS = rotationHist.Rms();

  return QPair<double, double>(positionRMS, rotationRMS);
  // Number of Segments
  fitStats.push_back( QPair<double, double>( positionPoly.segments(), rotationPoly.segments() ) );

  // Fit Degree
  fitStats.push_back( QPair<double, double>( positionPoly.degree(), rotationPoly.degree() ) );

  // Min Error
  fitStats.push_back( QPair<double, double>( positionHist.Minimum(), rotationHist.Minimum() ) );

  // Median Error
  fitStats.push_back( QPair<double, double>( positionHist.Median(), rotationHist.Median() ) );

  // Maximum Error
  fitStats.push_back( QPair<double, double>( positionHist.Maximum(), rotationHist.Maximum() ) );

  // RMS Error
  fitStats.push_back( QPair<double, double>( positionHist.Rms(), rotationHist.Rms() ) );

  // Mean Error
  fitStats.push_back( QPair<double, double>( positionHist.Average(), rotationHist.Average() ) );

  // Standard Deviation of the Error
  fitStats.push_back( QPair<double, double>( positionHist.StandardDeviation(), rotationHist.StandardDeviation() ) );

  // Chebyshev Minimum Error
  fitStats.push_back( QPair<double, double>( positionHist.ChebyshevMinimum(), rotationHist.ChebyshevMinimum() ) );

  // Chebyshev Maximum Error
  fitStats.push_back( QPair<double, double>( positionHist.ChebyshevMaximum(), rotationHist.ChebyshevMaximum() ) );

  return fitStats;
}
+4 −5
Original line number Diff line number Diff line
@@ -51,14 +51,13 @@
        <type>filename</type>
        <fileMode>output</fileMode>
        <brief>
          Output file that contains the quality of fits
          Output file that contains information about the quality of fits.
        </brief>
        <description>
          This text file will contain the quality of fit for each input cube.
          The first column is the cube name, the second column is the RMS error
          of the instrument position fit in kilometers, and the third column is
          the RMS error of the instrument pointing fit in radians. Any cubes
          for which the process fails will not be included in this output file.
          Each row contains information and statistics about the instrument
          position and pointing fit. If there is an existing file with the same
          name, then it will be overwritten.
        </description>
        <filter>
          *.txt, *.csv
+2 −0
Original line number Diff line number Diff line
@@ -2392,6 +2392,8 @@ namespace Isis {
        measuredAngle[2] = WrapAngle(start3, measuredAngle[2]);
      }
      polyAngle = poly.evaluate( (sampleTimes[i] - p_baseTime) / p_timeScale );
      polyAngle[0] = WrapAngle(start1, polyAngle[0]);
      polyAngle[2] = WrapAngle(start3, polyAngle[2]);
      error += (measuredAngle[0] - polyAngle[0]) * (measuredAngle[0] - polyAngle[0]);
      error += (measuredAngle[1] - polyAngle[1]) * (measuredAngle[1] - polyAngle[1]);
      error += (measuredAngle[2] - polyAngle[2]) * (measuredAngle[2] - polyAngle[2]);