Isis 3 Programmer Reference
BundleSolutionInfo.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "BundleSolutionInfo.h"
10
11#include <QDataStream>
12#include <QDebug>
13#include <QFile>
14#include <QList>
15#include <QString>
16#include <QStringList>
17#include <QUuid>
18#include <QXmlStreamWriter>
19
20#include "BundleLidarRangeConstraint.h"
21#include "BundleResults.h"
22#include "Control.h"
23#include "ControlList.h"
24#include "ControlMeasure.h"
25#include "ControlNet.h"
26#include "ControlPoint.h"
27#include "FileName.h"
28#include "ImageList.h"
29#include "IString.h"
30#include "iTime.h"
31#include "Project.h"
32#include "PvlKeyword.h"
33#include "PvlObject.h"
34#include "StatCumProbDistDynCalc.h"
35#include "Statistics.h"
36#include "XmlStackedHandlerReader.h"
37
38namespace Isis {
39
48 BundleSolutionInfo::BundleSolutionInfo(BundleSettingsQsp inputSettings,
49 FileName controlNetworkFileName,
50 BundleResults outputStatistics,
51 QList<ImageList *> imgList,
52 QObject *parent) : QObject(parent) {
53 m_id = new QUuid(QUuid::createUuid());
54 m_runTime = "";
56 m_inputControlNetFileName = new FileName(controlNetworkFileName);
57 m_outputControl = NULL;
58 m_outputControlName="";
61 m_settings = inputSettings;
62 m_statisticsResults = new BundleResults(outputStatistics);
63 m_images = new QList<ImageList *>(imgList);
64 m_adjustedImages = new QList<ImageList *>;
65 }
66
67
76 BundleSolutionInfo::BundleSolutionInfo(BundleSettingsQsp inputSettings,
77 FileName controlNetworkFileName,
78 FileName lidarDataFileName,
79 BundleResults outputStatistics,
80 QList<ImageList *> imgList,
81 QObject *parent) : QObject(parent) {
82 m_id = new QUuid(QUuid::createUuid());
83 m_runTime = "";
85 m_inputControlNetFileName = new FileName(controlNetworkFileName);
86 m_outputControl = NULL;
87 m_outputControlName="";
88 m_inputLidarDataFileName = new FileName(lidarDataFileName);
90 m_settings = inputSettings;
91 m_statisticsResults = new BundleResults(outputStatistics);
92 m_images = new QList<ImageList *>(imgList);
93 m_adjustedImages = new QList<ImageList *>;
94 }
95
96
104 BundleSolutionInfo::BundleSolutionInfo(Project *project,
105 XmlStackedHandlerReader *xmlReader,
106 QObject *parent) : QObject(parent) {
107 //TODO does xml stuff need project???
108 m_id = new QUuid(QUuid::createUuid());
109 m_runTime = "";
112 m_outputControl = NULL;
113 m_outputControlName="";
116 m_statisticsResults = NULL;
117 // what about the rest of the member data ? should we set defaults ??? CREATE INITIALIZE METHOD
118 m_images = new QList<ImageList *>;
119 m_adjustedImages = new QList<ImageList *>;
120
121 xmlReader->setErrorHandler(new XmlHandler(this, project));
122 xmlReader->pushContentHandler(new XmlHandler(this, project));
123 }
124
125
130 delete m_id;
131
134
135 delete m_outputControl;
136 m_outputControl = NULL;
137
140
143
144 delete m_statisticsResults;
145 m_statisticsResults = NULL;
146
147 if (m_images != NULL) {
148 delete m_images;
149 m_images = NULL;
150 }
151
152 // if (m_adjustedImages != NULL) {
153 // qDeleteAll(*m_adjustedImages);
154 // m_adjustedImages->clear();
155 // delete m_adjustedImages;
156 // m_adjustedImages = NULL;
157 // }
158 }
159
160
167 return m_txtBundleOutputFilename;
168 }
169
170
177 return m_csvSavedImagesFilename;
178 }
179
180
187 return m_csvSavedPointsFilename;
188 }
189
190
197 return m_csvSavedResidualsFilename;
198 }
199
200
207 m_adjustedImages->append(images);
208 }
209
210
217 delete m_statisticsResults;
218 m_statisticsResults = NULL;
219 m_statisticsResults = new BundleResults(statisticsResults);
220 }
221
222
236
237 //TODO do we need to close anything here?
238
239 FileName oldInputFileName(*m_inputControlNetFileName);
240 FileName newInputFileName(project->cnetRoot() + "/" +
241 oldInputFileName.dir().dirName() + "/" + oldInputFileName.name());
242 *m_inputControlNetFileName = newInputFileName.expanded();
243
244 FileName oldOutputFileName(m_outputControl->fileName());
245 FileName newOutputFileName(project->cnetRoot() + "/" +
246 oldOutputFileName.dir().dirName() + "/" + oldOutputFileName.name());
247
248 if (m_outputControl) {
249 delete m_outputControl;
250 }
251 m_outputControl = new Control(newOutputFileName.expanded());
252 m_outputControlName = newOutputFileName.expanded();
253 }
254
255
262 QList<ImageList *> BundleSolutionInfo::adjustedImages() const {
263 return *m_adjustedImages;
264 }
265
266
272 QString BundleSolutionInfo::id() const {
273 return m_id->toString().remove(QRegExp("[{}]"));
274 }
275
276
282 void BundleSolutionInfo::setRunTime(QString runTime) {
283 // ??? validate that a valid time has been given???
284 // try {
285 // iTime time(runTime);
286 // }
287 // catch (...) {
288 // throw IException(IException::Unknown,
289 // "Invalid bundle adjustment run time [" + runTime + ].",
290 // _FILEINFO_);
291 // }
293 if (m_name == m_runTime || m_name == "") {
294 m_name = runTime;
295 }
296 }
297
298
305 return m_runTime;
306 }
307
308
317
318
325
326 if (m_outputControl)
327 return m_outputControl->fileName();
328 else
329 return m_outputControlName;
330 }
331
332
341
342
349 m_outputControl = outputControl;
350 }
351
352
359 m_outputControlName = name;
360 }
361
362
369 return m_outputControlName;
370 }
371
380
381
390
391
401 return *m_statisticsResults;
402 }
403 else {
405 "Results for this bundle is NULL.",
406 _FILEINFO_);
407 }
408 }
409
410
416 QList<ImageList *> BundleSolutionInfo::imageList() {
417 return *m_images;
418 }
419
420
426 void BundleSolutionInfo::setName(QString name) {
427 m_name = name;
428 }
429
430
437 QString BundleSolutionInfo::name() const {
438 return m_name;
439 }
440
441
453 bool BundleSolutionInfo::outputImagesCSVHeader(std::ofstream &fpOut, BundleObservationQsp observation) {
454
455 if (!fpOut) {
456 return false;
457 }
458
459 char buf[1056];
460
461 // setup column headers
462 std::vector<QString> outputColumns;
463
464 outputColumns.push_back("Image,");
465 outputColumns.push_back("rms,");
466 outputColumns.push_back("rms,");
467 outputColumns.push_back("rms,");
468
469 QStringList observationParameters = observation->parameterList();
470
471 for (int i = 0; i < observationParameters.size(); i++) {
472 for (int j = 0; j < 5; j++) {
473 outputColumns.push_back(observationParameters[i] + ",");
474 }
475 }
476
477 // print first column header to buffer and output to file
478 int ncolumns = outputColumns.size();
479 for (int i = 0; i < ncolumns; i++) {
480 QString str = outputColumns.at(i);
481 snprintf(buf, sizeof(buf), "%s", (const char*)str.toLatin1().data());
482 fpOut << buf;
483 }
484 snprintf(buf, sizeof(buf), "\n");
485 fpOut << buf;
486
487 outputColumns.clear();
488
489 outputColumns.push_back("Filename,");
490 outputColumns.push_back("sample res,");
491 outputColumns.push_back("line res,");
492 outputColumns.push_back("total res,");
493
494 for (int i = 0; i < observationParameters.size(); i++) {
495 outputColumns.push_back("Initial,");
496 outputColumns.push_back("Correction,");
497 outputColumns.push_back("Final,");
498 outputColumns.push_back("Apriori Sigma,");
499 outputColumns.push_back("Adj Sigma,");
500 }
501
502 // print second column header to buffer and output to file
503 ncolumns = outputColumns.size();
504 for (int i = 0; i < ncolumns; i++) {
505 QString str = outputColumns.at(i);
506 snprintf(buf, sizeof(buf), "%s", (const char*)str.toLatin1().data());
507 fpOut << buf;
508 }
509 snprintf(buf, sizeof(buf), "\n");
510 fpOut << buf;
511
512 return true;
513 }
514
515
516
529 bool BundleSolutionInfo::outputHeader(std::ofstream &fpOut) {
530
531 if (!fpOut) {
532 return false;
533 }
534
536
537 char buf[1056];
538 int numObservations = m_statisticsResults->observations().size();
539 int numImages = 0;
540 for (int i = 0; i < numObservations; i++) {
541 numImages += m_statisticsResults->observations().at(i)->size();
542 }
543 int numValidPoints = m_statisticsResults->outputControlNet()->GetNumValidPoints();
544
545 int numValidLidarPoints = 0;
546 if (lidarData) {
547 numValidLidarPoints = lidarData->numberLidarPoints();
548 }
549
550 int numInnerConstraints = 0;
551 int numDistanceConstraints = 0;
552 int numDegreesOfFreedom = m_statisticsResults->degreesOfFreedom();
553
554 int convergenceCriteria = 1;
555
556 snprintf(buf, sizeof(buf), "JIGSAW: BUNDLE ADJUSTMENT\n=========================\n");
557 fpOut << buf;
558 snprintf(buf, sizeof(buf), "\n Run Time: %s",
559 Isis::iTime::CurrentLocalTime().toLatin1().data());
560 fpOut << buf;
561 snprintf(buf, sizeof(buf), "\n Network Filename: %s",
562 m_inputControlNetFileName->expanded().toLatin1().data());
563 fpOut << buf;
564
565 snprintf(buf, sizeof(buf),"\n Cube List: %s",
566 m_settings->cubeList().toStdString().c_str() );
567
568 fpOut << buf;
569
570 snprintf(buf, sizeof(buf), "\n Output Network Filename: %s",
571 outputControlName().toStdString().c_str() );
572 fpOut << buf;
573 snprintf(buf, sizeof(buf),"\n Output File Prefix: %s",
574 m_settings->outputFilePrefix().toStdString().c_str() );
575 fpOut <<buf;
576
577 snprintf(buf, sizeof(buf), "\n Network Id: %s",
578 m_statisticsResults->outputControlNet()->GetNetworkId().toLatin1().data());
579 fpOut << buf;
580 snprintf(buf, sizeof(buf), "\n Network Description: %s",\
581 m_statisticsResults->outputControlNet()->Description().toLatin1().data());
582 fpOut << buf;
584 snprintf(buf, sizeof(buf), "\n Lidar Data Filename: %s",
585 m_inputLidarDataFileName->expanded().toLatin1().data());
586 fpOut << buf;
587 }
588 snprintf(buf, sizeof(buf), "\n Target: %s",
589 m_statisticsResults->outputControlNet()->GetTarget().toLatin1().data());
590 fpOut << buf;
591 snprintf(buf, sizeof(buf), "\n\n Linear Units: kilometers");
592 fpOut << buf;
593 snprintf(buf, sizeof(buf), "\n Angular Units: decimal degrees");
594 fpOut << buf;
595 snprintf(buf, sizeof(buf), "\n\nINPUT: SOLVE OPTIONS\n====================\n");
596 fpOut << buf;
597
598 m_settings->solveObservationMode() ?
599 snprintf(buf, sizeof(buf), "\n OBSERVATIONS: ON"):
600 snprintf(buf, sizeof(buf), "\n OBSERVATIONS: OFF");
601 fpOut << buf;
602
603 m_settings->solveRadius() ?
604 snprintf(buf, sizeof(buf), "\n RADIUS: ON"):
605 snprintf(buf, sizeof(buf), "\n RADIUS: OFF");
606 fpOut << buf;
607
608 m_settings->solveTargetBody() ?
609 snprintf(buf, sizeof(buf), "\n TARGET BODY: ON"):
610 snprintf(buf, sizeof(buf), "\n TARGET BODY: OFF");
611 fpOut << buf;
612
613 m_settings->updateCubeLabel() ?
614 snprintf(buf, sizeof(buf), "\n UPDATE: YES"):
615 snprintf(buf, sizeof(buf), "\n UPDATE: NO");
616 fpOut << buf;
617
618 m_settings->errorPropagation() ?
619 snprintf(buf, sizeof(buf), "\n ERROR PROPAGATION: ON"):
620 snprintf(buf, sizeof(buf), "\n ERROR PROPAGATION: OFF");
621 fpOut << buf;
622
623 (m_settings->controlPointCoordTypeReports() == SurfacePoint::Latitudinal) ?
624 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR REPORTS: LATITUDINAL"):
625 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR REPORTS: RECTANGULAR");
626 fpOut << buf;
627
628 (m_settings->controlPointCoordTypeBundle() == SurfacePoint::Latitudinal) ?
629 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR BUNDLE: LATITUDINAL"):
630 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR BUNDLE: RECTANGULAR");
631 fpOut << buf;
632
633 if (m_settings->outlierRejection()) {
634 snprintf(buf, sizeof(buf), "\n OUTLIER REJECTION: ON");
635 fpOut << buf;
636 snprintf(buf, sizeof(buf), "\n REJECTION MULTIPLIER: %lf",
637 m_settings->outlierRejectionMultiplier());
638 fpOut << buf;
639
640 }
641 else {
642 snprintf(buf, sizeof(buf), "\n OUTLIER REJECTION: OFF");
643 fpOut << buf;
644 snprintf(buf, sizeof(buf), "\n REJECTION MULTIPLIER: N/A");
645 fpOut << buf;
646 }
647
648 // Added April 5, 2017
649 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR REPORTS: %s",
650 SurfacePoint::coordinateTypeToString(m_settings->controlPointCoordTypeReports()).toLatin1().data());
651
652 // Added July 4, 2017
653 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR BUNDLE: %s",
654 SurfacePoint::coordinateTypeToString(m_settings->controlPointCoordTypeBundle()).toLatin1().data());
655
656 snprintf(buf, sizeof(buf), "\n\nMAXIMUM LIKELIHOOD ESTIMATION\n============================\n");
657 fpOut << buf;
658
659 for (int tier = 0; tier < 3; tier++) {
660 if (tier < m_statisticsResults->numberMaximumLikelihoodModels()) {
661 snprintf(buf, sizeof(buf), "\n Tier %d Enabled: TRUE", tier);
662 fpOut << buf;
663 snprintf(buf, sizeof(buf), "\n Maximum Likelihood Model: %s",
666 maximumLikelihoodModelWFunc(tier).model()).toLatin1().data());
667 fpOut << buf;
668 snprintf(buf, sizeof(buf), "\n Quantile used for tweaking constant: %lf",
670 fpOut << buf;
671 snprintf(buf, sizeof(buf), "\n Quantile weighted R^2 Residual value: %lf",
673 fpOut << buf;
674 snprintf(buf, sizeof(buf), "\n Approx. weighted Residual cutoff: %s",
676 .weightedResidualCutoff().toLatin1().data());
677 fpOut << buf;
678 if (tier != 2) fpOut << "\n";
679 }
680 else {
681 snprintf(buf, sizeof(buf), "\n Tier %d Enabled: FALSE", tier);
682 fpOut << buf;
683 }
684 }
685
686 snprintf(buf, sizeof(buf), "\n\nINPUT: CONVERGENCE CRITERIA\n===========================\n");
687 fpOut << buf;
688 snprintf(buf, sizeof(buf), "\n SIGMA0: %e",
689 m_settings->convergenceCriteriaThreshold());
690 fpOut << buf;
691 snprintf(buf, sizeof(buf), "\n MAXIMUM ITERATIONS: %d",
692 m_settings->convergenceCriteriaMaximumIterations());
693 fpOut << buf;
694
695 //TODO Should it be checked that positionSigmas.size() == positionSolveDegree and
696 // pointingSigmas.size() == pointingSolveDegree somewhere? JAM
697
698 //TODO How do we output this information when using multiple solve settings? JAM
699
700 BundleObservationSolveSettings globalSettings = m_settings->observationSolveSettings(0);
701 int pointingSolveDegree = globalSettings.numberCameraAngleCoefficientsSolved();
702 QList<double> pointingSigmas = globalSettings.aprioriPointingSigmas();
703 int positionSolveDegree = globalSettings.numberCameraPositionCoefficientsSolved();
704 QList<double> positionSigmas = globalSettings.aprioriPositionSigmas();
705
706 snprintf(buf, sizeof(buf), "\n\nINPUT: CAMERA POINTING OPTIONS\n==============================\n");
707 fpOut << buf;
708 switch (pointingSolveDegree) {
709 case 0:
710 snprintf(buf, sizeof(buf),"\n CAMSOLVE: NONE");
711 break;
712 case 1:
713 snprintf(buf, sizeof(buf),"\n CAMSOLVE: ANGLES");
714 break;
715 case 2:
716 snprintf(buf, sizeof(buf),"\n CAMSOLVE: ANGLES, VELOCITIES");
717 break;
718 case 3:
719 snprintf(buf, sizeof(buf),"\n CAMSOLVE: ANGLES, VELOCITIES, ACCELERATIONS");
720 break;
721 default:
722 snprintf(buf, sizeof(buf),"\n CAMSOLVE: ALL POLYNOMIAL COEFFICIENTS (%d)"
723 "\n CKDEGREE: %d"
724 "\n CKSOLVEDEGREE: %d",
725 pointingSolveDegree,
726 globalSettings.ckDegree(),
727 globalSettings.ckSolveDegree());
728 break;
729 }
730 fpOut << buf;
731 globalSettings.solveTwist() ?
732 snprintf(buf, sizeof(buf), "\n TWIST: ON"):
733 snprintf(buf, sizeof(buf), "\n TWIST: OFF");
734 fpOut << buf;
735 globalSettings.solvePolyOverPointing() ?
736 snprintf(buf, sizeof(buf), "\n POLYNOMIAL OVER EXISTING POINTING: ON"):
737 snprintf(buf, sizeof(buf), "\nPOLYNOMIAL OVER EXISTING POINTING : OFF");
738 fpOut << buf;
739
740 snprintf(buf, sizeof(buf), "\n\nINPUT: SPACECRAFT OPTIONS\n=========================\n");
741 fpOut << buf;
742 switch (positionSolveDegree) {
743 case 0:
744 snprintf(buf, sizeof(buf),"\n SPSOLVE: NONE");
745 break;
746 case 1:
747 snprintf(buf, sizeof(buf),"\n SPSOLVE: POSITION");
748 break;
749 case 2:
750 snprintf(buf, sizeof(buf),"\n SPSOLVE: POSITION, VELOCITIES");
751 break;
752 case 3:
753 snprintf(buf, sizeof(buf),"\n SPSOLVE: POSITION, VELOCITIES, ACCELERATIONS");
754 break;
755 default:
756 snprintf(buf, sizeof(buf),"\n SPSOLVE: ALL POLYNOMIAL COEFFICIENTS (%d)"
757 "\n SPKDEGREE: %d"
758 "\n SPKSOLVEDEGREE: %d",
759 positionSolveDegree,
760 globalSettings.spkDegree(),
761 globalSettings.spkSolveDegree());
762 break;
763 }
764 fpOut << buf;
765 globalSettings.solvePositionOverHermite() ?
766 snprintf(buf, sizeof(buf), "\n POLYNOMIAL OVER HERMITE SPLINE: ON"):
767 snprintf(buf, sizeof(buf), "\nPOLYNOMIAL OVER HERMITE SPLINE : OFF");
768 fpOut << buf;
769
770 snprintf(buf, sizeof(buf), "\n\nINPUT: GLOBAL IMAGE PARAMETER UNCERTAINTIES\n===========================================\n");
771 QString coord1Str;
772 QString coord2Str;
773 QString coord3Str;
774 switch (m_settings->controlPointCoordTypeReports()) {
776 coord1Str = "LATITUDE";
777 coord2Str = "LONGITUDE";
778 coord3Str = "RADIUS";
779 break;
781 coord1Str = " X";
782 coord2Str = " Y";
783 coord3Str = " Z";
784 break;
785 default:
786 IString msg ="Unknown surface point coordinate type enum ["
787 + toString(m_settings->controlPointCoordTypeReports()) + "]." ;
788 throw IException(IException::Programmer, msg, _FILEINFO_);
789 break;
790 }
791
792 // Coordinate 1 (latitude or point X)
793 fpOut << buf;
794 (m_settings->globalPointCoord1AprioriSigma() == Isis::Null) ?
795 snprintf(buf, sizeof(buf),"\n POINT %s SIGMA: N/A", coord1Str.toLatin1().data()):
796 snprintf(buf, sizeof(buf),"\n POINT %s SIGMA: %lf (meters)", coord1Str.toLatin1().data(),
797 m_settings->globalPointCoord1AprioriSigma());
798 // Coordinate 2 (longitude or point Y)
799 fpOut << buf;
800 (m_settings->globalPointCoord2AprioriSigma() == Isis::Null) ?
801 snprintf(buf, sizeof(buf),"\n POINT %s SIGMA: N/A", coord2Str.toLatin1().data()):
802 snprintf(buf, sizeof(buf),"\n POINT %s SIGMA: %lf (meters)", coord2Str.toLatin1().data(),
803 m_settings->globalPointCoord2AprioriSigma());
804 // Coordinate 3 (radius or point Z)
805 fpOut << buf;
806 (m_settings->globalPointCoord3AprioriSigma() == Isis::Null) ?
807 snprintf(buf, sizeof(buf),"\n POINT %s SIGMA: N/A", coord3Str.toLatin1().data()):
808 snprintf(buf, sizeof(buf),"\n POINT %s SIGMA: %lf (meters)", coord3Str.toLatin1().data(),
809 m_settings->globalPointCoord3AprioriSigma());
810 fpOut << buf;
811 (positionSolveDegree < 1 || positionSigmas[0] == Isis::Null) ?
812 snprintf(buf, sizeof(buf),"\n SPACECRAFT POSITION SIGMA: N/A"):
813 snprintf(buf, sizeof(buf),"\n SPACECRAFT POSITION SIGMA: %lf (meters)",
814 positionSigmas[0]);
815 fpOut << buf;
816
817 (positionSolveDegree < 2 || positionSigmas[1] == Isis::Null) ?
818 snprintf(buf, sizeof(buf),"\n SPACECRAFT VELOCITY SIGMA: N/A"):
819 snprintf(buf, sizeof(buf),"\n SPACECRAFT VELOCITY SIGMA: %lf (m/s)",
820 positionSigmas[1]);
821 fpOut << buf;
822
823 (positionSolveDegree < 3 || positionSigmas[2] == Isis::Null) ?
824 snprintf(buf, sizeof(buf),"\n SPACECRAFT ACCELERATION SIGMA: N/A"):
825 snprintf(buf, sizeof(buf),"\n SPACECRAFT ACCELERATION SIGMA: %lf (m/s/s)",
826 positionSigmas[2]);
827 fpOut << buf;
828
829 (pointingSolveDegree < 1 || pointingSigmas[0] == Isis::Null) ?
830 snprintf(buf, sizeof(buf),"\n CAMERA ANGLES SIGMA: N/A"):
831 snprintf(buf, sizeof(buf),"\n CAMERA ANGLES SIGMA: %lf (dd)",
832 pointingSigmas[0]);
833 fpOut << buf;
834
835 (pointingSolveDegree < 2 || pointingSigmas[1] == Isis::Null) ?
836 snprintf(buf, sizeof(buf),"\n CAMERA ANGULAR VELOCITY SIGMA: N/A"):
837 snprintf(buf, sizeof(buf),"\n CAMERA ANGULAR VELOCITY SIGMA: %lf (dd/s)",
838 pointingSigmas[1]);
839 fpOut << buf;
840
841 (pointingSolveDegree < 3 || pointingSigmas[2] == Isis::Null) ?
842 snprintf(buf, sizeof(buf),"\n CAMERA ANGULAR ACCELERATION SIGMA: N/A"):
843 snprintf(buf, sizeof(buf),"\n CAMERA ANGULAR ACCELERATION SIGMA: %lf (dd/s/s)",
844 pointingSigmas[2]);
845 fpOut << buf;
846
847 if (m_settings->solveTargetBody()) {
848 snprintf(buf, sizeof(buf), "\n\nINPUT: TARGET BODY OPTIONS\n==============================\n");
849 fpOut << buf;
850
851 if (m_settings->solvePoleRA() && m_settings->solvePoleDec()) {
852 snprintf(buf, sizeof(buf),"\n POLE: RIGHT ASCENSION");
853 fpOut << buf;
854 snprintf(buf, sizeof(buf),"\n : DECLINATION\n");
855 fpOut << buf;
856 }
857 else if (m_settings->solvePoleRA()) {
858 snprintf(buf, sizeof(buf),"\n POLE: RIGHT ASCENSION\n");
859 fpOut << buf;
860 }
861 else if (m_settings->solvePoleDec()) {
862 snprintf(buf, sizeof(buf),"\n POLE: DECLINATION\n");
863 fpOut << buf;
864 }
865
866 if (m_settings->solvePM() || m_settings->solvePMVelocity()
867 || m_settings->solvePMAcceleration()) {
868 snprintf(buf, sizeof(buf),"\n PRIME MERIDIAN: W0 (OFFSET)");
869 fpOut << buf;
870
871 if (m_settings->solvePMVelocity()) {
872 snprintf(buf, sizeof(buf),"\n : WDOT (SPIN RATE)");
873 fpOut << buf;
874 }
875 if (m_settings->solvePMAcceleration()) {
876 snprintf(buf, sizeof(buf),"\n :W ACCELERATION");
877 fpOut << buf;
878 }
879 }
880
881 if (m_settings->solveTriaxialRadii() || m_settings->solveMeanRadius()) {
882 if (m_settings->solveMeanRadius()) {
883 snprintf(buf, sizeof(buf),"\n RADII: MEAN");
884 fpOut << buf;
885 }
886 else if (m_settings->solveTriaxialRadii()) {
887 snprintf(buf, sizeof(buf),"\n RADII: TRIAXIAL");
888 fpOut << buf;
889 }
890 }
891 }
892
893 snprintf(buf, sizeof(buf), "\n\nJIGSAW: RESULTS\n===============\n");
894 fpOut << buf;
895 snprintf(buf, sizeof(buf), "\n Images: %6d",numImages);
896 fpOut << buf;
897 snprintf(buf, sizeof(buf), "\n Points: %6d",numValidPoints);
898 fpOut << buf;
899
900 if (numValidLidarPoints > 0) {
901 snprintf(buf, sizeof(buf), "\n Lidar Points: %6d",numValidLidarPoints);
902 fpOut << buf;
903 }
904
905 snprintf(buf, sizeof(buf), "\n Total Measures: %6d",
908 fpOut << buf;
909
910 snprintf(buf, sizeof(buf), "\n Total Observations: %6d",
913 fpOut << buf;
914
915 snprintf(buf, sizeof(buf), "\n Good Observations: %6d",
917 fpOut << buf;
918
919 snprintf(buf, sizeof(buf), "\n Rejected Observations: %6d",
921 fpOut << buf;
922
924 snprintf(buf, sizeof(buf), "\n Constrained Point Parameters: %6d",
926 fpOut << buf;
927 }
928
930 snprintf(buf, sizeof(buf), "\n Constrained Image Parameters: %6d",
932 fpOut << buf;
933 }
934
936 snprintf(buf, sizeof(buf), "\n Constrained Target Parameters: %6d",
938 fpOut << buf;
939 }
940
942 snprintf(buf, sizeof(buf), "\n Lidar Range Constraints: %6d",
944 fpOut << buf;
945 }
946
947 snprintf(buf, sizeof(buf), "\n Unknowns: %6d",
949 fpOut << buf;
950
951 if (numInnerConstraints > 0) {
952 snprintf(buf, sizeof(buf), "\n Inner Constraints: %6d", numInnerConstraints);
953 fpOut << buf;
954 }
955
956 if (numDistanceConstraints > 0) {
957 snprintf(buf, sizeof(buf), "\n Distance Constraints: %d", numDistanceConstraints);
958 fpOut << buf;
959 }
960
961 snprintf(buf, sizeof(buf), "\n Degrees of Freedom: %6d", numDegreesOfFreedom);
962 fpOut << buf;
963
964 snprintf(buf, sizeof(buf), "\n Convergence Criteria: %6.3g",
965 m_settings->convergenceCriteriaThreshold());
966 fpOut << buf;
967
968 if (convergenceCriteria == 1) {
969 snprintf(buf, sizeof(buf), "(Sigma0)");
970 fpOut << buf;
971 }
972
973 snprintf(buf, sizeof(buf), "\n Iterations: %6d", m_statisticsResults->iterations());
974 fpOut << buf;
975
976 if (m_statisticsResults->iterations() >= m_settings->convergenceCriteriaMaximumIterations()) {
977 snprintf(buf, sizeof(buf), "(Maximum reached)");
978 fpOut << buf;
979 }
980
981 snprintf(buf, sizeof(buf), "\n Sigma0: %30.20lf\n", m_statisticsResults->sigma0());
982 fpOut << buf;
983 snprintf(buf, sizeof(buf), " Error Propagation Elapsed Time: %6.4lf (seconds)\n",
985 fpOut << buf;
986 snprintf(buf, sizeof(buf), " Total Elapsed Time: %6.4lf (seconds)\n",
988 fpOut << buf;
991 > 100) {
992 snprintf(buf, sizeof(buf), "\n Residual Percentiles:\n");
993 fpOut << buf;
994
995 // residual prob distribution values are calculated/printed
996 // even if there is no maximum likelihood estimation
997 try {
998 for (int bin = 1;bin < 34;bin++) {
999 double cumProb = double(bin) / 100.0;
1000 double resValue =
1002 residualsCumulativeProbabilityDistribution().value(cumProb);
1003 double resValue33 =
1005 residualsCumulativeProbabilityDistribution().value(cumProb + 0.33);
1006 double resValue66 =
1008 residualsCumulativeProbabilityDistribution().value(cumProb + 0.66);
1009 snprintf(buf, sizeof(buf), " Percentile %3d: %+8.3lf"
1010 " Percentile %3d: %+8.3lf"
1011 " Percentile %3d: %+8.3lf\n",
1012 bin, resValue,
1013 bin + 33, resValue33,
1014 bin + 66, resValue66);
1015 fpOut << buf;
1016 }
1017 }
1018 catch (IException &e) {
1019 QString msg = "Failed to output residual percentiles for bundleout";
1020 throw IException(e, IException::Io, msg, _FILEINFO_);
1021 }
1022 try {
1023 snprintf(buf, sizeof(buf), "\n Residual Box Plot:");
1024 fpOut << buf;
1025 snprintf(buf, sizeof(buf), "\n minimum: %+8.3lf",
1027 fpOut << buf;
1028 snprintf(buf, sizeof(buf), "\n Quartile 1: %+8.3lf",
1030 fpOut << buf;
1031 snprintf(buf, sizeof(buf), "\n Median: %+8.3lf",
1033 fpOut << buf;
1034 snprintf(buf, sizeof(buf), "\n Quartile 3: %+8.3lf",
1036 fpOut << buf;
1037 snprintf(buf, sizeof(buf), "\n maximum: %+8.3lf\n",
1039 fpOut << buf;
1040 }
1041 catch (IException &e) {
1042 QString msg = "Failed to output residual box plot for bundleout";
1043 throw IException(e, IException::Io, msg, _FILEINFO_);
1044 }
1045 }
1046
1047 // Loop over the observations to find the longest file path/name in the
1048 // bunch
1049 int filePadding = 0;
1050
1051 for (int i = 0; i < numObservations; i++) {
1052
1053 int numImagesInObservation = m_statisticsResults->observations().at(i)->size();
1054
1055 for (int j = 0; j < numImagesInObservation; j++) {
1056 BundleImageQsp bundleImage = m_statisticsResults->observations().at(i)->at(j);
1057
1058 if (bundleImage->fileName().length() > filePadding) {
1059 filePadding = bundleImage->fileName().length();
1060 }
1061 }
1062 }
1063
1064 snprintf(buf, sizeof(buf), "\nIMAGE MEASURES SUMMARY\n==========================\n\n");
1065 fpOut << buf;
1066
1067 // Pad each element in the table with the space for the longest image
1068 // path/name then padd it the length of the element + 1
1069 QString header("Measures RMS(pixels)");
1071 header += " Lidar RMS(pixels)";
1072 }
1073 // This is padded by an extra 11 to move it center to the table
1074 snprintf(buf, sizeof(buf),"%*s\n", header.length() + 11 + filePadding, header.toLatin1().data());
1075 fpOut << buf;
1076
1077 QString dividers("*************************** *******************************************");
1079 dividers += " *******************************************";
1080 }
1081 snprintf(buf, sizeof(buf),"%*s\n", dividers.length() + 1 + filePadding, dividers.toLatin1().data());
1082 fpOut << buf;
1083
1084 QString fields("| Accepted | Total | | Samples | Lines | Total |");
1086 fields += " | Samples | Lines | Total |";
1087 }
1088 snprintf(buf, sizeof(buf),"%*s\n", fields.length() + 1 + filePadding, fields.toLatin1().data());
1089 fpOut << buf;
1090
1091 int numMeasures, numLidarMeasures;
1092 int numRejectedMeasures, numLidarRejectedMeasures;
1093 int numUsed, numLidarUsed;
1094 int imageIndex = 0;
1095 Statistics rmsSamplesTotal,rmsLinesTotal,rmsTotals;
1096
1097 for (int i = 0; i < numObservations; i++) {
1098
1099 int numImagesInObservation = m_statisticsResults->observations().at(i)->size();
1100
1101 for (int j = 0; j < numImagesInObservation; j++) {
1102
1103 BundleImageQsp bundleImage = m_statisticsResults->observations().at(i)->at(j);
1104
1105 double rmsSampleResiduals = m_statisticsResults->
1106 rmsImageSampleResiduals()[imageIndex].Rms();
1107 double rmsLineResiduals = m_statisticsResults->
1108 rmsImageLineResiduals()[imageIndex].Rms();
1109 double rmsLandSResiduals = m_statisticsResults->
1110 rmsImageResiduals()[imageIndex].Rms();
1111 rmsSamplesTotal.AddData(rmsSampleResiduals);
1112 rmsLinesTotal.AddData(rmsLineResiduals);
1113 rmsTotals.AddData(rmsLandSResiduals);
1114
1115 numMeasures = m_statisticsResults->outputControlNet()->GetNumberOfValidMeasuresInImage
1116 (bundleImage->serialNumber());
1117
1118 numRejectedMeasures = m_statisticsResults->outputControlNet()->
1119 GetNumberOfJigsawRejectedMeasuresInImage(bundleImage->serialNumber());
1120
1121 numUsed = numMeasures - numRejectedMeasures;
1122
1123 QString filename = bundleImage->fileName();
1124 QStringList List;
1125 List = filename.split("/");
1126
1127 snprintf(buf, sizeof(buf),"%-*s" ,filePadding + 1, bundleImage->fileName().toLatin1().data());
1128 fpOut << buf;
1129
1130 snprintf(buf, sizeof(buf), " %12d %12d ", numUsed, numMeasures);
1131 fpOut << buf;
1132
1133 snprintf(buf, sizeof(buf),"%13.4lf %13.4lf %13.4lf",
1134 rmsSampleResiduals,rmsLineResiduals,rmsLandSResiduals);
1135
1136 fpOut << buf;
1137
1139 double rmsLidarSampleResiduals = m_statisticsResults->
1140 rmsLidarImageSampleResiduals()[imageIndex].Rms();
1141 double rmsLidarLineResiduals = m_statisticsResults->
1142 rmsLidarImageLineResiduals()[imageIndex].Rms();
1143 double rmsLidarLandSResiduals = m_statisticsResults->
1144 rmsLidarImageResiduals()[imageIndex].Rms();
1145
1146 numLidarMeasures = m_statisticsResults->outputLidarData()->
1147 GetNumberOfValidMeasuresInImage(bundleImage->serialNumber());
1148
1149 numLidarRejectedMeasures = m_statisticsResults->outputLidarData()->
1150 GetNumberOfJigsawRejectedMeasuresInImage(bundleImage->serialNumber());
1151
1152 numLidarUsed = numLidarMeasures - numLidarRejectedMeasures;
1153
1154 snprintf(buf, sizeof(buf), " %12d %12d ", numLidarUsed, numLidarMeasures);
1155 fpOut << buf;
1156
1157 snprintf(buf, sizeof(buf),"%13.4lf %13.4lf %13.4lf",
1158 rmsLidarSampleResiduals,rmsLidarLineResiduals,rmsLidarLandSResiduals);
1159
1160 fpOut << buf;
1161 }
1162
1163 snprintf(buf, sizeof(buf), " \n");
1164 fpOut << buf;
1165 imageIndex++;
1166 }
1167 }
1168
1169 // Do something similar to above but left justify the string and add a 33
1170 // character buffer
1171 snprintf(buf, sizeof(buf),"%*s", -(filePadding + 33), "\nTotal RMS:");
1172 fpOut << buf;
1173 snprintf(buf, sizeof(buf),"%13.4lf %13.4lf %13.4lf\n",
1174 rmsSamplesTotal.Rms(),rmsLinesTotal.Rms(),rmsTotals.Rms());
1175 fpOut << buf;
1176
1177 return true;
1178 }
1179
1180
1193
1194 char buf[1056];
1195
1196 QList<Statistics> rmsImageSampleResiduals = m_statisticsResults->rmsImageSampleResiduals();
1197 QList<Statistics> rmsImageLineResiduals = m_statisticsResults->rmsImageLineResiduals();
1198 QList<Statistics> rmsImageResiduals = m_statisticsResults->rmsImageResiduals();
1199
1200 bool errorProp = false;
1201 if (m_statisticsResults->converged() && m_settings->errorPropagation()) {
1202 errorProp = true;
1203 }
1204
1205 QList<QString> outputCsvFileNames;
1206 QList<QString> instrumentIds = m_statisticsResults->observations().instrumentIds();
1207 // If there's just a single instrumentId just call it bundleout_images.csv
1208 if (instrumentIds.size() == 1) {
1209 QString ofname = "bundleout_images.csv";
1210 ofname = m_settings->outputFilePrefix() + ofname;
1211 m_csvSavedImagesFilename = ofname;
1212 outputCsvFileNames.push_back(ofname);
1213 }
1214 // Otherwise append the instrument IDs so it's bundleout_images_spacecraft_sensor.csv
1215 else {
1216 for (int i = 0; i < instrumentIds.size(); i++) {
1217 QString updatedInstrumentId = instrumentIds[i];
1218 // Replace and "/" or " " characters with "_" to make the filename safer
1219 // This line must be separate to avoid modifying the instrumentId in the list
1220 // we will iterate over later
1221 updatedInstrumentId.replace("/", "_").replace(" ", "_");
1222 QString ofname = "bundleout_images_" + updatedInstrumentId + ".csv";
1223 ofname = m_settings->outputFilePrefix() + ofname;
1224 m_csvSavedImagesFilename = ofname;
1225 outputCsvFileNames.push_back(ofname);
1226 }
1227 }
1228
1229 for (int i = 0; i < instrumentIds.size(); i++) {
1230
1231 std::ofstream fpOut(outputCsvFileNames[i].toLatin1().data(), std::ios::out);
1232 if (!fpOut) {
1233 return false;
1234 }
1235
1236 QList<BundleObservationQsp> observations =
1237 m_statisticsResults->observations().observationsByInstId(instrumentIds[i]);
1238
1239 int nObservations = observations.size();
1240
1241 outputImagesCSVHeader(fpOut, observations.front());
1242
1243 for (int j = 0; j < nObservations; j++ ) {
1244 BundleObservationQsp observation = observations[j];
1245
1246 // We need the image index, not the observation index,
1247 // so count all of the images prior to this observation
1248 int observationIndex = observation->index();
1249 int imgIndex = 0;
1250 for (int obsIndex = 0; obsIndex < observationIndex; obsIndex++) {
1251 imgIndex += m_statisticsResults->observations().at(obsIndex)->size();
1252 }
1253
1254 if(!observation) {
1255 continue;
1256 }
1257
1258 int numImages = observation->size();
1259
1260 for (int k = 0; k < numImages; k++) {
1261 BundleImageQsp image = observation->at(k);
1262
1263 snprintf(buf, sizeof(buf), "%s", image->fileName().toLatin1().data());
1264 fpOut << buf;
1265 snprintf(buf, sizeof(buf),",");
1266 fpOut << buf;
1267
1268 fpOut << toString(rmsImageSampleResiduals[imgIndex].Rms()).toLatin1().data();
1269 snprintf(buf, sizeof(buf),",");
1270 fpOut << buf;
1271
1272 fpOut << toString(rmsImageLineResiduals[imgIndex].Rms()).toLatin1().data();
1273 snprintf(buf, sizeof(buf),",");
1274 fpOut << buf;
1275
1276 fpOut << toString(rmsImageResiduals[imgIndex].Rms()).toLatin1().data();
1277 snprintf(buf, sizeof(buf),",");
1278 fpOut << buf;
1279
1280 QString observationString =
1281 observation->bundleOutputCSV(errorProp);
1282
1283 //Removes trailing commas
1284 if (observationString.right(1)==",") {
1285 observationString.truncate(observationString.length()-1);
1286 }
1287
1288 fpOut << (const char*) observationString.toLatin1().data();
1289
1290 snprintf(buf, sizeof(buf),"\n");
1291 fpOut << buf;
1292 imgIndex++;
1293
1294 }
1295 }
1296 fpOut.close();
1297 }
1298
1299 return true;
1300 }
1301
1302
1309
1310 QString ofname = "bundleout.txt";
1311 ofname = m_settings->outputFilePrefix() + ofname;
1312
1313 std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
1314 if (!fpOut) {
1315 return false;
1316 }
1317
1318 m_txtBundleOutputFilename = ofname;
1319
1320 char buf[4096];
1321 BundleObservationQsp observation;
1322
1323 int nObservations = m_statisticsResults->observations().size();
1324
1325 outputHeader(fpOut);
1326
1327 bool berrorProp = false;
1328 if (m_statisticsResults->converged() && m_settings->errorPropagation()) {
1329 berrorProp = true;
1330 }
1331
1332 // output target body header if solving for target
1333 if (m_settings->solveTargetBody()) {
1334 snprintf(buf, sizeof(buf), "\nTARGET BODY\n==========================\n");
1335 fpOut << buf;
1336
1337 snprintf(buf, sizeof(buf), "\n Target Initial Total "
1338 "Final Initial Final\n"
1339 "Parameter Value Correction "
1340 "Value Accuracy Accuracy\n");
1341 fpOut << buf;
1342
1343 QString targetString =
1344 m_settings->bundleTargetBody()->formatBundleOutputString(berrorProp);
1345 fpOut << (const char*)targetString.toLatin1().data();
1346 }
1347
1348 // output image exterior orientation header
1349 snprintf(buf, sizeof(buf), "\nIMAGE EXTERIOR ORIENTATION\n==========================\n");
1350 fpOut << buf;
1351
1352 QMap<QString, QStringList> imagesAndParameters;
1353
1354 if (m_settings->solveTargetBody()) {
1355 imagesAndParameters.insert( "target", m_settings->bundleTargetBody()->parameterList() );
1356 }
1357
1358 for (int i = 0; i < nObservations; i++) {
1359
1360 observation = m_statisticsResults->observations().at(i);
1361 if (!observation) {
1362 continue;
1363 }
1364
1365 int numImages = observation->size();
1366 for (int j = 0; j < numImages; j++) {
1367 BundleImageQsp image = observation->at(j);
1368 snprintf(buf, sizeof(buf), "\nImage Full File Name: %s\n", image->fileName().toLatin1().data());
1369 fpOut << buf;
1370 snprintf(buf, sizeof(buf), "\nImage Serial Number: %s\n", image->serialNumber().toLatin1().data());
1371 fpOut << buf;
1372
1373 snprintf(buf, sizeof(buf),"Image Initial Total Final Accuracy\n");
1374 fpOut << buf;
1375 snprintf(buf, sizeof(buf),"Parameter Value Correction Value Initial Final Units\n");
1376 fpOut << buf;
1377
1378 snprintf(buf, sizeof(buf)," "
1379 "***************************************\n");
1380 fpOut << buf;
1381
1382 observation->bundleOutputString(fpOut,berrorProp);
1383 // Build list of images and parameters for correlation matrix.
1384 foreach ( QString image, observation->imageNames() ) {
1385 imagesAndParameters.insert( image, observation->parameterList() );
1386 }
1387 }
1388 }
1389
1390 // Save list of images and their associated parameters for CorrelationMatrix to use in ice.
1391 m_statisticsResults->setCorrMatImgsAndParams(imagesAndParameters);
1392
1393 // Save list of images and their associated parameters for CorrelationMatrix to use in ice.
1394 m_statisticsResults->setCorrMatImgsAndParams(imagesAndParameters);
1395
1396 // output point uncertainty statistics if error propagation is on
1397 if (berrorProp) {
1398 snprintf(buf, sizeof(buf), "\n\n\nPOINTS UNCERTAINTY SUMMARY\n==========================\n\n");
1399 fpOut << buf;
1400
1401 // Coordinate 1 (latitude or point x) summary
1402 QString
1403 coordName = surfacePointCoordName(m_settings->controlPointCoordTypeReports(),
1404 SurfacePoint::One);
1405 snprintf(buf, sizeof(buf), "RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(),
1407 fpOut << buf;
1408 snprintf(buf, sizeof(buf), "MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
1410 m_statisticsResults->minSigmaCoord1PointId().toLatin1().data());
1411 fpOut << buf;
1412 snprintf(buf, sizeof(buf), "MAX Sigma %s(m)%20.8lf at %s\n\n", coordName.toLatin1().data(),
1414 m_statisticsResults->maxSigmaCoord1PointId().toLatin1().data());
1415 fpOut << buf;
1416
1417 // Coordinate 2 (longitude or point y) summary
1418 coordName = surfacePointCoordName(m_settings->controlPointCoordTypeReports(),
1419 SurfacePoint::Two);
1420 snprintf(buf, sizeof(buf), "RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(),
1422 fpOut << buf;
1423 snprintf(buf, sizeof(buf), "MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
1425 m_statisticsResults->minSigmaCoord2PointId().toLatin1().data());
1426 fpOut << buf;
1427 snprintf(buf, sizeof(buf), "MAX Sigma %s(m)%20.8lf at %s\n\n", coordName.toLatin1().data(),
1429 m_statisticsResults->maxSigmaCoord2PointId().toLatin1().data());
1430 fpOut << buf;
1431
1432 // Coordinate 3 (radius or point z) summary
1433 coordName = surfacePointCoordName(m_settings->controlPointCoordTypeReports(),
1434 SurfacePoint::Three);
1435 if ( m_settings->solveRadius() ) {
1436 snprintf(buf, sizeof(buf), "RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(),
1438 fpOut << buf;
1439 snprintf(buf, sizeof(buf), "MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
1441 m_statisticsResults->minSigmaCoord3PointId().toLatin1().data());
1442 fpOut << buf;
1443 snprintf(buf, sizeof(buf), "MAX Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
1445 m_statisticsResults->maxSigmaCoord3PointId().toLatin1().data());
1446 fpOut << buf;
1447 }
1448 else {
1449 snprintf(buf, sizeof(buf), " RMS Sigma Radius(m) N/A\n");
1450 fpOut << buf;
1451 snprintf(buf, sizeof(buf), " MIN Sigma Radius(m) N/A\n");
1452 fpOut << buf;
1453 snprintf(buf, sizeof(buf), " MAX Sigma Radius(m) N/A\n");
1454 fpOut << buf;
1455 }
1456 }
1457
1458 // output point summary data header
1459 if (m_settings->controlPointCoordTypeReports() == SurfacePoint::Latitudinal) {
1460 snprintf(buf, sizeof(buf), "\n\nPOINTS SUMMARY\n==============\n%103s"
1461 "Sigma Sigma Sigma\n"
1462 " Label Status Rays RMS"
1463 " Latitude Longitude Radius"
1464 " Latitude Longitude Radius\n", "");
1465 }
1466 else { // Must be Rectangular
1467 snprintf(buf, sizeof(buf), "\n\nPOINTS SUMMARY\n==============\n%103s"
1468 "Sigma Sigma Sigma\n"
1469 " Label Status Rays RMS"
1470 " Point X Point Y Point Z"
1471 " Point X Point Y Point Z\n", "");
1472 }
1473 fpOut << buf;
1474
1475 int nPoints = m_statisticsResults->bundleControlPoints().size();
1476 for (int i = 0; i < nPoints; i++) {
1478
1479 QString pointSummaryString =
1480 bundleControlPoint->formatBundleOutputSummaryString(berrorProp);
1481 fpOut << (const char*)pointSummaryString.toLatin1().data();
1482 }
1483
1484 int nLidarPoints = m_statisticsResults->bundleLidarControlPoints().size();
1485 for (int i = 0; i < nLidarPoints; i++) {
1486 BundleLidarControlPointQsp lidarControlPoint
1488
1489 QString pointSummaryString =
1490 lidarControlPoint->formatBundleOutputSummaryString(berrorProp);
1491 fpOut << (const char*)pointSummaryString.toLatin1().data();
1492 }
1493
1494 // output point detail data header
1495 snprintf(buf, sizeof(buf), "\n\nPOINTS DETAIL\n=============\n\n");
1496 fpOut << buf;
1497
1498 bool solveRadius = m_settings->solveRadius();
1499
1500 for (int i = 0; i < nPoints; i++) {
1502
1503 // Removed radiansToMeters argument 9/18/2018 DAC
1504 QString pointDetailString =
1505 bundleControlPoint->formatBundleOutputDetailString(berrorProp, solveRadius);
1506 fpOut << (const char*)pointDetailString.toLatin1().data();
1507 }
1508
1509 for (int i = 0; i < nLidarPoints; i++) {
1510 BundleLidarControlPointQsp bundleLidarControlPoint =
1512
1513 QString pointDetailString =
1514 bundleLidarControlPoint->formatBundleOutputDetailString(berrorProp, solveRadius);
1515 fpOut << (const char*)pointDetailString.toLatin1().data();
1516 }
1517
1518 fpOut.close();
1519
1520 return true;
1521 }
1522
1523
1530 char buf[1056];
1531
1532 QString ofname = "bundleout_points.csv";
1533 ofname = m_settings->outputFilePrefix() + ofname;
1534 m_csvSavedPointsFilename = ofname;
1535
1536 std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
1537 if (!fpOut) {
1538 return false;
1539 }
1540
1541 int numPoints = m_statisticsResults->bundleControlPoints().size();
1542
1543 double dLat, dLon, dRadius;
1544 double dX, dY, dZ;
1545 double dSigmaLat, dSigmaLong, dSigmaRadius;
1546 QString strStatus;
1547 double cor_lat_m;
1548 double cor_lon_m;
1549 double cor_rad_m;
1550 int numMeasures, numRejectedMeasures;
1551 double dResidualRms;
1552
1553 // print column headers
1554 if (m_settings->errorPropagation()) {
1555 snprintf(buf, sizeof(buf), ",,,,,3-d,3-d,3-d,Sigma,Sigma,Sigma,Correction,Correction,Correction,Coordinate,"
1556 "Coordinate,Coordinate\nPoint,Point,Accepted,Rejected,Residual,Latitude,Longitude,"
1557 "Radius,Latitude,Longitude,Radius,Latitude,Longitude,Radius,X,Y,Z\nLabel,Status,"
1558 "Measures,Measures,RMS,(dd),(dd),(km),(m),(m),(m),(m),(m),(m),(km),(km),(km)\n");
1559 }
1560 else {
1561 snprintf(buf, sizeof(buf), ",,,,,3-d,3-d,3-d,Correction,Correction,Correction,Coordinate,Coordinate,"
1562 "Coordinate\nPoint,Point,Accepted,Rejected,Residual,Latitude,Longitude,Radius,"
1563 "Latitude,Longitude,Radius,X,Y,Z\nLabel,Status,Measures,Measures,RMS,(dd),(dd),(km),"
1564 "(m),(m),(m),(km),(km),(km)\n");
1565 }
1566 fpOut << buf;
1567
1568 for (int i = 0; i < numPoints; i++) {
1570
1571 if (!bundlecontrolpoint) {
1572 continue;
1573 }
1574
1575 if (bundlecontrolpoint->isRejected()) {
1576 continue;
1577 }
1578
1579 dLat = bundlecontrolpoint->adjustedSurfacePoint().GetLatitude().degrees();
1580 dLon = bundlecontrolpoint->adjustedSurfacePoint().GetLongitude().degrees();
1581 dRadius = bundlecontrolpoint->adjustedSurfacePoint().GetLocalRadius().kilometers();
1582 dX = bundlecontrolpoint->adjustedSurfacePoint().GetX().kilometers();
1583 dY = bundlecontrolpoint->adjustedSurfacePoint().GetY().kilometers();
1584 dZ = bundlecontrolpoint->adjustedSurfacePoint().GetZ().kilometers();
1585 numMeasures = bundlecontrolpoint->numberOfMeasures();
1586 numRejectedMeasures = bundlecontrolpoint->numberOfRejectedMeasures();
1587 dResidualRms = bundlecontrolpoint->residualRms();
1588
1589 // point corrections and initial sigmas
1590 boost::numeric::ublas::bounded_vector< double, 3 > corrections = bundlecontrolpoint->
1591 corrections();
1592 // Now use the local radius to convert radians to meters instead of the target body equatorial radius
1593 cor_lat_m = bundlecontrolpoint->adjustedSurfacePoint().LatitudeToMeters(corrections[0]);
1594 cor_lon_m = bundlecontrolpoint->adjustedSurfacePoint().LongitudeToMeters(corrections[1]);
1595 cor_rad_m = corrections[2]*1000.0;
1596
1597 if (bundlecontrolpoint->type() == ControlPoint::Fixed) {
1598 strStatus = "FIXED";
1599 }
1600 else if (bundlecontrolpoint->type() == ControlPoint::Constrained) {
1601 strStatus = "CONSTRAINED";
1602 }
1603 else if (bundlecontrolpoint->type() == ControlPoint::Free) {
1604 strStatus = "FREE";
1605 }
1606 else {
1607 strStatus = "UNKNOWN";
1608 }
1609
1610 if (m_settings->errorPropagation()) {
1611 dSigmaLat = bundlecontrolpoint->adjustedSurfacePoint().GetLatSigmaDistance().meters();
1612 dSigmaLong = bundlecontrolpoint->adjustedSurfacePoint().GetLonSigmaDistance().meters();
1613 dSigmaRadius = bundlecontrolpoint->adjustedSurfacePoint().GetLocalRadiusSigma().meters();
1614
1615 snprintf(buf, sizeof(buf), "%s,%s,%d,%d,%6.2lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,"
1616 "%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf\n",
1617 bundlecontrolpoint->id().toLatin1().data(), strStatus.toLatin1().data(),
1618 numMeasures, numRejectedMeasures, dResidualRms, dLat, dLon, dRadius, dSigmaLat,
1619 dSigmaLong, dSigmaRadius, cor_lat_m, cor_lon_m, cor_rad_m, dX, dY, dZ);
1620 }
1621 else
1622 snprintf(buf, sizeof(buf), "%s,%s,%d,%d,%6.2lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,"
1623 "%16.8lf,%16.8lf\n",
1624 bundlecontrolpoint->id().toLatin1().data(), strStatus.toLatin1().data(),
1625 numMeasures, numRejectedMeasures, dResidualRms, dLat, dLon, dRadius, cor_lat_m,
1626 cor_lon_m, cor_rad_m, dX, dY, dZ);
1627
1628 fpOut << buf;
1629 }
1630
1631 fpOut.close();
1632
1633 return true;
1634 }
1635
1636
1643 char buf[1056];
1644
1645 QString ofname = "bundleout_lidar.csv";
1646 ofname = m_settings->outputFilePrefix() + ofname;
1647 m_csvSavedPointsFilename = ofname;
1648
1649 std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
1650 if (!fpOut) {
1651 return false;
1652 }
1653
1654 int numPoints = m_statisticsResults->bundleLidarControlPoints().size();
1655
1656 // measured apriori adjusted adjusted
1657 // range sigma range residual sigma
1658 // point id image (km) (km) (km) (km) (km)
1659
1660 // print column headers
1661 if (m_settings->errorPropagation()) {
1662 snprintf(buf, sizeof(buf), ",,measured,a priori,adjusted,adjusted\n"
1663 "point,image,range,sigma,range,sigma,residual\n"
1664 "id,name,(km),(km),(km),(km),(km)\n");
1665 }
1666 else {
1667 snprintf(buf, sizeof(buf), ",,measured,a priori,adjusted\n"
1668 "point,image,range,sigma,range,residual\n"
1669 "id,name,(km),(km),(km),(km)\n");
1670 }
1671 fpOut << buf;
1672
1673 for (int i = 0; i < numPoints; i++) {
1674
1676 if (!point || point->isRejected()) {
1677 continue;
1678 }
1679
1680 int nRangeConstraints = point->numberRangeConstraints();
1681 for (int j = 0; j < nRangeConstraints; j++) {
1682 BundleLidarRangeConstraintQsp rangeConstraint = point->rangeConstraint(j);
1683
1684 QString str = rangeConstraint->formatBundleOutputString(m_settings->errorPropagation());
1685 fpOut << str;
1686 }
1687 }
1688
1689 fpOut.close();
1690
1691 return true;
1692 }
1693
1694
1701 char buf[1056];
1702
1703 QString ofname = "residuals.csv";
1704 ofname = m_settings->outputFilePrefix() + ofname;
1705 m_csvSavedResidualsFilename = ofname;
1706
1707 std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
1708 if (!fpOut) {
1709 return false;
1710 }
1711
1712 // output column headers
1713
1714 snprintf(buf, sizeof(buf), ",,,x image,y image,Measured,Measured,sample,line,Residual Vector\n");
1715 fpOut << buf;
1716 snprintf(buf, sizeof(buf), "Point,Image,Image,coordinate,coordinate,"
1717 "Sample,Line,residual,residual,Magnitude\n");
1718 fpOut << buf;
1719 snprintf(buf, sizeof(buf), "Label,Filename,Serial Number,(mm),(mm),"
1720 "(pixels),(pixels),(pixels),(pixels),(pixels),Rejected\n");
1721 fpOut << buf;
1722
1723 // Setup counts and pointers
1724
1725 int numPoints = m_statisticsResults->bundleControlPoints().size();
1726 int numMeasures = 0;
1727
1728 BundleControlPointQsp bundleControlPoint;
1729 BundleMeasureQsp bundleMeasure;
1730
1731 for (int i = 0; i < numPoints; i++) {
1732 bundleControlPoint = m_statisticsResults->bundleControlPoints().at(i);
1733 numMeasures = bundleControlPoint->size();
1734
1735 if (bundleControlPoint->rawControlPoint()->IsIgnored()) {
1736 continue;
1737 }
1738
1739 for (int j = 0; j < numMeasures; j++) {
1740 bundleMeasure = bundleControlPoint->at(j);
1741
1742 Camera *measureCamera = bundleMeasure->camera();
1743 if (!measureCamera) {
1744 continue;
1745 }
1746
1747 if (bundleMeasure->isRejected()) {
1748 snprintf(buf, sizeof(buf), "%s,%s,%s,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,*\n",
1749 bundleControlPoint->id().toLatin1().data(),
1750 bundleMeasure->parentBundleImage()->fileName().toLatin1().data(),
1751 bundleMeasure->cubeSerialNumber().toLatin1().data(),
1752 bundleMeasure->focalPlaneMeasuredX(),
1753 bundleMeasure->focalPlaneMeasuredY(),
1754 bundleMeasure->sample(),
1755 bundleMeasure->line(),
1756 bundleMeasure->sampleResidual(),
1757 bundleMeasure->lineResidual(),
1758 bundleMeasure->residualMagnitude());
1759 }
1760 else {
1761 snprintf(buf, sizeof(buf), "%s,%s,%s,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf\n",
1762 bundleControlPoint->id().toLatin1().data(),
1763 bundleMeasure->parentBundleImage()->fileName().toLatin1().data(),
1764 bundleMeasure->cubeSerialNumber().toLatin1().data(),
1765 bundleMeasure->focalPlaneMeasuredX(),
1766 bundleMeasure->focalPlaneMeasuredY(),
1767 bundleMeasure->sample(),
1768 bundleMeasure->line(),
1769 bundleMeasure->sampleResidual(),
1770 bundleMeasure->lineResidual(),
1771 bundleMeasure->residualMagnitude());
1772 }
1773 fpOut << buf;
1774 }
1775 }
1776
1777 numPoints = m_statisticsResults->bundleLidarControlPoints().size();
1778 numMeasures = 0;
1779
1780 BundleLidarControlPointQsp bundleLidarPoint;
1781
1782 for (int i = 0; i < numPoints; i++) {
1783 bundleLidarPoint = m_statisticsResults->bundleLidarControlPoints().at(i);
1784 numMeasures = bundleLidarPoint->size();
1785
1786 if (bundleLidarPoint->rawControlPoint()->IsIgnored()) {
1787 continue;
1788 }
1789
1790 for (int j = 0; j < numMeasures; j++) {
1791 bundleMeasure = bundleLidarPoint->at(j);
1792
1793 Camera *measureCamera = bundleMeasure->camera();
1794 if (!measureCamera) {
1795 continue;
1796 }
1797
1798 if (bundleMeasure->isRejected()) {
1799 snprintf(buf, sizeof(buf), "%s,%s,%s,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,*\n",
1800 bundleLidarPoint->id().toLatin1().data(),
1801 bundleMeasure->parentBundleImage()->fileName().toLatin1().data(),
1802 bundleMeasure->cubeSerialNumber().toLatin1().data(),
1803 bundleMeasure->focalPlaneMeasuredX(),
1804 bundleMeasure->focalPlaneMeasuredY(),
1805 bundleMeasure->sample(),
1806 bundleMeasure->line(),
1807 bundleMeasure->sampleResidual(),
1808 bundleMeasure->lineResidual(),
1809 bundleMeasure->residualMagnitude());
1810 }
1811 else {
1812 snprintf(buf, sizeof(buf), "%s,%s,%s,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf\n",
1813 bundleLidarPoint->id().toLatin1().data(),
1814 bundleMeasure->parentBundleImage()->fileName().toLatin1().data(),
1815 bundleMeasure->cubeSerialNumber().toLatin1().data(),
1816 bundleMeasure->focalPlaneMeasuredX(),
1817 bundleMeasure->focalPlaneMeasuredY(),
1818 bundleMeasure->sample(),
1819 bundleMeasure->line(),
1820 bundleMeasure->sampleResidual(),
1821 bundleMeasure->lineResidual(),
1822 bundleMeasure->residualMagnitude());
1823 }
1824 fpOut << buf;
1825 }
1826 }
1827
1828 fpOut.close();
1829
1830 return true;
1831 }
1832
1833
1850 void BundleSolutionInfo::save(QXmlStreamWriter &stream, const Project *project,
1851 FileName newProjectRoot) const {
1852
1853 // This is done for testing serialization without a Project
1854 QString relativePath;
1855 QString relativeBundlePath;
1856 FileName bundleSolutionInfoRoot;
1857
1858 if (project) {
1859 bundleSolutionInfoRoot = FileName(Project::bundleSolutionInfoRoot(newProjectRoot.expanded()) +
1860 "/" + runTime());
1861 QString oldPath = project->bundleSolutionInfoRoot(project->projectRoot()) + "/" + runTime();
1862 QString newPath = project->bundleSolutionInfoRoot(newProjectRoot.toString()) + "/" + runTime();
1863 // If project is being saved to new area, create directory and copy files
1864 if (oldPath != newPath) {
1865 // Create project folder for BundleSolutionInfo
1866 QDir bundleDir(newPath);
1867 if (!bundleDir.mkpath(bundleDir.path())) {
1869 QString("Failed to create directory [%1]")
1870 .arg(bundleSolutionInfoRoot.path()),
1871 _FILEINFO_);
1872 }
1873 QString oldFile = oldPath + "/" + FileName(m_outputControl->fileName()).name();
1874 QString newFile = newPath + "/" + FileName(m_outputControl->fileName()).name();
1875 if (!QFile::copy(oldFile, newFile)) {
1877 QString("Failed to copy file [%1] to new file [%2]")
1878 .arg(m_outputControl->fileName()).arg(newFile),
1879 _FILEINFO_);
1880 }
1881 newFile = newPath + "/" + FileName(m_txtBundleOutputFilename).name();
1882 if (!QFile::copy(m_txtBundleOutputFilename, newFile)) {
1884 QString("Failed to copy file [%1] to new file [%2]")
1885 .arg(m_txtBundleOutputFilename).arg(newFile),
1886 _FILEINFO_);
1887 }
1888 newFile = newPath + "/" + FileName(m_csvSavedImagesFilename).name();
1889 if (!QFile::copy(m_csvSavedImagesFilename, newFile)) {
1891 QString("Failed to copy file [%1] to new file [%2]")
1892 .arg(m_csvSavedImagesFilename).arg(newFile),
1893 _FILEINFO_);
1894 }
1895 newFile = newPath + "/" + FileName(m_csvSavedPointsFilename).name();
1896 if (!QFile::copy(m_csvSavedPointsFilename, newFile)) {
1898 QString("Failed to copy file [%1] to new file [%2]")
1899 .arg(m_csvSavedPointsFilename).arg(newFile),
1900 _FILEINFO_);
1901 }
1902 newFile = newPath + "/" + FileName(m_csvSavedResidualsFilename).name();
1903 if (!QFile::copy(m_csvSavedResidualsFilename, newFile)) {
1905 QString("Failed to copy file [%1] to new file [%2]")
1906 .arg(m_csvSavedResidualsFilename).arg(newFile),
1907 _FILEINFO_);
1908 }
1909 }
1910
1911 // Create relativePath
1912 relativePath = m_inputControlNetFileName->expanded().remove(project->newProjectRoot());
1913 // Get rid of any preceding "/" , but add on ending "/"
1914 if (relativePath.startsWith("/")) {
1915 relativePath.remove(0,1);
1916 }
1917
1918 // Create relativeBundlePath for bundleSolutionInfo
1919 relativeBundlePath = newPath.remove(project->newProjectRoot());
1920 // Get rid of any preceding "/" , but add on ending "/"
1921 if (relativeBundlePath.startsWith("/")) {
1922 relativeBundlePath.remove(0,1);
1923 }
1924 relativeBundlePath += "/";
1925 }
1926
1927 stream.writeStartElement("bundleSolutionInfo");
1928 // save ID, cnet file name, and run time to stream
1929 stream.writeStartElement("generalAttributes");
1930 stream.writeTextElement("id", m_id->toString());
1931 stream.writeTextElement("name", m_name);
1932 stream.writeTextElement("runTime", runTime());
1933
1934 stream.writeTextElement("inputFileName",
1935 relativePath);
1936 stream.writeTextElement("bundleOutTXT",
1937 relativeBundlePath + FileName(m_txtBundleOutputFilename).name());
1938 stream.writeTextElement("imagesCSV",
1939 relativeBundlePath + FileName(m_csvSavedImagesFilename).name());
1940 stream.writeTextElement("pointsCSV",
1941 relativeBundlePath + FileName(m_csvSavedPointsFilename).name());
1942 stream.writeTextElement("residualsCSV",
1943 relativeBundlePath + FileName(m_csvSavedResidualsFilename).name());
1944 stream.writeEndElement(); // end general attributes
1945
1946 // save settings to stream
1947 m_settings->save(stream, project);
1948
1949 // save statistics to stream
1950 m_statisticsResults->save(stream, project);
1951
1952 if (project) {
1953 // save adjusted images lists to stream
1954 if (!m_adjustedImages->isEmpty()) {
1955 stream.writeStartElement("imageLists");
1956 for (int i = 0; i < m_adjustedImages->count(); i++) {
1957 m_adjustedImages->at(i)->save(stream, project, bundleSolutionInfoRoot);
1958 }
1959 stream.writeEndElement();
1960 }
1961
1962 // save output control
1963 stream.writeStartElement("outputControl");
1964 m_outputControl->save(stream, project, relativeBundlePath);
1965 stream.writeEndElement();
1966 }
1967
1968 stream.writeEndElement(); //end bundleSolutionInfo
1969 }
1970
1971
1980 Project *project) {
1981 m_xmlHandlerBundleSolutionInfo = bundleSolutionInfo;
1982 m_xmlHandlerProject = project;
1984 }
1985
1986
1992
1993
2002 m_xmlHandlerCharacters += ch;
2003 return XmlStackedHandler::characters(ch);
2004 }
2005
2006
2017 bool BundleSolutionInfo::XmlHandler::startElement(const QString &namespaceURI,
2018 const QString &localName,
2019 const QString &qName,
2020 const QXmlAttributes &atts) {
2021 m_xmlHandlerCharacters = "";
2022
2023 if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {
2024
2025 if (localName == "bundleSettings") {
2026 m_xmlHandlerBundleSolutionInfo->m_settings =
2027 BundleSettingsQsp(new BundleSettings(m_xmlHandlerProject, reader()));
2028 }
2029 else if (localName == "bundleResults") {
2030 m_xmlHandlerBundleSolutionInfo->m_statisticsResults = new BundleResults(m_xmlHandlerProject,
2031 reader());
2032 }
2033 else if (localName == "imageList") {
2034 m_xmlHandlerBundleSolutionInfo->m_adjustedImages->append(
2035 new ImageList(m_xmlHandlerProject, reader()));
2036 }
2037 else if (localName == "outputControl") {
2038 FileName outputControlPath = FileName(m_xmlHandlerProject->bundleSolutionInfoRoot() + "/"
2039 + m_xmlHandlerBundleSolutionInfo->runTime());
2040
2041 m_xmlHandlerBundleSolutionInfo->m_outputControl = new Control(outputControlPath, reader());
2042 }
2043 }
2044 return true;
2045 }
2046
2047
2057 bool BundleSolutionInfo::XmlHandler::endElement(const QString &namespaceURI,
2058 const QString &localName,
2059 const QString &qName) {
2060 // This is done for unitTest which has no Project
2061 QString projectRoot;
2062 if (m_xmlHandlerProject) {
2063 projectRoot = m_xmlHandlerProject->projectRoot() + "/";
2064 }
2065
2066 if (localName == "id") {
2067 // all constructors assign a Uuid - we need to give it a one from the XML
2068 assert(m_xmlHandlerBundleSolutionInfo->m_id);
2069 delete m_xmlHandlerBundleSolutionInfo->m_id;
2070 m_xmlHandlerBundleSolutionInfo->m_id = new QUuid(m_xmlHandlerCharacters);
2071 }
2072 else if (localName == "name") {
2073 m_xmlHandlerBundleSolutionInfo->m_name = m_xmlHandlerCharacters;
2074 }
2075 else if (localName == "runTime") {
2076 m_xmlHandlerBundleSolutionInfo->m_runTime = m_xmlHandlerCharacters;
2077 }
2078 else if (localName == "inputFileName") {
2079 assert(m_xmlHandlerBundleSolutionInfo->m_inputControlNetFileName == NULL);
2080 m_xmlHandlerBundleSolutionInfo->m_inputControlNetFileName = new FileName(
2081 projectRoot + m_xmlHandlerCharacters);
2082 }
2083 else if (localName == "bundleOutTXT") {
2084 m_xmlHandlerBundleSolutionInfo->m_txtBundleOutputFilename =
2085 projectRoot + m_xmlHandlerCharacters;
2086 }
2087 else if (localName == "imagesCSV") {
2088 m_xmlHandlerBundleSolutionInfo->m_csvSavedImagesFilename =
2089 projectRoot + m_xmlHandlerCharacters;
2090 }
2091 else if (localName == "pointsCSV") {
2092 m_xmlHandlerBundleSolutionInfo->m_csvSavedPointsFilename =
2093 projectRoot + m_xmlHandlerCharacters;
2094 }
2095 else if (localName == "residualsCSV") {
2096 m_xmlHandlerBundleSolutionInfo->m_csvSavedResidualsFilename =
2097 projectRoot + m_xmlHandlerCharacters;
2098 }
2099
2100 m_xmlHandlerCharacters = "";
2101 return XmlStackedHandler::endElement(namespaceURI, localName, qName);
2102 }
2103
2104
2114 SurfacePoint::CoordIndex coordIdx) const {
2115 QString coordName;
2116 switch (m_settings->controlPointCoordTypeReports()) {
2118 switch (coordIdx) {
2119 case SurfacePoint::One:
2120 coordName = " Latitude";
2121 break;
2122 case SurfacePoint::Two:
2123 coordName = "Longitude";
2124 break;
2125 case SurfacePoint::Three:
2126 coordName = " Radius";
2127 break;
2128 default:
2129 IString msg = "Unknown surface point index enum ["
2130 + toString(coordIdx) + "].";
2131 throw IException(IException::Programmer, msg, _FILEINFO_);
2132 break;
2133 }
2134 break;
2136 switch (coordIdx) {
2137 case SurfacePoint::One:
2138 coordName = "POINT X";
2139 break;
2140 case SurfacePoint::Two:
2141 coordName = "POINT Y";
2142 break;
2143 case SurfacePoint::Three:
2144 coordName = "POINT Z";
2145 break;
2146 default:
2147 IString msg = "Unknown surface point index enum ["
2148 + toString(coordIdx) + "].";
2149 throw IException(IException::Programmer, msg, _FILEINFO_);
2150 break;
2151 }
2152 break;
2153 default:
2154 IString msg = "Unknown surface point coordinate type enum ["
2155 + toString(m_settings->controlPointCoordTypeReports()) + "].";
2156 throw IException(IException::Programmer, msg, _FILEINFO_);
2157 break;
2158 }
2159 return coordName;
2160 }
2161}
This class is used to modify and manage solve settings for 1 to many BundleObservations.
A container class for statistical results from a BundleAdjust solution.
double elapsedTimeErrorProp() const
Returns the elapsed time for error propagation.
int numberRejectedObservations() const
Returns the number of observation that were rejected.
QString minSigmaCoord2PointId() const
Returns the minimum sigma point id for coordinate 2.
QList< Statistics > rmsImageSampleResiduals() const
Returns the list of RMS image sample residuals statistics.
ControlNetQsp outputControlNet() const
Returns a shared pointer to the output control network.
int numberObservations() const
Returns the number of observations.
MaximumLikelihoodWFunctions maximumLikelihoodModelWFunc(int modelIndex) const
Returns the maximum likelihood model at the given index.
double sigmaCoord3StatisticsRms() const
Returns the RMS of the adjusted sigmas for coordinate 3.
double sigma0() const
Returns the Sigma0 of the bundle adjustment.
bool converged() const
Returns whether or not the bundle adjustment converged.
double maximumLikelihoodModelQuantile(int modelIndex) const
Returns the quantile of the maximum likelihood model at the given index.
int numberConstrainedPointParameters() const
Returns the number of constrained point parameters.
int iterations() const
Returns the number of iterations taken by the BundleAdjust.
QString minSigmaCoord1PointId() const
Returns the minimum sigma point id for coordinate 1.
void save(QXmlStreamWriter &stream, const Project *project) const
Saves the BundleResults object to an XML file.
QVector< BundleControlPointQsp > & bundleControlPoints()
Returns a reference to the BundleControlPoint vector.
void setCorrMatImgsAndParams(QMap< QString, QStringList > imgsAndParams)
Set the images and their associated parameters of the correlation matrix.
Distance maxSigmaCoord2Distance() const
Returns the maximum sigma distance for coordinate 2.
int numberUnknownParameters() const
Returns the number of unknown parameters.
QVector< BundleLidarControlPointQsp > & bundleLidarControlPoints()
Returns a reference to the BundleLidarControlPoint vector.
LidarDataQsp outputLidarData() const
Returns a shared pointer to the output LidarData object.
double sigmaCoord2StatisticsRms() const
Returns the RMS of the adjusted sigmas for coordinate 2.
Distance minSigmaCoord3Distance() const
Returns the minimum sigma distance for coordinate 3.
QString maxSigmaCoord1PointId() const
Returns the maximum sigma point id for coordinate 1.
int numberConstrainedTargetParameters() const
Return the number of constrained target parameters.
StatCumProbDistDynCalc residualsCumulativeProbabilityDistribution() const
Returns the cumulative probability distribution of the residuals used for reporting.
double elapsedTime() const
Returns the elapsed time for the bundle adjustment.
QList< Statistics > rmsImageResiduals() const
Returns the list of RMS image residuals statistics.
const BundleObservationVector & observations() const
Returns a reference to the observations used by the BundleAdjust.
Distance minSigmaCoord1Distance() const
Returns the minimum sigma distance for coordinate 1.
QString minSigmaCoord3PointId() const
Returns the minimum sigma point id for coordinate 3.
QList< Statistics > rmsImageLineResiduals() const
Returns the list of RMS image line residuals statistics.
int numberLidarRangeConstraintEquations() const
Return the number of lidar range constraint equations.
Distance maxSigmaCoord3Distance() const
Returns the maximum sigma distance for coordinate 3.
Distance maxSigmaCoord1Distance() const
Returns the maximum sigma distance for coordinate 1.
QString maxSigmaCoord3PointId() const
Returns the maximum sigma point id for coordinate 3.
QString maxSigmaCoord2PointId() const
Returns the maximum sigma point id for coordinate 2.
int numberConstrainedImageParameters() const
Returns the number of constrained image parameters.
double sigmaCoord1StatisticsRms() const
Returns the RMS of the adjusted sigmas for coordinate 1.
Distance minSigmaCoord2Distance() const
Returns the minimum sigma distance for coordinate 2.
int degreesOfFreedom() const
Returns the degrees of freedom.
Container class for BundleAdjustment settings.
This class is used to read an images.xml file into an image list.
virtual bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName)
Handle an XML end element.
virtual bool characters(const QString &ch)
Adds characters to m_xmlHandlerCharacters.
XmlHandler(BundleSolutionInfo *bundleSolutionInfo, Project *project)
Create an XML Handler (reader) that can populate the BundleSolutionInfo class data.
QString m_xmlHandlerCharacters
List of characters that have been handled.
virtual bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts)
Handle an XML start element.
BundleSolutionInfo * m_xmlHandlerBundleSolutionInfo
The bundleSolutionInfo object.
Container class for BundleAdjustment results.
bool outputResiduals()
Outputs image coordinate residuals to a csv file.
bool outputImagesCSV()
Outputs the bundleout_images.csv file which contains Jigsaw data about the images within each observa...
BundleSettingsQsp m_settings
Bundle settings.
QString inputControlNetFileName() const
Returns the name of the input control network.
QString m_runTime
Run time of the bundle adjustment.
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Saves the BundleSolutionInfo to the project.
QString inputLidarDataFileName() const
Returns name of input lidar data file (if any).
void addAdjustedImages(ImageList *images)
Adds a list of images that were adjusted (their labels were updated).
QString savedPointsFilename()
Returns filename of output bundle points csv file.
QUuid * m_id
A unique ID for this BundleSolutionInfo object (useful for others to reference this object when savin...
BundleSettingsQsp bundleSettings()
Returns bundle settings.
void setName(QString name)
Sets the name of the bundle.
QList< ImageList * > * m_adjustedImages
Adjusted image list.
FileName * m_inputControlNetFileName
Input control network file name.
void setOutputControl(Control *outputControl)
Returns the name of the output control network.
QList< ImageList * > adjustedImages() const
Returns the list of images that were adjusted after a bundle.
QList< ImageList * > * m_images
Input image list.
FileName * m_inputLidarDataFileName
Input lidar data file name.
QString surfacePointCoordName(SurfacePoint::CoordinateType type, SurfacePoint::CoordIndex coordInx) const
Determine the control point coordinate name.
QString savedResidualsFilename()
Returns filename of output bundle residuals csv file.
void setOutputControlName(QString name)
Sets m_outputControlName.
BundleResults bundleResults()
Returns the bundle results.
QString id() const
Get a unique, identifying string associated with this BundleSolutionInfo object.
void setRunTime(QString runTime)
Sets the run time, and the name if a name is not already set.
bool outputPointsCSV()
Outputs point data to a csv file.
QString outputControlName() const
Returns m_outputControlName.
void updateFileName(Project *)
TODO: change description below to something more like english.
QString outputControlNetFileName() const
Returns the name of the output control network.
BundleResults * m_statisticsResults
Bundle statistical results.
QString runTime() const
Returns the run time.
bool outputHeader(std::ofstream &fpOut)
Output header for bundle results file.
LidarData * m_outputLidarDataSet
QList of adjusted lidar points.
QString name() const
Returns the name of the bundle.
QString savedBundleOutputFilename()
Returns bundleout text filename.
bool outputText()
Outputs a text file with the results of the BundleAdjust.
Control * m_outputControl
Output control.
QString savedImagesFilename()
Returns filename of output bundle images csv file.
QList< ImageList * > imageList()
Returns the images used in the bundle.
void setOutputStatistics(BundleResults statisticsResults)
Sets the stat results.
QString m_name
Name of the bundle. Defaults to the id.
bool outputImagesCSVHeader(std::ofstream &fpOut, BundleObservationQsp observations)
Outputs the header for the bundleout_images.csv file.
Control * control() const
Returns bundle output Control object.
bool outputLidarCSV()
Outputs lidar data to a csv file.
This represents an ISIS control net in a project-based GUI interface.
Definition Control.h:66
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Method to write this Control object's member data to an XML stream.
Definition Control.cpp:373
QString fileName() const
Access the name of the control network file associated with this Control.
Definition Control.cpp:272
@ Constrained
A Constrained point is a Control Point whose lat/lon/radius is somewhat established and should not be...
@ Free
A Free point is a Control Point that identifies common measurements between two or more cubes.
@ Fixed
A Fixed point is a Control Point whose lat/lon is well established and should not be changed.
double meters() const
Get the distance in meters.
Definition Distance.cpp:85
File name manipulation and expansion.
Definition FileName.h:100
QString path() const
Returns the path of the file name.
Definition FileName.cpp:103
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition FileName.cpp:162
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition FileName.cpp:196
QString toString() const
Returns a QString of the full file name including the file path, excluding the attributes with any Is...
Definition FileName.cpp:515
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
Adds specific functionality to C++ strings.
Definition IString.h:165
Internalizes a list of images and allows for operations on the entire list.
Definition ImageList.h:55
static QString modelToString(Model model)
Static method to return a string represtentation for a given MaximumLikelihoodWFunctions::Model enum.
QString weightedResidualCutoff()
Method to return a string represtentation of the weighted residual cutoff (if it exists) for the Maxi...
double tweakingConstant() const
Returns the current tweaking constant.
The main project for ipce.
Definition Project.h:289
static QString cnetRoot(QString projectRoot)
Appends the root directory name 'cnets' to the project.
Definition Project.cpp:2018
QString bundleSolutionInfoRoot() const
Accessor for the root directory of the results data.
Definition Project.cpp:2242
static QString bundleSolutionInfoRoot(QString projectRoot)
Appends the root directory name 'bundle' to the project results directory.
Definition Project.cpp:2232
QString newProjectRoot() const
Get the top-level folder of the new project.
Definition Project.cpp:1674
QString projectRoot() const
Get the top-level folder of the project.
Definition Project.cpp:1665
double min()
Returns the maximum observation so far included in the dynamic calculation.
double value(double cumProb)
Provides the value of the variable that has the given cumulative probility (according the current est...
double max()
Returns the maximum observation so far included in the dynamic calculation.
This class is used to accumulate statistics on double arrays.
Definition Statistics.h:94
CoordinateType
Defines the coordinate typ, units, and coordinate index for some of the output methods.
@ Latitudinal
Planetocentric latitudinal (lat/lon/rad) coordinates.
@ Rectangular
Body-fixed rectangular x/y/z coordinates.
static QString coordinateTypeToString(CoordinateType type)
Converts the given SurfacePoint::CoordinateType enumeration to a string.
Manage a stack of content handlers for reading XML files.
static QString CurrentLocalTime()
Returns the current local time This time is taken directly from the system clock, so if the system cl...
Definition iTime.cpp:520
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
QSharedPointer< BundleSettings > BundleSettingsQsp
Definition for a BundleSettingsQsp, a shared pointer to a BundleSettings object.
QSharedPointer< BundleLidarRangeConstraint > BundleLidarRangeConstraintQsp
Typdef for BundleLidarRangeConstraint QSharedPointer.
const double Null
Value for an Isis Null pixel.