Isis 3 Programmer Reference
JigsawSetupDialog.cpp
1 #include "JigsawSetupDialog.h"
2 
3 #include <vector>
4 
5 #include <QDebug>
6 #include <QIdentityProxyModel>
7 #include <QMessageBox>
8 #include <QPushButton>
9 #include <QSortFilterProxyModel>
10 #include <QStandardItemModel>
11 #include <QItemSelection>
12 
14 #include "BundleSolutionInfo.h"
15 #include "BundleSettings.h"
16 #include "BundleTargetBody.h"
17 #include "Camera.h"
18 #include "Control.h"
19 #include "Cube.h"
20 #include "Image.h"
21 #include "IString.h"
23 #include "Project.h"
24 #include "ProjectItem.h"
25 #include "ProjectItemProxyModel.h"
26 #include "SpecialPixel.h"
27 #include "SortFilterProxyModel.h"
28 #include "ui_JigsawSetupDialog.h"
29 
30 namespace Isis {
31 
32  JigsawSetupDialog::JigsawSetupDialog(Project *project, bool useLastSettings, bool readOnly,
33  QWidget *parent) : QDialog(parent),
34  m_ui(new Ui::JigsawSetupDialog) {
35  //
36  // Note: When the ui is set up, all initializations to enabled/disabled
37  // are taken care of. Also connections between some widgets will be taken
38  // care of in the ui setup.
39 
40  // For example:
41  // pointRadiusSigmaCheckBox is connected to pointRadiusSigmaLineEdit
42  // outlierRejectionCheckBox is connected
43  // to outlierRejectionMultiplierLabel and outlierRejectionMultiplierLineEdit
44  //
45  // These connections and settings can be found in the JigsawSetupDialog.ui file
46  // created by QtDesigner and may be edited by opening the ui file in QtDesigner.
47  //
48  // More complex connections such as the relationship between positionSolveOption and
49  // spkDegree are handled in this file by the on_widgetName_signal methods.
50  m_ui->setupUi(this);
51 
52  m_project = project;
53 
54  m_ui->JigsawSetup->setCurrentIndex(0);
55 
56  if (readOnly) {
57  makeReadOnly();
58  }
59 
60  m_bundleSettings = BundleSettingsQsp(new BundleSettings());
61 
62  //connect( m_project->directory()->model(), SIGNAL(selectionChanged(QList<ProjectItem *> &)),
63  // this, SLOT(on_projectItemSelectionChanged(const QList<ProjectItem *> &) ) );
64 
65  // initializations for general tab
66 
67  // fill control net combo box from project
68  for (int i = 0; i < project->controls().size(); i++) {
69  ControlList* conlist = project->controls().at(i);
70  for (int j = 0; j < conlist->size(); j++) {
71  Control *control = conlist->at(j);
72 
73  QVariant v = qVariantFromValue((void*)control);
74 
75  m_ui->inputControlNetCombo->addItem(control->displayProperties()->displayName(), v);
76  }
77  }
78  // add control nets from bundle solutions, if any
79  int numBundles = project->bundleSolutionInfo().size();
80  for (int i = 0; i < numBundles; i++) {
81  Control *bundleControl = project->bundleSolutionInfo().at(i)->control();
82 
83  QVariant v = qVariantFromValue((void*)bundleControl);
84 
85  m_ui->inputControlNetCombo->addItem(bundleControl->displayProperties()->displayName(), v);
86  }
87 
88  // initialize default output control network filename
89  FileName fname = m_ui->inputControlNetCombo->currentText();
90  m_ui->outputControlNetLineEdit->setText(fname.baseName() + "-out.net");
91 
92  // initializations for observation solve settings tab
93  createObservationSolveSettingsTreeView();
94 
95 
96  // Create default settings for all of the observations
97  QList<Image *> imagesToAdd;
98  // If we have selected any project items, find the images and add them to imagesToAdd
99  if (!m_project->directory()->model()->selectedItems().isEmpty()) {
100  foreach (ProjectItem * projItem, m_project->directory()->model()->selectedItems()) {
101  if (projItem->isImage()) {
102  imagesToAdd.append(projItem->image());
103  }
104  else if (projItem->isImageList()) {
105  for (int i = 0; i < projItem->rowCount(); i++) {
106  imagesToAdd.append(projItem->child(i)->image());
107  }
108  }
109  }
110  }
111  // if we didnt have any images selected in the previous case, or no proj items were selected,
112  // take all images from the project tree
113  if (imagesToAdd.isEmpty()) {
114  ProjectItem *imgRoot = m_project->directory()->model()->findItemData(QVariant("Images"),0);
115  if (imgRoot) {
116  for (int i = 0; i < imgRoot->rowCount(); i++) {
117  ProjectItem * imglistItem = imgRoot->child(i);
118  for (int j = 0; j < imglistItem->rowCount(); j++) {
119  ProjectItem * imgItem = imglistItem->child(j);
120  if (imgItem->isImage()) {
121  imagesToAdd.append(imgItem->image());
122  }
123  }
124  }
125  }
126  }
127 
128  // create default solve settings for supported camera types
129  BundleObservationSolveSettings defaultFramingSettings;
130  BundleObservationSolveSettings defaultLineScanSettings;
131  defaultLineScanSettings.setInstrumentPointingSettings(
133 
134 
135  // sort each chosen image into its camera type
136  foreach (Image * image, imagesToAdd) {
137  int cameraType = image->cube()->camera()->GetCameraType();
138  if (cameraType == Camera::LineScan) {
139  defaultLineScanSettings.addObservationNumber(image->observationNumber());
140  }
141  else { // assume cameraType == Camera::Framing
142  defaultFramingSettings.addObservationNumber(image->observationNumber());
143  }
144  }
145 
146  // only add defaults that have been applied
147  QList<BundleObservationSolveSettings> solveSettingsList;
148  if (defaultFramingSettings.observationNumbers().count())
149  solveSettingsList.append(defaultFramingSettings);
150  if (defaultLineScanSettings.observationNumbers().count())
151  solveSettingsList.append(defaultLineScanSettings);
152 
153  m_bundleSettings->setObservationSolveOptions(solveSettingsList);
154 
155  // Populate the solve option comboboxes
156  const QStringList positionOptions{"NONE", "POSITION", "VELOCITY", "ACCELERATION", "ALL"};
157  m_ui->positionComboBox->insertItems(0, positionOptions);
158  m_ui->positionComboBox->setCurrentIndex(0);
159 
160  const QStringList pointingOptions{"NONE", "ANGLES", "VELOCITY", "ACCELERATION", "ALL"};
161  m_ui->pointingComboBox->insertItems(0, pointingOptions);
162  m_ui->pointingComboBox->setCurrentIndex(1);
163 
164  // The degree solve options' minimums are -1 (set in ui file), make the -1's display as N/A
165  m_ui->spkSolveDegreeSpinBox->setSpecialValueText("N/A");
166  m_ui->ckSolveDegreeSpinBox->setSpecialValueText("N/A");
167 
168 
169  QStringList tableHeaders;
170  tableHeaders << "coefficients" << "description" << "units" << "a priori sigma";
171  m_ui->positionAprioriSigmaTable->setHorizontalHeaderLabels(tableHeaders);
172  m_ui->pointingAprioriSigmaTable->setHorizontalHeaderLabels(tableHeaders);
173 
174  // Set the default size of the columns
175  m_ui->positionAprioriSigmaTable->setColumnWidth(0, fontMetrics().width(tableHeaders.at(0)) + 10);
176  m_ui->positionAprioriSigmaTable->setColumnWidth(1, fontMetrics().width(tableHeaders.at(1)) + 10);
177  m_ui->positionAprioriSigmaTable->setColumnWidth(2, fontMetrics().width(tableHeaders.at(2)) + 10);
178  m_ui->positionAprioriSigmaTable->setColumnWidth(3, fontMetrics().width(tableHeaders.at(3)) + 10);
179 
180  m_ui->pointingAprioriSigmaTable->setColumnWidth(0, fontMetrics().width(tableHeaders.at(0)) + 10);
181  m_ui->pointingAprioriSigmaTable->setColumnWidth(1, fontMetrics().width(tableHeaders.at(1)) + 10);
182  m_ui->pointingAprioriSigmaTable->setColumnWidth(2, fontMetrics().width(tableHeaders.at(2)) + 10);
183  m_ui->pointingAprioriSigmaTable->setColumnWidth(3, fontMetrics().width(tableHeaders.at(3)) + 10);
184 
185 
186  // Add validators to the tables in the observation solve settings tab to validate the a priori
187  // sigma items
188  connect(m_ui->positionAprioriSigmaTable, SIGNAL(itemChanged(QTableWidgetItem *)),
189  this, SLOT(validateSigmaValue(QTableWidgetItem *)));
190  connect(m_ui->pointingAprioriSigmaTable, SIGNAL(itemChanged(QTableWidgetItem *)),
191  this, SLOT(validateSigmaValue(QTableWidgetItem *)));
192 
193  // initializations for target body tab
194 
195  // fill target combo box from project
196  for (int i = 0; i < project->targetBodies().size(); i++) {
197  TargetBodyQsp target = project->targetBodies().at(i);
198 
199  QVariant v = qVariantFromValue((void*)target.data());
200 
201  QString name = target->displayProperties()->displayName();
202 
203  if (name == "MOON")
204  m_ui->targetBodyComboBox->addItem(QIcon(FileName(
205  "$base/icons/weather-clear-night.png").expanded()), name, v);
206  else if (name == "Enceladus")
207  m_ui->targetBodyComboBox->addItem(QIcon(FileName(
208  "$base/icons/nasa_enceladus.png").expanded()), name, v);
209  else if (name == "Mars")
210  m_ui->targetBodyComboBox->addItem(QIcon(FileName(
211  "$base/icons/nasa_mars.png").expanded()), name, v);
212  else if (name == "Titan")
213  m_ui->targetBodyComboBox->addItem(QIcon(FileName(
214  "$base/icons/nasa_titan.png").expanded()), name, v);
215  else
216  m_ui->targetBodyComboBox->addItem(QIcon(FileName(
217  "$base/icons/weather-clear-night.png").expanded()), name, v);
218  }
219 
220  m_ui->radiiButtonGroup->setId(m_ui->noneRadiiRadioButton,0);
221  m_ui->radiiButtonGroup->setId(m_ui->triaxialRadiiRadioButton,1);
222  m_ui->radiiButtonGroup->setId(m_ui->meanRadiusRadioButton,2);
223  m_ui->noneRadiiRadioButton->setChecked(true);
224 
225  // validators for target body entries...
226  QDoubleValidator *sigmaValidator = new QDoubleValidator(0.0, 1.0e+4, 8, this);
227  sigmaValidator->setNotation(QDoubleValidator::ScientificNotation);
228 
229  // right ascension valid range is from 0 to 360 degrees
230  QDoubleValidator *raValidator = new QDoubleValidator(0.0, 360.0, 8, this);
231  raValidator->setNotation(QDoubleValidator::StandardNotation);
232  m_ui->rightAscensionLineEdit->setValidator(raValidator);
233  m_ui->rightAscensionSigmaLineEdit->setValidator(sigmaValidator);
234 
235  m_ui->rightAscensionVelocityLineEdit->setValidator(raValidator);
236  m_ui->rightAscensionVelocitySigmaLineEdit->setValidator(sigmaValidator);
237 
238  // declination valid range is from -90 to +90 degrees
239  QDoubleValidator *decValidator = new QDoubleValidator(-90.0, 90.0, 8,
240  m_ui->declinationLineEdit);
241  decValidator->setNotation(QDoubleValidator::StandardNotation);
242  m_ui->declinationLineEdit->setValidator(decValidator);
243  m_ui->declinationSigmaLineEdit->setValidator(sigmaValidator);
244 
245  m_ui->declinationVelocityLineEdit->setValidator(new QDoubleValidator(0.0, 1.0e+10, 8,
246  m_ui->declinationVelocityLineEdit));
247  m_ui->declinationVelocitySigmaLineEdit->setValidator(sigmaValidator);
248 
249  m_ui->primeMeridianOffsetLineEdit->setValidator(raValidator);
250  m_ui->primeMeridianOffsetSigmaLineEdit->setValidator(sigmaValidator);
251 
252  // spin rate valid for non-negative values
253  m_ui->spinRateLineEdit->setValidator(new QDoubleValidator(0.0, 1.0e+10, 8,
254  m_ui->spinRateLineEdit));
255  m_ui->spinRateSigmaLineEdit->setValidator(sigmaValidator);
256 
257  m_ui->aRadiusLineEdit->setValidator(new QDoubleValidator(0.0, 1.0e+10, 8,
258  m_ui->aRadiusLineEdit));
259  m_ui->aRadiusSigmaLineEdit->setValidator(sigmaValidator);
260 
261  m_ui->bRadiusLineEdit->setValidator(new QDoubleValidator(0.0, 1.0e+10, 8,
262  m_ui->bRadiusLineEdit));
263  m_ui->bRadiusSigmaLineEdit->setValidator(sigmaValidator);
264 
265  m_ui->cRadiusLineEdit->setValidator(new QDoubleValidator(0.0, 1.0e+10, 8,
266  m_ui->cRadiusLineEdit));
267  m_ui->cRadiusSigmaLineEdit->setValidator(sigmaValidator);
268 
269  m_ui->meanRadiusLineEdit->setValidator(new QDoubleValidator(0.0, 1.0e+10, 8,
270  m_ui->meanRadiusLineEdit));
271  m_ui->meanRadiusSigmaLineEdit->setValidator(sigmaValidator);
272 
273 
274 
275  // jigsaw run setup general tab validation
276  // global apriori point sigmas
277  m_ui->pointLatitudeSigmaLineEdit->setValidator(new QDoubleValidator(1.0e-10, 1.0e+10, 8, this));
278  m_ui->pointLongitudeSigmaLineEdit->setValidator(new QDoubleValidator(1.0e-10, 1.0e+10, 8,this));
279  m_ui->pointRadiusSigmaLineEdit->setValidator(new QDoubleValidator(1.0e-10, 1.0e+10, 8, this));
280 
281  // outlier rejection
282  m_ui->outlierRejectionMultiplierLineEdit->setValidator(
283  new QDoubleValidator(1.0e-10, 1.0e+10, 8, this));
284  m_ui->maximumLikelihoodModel1QuantileLineEdit->setValidator(
285  new QDoubleValidator(1.0e-10, 1.0, 8, this));
286  m_ui->maximumLikelihoodModel2QuantileLineEdit->setValidator(
287  new QDoubleValidator(1.0e-10, 1.0, 8, this));
288  m_ui->maximumLikelihoodModel3QuantileLineEdit->setValidator(
289  new QDoubleValidator(1.0e-10, 1.0, 8, this));
290 
291  // convergence criteria
292  m_ui->sigma0ThresholdLineEdit->setValidator(new QDoubleValidator(1.0e-20, 1.0e+10, 8, this));
293  m_ui->maximumIterationsLineEdit->setValidator(new QIntValidator(1, 10000, this));
294 
295 
296 
297  // signals for target body tab
298 // connect(m_ui->radiiButtonGroup, SIGNAL(buttonClicked(int)),
299 // this, SLOT(on_radiiGroupClicked(int)));
300  connect(m_ui->radiiButtonGroup, SIGNAL(buttonClicked(int)),
301  this, SLOT(on_radiiButtonGroupClicked(int)));
302  connect(m_ui->aRadiusLineEdit, SIGNAL(textChanged(QString)), SLOT(slotTextChanged(QString)));
303  connect(m_ui->aRadiusLineEdit, SIGNAL(returnPressed()), SLOT(checkIsValid()));
304  connect(m_ui->aRadiusLineEdit, SIGNAL(editingFinished()), SLOT(checkIsValid()));
305  connect(m_ui->aRadiusLineEdit, SIGNAL(textChanged(QString)), SLOT(on_aRadiusLineEdit_textChanged(QString)));
306  }
307 
308 
309 
310  JigsawSetupDialog::~JigsawSetupDialog() {
311  // delete/null m_ui since we did "new" this pointers in the constructor
312  if (m_ui) {
313  delete m_ui;
314  }
315  m_ui = NULL;
316  // do not delete/null m_project since we didn't "new" this pointer
317  }
318 
319 
320  void JigsawSetupDialog::on_pointRadiusSigmaCheckBox_toggled(bool checked) {
321  m_ui->pointRadiusSigmaLineEdit->setEnabled(checked);
322  }
323 
324 // m_ui->positionComboBox has been removed from the general tab, it is planned to be moved to
325 // the obs solve settings tab. This function will be commented out until it is added back.
326 // void JigsawSetupDialog::on_positionComboBox_currentIndexChanged(int index) {
327 
328 // // indices:
329 // // 0 = none, 1 = position, 2 = velocity, 3 = acceleration, 4 = all
330 // bool solvePosition = (bool) (index > 0);
331 // bool solveVelocity = (bool) (index > 1);
332 // bool solveAcceleration = (bool) (index > 2);
333 // // bool solveAllPolynomialCoefficients = (bool) (index > 3);
334 
335 // m_ui->hermiteSplineCheckBox->setEnabled(solvePosition);
336 // m_ui->positionSigmaLabel->setEnabled(solvePosition);
337 // m_ui->positionSigmaLineEdit->setEnabled(solvePosition);
338 // m_ui->positionSigmaUnitsLabel->setEnabled(solvePosition);
339 
340 // m_ui->velocitySigmaLabel->setEnabled(solveVelocity);
341 // m_ui->velocitySigmaLineEdit->setEnabled(solveVelocity);
342 // m_ui->velocitySigmaUnitsLabel->setEnabled(solveVelocity);
343 
344 // m_ui->accelerationSigmaLabel->setEnabled(solveAcceleration);
345 // m_ui->accelerationSigmaLineEdit->setEnabled(solveAcceleration);
346 // m_ui->accelerationSigmaUnitsLabel->setEnabled(solveAcceleration);
347 
348 // // m_ui->spkDegreeLabel->setEnabled(solveAllPolynomialCoefficients);
349 // // m_ui->spkDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients);
350 // // m_ui->spkSolveDegreeLabel->setEnabled(solveAllPolynomialCoefficients);
351 // // m_ui->spkSolveDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients);
352 
353 // }
354 
355 // m_ui->pointingComboBox has been removed from the general tab, it is planned to be moved to
356 // the obs solve settings tab. This function will be commented out until it is added back.
357 // void JigsawSetupDialog::on_pointingComboBox_currentIndexChanged(int index) {
358 
359 // // indices:
360 // // 0 = angles, 1 = none, 2 = velocity, 3 = acceleration, 4 = all
361 // bool solveAngles = (bool) (index == 0 || index > 1);
362 // bool solveAngularVelocity = (bool) (index > 1);
363 // bool solveAngularAcceleration = (bool) (index > 2);
364 // // bool solveAllPolynomialCoefficients = (bool) (index > 3);
365 
366 // m_ui->twistCheckBox->setEnabled(solveAngles);
367 // m_ui->fitOverPointingCheckBox->setEnabled(solveAngles);
368 
369 // // m_ui->ckDegreeLabel->setEnabled(solveAllPolynomialCoefficients);
370 // // m_ui->ckDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients);
371 // // m_ui->ckSolveDegreeSpinBox->setEnabled(solveAllPolynomialCoefficients);
372 // // m_ui->ckSolveDegreeLabel->setEnabled(solveAllPolynomialCoefficients);
373 
374 // m_ui->pointingAnglesSigmaLabel->setEnabled(solveAngles);
375 // m_ui->pointingAnglesSigmaLineEdit->setEnabled(solveAngles);
376 // m_ui->pointingAnglesSigmaUnitsLabel->setEnabled(solveAngles);
377 
378 // m_ui->pointingAngularVelocitySigmaLabel->setEnabled(solveAngularVelocity);
379 // m_ui->pointingAngularVelocitySigmaLineEdit->setEnabled(solveAngularVelocity);
380 // m_ui->pointingAngularVelocitySigmaUnitsLabel->setEnabled(solveAngularVelocity);
381 
382 // m_ui->pointingAngularAccelerationSigmaLabel->setEnabled(solveAngularAcceleration);
383 // m_ui->pointingAngularAccelerationSigmaLineEdit->setEnabled(solveAngularAcceleration);
384 // m_ui->pointingAngularAccelerationSigmaUnitsLabel->setEnabled(solveAngularAcceleration);
385 
386 // }
387 
388 
389  void JigsawSetupDialog::on_maximumLikelihoodModel1ComboBox_currentIndexChanged(int index) {
390 
391  bool model1Selected = (bool) (index > 0);
392 
393  // lock/unlock current tier's quantile and next tier's model
394  m_ui->maximumLikelihoodModel1QuantileLineEdit->setEnabled(model1Selected);
395  m_ui->maximumLikelihoodModel2Label->setEnabled(model1Selected);
396  m_ui->maximumLikelihoodModel2ComboBox->setEnabled(model1Selected);
397  m_ui->maximumLikelihoodModel2QuantileLineEdit->setEnabled(
398  m_ui->maximumLikelihoodModel2ComboBox->currentIndex());
399 
400  // when setting "NONE", set remaining max likelihood options to false
401  if (!model1Selected) {
402  m_ui->maximumLikelihoodModel2QuantileLineEdit->setEnabled(false);
403  m_ui->maximumLikelihoodModel3QuantileLineEdit->setEnabled(false);
404  m_ui->maximumLikelihoodModel3Label->setEnabled(false);
405  m_ui->maximumLikelihoodModel3ComboBox->setEnabled(false);
406  }
407 
408  on_maximumLikelihoodModel1QuantileLineEdit_textChanged("");
409  on_maximumLikelihoodModel2QuantileLineEdit_textChanged("");
410  on_maximumLikelihoodModel3QuantileLineEdit_textChanged("");
411 
412  // sigma and max likelihood options are exclusive
413  m_ui->outlierRejectionCheckBox->setEnabled(!model1Selected);
414  }
415 
416 
417  void JigsawSetupDialog::on_maximumLikelihoodModel2ComboBox_currentIndexChanged(int index) {
418 
419  bool model2Selected = (bool)(index > 0);
420 
421  // lock/unlock current tier's quantile and next tier's model
422  m_ui->maximumLikelihoodModel2QuantileLineEdit->setEnabled(model2Selected);
423  m_ui->maximumLikelihoodModel3Label->setEnabled(model2Selected);
424  m_ui->maximumLikelihoodModel3ComboBox->setEnabled(model2Selected);
425  m_ui->maximumLikelihoodModel3QuantileLineEdit->setEnabled(
426  m_ui->maximumLikelihoodModel3ComboBox->currentIndex());
427 
428  // when setting "NONE", set remaining max likelihood options to false
429  if (!model2Selected) {
430  m_ui->maximumLikelihoodModel3QuantileLineEdit->setEnabled(false);
431  }
432 
433  on_maximumLikelihoodModel2QuantileLineEdit_textChanged("");
434  on_maximumLikelihoodModel3QuantileLineEdit_textChanged("");
435  }
436 
437 
438  void JigsawSetupDialog::on_maximumLikelihoodModel3ComboBox_currentIndexChanged(int index) {
439 
440  bool model3Selected = (bool)(index > 0);
441 
442  m_ui->maximumLikelihoodModel3QuantileLineEdit->setEnabled(model3Selected);
443  on_maximumLikelihoodModel3QuantileLineEdit_textChanged("");
444 
445  }
446 
447 
448  void JigsawSetupDialog::on_outlierRejectionCheckBox_stateChanged(int arg1) {
449 
450  on_outlierRejectionMultiplierLineEdit_textChanged("");
451  m_ui->outlierRejectionMultiplierLineEdit->setEnabled(arg1);
452 
453  // sigma and maxlikelihood options are exclusive
454  m_ui->CQuantileLabel->setEnabled(!arg1);
455  m_ui->maxLikelihoodEstimationLabel->setEnabled(!arg1);
456  m_ui->maximumLikelihoodModel1ComboBox->setEnabled(!arg1);
457  m_ui->maximumLikelihoodModel1Label->setEnabled(!arg1);
458  }
459 
460 
461  void JigsawSetupDialog::fillFromSettings(const BundleSettingsQsp settings) {
462 
463  // general tab
464  m_ui->observationModeCheckBox->setChecked(settings->solveObservationMode());
465  m_ui->pointRadiusSigmaCheckBox->setChecked(settings->solveRadius());
466  // m_ui->updateCubeLabelCheckBox->setChecked(settings->updateCubeLabel());
467  m_ui->errorPropagationCheckBox->setChecked(settings->errorPropagation());
468  m_ui->outlierRejectionCheckBox->setChecked(settings->outlierRejection());
469  m_ui->outlierRejectionMultiplierLineEdit->setText(toString(settings->outlierRejectionMultiplier()));
470  m_ui->sigma0ThresholdLineEdit->setText(toString(settings->convergenceCriteriaThreshold()));
471  m_ui->maximumIterationsLineEdit->setText(toString(settings->convergenceCriteriaMaximumIterations()));
472 
473  // weighting tab
474  if ( !IsNullPixel(settings->globalPointCoord1AprioriSigma()) ) {
475  m_ui->pointLatitudeSigmaLineEdit->setText(toString(settings->globalPointCoord1AprioriSigma()));
476  m_ui->pointLatitudeSigmaLineEdit->setModified(true);
477  }
478  if ( !IsNullPixel(settings->globalPointCoord2AprioriSigma()) ) {
479  m_ui->pointLongitudeSigmaLineEdit->setText(toString(settings->globalPointCoord2AprioriSigma()));
480  m_ui->pointLongitudeSigmaLineEdit->setModified(true);
481  }
482  if ( !IsNullPixel(settings->globalPointCoord3AprioriSigma()) ) {
483  m_ui->pointRadiusSigmaLineEdit->setText(toString(settings->globalPointCoord3AprioriSigma()));
484  m_ui->pointRadiusSigmaLineEdit->setModified(true);
485 
486  }
487 
488  // If we click setup after changing image selection in the project tree, not all images will
489  // have solve settings. Here we add those images and their default settings to the list
490  QList<BundleObservationSolveSettings> defaultSettings = m_bundleSettings->observationSolveSettings();
491  QList<BundleObservationSolveSettings> fillSettings = settings->observationSolveSettings();
492 
493  for (auto &solveSettings : defaultSettings) {
494  // Remove any images from defaultSettings that exist in fillSettings
495  foreach (QString observationNumber, solveSettings.observationNumbers()) {
496  // The method will return a default with no obs numbers if none are found
497  if (!settings->observationSolveSettings(observationNumber).observationNumbers().isEmpty()) {
498  solveSettings.removeObservationNumber(observationNumber);
499  }
500  }
501  // Append leftover defaultSettings
502  if (!solveSettings.observationNumbers().isEmpty()) {
503  fillSettings.append(solveSettings);
504  }
505  }
506 
507  m_bundleSettings->setObservationSolveOptions(fillSettings);
508 
509  update();
510 
511  }
512 
513 
514  BundleSettingsQsp JigsawSetupDialog::bundleSettings() {
515 
517  settings->setValidateNetwork(true);
518 
519  // solve options
520  double latitudeSigma = -1.0;
521  double longitudeSigma = -1.0;
522  double radiusSigma = -1.0;
523  if (m_ui->pointLatitudeSigmaLineEdit->isModified()) {
524  latitudeSigma = m_ui->pointLatitudeSigmaLineEdit->text().toDouble();
525  }
526  if (m_ui->pointLongitudeSigmaLineEdit->isModified()) {
527  longitudeSigma = m_ui->pointLongitudeSigmaLineEdit->text().toDouble();
528  }
529  if (m_ui->pointRadiusSigmaLineEdit->isModified()) {
530  radiusSigma = m_ui->pointRadiusSigmaLineEdit->text().toDouble();
531  }
532  // Stick with the default coordinate types for the bundle and reports until
533  // a gui is added to get the settings
534  settings->setSolveOptions(m_ui->observationModeCheckBox->isChecked(),
535  false,
536  // m_ui->updateCubeLabelCheckBox->isChecked(),
537  m_ui->errorPropagationCheckBox->isChecked(),
538  m_ui->pointRadiusSigmaCheckBox->isChecked(),
540  latitudeSigma,
541  longitudeSigma,
542  radiusSigma);
543  settings->setOutlierRejection(m_ui->outlierRejectionCheckBox->isChecked(),
544  m_ui->outlierRejectionMultiplierLineEdit->text().toDouble());
545 
546  // convergence criteria
547  settings->setConvergenceCriteria(BundleSettings::Sigma0,
548  m_ui->sigma0ThresholdLineEdit->text().toDouble(),
549  m_ui->maximumIterationsLineEdit->text().toInt()); // TODO: change this to give user a choice between sigma0 and param corrections???
550 
551  // max likelihood estimation
552  if (m_ui->maximumLikelihoodModel1ComboBox->currentText().compare("NONE") != 0) {
553  // if model1 is not "NONE", add to the models list with its quantile
554  settings->addMaximumLikelihoodEstimatorModel(
555  MaximumLikelihoodWFunctions::stringToModel(
556  m_ui->maximumLikelihoodModel1ComboBox->currentText()),
557  m_ui->maximumLikelihoodModel1QuantileLineEdit->text().toDouble());
558 
559  if (m_ui->maximumLikelihoodModel2ComboBox->currentText().compare("NONE") != 0) {
560  // if model2 is not "NONE", add to the models list with its quantile
561  settings->addMaximumLikelihoodEstimatorModel(
562  MaximumLikelihoodWFunctions::stringToModel(
563  m_ui->maximumLikelihoodModel2ComboBox->currentText()),
564  m_ui->maximumLikelihoodModel2QuantileLineEdit->text().toDouble());
565 
566  if (m_ui->maximumLikelihoodModel3ComboBox->currentText().compare("NONE") != 0) {
567  // if model3 is not "NONE", add to the models list with its quantile
568  settings->addMaximumLikelihoodEstimatorModel(
569  MaximumLikelihoodWFunctions::stringToModel(
570  m_ui->maximumLikelihoodModel3ComboBox->currentText()),
571  m_ui->maximumLikelihoodModel3QuantileLineEdit->text().toDouble());
572  }
573  }
574  }
575  // target body
576  // ensure user entered something to adjust
577  if (m_ui->poleRaCheckBox->isChecked() ||
578  m_ui->poleRaVelocityCheckBox->isChecked() ||
579  m_ui->poleDecCheckBox->isChecked() ||
580  m_ui->poleDecVelocityCheckBox->isChecked() ||
581  m_ui->primeMeridianOffsetCheckBox->isChecked() ||
582  m_ui->spinRateCheckBox->isChecked() ||
583  !m_ui->noneRadiiRadioButton->isChecked()) {
584 
585  // create BundleTargetBody utility object
587 
588  int radiiOption = 0;
589  if (m_ui->meanRadiusRadioButton->isChecked())
590  radiiOption = 1;
591  else if (m_ui->triaxialRadiiRadioButton->isChecked())
592  radiiOption = 2;
593 
594  std::set<int> targetParameterSolveCodes;
595  if (m_ui->poleRaCheckBox->isChecked())
596  targetParameterSolveCodes.insert(BundleTargetBody::PoleRA);
597  if (m_ui->poleRaVelocityCheckBox->isChecked())
598  targetParameterSolveCodes.insert(BundleTargetBody::VelocityPoleRA);
599  if (m_ui->poleDecCheckBox->isChecked())
600  targetParameterSolveCodes.insert(BundleTargetBody::PoleDec);
601  if (m_ui->poleDecVelocityCheckBox->isChecked())
602  targetParameterSolveCodes.insert(BundleTargetBody::VelocityPoleDec);
603  if (m_ui->primeMeridianOffsetCheckBox->isChecked())
604  targetParameterSolveCodes.insert(BundleTargetBody::PM);
605  if (m_ui->spinRateCheckBox->isChecked())
606  targetParameterSolveCodes.insert(BundleTargetBody::VelocityPM);
607  if (m_ui->triaxialRadiiRadioButton->isChecked()) {
608  targetParameterSolveCodes.insert(BundleTargetBody::TriaxialRadiusA);
609  targetParameterSolveCodes.insert(BundleTargetBody::TriaxialRadiusB);
610  targetParameterSolveCodes.insert(BundleTargetBody::TriaxialRadiusC);
611  }
612  else if (m_ui->meanRadiusRadioButton->isChecked())
613  targetParameterSolveCodes.insert(BundleTargetBody::MeanRadius);
614 
615  double poleRASigma = -1.0;
616  double poleRAVelocitySigma = -1.0;
617 // double poleRAAccelerationSigma = -1.0;
618  double poleDecSigma = -1.0;
619  double poleDecVelocitySigma = -1.0;
620 // double poleDecAccelerationSigma = -1.0;
621  double pmSigma = -1.0;
622  double pmVelocitySigma = -1.0;
623 // double pmAccelerationSigma = -1.0;
624  double aRadiusSigma = 0.0;
625  double bRadiusSigma = 0.0;
626  double cRadiusSigma = 0.0;
627  double meanRadiusSigma = 0.0;
628 
629  if (m_ui->rightAscensionSigmaLineEdit->isModified())
630  poleRASigma = m_ui->rightAscensionSigmaLineEdit->text().toDouble();
631  if (m_ui->rightAscensionVelocityLineEdit->isModified())
632  poleRAVelocitySigma = m_ui->rightAscensionVelocityLineEdit->text().toDouble();
633 // if (m_ui->rightAscensionAccelerationLineEdit->isModified())
634 // poleRAAccelerationSigma = m_ui->rightAscensionAccelerationLineEdit->text().toDouble();
635  if (m_ui->declinationSigmaLineEdit->isModified())
636  poleDecSigma = m_ui->declinationSigmaLineEdit->text().toDouble();
637  if (m_ui->declinationVelocitySigmaLineEdit->isModified())
638  poleDecVelocitySigma = m_ui->declinationVelocitySigmaLineEdit->text().toDouble();
639 // if (m_ui->declinationAccelerationSigmaLineEdit->isModified())
640 // poleDecAccelerationSigma = m_ui->declinationAccelerationSigmaLineEdit->text().toDouble();
641  if (m_ui->primeMeridianOffsetSigmaLineEdit->isModified())
642  pmSigma = m_ui->primeMeridianOffsetSigmaLineEdit->text().toDouble();
643  if (m_ui->spinRateSigmaLineEdit->isModified())
644  pmVelocitySigma = m_ui->spinRateSigmaLineEdit->text().toDouble();
645 // if (m_ui->pmAccelerationSigmaLineEdit->isModified())
646 // pmAccelerationSigma = m_ui->pmAccelerationSigmaLineEdit->text().toDouble();
647  if (m_ui->aRadiusSigmaLineEdit->isModified())
648  aRadiusSigma = m_ui->aRadiusSigmaLineEdit->text().toDouble();
649  if (m_ui->bRadiusSigmaLineEdit->isModified())
650  bRadiusSigma = m_ui->bRadiusSigmaLineEdit->text().toDouble();
651  if (m_ui->cRadiusSigmaLineEdit->isModified())
652  cRadiusSigma = m_ui->cRadiusSigmaLineEdit->text().toDouble();
653  if (m_ui->meanRadiusSigmaLineEdit->isModified())
654  meanRadiusSigma = m_ui->meanRadiusSigmaLineEdit->text().toDouble();
655 
656  bundleTargetBody->setSolveSettings(targetParameterSolveCodes,
657  Angle(m_ui->rightAscensionLineEdit->text().toDouble(), Angle::Degrees),
658  Angle(poleRASigma, Angle::Degrees),
659  Angle(m_ui->rightAscensionVelocityLineEdit->text().toDouble(), Angle::Degrees),
660  Angle(poleRAVelocitySigma, Angle::Degrees),
661  Angle(m_ui->declinationLineEdit->text().toDouble(), Angle::Degrees),
662  Angle(poleDecSigma, Angle::Degrees),
663  Angle(m_ui->declinationVelocityLineEdit->text().toDouble(), Angle::Degrees),
664  Angle(poleDecVelocitySigma, Angle::Degrees),
665  Angle(m_ui->primeMeridianOffsetLineEdit->text().toDouble(), Angle::Degrees),
666  Angle(pmSigma, Angle::Degrees),
667  Angle(m_ui->spinRateLineEdit->text().toDouble(), Angle::Degrees),
668  Angle(pmVelocitySigma, Angle::Degrees),
670  Distance(m_ui->aRadiusLineEdit->text().toDouble(), Distance::Kilometers),
671  Distance(aRadiusSigma, Distance::Meters),
672  Distance(m_ui->bRadiusLineEdit->text().toDouble(), Distance::Kilometers),
673  Distance(bRadiusSigma, Distance::Meters),
674  Distance(m_ui->cRadiusLineEdit->text().toDouble(), Distance::Kilometers),
675  Distance(cRadiusSigma, Distance::Meters),
676  Distance(m_ui->meanRadiusLineEdit->text().toDouble(), Distance::Kilometers),
677  Distance(meanRadiusSigma, Distance::Meters));
678 
679  settings->setBundleTargetBody(bundleTargetBody);
680  }
681  return settings;
682  }
683 
684 
692  fillFromSettings(settings);
693  }
694 
695 
705  void JigsawSetupDialog::selectControl(const QString &controlName) {
706  QComboBox &cnetBox = *(m_ui->inputControlNetCombo);
707  int foundControlIndex = cnetBox.findText(FileName(controlName).name());
708  // We did not find it, so we need to see if the combo box is empty or not.
709  if (foundControlIndex == -1) {
710  if (cnetBox.count() == 0) {
711  cnetBox.setCurrentIndex(-1);
712  }
713  // If it is not empty, just set the current index to the first item.
714  else {
715  cnetBox.setCurrentIndex(0);
716  }
717  }
718  // Otherwise, set the current index to the found control net index.
719  else {
720  cnetBox.setCurrentIndex(foundControlIndex);
721  }
722  }
723 
724 
725  Control *JigsawSetupDialog::selectedControl() {
726 
727  int nIndex = m_ui->inputControlNetCombo->currentIndex();
728  Control *selectedControl
729  = (Control *)(m_ui->inputControlNetCombo->itemData(nIndex).value< void * >());
730  return selectedControl;
731 
732  }
733 
734 
735  QString JigsawSetupDialog::selectedControlName() {
736  return QString(m_ui->inputControlNetCombo->currentText());
737  }
738 
739 
740 
750  {
751 
752  int ckSolveDegree = m_ui->ckSolveDegreeSpinBox->value();
753  int spkSolveDegree = m_ui->spkSolveDegreeSpinBox->value();
754  int ckDegree = m_ui->ckDegreeSpinBox->value();
755  int spkDegree = m_ui->spkDegreeSpinBox->value();
756  int instrumentPointingSolveOption=m_ui->pointingComboBox->currentIndex();
757  int instrumentPositionSolveOption=m_ui->positionComboBox->currentIndex();
758 
761 
762  double anglesAprioriSigma(-1.0);
763  double angularVelocityAprioriSigma(-1.0);
764  double angularAccelerationAprioriSigma(-1.0);
765  QList<double> additionalAngularCoefficients;
766 
767  double positionAprioriSigma(-1.0);
768  double velocityAprioriSigma(-1.0);
769  double accelerationAprioriSigma(-1.0);
770  QList<double> additionalPositionCoefficients;
771 
772  bool solveTwist(false);
773  bool solvePolynomialOverExisting(false);
774  bool positionOverHermite(false);
775 
776  if (m_ui->pointingAprioriSigmaTable->item(0,3))
777  anglesAprioriSigma = m_ui->pointingAprioriSigmaTable->item(0,3)->data(0).toDouble();
778 
779  if (m_ui->pointingAprioriSigmaTable->item(1,3))
780  angularVelocityAprioriSigma = m_ui->pointingAprioriSigmaTable->item(1,3)->data(0).toDouble();
781 
782  if (m_ui->pointingAprioriSigmaTable->item(2,3) )
783  angularAccelerationAprioriSigma = m_ui->pointingAprioriSigmaTable->item(2,3)->data(0).toDouble();
784 
785  if (m_ui->positionAprioriSigmaTable->item(0,3))
786  positionAprioriSigma = m_ui->positionAprioriSigmaTable->item(0,3)->data(0).toDouble();
787 
788  if (m_ui->positionAprioriSigmaTable->item(1,3))
789  velocityAprioriSigma = m_ui->positionAprioriSigmaTable->item(1,3)->data(0).toDouble();
790 
791  if (m_ui->positionAprioriSigmaTable->item(2,3) )
792  accelerationAprioriSigma = m_ui->positionAprioriSigmaTable->item(2,3)->data(0).toDouble();
793 
794  //Saving additionalPositional/Angular coefficients (deg >=3) in case they are needed
795  //later.
796  if (spkSolveDegree >2) {
797  for (int i = 3;i <= spkSolveDegree;i++ ) {
798  if (m_ui->positionAprioriSigmaTable->item(i,3))
799  additionalPositionCoefficients.append(m_ui->positionAprioriSigmaTable->item(i,3)->data(0).toDouble() );
800  }
801  }
802 
803  if (ckSolveDegree > 2) {
804  for (int i = 3;i <= ckSolveDegree;i++ ) {
805  if (m_ui->pointingAprioriSigmaTable->item(i,3))
806  additionalAngularCoefficients.append(m_ui->pointingAprioriSigmaTable->item(i,3)->data(0).toDouble() );
807  }
808 
809  }
810 
811 
812  if (m_ui->twistCheckBox->checkState() == Qt::Checked)
813  solveTwist = true;
814  if (m_ui->fitOverPointingCheckBox->checkState() == Qt::Checked)
815  solvePolynomialOverExisting = true;
816  if (m_ui->hermiteSplineCheckBox->checkState() == Qt::Checked)
817  positionOverHermite = true;
818 
819  switch(instrumentPointingSolveOption) {
820 
821  case 0: pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::NoPointingFactors;
822  break;
823  case 1:pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::AnglesOnly;
824  break;
825  case 2:pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::AnglesVelocity;
826  break;
827  case 3:pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::AnglesVelocityAcceleration;
828  break;
829 
830  case 4:pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::AllPointingCoefficients;
831  break;
832  default: pointSolvingOption = BundleObservationSolveSettings::InstrumentPointingSolveOption::NoPointingFactors;
833  break;
834 
835  }
836 
837  switch(instrumentPositionSolveOption) {
838 
839  case 0: positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::NoPositionFactors;
840  break;
841  case 1:positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::PositionOnly;
842  break;
843  case 2:positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::PositionVelocity;
844  break;
845  case 3:positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::PositionVelocityAcceleration;
846  break;
847 
848  case 4:positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::AllPositionCoefficients;
849  break;
850  default: positionSolvingOption = BundleObservationSolveSettings::InstrumentPositionSolveOption::NoPositionFactors;
851  break;
852 
853  }
854 
855 
856  boss.setInstrumentPositionSettings(positionSolvingOption,spkDegree,spkSolveDegree,positionOverHermite,
857  positionAprioriSigma,velocityAprioriSigma,accelerationAprioriSigma,
858  &additionalPositionCoefficients);
859 
860  boss.setInstrumentPointingSettings(pointSolvingOption,solveTwist,ckDegree,ckSolveDegree,solvePolynomialOverExisting,
861  anglesAprioriSigma,angularVelocityAprioriSigma,angularAccelerationAprioriSigma,
862  &additionalAngularCoefficients);
863 
864  //What if multiple instrument IDs are represented?
865  boss.setInstrumentId("");
866 
867 
868  SortFilterProxyModel* proxyModel = (SortFilterProxyModel *)m_ui->treeView->model();
869  ProjectItemModel* sourceModel = (ProjectItemModel *)proxyModel->sourceModel();
870  QModelIndexList selectedIndexes = m_ui->treeView->selectionModel()->selectedIndexes();
871 
872  foreach (QModelIndex index, selectedIndexes) {
873 
874  QModelIndex sourceix = proxyModel->mapToSource(index);
875  ProjectItem * projItem = sourceModel->itemFromIndex(sourceix);
876 
877  if (projItem) {
878 
879  if (projItem->isImage() ) {
880  Image * img = projItem->data().value<Image *>();
882 
883  }
884  }
885 
886  }
887 
888  }
889 
890 
891  QString JigsawSetupDialog::outputControlName() {
892  return QString(m_ui->outputControlNetLineEdit->text());
893  }
894 
895 
896  void JigsawSetupDialog::makeReadOnly() {
897  m_ui->inputControlNetCombo->setEnabled(false);
898  m_ui->observationModeCheckBox->setEnabled(false);
899  m_ui->pointRadiusSigmaCheckBox->setEnabled(false);
900  // m_ui->updateCubeLabelCheckBox->setEnabled(false);
901  m_ui->errorPropagationCheckBox->setEnabled(false);
902  m_ui->outlierRejectionCheckBox->setEnabled(false);
903  m_ui->outlierRejectionMultiplierLineEdit->setEnabled(false);
904  m_ui->sigma0ThresholdLineEdit->setEnabled(false);
905  m_ui->maximumIterationsLineEdit->setEnabled(false);
906  // m_ui->positionComboBox->setEnabled(false);
907  m_ui->hermiteSplineCheckBox->setEnabled(false);
908  m_ui->spkDegreeSpinBox->setEnabled(false);
909  m_ui->spkSolveDegreeSpinBox->setEnabled(false);
910  m_ui->twistCheckBox->setEnabled(false);
911  // m_ui->pointingComboBox->setEnabled(false);
912  m_ui->fitOverPointingCheckBox->setEnabled(false);
913  m_ui->ckDegreeSpinBox->setEnabled(false);
914  m_ui->ckSolveDegreeSpinBox->setEnabled(false);
915 
916  // observation solve settings tab
917  m_ui->treeView->setEnabled(false);
918  m_ui->positionComboBox->setEnabled(false);
919  m_ui->spkSolveDegreeSpinBox->setEnabled(false);
920  m_ui->spkDegreeSpinBox->setEnabled(false);
921  m_ui->hermiteSplineCheckBox->setEnabled(false);
922  m_ui->positionAprioriSigmaTable->setEnabled(false);
923  m_ui->pointingComboBox->setEnabled(false);
924  m_ui->ckSolveDegreeSpinBox->setEnabled(false);
925  m_ui->ckDegreeSpinBox->setEnabled(false);
926  m_ui->twistCheckBox->setEnabled(false);
927  m_ui->fitOverPointingCheckBox->setEnabled(false);
928  m_ui->pointingAprioriSigmaTable->setEnabled(false);
929  m_ui->applySettingsPushButton->setEnabled(false);
930 
931  // target body tab
932  m_ui->targetBodyComboBox->setEnabled(false);
933  m_ui->poleRaCheckBox->setEnabled(false);
934  m_ui->rightAscensionLineEdit->setEnabled(false);
935  m_ui->rightAscensionSigmaLineEdit->setEnabled(false);
936  m_ui->rightAscensionVelocityLineEdit->setEnabled(false);
937  m_ui->rightAscensionVelocitySigmaLineEdit->setEnabled(false);
938  m_ui->poleDecCheckBox->setEnabled(false);
939  m_ui->declinationLineEdit->setEnabled(false);
940  m_ui->declinationSigmaLineEdit->setEnabled(false);
941  m_ui->declinationVelocityLineEdit->setEnabled(false);
942  m_ui->declinationVelocitySigmaLineEdit->setEnabled(false);
943  m_ui->primeMeridianOffsetCheckBox->setEnabled(false);
944  m_ui->primeMeridianOffsetLineEdit->setEnabled(false);
945  m_ui->primeMeridianOffsetSigmaLineEdit->setEnabled(false);
946  m_ui->spinRateCheckBox->setEnabled(false);
947  m_ui->spinRateLineEdit->setEnabled(false);
948  m_ui->spinRateSigmaLineEdit->setEnabled(false);
949  m_ui->radiiGroupBox->setEnabled(false);
950  m_ui->aRadiusLineEdit->setEnabled(false);
951  m_ui->aRadiusSigmaLineEdit->setEnabled(false);
952  m_ui->bRadiusLineEdit->setEnabled(false);
953  m_ui->bRadiusSigmaLineEdit->setEnabled(false);
954  m_ui->cRadiusLineEdit->setEnabled(false);
955  m_ui->cRadiusSigmaLineEdit->setEnabled(false);
956  m_ui->meanRadiusLineEdit->setEnabled(false);
957  m_ui->meanRadiusSigmaLineEdit->setEnabled(false);
958 
959  update();
960  }
961 
962 
963  void Isis::JigsawSetupDialog::on_poleRaCheckBox_stateChanged(int arg1) {
964  if (arg1) {
965  m_ui->rightAscensionLineEdit->setEnabled(true);
966  m_ui->rightAscensionSigmaLineEdit->setEnabled(true);
967  }
968  else {
969  m_ui->rightAscensionLineEdit->setEnabled(false);
970  m_ui->rightAscensionSigmaLineEdit->setEnabled(false);
971  }
972 
973  update();
974  }
975 
976 
977  void Isis::JigsawSetupDialog::on_poleRaVelocityCheckBox_stateChanged(int arg1) {
978  if (arg1) {
979  m_ui->rightAscensionVelocityLineEdit->setEnabled(true);
980  m_ui->rightAscensionVelocitySigmaLineEdit->setEnabled(true);
981  }
982  else {
983  m_ui->rightAscensionVelocityLineEdit->setEnabled(false);
984  m_ui->rightAscensionVelocitySigmaLineEdit->setEnabled(false);
985  }
986 
987  update();
988  }
989 
990 
991  void Isis::JigsawSetupDialog::on_poleDecCheckBox_stateChanged(int arg1) {
992  if (arg1) {
993  m_ui->declinationLineEdit->setEnabled(true);
994  m_ui->declinationSigmaLineEdit->setEnabled(true);
995  }
996  else {
997  m_ui->declinationLineEdit->setEnabled(false);
998  m_ui->declinationSigmaLineEdit->setEnabled(false);
999  }
1000 
1001  update();
1002  }
1003 
1004 
1005  void Isis::JigsawSetupDialog::on_poleDecVelocityCheckBox_stateChanged(int arg1) {
1006  if (arg1) {
1007  m_ui->declinationVelocityLineEdit->setEnabled(true);
1008  m_ui->declinationVelocitySigmaLineEdit->setEnabled(true);
1009  }
1010  else {
1011  m_ui->declinationVelocityLineEdit->setEnabled(false);
1012  m_ui->declinationVelocitySigmaLineEdit->setEnabled(false);
1013  }
1014 
1015  update();
1016  }
1017 
1018 
1019  void Isis::JigsawSetupDialog::on_spinRateCheckBox_stateChanged(int arg1) {
1020  if (arg1) {
1021  m_ui->spinRateLineEdit->setEnabled(true);
1022  m_ui->spinRateSigmaLineEdit->setEnabled(true);
1023  }
1024  else {
1025  m_ui->spinRateLineEdit->setEnabled(false);
1026  m_ui->spinRateSigmaLineEdit->setEnabled(false);
1027  }
1028 
1029  update();
1030  }
1031 
1032 
1033  void Isis::JigsawSetupDialog::on_primeMeridianOffsetCheckBox_stateChanged(int arg1) {
1034  if (arg1) {
1035  m_ui->primeMeridianOffsetLineEdit->setEnabled(true);
1036  m_ui->primeMeridianOffsetSigmaLineEdit->setEnabled(true);
1037  }
1038  else {
1039  m_ui->primeMeridianOffsetLineEdit->setEnabled(false);
1040  m_ui->primeMeridianOffsetSigmaLineEdit->setEnabled(false);
1041  }
1042 
1043  update();
1044  }
1045 
1046 
1047  void Isis::JigsawSetupDialog::on_radiiButtonGroupClicked(int arg1) {
1048 
1049  if (arg1 == 0) {
1050  m_ui->aRadiusLabel->setEnabled(false);
1051  m_ui->aRadiusLineEdit->setEnabled(false);
1052  m_ui->aRadiusSigmaLineEdit->setEnabled(false);
1053  m_ui->bRadiusLabel->setEnabled(false);
1054  m_ui->bRadiusLineEdit->setEnabled(false);
1055  m_ui->bRadiusSigmaLineEdit->setEnabled(false);
1056  m_ui->cRadiusLabel->setEnabled(false);
1057  m_ui->cRadiusLineEdit->setEnabled(false);
1058  m_ui->cRadiusSigmaLineEdit->setEnabled(false);
1059  m_ui->meanRadiusLineEdit->setEnabled(false);
1060  m_ui->meanRadiusSigmaLineEdit->setEnabled(false);
1061 
1062  // if we're not solving for target body triaxial radii or mean radius, we CAN solve for point
1063  // radii so we ensure the point radius checkbox under the general settings tab is enabled
1064  m_ui->pointRadiusSigmaCheckBox->setEnabled(true);
1065  }
1066  else if (arg1 == 1) {
1067  m_ui->aRadiusLabel->setEnabled(true);
1068  m_ui->aRadiusLineEdit->setEnabled(true);
1069  m_ui->aRadiusSigmaLineEdit->setEnabled(true);
1070  m_ui->bRadiusLabel->setEnabled(true);
1071  m_ui->bRadiusLineEdit->setEnabled(true);
1072  m_ui->bRadiusSigmaLineEdit->setEnabled(true);
1073  m_ui->cRadiusLabel->setEnabled(true);
1074  m_ui->cRadiusLineEdit->setEnabled(true);
1075  m_ui->cRadiusSigmaLineEdit->setEnabled(true);
1076  m_ui->meanRadiusLineEdit->setEnabled(false);
1077  m_ui->meanRadiusSigmaLineEdit->setEnabled(false);
1078 
1079  // if we're solving for target body mean radius, we can't solve for point radii
1080  // so we uncheck and disable the point radius checkbox under the general settings tab
1081  // and remind the user
1082  m_ui->pointRadiusSigmaCheckBox->setChecked(false);
1083  m_ui->pointRadiusSigmaCheckBox->setEnabled(false);
1084 
1085  QMessageBox *msgBox = new QMessageBox(QMessageBox::Information, "Triaxial Radii Reminder!",
1086  "Individual point radii and target body triaxial radii can't be solved for"
1087  " simultaneously so we've unchecked and disabled the Radius checkbox under the"
1088  " General Settings tab.", QMessageBox::Ok, this);
1089  msgBox->exec();
1090  }
1091  else if (arg1 == 2) {
1092  m_ui->aRadiusLabel->setEnabled(false);
1093  m_ui->aRadiusLineEdit->setEnabled(false);
1094  m_ui->aRadiusSigmaLineEdit->setEnabled(false);
1095  m_ui->bRadiusLabel->setEnabled(false);
1096  m_ui->bRadiusLineEdit->setEnabled(false);
1097  m_ui->bRadiusSigmaLineEdit->setEnabled(false);
1098  m_ui->cRadiusLabel->setEnabled(false);
1099  m_ui->cRadiusLineEdit->setEnabled(false);
1100  m_ui->cRadiusSigmaLineEdit->setEnabled(false);
1101  m_ui->meanRadiusLineEdit->setEnabled(true);
1102  m_ui->meanRadiusSigmaLineEdit->setEnabled((true));
1103 
1104  // if we're solving for target body triaxial radii, we can't solve for point radii
1105  // so we uncheck and disable the point radius checkbox under the general settings tab
1106  // and remind the user
1107  m_ui->pointRadiusSigmaCheckBox->setChecked(false);
1108  m_ui->pointRadiusSigmaCheckBox->setEnabled(false);
1109 
1110  QMessageBox *msgBox = new QMessageBox(QMessageBox::Information, "Mean Radius Reminder!",
1111  "Individual point radii and target body mean radius can't be solved for"
1112  " simultaneously so we've unchecked and disabled the Radius checkbox under the"
1113  " General Settings tab.", QMessageBox::Ok, this);
1114  msgBox->exec();
1115  }
1116 
1117  update();
1118  }
1119 
1120 
1121  void Isis::JigsawSetupDialog::checkIsValid() {
1122  if (!m_ui->aRadiusSigmaLineEdit->hasAcceptableInput()) {
1123 // qDebug() << "invalid input";
1124  }
1125 
1126 
1127  }
1128 
1129 
1130  void Isis::JigsawSetupDialog::slotTextChanged(const QString &text) {
1131 // qDebug() << "Text change to" << text << "and value is valid ==" << m_ui->aRadiusSigmaLineEdit->hasAcceptableInput();
1132  }
1133 
1134 
1135  void Isis::JigsawSetupDialog::on_aRadiusLineEdit_textChanged(const QString &arg1) {
1136 // qDebug() << "Text change to" << arg1 << "and value is valid ==" << m_ui->aRadiusLineEdit->hasAcceptableInput();
1137  }
1138 
1139 
1140  void Isis::JigsawSetupDialog::on_targetBodyComboBox_currentIndexChanged(int index) {
1141 
1142  TargetBodyQsp target = m_project->targetBodies().at(index);
1143  if (target) {
1144  if (target->frameType() != Isis::SpiceRotation::BPC &&
1145  target->frameType() != Isis::SpiceRotation::UNKNOWN) {
1146  m_ui->targetParametersMessage->hide();
1147 
1148  std::vector<Angle> raCoefs = target->poleRaCoefs();
1149  std::vector<Angle> decCoefs = target->poleDecCoefs();
1150  std::vector<Angle> pmCoefs = target->pmCoefs();
1151 
1152  showTargetParametersGroupBox();
1153 
1154  m_ui->rightAscensionLineEdit->setText(toString(raCoefs[0].degrees()));
1155  m_ui->rightAscensionVelocityLineEdit->setText(toString(raCoefs[1].degrees()));
1156  m_ui->declinationLineEdit->setText(toString(decCoefs[0].degrees()));
1157  m_ui->declinationVelocityLineEdit->setText(toString(decCoefs[1].degrees()));
1158  m_ui->primeMeridianOffsetLineEdit->setText(toString(pmCoefs[0].degrees()));
1159  m_ui->spinRateLineEdit->setText(toString(pmCoefs[1].degrees()));
1160  }
1161  else {
1162  // Formulate message indicating why target parameters are disabled
1163  QString msg;
1164  if (target->displayProperties()->displayName() == "MOON") {
1165  msg = "Target body parameter cannot be solved for the Moon.";
1166  }
1167  else {
1168  msg = "The body frame type is unknown. If you want to solve the target body parameters, "
1169  "you must run spiceinit on the cubes.";
1170  }
1171  m_ui->targetParametersMessage->setText(msg);
1172  m_ui->targetParametersMessage->show();
1173  hideTargetParametersGroupBox();
1174  }
1175 
1176  m_ui->aRadiusLineEdit->setText(toString(target->radiusA().kilometers()));
1177  //m_ui->aRadiusSigmaLineEdit->setText(toString(target->sigmaRadiusA().kilometers()));
1178 
1179  m_ui->bRadiusLineEdit->setText(toString(target->radiusB().kilometers()));
1180  //m_ui->bRadiusSigmaLineEdit->setText(toString(target->sigmaRadiusB().kilometers()));
1181 
1182  m_ui->cRadiusLineEdit->setText(toString(target->radiusC().kilometers()));
1183  //m_ui->cRadiusSigmaLineEdit->setText(toString(target->sigmaRadiusC().kilometers()));
1184 
1185  m_ui->meanRadiusLineEdit->setText(toString(target->meanRadius().kilometers()));
1186  //m_ui->meanRadiusSigmaLineEdit->setText(toString(target->sigmaMeanRadius().kilometers()));
1187  }
1188  }
1189 
1190 
1191  void Isis::JigsawSetupDialog::on_rightAscensionLineEdit_textChanged(const QString &arg1) {
1192  if (!m_ui->rightAscensionLineEdit->hasAcceptableInput()) {
1193  m_ui->rightAscensionLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1194  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1195  }
1196  else {
1197  m_ui->rightAscensionLineEdit->setStyleSheet("QLineEdit { background-color: white }");
1198  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1199  }
1200  update();
1201  }
1202 
1203 
1204  void Isis::JigsawSetupDialog::on_declinationLineEdit_textChanged(const QString &arg1) {
1205  if (!m_ui->declinationLineEdit->hasAcceptableInput()) {
1206  m_ui->declinationLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1207  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1208  }
1209  else {
1210  m_ui->declinationLineEdit->setStyleSheet("QLineEdit { background-color: white }");
1211  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1212  }
1213  update();
1214  }
1215 
1216 
1217  void Isis::JigsawSetupDialog::on_rightAscensionVelocityLineEdit_textChanged(const QString &arg1) {
1218  if (!m_ui->rightAscensionVelocityLineEdit->hasAcceptableInput()) {
1219  m_ui->rightAscensionVelocityLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1220  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1221  }
1222  else {
1223  m_ui->rightAscensionVelocityLineEdit->setStyleSheet("QLineEdit { background-color: white }");
1224  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1225  }
1226  update();
1227  }
1228 
1229 
1230  void Isis::JigsawSetupDialog::on_declinationVelocityLineEdit_textChanged(const QString &arg1) {
1231  if (!m_ui->declinationVelocityLineEdit->hasAcceptableInput()) {
1232  m_ui->declinationVelocityLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1233  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1234  }
1235  else {
1236  m_ui->declinationVelocityLineEdit->setStyleSheet("QLineEdit { background-color: white }");
1237  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1238  }
1239  update();
1240  }
1241 
1242 
1243  void Isis::JigsawSetupDialog::on_primeMeridianOffsetLineEdit_textChanged(const QString &arg1) {
1244  if (!m_ui->primeMeridianOffsetLineEdit->hasAcceptableInput()) {
1245  m_ui->primeMeridianOffsetLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1246  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1247  }
1248  else {
1249  m_ui->primeMeridianOffsetLineEdit->setStyleSheet("QLineEdit { background-color: white }");
1250  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1251  }
1252  update();
1253  }
1254 
1255 
1256  void Isis::JigsawSetupDialog::on_spinRateLineEdit_textChanged(const QString &arg1) {
1257  if (!m_ui->spinRateLineEdit->hasAcceptableInput()) {
1258  m_ui->spinRateLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1259  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1260  }
1261  else {
1262  m_ui->spinRateLineEdit->setStyleSheet("QLineEdit { background-color: white }");
1263  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1264  }
1265  update();
1266  }
1267 
1268  // general tab text validation
1269  // global apriori point sigmas
1270  void Isis::JigsawSetupDialog::on_pointLatitudeSigmaLineEdit_textChanged(const QString &arg1) {
1271  if (arg1 == "" || m_ui->pointLatitudeSigmaLineEdit->hasAcceptableInput()) {
1272  m_ui->pointLatitudeSigmaLineEdit->setStyleSheet("QLineEdit { background-color: white }");
1273  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1274  }
1275  else {
1276  m_ui->pointLatitudeSigmaLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1277  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1278  }
1279  update();
1280  }
1281 
1282  void Isis::JigsawSetupDialog::on_pointLongitudeSigmaLineEdit_textChanged(const QString &arg1) {
1283  if (arg1 == "" || m_ui->pointLongitudeSigmaLineEdit->hasAcceptableInput()) {
1284  m_ui->pointLongitudeSigmaLineEdit->setStyleSheet("QLineEdit { background-color: white }");
1285  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1286  }
1287  else {
1288  m_ui->pointLongitudeSigmaLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1289  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1290  }
1291  update();
1292  }
1293 
1294 
1295  void Isis::JigsawSetupDialog::on_pointRadiusSigmaLineEdit_textChanged(const QString &arg1) {
1296  if (arg1 == "" || m_ui->pointRadiusSigmaLineEdit->hasAcceptableInput()) {
1297  m_ui->pointRadiusSigmaLineEdit->setStyleSheet("QLineEdit { background-color: white }");
1298  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1299  }
1300  else {
1301  m_ui->pointRadiusSigmaLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1302  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1303  }
1304  update();
1305  }
1306 
1307  // outlier rejection
1308  void Isis::JigsawSetupDialog::on_maximumLikelihoodModel1QuantileLineEdit_textChanged(const QString &arg1) {
1309  if (!m_ui->maximumLikelihoodModel1QuantileLineEdit->isEnabled() ||
1310  m_ui->maximumLikelihoodModel1QuantileLineEdit->hasAcceptableInput()) {
1311  m_ui->maximumLikelihoodModel1QuantileLineEdit->setStyleSheet("");
1312  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1313  }
1314  else {
1315  m_ui->maximumLikelihoodModel1QuantileLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1316  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1317  }
1318  update();
1319  }
1320 
1321 
1322  void Isis::JigsawSetupDialog::on_maximumLikelihoodModel2QuantileLineEdit_textChanged(const QString &arg1) {
1323  if (!m_ui->maximumLikelihoodModel2QuantileLineEdit->isEnabled() ||
1324  m_ui->maximumLikelihoodModel2QuantileLineEdit->hasAcceptableInput()) {
1325  m_ui->maximumLikelihoodModel2QuantileLineEdit->setStyleSheet("");
1326  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1327  }
1328  else {
1329  m_ui->maximumLikelihoodModel2QuantileLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1330  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1331  }
1332  update();
1333  }
1334 
1335 
1336  void Isis::JigsawSetupDialog::on_maximumLikelihoodModel3QuantileLineEdit_textChanged(const QString &arg1) {
1337  if (!m_ui->maximumLikelihoodModel3QuantileLineEdit->isEnabled() ||
1338  m_ui->maximumLikelihoodModel3QuantileLineEdit->hasAcceptableInput()) {
1339  m_ui->maximumLikelihoodModel3QuantileLineEdit->setStyleSheet("");
1340  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1341  }
1342  else {
1343  m_ui->maximumLikelihoodModel3QuantileLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1344  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1345  }
1346  update();
1347  }
1348 
1349 
1350  // convergence criteria
1351  void Isis::JigsawSetupDialog::on_outlierRejectionMultiplierLineEdit_textChanged(const QString &arg1) {
1352  if (!m_ui->outlierRejectionCheckBox->isChecked() ||
1353  m_ui->outlierRejectionMultiplierLineEdit->hasAcceptableInput()) {
1354  m_ui->outlierRejectionMultiplierLineEdit->setStyleSheet("");
1355  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1356  }
1357  else {
1358  m_ui->outlierRejectionMultiplierLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1359  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1360  }
1361  update();
1362  }
1363 
1364 
1365  void Isis::JigsawSetupDialog::on_sigma0ThresholdLineEdit_textChanged(const QString &arg1) {
1366  if (m_ui->sigma0ThresholdLineEdit->hasAcceptableInput()) {
1367  m_ui->sigma0ThresholdLineEdit->setStyleSheet("QLineEdit { background-color: white }");
1368  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1369  }
1370  else {
1371  m_ui->sigma0ThresholdLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1372  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1373  }
1374  update();
1375  }
1376 
1377 
1378  void Isis::JigsawSetupDialog::on_maximumIterationsLineEdit_textChanged(const QString &arg1) {
1379  if (m_ui->maximumIterationsLineEdit->hasAcceptableInput()) {
1380  m_ui->maximumIterationsLineEdit->setStyleSheet("QLineEdit { background-color: white }");
1381  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
1382  }
1383  else {
1384  m_ui->maximumIterationsLineEdit->setStyleSheet("QLineEdit { background-color: red }");
1385  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
1386  }
1387  update();
1388  }
1389 
1390 
1391  void JigsawSetupDialog::showTargetParametersGroupBox() {
1392  m_ui->targetParametersGroupBox->setEnabled(true);
1393  }
1394 
1395 
1396  void JigsawSetupDialog::hideTargetParametersGroupBox() {
1397  m_ui->targetParametersGroupBox->setEnabled(false);
1398  }
1399 
1400  void Isis::JigsawSetupDialog::on_inputControlNetCombo_currentTextChanged(const QString &arg1) {
1401  FileName fname = arg1;
1402  m_ui->outputControlNetLineEdit->setText(fname.baseName() + "-out.net");
1403  }
1404 
1405 
1415  void JigsawSetupDialog::validateSigmaValue(QTableWidgetItem *item) {
1416  // Only validate the "a priori sigma" column
1417  if (item->column() != 3) {
1418  return;
1419  }
1420  // FREE is a valid value for the a priori sigma column
1421  int free = item->text().simplified().compare("FREE", Qt::CaseInsensitive);
1422 
1423  // Positive doubles are valid values for the a priori sigma column
1424  bool convertSuccess = false;
1425  double sigma = item->text().toDouble(&convertSuccess);
1426  if ((convertSuccess && sigma >= 0.0) || free == 0) {
1427  const QTableWidget *table = item->tableWidget();
1428  item->setData(Qt::UserRole, QVariant(true));
1429  // Set background color depending on if the table has alternating row colors and row is odd
1430  if (table->alternatingRowColors() && item->row() % 2 != 0) {
1431  item->setBackground(table->palette().color(QPalette::AlternateBase));
1432  }
1433  else {
1434  item->setBackground(table->palette().color(QPalette::Base));
1435  }
1436 
1437  if (sigma == 0.0) {
1438  item->setText("FREE");
1439  }
1440  }
1441  else {
1442  item->setData(Qt::UserRole, QVariant(false));
1443  item->setBackground(Qt::red);
1444  }
1445 
1447  }
1448 
1449 
1460  bool tablesAreValid = true;
1461 
1462  // Evaluate both tables; if any value is invalid, the table is invalid
1463  QList<const QTableWidget *> tables{m_ui->positionAprioriSigmaTable,
1464  m_ui->pointingAprioriSigmaTable};
1465 
1466  for (const auto &table : tables) {
1467  for (int i = 0; i < table->rowCount(); i++) {
1468  // a priori sigma column is column 3
1469  const QTableWidgetItem *item = table->item(i,3);
1470  if (item) {
1471  if (item->data(Qt::UserRole).toBool() == false) {
1472  tablesAreValid = false;
1473  break;
1474  }
1475  }
1476  }
1477  }
1478 
1479  m_ui->okCloseButtonBox->button(QDialogButtonBox::Ok)->setEnabled(tablesAreValid);
1480  if (!m_ui->treeView->selectionModel()->selectedRows().isEmpty()) {
1481  m_ui->applySettingsPushButton->setEnabled(tablesAreValid);
1482  }
1483  }
1484 
1485 
1497  // Update the position apriori sigma table and use the position combo box solve option
1498  updateSolveSettingsSigmaTables(m_ui->positionComboBox, m_ui->positionAprioriSigmaTable);
1499  }
1500 
1501 
1513  // Update the pointing apriori sigma table and use the pointing combo box solve option
1514  updateSolveSettingsSigmaTables(m_ui->pointingComboBox, m_ui->pointingAprioriSigmaTable);
1515  }
1516 
1517 
1528  QTableWidget *table) {
1529  int rowCount = solveOptionComboBox->currentIndex();
1530 
1531  // Position: { NONE, POSITION, VELOCITY, ACCELERATION, ALL }
1532  // Pointing: { NONE, ANGLES, ANGULAR VELOCITY, ANGULAR ACCELERATION, ALL }
1533  // Need to add to the solve degree value since number of rows == number of solve coefficients,
1534  // and for our polynomials the number of solve coefficients == solve degree + 1
1535  // When solve option is ALL (index 4), use the spk/ck solve degree value + 1 for number of rows
1536  if (rowCount == 4) {
1537  if (solveOptionComboBox == m_ui->positionComboBox) {
1538  rowCount = m_ui->spkSolveDegreeSpinBox->value() + 1;
1539  }
1540  else { // if (solveOptionComboBox == m_ui->pointingComboBox)
1541  rowCount = m_ui->ckSolveDegreeSpinBox->value() + 1;
1542  }
1543  }
1544 
1545  // number of rows == position solve option == SolveDegree value + 1 (i+1)
1546  const int oldRowCount = table->rowCount();
1547  // if solving ALL, don't add extra row
1548  table->setRowCount(rowCount);
1549  const int newRowCount = table->rowCount();
1550 
1551  // Need to check if table is valid in case a row is removed (a row is removed implicitly when
1552  // the setRowCount() is called when newRowCount < oldRowCount
1554 
1555  // Determine the units for either position or pointing
1556  QStringList solveOptions;
1557  QString longUnits("N/A");
1558  QString shortUnits("N/A");
1559  if (solveOptionComboBox == m_ui->positionComboBox) {
1560  longUnits = "meters";
1561  shortUnits = "m";
1562  solveOptions += {"POSITION", "VELOCITY", "ACCELERATION"};
1563  }
1564  else { // if (solveOptionComboBox == m_ui->pointingComboBox) {
1565  longUnits = "degrees";
1566  shortUnits = "deg";
1567  solveOptions += {"ANGLES", "ANGULAR VELOCITY", "ANGULAR ACCELERATION"};
1568  }
1569 
1570  // Rows need to be added
1571  if (newRowCount > oldRowCount) {
1572  for (int row = oldRowCount; row < newRowCount; row++) {
1573  // Headers : coefficient, description, units, a priori sigma
1574  QTableWidgetItem *coefficient = new QTableWidgetItem();
1575  coefficient->setFlags(Qt::ItemIsEnabled);
1576  coefficient->setText(QString::number(row + 1));
1577  table->setItem(row, 0, coefficient);
1578 
1579  QTableWidgetItem *description = new QTableWidgetItem();
1580  description->setFlags(Qt::ItemIsEnabled);
1581  description->setText("N/A");
1582  table->setItem(row, 1, description);
1583 
1584  QTableWidgetItem *units = new QTableWidgetItem();
1585  units->setFlags(Qt::ItemIsEnabled);
1586  units->setText(shortUnits + "/s^" + QString::number(row));
1587  table->setItem(row, 2, units);
1588 
1589  QTableWidgetItem *sigma = new QTableWidgetItem();
1590  sigma->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
1591  sigma->setText("0.0");
1592  sigma->setData(Qt::UserRole, QVariant(true));
1593  table->setItem(row, 3, sigma);
1594 
1595  // Solve option: spk degree { NONE: -1, POSITION: 0, VELOCITY: 1, ACCELERATION: 2, ALL: 2 }
1596  // POSITION
1597  if (row == 0) {
1598  QTableWidgetItem *description = table->item(0, 1);
1599  description->setText(solveOptions.at(row));
1600 
1601  QTableWidgetItem *units = table->item(0, 2);
1602  units->setText(longUnits);
1603  }
1604 
1605  // VELOCITY
1606  else if (row == 1) {
1607  QTableWidgetItem *description = table->item(1, 1);
1608  description->setText(solveOptions.at(row));
1609 
1610  QTableWidgetItem *units = table->item(1, 2);
1611  units->setText(shortUnits + "/s");
1612  }
1613 
1614  // ACCELERATION
1615  else if (row == 2) {
1616  QTableWidgetItem *description = table->item(2, 1);
1617  description->setText(solveOptions.at(row));
1618 
1619  QTableWidgetItem *units = table->item(2, 2);
1620  units->setText(shortUnits + "/s^2");
1621  }
1622  }
1623  }
1624 
1625  table->resizeColumnToContents(1);
1626  table->resizeColumnToContents(2);
1627  }
1628 
1629 
1640  int solveIndex = m_ui->positionComboBox->currentIndex();
1641  QList<QSpinBox *> spinBoxes{m_ui->spkSolveDegreeSpinBox, m_ui->spkDegreeSpinBox};
1642  for (auto &spinBox : spinBoxes) {
1643  // ALL enables the solve degree spin box, but does not increase the degree
1644  // Below shows the corresponding degree for each of the solve options:
1645  // NONE = -1; ANGLES = 0; VELOCITY = 1; ACCELERATION = 2; ALL = 2
1646  if (arg1 == "ALL") {
1647  spinBox->setValue(solveIndex - 2);
1648  spinBox->setEnabled(true);
1649  }
1650  else {
1651  // The default value for the spk solve degree and spk degree spinboxes is 2. This is
1652  // emulating jigsaw's defaults for position solve options that are not ALL.
1653  spinBox->setValue(2);
1654  spinBox->setEnabled(false);
1655  }
1656  }
1657 
1658  updateSolveSettingsSigmaTables(m_ui->positionComboBox, m_ui->positionAprioriSigmaTable);
1659  }
1660 
1661 
1672  int solveIndex = m_ui->pointingComboBox->currentIndex();
1673  QList<QSpinBox *> spinBoxes{m_ui->ckSolveDegreeSpinBox, m_ui->ckDegreeSpinBox};
1674  for (auto &spinBox : spinBoxes) {
1675  // ALL enables the solve degree spin box, but does not increase the degree
1676  // Below shows the corresponding degree for each of the solve options:
1677  // NONE = -1; ANGLES = 0; ANGULAR VELOCITY = 1; ANGULAR ACCELERATION = 2; ALL = 2
1678  if (arg1 == "ALL") {
1679  spinBox->setValue(solveIndex - 2);
1680  spinBox->setEnabled(true);
1681  }
1682  else {
1683  // The default value for the ck solve degree and spk degree spinboxes is 2. This is
1684  // emulating jigsaw's defaults for pointing solve options that are not ALL.
1685  spinBox->setValue(2);
1686  spinBox->setEnabled(false);
1687  }
1688  }
1689 
1690  updateSolveSettingsSigmaTables(m_ui->pointingComboBox, m_ui->pointingAprioriSigmaTable);
1691  }
1692 
1693 
1694 
1695  void JigsawSetupDialog::createObservationSolveSettingsTreeView() {
1696 
1697  QList<ProjectItem *> selectedBOSSItems = m_project->directory()->model()->selectedBOSSImages();
1698 
1699  ProjectItemModel *model = m_project->directory()->model();
1700 
1702  osspm->setSourceModel(model);
1703 
1704  //osspm->setDynamicSortFilter(true);
1705  osspm->setSelectedItems(selectedBOSSItems );
1706  m_ui->treeView->setModel(osspm);
1707 
1708 
1709 
1710 
1711  ProjectItem *imgRoot = model->findItemData(QVariant("Images"),0);
1712  if (imgRoot) {
1713 
1714  m_ui->treeView->setRootIndex(osspm->mapFromSource(imgRoot->index()));
1715  }
1716  else {
1717  m_ui->treeView->setRootIndex(QModelIndex());
1718  }
1719 
1720  connect(m_ui->treeView->selectionModel(),
1721  SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
1722  this,
1723  SLOT(treeViewSelectionChanged(const QItemSelection&,const QItemSelection&)));
1724 
1725 
1726  // Try to loop through the view here to add the "groups" so they aren't part of the model
1727 
1728  // Add apply button to the tab view
1729  // set the text to bold?
1730 
1731 
1732  }
1733 
1734 
1735  void JigsawSetupDialog::treeViewSelectionChanged(const QItemSelection &selected,
1736  const QItemSelection &deselected) {
1737  QModelIndexList indexList = m_ui->treeView->selectionModel()->selectedRows();
1738 
1739  // qDebug() << "\n\nselected: " << selected.indexes();
1740  // qDebug() << "deselected: " << deselected.indexes();
1741  // qDebug() << "selectedRows: " << m_ui->treeView->selectionModel()->selectedRows();
1742 
1743 
1744  if (!indexList.isEmpty()) {
1745  QModelIndex displayIndex = indexList[0];
1746 
1747  SortFilterProxyModel * proxyModel = (SortFilterProxyModel *) m_ui->treeView->model();
1748  ProjectItemModel *sourceModel = (ProjectItemModel *) proxyModel->sourceModel();
1749 
1750  QModelIndex sourceIndex = proxyModel->mapToSource(displayIndex);
1751  ProjectItem * projItem = sourceModel->itemFromIndex(sourceIndex);
1752 
1753  if (projItem->isImageList()) {
1754  projItem = projItem->child(0);
1755  }
1756  BundleObservationSolveSettings settings = m_bundleSettings->observationSolveSettings(
1757  projItem->image()->observationNumber());
1758 
1759  // Populate RHS of Observation Solve Settings tab with selected image's BOSS
1760  // Instrument Position Solve Options
1761  m_ui->positionComboBox->setCurrentIndex(settings.instrumentPositionSolveOption());
1762  m_ui->spkSolveDegreeSpinBox->setValue(settings.spkSolveDegree());
1763  m_ui->spkDegreeSpinBox->setValue(settings.spkDegree());
1764  m_ui->hermiteSplineCheckBox->setChecked(settings.solvePositionOverHermite());
1765 
1766  for (int row = 0; row < settings.aprioriPositionSigmas().count(); row++) {
1767  QTableWidgetItem * sigmaItem = m_ui->positionAprioriSigmaTable->item(row, 3);
1768  double sigma = settings.aprioriPositionSigmas()[row];
1769  if (sigma == Isis::Null) {
1770  sigmaItem->setText("FREE");
1771  }
1772  else {
1773  sigmaItem->setText(QString::number(sigma));
1774  }
1775  }
1776 
1777  // Instrument Pointing Solve Options
1778  m_ui->pointingComboBox->setCurrentIndex(settings.instrumentPointingSolveOption());
1779  m_ui->ckSolveDegreeSpinBox->setValue(settings.ckSolveDegree());
1780  m_ui->ckDegreeSpinBox->setValue(settings.ckDegree());
1781  m_ui->twistCheckBox->setChecked(settings.solveTwist());
1782  m_ui->fitOverPointingCheckBox->setChecked(settings.solvePolyOverPointing());
1783 
1784  for (int row = 0; row < settings.aprioriPointingSigmas().count(); row++) {
1785  QTableWidgetItem * sigmaItem = m_ui->pointingAprioriSigmaTable->item(row, 3);
1786  double sigma = settings.aprioriPointingSigmas()[row];
1787  if (sigma == Isis::Null) {
1788  sigmaItem->setText("FREE");
1789  }
1790  else {
1791  sigmaItem->setText(QString::number(sigma));
1792  }
1793  }
1794 
1795  }
1796 
1797  m_ui->applySettingsPushButton->setEnabled(!selected.isEmpty());
1798  }
1799 
1800 
1801 
1809 
1810  // Get the current selected images and the item models
1811  SortFilterProxyModel * proxyModel = (SortFilterProxyModel *) m_ui->treeView->model();
1812  ProjectItemModel *sourceModel = (ProjectItemModel *) proxyModel->sourceModel();
1813 
1814  QModelIndexList selectedIndexes = m_ui->treeView->selectionModel()->selectedIndexes();
1815  QStringList selectedObservationNumbers;
1816 
1817  // Append selected images' serial numbers to selectedObservationNumbers
1818  foreach (QModelIndex index, selectedIndexes) {
1819  QModelIndex sourceIndex = proxyModel->mapToSource(index);
1820  ProjectItem * projItem = sourceModel->itemFromIndex(sourceIndex);
1821 
1822  if (projItem) {
1823  // Tree traversal is top down so we dont need to do this check for imagelists?
1824  if (projItem->isImage()) {
1825  // Grab the observation up front so we don't need to re-compose the observation number
1826  // more than once (@todo: this should not be necessary when 5026 is integrated)
1827  const QString observationNumber = projItem->image()->observationNumber();
1828  if (!selectedObservationNumbers.contains(observationNumber)) {
1829  selectedObservationNumbers.append(observationNumber);
1830  }
1831  }
1832  else if (projItem->isImageList()) {
1833  // Use the proxymodel's children as it might not include all of the sourcemodel's children
1834  for (int i = 0; i < proxyModel->rowCount(index); i++) {
1835  QModelIndex childProxyIndex = proxyModel->index(i, 0, index);
1836  QModelIndex childSourceIndex = proxyModel->mapToSource(childProxyIndex);
1837  ProjectItem * childItem = sourceModel->itemFromIndex(childSourceIndex);
1838  selectedObservationNumbers.append(childItem->image()->observationNumber());
1839  }
1840  }
1841  }
1842  }
1843 
1844  QList<BundleObservationSolveSettings> solveSettingsList = m_bundleSettings->observationSolveSettings();
1845 
1846  //find the bundle observation solve settings for each of the selected observations and remove
1847  // the observation number from them
1848  for (auto &solveSettings : solveSettingsList) {
1849  foreach (QString observationNumber, selectedObservationNumbers) {
1850  solveSettings.removeObservationNumber(observationNumber);
1851  }
1852  }
1853 
1854 
1855  // Remove any existing solve settings that no longer have any observation numbers
1856  int iter = 0;
1857  while (iter < solveSettingsList.count()) {
1858  if (solveSettingsList[iter].observationNumbers().isEmpty() ) {
1859  solveSettingsList.removeAt(iter);
1860  }
1861  else {
1862  iter++; // This list shrinks as we remove, so we dont need to iterate every time
1863  }
1864  }
1865 
1866  // Create a new bundle observation solve settings
1867  BundleObservationSolveSettings solveSettings;
1868  foreach (QString observationNumber, selectedObservationNumbers) {
1869  solveSettings.addObservationNumber(observationNumber);
1870  }
1871 
1872  // Grab the data from the right hand side of the observation solve settings tab to set
1873  // up the new bundle observation solve settings
1874  updateBundleObservationSolveSettings(solveSettings);
1875 
1876  // Add the new solve settings to the solve settings list
1877  solveSettingsList.append(solveSettings);
1878 
1879  // Update bundle settings with the new list of bundle observation solve settings
1880  m_bundleSettings->setObservationSolveOptions(solveSettingsList);
1881 
1882  // qDebug()<<"Current BOSS list --------";
1883  // for (int i = 0; i < solveSettingsList.count(); i++) {
1884  // qDebug() << "solveSettingsList["<<i<<"]: " << solveSettingsList[i].observationNumbers();
1885  // }
1886  }
1887 
1888 }
This represents an ISIS control net in a project-based GUI interface.
Definition: Control.h:79
This class is used to represent a target body in a bundle and how to solve for it.
void updateBundleObservationSolveSettings(BundleObservationSolveSettings &boss)
updateBundleObservationSolveSettings: This function sets the parameters of a BundleObservationSolveSe...
bool isImageList() const
Returns true if an ImageList is stored in the data of the item.
$Revision$ $Date$
Isis specific code for binary pck.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
virtual CameraType GetCameraType() const =0
Returns the type of camera that was created.
Line Scan Camera.
Definition: Camera.h:373
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
The value of sigma0 will be used to determine that the bundle adjustment has converged.
The main project for ipce.
Definition: Project.h:289
bool isImage() const
Returns true if an Image is stored in the data of the item.
void loadSettings(const BundleSettingsQsp settings)
Loads the passed bundle settings into the setup dialog.
File name manipulation and expansion.
Definition: FileName.h:116
ProjectItem * itemFromIndex(const QModelIndex &index)
Returns the ProjectItem corresponding to a given QModelIndex.
void selectControl(const QString &controlName)
Selects a control in the control network combo box by trying to find an item with the matching name...
QSet< QString > observationNumbers() const
Returns a list of observation numbers associated with these solve settings.
Camera * camera()
Return a camera associated with the cube.
Definition: Cube.cpp:1166
InstrumentPositionSolveOption instrumentPositionSolveOption() const
Accesses the instrument position solve option.
Maintains a list of Controls so that control nets can easily be copied from one Project to another...
Definition: ControlList.h:36
void on_pointingComboBox_currentIndexChanged(const QString &arg1)
Slot that listens for when the Instrument Pointing Solve Option combobox changes. ...
void on_spkSolveDegreeSpinBox_valueChanged(int arg1)
Slot that listens for changes to the SPK Solve Degree spin box.
QSharedPointer< BundleTargetBody > BundleTargetBodyQsp
Definition for BundleTargetBodyQsp, a QSharedPointer to a BundleTargetBody.
QString displayName() const
Returns the display name.
bool solvePositionOverHermite() const
Whether or not the polynomial for solving will be fit over an existing Hermite spline.
The distance is being specified in kilometers.
Definition: Distance.h:58
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
Solve for pointing angles, their velocities and their accelerations.
void on_positionComboBox_currentIndexChanged(const QString &arg1)
Slot that listens for when the Instrument Position Solve Option combobox changes. ...
void validateSigmaValue(QTableWidgetItem *)
Validates the a priori sigma values for a given QTableWidgetItem.
void on_ckSolveDegreeSpinBox_valueChanged(int arg1)
Slot that listens for changes to the CK Solve Degree spin box.
Distance measurement, usually in meters.
Definition: Distance.h:47
void on_applySettingsPushButton_clicked()
Slot for handling the Observation Solve Settings tab&#39;s Apply button.
Provides access to data stored in a Project through Qt&#39;s model-view framework.
Isis specific code for unknown frame type.
Planetocentric latitudinal (lat/lon/rad) coordinates.
Definition: SurfacePoint.h:156
ProjectItem * findItemData(const QVariant &data, int role=Qt::UserRole+1)
Returns the first item found that contains the given data in the given role or a null pointer if no i...
int ckDegree() const
Accesses the degree of polynomial fit to original camera angles (ckDegree).
InstrumentPointingSolveOption instrumentPointingSolveOption() const
Accesses the instrument pointing solve option.
Directory * directory() const
Returns the directory associated with this Project.
Definition: Project.cpp:1229
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:73
ProjectItemModel * model()
Gets the ProjectItemModel for this directory.
Definition: Directory.cpp:1105
int ckSolveDegree() const
Accesses the degree of the camera angles polynomial being fit to in the bundle adjustment (ckSolveDeg...
int spkSolveDegree() const
Accesses the degree of thecamera position polynomial being fit to in the bundle adjustment (spkSolveD...
void addObservationNumber(QString observationNumber)
Associates an observation number with these solve settings.
void updateSolveSettingsSigmaTables(const QComboBox *solveOptionComboBox, QTableWidget *table)
Slot that updates the sigma tables based on the current solve option selection.
TargetRadiiSolveMethod
Enumeration that defines how to solve for target radii.
QSharedPointer< BundleSettings > BundleSettingsQsp
Definition for a BundleSettingsQsp, a shared pointer to a BundleSettings object.
void validateSigmaTables()
Validates the tables in the observation solve settings tab and enables/disables the OK button appropr...
Container class for BundleAdjustment settings.
bool solvePolyOverPointing() const
Whether or not the solve polynomial will be fit over the existing pointing polynomial.
TargetBodyList targetBodies()
Return TargetBodyList in Project.
Definition: Project.cpp:2194
This represents a cube in a project-based GUI interface.
Definition: Image.h:107
Image * image() const
Returns the Image stored in the data of the item.
void setInstrumentPositionSettings(InstrumentPositionSolveOption option, int spkDegree=2, int spkSolveDegree=2, bool positionOverHermite=false, double positionAprioriSigma=-1.0, double velocityAprioriSigma=-1.0, double accelerationAprioriSigma=-1.0, QList< double > *additionalPositionSigmas=nullptr)
Sets the instrument pointing settings.
void setInstrumentId(QString instrumentId)
Sets the instrument id for this observation.
QList< ControlList * > controls()
Return controls in project.
Definition: Project.cpp:2038
QList< double > aprioriPositionSigmas() const
Accesses the a priori position sigmas.
Ui::JigsawRunWidget * m_ui
Reference to self&#39;s UI generated with QtDesigner.
This class is used to modify and manage solve settings for 1 to many BundleObservations.
QString observationNumber()
Returns the observation number of the Cube.
Definition: Image.cpp:349
Defines an angle and provides unit conversions.
Definition: Angle.h:62
ControlDisplayProperties * displayProperties()
Access a pointer to the display properties for the control network.
Definition: Control.cpp:244
QString baseName() const
Returns the name of the file without the path and without extensions.
Definition: FileName.cpp:161
QList< BundleSolutionInfo * > bundleSolutionInfo()
Return BundleSolutionInfo objects in Project.
Definition: Project.cpp:2223
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
ProjectItem * child(int row) const
Returns the child item at a given row.
void setInstrumentPointingSettings(InstrumentPointingSolveOption option, bool solveTwist, int ckDegree=2, int ckSolveDegree=2, bool solvePolynomialOverExisting=false, double anglesAprioriSigma=-1.0, double angularVelocityAprioriSigma=-1.0, double angularAccelerationAprioriSigma=-1.0, QList< double > *additionalPointingSigmas=nullptr)
Sets the instrument pointing settings.
QList< ProjectItem * > selectedItems()
Returns a list of the selected items of the internal selection model.
Represents an item of a ProjectItemModel in Qt&#39;s model-view framework.
Definition: ProjectItem.h:146
QList< ProjectItem * > selectedBOSSImages()
ProjectItemModel::selectedBOSSImages.
InstrumentPositionSolveOption
Options for how to solve for instrument position.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
bool IsNullPixel(const double d)
Returns if the input pixel is null.
Definition: SpecialPixel.h:250
Cube * cube()
Get the Cube pointer associated with this display property.
Definition: Image.cpp:287
The distance is being specified in meters.
Definition: Distance.h:56
InstrumentPointingSolveOption
Options for how to solve for instrument pointing.
int spkDegree() const
Accesses the degree of the polynomial fit to the original camera position (spkDegree).
BundleSettingsQsp m_bundleSettings
The BundleSettings Object created by this dialog.
bool solveTwist() const
Accesses the flag for solving for twist.
QList< double > aprioriPointingSigmas() const
Accesses the a priori pointing sigmas.