Official websites use .gov
A .gov website belongs to an official government organization in the United States.

Secure .gov websites use HTTPS
A lock ( ) or https:// means you’ve safely connected to the .gov website. Share sensitive information only on official, secure websites.

Isis 3 Programmer Reference
BundleSolutionInfo.cpp
1
6
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 <QRegularExpression>
16#include <QString>
17#include <QStringList>
18#include <QUuid>
19#include <QXmlStreamWriter>
20#include <QXmlStreamReader>
21
22#include "BundleLidarRangeConstraint.h"
23#include "BundleResults.h"
24#include "Control.h"
25#include "ControlList.h"
26#include "ControlMeasure.h"
27#include "ControlNet.h"
28#include "ControlPoint.h"
29#include "FileName.h"
30#include "ImageList.h"
31#include "IString.h"
32#include "iTime.h"
33#include "Project.h"
34#include "PvlKeyword.h"
35#include "PvlObject.h"
36#include "StatCumProbDistDynCalc.h"
37#include "Statistics.h"
38
39namespace Isis {
40
50 FileName controlNetworkFileName,
51 BundleResults outputStatistics,
52 QList<ImageList *> imgList,
53 QObject *parent) : QObject(parent) {
54 m_id = new QUuid(QUuid::createUuid());
55 m_runTime = "";
57 m_inputControlNetFileName = new FileName(controlNetworkFileName);
58 m_outputControl = NULL;
59 m_outputControlName="";
62 m_settings = inputSettings;
63 m_statisticsResults = new BundleResults(outputStatistics);
64 m_images = new QList<ImageList *>(imgList);
66 }
67
68
78 FileName controlNetworkFileName,
79 FileName lidarDataFileName,
80 BundleResults outputStatistics,
81 QList<ImageList *> imgList,
82 QObject *parent) : QObject(parent) {
83 m_id = new QUuid(QUuid::createUuid());
84 m_runTime = "";
86 m_inputControlNetFileName = new FileName(controlNetworkFileName);
87 m_outputControl = NULL;
88 m_outputControlName="";
89 m_inputLidarDataFileName = new FileName(lidarDataFileName);
91 m_settings = inputSettings;
92 m_statisticsResults = new BundleResults(outputStatistics);
93 m_images = new QList<ImageList *>(imgList);
95 }
96
97
109 QXmlStreamReader *xmlReader,
110 QObject *parent) : QObject(parent)
111 {
112 m_id = new QUuid(QUuid::createUuid());
113 m_runTime = "";
116 m_outputControl = NULL;
117 m_outputControlName = "";
120 m_statisticsResults = NULL;
121 // what about the rest of the member data ? should we set defaults ??? CREATE INITIALIZE METHOD
124
125 m_xmlHandlerProject = project;
127
128 readBundleSolutionInfo(xmlReader);
129 }
130
131 void BundleSolutionInfo::readBundleSolutionInfo(QXmlStreamReader *xmlReader) {
132 QString projectRoot;
133 if (m_xmlHandlerProject) {
134 projectRoot = m_xmlHandlerProject->projectRoot() + "/";
135 }
136 if (!m_adjustedImages){
138 }
139 Q_ASSERT(xmlReader->name() == "bundleSolutionInfo");
140 while(xmlReader->readNextStartElement()) {
141 if (xmlReader->qualifiedName() == "generalAttributes") {
142 while (xmlReader->readNextStartElement()) {
143 if (xmlReader->qualifiedName() == "id") {
144 m_id = new QUuid(xmlReader->readElementText());
145 }
146 else if (xmlReader->qualifiedName() == "name") {
147 m_name = xmlReader->readElementText();
148 }
149 else if (xmlReader->qualifiedName() == "runTime") {
150 m_runTime = xmlReader->readElementText();
151 }
152 else if (xmlReader->qualifiedName() == "inputFileName") {
153 m_inputControlNetFileName = new FileName(projectRoot + xmlReader->readElementText());
154 }
155 else if (xmlReader->qualifiedName() == "bundleOutTXT") {
156 m_txtBundleOutputFilename = projectRoot + xmlReader->readElementText();
157 }
158 else if (xmlReader->qualifiedName() == "imagesCSV") {
159 m_csvSavedImagesFilename = projectRoot + xmlReader->readElementText();
160 }
161 else if (xmlReader->qualifiedName() == "pointsCSV") {
162 m_csvSavedPointsFilename = projectRoot + xmlReader->readElementText();
163 }
164 else if (xmlReader->qualifiedName() == "residualsCSV") {
165 m_csvSavedResidualsFilename = projectRoot + xmlReader->readElementText();
166 }
167 else {
168 xmlReader->skipCurrentElement();
169 }
170 }
171 }
172 else if (xmlReader->name() == "bundleSettings") {
173 m_settings = NULL;
174 BundleSettings *settings = new BundleSettings();
175 settings->readBundleSettings(xmlReader);
176 m_settings = BundleSettingsQsp(settings);
177 }
178 else if (xmlReader->name() == "bundleResults") {
179 m_statisticsResults = NULL;
180 m_statisticsResults = new BundleResults();
181 m_statisticsResults->readBundleResults(xmlReader);
182 }
183 else {
184 xmlReader->skipCurrentElement();
185 }
186 }
187 }
188
193 delete m_id;
194
197
198 delete m_outputControl;
199 m_outputControl = NULL;
200
203
206
207 delete m_statisticsResults;
208 m_statisticsResults = NULL;
209
210 if (m_images != NULL) {
211 delete m_images;
212 m_images = NULL;
213 }
214
215 // if (m_adjustedImages != NULL) {
216 // qDeleteAll(*m_adjustedImages);
217 // m_adjustedImages->clear();
218 // delete m_adjustedImages;
219 // m_adjustedImages = NULL;
220 // }
221 }
222
223
230 return m_txtBundleOutputFilename;
231 }
232
233
240 return m_csvSavedImagesFilename;
241 }
242
243
250 return m_csvSavedPointsFilename;
251 }
252
253
260 return m_csvSavedResidualsFilename;
261 }
262
263
270 m_adjustedImages->append(images);
271 }
272
273
280 delete m_statisticsResults;
281 m_statisticsResults = NULL;
282 m_statisticsResults = new BundleResults(statisticsResults);
283 }
284
285
299
300 //TODO do we need to close anything here?
301
302 FileName oldInputFileName(*m_inputControlNetFileName);
303 FileName newInputFileName(project->cnetRoot() + "/" +
304 oldInputFileName.dir().dirName() + "/" + oldInputFileName.name());
305 *m_inputControlNetFileName = newInputFileName.expanded();
306
307 FileName oldOutputFileName(m_outputControl->fileName());
308 FileName newOutputFileName(project->cnetRoot() + "/" +
309 oldOutputFileName.dir().dirName() + "/" + oldOutputFileName.name());
310
311 if (m_outputControl) {
312 delete m_outputControl;
313 }
314 m_outputControl = new Control(newOutputFileName.expanded());
315 m_outputControlName = newOutputFileName.expanded();
316 }
317
318
328
329
335 QString BundleSolutionInfo::id() const {
336 return m_id->toString().remove(QRegularExpression("[{}]"));
337 }
338
339
346 // ??? validate that a valid time has been given???
347 // try {
348 // iTime time(runTime);
349 // }
350 // catch (...) {
351 // throw IException(IException::Unknown,
352 // "Invalid bundle adjustment run time [" + runTime + ].",
353 // _FILEINFO_);
354 // }
356 if (m_name == m_runTime || m_name == "") {
357 m_name = runTime;
358 }
359 }
360
361
368 return m_runTime;
369 }
370
371
378 return m_inputControlNetFileName->expanded();
379 }
380
381
388
389 if (m_outputControl)
390 return m_outputControl->fileName();
391 else
392 return m_outputControlName;
393 }
394
395
402 return m_inputLidarDataFileName->expanded();
403 }
404
405
412 m_outputControl = outputControl;
413 }
414
415
422 m_outputControlName = name;
423 }
424
425
432 return m_outputControlName;
433 }
434
443
444
453
454
464 return *m_statisticsResults;
465 }
466 else {
467 throw IException(IException::Unknown,
468 "Results for this bundle is NULL.",
469 _FILEINFO_);
470 }
471 }
472
473
482
483
490 m_name = name;
491 }
492
493
500 QString BundleSolutionInfo::name() const {
501 return m_name;
502 }
503
504
516 bool BundleSolutionInfo::outputImagesCSVHeader(std::ofstream &fpOut, BundleObservationQsp observation) {
517
518 if (!fpOut) {
519 return false;
520 }
521
522 char buf[1056];
523
524 // setup column headers
525 std::vector<QString> outputColumns;
526
527 outputColumns.push_back("Image,");
528 outputColumns.push_back("rms,");
529 outputColumns.push_back("rms,");
530 outputColumns.push_back("rms,");
531
532 QStringList observationParameters = observation->parameterList();
533
534 for (int i = 0; i < observationParameters.size(); i++) {
535 for (int j = 0; j < 5; j++) {
536 outputColumns.push_back(observationParameters[i] + ",");
537 }
538 }
539
540 // print first column header to buffer and output to file
541 int ncolumns = outputColumns.size();
542 for (int i = 0; i < ncolumns; i++) {
543 QString str = outputColumns.at(i);
544 snprintf(buf, sizeof(buf), "%s", (const char*)str.toLatin1().data());
545 fpOut << buf;
546 }
547 snprintf(buf, sizeof(buf), "\n");
548 fpOut << buf;
549
550 outputColumns.clear();
551
552 outputColumns.push_back("Filename,");
553 outputColumns.push_back("sample res,");
554 outputColumns.push_back("line res,");
555 outputColumns.push_back("total res,");
556
557 for (int i = 0; i < observationParameters.size(); i++) {
558 outputColumns.push_back("Initial,");
559 outputColumns.push_back("Correction,");
560 outputColumns.push_back("Final,");
561 outputColumns.push_back("Apriori Sigma,");
562 outputColumns.push_back("Adj Sigma,");
563 }
564
565 // print second column header to buffer and output to file
566 ncolumns = outputColumns.size();
567 for (int i = 0; i < ncolumns; i++) {
568 QString str = outputColumns.at(i);
569 snprintf(buf, sizeof(buf), "%s", (const char*)str.toLatin1().data());
570 fpOut << buf;
571 }
572 snprintf(buf, sizeof(buf), "\n");
573 fpOut << buf;
574
575 return true;
576 }
577
578
579
592 bool BundleSolutionInfo::outputHeader(std::ofstream &fpOut) {
593
594 if (!fpOut) {
595 return false;
596 }
597
598 LidarDataQsp lidarData = m_statisticsResults->outputLidarData();
599
600 char buf[1056];
601 int numObservations = m_statisticsResults->observations().size();
602 int numImages = 0;
603 for (int i = 0; i < numObservations; i++) {
604 numImages += m_statisticsResults->observations().at(i)->size();
605 }
606 int numValidPoints = m_statisticsResults->outputControlNet()->GetNumValidPoints();
607
608 int numValidLidarPoints = 0;
609 if (lidarData) {
610 numValidLidarPoints = lidarData->numberLidarPoints();
611 }
612
613 int numInnerConstraints = 0;
614 int numDistanceConstraints = 0;
615 int numDegreesOfFreedom = m_statisticsResults->degreesOfFreedom();
616
617 int convergenceCriteria = 1;
618
619 snprintf(buf, sizeof(buf), "JIGSAW: BUNDLE ADJUSTMENT\n=========================\n");
620 fpOut << buf;
621 snprintf(buf, sizeof(buf), "\n Run Time: %s",
622 Isis::iTime::CurrentLocalTime().toLatin1().data());
623 fpOut << buf;
624 snprintf(buf, sizeof(buf), "\n Network Filename: %s",
625 m_inputControlNetFileName->expanded().toLatin1().data());
626 fpOut << buf;
627
628 snprintf(buf, sizeof(buf),"\n Cube List: %s",
629 m_settings->cubeList().toStdString().c_str() );
630
631 fpOut << buf;
632
633 snprintf(buf, sizeof(buf), "\n Output Network Filename: %s",
634 outputControlName().toStdString().c_str() );
635 fpOut << buf;
636 snprintf(buf, sizeof(buf),"\n Output File Prefix: %s",
637 m_settings->outputFilePrefix().toStdString().c_str() );
638 fpOut <<buf;
639
640 snprintf(buf, sizeof(buf), "\n Network Id: %s",
641 m_statisticsResults->outputControlNet()->GetNetworkId().toLatin1().data());
642 fpOut << buf;
643 snprintf(buf, sizeof(buf), "\n Network Description: %s",\
644 m_statisticsResults->outputControlNet()->Description().toLatin1().data());
645 fpOut << buf;
647 snprintf(buf, sizeof(buf), "\n Lidar Data Filename: %s",
648 m_inputLidarDataFileName->expanded().toLatin1().data());
649 fpOut << buf;
650 }
651 snprintf(buf, sizeof(buf), "\n Target: %s",
652 m_statisticsResults->outputControlNet()->GetTarget().toLatin1().data());
653 fpOut << buf;
654 snprintf(buf, sizeof(buf), "\n\n Linear Units: kilometers");
655 fpOut << buf;
656 snprintf(buf, sizeof(buf), "\n Angular Units: decimal degrees");
657 fpOut << buf;
658 snprintf(buf, sizeof(buf), "\n\nINPUT: SOLVE OPTIONS\n====================\n");
659 fpOut << buf;
660
661 m_settings->solveObservationMode() ?
662 snprintf(buf, sizeof(buf), "\n OBSERVATIONS: ON"):
663 snprintf(buf, sizeof(buf), "\n OBSERVATIONS: OFF");
664 fpOut << buf;
665
666 if (m_settings->controlPointCoordTypeBundle() == SurfacePoint::Latitudinal) {
667 m_settings->solveRadius() ?
668 snprintf(buf, sizeof(buf), "\n RADIUS: ON"):
669 snprintf(buf, sizeof(buf), "\n RADIUS: OFF");
670 }
671 else { // Rectangular (XYZ) solution
672 snprintf(buf, sizeof(buf), "\n RADIUS: N/A");
673 }
674 fpOut << buf;
675
676 m_settings->solveTargetBody() ?
677 snprintf(buf, sizeof(buf), "\n TARGET BODY: ON"):
678 snprintf(buf, sizeof(buf), "\n TARGET BODY: OFF");
679 fpOut << buf;
680
681 m_settings->updateCubeLabel() ?
682 snprintf(buf, sizeof(buf), "\n UPDATE: YES"):
683 snprintf(buf, sizeof(buf), "\n UPDATE: NO");
684 fpOut << buf;
685
686 m_settings->errorPropagation() ?
687 snprintf(buf, sizeof(buf), "\n ERROR PROPAGATION: ON"):
688 snprintf(buf, sizeof(buf), "\n ERROR PROPAGATION: OFF");
689 fpOut << buf;
690
691 (m_settings->controlPointCoordTypeReports() == SurfacePoint::Latitudinal) ?
692 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR REPORTS: LATITUDINAL"):
693 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR REPORTS: RECTANGULAR");
694 fpOut << buf;
695
696 (m_settings->controlPointCoordTypeBundle() == SurfacePoint::Latitudinal) ?
697 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR BUNDLE: LATITUDINAL"):
698 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR BUNDLE: RECTANGULAR");
699 fpOut << buf;
700
701 if (m_settings->outlierRejection()) {
702 snprintf(buf, sizeof(buf), "\n OUTLIER REJECTION: ON");
703 fpOut << buf;
704 snprintf(buf, sizeof(buf), "\n REJECTION MULTIPLIER: %lf",
705 m_settings->outlierRejectionMultiplier());
706 fpOut << buf;
707
708 }
709 else {
710 snprintf(buf, sizeof(buf), "\n OUTLIER REJECTION: OFF");
711 fpOut << buf;
712 snprintf(buf, sizeof(buf), "\n REJECTION MULTIPLIER: N/A");
713 fpOut << buf;
714 }
715
716 // Added April 5, 2017
717 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR REPORTS: %s",
718 SurfacePoint::coordinateTypeToString(m_settings->controlPointCoordTypeReports()).toLatin1().data());
719
720 // Added July 4, 2017
721 snprintf(buf, sizeof(buf), "\n CONTROL POINT COORDINATE TYPE FOR BUNDLE: %s",
722 SurfacePoint::coordinateTypeToString(m_settings->controlPointCoordTypeBundle()).toLatin1().data());
723
724 snprintf(buf, sizeof(buf), "\n\nMAXIMUM LIKELIHOOD ESTIMATION\n============================\n");
725 fpOut << buf;
726
727 for (int tier = 0; tier < 3; tier++) {
728 if (tier < m_statisticsResults->numberMaximumLikelihoodModels()) {
729 snprintf(buf, sizeof(buf), "\n Tier %d Enabled: TRUE", tier);
730 fpOut << buf;
731 snprintf(buf, sizeof(buf), "\n Maximum Likelihood Model: %s",
734 maximumLikelihoodModelWFunc(tier).model()).toLatin1().data());
735 fpOut << buf;
736 snprintf(buf, sizeof(buf), "\n Quantile used for tweaking constant: %lf",
737 m_statisticsResults->maximumLikelihoodModelQuantile(tier));
738 fpOut << buf;
739 snprintf(buf, sizeof(buf), "\n Quantile weighted R^2 Residual value: %lf",
740 m_statisticsResults->maximumLikelihoodModelWFunc(tier).tweakingConstant());
741 fpOut << buf;
742 snprintf(buf, sizeof(buf), "\n Approx. weighted Residual cutoff: %s",
743 m_statisticsResults->maximumLikelihoodModelWFunc(tier)
744 .weightedResidualCutoff().toLatin1().data());
745 fpOut << buf;
746 if (tier != 2) fpOut << "\n";
747 }
748 else {
749 snprintf(buf, sizeof(buf), "\n Tier %d Enabled: FALSE", tier);
750 fpOut << buf;
751 }
752 }
753
754 snprintf(buf, sizeof(buf), "\n\nINPUT: CONVERGENCE CRITERIA\n===========================\n");
755 fpOut << buf;
756 snprintf(buf, sizeof(buf), "\n SIGMA0: %e",
757 m_settings->convergenceCriteriaThreshold());
758 fpOut << buf;
759 snprintf(buf, sizeof(buf), "\n MAXIMUM ITERATIONS: %d",
760 m_settings->convergenceCriteriaMaximumIterations());
761 fpOut << buf;
762
763 //TODO Should it be checked that positionSigmas.size() == positionSolveDegree and
764 // pointingSigmas.size() == pointingSolveDegree somewhere? JAM
765
766 //TODO How do we output this information when using multiple solve settings? JAM
767
768 BundleObservationSolveSettings globalSettings = m_settings->observationSolveSettings(0);
769 int pointingSolveDegree = globalSettings.numberCameraAngleCoefficientsSolved();
770 QList<double> pointingSigmas = globalSettings.aprioriPointingSigmas();
771 int positionSolveDegree = globalSettings.numberCameraPositionCoefficientsSolved();
772 QList<double> positionSigmas = globalSettings.aprioriPositionSigmas();
773
774 snprintf(buf, sizeof(buf), "\n\nINPUT: CAMERA POINTING OPTIONS\n==============================\n");
775 fpOut << buf;
776 switch (pointingSolveDegree) {
777 case 0:
778 snprintf(buf, sizeof(buf),"\n CAMSOLVE: NONE");
779 break;
780 case 1:
781 snprintf(buf, sizeof(buf),"\n CAMSOLVE: ANGLES");
782 break;
783 case 2:
784 snprintf(buf, sizeof(buf),"\n CAMSOLVE: ANGLES, VELOCITIES");
785 break;
786 case 3:
787 snprintf(buf, sizeof(buf),"\n CAMSOLVE: ANGLES, VELOCITIES, ACCELERATIONS");
788 break;
789 default:
790 snprintf(buf, sizeof(buf),"\n CAMSOLVE: ALL POLYNOMIAL COEFFICIENTS (%d)"
791 "\n CKDEGREE: %d"
792 "\n CKSOLVEDEGREE: %d",
793 pointingSolveDegree,
794 globalSettings.ckDegree(),
795 globalSettings.ckSolveDegree());
796 break;
797 }
798 fpOut << buf;
799 globalSettings.solveTwist() ?
800 snprintf(buf, sizeof(buf), "\n TWIST: ON"):
801 snprintf(buf, sizeof(buf), "\n TWIST: OFF");
802 fpOut << buf;
803 globalSettings.solvePolyOverPointing() ?
804 snprintf(buf, sizeof(buf), "\n POLYNOMIAL OVER EXISTING POINTING: ON"):
805 snprintf(buf, sizeof(buf), "\nPOLYNOMIAL OVER EXISTING POINTING : OFF");
806 fpOut << buf;
807
808 snprintf(buf, sizeof(buf), "\n\nINPUT: SPACECRAFT OPTIONS\n=========================\n");
809 fpOut << buf;
810 switch (positionSolveDegree) {
811 case 0:
812 snprintf(buf, sizeof(buf),"\n SPSOLVE: NONE");
813 break;
814 case 1:
815 snprintf(buf, sizeof(buf),"\n SPSOLVE: POSITION");
816 break;
817 case 2:
818 snprintf(buf, sizeof(buf),"\n SPSOLVE: POSITION, VELOCITIES");
819 break;
820 case 3:
821 snprintf(buf, sizeof(buf),"\n SPSOLVE: POSITION, VELOCITIES, ACCELERATIONS");
822 break;
823 default:
824 snprintf(buf, sizeof(buf),"\n SPSOLVE: ALL POLYNOMIAL COEFFICIENTS (%d)"
825 "\n SPKDEGREE: %d"
826 "\n SPKSOLVEDEGREE: %d",
827 positionSolveDegree,
828 globalSettings.spkDegree(),
829 globalSettings.spkSolveDegree());
830 break;
831 }
832 fpOut << buf;
833 globalSettings.solvePositionOverHermite() ?
834 snprintf(buf, sizeof(buf), "\n POLYNOMIAL OVER HERMITE SPLINE: ON"):
835 snprintf(buf, sizeof(buf), "\nPOLYNOMIAL OVER HERMITE SPLINE : OFF");
836 fpOut << buf;
837
838 snprintf(buf, sizeof(buf), "\n\nINPUT: GLOBAL IMAGE PARAMETER UNCERTAINTIES\n===========================================\n");
839 QString coord1Str;
840 QString coord2Str;
841 QString coord3Str;
842 switch (m_settings->controlPointCoordTypeBundle()) {
844 coord1Str = " POINT LATITUDE";
845 coord2Str = " POINT LONGITUDE";
846 coord3Str = " POINT RADIUS";
847 break;
849 coord1Str = " POINT X";
850 coord2Str = " POINT Y";
851 coord3Str = " POINT Z";
852 break;
853 default:
854 IString msg ="Unknown surface point coordinate type enum ["
855 + toString(m_settings->controlPointCoordTypeReports()) + "]." ;
856 throw IException(IException::Programmer, msg, _FILEINFO_);
857 break;
858 }
859
860 // Coordinate 1 (latitude or point X)
861 fpOut << buf;
862 (m_settings->globalPointCoord1AprioriSigma() == Isis::Null) ?
863 snprintf(buf, sizeof(buf),"\n%s SIGMA: N/A", coord1Str.toLatin1().data()):
864 snprintf(buf, sizeof(buf),"\n%s SIGMA: %lf (meters)", coord1Str.toLatin1().data(),
865 m_settings->globalPointCoord1AprioriSigma());
866 // Coordinate 2 (longitude or point Y)
867 fpOut << buf;
868 (m_settings->globalPointCoord2AprioriSigma() == Isis::Null) ?
869 snprintf(buf, sizeof(buf),"\n%s SIGMA: N/A", coord2Str.toLatin1().data()):
870 snprintf(buf, sizeof(buf),"\n%s SIGMA: %lf (meters)", coord2Str.toLatin1().data(),
871 m_settings->globalPointCoord2AprioriSigma());
872 // Coordinate 3 (radius or point Z)
873 fpOut << buf;
874 (m_settings->globalPointCoord3AprioriSigma() == Isis::Null) ?
875 snprintf(buf, sizeof(buf),"\n%s SIGMA: N/A", coord3Str.toLatin1().data()):
876 snprintf(buf, sizeof(buf),"\n%s SIGMA: %lf (meters)", coord3Str.toLatin1().data(),
877 m_settings->globalPointCoord3AprioriSigma());
878 fpOut << buf;
879 (positionSolveDegree < 1 || positionSigmas[0] == Isis::Null) ?
880 snprintf(buf, sizeof(buf),"\n SPACECRAFT POSITION SIGMA: N/A"):
881 snprintf(buf, sizeof(buf),"\n SPACECRAFT POSITION SIGMA: %lf (meters)",
882 positionSigmas[0]);
883 fpOut << buf;
884
885 (positionSolveDegree < 2 || positionSigmas[1] == Isis::Null) ?
886 snprintf(buf, sizeof(buf),"\n SPACECRAFT VELOCITY SIGMA: N/A"):
887 snprintf(buf, sizeof(buf),"\n SPACECRAFT VELOCITY SIGMA: %lf (m/s)",
888 positionSigmas[1]);
889 fpOut << buf;
890
891 (positionSolveDegree < 3 || positionSigmas[2] == Isis::Null) ?
892 snprintf(buf, sizeof(buf),"\n SPACECRAFT ACCELERATION SIGMA: N/A"):
893 snprintf(buf, sizeof(buf),"\n SPACECRAFT ACCELERATION SIGMA: %lf (m/s/s)",
894 positionSigmas[2]);
895 fpOut << buf;
896
897 (pointingSolveDegree < 1 || pointingSigmas[0] == Isis::Null) ?
898 snprintf(buf, sizeof(buf),"\n CAMERA ANGLES SIGMA: N/A"):
899 snprintf(buf, sizeof(buf),"\n CAMERA ANGLES SIGMA: %lf (dd)",
900 pointingSigmas[0]);
901 fpOut << buf;
902
903 (pointingSolveDegree < 2 || pointingSigmas[1] == Isis::Null) ?
904 snprintf(buf, sizeof(buf),"\n CAMERA ANGULAR VELOCITY SIGMA: N/A"):
905 snprintf(buf, sizeof(buf),"\n CAMERA ANGULAR VELOCITY SIGMA: %lf (dd/s)",
906 pointingSigmas[1]);
907 fpOut << buf;
908
909 (pointingSolveDegree < 3 || pointingSigmas[2] == Isis::Null) ?
910 snprintf(buf, sizeof(buf),"\n CAMERA ANGULAR ACCELERATION SIGMA: N/A"):
911 snprintf(buf, sizeof(buf),"\n CAMERA ANGULAR ACCELERATION SIGMA: %lf (dd/s/s)",
912 pointingSigmas[2]);
913 fpOut << buf;
914
915 if (m_settings->solveTargetBody()) {
916 snprintf(buf, sizeof(buf), "\n\nINPUT: TARGET BODY OPTIONS\n==============================\n");
917 fpOut << buf;
918
919 if (m_settings->solvePoleRA() && m_settings->solvePoleDec()) {
920 snprintf(buf, sizeof(buf),"\n POLE: RIGHT ASCENSION");
921 fpOut << buf;
922 snprintf(buf, sizeof(buf),"\n : DECLINATION\n");
923 fpOut << buf;
924 }
925 else if (m_settings->solvePoleRA()) {
926 snprintf(buf, sizeof(buf),"\n POLE: RIGHT ASCENSION\n");
927 fpOut << buf;
928 }
929 else if (m_settings->solvePoleDec()) {
930 snprintf(buf, sizeof(buf),"\n POLE: DECLINATION\n");
931 fpOut << buf;
932 }
933
934 if (m_settings->solvePM() || m_settings->solvePMVelocity()
935 || m_settings->solvePMAcceleration()) {
936 snprintf(buf, sizeof(buf),"\n PRIME MERIDIAN: W0 (OFFSET)");
937 fpOut << buf;
938
939 if (m_settings->solvePMVelocity()) {
940 snprintf(buf, sizeof(buf),"\n : WDOT (SPIN RATE)");
941 fpOut << buf;
942 }
943 if (m_settings->solvePMAcceleration()) {
944 snprintf(buf, sizeof(buf),"\n :W ACCELERATION");
945 fpOut << buf;
946 }
947 }
948
949 if (m_settings->solveTriaxialRadii() || m_settings->solveMeanRadius()) {
950 if (m_settings->solveMeanRadius()) {
951 snprintf(buf, sizeof(buf),"\n RADII: MEAN");
952 fpOut << buf;
953 }
954 else if (m_settings->solveTriaxialRadii()) {
955 snprintf(buf, sizeof(buf),"\n RADII: TRIAXIAL");
956 fpOut << buf;
957 }
958 }
959 }
960
961 snprintf(buf, sizeof(buf), "\n\nJIGSAW: RESULTS\n===============\n");
962 fpOut << buf;
963 snprintf(buf, sizeof(buf), "\n Images: %6d",numImages);
964 fpOut << buf;
965 snprintf(buf, sizeof(buf), "\n Points: %6d",numValidPoints);
966 fpOut << buf;
967
968 if (numValidLidarPoints > 0) {
969 snprintf(buf, sizeof(buf), "\n Lidar Points: %6d",numValidLidarPoints);
970 fpOut << buf;
971 }
972
973 snprintf(buf, sizeof(buf), "\n Total Measures: %6d",
974 (m_statisticsResults->numberObservations()
975 + m_statisticsResults->numberRejectedObservations()) / 2);
976 fpOut << buf;
977
978 snprintf(buf, sizeof(buf), "\n Total Observations: %6d",
979 m_statisticsResults->numberObservations()
980 + m_statisticsResults->numberRejectedObservations());
981 fpOut << buf;
982
983 snprintf(buf, sizeof(buf), "\n Good Observations: %6d",
984 m_statisticsResults->numberObservations());
985 fpOut << buf;
986
987 snprintf(buf, sizeof(buf), "\n Rejected Observations: %6d",
988 m_statisticsResults->numberRejectedObservations());
989 fpOut << buf;
990
991 if (m_statisticsResults->numberConstrainedPointParameters() > 0) {
992 snprintf(buf, sizeof(buf), "\n Constrained Point Parameters: %6d",
993 m_statisticsResults->numberConstrainedPointParameters());
994 fpOut << buf;
995 }
996
997 if (m_statisticsResults->numberConstrainedImageParameters() > 0) {
998 snprintf(buf, sizeof(buf), "\n Constrained Image Parameters: %6d",
999 m_statisticsResults->numberConstrainedImageParameters());
1000 fpOut << buf;
1001 }
1002
1003 if (m_statisticsResults->numberConstrainedTargetParameters() > 0) {
1004 snprintf(buf, sizeof(buf), "\n Constrained Target Parameters: %6d",
1005 m_statisticsResults->numberConstrainedTargetParameters());
1006 fpOut << buf;
1007 }
1008
1009 if (m_statisticsResults->numberLidarRangeConstraintEquations() > 0) {
1010 snprintf(buf, sizeof(buf), "\n Lidar Range Constraints: %6d",
1011 m_statisticsResults->numberLidarRangeConstraintEquations());
1012 fpOut << buf;
1013 }
1014
1015 snprintf(buf, sizeof(buf), "\n Unknowns: %6d",
1016 m_statisticsResults->numberUnknownParameters());
1017 fpOut << buf;
1018
1019 if (numInnerConstraints > 0) {
1020 snprintf(buf, sizeof(buf), "\n Inner Constraints: %6d", numInnerConstraints);
1021 fpOut << buf;
1022 }
1023
1024 if (numDistanceConstraints > 0) {
1025 snprintf(buf, sizeof(buf), "\n Distance Constraints: %d", numDistanceConstraints);
1026 fpOut << buf;
1027 }
1028
1029 snprintf(buf, sizeof(buf), "\n Degrees of Freedom: %6d", numDegreesOfFreedom);
1030 fpOut << buf;
1031
1032 snprintf(buf, sizeof(buf), "\n Convergence Criteria: %6.3g",
1033 m_settings->convergenceCriteriaThreshold());
1034 fpOut << buf;
1035
1036 if (convergenceCriteria == 1) {
1037 snprintf(buf, sizeof(buf), "(Sigma0)");
1038 fpOut << buf;
1039 }
1040
1041 snprintf(buf, sizeof(buf), "\n Iterations: %6d", m_statisticsResults->iterations());
1042 fpOut << buf;
1043
1044 if (m_statisticsResults->iterations() >= m_settings->convergenceCriteriaMaximumIterations()) {
1045 snprintf(buf, sizeof(buf), "(Maximum reached)");
1046 fpOut << buf;
1047 }
1048
1049 snprintf(buf, sizeof(buf), "\n Sigma0: %30.20lf\n", m_statisticsResults->sigma0());
1050 fpOut << buf;
1051 snprintf(buf, sizeof(buf), " Error Propagation Elapsed Time: %6.4lf (seconds)\n",
1052 m_statisticsResults->elapsedTimeErrorProp());
1053 fpOut << buf;
1054 snprintf(buf, sizeof(buf), " Total Elapsed Time: %6.4lf (seconds)\n",
1055 m_statisticsResults->elapsedTime());
1056 fpOut << buf;
1057 if (m_statisticsResults->numberObservations()
1058 + m_statisticsResults->numberRejectedObservations()
1059 > 100) {
1060 snprintf(buf, sizeof(buf), "\n Residual Percentiles:\n");
1061 fpOut << buf;
1062
1063 // residual prob distribution values are calculated/printed
1064 // even if there is no maximum likelihood estimation
1065 try {
1066 for (int bin = 1;bin < 34;bin++) {
1067 double cumProb = double(bin) / 100.0;
1068 double resValue =
1070 residualsCumulativeProbabilityDistribution().value(cumProb);
1071 double resValue33 =
1073 residualsCumulativeProbabilityDistribution().value(cumProb + 0.33);
1074 double resValue66 =
1076 residualsCumulativeProbabilityDistribution().value(cumProb + 0.66);
1077 snprintf(buf, sizeof(buf), " Percentile %3d: %+8.3lf"
1078 " Percentile %3d: %+8.3lf"
1079 " Percentile %3d: %+8.3lf\n",
1080 bin, resValue,
1081 bin + 33, resValue33,
1082 bin + 66, resValue66);
1083 fpOut << buf;
1084 }
1085 }
1086 catch (IException &e) {
1087 QString msg = "Failed to output residual percentiles for bundleout";
1088 throw IException(e, IException::Io, msg, _FILEINFO_);
1089 }
1090 try {
1091 snprintf(buf, sizeof(buf), "\n Residual Box Plot:");
1092 fpOut << buf;
1093 snprintf(buf, sizeof(buf), "\n minimum: %+8.3lf",
1094 m_statisticsResults->residualsCumulativeProbabilityDistribution().min());
1095 fpOut << buf;
1096 snprintf(buf, sizeof(buf), "\n Quartile 1: %+8.3lf",
1097 m_statisticsResults->residualsCumulativeProbabilityDistribution().value(0.25));
1098 fpOut << buf;
1099 snprintf(buf, sizeof(buf), "\n Median: %+8.3lf",
1100 m_statisticsResults->residualsCumulativeProbabilityDistribution().value(0.50));
1101 fpOut << buf;
1102 snprintf(buf, sizeof(buf), "\n Quartile 3: %+8.3lf",
1103 m_statisticsResults->residualsCumulativeProbabilityDistribution().value(0.75));
1104 fpOut << buf;
1105 snprintf(buf, sizeof(buf), "\n maximum: %+8.3lf\n",
1106 m_statisticsResults->residualsCumulativeProbabilityDistribution().max());
1107 fpOut << buf;
1108 }
1109 catch (IException &e) {
1110 QString msg = "Failed to output residual box plot for bundleout";
1111 throw IException(e, IException::Io, msg, _FILEINFO_);
1112 }
1113 }
1114
1115 // Loop over the observations to find the longest file path/name in the
1116 // bunch
1117 int filePadding = 0;
1118
1119 for (int i = 0; i < numObservations; i++) {
1120
1121 int numImagesInObservation = m_statisticsResults->observations().at(i)->size();
1122
1123 for (int j = 0; j < numImagesInObservation; j++) {
1124 BundleImageQsp bundleImage = m_statisticsResults->observations().at(i)->at(j);
1125
1126 if (bundleImage->fileName().length() > filePadding) {
1127 filePadding = bundleImage->fileName().length();
1128 }
1129 }
1130 }
1131
1132 snprintf(buf, sizeof(buf), "\nIMAGE MEASURES SUMMARY\n==========================\n\n");
1133 fpOut << buf;
1134
1135 // Pad each element in the table with the space for the longest image
1136 // path/name then padd it the length of the element + 1
1137 QString header("Measures RMS(pixels)");
1138 if (m_statisticsResults->outputLidarData()) {
1139 header += " Lidar RMS(pixels)";
1140 }
1141 // This is padded by an extra 11 to move it center to the table
1142 snprintf(buf, sizeof(buf),"%*s\n", header.length() + 11 + filePadding, header.toLatin1().data());
1143 fpOut << buf;
1144
1145 QString dividers("*************************** *******************************************");
1146 if (m_statisticsResults->outputLidarData()) {
1147 dividers += " *******************************************";
1148 }
1149 snprintf(buf, sizeof(buf),"%*s\n", dividers.length() + 1 + filePadding, dividers.toLatin1().data());
1150 fpOut << buf;
1151
1152 QString fields("| Accepted | Total | | Samples | Lines | Total |");
1153 if (m_statisticsResults->outputLidarData()) {
1154 fields += " | Samples | Lines | Total |";
1155 }
1156 snprintf(buf, sizeof(buf),"%*s\n", fields.length() + 1 + filePadding, fields.toLatin1().data());
1157 fpOut << buf;
1158
1159 int numMeasures, numLidarMeasures;
1160 int numRejectedMeasures, numLidarRejectedMeasures;
1161 int numUsed, numLidarUsed;
1162 int imageIndex = 0;
1163 Statistics rmsSamplesTotal,rmsLinesTotal,rmsTotals;
1164
1165 for (int i = 0; i < numObservations; i++) {
1166
1167 int numImagesInObservation = m_statisticsResults->observations().at(i)->size();
1168
1169 for (int j = 0; j < numImagesInObservation; j++) {
1170
1171 BundleImageQsp bundleImage = m_statisticsResults->observations().at(i)->at(j);
1172
1173 double rmsSampleResiduals = m_statisticsResults->
1174 rmsImageSampleResiduals()[imageIndex].Rms();
1175 double rmsLineResiduals = m_statisticsResults->
1176 rmsImageLineResiduals()[imageIndex].Rms();
1177 double rmsLandSResiduals = m_statisticsResults->
1178 rmsImageResiduals()[imageIndex].Rms();
1179 rmsSamplesTotal.AddData(rmsSampleResiduals);
1180 rmsLinesTotal.AddData(rmsLineResiduals);
1181 rmsTotals.AddData(rmsLandSResiduals);
1182
1183 numMeasures = m_statisticsResults->outputControlNet()->GetNumberOfValidMeasuresInImage
1184 (bundleImage->serialNumber());
1185
1186 numRejectedMeasures = m_statisticsResults->outputControlNet()->
1187 GetNumberOfJigsawRejectedMeasuresInImage(bundleImage->serialNumber());
1188
1189 numUsed = numMeasures - numRejectedMeasures;
1190
1191 QString filename = bundleImage->fileName();
1192 QStringList List;
1193 List = filename.split("/");
1194
1195 snprintf(buf, sizeof(buf),"%-*s" ,filePadding + 1, bundleImage->fileName().toLatin1().data());
1196 fpOut << buf;
1197
1198 snprintf(buf, sizeof(buf), " %12d %12d ", numUsed, numMeasures);
1199 fpOut << buf;
1200
1201 snprintf(buf, sizeof(buf),"%13.4lf %13.4lf %13.4lf",
1202 rmsSampleResiduals,rmsLineResiduals,rmsLandSResiduals);
1203
1204 fpOut << buf;
1205
1206 if (m_statisticsResults->outputLidarData()) {
1207 double rmsLidarSampleResiduals = m_statisticsResults->
1208 rmsLidarImageSampleResiduals()[imageIndex].Rms();
1209 double rmsLidarLineResiduals = m_statisticsResults->
1210 rmsLidarImageLineResiduals()[imageIndex].Rms();
1211 double rmsLidarLandSResiduals = m_statisticsResults->
1212 rmsLidarImageResiduals()[imageIndex].Rms();
1213
1214 numLidarMeasures = m_statisticsResults->outputLidarData()->
1215 GetNumberOfValidMeasuresInImage(bundleImage->serialNumber());
1216
1217 numLidarRejectedMeasures = m_statisticsResults->outputLidarData()->
1218 GetNumberOfJigsawRejectedMeasuresInImage(bundleImage->serialNumber());
1219
1220 numLidarUsed = numLidarMeasures - numLidarRejectedMeasures;
1221
1222 snprintf(buf, sizeof(buf), " %12d %12d ", numLidarUsed, numLidarMeasures);
1223 fpOut << buf;
1224
1225 snprintf(buf, sizeof(buf),"%13.4lf %13.4lf %13.4lf",
1226 rmsLidarSampleResiduals,rmsLidarLineResiduals,rmsLidarLandSResiduals);
1227
1228 fpOut << buf;
1229 }
1230
1231 snprintf(buf, sizeof(buf), " \n");
1232 fpOut << buf;
1233 imageIndex++;
1234 }
1235 }
1236
1237 // Do something similar to above but left justify the string and add a 33
1238 // character buffer
1239 snprintf(buf, sizeof(buf),"%*s", -(filePadding + 33), "\nTotal RMS:");
1240 fpOut << buf;
1241 snprintf(buf, sizeof(buf),"%13.4lf %13.4lf %13.4lf\n",
1242 rmsSamplesTotal.Rms(),rmsLinesTotal.Rms(),rmsTotals.Rms());
1243 fpOut << buf;
1244
1245 return true;
1246 }
1247
1248
1261
1262 char buf[1056];
1263
1264 QList<Statistics> rmsImageSampleResiduals = m_statisticsResults->rmsImageSampleResiduals();
1265 QList<Statistics> rmsImageLineResiduals = m_statisticsResults->rmsImageLineResiduals();
1266 QList<Statistics> rmsImageResiduals = m_statisticsResults->rmsImageResiduals();
1267
1268 bool errorProp = false;
1269 if (m_statisticsResults->converged() && m_settings->errorPropagation()) {
1270 errorProp = true;
1271 }
1272
1273 QList<QString> outputCsvFileNames;
1274 QList<QString> instrumentIds = m_statisticsResults->observations().instrumentIds();
1275 // If there's just a single instrumentId just call it bundleout_images.csv
1276 if (instrumentIds.size() == 1) {
1277 QString ofname = "bundleout_images.csv";
1278 ofname = m_settings->outputFilePrefix() + ofname;
1279 m_csvSavedImagesFilename = ofname;
1280 outputCsvFileNames.push_back(ofname);
1281 }
1282 // Otherwise append the instrument IDs so it's bundleout_images_spacecraft_sensor.csv
1283 else {
1284 for (int i = 0; i < instrumentIds.size(); i++) {
1285 QString updatedInstrumentId = instrumentIds[i];
1286 // Replace and "/" or " " characters with "_" to make the filename safer
1287 // This line must be separate to avoid modifying the instrumentId in the list
1288 // we will iterate over later
1289 updatedInstrumentId.replace("/", "_").replace(" ", "_");
1290 QString ofname = "bundleout_images_" + updatedInstrumentId + ".csv";
1291 ofname = m_settings->outputFilePrefix() + ofname;
1292 m_csvSavedImagesFilename = ofname;
1293 outputCsvFileNames.push_back(ofname);
1294 }
1295 }
1296
1297 for (int i = 0; i < instrumentIds.size(); i++) {
1298
1299 std::ofstream fpOut(outputCsvFileNames[i].toLatin1().data(), std::ios::out);
1300 if (!fpOut) {
1301 return false;
1302 }
1303
1304 QList<BundleObservationQsp> observations =
1305 m_statisticsResults->observations().observationsByInstId(instrumentIds[i]);
1306
1307 int nObservations = observations.size();
1308
1309 outputImagesCSVHeader(fpOut, observations.front());
1310
1311 for (int j = 0; j < nObservations; j++ ) {
1312 BundleObservationQsp observation = observations[j];
1313
1314 // We need the image index, not the observation index,
1315 // so count all of the images prior to this observation
1316 int observationIndex = observation->index();
1317 int imgIndex = 0;
1318 for (int obsIndex = 0; obsIndex < observationIndex; obsIndex++) {
1319 imgIndex += m_statisticsResults->observations().at(obsIndex)->size();
1320 }
1321
1322 if(!observation) {
1323 continue;
1324 }
1325
1326 int numImages = observation->size();
1327
1328 for (int k = 0; k < numImages; k++) {
1329 BundleImageQsp image = observation->at(k);
1330
1331 snprintf(buf, sizeof(buf), "%s", image->fileName().toLatin1().data());
1332 fpOut << buf;
1333 snprintf(buf, sizeof(buf),",");
1334 fpOut << buf;
1335
1336 fpOut << toString(rmsImageSampleResiduals[imgIndex].Rms()).toLatin1().data();
1337 snprintf(buf, sizeof(buf),",");
1338 fpOut << buf;
1339
1340 fpOut << toString(rmsImageLineResiduals[imgIndex].Rms()).toLatin1().data();
1341 snprintf(buf, sizeof(buf),",");
1342 fpOut << buf;
1343
1344 fpOut << toString(rmsImageResiduals[imgIndex].Rms()).toLatin1().data();
1345 snprintf(buf, sizeof(buf),",");
1346 fpOut << buf;
1347
1348 QString observationString =
1349 observation->bundleOutputCSV(errorProp);
1350
1351 //Removes trailing commas
1352 if (observationString.right(1)==",") {
1353 observationString.truncate(observationString.length()-1);
1354 }
1355
1356 fpOut << (const char*) observationString.toLatin1().data();
1357
1358 snprintf(buf, sizeof(buf),"\n");
1359 fpOut << buf;
1360 imgIndex++;
1361
1362 }
1363 }
1364 fpOut.close();
1365 }
1366
1367 return true;
1368 }
1369
1370
1377
1378 QString ofname = "bundleout.txt";
1379 ofname = m_settings->outputFilePrefix() + ofname;
1380
1381 std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
1382 if (!fpOut) {
1383 return false;
1384 }
1385
1386 m_txtBundleOutputFilename = ofname;
1387
1388 char buf[4096];
1389 BundleObservationQsp observation;
1390
1391 int nObservations = m_statisticsResults->observations().size();
1392
1393 outputHeader(fpOut);
1394
1395 bool berrorProp = false;
1396 if (m_statisticsResults->converged() && m_settings->errorPropagation()) {
1397 berrorProp = true;
1398 }
1399
1400 // output target body header if solving for target
1401 if (m_settings->solveTargetBody()) {
1402 snprintf(buf, sizeof(buf), "\nTARGET BODY\n==========================\n");
1403 fpOut << buf;
1404
1405 snprintf(buf, sizeof(buf), "\n Target Initial Total "
1406 "Final Initial Final\n"
1407 "Parameter Value Correction "
1408 "Value Accuracy Accuracy\n");
1409 fpOut << buf;
1410
1411 QString targetString =
1412 m_settings->bundleTargetBody()->formatBundleOutputString(berrorProp);
1413 fpOut << (const char*)targetString.toLatin1().data();
1414 }
1415
1416 // output image exterior orientation header
1417 snprintf(buf, sizeof(buf), "\nIMAGE EXTERIOR ORIENTATION\n==========================\n");
1418 fpOut << buf;
1419
1420 QMap<QString, QStringList> imagesAndParameters;
1421
1422 if (m_settings->solveTargetBody()) {
1423 imagesAndParameters.insert( "target", m_settings->bundleTargetBody()->parameterList() );
1424 }
1425
1426 for (int i = 0; i < nObservations; i++) {
1427
1428 observation = m_statisticsResults->observations().at(i);
1429 if (!observation) {
1430 continue;
1431 }
1432
1433 int numImages = observation->size();
1434 for (int j = 0; j < numImages; j++) {
1435 BundleImageQsp image = observation->at(j);
1436 snprintf(buf, sizeof(buf), "\nImage Full File Name: %s\n", image->fileName().toLatin1().data());
1437 fpOut << buf;
1438 snprintf(buf, sizeof(buf), "\nImage Serial Number: %s\n", image->serialNumber().toLatin1().data());
1439 fpOut << buf;
1440
1441 snprintf(buf, sizeof(buf),"Image Initial Total Final Accuracy\n");
1442 fpOut << buf;
1443 snprintf(buf, sizeof(buf),"Parameter Value Correction Value Initial Final Units\n");
1444 fpOut << buf;
1445
1446 snprintf(buf, sizeof(buf)," "
1447 "***************************************\n");
1448 fpOut << buf;
1449
1450 observation->bundleOutputString(fpOut,berrorProp);
1451 // Build list of images and parameters for correlation matrix.
1452 foreach ( QString image, observation->imageNames() ) {
1453 imagesAndParameters.insert( image, observation->parameterList() );
1454 }
1455 }
1456 }
1457
1458 // Save list of images and their associated parameters for CorrelationMatrix to use in ice.
1459 m_statisticsResults->setCorrMatImgsAndParams(imagesAndParameters);
1460
1461 // Save list of images and their associated parameters for CorrelationMatrix to use in ice.
1462 m_statisticsResults->setCorrMatImgsAndParams(imagesAndParameters);
1463
1464 // output point uncertainty statistics if error propagation is on
1465 if (berrorProp) {
1466 snprintf(buf, sizeof(buf), "\n\n\nPOINTS UNCERTAINTY SUMMARY\n==========================\n\n");
1467 fpOut << buf;
1468
1469 // Coordinate 1 (latitude or point x) summary
1470 QString coordName = surfacePointCoordName(m_settings->controlPointCoordTypeReports(),
1471 SurfacePoint::One);
1472 snprintf(buf, sizeof(buf), "RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(),
1473 m_statisticsResults->sigmaCoord1StatisticsRms());
1474 fpOut << buf;
1475 snprintf(buf, sizeof(buf), "MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
1476 m_statisticsResults->minSigmaCoord1Distance().meters(),
1477 m_statisticsResults->minSigmaCoord1PointId().toLatin1().data());
1478 fpOut << buf;
1479 snprintf(buf, sizeof(buf), "MAX Sigma %s(m)%20.8lf at %s\n\n", coordName.toLatin1().data(),
1480 m_statisticsResults->maxSigmaCoord1Distance().meters(),
1481 m_statisticsResults->maxSigmaCoord1PointId().toLatin1().data());
1482 fpOut << buf;
1483
1484 // Coordinate 2 (longitude or point y) summary
1485 coordName = surfacePointCoordName(m_settings->controlPointCoordTypeReports(),
1486 SurfacePoint::Two);
1487 snprintf(buf, sizeof(buf), "RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(),
1488 m_statisticsResults->sigmaCoord2StatisticsRms());
1489 fpOut << buf;
1490 snprintf(buf, sizeof(buf), "MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
1491 m_statisticsResults->minSigmaCoord2Distance().meters(),
1492 m_statisticsResults->minSigmaCoord2PointId().toLatin1().data());
1493 fpOut << buf;
1494 snprintf(buf, sizeof(buf), "MAX Sigma %s(m)%20.8lf at %s\n\n", coordName.toLatin1().data(),
1495 m_statisticsResults->maxSigmaCoord2Distance().meters(),
1496 m_statisticsResults->maxSigmaCoord2PointId().toLatin1().data());
1497 fpOut << buf;
1498
1499 // Coordinate 3 (radius or point z) summary
1500 coordName = surfacePointCoordName(m_settings->controlPointCoordTypeReports(),
1501 SurfacePoint::Three);
1502
1503 if (m_settings->controlPointCoordTypeBundle() == SurfacePoint::Latitudinal &&
1504 m_settings->controlPointCoordTypeReports() == SurfacePoint::Latitudinal &&
1505 m_settings->solveRadius() == false ) {
1506 snprintf(buf, sizeof(buf), " RMS Sigma Radius(m) N/A\n");
1507 fpOut << buf;
1508 snprintf(buf, sizeof(buf), " MIN Sigma Radius(m) N/A\n");
1509 fpOut << buf;
1510 snprintf(buf, sizeof(buf), " MAX Sigma Radius(m) N/A\n");
1511 fpOut << buf;
1512 }
1513 else {
1514 snprintf(buf, sizeof(buf), "RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(),
1515 m_statisticsResults->sigmaCoord3StatisticsRms());
1516 fpOut << buf;
1517 snprintf(buf, sizeof(buf), "MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
1518 m_statisticsResults->minSigmaCoord3Distance().meters(),
1519 m_statisticsResults->minSigmaCoord3PointId().toLatin1().data());
1520 fpOut << buf;
1521 snprintf(buf, sizeof(buf), "MAX Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(),
1522 m_statisticsResults->maxSigmaCoord3Distance().meters(),
1523 m_statisticsResults->maxSigmaCoord3PointId().toLatin1().data());
1524 fpOut << buf;
1525 }
1526 }
1527
1528 // output point summary data header
1529 if (m_settings->controlPointCoordTypeReports() == SurfacePoint::Latitudinal) {
1530 snprintf(buf, sizeof(buf), "\n\nPOINTS SUMMARY\n==============\n%103s"
1531 "Sigma Sigma Sigma\n"
1532 " Label Status Rays RMS"
1533 " Latitude Longitude Radius"
1534 " Latitude Longitude Radius\n", "");
1535 }
1536 else { // Must be Rectangular
1537 snprintf(buf, sizeof(buf), "\n\nPOINTS SUMMARY\n==============\n%103s"
1538 "Sigma Sigma Sigma\n"
1539 " Label Status Rays RMS"
1540 " Point X Point Y Point Z"
1541 " Point X Point Y Point Z\n", "");
1542 }
1543 fpOut << buf;
1544
1545 int nPoints = m_statisticsResults->bundleControlPoints().size();
1546 for (int i = 0; i < nPoints; i++) {
1547 BundleControlPointQsp bundleControlPoint = m_statisticsResults->bundleControlPoints().at(i);
1548
1549 QString pointSummaryString =
1550 bundleControlPoint->formatBundleOutputSummaryString(berrorProp);
1551 fpOut << (const char*)pointSummaryString.toLatin1().data();
1552 }
1553
1554 int nLidarPoints = m_statisticsResults->bundleLidarControlPoints().size();
1555 for (int i = 0; i < nLidarPoints; i++) {
1556 BundleLidarControlPointQsp lidarControlPoint
1557 = m_statisticsResults->bundleLidarControlPoints().at(i);
1558
1559 QString pointSummaryString =
1560 lidarControlPoint->formatBundleOutputSummaryString(berrorProp);
1561 fpOut << (const char*)pointSummaryString.toLatin1().data();
1562 }
1563
1564 // output point detail data header
1565 snprintf(buf, sizeof(buf), "\n\nPOINTS DETAIL\n=============\n\n");
1566 fpOut << buf;
1567
1568 bool solveRadius = m_settings->solveRadius();
1569
1570 for (int i = 0; i < nPoints; i++) {
1571 BundleControlPointQsp bundleControlPoint = m_statisticsResults->bundleControlPoints().at(i);
1572
1573 // Removed radiansToMeters argument 9/18/2018 DAC
1574 QString pointDetailString =
1575 bundleControlPoint->formatBundleOutputDetailString(berrorProp, solveRadius);
1576 fpOut << (const char*)pointDetailString.toLatin1().data();
1577 }
1578
1579 for (int i = 0; i < nLidarPoints; i++) {
1580 BundleLidarControlPointQsp bundleLidarControlPoint =
1581 m_statisticsResults->bundleLidarControlPoints().at(i);
1582
1583 QString pointDetailString =
1584 bundleLidarControlPoint->formatBundleOutputDetailString(berrorProp, solveRadius);
1585 fpOut << (const char*)pointDetailString.toLatin1().data();
1586 }
1587
1588 fpOut.close();
1589
1590 return true;
1591 }
1592
1593
1600 char buf[1056];
1601
1602 QString ofname = "bundleout_points.csv";
1603 ofname = m_settings->outputFilePrefix() + ofname;
1604 m_csvSavedPointsFilename = ofname;
1605
1606 std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
1607 if (!fpOut) {
1608 return false;
1609 }
1610
1611 int numPoints = m_statisticsResults->bundleControlPoints().size();
1612
1613 double dLat, dLon, dRadius;
1614 double dX, dY, dZ;
1615 QString strStatus;
1616 double cor_lat_dd = 0.0; // lat correction, decimal degrees
1617 double cor_lon_dd = 0.0; // lon correction, decimal degrees
1618 double cor_rad_km = 0.0; // radius correction, kilometers
1619
1620 double cor_lat_m = 0.0; // lat correction, meters
1621 double cor_lon_m = 0.0; // lon correction, meters
1622 double cor_rad_m = 0.0; // radius correction, meters
1623
1624 double cor_x_km = 0.0; // x correction, kilometers
1625 double cor_y_km = 0.0; // y correction, kilometers
1626 double cor_z_km = 0.0; // z correction, kilometers
1627
1628 double latInit = Isis::Null;
1629 double lonInit = Isis::Null;
1630 double radInit = Isis::Null;
1631
1632 int numMeasures, numRejectedMeasures;
1633 double dResidualRms;
1634
1635 // bundle coordinate type (Lat, Lon, Radius or XYZ)
1636 bool bundleLatLonRadius = true;
1637 if ( m_settings->controlPointCoordTypeBundle() == SurfacePoint::Rectangular ) {
1638 bundleLatLonRadius = false;
1639 }
1640
1641 // print column headers
1642 if (m_settings->errorPropagation()) {
1643 snprintf(buf, sizeof(buf), ",,,,,3-d,3-d,3-d,Sigma,Sigma,Sigma,Correction,Correction,Correction,"
1644 "Coordinate,Coordinate,Coordinate,Sigma,Sigma,Sigma\n"
1645 "Point,Point,Accepted,Rejected,Residual,Latitude,Longitude,Radius,Latitude,Longitude,"
1646 "Radius,Latitude,Longitude,Radius,X,Y,Z,X,Y,Z\n"
1647 "Label,Status,Measures,Measures,RMS,(dd),(dd),(km),(m),(m),(m),(m),(m),(m),(km),(km),(km),"
1648 "(m),(m),(m)\n");
1649 }
1650 else {
1651 snprintf(buf, sizeof(buf), ",,,,,3-d,3-d,3-d,Correction,Correction,Correction,Coordinate,"
1652 "Coordinate,Coordinate\n"
1653 "Point,Point,Accepted,Rejected,Residual,Latitude,Longitude,Radius,Latitude,Longitude,"
1654 "Radius,X,Y,Z\n"
1655 "Label,Status,Measures,Measures,RMS,(dd),(dd),(km),(m),(m),(m),(km),(km),(km)\n");
1656 }
1657 fpOut << buf;
1658
1659 for (int i = 0; i < numPoints; i++) {
1660 BundleControlPointQsp bundlecontrolpoint = m_statisticsResults->bundleControlPoints().at(i);
1661
1662 if (!bundlecontrolpoint) {
1663 continue;
1664 }
1665
1666 if (bundlecontrolpoint->isRejected()) {
1667 continue;
1668 }
1669
1670 dLat = bundlecontrolpoint->adjustedSurfacePoint().GetLatitude().degrees();
1671 dLon = bundlecontrolpoint->adjustedSurfacePoint().GetLongitude().degrees();
1672 dRadius = bundlecontrolpoint->adjustedSurfacePoint().GetLocalRadius().kilometers();
1673 dX = bundlecontrolpoint->adjustedSurfacePoint().GetX().kilometers();
1674 dY = bundlecontrolpoint->adjustedSurfacePoint().GetY().kilometers();
1675 dZ = bundlecontrolpoint->adjustedSurfacePoint().GetZ().kilometers();
1676 numMeasures = bundlecontrolpoint->numberOfMeasures();
1677 numRejectedMeasures = bundlecontrolpoint->numberOfRejectedMeasures();
1678 dResidualRms = bundlecontrolpoint->residualRms();
1679
1680 // Use the local radius in meters, rad*1000., to convert radians to meters now instead of the
1681 // target body equatorial radius (DAC 09/17/2018; from BundleControlPoint.cpp)
1682 double rtm = dRadius * 1000.;
1683
1684 // point corrections
1685 // Latitude, Longitude corrections are decimal degrees;
1686 // Radius correction is kilometers
1687 boost::numeric::ublas::bounded_vector< double, 3 > corrections = bundlecontrolpoint->
1688 corrections();
1689
1690 // solution is rectangular (point coordinates are X,Y,Z)
1691 // must compute latitudinal initial coordinates and corrections
1692 if (bundleLatLonRadius == false) {
1693 cor_x_km = corrections(0);
1694 cor_y_km = corrections(1);
1695 cor_z_km = corrections(2);
1696
1697 if (!IsSpecial(dX) && !IsSpecial(dY) && !IsSpecial(dZ)) {
1698 SurfacePoint rectInitPoint(Displacement(dX - cor_x_km, Displacement::Kilometers),
1699 Displacement(dY - cor_y_km, Displacement::Kilometers),
1700 Displacement(dZ - cor_z_km, Displacement::Kilometers));
1701
1702 latInit = rectInitPoint.GetLatitude().degrees();
1703 lonInit = rectInitPoint.GetLongitude().degrees();
1704 radInit = rectInitPoint.GetLocalRadius().kilometers();
1705
1706 cor_lat_dd = (dLat - latInit); // degrees
1707 cor_lon_dd = (dLon - lonInit); // degrees
1708 cor_rad_km = dRadius - radInit;
1709
1710 cor_lat_m = cor_lat_dd * DEG2RAD * rtm;
1711 cor_lon_m = cor_lon_dd * DEG2RAD * rtm * cos(dLat*DEG2RAD); // lon corrections meters
1712 cor_rad_m = cor_rad_km * 1000.;
1713 }
1714 }
1715 // solution is latitudinal (point coordinates are Latitude, Longitude, Radius)
1716 else if (bundleLatLonRadius == true) {
1717 cor_lat_dd = corrections(0) * RAD2DEG; // lat correction, decimal degs
1718 cor_lon_dd = corrections(1) * RAD2DEG; // lon correction, decimal degs
1719 cor_rad_m = corrections(2) * 1000.0; // radius correction, meters
1720
1721 cor_lat_m = bundlecontrolpoint->adjustedSurfacePoint().LatitudeToMeters(corrections(0));
1722 cor_lon_m = bundlecontrolpoint->adjustedSurfacePoint().LongitudeToMeters(corrections(1));
1723 cor_rad_km = corrections(2);
1724
1725 if (!IsSpecial(dLat) && !IsSpecial(dLon) && !IsSpecial(dRadius)) {
1726 SurfacePoint latInitPoint(Latitude(dLat - cor_lat_dd, Angle::Degrees),
1727 Longitude(dLon - cor_lon_dd, Angle::Degrees),
1728 Distance(dRadius - corrections(2), Distance::Kilometers));
1729
1730 latInit = latInitPoint.GetLatitude().degrees();
1731 lonInit = latInitPoint.GetLongitude().degrees();
1732 radInit = latInitPoint.GetLocalRadius().kilometers();
1733 }
1734 }
1735
1736 if (bundlecontrolpoint->type() == ControlPoint::Fixed) {
1737 strStatus = "FIXED";
1738 }
1739 else if (bundlecontrolpoint->type() == ControlPoint::Constrained) {
1740 strStatus = "CONSTRAINED";
1741 }
1742 else if (bundlecontrolpoint->type() == ControlPoint::Free) {
1743 strStatus = "FREE";
1744 }
1745 else {
1746 strStatus = "UNKNOWN";
1747 }
1748
1749 if (m_settings->errorPropagation()) {
1750 double dSigmaLat, dSigmaLong, dSigmaRadius;
1751 double dSigmaX, dSigmaY, dSigmaZ;
1752
1753 dSigmaLat = bundlecontrolpoint->adjustedSurfacePoint().GetLatSigmaDistance().meters();
1754 dSigmaLong = bundlecontrolpoint->adjustedSurfacePoint().GetLonSigmaDistance().meters();
1755 dSigmaRadius = bundlecontrolpoint->adjustedSurfacePoint().GetLocalRadiusSigma().meters();
1756
1757 dSigmaX = bundlecontrolpoint->adjustedSurfacePoint().GetXSigma().meters();
1758 dSigmaY = bundlecontrolpoint->adjustedSurfacePoint().GetYSigma().meters();
1759 dSigmaZ = bundlecontrolpoint->adjustedSurfacePoint().GetZSigma().meters();
1760
1761 snprintf(buf, sizeof(buf), "%s,%s,%d,%d,%6.2lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,"
1762 "%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,"
1763 "%16.8lf\n",
1764 bundlecontrolpoint->id().toLatin1().data(), strStatus.toLatin1().data(),
1765 numMeasures, numRejectedMeasures, dResidualRms, dLat, dLon, dRadius, dSigmaLat,
1766 dSigmaLong, dSigmaRadius, cor_lat_m, cor_lon_m, cor_rad_m, dX, dY, dZ,
1767 dSigmaX,dSigmaY,dSigmaZ);
1768 }
1769 else
1770 snprintf(buf, sizeof(buf), "%s,%s,%d,%d,%6.2lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,"
1771 "%16.8lf,%16.8lf,%16.8lf\n",
1772 bundlecontrolpoint->id().toLatin1().data(), strStatus.toLatin1().data(),
1773 numMeasures, numRejectedMeasures, dResidualRms, dLat, dLon, dRadius, cor_lat_m,
1774 cor_lon_m, cor_rad_m, dX, dY, dZ);
1775
1776 fpOut << buf;
1777 }
1778
1779 fpOut.close();
1780
1781 return true;
1782 }
1783
1784
1791 char buf[1056];
1792
1793 QString ofname = "bundleout_lidar.csv";
1794 ofname = m_settings->outputFilePrefix() + ofname;
1795 m_csvSavedPointsFilename = ofname;
1796
1797 std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
1798 if (!fpOut) {
1799 return false;
1800 }
1801
1802 int numPoints = m_statisticsResults->bundleLidarControlPoints().size();
1803
1804 // measured apriori adjusted adjusted
1805 // range sigma range residual sigma
1806 // point id image (km) (km) (km) (km) (km)
1807
1808 // print column headers
1809 if (m_settings->errorPropagation()) {
1810 snprintf(buf, sizeof(buf), ",,measured,a priori,adjusted,adjusted\n"
1811 "point,image,range,sigma,range,sigma,residual\n"
1812 "id,name,(km),(km),(km),(km),(km)\n");
1813 }
1814 else {
1815 snprintf(buf, sizeof(buf), ",,measured,a priori,adjusted\n"
1816 "point,image,range,sigma,range,residual\n"
1817 "id,name,(km),(km),(km),(km)\n");
1818 }
1819 fpOut << buf;
1820
1821 for (int i = 0; i < numPoints; i++) {
1822
1823 BundleLidarControlPointQsp point = m_statisticsResults->bundleLidarControlPoints().at(i);
1824 if (!point || point->isRejected()) {
1825 continue;
1826 }
1827
1828 int nRangeConstraints = point->numberRangeConstraints();
1829 for (int j = 0; j < nRangeConstraints; j++) {
1830 BundleLidarRangeConstraintQsp rangeConstraint = point->rangeConstraint(j);
1831
1832 QString str = rangeConstraint->formatBundleOutputString(m_settings->errorPropagation());
1833 fpOut << str;
1834 }
1835 }
1836
1837 fpOut.close();
1838
1839 return true;
1840 }
1841
1842
1849 char buf[1056];
1850
1851 QString ofname = "residuals.csv";
1852 ofname = m_settings->outputFilePrefix() + ofname;
1853 m_csvSavedResidualsFilename = ofname;
1854
1855 std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
1856 if (!fpOut) {
1857 return false;
1858 }
1859
1860 // output column headers
1861
1862 snprintf(buf, sizeof(buf), ",,,x image,y image,Measured,Measured,sample,line,Residual Vector\n");
1863 fpOut << buf;
1864 snprintf(buf, sizeof(buf), "Point,Image,Image,coordinate,coordinate,"
1865 "Sample,Line,residual,residual,Magnitude\n");
1866 fpOut << buf;
1867 snprintf(buf, sizeof(buf), "Label,Filename,Serial Number,(mm),(mm),"
1868 "(pixels),(pixels),(pixels),(pixels),(pixels),Rejected\n");
1869 fpOut << buf;
1870
1871 // Setup counts and pointers
1872
1873 int numPoints = m_statisticsResults->bundleControlPoints().size();
1874 int numMeasures = 0;
1875
1876 BundleControlPointQsp bundleControlPoint;
1877 BundleMeasureQsp bundleMeasure;
1878
1879 for (int i = 0; i < numPoints; i++) {
1880 bundleControlPoint = m_statisticsResults->bundleControlPoints().at(i);
1881 numMeasures = bundleControlPoint->size();
1882
1883 if (bundleControlPoint->rawControlPoint()->IsIgnored()) {
1884 continue;
1885 }
1886
1887 for (int j = 0; j < numMeasures; j++) {
1888 bundleMeasure = bundleControlPoint->at(j);
1889
1890 Camera *measureCamera = bundleMeasure->camera();
1891 if (!measureCamera) {
1892 continue;
1893 }
1894
1895 if (bundleMeasure->isRejected()) {
1896 snprintf(buf, sizeof(buf), "%s,%s,%s,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,*\n",
1897 bundleControlPoint->id().toLatin1().data(),
1898 bundleMeasure->parentBundleImage()->fileName().toLatin1().data(),
1899 bundleMeasure->cubeSerialNumber().toLatin1().data(),
1900 bundleMeasure->focalPlaneMeasuredX(),
1901 bundleMeasure->focalPlaneMeasuredY(),
1902 bundleMeasure->sample(),
1903 bundleMeasure->line(),
1904 bundleMeasure->sampleResidual(),
1905 bundleMeasure->lineResidual(),
1906 bundleMeasure->residualMagnitude());
1907 }
1908 else {
1909 snprintf(buf, sizeof(buf), "%s,%s,%s,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf\n",
1910 bundleControlPoint->id().toLatin1().data(),
1911 bundleMeasure->parentBundleImage()->fileName().toLatin1().data(),
1912 bundleMeasure->cubeSerialNumber().toLatin1().data(),
1913 bundleMeasure->focalPlaneMeasuredX(),
1914 bundleMeasure->focalPlaneMeasuredY(),
1915 bundleMeasure->sample(),
1916 bundleMeasure->line(),
1917 bundleMeasure->sampleResidual(),
1918 bundleMeasure->lineResidual(),
1919 bundleMeasure->residualMagnitude());
1920 }
1921 fpOut << buf;
1922 }
1923 }
1924
1925 numPoints = m_statisticsResults->bundleLidarControlPoints().size();
1926 numMeasures = 0;
1927
1928 BundleLidarControlPointQsp bundleLidarPoint;
1929
1930 for (int i = 0; i < numPoints; i++) {
1931 bundleLidarPoint = m_statisticsResults->bundleLidarControlPoints().at(i);
1932 numMeasures = bundleLidarPoint->size();
1933
1934 if (bundleLidarPoint->rawControlPoint()->IsIgnored()) {
1935 continue;
1936 }
1937
1938 for (int j = 0; j < numMeasures; j++) {
1939 bundleMeasure = bundleLidarPoint->at(j);
1940
1941 Camera *measureCamera = bundleMeasure->camera();
1942 if (!measureCamera) {
1943 continue;
1944 }
1945
1946 if (bundleMeasure->isRejected()) {
1947 snprintf(buf, sizeof(buf), "%s,%s,%s,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,*\n",
1948 bundleLidarPoint->id().toLatin1().data(),
1949 bundleMeasure->parentBundleImage()->fileName().toLatin1().data(),
1950 bundleMeasure->cubeSerialNumber().toLatin1().data(),
1951 bundleMeasure->focalPlaneMeasuredX(),
1952 bundleMeasure->focalPlaneMeasuredY(),
1953 bundleMeasure->sample(),
1954 bundleMeasure->line(),
1955 bundleMeasure->sampleResidual(),
1956 bundleMeasure->lineResidual(),
1957 bundleMeasure->residualMagnitude());
1958 }
1959 else {
1960 snprintf(buf, sizeof(buf), "%s,%s,%s,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf\n",
1961 bundleLidarPoint->id().toLatin1().data(),
1962 bundleMeasure->parentBundleImage()->fileName().toLatin1().data(),
1963 bundleMeasure->cubeSerialNumber().toLatin1().data(),
1964 bundleMeasure->focalPlaneMeasuredX(),
1965 bundleMeasure->focalPlaneMeasuredY(),
1966 bundleMeasure->sample(),
1967 bundleMeasure->line(),
1968 bundleMeasure->sampleResidual(),
1969 bundleMeasure->lineResidual(),
1970 bundleMeasure->residualMagnitude());
1971 }
1972 fpOut << buf;
1973 }
1974 }
1975
1976 fpOut.close();
1977
1978 return true;
1979 }
1980
1981
1998 void BundleSolutionInfo::save(QXmlStreamWriter &stream, const Project *project,
1999 FileName newProjectRoot) const {
2000
2001 // This is done for testing serialization without a Project
2002 QString relativePath;
2003 QString relativeBundlePath;
2004 FileName bundleSolutionInfoRoot;
2005
2006 if (project) {
2007 bundleSolutionInfoRoot = FileName(Project::bundleSolutionInfoRoot(newProjectRoot.expanded()) +
2008 "/" + runTime());
2009 QString oldPath = project->bundleSolutionInfoRoot(project->projectRoot()) + "/" + runTime();
2010 QString newPath = project->bundleSolutionInfoRoot(newProjectRoot.toString()) + "/" + runTime();
2011 // If project is being saved to new area, create directory and copy files
2012 if (oldPath != newPath) {
2013 // Create project folder for BundleSolutionInfo
2014 QDir bundleDir(newPath);
2015 if (!bundleDir.mkpath(bundleDir.path())) {
2016 throw IException(IException::Io,
2017 QString("Failed to create directory [%1]")
2018 .arg(bundleSolutionInfoRoot.path()),
2019 _FILEINFO_);
2020 }
2021 QString oldFile = oldPath + "/" + FileName(m_outputControl->fileName()).name();
2022 QString newFile = newPath + "/" + FileName(m_outputControl->fileName()).name();
2023 if (!QFile::copy(oldFile, newFile)) {
2024 throw IException(IException::Io,
2025 QString("Failed to copy file [%1] to new file [%2]")
2026 .arg(m_outputControl->fileName()).arg(newFile),
2027 _FILEINFO_);
2028 }
2029 newFile = newPath + "/" + FileName(m_txtBundleOutputFilename).name();
2030 if (!QFile::copy(m_txtBundleOutputFilename, newFile)) {
2031 throw IException(IException::Io,
2032 QString("Failed to copy file [%1] to new file [%2]")
2033 .arg(m_txtBundleOutputFilename).arg(newFile),
2034 _FILEINFO_);
2035 }
2036 newFile = newPath + "/" + FileName(m_csvSavedImagesFilename).name();
2037 if (!QFile::copy(m_csvSavedImagesFilename, newFile)) {
2038 throw IException(IException::Io,
2039 QString("Failed to copy file [%1] to new file [%2]")
2040 .arg(m_csvSavedImagesFilename).arg(newFile),
2041 _FILEINFO_);
2042 }
2043 newFile = newPath + "/" + FileName(m_csvSavedPointsFilename).name();
2044 if (!QFile::copy(m_csvSavedPointsFilename, newFile)) {
2045 throw IException(IException::Io,
2046 QString("Failed to copy file [%1] to new file [%2]")
2047 .arg(m_csvSavedPointsFilename).arg(newFile),
2048 _FILEINFO_);
2049 }
2050 newFile = newPath + "/" + FileName(m_csvSavedResidualsFilename).name();
2051 if (!QFile::copy(m_csvSavedResidualsFilename, newFile)) {
2052 throw IException(IException::Io,
2053 QString("Failed to copy file [%1] to new file [%2]")
2054 .arg(m_csvSavedResidualsFilename).arg(newFile),
2055 _FILEINFO_);
2056 }
2057 }
2058
2059 // Create relativePath
2060 relativePath = m_inputControlNetFileName->expanded().remove(project->newProjectRoot());
2061 // Get rid of any preceding "/" , but add on ending "/"
2062 if (relativePath.startsWith("/")) {
2063 relativePath.remove(0,1);
2064 }
2065
2066 // Create relativeBundlePath for bundleSolutionInfo
2067 relativeBundlePath = newPath.remove(project->newProjectRoot());
2068 // Get rid of any preceding "/" , but add on ending "/"
2069 if (relativeBundlePath.startsWith("/")) {
2070 relativeBundlePath.remove(0,1);
2071 }
2072 relativeBundlePath += "/";
2073 }
2074
2075 stream.writeStartElement("bundleSolutionInfo");
2076 // save ID, cnet file name, and run time to stream
2077 stream.writeStartElement("generalAttributes");
2078 stream.writeTextElement("id", m_id->toString());
2079 stream.writeTextElement("name", m_name);
2080 stream.writeTextElement("runTime", runTime());
2081
2082 stream.writeTextElement("inputFileName",
2083 relativePath);
2084 stream.writeTextElement("bundleOutTXT",
2085 relativeBundlePath + FileName(m_txtBundleOutputFilename).name());
2086 stream.writeTextElement("imagesCSV",
2087 relativeBundlePath + FileName(m_csvSavedImagesFilename).name());
2088 stream.writeTextElement("pointsCSV",
2089 relativeBundlePath + FileName(m_csvSavedPointsFilename).name());
2090 stream.writeTextElement("residualsCSV",
2091 relativeBundlePath + FileName(m_csvSavedResidualsFilename).name());
2092 stream.writeEndElement(); // end general attributes
2093
2094 // save settings to stream
2095 m_settings->save(stream, project);
2096
2097 // save statistics to stream
2098 m_statisticsResults->save(stream, project);
2099
2100 if (project) {
2101 // save adjusted images lists to stream
2102 if (!m_adjustedImages->isEmpty()) {
2103 stream.writeStartElement("imageLists");
2104 for (int i = 0; i < m_adjustedImages->count(); i++) {
2105 m_adjustedImages->at(i)->save(stream, project, bundleSolutionInfoRoot);
2106 }
2107 stream.writeEndElement();
2108 }
2109
2110 // save output control
2111 stream.writeStartElement("outputControl");
2112 m_outputControl->save(stream, project, relativeBundlePath);
2113 stream.writeEndElement();
2114 }
2115
2116 stream.writeEndElement(); //end bundleSolutionInfo
2117 }
2118
2119
2129 SurfacePoint::CoordIndex coordIdx) const {
2130 QString coordName;
2131 switch (m_settings->controlPointCoordTypeReports()) {
2133 switch (coordIdx) {
2134 case SurfacePoint::One:
2135 coordName = " Latitude";
2136 break;
2137 case SurfacePoint::Two:
2138 coordName = "Longitude";
2139 break;
2140 case SurfacePoint::Three:
2141 coordName = " Radius";
2142 break;
2143 default:
2144 IString msg = "Unknown surface point index enum ["
2145 + toString(coordIdx) + "].";
2146 throw IException(IException::Programmer, msg, _FILEINFO_);
2147 break;
2148 }
2149 break;
2151 switch (coordIdx) {
2152 case SurfacePoint::One:
2153 coordName = "POINT X";
2154 break;
2155 case SurfacePoint::Two:
2156 coordName = "POINT Y";
2157 break;
2158 case SurfacePoint::Three:
2159 coordName = "POINT Z";
2160 break;
2161 default:
2162 IString msg = "Unknown surface point index enum ["
2163 + toString(coordIdx) + "].";
2164 throw IException(IException::Programmer, msg, _FILEINFO_);
2165 break;
2166 }
2167 break;
2168 default:
2169 IString msg = "Unknown surface point coordinate type enum ["
2170 + toString(m_settings->controlPointCoordTypeReports()) + "].";
2171 throw IException(IException::Programmer, msg, _FILEINFO_);
2172 break;
2173 }
2174 return coordName;
2175 }
2176}
double degrees() const
Get the angle in units of Degrees.
Definition Angle.h:232
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
This class is used to modify and manage solve settings for 1 to many BundleObservations.
bool solveTwist() const
Accesses the flag for solving for twist.
bool solvePolyOverPointing() const
Whether or not the solve polynomial will be fit over the existing pointing polynomial.
int numberCameraPositionCoefficientsSolved() const
Accesses the number of camera position coefficients in the solution.
int ckDegree() const
Accesses the degree of polynomial fit to original camera angles (ckDegree).
QList< double > aprioriPositionSigmas() const
Accesses the a priori position sigmas.
QList< double > aprioriPointingSigmas() const
Accesses the a priori pointing sigmas.
int ckSolveDegree() const
Accesses the degree of the camera angles polynomial being fit to in the bundle adjustment (ckSolveDeg...
bool solvePositionOverHermite() const
Whether or not the polynomial for solving will be fit over an existing Hermite spline.
int numberCameraAngleCoefficientsSolved() const
Accesses the number of camera angle coefficients in the solution.
int spkSolveDegree() const
Accesses the degree of thecamera position polynomial being fit to in the bundle adjustment (spkSolveD...
int spkDegree() const
Accesses the degree of the polynomial fit to the original camera position (spkDegree).
A container class for statistical results from a BundleAdjust solution.
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.
QString m_xmlHandlerCharacters
List of characters that have been handled.
void setOutputControl(Control *outputControl)
Returns the name of the output control network.
BundleSolutionInfo(BundleSettingsQsp inputSettings, FileName controlNetworkFileName, BundleResults outputStatistics, QList< ImageList * > imgList, QObject *parent=0)
Constructor.
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:65
@ 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.
Displacement is a signed length, usually in meters.
@ Kilometers
The distance is being specified in kilometers.
Distance measurement, usually in meters.
Definition Distance.h:34
double kilometers() const
Get the distance in kilometers.
Definition Distance.cpp:106
@ Kilometers
The distance is being specified in kilometers.
Definition Distance.h:45
Internalizes a list of images and allows for operations on the entire list.
Definition ImageList.h:52
This class is designed to encapsulate the concept of a Latitude.
Definition Latitude.h:51
This class is designed to encapsulate the concept of a Longitude.
Definition Longitude.h:40
static QString modelToString(Model model)
Static method to return a string represtentation for a given MaximumLikelihoodWFunctions::Model enum.
The main project for ipce.
Definition Project.h:287
static QString cnetRoot(QString projectRoot)
Appends the root directory name 'cnets' to the project.
Definition Project.cpp:2081
static QString bundleSolutionInfoRoot(QString projectRoot)
Appends the root directory name 'bundle' to the project results directory.
Definition Project.cpp:2295
QString newProjectRoot() const
Get the top-level folder of the new project.
Definition Project.cpp:1737
QString projectRoot() const
Get the top-level folder of the project.
Definition Project.cpp:1728
This class is used to accumulate statistics on double arrays.
Definition Statistics.h:93
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
double Rms() const
Computes and returns the rms.
This class defines a body-fixed surface point.
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.
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
Distance GetLocalRadius() const
Return the radius of the surface point.
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:522
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QSharedPointer< LidarData > LidarDataQsp
Definition for a shared pointer to a LidarData object.
Definition LidarData.h:100
QSharedPointer< BundleLidarControlPoint > BundleLidarControlPointQsp
QSharedPointer to a BundleLidarControlPoint.
QSharedPointer< BundleSettings > BundleSettingsQsp
Definition for a BundleSettingsQsp, a shared pointer to a BundleSettings object.
QSharedPointer< BundleLidarRangeConstraint > BundleLidarRangeConstraintQsp
Typdef for BundleLidarRangeConstraint QSharedPointer.
QSharedPointer< BundleObservation > BundleObservationQsp
Typdef for BundleObservation QSharedPointer.
QString toString(const LinearAlgebra::Vector &vector, int precision)
A global function to format LinearAlgebra::Vector as a QString with the given precision.
QSharedPointer< BundleControlPoint > BundleControlPointQsp
Definition for BundleControlPointQSP, a shared pointer to a BundleControlPoint.
QSharedPointer< BundleMeasure > BundleMeasureQsp
Definition for BundleMeasureQsp, a shared pointer to a BundleMeasure.