File failed to load: https://isis.astrogeology.usgs.gov/9.0.0/Object/assets/jax/output/NativeMML/config.js
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
13#include "BundleObservationSolveSettings.h"
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"
22#include "MaximumLikelihoodWFunctions.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
30namespace 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 = QVariant::fromValue((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 = QVariant::fromValue((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
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().horizontalAdvance(tableHeaders.at(0)) + 10);
176 m_ui->positionAprioriSigmaTable->setColumnWidth(1, fontMetrics().horizontalAdvance(tableHeaders.at(1)) + 10);
177 m_ui->positionAprioriSigmaTable->setColumnWidth(2, fontMetrics().horizontalAdvance(tableHeaders.at(2)) + 10);
178 m_ui->positionAprioriSigmaTable->setColumnWidth(3, fontMetrics().horizontalAdvance(tableHeaders.at(3)) + 10);
179
180 m_ui->pointingAprioriSigmaTable->setColumnWidth(0, fontMetrics().horizontalAdvance(tableHeaders.at(0)) + 10);
181 m_ui->pointingAprioriSigmaTable->setColumnWidth(1, fontMetrics().horizontalAdvance(tableHeaders.at(1)) + 10);
182 m_ui->pointingAprioriSigmaTable->setColumnWidth(2, fontMetrics().horizontalAdvance(tableHeaders.at(2)) + 10);
183 m_ui->pointingAprioriSigmaTable->setColumnWidth(3, fontMetrics().horizontalAdvance(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 = QVariant::fromValue((void*)target.data());
200
201 QString name = target->displayProperties()->displayName();
202
203 if (name == "MOON")
204 m_ui->targetBodyComboBox->addItem(QIcon(FileName(
205 "$ISISROOT/appdata/images/icons/weather-clear-night.png").expanded()), name, v);
206 else if (name == "Enceladus")
207 m_ui->targetBodyComboBox->addItem(QIcon(FileName(
208 "$ISISROOT/appdata/images/icons/nasa_enceladus.png").expanded()), name, v);
209 else if (name == "Mars")
210 m_ui->targetBodyComboBox->addItem(QIcon(FileName(
211 "$ISISROOT/appdata/images/icons/nasa_mars.png").expanded()), name, v);
212 else if (name == "Titan")
213 m_ui->targetBodyComboBox->addItem(QIcon(FileName(
214 "$ISISROOT/appdata/images/icons/nasa_titan.png").expanded()), name, v);
215 else
216 m_ui->targetBodyComboBox->addItem(QIcon(FileName(
217 "$ISISROOT/appdata/images/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
586 BundleTargetBodyQsp bundleTargetBody = BundleTargetBodyQsp(new BundleTargetBody);
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
822 break;
824 break;
826 break;
828 break;
829
831 break;
833 break;
834
835 }
836
837 switch(instrumentPositionSolveOption) {
838
840 break;
842 break;
844 break;
846 break;
847
849 break;
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
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}
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
This class is used to modify and manage solve settings for 1 to many BundleObservations.
InstrumentPositionSolveOption
Options for how to solve for instrument position.
@ PositionVelocity
Solve for instrument positions and velocities.
@ PositionVelocityAcceleration
Solve for instrument positions, velocities, and accelerations.
@ AllPositionCoefficients
Solve for all coefficients in the polynomials fit to the instrument positions.
@ PositionOnly
Solve for instrument positions only.
@ NoPositionFactors
Solve for none of the position factors.
void addObservationNumber(QString observationNumber)
Associates an observation number with these solve settings.
InstrumentPositionSolveOption instrumentPositionSolveOption() const
Accesses the instrument position solve option.
bool solveTwist() const
Accesses the flag for solving for twist.
bool solvePolyOverPointing() const
Whether or not the solve polynomial will be fit over the existing pointing polynomial.
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.
int ckDegree() const
Accesses the degree of polynomial fit to original camera angles (ckDegree).
QList< double > aprioriPositionSigmas() const
Accesses the a priori position sigmas.
QList< double > aprioriPointingSigmas() const
Accesses the a priori pointing sigmas.
int ckSolveDegree() const
Accesses the degree of the camera angles polynomial being fit to in the bundle adjustment (ckSolveDeg...
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.
bool solvePositionOverHermite() const
Whether or not the polynomial for solving will be fit over an existing Hermite spline.
QSet< QString > observationNumbers() const
Returns a list of observation numbers associated with these solve settings.
int spkSolveDegree() const
Accesses the degree of thecamera position polynomial being fit to in the bundle adjustment (spkSolveD...
InstrumentPointingSolveOption instrumentPointingSolveOption() const
Accesses the instrument pointing solve option.
InstrumentPointingSolveOption
Options for how to solve for instrument pointing.
@ AnglesVelocity
Solve for pointing angles and their angular velocities.
@ AnglesVelocityAcceleration
Solve for pointing angles, their velocities and their accelerations.
@ AllPointingCoefficients
Solve for all coefficients in the polynomials fit to the pointing angles.
@ AnglesOnly
Solve for pointing angles: right ascension, declination and, optionally, twist.
@ NoPointingFactors
Solve for none of the pointing factors.
int spkDegree() const
Accesses the degree of the polynomial fit to the original camera position (spkDegree).
Container class for BundleAdjustment settings.
@ Sigma0
The value of sigma0 will be used to determine that the bundle adjustment has converged.
TargetRadiiSolveMethod
Enumeration that defines how to solve for target radii.
@ LineScan
Line Scan Camera.
Definition Camera.h:361
virtual CameraType GetCameraType() const =0
Returns the type of camera that was created.
This represents an ISIS control net in a project-based GUI interface.
Definition Control.h:65
ControlDisplayProperties * displayProperties()
Access a pointer to the display properties for the control network.
Definition Control.cpp:232
Maintains a list of Controls so that control nets can easily be copied from one Project to another,...
Definition ControlList.h:42
Camera * camera()
Return a camera associated with the cube.
Definition Cube.cpp:1464
ProjectItemModel * model()
Gets the ProjectItemModel for this directory.
QString displayName() const
Returns the display name.
@ Kilometers
The distance is being specified in kilometers.
Definition Distance.h:45
@ Meters
The distance is being specified in meters.
Definition Distance.h:43
File name manipulation and expansion.
Definition FileName.h:100
QString baseName() const
Returns the name of the file without the path and without extensions.
Definition FileName.cpp:145
This represents a cube in a project-based GUI interface.
Definition Image.h:105
Cube * cube()
Get the Cube pointer associated with this display property.
Definition Image.cpp:262
QString observationNumber()
Returns the observation number of the Cube.
Definition Image.cpp:324
void on_ckSolveDegreeSpinBox_valueChanged(int arg1)
Slot that listens for changes to the CK Solve Degree spin box.
void on_positionComboBox_currentIndexChanged(const QString &arg1)
Slot that listens for when the Instrument Position Solve Option combobox changes.
void updateBundleObservationSolveSettings(BundleObservationSolveSettings &boss)
updateBundleObservationSolveSettings: This function sets the parameters of a BundleObservationSolveSe...
void on_applySettingsPushButton_clicked()
Slot for handling the Observation Solve Settings tab's Apply button.
BundleSettingsQsp m_bundleSettings
The BundleSettings Object created by this dialog.
void loadSettings(const BundleSettingsQsp settings)
Loads the passed bundle settings into the setup dialog.
void on_spkSolveDegreeSpinBox_valueChanged(int arg1)
Slot that listens for changes to the SPK Solve Degree spin box.
void validateSigmaValue(QTableWidgetItem *)
Validates the a priori sigma values for a given QTableWidgetItem.
void selectControl(const QString &controlName)
Selects a control in the control network combo box by trying to find an item with the matching name.
void on_pointingComboBox_currentIndexChanged(const QString &arg1)
Slot that listens for when the Instrument Pointing Solve Option combobox changes.
void validateSigmaTables()
Validates the tables in the observation solve settings tab and enables/disables the OK button appropr...
void updateSolveSettingsSigmaTables(const QComboBox *solveOptionComboBox, QTableWidget *table)
Slot that updates the sigma tables based on the current solve option selection.
The main project for ipce.
Definition Project.h:287
TargetBodyList targetBodies()
Return TargetBodyList in Project.
Definition Project.cpp:2255
QList< ControlList * > controls()
Return controls in project.
Definition Project.cpp:2099
Directory * directory() const
Returns the directory associated with this Project.
Definition Project.cpp:1226
QList< BundleSolutionInfo * > bundleSolutionInfo()
Return BundleSolutionInfo objects in Project.
Definition Project.cpp:2284
Represents an item of a ProjectItemModel in Qt's model-view framework.
bool isImageList() const
Returns true if an ImageList is stored in the data of the item.
Image * image() const
Returns the Image stored in the data of the item.
bool isImage() const
Returns true if an Image is stored in the data of the item.
ProjectItem * child(int row) const
Returns the child item at a given row.
ProjectItemModel * model() const
Returns the ProjectItemModel associated with this item.
Provides access to data stored in a Project through Qt's model-view framework.
QList< ProjectItem * > selectedItems()
Returns a list of the selected items of the internal selection model.
ProjectItem * itemFromIndex(const QModelIndex &index)
Returns the ProjectItem corresponding to a given QModelIndex.
QList< ProjectItem * > selectedBOSSImages()
ProjectItemModel::selectedBOSSImages.
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...
@ UNKNOWN
Isis specific code for unknown frame type.
@ BPC
Isis specific code for binary pck.
@ Latitudinal
Planetocentric latitudinal (lat/lon/rad) coordinates.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
QSharedPointer< TargetBody > TargetBodyQsp
Defines A smart pointer to a TargetBody obj.
Definition TargetBody.h:184
QSharedPointer< BundleSettings > BundleSettingsQsp
Definition for a BundleSettingsQsp, a shared pointer to a BundleSettings object.
bool IsNullPixel(const double d)
Returns if the input pixel is null.
const double Null
Value for an Isis Null pixel.
QSharedPointer< BundleTargetBody > BundleTargetBodyQsp
Definition for BundleTargetBodyQsp, a QSharedPointer to a BundleTargetBody.