Isis 3 Programmer Reference
BundleObservation.cpp
1 #include "BundleObservation.h"
2 
3 #include <QDebug>
4 #include <QString>
5 #include <QStringList>
6 #include <QVector>
7 
8 #include "BundleImage.h"
10 #include "BundleTargetBody.h"
11 #include "Camera.h"
12 #include "LinearAlgebra.h"
13 #include "SpicePosition.h"
14 #include "SpiceRotation.h"
15 
16 using namespace std;
17 
18 namespace Isis {
19 
23  BundleObservation::BundleObservation() {
24  m_serialNumbers.clear();
25  m_imageNames.clear();
26  m_parameterNamesList.clear();
27  m_observationNumber = "";
28  m_instrumentId = "";
29  m_instrumentRotation = NULL;
30  m_instrumentPosition = NULL;
31  m_index = 0;
32  m_weights.clear();
33  m_corrections.clear();
34 // m_solution.clear();
35  m_aprioriSigmas.clear();
36  m_adjustedSigmas.clear();
37  }
38 
39 
49  BundleObservation::BundleObservation(BundleImageQsp image, QString observationNumber,
50  QString instrumentId, BundleTargetBodyQsp bundleTargetBody) {
51  m_serialNumbers.clear();
52  m_imageNames.clear();
53  m_parameterNamesList.clear();
54  m_observationNumber = "";
55  m_instrumentId = "";
56  m_instrumentRotation = NULL;
57  m_instrumentPosition = NULL;
58  m_index = 0;
59  m_weights.clear();
60  m_corrections.clear();
61 // m_solution.clear();
62  m_aprioriSigmas.clear();
63  m_adjustedSigmas.clear();
64 
65  m_observationNumber = observationNumber;
66  m_instrumentId = instrumentId;
67 
68  m_bundleTargetBody = bundleTargetBody;
69 
70  if (image) {
71  append(image);
72  m_serialNumbers.append(image->serialNumber());
73  m_imageNames.append(image->fileName());
74  m_cubeSerialNumberToBundleImageMap.insert(image->serialNumber(), image);
75 
76  // set the observations spice position and rotation objects from the primary image in the
77  // observation (this is, by design at the moment, the first image added to the observation)
78  // if the image, camera, or instrument position/orientation is null, then set to null
79  m_instrumentPosition = (image->camera() ?
80  (image->camera()->instrumentPosition() ?
81  image->camera()->instrumentPosition() : NULL)
82  : NULL);
83  m_instrumentRotation = (image->camera() ?
84  (image->camera()->instrumentRotation() ?
85  image->camera()->instrumentRotation() : NULL)
86  : NULL);
87 
88  // set the observations target body spice rotation object from the primary image in the
89  // observation (this is, by design at the moment, the first image added to the observation)
90  // if the image, camera, or instrument position/orientation is null, then set to null
91 // m_bodyRotation = (image->camera() ?
92 // (image->camera()->bodyRotation() ?
93 // image->camera()->bodyRotation() : NULL)
94 // : NULL);
95  }
96  }
97 
98 
104  BundleObservation::BundleObservation(const BundleObservation &src) {
105  m_serialNumbers = src.m_serialNumbers;
106  m_cubeSerialNumberToBundleImageMap = src.m_cubeSerialNumberToBundleImageMap;
107 
108  m_observationNumber = src.m_observationNumber;
109  m_instrumentId = src.m_instrumentId;
110 
111  m_instrumentPosition = src.m_instrumentPosition;
112  m_instrumentRotation = src.m_instrumentRotation;
113 
114  m_solveSettings = src.m_solveSettings;
115 
116  m_index = src.m_index;
117  }
118 
119 
125  BundleObservation::~BundleObservation() {
126  clear();
127  }
128 
129 
139  BundleObservation &BundleObservation::operator=(const BundleObservation &src) {
140  if (&src != this) {
141  m_serialNumbers = src.m_serialNumbers;
142  m_cubeSerialNumberToBundleImageMap = src.m_cubeSerialNumberToBundleImageMap;
143 
144  m_observationNumber = src.m_observationNumber;
145  m_instrumentId = src.m_instrumentId;
146 
147  m_instrumentPosition = src.m_instrumentPosition;
148  m_instrumentRotation = src.m_instrumentRotation;
149 
150  m_solveSettings = src.m_solveSettings;
151  }
152  return *this;
153  }
154 
155 
165  void BundleObservation::append(const BundleImageQsp &value) {
166  if (value) {
167  m_cubeSerialNumberToBundleImageMap.insert(value->serialNumber(), value);
168  }
170  }
171 
172 
181  BundleImageQsp BundleObservation::imageByCubeSerialNumber(QString cubeSerialNumber) {
182  BundleImageQsp bundleImage;
183 
184  if (m_cubeSerialNumberToBundleImageMap.contains(cubeSerialNumber)) {
185  bundleImage = m_cubeSerialNumberToBundleImageMap.value(cubeSerialNumber);
186  }
187 
188  return bundleImage;
189  }
190 
191 
203  bool BundleObservation::setSolveSettings(BundleObservationSolveSettings solveSettings) {
204  m_solveSettings = BundleObservationSolveSettingsQsp(
205  new BundleObservationSolveSettings(solveSettings));
206 
207  // initialize solution parameters for this observation
208  int nCameraAngleCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
209  int nCameraPositionCoefficients = m_solveSettings->numberCameraPositionCoefficientsSolved();
210 
211  int nParameters = 3*nCameraPositionCoefficients + 2*nCameraAngleCoefficients;
212  if (nCameraAngleCoefficients >= 1 && m_solveSettings->solveTwist()) {
213  nParameters += nCameraAngleCoefficients;
214  }
215  // size vectors and set to zero
216  m_weights.resize(nParameters);
217  m_weights.clear();
218  m_corrections.resize(nParameters);
219  m_corrections.clear();
220 // m_solution.resize(nParameters);
221 // m_solution.clear();
222  m_adjustedSigmas.resize(nParameters);
223  m_adjustedSigmas.clear();
224  m_aprioriSigmas.resize(nParameters);
225  for ( int i = 0; i < nParameters; i++) // initialize apriori sigmas to -1.0
226  m_aprioriSigmas[i] = Isis::Null;
227 
228  if (!initParameterWeights()) {
229  // TODO: some message here!!!!!!!!!!!
230  // TODO: do we need this??? initParameterWeights() never returns false...
231  return false;
232  }
233 
234  return true;
235  }
236 
237 
243  QString BundleObservation::instrumentId() {
244  return m_instrumentId;
245  }
246 
247 
253  SpiceRotation *BundleObservation::spiceRotation() {
254  return m_instrumentRotation;
255  }
256 
257 
263  SpicePosition *BundleObservation::spicePosition() {
264  return m_instrumentPosition;
265  }
266 
267 
273  LinearAlgebra::Vector &BundleObservation::parameterWeights() {
274  return m_weights;
275  }
276 
277 
283  LinearAlgebra::Vector &BundleObservation::parameterCorrections() {
284  return m_corrections;
285  }
286 
287 
292 // LinearAlgebra::Vector &BundleObservation::parameterSolution() {
293 // return m_solution;
294 // }
295 
296 
302  LinearAlgebra::Vector &BundleObservation::aprioriSigmas() {
303  return m_aprioriSigmas;
304  }
305 
306 
312  LinearAlgebra::Vector &BundleObservation::adjustedSigmas() {
313  return m_adjustedSigmas;
314  }
315 
316 
323  const BundleObservationSolveSettingsQsp BundleObservation::solveSettings() {
324  return m_solveSettings;
325  }
326 
327 
336  bool BundleObservation::initializeExteriorOrientation() {
337 
338  if (m_solveSettings->instrumentPositionSolveOption() !=
339  BundleObservationSolveSettings::NoPositionFactors) {
340 
341  double positionBaseTime = 0.0;
342  double positiontimeScale = 0.0;
343  std::vector<double> posPoly1, posPoly2, posPoly3;
344 
345  for (int i = 0; i < size(); i++) {
346  BundleImageQsp image = at(i);
347  SpicePosition *spicePosition = image->camera()->instrumentPosition();
348 
349  if (i > 0) {
350  spicePosition->SetPolynomialDegree(m_solveSettings->spkSolveDegree());
351  spicePosition->SetOverrideBaseTime(positionBaseTime, positiontimeScale);
352  spicePosition->SetPolynomial(posPoly1, posPoly2, posPoly3,
353  m_solveSettings->positionInterpolationType());
354  }
355  else {
356  // first, set the degree of the spk polynomial to be fit for a priori values
357  spicePosition->SetPolynomialDegree(m_solveSettings->spkDegree());
358 
359  // now, set what kind of interpolation to use (SPICE, memcache, hermitecache, polynomial
360  // function, or polynomial function over constant hermite spline)
361  // TODO: verify - I think this actually performs the a priori fit
362  spicePosition->SetPolynomial(m_solveSettings->positionInterpolationType());
363 
364  // finally, set the degree of the spk polynomial actually used in the bundle adjustment
365  spicePosition->SetPolynomialDegree(m_solveSettings->spkSolveDegree());
366 
367  if (m_instrumentPosition) { // ??? TODO: why is this different from rotation code below???
368  positionBaseTime = m_instrumentPosition->GetBaseTime();
369  positiontimeScale = m_instrumentPosition->GetTimeScale();
370  m_instrumentPosition->GetPolynomial(posPoly1, posPoly2, posPoly3);
371  }
372  }
373  }
374  }
375 
376  if (m_solveSettings->instrumentPointingSolveOption() !=
377  BundleObservationSolveSettings::NoPointingFactors) {
378 
379  double rotationBaseTime = 0.0;
380  double rotationtimeScale = 0.0;
381  std::vector<double> anglePoly1, anglePoly2, anglePoly3;
382 
383  for (int i = 0; i < size(); i++) {
384  BundleImageQsp image = at(i);
385  SpiceRotation *spicerotation = image->camera()->instrumentRotation();
386 
387  if (i > 0) {
388  spicerotation->SetPolynomialDegree(m_solveSettings->ckSolveDegree());
389  spicerotation->SetOverrideBaseTime(rotationBaseTime, rotationtimeScale);
390  spicerotation->SetPolynomial(anglePoly1, anglePoly2, anglePoly3,
391  m_solveSettings->pointingInterpolationType());
392  }
393  else {
394  // first, set the degree of the spk polynomial to be fit for a priori values
395  spicerotation->SetPolynomialDegree(m_solveSettings->ckDegree());
396 
397  // now, set what kind of interpolation to use (SPICE, memcache, hermitecache, polynomial
398  // function, or polynomial function over constant hermite spline)
399  // TODO: verify - I think this actually performs the a priori fit
400  spicerotation->SetPolynomial(m_solveSettings->pointingInterpolationType());
401 
402  // finally, set the degree of the spk polynomial actually used in the bundle adjustment
403  spicerotation->SetPolynomialDegree(m_solveSettings->ckSolveDegree());
404 
405  rotationBaseTime = spicerotation->GetBaseTime();
406  rotationtimeScale = spicerotation->GetTimeScale();
407  spicerotation->GetPolynomial(anglePoly1, anglePoly2, anglePoly3);
408  }
409  }
410  }
411 
412  return true;
413  }
414 
415 
421  void BundleObservation::initializeBodyRotation() {
422  std::vector<Angle> raCoefs = m_bundleTargetBody->poleRaCoefs();
423  std::vector<Angle> decCoefs = m_bundleTargetBody->poleDecCoefs();
424  std::vector<Angle> pmCoefs = m_bundleTargetBody->pmCoefs();
425 
426  for (int i = 0; i < size(); i++) {
427  BundleImageQsp image = at(i);
428  image->camera()->bodyRotation()->setPckPolynomial(raCoefs, decCoefs, pmCoefs);
429  }
430  }
431 
432 
439  void BundleObservation::updateBodyRotation() {
440  std::vector<Angle> raCoefs = m_bundleTargetBody->poleRaCoefs();
441  std::vector<Angle> decCoefs = m_bundleTargetBody->poleDecCoefs();
442  std::vector<Angle> pmCoefs = m_bundleTargetBody->pmCoefs();
443 
444  for (int i = 0; i < size(); i++) {
445  BundleImageQsp image = at(i);
446  image->camera()->bodyRotation()->setPckPolynomial(raCoefs, decCoefs, pmCoefs);
447  }
448  }
449 
450 
451 /*
452  bool BundleObservation::initializeExteriorOrientation() {
453 
454  if (m_solveSettings->instrumentPositionSolveOption() !=
455  BundleObservationSolveSettings::NoPositionFactors) {
456 
457  for (int i = 0; i < size(); i++) {
458  BundleImageQsp image = at(i);
459  SpicePosition *spiceposition = image->camera()->instrumentPosition();
460 
461  // first, set the degree of the spk polynomial to be fit for a priori values
462  spiceposition->SetPolynomialDegree(m_solveSettings->spkDegree());
463 
464  // now, set what kind of interpolation to use (SPICE, memcache, hermitecache, polynomial
465  // function, or polynomial function over constant hermite spline)
466  // TODO: verify - I think this actually performs the a priori fit
467  spiceposition->SetPolynomial(m_solveSettings->positionInterpolationType());
468 
469  // finally, set the degree of the spk polynomial actually used in the bundle adjustment
470  spiceposition->SetPolynomialDegree(m_solveSettings->spkSolveDegree());
471  }
472  }
473 
474  if (m_solveSettings->instrumentPointingSolveOption() !=
475  BundleObservationSolveSettings::NoPointingFactors) {
476 
477  for (int i = 0; i < size(); i++) {
478  BundleImageQsp image = at(i);
479  SpiceRotation *spicerotation = image->camera()->instrumentRotation();
480 
481  // first, set the degree of the spk polynomial to be fit for a priori values
482  spicerotation->SetPolynomialDegree(m_solveSettings->ckDegree());
483 
484  // now, set what kind of interpolation to use (SPICE, memcache, hermitecache, polynomial
485  // function, or polynomial function over constant hermite spline)
486  // TODO: verify - I think this actually performs the a priori fit
487  spicerotation->SetPolynomial(m_solveSettings->pointingInterpolationType());
488 
489  // finally, set the degree of the spk polynomial actually used in the bundle adjustment
490  spicerotation->SetPolynomialDegree(m_solveSettings->ckSolveDegree());
491  }
492  }
493 
494  return true;
495  }
496 */
497 
498 
513  bool BundleObservation::initParameterWeights() {
514 
515  // weights for
516  double posWeight = 0.0; // position
517  double velWeight = 0.0; // velocity
518  double accWeight = 0.0; // acceleration
519  double angWeight = 0.0; // angles
520  double angVelWeight = 0.0; // angular velocity
521  double angAccWeight = 0.0; // angular acceleration
522 
523  QList<double> aprioriPointingSigmas = m_solveSettings->aprioriPointingSigmas();
524  QList<double> aprioriPositionSigmas = m_solveSettings->aprioriPositionSigmas();
525 
526  int nCamPosCoeffsSolved = 3 *m_solveSettings->numberCameraPositionCoefficientsSolved();
527 
528  int nCamAngleCoeffsSolved;
529  if (m_solveSettings->solveTwist()) {
530  nCamAngleCoeffsSolved = 3 *m_solveSettings->numberCameraAngleCoefficientsSolved();
531  }
532  else {
533  nCamAngleCoeffsSolved = 2 *m_solveSettings->numberCameraAngleCoefficientsSolved();
534  }
535 
536  if (aprioriPositionSigmas.size() >= 1 && aprioriPositionSigmas.at(0) > 0.0) {
537  posWeight = aprioriPositionSigmas.at(0);
538  posWeight = 1.0 / (posWeight *posWeight * 1.0e-6);
539  }
540  if (aprioriPositionSigmas.size() >= 2 && aprioriPositionSigmas.at(1) > 0.0) {
541  velWeight = aprioriPositionSigmas.at(1);
542  velWeight = 1.0 / (velWeight *velWeight * 1.0e-6);
543  }
544  if (aprioriPositionSigmas.size() >= 3 && aprioriPositionSigmas.at(2) > 0.0) {
545  accWeight = aprioriPositionSigmas.at(2);
546  accWeight = 1.0 / (accWeight *accWeight * 1.0e-6);
547  }
548 
549  if (aprioriPointingSigmas.size() >= 1 && aprioriPointingSigmas.at(0) > 0.0) {
550  angWeight = aprioriPointingSigmas.at(0);
551  angWeight = 1.0 / (angWeight *angWeight * DEG2RAD * DEG2RAD);
552  }
553  if (aprioriPointingSigmas.size() >= 2 && aprioriPointingSigmas.at(1) > 0.0) {
554  angVelWeight = aprioriPointingSigmas.at(1);
555  angVelWeight = 1.0 / (angVelWeight * angVelWeight * DEG2RAD * DEG2RAD);
556  }
557  if (aprioriPointingSigmas.size() >= 3 && aprioriPointingSigmas.at(2) > 0.0) {
558  angAccWeight = aprioriPointingSigmas.at(2);
559  angAccWeight = 1.0 / (angAccWeight * angAccWeight * DEG2RAD * DEG2RAD);
560  }
561 
562  int nSpkTerms = m_solveSettings->spkSolveDegree()+1;
563  nSpkTerms = m_solveSettings->numberCameraPositionCoefficientsSolved();
564  for ( int i = 0; i < nCamPosCoeffsSolved; i++) {
565  if (i % nSpkTerms == 0) {
566  m_aprioriSigmas[i] = aprioriPositionSigmas.at(0);
567  m_weights[i] = posWeight;
568  }
569  if (i % nSpkTerms == 1) {
570  m_aprioriSigmas[i] = aprioriPositionSigmas.at(1);
571  m_weights[i] = velWeight;
572  }
573  if (i % nSpkTerms == 2) {
574  m_aprioriSigmas[i] = aprioriPositionSigmas.at(2);
575  m_weights[i] = accWeight;
576  }
577  }
578 
579  int nCkTerms = m_solveSettings->ckSolveDegree()+1;
580  nCkTerms = m_solveSettings->numberCameraAngleCoefficientsSolved();
581  for ( int i = 0; i < nCamAngleCoeffsSolved; i++) {
582  if (i % nCkTerms == 0) {
583  m_aprioriSigmas[nCamPosCoeffsSolved + i] = aprioriPointingSigmas.at(0);
584  m_weights[nCamPosCoeffsSolved + i] = angWeight;
585  }
586  if (i % nCkTerms == 1) {
587  m_aprioriSigmas[nCamPosCoeffsSolved + i] = aprioriPointingSigmas.at(1);
588  m_weights[nCamPosCoeffsSolved + i] = angVelWeight;
589  }
590  if (i % nCkTerms == 2) {
591  m_aprioriSigmas[nCamPosCoeffsSolved + i] = aprioriPointingSigmas.at(2);
592  m_weights[nCamPosCoeffsSolved + i] = angAccWeight;
593  }
594  }
595 
596 // for ( int i = 0; i < (int)m_weights.size(); i++ )
597 // std::cout << m_weights[i] << std::endl;
598 
599  return true;
600  }
601 
602 
619  bool BundleObservation::applyParameterCorrections(LinearAlgebra::Vector corrections) {
620 
621  int index = 0;
622 
623  try {
624  int nCameraAngleCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
625  int nCameraPositionCoefficients = m_solveSettings->numberCameraPositionCoefficientsSolved();
626 
628  = m_solveSettings->instrumentPositionSolveOption();
629  if (positionOption != BundleObservationSolveSettings::NoPositionFactors) {
630 
631  if (!m_instrumentPosition) {
632  QString msg = "Instrument position is NULL, but position solve option is ";
633  msg.append(BundleObservationSolveSettings::instrumentPositionSolveOptionToString(
634  positionOption));
635  throw IException(IException::Unknown, msg, _FILEINFO_);
636  }
637 
638  std::vector<double> coefX(nCameraPositionCoefficients);
639  std::vector<double> coefY(nCameraPositionCoefficients);
640  std::vector<double> coefZ(nCameraPositionCoefficients);
641 
642  m_instrumentPosition->GetPolynomial(coefX, coefY, coefZ);
643 
644  // update X coordinate coefficient(s) and sum parameter correction
645  for (int i = 0; i < nCameraPositionCoefficients; i++) {
646  coefX[i] += corrections(index);
647  index++;
648  }
649 
650  // update Y coordinate coefficient(s) and sum parameter correction
651  for (int i = 0; i < nCameraPositionCoefficients; i++) {
652  coefY[i] += corrections(index);
653  index++;
654  }
655 
656  // update Z coordinate coefficient(s) and sum parameter correction
657  for (int i = 0; i < nCameraPositionCoefficients; i++) {
658  coefZ[i] += corrections(index);
659  index++;
660  }
661 
662  // apply updates to all images in observation
663  for (int i = 0; i < size(); i++) {
664  BundleImageQsp image = at(i);
665  SpicePosition *spiceposition = image->camera()->instrumentPosition();
666  spiceposition->SetPolynomial(coefX, coefY, coefZ,
667  m_solveSettings->positionInterpolationType());
668  }
669  }
670 
672  = m_solveSettings->instrumentPointingSolveOption();
673  if (pointingOption != BundleObservationSolveSettings::NoPointingFactors) {
674 
675  if (!m_instrumentRotation) {
676  QString msg = "Instrument rotation is NULL, but pointing solve option is ";
677  msg.append(BundleObservationSolveSettings::instrumentPointingSolveOptionToString(
678  pointingOption));
679  throw IException(IException::Unknown, msg, _FILEINFO_);
680  }
681 
682  std::vector<double> coefRA(nCameraPositionCoefficients);
683  std::vector<double> coefDEC(nCameraPositionCoefficients);
684  std::vector<double> coefTWI(nCameraPositionCoefficients);
685 
686  m_instrumentRotation->GetPolynomial(coefRA, coefDEC, coefTWI);
687 
688  // update RA coefficient(s)
689  for (int i = 0; i < nCameraAngleCoefficients; i++) {
690  coefRA[i] += corrections(index);
691  index++;
692  }
693 
694  // update DEC coefficient(s)
695  for (int i = 0; i < nCameraAngleCoefficients; i++) {
696  coefDEC[i] += corrections(index);
697  index++;
698  }
699 
700  if (m_solveSettings->solveTwist()) {
701  // update TWIST coefficient(s)
702  for (int i = 0; i < nCameraAngleCoefficients; i++) {
703  coefTWI[i] += corrections(index);
704  index++;
705  }
706  }
707 
708  // apply updates to all images in observation
709  for (int i = 0; i < size(); i++) {
710  BundleImageQsp image = at(i);
711  SpiceRotation *spiceRotation = image->camera()->instrumentRotation();
712  spiceRotation->SetPolynomial(coefRA, coefDEC, coefTWI,
713  m_solveSettings->pointingInterpolationType());
714  }
715  }
716 
717  // update corrections
718  m_corrections += corrections;
719 
720  }
721  catch (IException &e) {
722  QString msg = "Unable to apply parameter corrections to BundleObservation.";
723  throw IException(e, IException::Unknown, msg, _FILEINFO_);
724  }
725  return true;
726  }
727 
728 
734  int BundleObservation::numberPositionParameters() {
735  return 3.0 * m_solveSettings->numberCameraPositionCoefficientsSolved();
736  }
737 
738 
744  int BundleObservation::numberPointingParameters() {
745  int angleCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
746 
747  if (m_solveSettings->solveTwist()) {
748  return 3.0 * angleCoefficients;
749  }
750  return 2.0 * angleCoefficients;
751  }
752 
753 
762  int BundleObservation::numberParameters() {
763  return numberPositionParameters() + numberPointingParameters();
764  }
765 
766 
772  void BundleObservation::setIndex(int n) {
773  m_index = n;
774  }
775 
776 
782  int BundleObservation::index() {
783  return m_index;
784  }
785 
805 QString BundleObservation::formatBundleOutputString(bool errorPropagation, bool imageCSV) {
806 
807  std::cerr << "The function formatBundleOutputString is depricated as of ISIS 3.9"
808  "and will be removed in ISIS 4.0" << std::endl;
809 
810  std::vector<double> coefX;
811  std::vector<double> coefY;
812  std::vector<double> coefZ;
813  std::vector<double> coefRA;
814  std::vector<double> coefDEC;
815  std::vector<double> coefTWI;
816 
817  int nPositionCoefficients = m_solveSettings->numberCameraPositionCoefficientsSolved();
818  int nPointingCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
819 
820  // Indicate if we need to obtain default position or pointing values
821  bool useDefaultPosition = false;
822  bool useDefaultPointing = false;
823  // Indicate if we need to use default values when not solving twist
824  bool useDefaultTwist = !(m_solveSettings->solveTwist());
825 
826  // If we aren't solving for position, set the number of coefficients to 1 so we can output the
827  // instrumentPosition's center coordinate values for X, Y, and Z
828  if (nPositionCoefficients == 0) {
829  nPositionCoefficients = 1;
830  useDefaultPosition = true;
831  }
832  // If we arent' solving for pointing, set the number of coefficients to 1 so we can output the
833  // instrumentPointing's center angles for RA, DEC, and TWI
834  if (nPointingCoefficients == 0) {
835  nPointingCoefficients = 1;
836  useDefaultPointing = true;
837  }
838 
839  // Force number of position and pointing parameters to each be 3 (X,Y,Z; RA,DEC,TWI)
840  // so we can always output a value for them
841  int nPositionParameters = 3 * nPositionCoefficients;
842  int nPointingParameters = 3 * nPointingCoefficients;
843  int nParameters = nPositionParameters + nPointingParameters;
844 
845  coefX.resize(nPositionCoefficients);
846  coefY.resize(nPositionCoefficients);
847  coefZ.resize(nPositionCoefficients);
848  coefRA.resize(nPointingCoefficients);
849  coefDEC.resize(nPointingCoefficients);
850  coefTWI.resize(nPointingCoefficients);
851 
852  if (m_instrumentPosition) {
853  if (!useDefaultPosition) {
854  m_instrumentPosition->GetPolynomial(coefX, coefY, coefZ);
855  }
856  // Use the position's center coordinate if not solving for spacecraft position
857  else {
858  const std::vector<double> centerCoord = m_instrumentPosition->GetCenterCoordinate();
859  coefX[0] = centerCoord[0];
860  coefY[0] = centerCoord[1];
861  coefZ[0] = centerCoord[2];
862  }
863  }
864 
865  if (m_instrumentRotation) {
866  if (!useDefaultPointing) {
867  m_instrumentRotation->GetPolynomial(coefRA, coefDEC, coefTWI);
868  }
869  // Use the pointing's center angles if not solving for pointing (rotation)
870  else {
871  const std::vector<double> centerAngles = m_instrumentRotation->GetCenterAngles();
872  coefRA[0] = centerAngles[0];
873  coefDEC[0] = centerAngles[1];
874  coefTWI[0] = centerAngles[2];
875  }
876  }
877 
878  // for convenience, create vectors of parameters names and values in the correct sequence
879  std::vector<double> finalParameterValues;
880  QStringList parameterNamesList;
881 
882  if (!imageCSV) {
883 
884  QString str("%1(t%2)");
885 
886  if (nPositionCoefficients > 0) {
887  for (int i = 0; i < nPositionCoefficients; i++) {
888  finalParameterValues.push_back(coefX[i]);
889  if (i == 0)
890  parameterNamesList.append( str.arg(" X ").arg("0") );
891  else
892  parameterNamesList.append( str.arg(" ").arg(i) );
893  }
894  for (int i = 0; i < nPositionCoefficients; i++) {
895  finalParameterValues.push_back(coefY[i]);
896  if (i == 0)
897  parameterNamesList.append( str.arg(" Y ").arg("0") );
898  else
899  parameterNamesList.append( str.arg(" ").arg(i) );
900  }
901  for (int i = 0; i < nPositionCoefficients; i++) {
902  finalParameterValues.push_back(coefZ[i]);
903  if (i == 0)
904  parameterNamesList.append( str.arg(" Z ").arg("0") );
905  else
906  parameterNamesList.append( str.arg(" ").arg(i) );
907  }
908  }
909  if (nPointingCoefficients > 0) {
910  for (int i = 0; i < nPointingCoefficients; i++) {
911  finalParameterValues.push_back(coefRA[i] * RAD2DEG);
912  if (i == 0)
913  parameterNamesList.append( str.arg(" RA ").arg("0") );
914  else
915  parameterNamesList.append( str.arg(" ").arg(i) );
916  }
917  for (int i = 0; i < nPointingCoefficients; i++) {
918  finalParameterValues.push_back(coefDEC[i] * RAD2DEG);
919  if (i == 0)
920  parameterNamesList.append( str.arg("DEC ").arg("0") );
921  else
922  parameterNamesList.append( str.arg(" ").arg(i) );
923  }
924  for (int i = 0; i < nPointingCoefficients; i++) {
925  finalParameterValues.push_back(coefTWI[i] * RAD2DEG);
926  if (i == 0)
927  parameterNamesList.append( str.arg("TWI ").arg("0") );
928  else
929  parameterNamesList.append( str.arg(" ").arg(i) );
930  }
931  }
932 
933  }// end if(!imageCSV)
934 
935  else {
936  if (nPositionCoefficients > 0) {
937  for (int i = 0; i < nPositionCoefficients; i++) {
938  finalParameterValues.push_back(coefX[i]);
939  }
940  for (int i = 0; i < nPositionCoefficients; i++) {
941  finalParameterValues.push_back(coefY[i]);
942  }
943  for (int i = 0; i < nPositionCoefficients; i++) {
944  finalParameterValues.push_back(coefZ[i]);
945  }
946  }
947  if (nPointingCoefficients > 0) {
948  for (int i = 0; i < nPointingCoefficients; i++) {
949  finalParameterValues.push_back(coefRA[i] * RAD2DEG);
950  }
951  for (int i = 0; i < nPointingCoefficients; i++) {
952  finalParameterValues.push_back(coefDEC[i] * RAD2DEG);
953  }
954  for (int i = 0; i < nPointingCoefficients; i++) {
955  finalParameterValues.push_back(coefTWI[i] * RAD2DEG);
956  }
957  }
958  }//end else
959 
960  // Save the list of parameter names we've accumulated above
961  m_parameterNamesList = parameterNamesList;
962 
963  QString finalqStr = "";
964  QString qStr = "";
965 
966  // Set up default values when we are using default position
967  QString sigma = "N/A";
968  QString adjustedSigma = "N/A";
969  double correction = 0.0;
970 
971  // this implies we're writing to bundleout.txt
972  if (!imageCSV) {
973  // position parameters
974  for (int i = 0; i < nPositionParameters; i++) {
975  // If not using the default position, we can correctly access sigmas and corrections
976  // members
977  if (!useDefaultPosition) {
978  correction = m_corrections(i);
979  adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
980  sigma = ( IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8) );
981  }
982  if (errorPropagation) {
983  qStr = QString("%1%2%3%4%5%6\n").
984  arg( parameterNamesList.at(i) ).
985  arg(finalParameterValues[i] - correction, 17, 'f', 8).
986  arg(correction, 21, 'f', 8).
987  arg(finalParameterValues[i], 20, 'f', 8).
988  arg(sigma, 18).
989  arg(adjustedSigma, 18);
990  }
991  else {
992  qStr = QString("%1%2%3%4%5%6\n").
993  arg( parameterNamesList.at(i) ).
994  arg(finalParameterValues[i] - correction, 17, 'f', 8).
995  arg(correction, 21, 'f', 8).
996  arg(finalParameterValues[i], 20, 'f', 8).
997  arg(sigma, 18).
998  arg("N/A", 18);
999  }
1000  finalqStr += qStr;
1001  }
1002 
1003  // We need to use an offset of -3 (1 coef; X,Y,Z) if we used the default center coordinate
1004  // (i.e. we did not solve for position), as m_corrections and m_*sigmas are populated
1005  // according to which parameters are solved
1006  int offset = 0;
1007  if (useDefaultPosition) {
1008  offset = 3;
1009  }
1010  // pointing parameters
1011  for (int i = nPositionParameters; i < nParameters; i++) {
1012  if (!useDefaultPointing) {
1013  // If solving camera and not solving for twist, provide default values for twist to
1014  // prevent bad indexing into m_corrections and m_*sigmas
1015  // TWIST is last parameter, which corresponds to nParameters - nPointingCoefficients
1016  if ( (i >= nParameters - nPointingCoefficients) && useDefaultTwist) {
1017  correction = 0.0;
1018  adjustedSigma = "N/A";
1019  sigma = "N/A";
1020  }
1021  else {
1022  correction = m_corrections(i - offset);
1023  adjustedSigma = QString::number(m_adjustedSigmas(i-offset) * RAD2DEG, 'f', 8);
1024  sigma = ( IsSpecial(m_aprioriSigmas[i - offset]) ? "FREE" :
1025  toString(m_aprioriSigmas[i-offset], 8) );
1026  }
1027  }
1028  // We are using default pointing, so provide default correction and sigma values to output
1029  else {
1030  correction = 0.0;
1031  adjustedSigma = "N/A";
1032  sigma = "N/A";
1033  }
1034  if (errorPropagation) {
1035  qStr = QString("%1%2%3%4%5%6\n").
1036  arg( parameterNamesList.at(i) ).
1037  arg( (finalParameterValues[i] - correction * RAD2DEG), 17, 'f', 8).
1038  arg(correction * RAD2DEG, 21, 'f', 8).
1039  arg(finalParameterValues[i], 20, 'f', 8).
1040  arg(sigma, 18).
1041  arg(adjustedSigma, 18);
1042  }
1043  else {
1044  qStr = QString("%1%2%3%4%5%6\n").
1045  arg( parameterNamesList.at(i) ).
1046  arg( (finalParameterValues[i] - correction * RAD2DEG), 17, 'f', 8).
1047  arg(correction * RAD2DEG, 21, 'f', 8).
1048  arg(finalParameterValues[i], 20, 'f', 8).
1049  arg(sigma, 18).
1050  arg("N/A", 18);
1051  }
1052  finalqStr += qStr;
1053  }
1054 
1055  }
1056  // this implies we're writing to images.csv
1057  else {
1058  // position parameters
1059  for (int i = 0; i < nPositionParameters; i++) {
1060  if (!useDefaultPosition) {
1061  correction = m_corrections(i);
1062  adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
1063  sigma = ( IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8) );
1064  }
1065  // Provide default values for position if not solving position
1066  else {
1067  correction = 0.0;
1068  adjustedSigma = "N/A";
1069  sigma = "N/A";
1070  }
1071  qStr = "";
1072  if (errorPropagation) {
1073  qStr += toString(finalParameterValues[i] - correction) + ",";
1074  qStr += toString(correction) + ",";
1075  qStr += toString(finalParameterValues[i]) + ",";
1076  qStr += sigma + ",";
1077  qStr += adjustedSigma + ",";
1078  }
1079  else {
1080  qStr += toString(finalParameterValues[i] - correction) + ",";
1081  qStr += toString(correction) + ",";
1082  qStr += toString(finalParameterValues[i]) + ",";
1083  qStr += sigma + ",";
1084  qStr += "N/A,";
1085  }
1086  finalqStr += qStr;
1087  }
1088 
1089  // If not solving position, we need to offset access to correction and sigma members by -3
1090  // (X,Y,Z) since m_corrections and m_*sigmas are populated according to which parameters are
1091  // solved
1092  int offset = 0;
1093  if (useDefaultPosition) {
1094  offset = 3;
1095  }
1096  // pointing parameters
1097  for (int i = nPositionParameters; i < nParameters; i++) {
1098  if (!useDefaultPointing) {
1099  // Use default values if solving camera but not solving for TWIST to prevent bad indexing
1100  // into m_corrections and m_*sigmas
1101  if ( (i >= nParameters - nPointingCoefficients) && useDefaultTwist) {
1102  correction = 0.0;
1103  adjustedSigma = "N/A";
1104  sigma = "N/A";
1105  }
1106  else {
1107  correction = m_corrections(i - offset);
1108  adjustedSigma = QString::number(m_adjustedSigmas(i-offset) * RAD2DEG, 'f', 8);
1109  sigma = ( IsSpecial(m_aprioriSigmas[i-offset]) ? "FREE" :
1110  toString(m_aprioriSigmas[i-offset], 8) );
1111  }
1112  }
1113  // Provide default values for pointing if not solving pointing
1114  else {
1115  correction = 0.0;
1116  adjustedSigma = "N/A";
1117  sigma = "N/A";
1118  }
1119  qStr = "";
1120  if (errorPropagation) {
1121  qStr += toString(finalParameterValues[i] - correction * RAD2DEG) + ",";
1122  qStr += toString(correction * RAD2DEG) + ",";
1123  qStr += toString(finalParameterValues[i]) + ",";
1124  qStr += sigma + ",";
1125  qStr += adjustedSigma + ",";
1126  }
1127  else {
1128  qStr += toString(finalParameterValues[i] - correction * RAD2DEG) + ",";
1129  qStr += toString(correction * RAD2DEG) + ",";
1130  qStr += toString(finalParameterValues[i]) + ",";
1131  qStr += sigma + ",";
1132  qStr += "N/A,";
1133  }
1134  finalqStr += qStr;
1135  }
1136  }
1137 
1138  return finalqStr;
1139 }
1140 
1141 
1153  void BundleObservation::bundleOutputFetchData(QVector<double> &finalParameterValues,
1154  int &nPositionCoefficients, int &nPointingCoefficients,
1155  bool &useDefaultPosition,
1156  bool &useDefaultPointing, bool &useDefaultTwist) {
1157 
1158  std::vector<double> coefX,coefY,coefZ,coefRA,coefDEC,coefTWI;
1159  nPositionCoefficients = m_solveSettings->numberCameraPositionCoefficientsSolved();
1160  nPointingCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
1161 
1162  // Indicate if we need to obtain default position or pointing values
1163  useDefaultPosition = false;
1164  useDefaultPointing = false;
1165  // Indicate if we need to use default values when not solving twist
1166  useDefaultTwist = !(m_solveSettings->solveTwist());
1167 
1168  // If we aren't solving for position, set the number of coefficients to 1 so we
1169  // can output the instrumentPosition's center coordinate values for X, Y, and Z
1170  if (nPositionCoefficients == 0) {
1171  nPositionCoefficients = 1;
1172  useDefaultPosition = true;
1173  }
1174 
1175  // If we arent' solving for pointing, set the number of coefficients to 1 so we
1176  // can output the instrumentPointing's center angles for RA, DEC, and TWI
1177  if (nPointingCoefficients == 0) {
1178  nPointingCoefficients = 1;
1179  useDefaultPointing = true;
1180  }
1181 
1182  coefX.resize(nPositionCoefficients);
1183  coefY.resize(nPositionCoefficients);
1184  coefZ.resize(nPositionCoefficients);
1185  coefRA.resize(nPointingCoefficients);
1186  coefDEC.resize(nPointingCoefficients);
1187  coefTWI.resize(nPointingCoefficients);
1188 
1189  if (m_instrumentPosition) {
1190  if (!useDefaultPosition) {
1191  m_instrumentPosition->GetPolynomial(coefX,coefY,coefZ);
1192  }
1193  // Use the position's center coordinate if not solving for spacecraft position
1194  else {
1195  const std::vector<double> centerCoord = m_instrumentPosition->GetCenterCoordinate();
1196  coefX[0] = centerCoord[0];
1197  coefY[0] = centerCoord[1];
1198  coefZ[0] = centerCoord[2];
1199  }
1200  }
1201 
1202  if (m_instrumentRotation) {
1203  if (!useDefaultPointing) {
1204  m_instrumentRotation->GetPolynomial(coefRA,coefDEC,coefTWI);
1205  }
1206  // Use the pointing's center angles if not solving for pointing (rotation)
1207  else {
1208  const std::vector<double> centerAngles = m_instrumentRotation->GetCenterAngles();
1209  coefRA[0] = centerAngles[0];
1210  coefDEC[0] = centerAngles[1];
1211  coefTWI[0] = centerAngles[2];
1212  }
1213  }
1214 
1215  // Combine all vectors into one
1216  if (nPositionCoefficients > 0) {
1217  for (int i=0; i < nPositionCoefficients; i++) {
1218  finalParameterValues.append(coefX[i]);
1219  }
1220  for (int i=0; i < nPositionCoefficients; i++) {
1221  finalParameterValues.append(coefY[i]);
1222  }
1223  for (int i=0; i < nPositionCoefficients; i++) {
1224  finalParameterValues.append(coefZ[i]);
1225  }
1226  }
1227  if (nPointingCoefficients > 0) {
1228  for (int i=0; i < nPointingCoefficients; i++) {
1229  finalParameterValues.append(coefRA[i]);
1230  }
1231  for (int i=0; i < nPointingCoefficients; i++) {
1232  finalParameterValues.append(coefDEC[i]);
1233  }
1234  for (int i=0; i < nPointingCoefficients; i++) {
1235  finalParameterValues.append(coefTWI[i]);
1236  }
1237  }
1238 
1239  }
1240 
1241 
1251  void BundleObservation::bundleOutputString(std::ostream &fpOut, bool errorPropagation) {
1252 
1253  char buf[4096];
1254 
1255  QVector<double> finalParameterValues;
1256  int nPositionCoefficients, nPointingCoefficients;
1257  bool useDefaultPosition, useDefaultPointing,useDefaultTwist;
1258 
1259  bundleOutputFetchData(finalParameterValues,
1260  nPositionCoefficients,nPointingCoefficients,
1261  useDefaultPosition,useDefaultPointing,useDefaultTwist);
1262 
1263  int nPositionParameters = 3 * nPositionCoefficients;
1264  int nPointingParameters = 3 * nPointingCoefficients;
1265  int nParameters = nPositionParameters + nPointingParameters;
1266 
1267  // for convenience, create vectors of parameters names and values in the correct sequence
1268  QStringList parameterNamesListX,parameterNamesListY,parameterNamesListZ,
1269  parameterNamesListRA,parameterNamesListDEC,parameterNamesListTWI,
1270  parameterNamesList;
1271  QStringList correctionUnitListX,correctionUnitListY,correctionUnitListZ,
1272  correctionUnitListRA,correctionUnitListDEC,correctionUnitListTWI,
1273  correctionUnitList;
1274 
1275  QString str("%1(%2) ");
1276  QString str2("%1(%2) ");
1277  QString strN("%1(%2)");
1278 
1279 
1280  if (nPositionCoefficients > 0) {
1281  for (int j = 0; j < nPositionCoefficients;j++) {
1282  if (j == 0) {
1283  parameterNamesListX.append(str.arg(" X ").arg("km"));
1284  parameterNamesListY.append(str.arg(" Y ").arg("km"));
1285  parameterNamesListZ.append(str.arg(" Z ").arg("km"));
1286  correctionUnitListX.append("m");
1287  correctionUnitListY.append("m");
1288  correctionUnitListZ.append("m");
1289  } //end inner-if
1290 
1291  else if (j==1) {
1292  parameterNamesListX.append( str2.arg(" ").arg("km/s") );
1293  parameterNamesListY.append( str2.arg(" ").arg("km/s") );
1294  parameterNamesListZ.append( str2.arg(" ").arg("km/s") );
1295  correctionUnitListX.append("m/s");
1296  correctionUnitListY.append("m/s");
1297  correctionUnitListZ.append("m/s");
1298  }
1299  else {
1300  QString str("%1(%2)");
1301  parameterNamesListX.append(strN.arg(" ").arg("km/s^"+toString(j) ) );
1302  parameterNamesListY.append(strN.arg(" ").arg("km/s^"+toString(j) ) );
1303  parameterNamesListZ.append(strN.arg(" ").arg("km/s^"+toString(j) ) );
1304  correctionUnitListX.append("m/s^"+toString(j));
1305  correctionUnitListY.append("m/s^"+toString(j));
1306  correctionUnitListZ.append("m/s^"+toString(j));
1307  }
1308  }//end for
1309  }//end outer-if
1310 
1311  if (nPointingCoefficients > 0) {
1312  for (int j = 0; j < nPointingCoefficients;j++) {
1313  if (j == 0) {
1314  parameterNamesListRA.append(str.arg(" RA ").arg("dd"));
1315  parameterNamesListDEC.append(str.arg("DEC ").arg("dd"));
1316  parameterNamesListTWI.append(str.arg("TWI ").arg("dd"));
1317  correctionUnitListRA.append("dd");
1318  correctionUnitListDEC.append("dd");
1319  correctionUnitListTWI.append("dd");
1320  } //end inner-if
1321 
1322  else if (j==1) {
1323  parameterNamesListRA.append( str2.arg(" ").arg("dd/s") );
1324  parameterNamesListDEC.append( str2.arg(" ").arg("dd/s") );
1325  parameterNamesListTWI.append( str2.arg(" ").arg("dd/s") );
1326  correctionUnitListRA.append("dd/s");
1327  correctionUnitListDEC.append("dd/s");
1328  correctionUnitListTWI.append("dd/s");
1329  }
1330  else {
1331  parameterNamesListRA.append(strN.arg(" ").arg("dd/s^"+toString(j) ) );
1332  parameterNamesListDEC.append(strN.arg(" ").arg("dd/s^"+toString(j) ) );
1333  parameterNamesListTWI.append(strN.arg(" ").arg("dd/s^"+toString(j) ) );
1334  correctionUnitListRA.append("dd/s^"+toString(j));
1335  correctionUnitListDEC.append("dd/s^"+toString(j));
1336  correctionUnitListTWI.append("dd/s^"+toString(j));
1337  }
1338  }//end for
1339  }// end outer-if
1340 
1341  //Put all of the parameter names together into one QStringList
1342  parameterNamesList.append(parameterNamesListX);
1343  parameterNamesList.append(parameterNamesListY);
1344  parameterNamesList.append(parameterNamesListZ);
1345  parameterNamesList.append(parameterNamesListRA);
1346  parameterNamesList.append(parameterNamesListDEC);
1347  parameterNamesList.append(parameterNamesListTWI);
1348 
1349  //Put all of the correction unit names together into one QStringList
1350  correctionUnitList.append(correctionUnitListX);
1351  correctionUnitList.append(correctionUnitListY);
1352  correctionUnitList.append(correctionUnitListZ);
1353  correctionUnitList.append(correctionUnitListDEC);
1354  correctionUnitList.append(correctionUnitListRA);
1355  correctionUnitList.append(correctionUnitListTWI);
1356 
1357  // Save the list of parameter names we've accumulated above
1358  m_parameterNamesList = parameterNamesList;
1359 
1360  // Set up default values when we are using default position
1361  QString sigma = "N/A";
1362  QString adjustedSigma = "N/A";
1363  double correction = 0.0;
1364 
1365  // position parameters
1366  for (int i = 0; i < nPositionParameters; i++) {
1367  // If not using the default position, we can correctly access sigmas and corrections
1368  // members
1369  if (!useDefaultPosition) {
1370  correction = m_corrections(i);
1371  adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
1372  sigma = ( IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8) );
1373  }
1374 
1375  sprintf(buf,"%s",parameterNamesList.at(i).toStdString().c_str() );
1376  fpOut << buf;
1377  sprintf(buf,"%18.8lf ",finalParameterValues[i] - correction);
1378  fpOut << buf;
1379  sprintf(buf,"%20.8lf ",correction);
1380  fpOut << buf;
1381  sprintf(buf,"%23.8lf ",finalParameterValues[i]);
1382  fpOut << buf;
1383  sprintf(buf," ");
1384  fpOut << buf;
1385  sprintf(buf,"%6s",sigma.toStdString().c_str());
1386  fpOut << buf;
1387  sprintf(buf," ");
1388  fpOut << buf;
1389  if (errorPropagation) {
1390  sprintf(buf,"%s",adjustedSigma.toStdString().c_str());
1391  }
1392  else {
1393  sprintf(buf,"%s","N/A");
1394  }
1395  fpOut<<buf;
1396  sprintf(buf," ");
1397  fpOut<<buf;
1398  sprintf(buf,"%s\n",correctionUnitList.at(i).toStdString().c_str() );
1399  fpOut<<buf;
1400 
1401  }
1402 
1403  // We need to use an offset of -3 (1 coef; X,Y,Z) if we used the default center coordinate
1404  // (i.e. we did not solve for position), as m_corrections and m_*sigmas are populated
1405  // according to which parameters are solved
1406  int offset = 0;
1407  if (useDefaultPosition) {
1408  offset = 3;
1409  }
1410 
1411  // pointing parameters
1412  for (int i = nPositionParameters; i < nParameters; i++) {
1413  if (!useDefaultPointing) {
1414  // If solving camera and not solving for twist, provide default values for twist to
1415  // prevent bad indexing into m_corrections and m_*sigmas
1416  // TWIST is last parameter, which corresponds to nParameters - nPointingCoefficients
1417  if ( (i >= nParameters - nPointingCoefficients) && useDefaultTwist) {
1418  correction = 0.0;
1419  adjustedSigma = "N/A";
1420  sigma = "N/A";
1421  }
1422  else {
1423  correction = m_corrections(i - offset);
1424  adjustedSigma = QString::number(m_adjustedSigmas(i-offset) * RAD2DEG, 'f', 8);
1425  sigma = ( IsSpecial(m_aprioriSigmas[i - offset]) ? "FREE" :
1426  toString(m_aprioriSigmas[i-offset], 8) );
1427  }
1428  }
1429  // We are using default pointing, so provide default correction and sigma values to output
1430  else {
1431  correction = 0.0;
1432  adjustedSigma = "N/A";
1433  sigma = "N/A";
1434  }
1435 
1436  sprintf(buf,"%s",parameterNamesList.at(i).toStdString().c_str() );
1437  fpOut << buf;
1438  sprintf(buf,"%18.8lf ",(finalParameterValues[i]*RAD2DEG - correction*RAD2DEG));
1439  fpOut << buf;
1440  sprintf(buf,"%20.8lf ",(correction*RAD2DEG));
1441  fpOut << buf;
1442  sprintf(buf,"%23.8lf ",(finalParameterValues[i]*RAD2DEG));
1443  fpOut << buf;
1444  sprintf(buf," ");
1445  fpOut << buf;
1446  sprintf(buf,"%6s",sigma.toStdString().c_str());
1447  fpOut << buf;
1448  sprintf(buf," ");
1449  fpOut << buf;
1450  if (errorPropagation) {
1451  sprintf(buf,"%s",adjustedSigma.toStdString().c_str());
1452  }
1453  else {
1454  sprintf(buf,"%s","N/A");
1455  }
1456  fpOut<<buf;
1457  sprintf(buf," ");
1458  fpOut<<buf;
1459  sprintf(buf,"%s\n",correctionUnitList.at(i).toStdString().c_str() );
1460  fpOut<<buf;
1461  }
1462 
1463  }
1464 
1475  QString BundleObservation::bundleOutputCSV(bool errorPropagation) {
1476 
1477  QVector<double> finalParameterValues;
1478  int nPositionCoefficients, nPointingCoefficients;
1479  bool useDefaultPosition, useDefaultPointing,useDefaultTwist;
1480 
1481  bundleOutputFetchData(finalParameterValues,
1482  nPositionCoefficients,nPointingCoefficients,
1483  useDefaultPosition,useDefaultPointing,useDefaultTwist);
1484 
1485  int nPositionParameters = 3 * nPositionCoefficients;
1486  int nPointingParameters = 3 * nPointingCoefficients;
1487  int nParameters = nPositionParameters + nPointingParameters;
1488 
1489  QString finalqStr = "";
1490 
1491  // Set up default values when we are using default position
1492  QString sigma = "N/A";
1493  QString adjustedSigma = "N/A";
1494  double correction = 0.0;
1495 
1496  // Position parameters
1497  for (int i = 0; i < nPositionParameters; i++) {
1498  if (!useDefaultPosition) {
1499  correction = m_corrections(i);
1500  adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
1501  sigma = ( IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8) );
1502  }
1503  // Provide default values for position if not solving position
1504  else {
1505  correction = 0.0;
1506  adjustedSigma = "N/A";
1507  sigma = "N/A";
1508  }
1509 
1510  finalqStr += toString(finalParameterValues[i] - correction) + ",";
1511  finalqStr += toString(correction) + ",";
1512  finalqStr += toString(finalParameterValues[i]) + ",";
1513  finalqStr += sigma + ",";
1514  if (errorPropagation) {
1515  finalqStr += adjustedSigma + ",";
1516  }
1517  else {
1518  finalqStr += "N/A,";
1519  }
1520 
1521  }
1522 
1523  // If not solving position, we need to offset access to correction and sigma members by -3
1524  // (X,Y,Z) since m_corrections and m_*sigmas are populated according to which parameters are
1525  // solved
1526  int offset = 0;
1527  if (useDefaultPosition) {
1528  offset = 3;
1529  }
1530  // pointing parameters
1531  for (int i = nPositionParameters; i < nParameters; i++) {
1532  if (!useDefaultPointing) {
1533  // Use default values if solving camera but not solving for TWIST to prevent bad indexing
1534  // into m_corrections and m_*sigmas
1535  if ( (i >= nParameters - nPointingCoefficients) && useDefaultTwist) {
1536  correction = 0.0;
1537  adjustedSigma = "N/A";
1538  sigma = "N/A";
1539  }
1540  else {
1541  correction = m_corrections(i - offset);
1542  adjustedSigma = QString::number(m_adjustedSigmas(i-offset) * RAD2DEG, 'f', 8);
1543  sigma = ( IsSpecial(m_aprioriSigmas[i-offset]) ? "FREE" :
1544  toString(m_aprioriSigmas[i-offset], 8) );
1545  }
1546  }
1547  // Provide default values for pointing if not solving pointing
1548  else {
1549  correction = 0.0;
1550  adjustedSigma = "N/A";
1551  sigma = "N/A";
1552  }
1553 
1554  finalqStr += toString(finalParameterValues[i]*RAD2DEG - correction * RAD2DEG) + ",";
1555  finalqStr += toString(correction * RAD2DEG) + ",";
1556  finalqStr += toString(finalParameterValues[i]*RAD2DEG) + ",";
1557  finalqStr += sigma + ",";
1558  if (errorPropagation) {
1559  finalqStr += adjustedSigma + ",";
1560  }
1561  else {
1562  finalqStr += "N/A,";
1563  }
1564 
1565  }
1566 
1567  return finalqStr;
1568  }
1569 
1570 
1576  QStringList BundleObservation::parameterList() {
1577  return m_parameterNamesList;
1578  }
1579 
1580 
1586  QStringList BundleObservation::imageNames() {
1587  return m_imageNames;
1588  }
1589 }
void SetOverrideBaseTime(double baseTime, double timeScale)
Set an override base time to be used with observations on scanners to allow all images in an observat...
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
QString m_observationNumber
This is typically equivalent to serial number except in the case of "observation mode" (e...
void SetPolynomialDegree(int degree)
Set the degree of the polynomials to be fit to the three camera angles for the time period covered by...
void GetPolynomial(std::vector< double > &abcAng1, std::vector< double > &abcAng2, std::vector< double > &abcAng3)
Return the coefficients of a polynomial fit to each of the three camera angles for the time period co...
QSharedPointer< BundleObservationSolveSettings > BundleObservationSolveSettingsQsp
Definition for BundleObservationSolveSettingsQsp, a QSharedPointer to a BundleObservationSolveSetting...
QMap< QString, BundleImageQsp > m_cubeSerialNumberToBundleImageMap
Map between cube serial number and BundleImage pointers.
Namespace for the standard library.
Class for bundle observations.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
BundleObservationSolveSettingsQsp m_solveSettings
Solve settings for this observation.
boost::numeric::ublas::vector< double > Vector
Definition for an Isis::LinearAlgebra::Vector of doubles.
double GetBaseTime()
Accessor method to get the rotation base time.
SpiceRotation * m_instrumentRotation
Instrument spice rotation (in primary image).
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
void SetPolynomialDegree(int degree)
Set the polynomial degree.
void SetOverrideBaseTime(double baseTime, double timeScale)
Set an override base time to be used with observations on scanners to allow all images in an observat...
QStringList m_serialNumbers
List of all cube serial numbers in observation.
bool IsSpecial(const double d)
Returns if the input pixel is special.
Definition: SpecialPixel.h:212
Obtain SPICE rotation information for a body.
This class is used to modify and manage solve settings for 1 to many BundleObservations.
const double DEG2RAD
Multiplier for converting from degrees to radians.
Definition: Constants.h:59
QString m_instrumentId
Spacecraft instrument id.
Isis exception class.
Definition: IException.h:107
InstrumentPositionSolveOption
Options for how to solve for instrument position.
Obtain SPICE position information for a body.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
SpicePosition * m_instrumentPosition
Instrument spice position (in primary image).
InstrumentPointingSolveOption
Options for how to solve for instrument pointing.
const double RAD2DEG
Multiplier for converting from radians to degrees.
Definition: Constants.h:60
double GetTimeScale()
Accessor method to get the rotation time scale.
void SetPolynomial(const Source type=PolyFunction)
Set the coefficients of a polynomial fit to each of the three camera angles for the time period cover...
int m_index
Index of this observation.
void SetPolynomial(const Source type=PolyFunction)
Set the coefficients of a polynomial fit to each of the components (X, Y, Z) of the position vector f...