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 = 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 "$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
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 *>();
881 boss.addObservationNumber(img->observationNumber() );
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}
Defines an angle and provides unit conversions.
Definition Angle.h:45
@ 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.
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.
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.
Container class for BundleAdjustment settings.
@ Sigma0
The value of sigma0 will be used to determine that the bundle adjustment has converged.
This class is used to represent a target body in a bundle and how to solve for it.
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:66
ControlDisplayProperties * displayProperties()
Access a pointer to the display properties for the control network.
Definition Control.cpp:252
Maintains a list of Controls so that control nets can easily be copied from one Project to another,...
Definition ControlList.h:44
Camera * camera()
Return a camera associated with the cube.
Definition Cube.cpp:1457
ProjectItemModel * model()
Gets the ProjectItemModel for this directory.
QString displayName() const
Returns the display name.
Distance measurement, usually in meters.
Definition Distance.h:34
@ 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 name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition FileName.cpp:162
This represents a cube in a project-based GUI interface.
Definition Image.h:107
Cube * cube()
Get the Cube pointer associated with this display property.
Definition Image.cpp:287
QString observationNumber()
Returns the observation number of the Cube.
Definition Image.cpp:349
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:289
TargetBodyList targetBodies()
Return TargetBodyList in Project.
Definition Project.cpp:2193
QList< ControlList * > controls()
Return controls in project.
Definition Project.cpp:2037
Directory * directory() const
Returns the directory associated with this Project.
Definition Project.cpp:1228
QList< BundleSolutionInfo * > bundleSolutionInfo()
Return BundleSolutionInfo objects in Project.
Definition Project.cpp:2222
Represents an item of a ProjectItemModel in Qt's model-view framework.
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.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
QSharedPointer< BundleSettings > BundleSettingsQsp
Definition for a BundleSettingsQsp, a shared pointer to a BundleSettings object.
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.