9 #include "BundleSolutionInfo.h" 
   11 #include <QDataStream> 
   16 #include <QStringList> 
   18 #include <QXmlStreamWriter> 
   20 #include "BundleResults.h" 
   22 #include "ControlList.h" 
   23 #include "ControlMeasure.h" 
   24 #include "ControlNet.h" 
   25 #include "ControlPoint.h" 
   27 #include "ImageList.h" 
   31 #include "PvlKeyword.h" 
   32 #include "PvlObject.h" 
   33 #include "StatCumProbDistDynCalc.h" 
   34 #include "Statistics.h" 
   35 #include "XmlStackedHandlerReader.h" 
   52     m_id = 
new QUuid(QUuid::createUuid());
 
   57     m_outputControlName=
"";
 
   72   BundleSolutionInfo::BundleSolutionInfo(
Project *project,
 
   76     m_id = 
new QUuid(QUuid::createUuid());
 
   81     m_outputControlName=
"";
 
   87     xmlReader->setErrorHandler(
new XmlHandler(
this, project));
 
  127     return m_txtBundleOutputFilename;
 
  137     return m_csvSavedImagesFilename;
 
  147     return m_csvSavedPointsFilename;
 
  157     return m_csvSavedResidualsFilename;
 
  201                      oldInputFileName.
dir().dirName() + 
"/" + oldInputFileName.
name());
 
  206                      oldOutputFileName.
dir().dirName() + 
"/" + oldOutputFileName.
name());
 
  212     m_outputControlName = newOutputFileName.
expanded();
 
  233     return m_id->toString().remove(QRegExp(
"[{}]"));
 
  289       return m_outputControlName;
 
  309     m_outputControlName = 
name;
 
  319     return m_outputControlName;
 
  355                        "Results for this bundle is NULL.",
 
  412     std::vector<QString> outputColumns;
 
  414     outputColumns.push_back(
"Image,");
 
  415     outputColumns.push_back(
"rms,");
 
  416     outputColumns.push_back(
"rms,");
 
  417     outputColumns.push_back(
"rms,");
 
  419     QStringList observationParameters = observation->parameterList();
 
  421     for (
int i = 0; i < observationParameters.size(); i++) {
 
  422       for (
int j = 0; j < 5; j++) {
 
  423         outputColumns.push_back(observationParameters[i] + 
",");
 
  428     int ncolumns = outputColumns.size();
 
  429     for (
int i = 0; i < ncolumns; i++) {
 
  430       QString str = outputColumns.at(i);
 
  431       sprintf(buf, 
"%s", (
const char*)str.toLatin1().data());
 
  437     outputColumns.clear();
 
  439     outputColumns.push_back(
"Filename,");
 
  440     outputColumns.push_back(
"sample res,");
 
  441     outputColumns.push_back(
"line res,");
 
  442     outputColumns.push_back(
"total res,");
 
  444     for (
int i = 0; i < observationParameters.size(); i++) {
 
  445       outputColumns.push_back(
"Initial,");
 
  446       outputColumns.push_back(
"Correction,");
 
  447       outputColumns.push_back(
"Final,");
 
  448       outputColumns.push_back(
"Apriori Sigma,");
 
  449       outputColumns.push_back(
"Adj Sigma,");
 
  453     ncolumns = outputColumns.size();
 
  454     for (
int i = 0; i < ncolumns; i++) {
 
  455       QString str = outputColumns.at(i);
 
  456       sprintf(buf, 
"%s", (
const char*)str.toLatin1().data());
 
  488     for (
int i = 0; i < numObservations; i++) {
 
  492     int numInnerConstraints = 0;
 
  493     int numDistanceConstraints = 0;
 
  500     int convergenceCriteria = 1;
 
  502     sprintf(buf, 
"JIGSAW: BUNDLE ADJUSTMENT\n=========================\n");
 
  504     sprintf(buf, 
"\n                       Run Time: %s",
 
  507     sprintf(buf, 
"\n                       Network Filename: %s",
 
  511     sprintf(buf,
"\n                       Cube List: %s",
 
  512                 m_settings->cubeList().toStdString().c_str() );
 
  516     sprintf(buf, 
"\n                       Output Network Filename: %s",
 
  519     sprintf(buf,
"\n                       Output File Prefix: %s",
 
  520                 m_settings->outputFilePrefix().toStdString().c_str() );
 
  523     sprintf(buf, 
"\n                       Network Id: %s",
 
  526     sprintf(buf, 
"\n                       Network Description: %s",\
 
  529     sprintf(buf, 
"\n                       Target: %s",
 
  532     sprintf(buf, 
"\n\n                       Linear Units: kilometers");
 
  534     sprintf(buf, 
"\n                       Angular Units: decimal degrees");
 
  536     sprintf(buf, 
"\n\nINPUT: SOLVE OPTIONS\n====================\n");
 
  540       sprintf(buf, 
"\n                   OBSERVATIONS: ON"):
 
  541       sprintf(buf, 
"\n                   OBSERVATIONS: OFF");
 
  545       sprintf(buf, 
"\n                         RADIUS: ON"):
 
  546       sprintf(buf, 
"\n                         RADIUS: OFF");
 
  550       sprintf(buf, 
"\n                    TARGET BODY: ON"):
 
  551       sprintf(buf, 
"\n                    TARGET BODY: OFF");
 
  555       sprintf(buf, 
"\n                         UPDATE: YES"):
 
  556       sprintf(buf, 
"\n                         UPDATE: NO");
 
  560       sprintf(buf, 
"\n              ERROR PROPAGATION: ON"):
 
  561       sprintf(buf, 
"\n              ERROR PROPAGATION: OFF");
 
  565       sprintf(buf, 
"\n  CONTROL POINT COORDINATE TYPE FOR REPORTS: LATITUDINAL"):
 
  566       sprintf(buf, 
"\n  CONTROL POINT COORDINATE TYPE FOR REPORTS: RECTANGULAR");
 
  570       sprintf(buf, 
"\n  CONTROL POINT COORDINATE TYPE FOR BUNDLE: LATITUDINAL"):
 
  571       sprintf(buf, 
"\n  CONTROL POINT COORDINATE TYPE FOR BUNDLE: RECTANGULAR");
 
  575       sprintf(buf, 
"\n              OUTLIER REJECTION: ON");
 
  577       sprintf(buf, 
"\n           REJECTION MULTIPLIER: %lf",
 
  583       sprintf(buf, 
"\n              OUTLIER REJECTION: OFF");
 
  585       sprintf(buf, 
"\n           REJECTION MULTIPLIER: N/A");
 
  590     sprintf(buf, 
"\n              CONTROL POINT COORDINATE TYPE FOR REPORTS:  %s",
 
  594     sprintf(buf, 
"\n              CONTROL POINT COORDINATE TYPE FOR BUNDLE:  %s",
 
  597     sprintf(buf, 
"\n\nMAXIMUM LIKELIHOOD ESTIMATION\n============================\n");
 
  600     for (
int tier = 0; tier < 3; tier++) {
 
  601       if (tier < m_statisticsResults->numberMaximumLikelihoodModels()) {
 
  602         sprintf(buf, 
"\n                         Tier %d Enabled: TRUE", tier);
 
  604         sprintf(buf, 
"\n               Maximum Likelihood Model: %s",
 
  607                               maximumLikelihoodModelWFunc(tier).model()).toLatin1().data());
 
  609         sprintf(buf, 
"\n    Quantile used for tweaking constant: %lf",
 
  612         sprintf(buf, 
"\n   Quantile weighted R^2 Residual value: %lf",
 
  615         sprintf(buf, 
"\n       Approx. weighted Residual cutoff: %s",
 
  619         if (tier != 2) fpOut << 
"\n";
 
  622         sprintf(buf, 
"\n                         Tier %d Enabled: FALSE", tier);
 
  627     sprintf(buf, 
"\n\nINPUT: CONVERGENCE CRITERIA\n===========================\n");
 
  629     sprintf(buf, 
"\n                         SIGMA0: %e",
 
  632     sprintf(buf, 
"\n             MAXIMUM ITERATIONS: %d",
 
  633                   m_settings->convergenceCriteriaMaximumIterations());
 
  647     sprintf(buf, 
"\n\nINPUT: CAMERA POINTING OPTIONS\n==============================\n");
 
  649     switch (pointingSolveDegree) {
 
  651         sprintf(buf,
"\n                          CAMSOLVE: NONE");
 
  654         sprintf(buf,
"\n                          CAMSOLVE: ANGLES");
 
  657         sprintf(buf,
"\n                          CAMSOLVE: ANGLES, VELOCITIES");
 
  660         sprintf(buf,
"\n                          CAMSOLVE: ANGLES, VELOCITIES, ACCELERATIONS");
 
  663         sprintf(buf,
"\n                          CAMSOLVE: ALL POLYNOMIAL COEFFICIENTS (%d)" 
  665                     "\n                     CKSOLVEDEGREE: %d",
 
  673         sprintf(buf, 
"\n                             TWIST: ON"):
 
  674         sprintf(buf, 
"\n                             TWIST: OFF");
 
  677         sprintf(buf, 
"\n POLYNOMIAL OVER EXISTING POINTING: ON"):
 
  678         sprintf(buf, 
"\nPOLYNOMIAL OVER EXISTING POINTING : OFF");
 
  681     sprintf(buf, 
"\n\nINPUT: SPACECRAFT OPTIONS\n=========================\n");
 
  683     switch (positionSolveDegree) {
 
  685         sprintf(buf,
"\n                        SPSOLVE: NONE");
 
  688         sprintf(buf,
"\n                        SPSOLVE: POSITION");
 
  691         sprintf(buf,
"\n                        SPSOLVE: POSITION, VELOCITIES");
 
  694         sprintf(buf,
"\n                        SPSOLVE: POSITION, VELOCITIES, ACCELERATIONS");
 
  697         sprintf(buf,
"\n                        SPSOLVE: ALL POLYNOMIAL COEFFICIENTS (%d)" 
  699                     "\n                 SPKSOLVEDEGREE: %d",
 
  707         sprintf(buf, 
"\n POLYNOMIAL OVER HERMITE SPLINE: ON"):
 
  708         sprintf(buf, 
"\nPOLYNOMIAL OVER HERMITE SPLINE : OFF");
 
  711     sprintf(buf, 
"\n\nINPUT: GLOBAL IMAGE PARAMETER UNCERTAINTIES\n===========================================\n");
 
  715     switch (
m_settings->controlPointCoordTypeReports()) {
 
  717         coord1Str = 
"LATITUDE";
 
  718         coord2Str = 
"LONGITUDE";
 
  719         coord3Str = 
"RADIUS";
 
  727          IString msg =
"Unknown surface point coordinate type enum [" 
  736       sprintf(buf,
"\n               POINT %s SIGMA: N/A", coord1Str.toLatin1().data()):
 
  737       sprintf(buf,
"\n               POINT %s SIGMA: %lf (meters)", coord1Str.toLatin1().data(),
 
  742       sprintf(buf,
"\n              POINT %s SIGMA: N/A", coord2Str.toLatin1().data()):
 
  743       sprintf(buf,
"\n              POINT %s SIGMA: %lf (meters)", coord2Str.toLatin1().data(),
 
  748       sprintf(buf,
"\n                 POINT %s SIGMA: N/A", coord3Str.toLatin1().data()):
 
  749       sprintf(buf,
"\n                 POINT %s SIGMA: %lf (meters)", coord3Str.toLatin1().data(),
 
  752     (positionSolveDegree < 1 || positionSigmas[0] == 
Isis::Null) ?
 
  753         sprintf(buf,
"\n          SPACECRAFT POSITION SIGMA: N/A"):
 
  754         sprintf(buf,
"\n          SPACECRAFT POSITION SIGMA: %lf (meters)",
 
  758     (positionSolveDegree < 2 || positionSigmas[1] == 
Isis::Null) ?
 
  759         sprintf(buf,
"\n          SPACECRAFT VELOCITY SIGMA: N/A"):
 
  760         sprintf(buf,
"\n          SPACECRAFT VELOCITY SIGMA: %lf (m/s)",
 
  764     (positionSolveDegree < 3 || positionSigmas[2] == 
Isis::Null) ?
 
  765         sprintf(buf,
"\n      SPACECRAFT ACCELERATION SIGMA: N/A"):
 
  766         sprintf(buf,
"\n      SPACECRAFT ACCELERATION SIGMA: %lf (m/s/s)",
 
  770     (pointingSolveDegree < 1 || pointingSigmas[0] == 
Isis::Null) ?
 
  771         sprintf(buf,
"\n                CAMERA ANGLES SIGMA: N/A"):
 
  772         sprintf(buf,
"\n                CAMERA ANGLES SIGMA: %lf (dd)",
 
  776     (pointingSolveDegree < 2 || pointingSigmas[1] == 
Isis::Null) ?
 
  777         sprintf(buf,
"\n      CAMERA ANGULAR VELOCITY SIGMA: N/A"):
 
  778         sprintf(buf,
"\n      CAMERA ANGULAR VELOCITY SIGMA: %lf (dd/s)",
 
  782     (pointingSolveDegree < 3 || pointingSigmas[2] == 
Isis::Null) ?
 
  783         sprintf(buf,
"\n  CAMERA ANGULAR ACCELERATION SIGMA: N/A"):
 
  784         sprintf(buf,
"\n  CAMERA ANGULAR ACCELERATION SIGMA: %lf (dd/s/s)",
 
  789       sprintf(buf, 
"\n\nINPUT: TARGET BODY OPTIONS\n==============================\n");
 
  793         sprintf(buf,
"\n                             POLE: RIGHT ASCENSION");
 
  795         sprintf(buf,
"\n                                 : DECLINATION\n");
 
  799         sprintf(buf,
"\n                             POLE: RIGHT ASCENSION\n");
 
  803         sprintf(buf,
"\n                             POLE: DECLINATION\n");
 
  809         sprintf(buf,
"\n                   PRIME MERIDIAN: W0 (OFFSET)");
 
  813           sprintf(buf,
"\n                                 : WDOT (SPIN RATE)");
 
  817           sprintf(buf,
"\n                               :W ACCELERATION");
 
  824           sprintf(buf,
"\n                            RADII: MEAN");
 
  828           sprintf(buf,
"\n                            RADII: TRIAXIAL");
 
  834     sprintf(buf, 
"\n\nJIGSAW: RESULTS\n===============\n");
 
  836     sprintf(buf, 
"\n                         Images: %6d",numImages);
 
  838     sprintf(buf, 
"\n                         Points: %6d",numValidPoints);
 
  841     sprintf(buf, 
"\n                 Total Measures: %6d",
 
  846     sprintf(buf, 
"\n             Total Observations: %6d",
 
  851     sprintf(buf, 
"\n              Good Observations: %6d",
 
  855     sprintf(buf, 
"\n          Rejected Observations: %6d",
 
  860       sprintf(buf, 
"\n   Constrained Point Parameters: %6d",
 
  866       sprintf(buf, 
"\n   Constrained Image Parameters: %6d",
 
  872       sprintf(buf, 
"\n  Constrained Target Parameters: %6d",
 
  877     sprintf(buf, 
"\n                       Unknowns: %6d",
 
  881     if (numInnerConstraints > 0) {
 
  882       sprintf(buf, 
"\n      Inner Constraints: %6d", numInnerConstraints);
 
  886     if (numDistanceConstraints > 0) {
 
  887       sprintf(buf, 
"\n   Distance Constraints: %d", numDistanceConstraints);
 
  891     sprintf(buf, 
"\n             Degrees of Freedom: %6d", numDegreesOfFreedom);
 
  894     sprintf(buf, 
"\n           Convergence Criteria: %6.3g",
 
  898     if (convergenceCriteria == 1) {
 
  899       sprintf(buf, 
"(Sigma0)");
 
  907       sprintf(buf, 
"(Maximum reached)");
 
  913     sprintf(buf, 
" Error Propagation Elapsed Time: %6.4lf (seconds)\n",
 
  916     sprintf(buf, 
"             Total Elapsed Time: %6.4lf (seconds)\n",
 
  922       sprintf(buf, 
"\n           Residual Percentiles:\n");
 
  928         for (
int bin = 1;bin < 34;bin++) {
 
  929           double cumProb = double(bin) / 100.0;
 
  932                   residualsCumulativeProbabilityDistribution().value(cumProb);
 
  935                   residualsCumulativeProbabilityDistribution().value(cumProb + 0.33);
 
  938                   residualsCumulativeProbabilityDistribution().value(cumProb + 0.66);
 
  939           sprintf(buf, 
"                 Percentile %3d: %+8.3lf" 
  940                        "                 Percentile %3d: %+8.3lf" 
  941                        "                 Percentile %3d: %+8.3lf\n",
 
  943                                          bin + 33, resValue33,
 
  944                                          bin + 66, resValue66);
 
  949         QString msg = 
"Failed to output residual percentiles for bundleout";
 
  953         sprintf(buf, 
"\n              Residual Box Plot:");
 
  955         sprintf(buf, 
"\n                        minimum: %+8.3lf",
 
  958         sprintf(buf, 
"\n                     Quartile 1: %+8.3lf",
 
  961         sprintf(buf, 
"\n                         Median: %+8.3lf",
 
  964         sprintf(buf, 
"\n                     Quartile 3: %+8.3lf",
 
  967         sprintf(buf, 
"\n                        maximum: %+8.3lf\n",
 
  972         QString msg = 
"Failed to output residual box plot for bundleout";
 
  981     for (
int i = 0; i < numObservations; i++) {
 
  985       for (
int j = 0; j < numImagesInObservation; j++) {
 
  988         if (bundleImage->fileName().length() > filePadding) {
 
  989           filePadding = bundleImage->fileName().length();
 
  994     sprintf(buf, 
"\nIMAGE MEASURES SUMMARY\n==========================\n\n");
 
  999     QString header(
"Measures                            RMS(pixels)");
 
 1001     sprintf(buf,
"%*s\n", header.length() + 11 + filePadding, header.toLatin1().data());
 
 1004     QString dividers(
"***************************   *******************************************");
 
 1005     sprintf(buf,
"%*s\n", dividers.length() + 1 + filePadding, dividers.toLatin1().data());
 
 1008     QString fields(
"|  Accepted  |   Total    |   |   Samples   |    Lines    |    Total    |");
 
 1009     sprintf(buf,
"%*s\n", fields.length() + 1 + filePadding, fields.toLatin1().data());
 
 1013     int numRejectedMeasures;
 
 1016     Statistics rmsSamplesTotal,rmsLinesTotal,rmsTotals;
 
 1018     for (
int i = 0; i < numObservations; i++) {
 
 1022       for (
int j = 0; j < numImagesInObservation; j++) {
 
 1027                                         rmsImageSampleResiduals()[imageIndex].Rms();
 
 1029                                         rmsImageLineResiduals()[imageIndex].Rms();
 
 1031                                         rmsImageResiduals()[imageIndex].Rms();
 
 1032         rmsSamplesTotal.
AddData(rmsSampleResiduals);
 
 1033         rmsLinesTotal.
AddData(rmsLineResiduals);
 
 1034         rmsTotals.
AddData(rmsLandSResiduals);
 
 1037             (bundleImage->serialNumber());
 
 1040             GetNumberOfJigsawRejectedMeasuresInImage(bundleImage->serialNumber());
 
 1042         numUsed = numMeasures - numRejectedMeasures;
 
 1044         QString filename = bundleImage->fileName();
 
 1046         List = filename.split(
"/");
 
 1048         sprintf(buf,
"%-*s" ,filePadding + 1, bundleImage->fileName().toLatin1().data());
 
 1051         sprintf(buf, 
" %12d %12d     ", numUsed, numMeasures);
 
 1054         sprintf(buf,
"%13.4lf %13.4lf %13.4lf \n",
 
 1055                 rmsSampleResiduals,rmsLineResiduals,rmsLandSResiduals);
 
 1064     sprintf(buf,
"%*s", -(filePadding + 33), 
"\nTotal RMS:");
 
 1066     sprintf(buf,
"%13.4lf %13.4lf %13.4lf\n",
 
 1067     rmsSamplesTotal.
Rms(),rmsLinesTotal.
Rms(),rmsTotals.
Rms());
 
 1093     bool errorProp = 
false;
 
 1101     if (instrumentIds.size() == 1) {
 
 1102       QString ofname = 
"bundleout_images.csv";
 
 1103       ofname = 
m_settings->outputFilePrefix() + ofname;
 
 1104       m_csvSavedImagesFilename = ofname;
 
 1105       outputCsvFileNames.push_back(ofname);
 
 1109       for (
int i = 0; i < instrumentIds.size(); i++) {
 
 1110         QString updatedInstrumentId = instrumentIds[i];
 
 1114         updatedInstrumentId.replace(
"/", 
"_").replace(
" ", 
"_");
 
 1115         QString ofname = 
"bundleout_images_" + updatedInstrumentId + 
".csv";
 
 1116         ofname = 
m_settings->outputFilePrefix() + ofname;
 
 1117         m_csvSavedImagesFilename = ofname;
 
 1118         outputCsvFileNames.push_back(ofname);
 
 1122     for (
int i = 0; i < instrumentIds.size(); i++) {
 
 1124       std::ofstream fpOut(outputCsvFileNames[i].toLatin1().data(), std::ios::out);
 
 1132       int nObservations = observations.size();
 
 1136       for (
int j = 0; j < nObservations; j++ ) {
 
 1141         int observationIndex = observation->index();
 
 1143         for (
int obsIndex = 0; obsIndex < observationIndex; obsIndex++) {
 
 1151         int numImages = observation->size();
 
 1153         for (
int k = 0; k < numImages; k++) {
 
 1156           sprintf(buf, 
"%s", image->fileName().toLatin1().data());
 
 1161           fpOut << 
toString(rmsImageSampleResiduals[imgIndex].Rms()).toLatin1().data();
 
 1165           fpOut << 
toString(rmsImageLineResiduals[imgIndex].Rms()).toLatin1().data();
 
 1169           fpOut << 
toString(rmsImageResiduals[imgIndex].Rms()).toLatin1().data();
 
 1173           QString observationString =
 
 1174               observation->bundleOutputCSV(errorProp);
 
 1177           if (observationString.right(1)==
",") {
 
 1178               observationString.truncate(observationString.length()-1);
 
 1181           fpOut << (
const char*) observationString.toLatin1().data();
 
 1203     QString ofname = 
"bundleout.txt";
 
 1204     ofname = 
m_settings->outputFilePrefix() + ofname;
 
 1206     std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
 
 1211     m_txtBundleOutputFilename = ofname;
 
 1220     bool berrorProp = 
false;
 
 1227       sprintf(buf, 
"\nTARGET BODY\n==========================\n");
 
 1230       sprintf(buf, 
"\n   Target         Initial            Total               " 
 1231                    "Final           Initial           Final\n" 
 1232                    "Parameter         Value            Correction           " 
 1233                    "Value             Accuracy          Accuracy\n");
 
 1236       QString targetString =
 
 1237           m_settings->bundleTargetBody()->formatBundleOutputString(berrorProp);
 
 1238       fpOut << (
const char*)targetString.toLatin1().data();
 
 1242     sprintf(buf, 
"\nIMAGE EXTERIOR ORIENTATION\n==========================\n");
 
 1248       imagesAndParameters.insert( 
"target", 
m_settings->bundleTargetBody()->parameterList() );
 
 1251     for (
int i = 0; i < nObservations; i++) {
 
 1258       int numImages = observation->size();
 
 1259       for (
int j = 0; j < numImages; j++) {
 
 1261         sprintf(buf, 
"\nImage Full File Name: %s\n", image->fileName().toLatin1().data());
 
 1263         sprintf(buf, 
"\nImage Serial Number: %s\n", image->serialNumber().toLatin1().data());
 
 1266         sprintf(buf,
"Image           Initial                 Total                  Final                                      Accuracy\n");
 
 1268         sprintf(buf,
"Parameter       Value                   Correction             Value                      Initial           Final           Units\n");
 
 1272                     "***************************************\n");
 
 1275         observation->bundleOutputString(fpOut,berrorProp);
 
 1277         foreach ( QString image, observation->imageNames() ) {
 
 1278           imagesAndParameters.insert( image, observation->parameterList() );
 
 1291       sprintf(buf, 
"\n\n\nPOINTS UNCERTAINTY SUMMARY\n==========================\n\n");
 
 1298       sprintf(buf, 
"RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(),
 
 1301       sprintf(buf, 
"MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
 
 1305       sprintf(buf, 
"MAX Sigma %s(m)%20.8lf at %s\n\n", coordName.toLatin1().data(),
 
 1313       sprintf(buf, 
"RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(),
 
 1316       sprintf(buf, 
"MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
 
 1320       sprintf(buf, 
"MAX Sigma %s(m)%20.8lf at %s\n\n", coordName.toLatin1().data(),
 
 1327                                         SurfacePoint::Three);
 
 1329         sprintf(buf, 
"RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(),
 
 1332         sprintf(buf, 
"MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
 
 1336         sprintf(buf, 
"MAX Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
 
 1342         sprintf(buf, 
"   RMS Sigma Radius(m)                 N/A\n");
 
 1344         sprintf(buf, 
"   MIN Sigma Radius(m)                 N/A\n");
 
 1346         sprintf(buf, 
"   MAX Sigma Radius(m)                 N/A\n");
 
 1353       sprintf(buf, 
"\n\nPOINTS SUMMARY\n==============\n%103s" 
 1354             "Sigma          Sigma              Sigma\n" 
 1355             "           Label         Status     Rays    RMS" 
 1356             "        Latitude       Longitude          Radius" 
 1357             "        Latitude       Longitude          Radius\n", 
"");
 
 1360       sprintf(buf, 
"\n\nPOINTS SUMMARY\n==============\n%103s" 
 1361             "Sigma          Sigma              Sigma\n" 
 1362             "           Label         Status     Rays    RMS" 
 1363             "         Point X            Point Y          Point Z" 
 1364             "         Point X            Point Y          Point Z\n", 
"");
 
 1369     for (
int i = 0; i < nPoints; i++) {
 
 1372       QString pointSummaryString =
 
 1373           bundleControlPoint->formatBundleOutputSummaryString(berrorProp);
 
 1374       fpOut << (
const char*)pointSummaryString.toLatin1().data();
 
 1378     sprintf(buf, 
"\n\nPOINTS DETAIL\n=============\n\n");
 
 1381     bool solveRadius = 
m_settings->solveRadius();
 
 1383     for (
int i = 0; i < nPoints; i++) {
 
 1387       QString pointDetailString =
 
 1388           bundleControlPoint->formatBundleOutputDetailString(berrorProp,
 
 1390       fpOut << (
const char*)pointDetailString.toLatin1().data();
 
 1407     QString ofname = 
"bundleout_points.csv";
 
 1408     ofname = 
m_settings->outputFilePrefix() + ofname;
 
 1409     m_csvSavedPointsFilename = ofname;
 
 1411     std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
 
 1418     double dLat, dLon, dRadius;
 
 1420     double dSigmaLat, dSigmaLong, dSigmaRadius;
 
 1425     int numMeasures, numRejectedMeasures;
 
 1426     double dResidualRms;
 
 1430       sprintf(buf, 
",,,,,3-d,3-d,3-d,Sigma,Sigma,Sigma,Correction,Correction,Correction,Coordinate," 
 1431               "Coordinate,Coordinate\nPoint,Point,Accepted,Rejected,Residual,Latitude,Longitude," 
 1432               "Radius,Latitude,Longitude,Radius,Latitude,Longitude,Radius,X,Y,Z\nLabel,Status," 
 1433               "Measures,Measures,RMS,(dd),(dd),(km),(m),(m),(m),(m),(m),(m),(km),(km),(km)\n");
 
 1436       sprintf(buf, 
",,,,,3-d,3-d,3-d,Correction,Correction,Correction,Coordinate,Coordinate," 
 1437               "Coordinate\nPoint,Point,Accepted,Rejected,Residual,Latitude,Longitude,Radius," 
 1438               "Latitude,Longitude,Radius,X,Y,Z\nLabel,Status,Measures,Measures,RMS,(dd),(dd),(km)," 
 1439               "(m),(m),(m),(km),(km),(km)\n");
 
 1443     for (
int i = 0; i < numPoints; i++) {
 
 1446       if (!bundlecontrolpoint) {
 
 1450       if (bundlecontrolpoint->isRejected()) {
 
 1454       dLat              = bundlecontrolpoint->adjustedSurfacePoint().GetLatitude().degrees();
 
 1455       dLon              = bundlecontrolpoint->adjustedSurfacePoint().GetLongitude().degrees();
 
 1456       dRadius           = bundlecontrolpoint->adjustedSurfacePoint().GetLocalRadius().kilometers();
 
 1457       dX                = bundlecontrolpoint->adjustedSurfacePoint().GetX().kilometers();
 
 1458       dY                = bundlecontrolpoint->adjustedSurfacePoint().GetY().kilometers();
 
 1459       dZ                = bundlecontrolpoint->adjustedSurfacePoint().GetZ().kilometers();
 
 1460       numMeasures         = bundlecontrolpoint->numberOfMeasures();
 
 1461       numRejectedMeasures = bundlecontrolpoint->numberOfRejectedMeasures();
 
 1462       dResidualRms      = bundlecontrolpoint->residualRms();
 
 1465       boost::numeric::ublas::bounded_vector< double, 3 > corrections = bundlecontrolpoint->
 
 1468       cor_lat_m = bundlecontrolpoint->adjustedSurfacePoint().LatitudeToMeters(corrections[0]);
 
 1469       cor_lon_m = bundlecontrolpoint->adjustedSurfacePoint().LongitudeToMeters(corrections[1]);
 
 1470       cor_rad_m  = corrections[2]*1000.0;
 
 1473         strStatus = 
"FIXED";
 
 1476         strStatus = 
"CONSTRAINED";
 
 1482         strStatus = 
"UNKNOWN";
 
 1486         dSigmaLat = bundlecontrolpoint->adjustedSurfacePoint().GetLatSigmaDistance().meters();
 
 1487         dSigmaLong = bundlecontrolpoint->adjustedSurfacePoint().GetLonSigmaDistance().meters();
 
 1488         dSigmaRadius = bundlecontrolpoint->adjustedSurfacePoint().GetLocalRadiusSigma().meters();
 
 1490         sprintf(buf, 
"%s,%s,%d,%d,%6.2lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf," 
 1491                      "%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf\n",
 
 1492                 bundlecontrolpoint->id().toLatin1().data(), strStatus.toLatin1().data(),
 
 1493                 numMeasures, numRejectedMeasures, dResidualRms, dLat, dLon, dRadius, dSigmaLat,
 
 1494                 dSigmaLong, dSigmaRadius, cor_lat_m, cor_lon_m, cor_rad_m, dX, dY, dZ);
 
 1497         sprintf(buf, 
"%s,%s,%d,%d,%6.2lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf," 
 1498                      "%16.8lf,%16.8lf\n",
 
 1499                 bundlecontrolpoint->id().toLatin1().data(), strStatus.toLatin1().data(),
 
 1500                 numMeasures, numRejectedMeasures, dResidualRms, dLat, dLon, dRadius, cor_lat_m,
 
 1501                 cor_lon_m, cor_rad_m, dX, dY, dZ);
 
 1520     QString ofname = 
"residuals.csv";
 
 1521     ofname = 
m_settings->outputFilePrefix() + ofname;
 
 1522     m_csvSavedResidualsFilename = ofname;
 
 1524     std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
 
 1531     sprintf(buf, 
",,,x image,y image,Measured,Measured,sample,line,Residual Vector\n");
 
 1533     sprintf(buf, 
"Point,Image,Image,coordinate,coordinate," 
 1534                  "Sample,Line,residual,residual,Magnitude\n");
 
 1536     sprintf(buf, 
"Label,Filename,Serial Number,(mm),(mm)," 
 1537                  "(pixels),(pixels),(pixels),(pixels),(pixels),Rejected\n");
 
 1543     int numMeasures = 0;
 
 1548     for (
int i = 0; i < numPoints; i++) {
 
 1550       numMeasures = bundleControlPoint->size();
 
 1552       if (bundleControlPoint->rawControlPoint()->IsIgnored()) {
 
 1556       for (
int j = 0; j < numMeasures; j++) {
 
 1557         bundleMeasure = bundleControlPoint->at(j);
 
 1559         Camera *measureCamera = bundleMeasure->camera();
 
 1560         if (!measureCamera) {
 
 1564         if (bundleMeasure->isRejected()) {
 
 1565           sprintf(buf, 
"%s,%s,%s,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,*\n",
 
 1566                   bundleControlPoint->id().toLatin1().data(),
 
 1567                   bundleMeasure->parentBundleImage()->fileName().toLatin1().data(),
 
 1568                   bundleMeasure->cubeSerialNumber().toLatin1().data(),
 
 1569                   bundleMeasure->focalPlaneMeasuredX(),
 
 1570                   bundleMeasure->focalPlaneMeasuredY(),
 
 1571                   bundleMeasure->sample(),
 
 1572                   bundleMeasure->line(),
 
 1573                   bundleMeasure->sampleResidual(),
 
 1574                   bundleMeasure->lineResidual(),
 
 1575                   bundleMeasure->residualMagnitude());
 
 1578           sprintf(buf, 
"%s,%s,%s,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf\n",
 
 1579                   bundleControlPoint->id().toLatin1().data(),
 
 1580                   bundleMeasure->parentBundleImage()->fileName().toLatin1().data(),
 
 1581                   bundleMeasure->cubeSerialNumber().toLatin1().data(),
 
 1582                   bundleMeasure->focalPlaneMeasuredX(),
 
 1583                   bundleMeasure->focalPlaneMeasuredY(),
 
 1584                   bundleMeasure->sample(),
 
 1585                   bundleMeasure->line(),
 
 1586                   bundleMeasure->sampleResidual(),
 
 1587                   bundleMeasure->lineResidual(),
 
 1588                   bundleMeasure->residualMagnitude());
 
 1622     QString relativePath;
 
 1623     QString relativeBundlePath;
 
 1632       if (oldPath != newPath) {
 
 1634         QDir bundleDir(newPath);
 
 1635         if (!bundleDir.mkpath(bundleDir.path())) {
 
 1637                            QString(
"Failed to create directory [%1]")
 
 1638                              .arg(bundleSolutionInfoRoot.
path()),
 
 1643         if (!QFile::copy(oldFile, newFile)) {
 
 1645                            QString(
"Failed to copy file [%1] to new file [%2]")
 
 1649         newFile = newPath + 
"/" + 
FileName(m_txtBundleOutputFilename).
name();
 
 1650         if (!QFile::copy(m_txtBundleOutputFilename, newFile)) {
 
 1652                            QString(
"Failed to copy file [%1] to new file [%2]")
 
 1653                              .arg(m_txtBundleOutputFilename).arg(newFile),
 
 1656         newFile = newPath + 
"/" + 
FileName(m_csvSavedImagesFilename).
name();
 
 1657         if (!QFile::copy(m_csvSavedImagesFilename, newFile)) {
 
 1659                            QString(
"Failed to copy file [%1] to new file [%2]")
 
 1660                              .arg(m_csvSavedImagesFilename).arg(newFile),
 
 1663         newFile = newPath + 
"/" + 
FileName(m_csvSavedPointsFilename).
name();
 
 1664         if (!QFile::copy(m_csvSavedPointsFilename, newFile)) {
 
 1666                            QString(
"Failed to copy file [%1] to new file [%2]")
 
 1667                              .arg(m_csvSavedPointsFilename).arg(newFile),
 
 1670         newFile = newPath + 
"/" + 
FileName(m_csvSavedResidualsFilename).
name();
 
 1671         if (!QFile::copy(m_csvSavedResidualsFilename, newFile)) {
 
 1673                            QString(
"Failed to copy file [%1] to new file [%2]")
 
 1674                              .arg(m_csvSavedResidualsFilename).arg(newFile),
 
 1682       if (relativePath.startsWith(
"/")) {
 
 1683         relativePath.remove(0,1);
 
 1689       if (relativeBundlePath.startsWith(
"/")) {
 
 1690         relativeBundlePath.remove(0,1);
 
 1692       relativeBundlePath += 
"/";
 
 1697     stream.writeStartElement(
"bundleSolutionInfo");
 
 1699     stream.writeStartElement(
"generalAttributes");
 
 1700     stream.writeTextElement(
"id", 
m_id->toString());
 
 1701     stream.writeTextElement(
"name", 
m_name);
 
 1702     stream.writeTextElement(
"runTime", 
runTime());
 
 1704     stream.writeTextElement(
"inputFileName",
 
 1706     stream.writeTextElement(
"bundleOutTXT",
 
 1707                             relativeBundlePath + 
FileName(m_txtBundleOutputFilename).
name());
 
 1708     stream.writeTextElement(
"imagesCSV",
 
 1709                             relativeBundlePath + 
FileName(m_csvSavedImagesFilename).
name());
 
 1710     stream.writeTextElement(
"pointsCSV",
 
 1711                             relativeBundlePath + 
FileName(m_csvSavedPointsFilename).
name());
 
 1712     stream.writeTextElement(
"residualsCSV",
 
 1713                             relativeBundlePath + 
FileName(m_csvSavedResidualsFilename).
name());
 
 1714     stream.writeEndElement(); 
 
 1725         stream.writeStartElement(
"imageLists");
 
 1729         stream.writeEndElement();
 
 1733       stream.writeStartElement(
"outputControl");
 
 1735       stream.writeEndElement();
 
 1738     stream.writeEndElement(); 
 
 1752     m_xmlHandlerProject = project;
 
 1772     m_xmlHandlerCharacters += ch;
 
 1773     return XmlStackedHandler::characters(ch);
 
 1788                                                     const QString &localName,
 
 1789                                                     const QString &qName,
 
 1790                                                     const QXmlAttributes &atts) {
 
 1791     m_xmlHandlerCharacters = 
"";
 
 1793     if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {
 
 1795       if (localName == 
"bundleSettings") {
 
 1796         m_xmlHandlerBundleSolutionInfo->m_settings =
 
 1799       else if (localName == 
"bundleResults") {
 
 1800         m_xmlHandlerBundleSolutionInfo->m_statisticsResults = 
new BundleResults(m_xmlHandlerProject,
 
 1803       else if (localName == 
"imageList") {
 
 1804         m_xmlHandlerBundleSolutionInfo->m_adjustedImages->append(
 
 1805             new ImageList(m_xmlHandlerProject, reader()));
 
 1807       else if (localName == 
"outputControl") {
 
 1808         FileName outputControlPath = 
FileName(m_xmlHandlerProject->bundleSolutionInfoRoot() + 
"/" 
 1809                                               + m_xmlHandlerBundleSolutionInfo->runTime());
 
 1811         m_xmlHandlerBundleSolutionInfo->m_outputControl = 
new Control(outputControlPath, reader());
 
 1828                                                   const QString &localName,
 
 1829                                                   const QString &qName) {
 
 1831     QString projectRoot;
 
 1832     if (m_xmlHandlerProject) {
 
 1833       projectRoot = m_xmlHandlerProject->projectRoot() + 
"/";
 
 1836     if (localName == 
"id") {
 
 1838       assert(m_xmlHandlerBundleSolutionInfo->m_id);
 
 1839       delete m_xmlHandlerBundleSolutionInfo->m_id;
 
 1840       m_xmlHandlerBundleSolutionInfo->m_id = 
new QUuid(m_xmlHandlerCharacters);
 
 1842     else if (localName == 
"name") {
 
 1843       m_xmlHandlerBundleSolutionInfo->m_name = m_xmlHandlerCharacters;
 
 1845     else if (localName == 
"runTime") {
 
 1846       m_xmlHandlerBundleSolutionInfo->m_runTime = m_xmlHandlerCharacters;
 
 1848     else if (localName == 
"inputFileName") {
 
 1849       assert(m_xmlHandlerBundleSolutionInfo->m_inputControlNetFileName == NULL);
 
 1850       m_xmlHandlerBundleSolutionInfo->m_inputControlNetFileName = 
new FileName(
 
 1851         projectRoot + m_xmlHandlerCharacters);
 
 1853     else if (localName == 
"bundleOutTXT") {
 
 1854       m_xmlHandlerBundleSolutionInfo->m_txtBundleOutputFilename =
 
 1855         projectRoot + m_xmlHandlerCharacters;
 
 1857     else if (localName == 
"imagesCSV") {
 
 1858       m_xmlHandlerBundleSolutionInfo->m_csvSavedImagesFilename =
 
 1859         projectRoot + m_xmlHandlerCharacters;
 
 1861     else if (localName == 
"pointsCSV") {
 
 1862       m_xmlHandlerBundleSolutionInfo->m_csvSavedPointsFilename =
 
 1863         projectRoot + m_xmlHandlerCharacters;
 
 1865     else if (localName == 
"residualsCSV") {
 
 1866       m_xmlHandlerBundleSolutionInfo->m_csvSavedResidualsFilename =
 
 1867         projectRoot + m_xmlHandlerCharacters;
 
 1870     m_xmlHandlerCharacters = 
"";
 
 1871     return XmlStackedHandler::endElement(namespaceURI, localName, qName);
 
 1884                                                  SurfacePoint::CoordIndex coordIdx)
 const {
 
 1886     switch (
m_settings->controlPointCoordTypeReports()) {
 
 1889           case SurfacePoint::One:
 
 1890             coordName = 
" Latitude";
 
 1892           case SurfacePoint::Two:
 
 1893             coordName = 
"Longitude";
 
 1895           case SurfacePoint::Three:
 
 1896             coordName = 
"   Radius";
 
 1899             IString msg = 
"Unknown surface point index enum [" 
 1907           case SurfacePoint::One:
 
 1908             coordName = 
"POINT X";
 
 1910           case SurfacePoint::Two:
 
 1911             coordName = 
"POINT Y";
 
 1913           case SurfacePoint::Three:
 
 1914             coordName = 
"POINT Z";
 
 1917             IString msg = 
"Unknown surface point index enum [" 
 1924       IString msg = 
"Unknown surface point coordinate type enum ["