7#include "aberrationinspector.h"
8#include "aberrationinspectorplot.h"
9#include "sensorgraphic.h"
10#include <kstars_debug.h>
15const float RADIANS2DEGREES = 360.0f / (2.0f * M_PI);
20AberrationInspector::AberrationInspector(
const abInsData &data,
const QVector<int> &positions,
23 m_data(data), m_positions(positions), m_measures(measures), m_weights(weights),
24 m_numStars(numStars), m_tileOffsets(tileCenterOffsets)
35 initAberrationInspector();
50 setTileSelection(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
53AberrationInspector::~AberrationInspector()
57void AberrationInspector::setupGUI()
60 this->setWindowTitle(
i18n(
"Aberration Inspector - Run %1", m_data.run));
65 this->done(QDialog::Accepted);
70 setTileSelection(
static_cast<TileSelection
>(index));
75 setShowLabels(setting);
85 setOptCentres(setting);
89 m_plot =
new AberrationInspectorPlot(
this);
90 abInsPlotLayout->addWidget(m_plot);
94 abInsTable->setColumnCount(Headers.count());
95 abInsTable->setHorizontalHeaderLabels(Headers);
98 abInsTable->horizontalHeaderItem(0)->setToolTip(
i18n(
"Tile"));
99 abInsTable->horizontalHeaderItem(1)->setToolTip(
i18n(
"Description"));
100 abInsTable->horizontalHeaderItem(2)->setToolTip(
i18n(
"Focuser Solution"));
101 abInsTable->horizontalHeaderItem(3)->setToolTip(
i18n(
"Delta from central tile in ticks"));
102 abInsTable->horizontalHeaderItem(4)->setToolTip(
i18n(
"Delta from central tile in micrometers"));
103 abInsTable->horizontalHeaderItem(5)->setToolTip(
i18n(
"Min / max number of stars detected in the focus run"));
104 abInsTable->horizontalHeaderItem(6)->setToolTip(
i18n(
"R²"));
105 abInsTable->horizontalHeaderItem(7)->setToolTip(
i18n(
"Check to exclude row from calculations"));
110 abInsTable->setEditTriggers(editTrigger);
115 connect(abInsTable, &AbInsTableWidget::leaveTableEvent,
this, &AberrationInspector::leaveTableEvent);
118 sensorGraphic =
new SensorGraphic(abInsTable, m_data.sensorWidth, m_data.sensorHeight, m_data.tileWidth);
122void AberrationInspector::newMousePos(
int row,
int column)
127 for (
int i = 0; i < NUM_TILES; i++)
129 if (TILE_NAME[i] == tile->
text())
132 sensorGraphic->setHighlight(i);
136 if (m_HighlightedRow != -1 && m_HighlightedRow != i)
137 sensorGraphic->repaint();
139 sensorGraphic->show();
140 m_HighlightedRow = row;
145 m_HighlightedRow = -1;
146 sensorGraphic->hide();
150void AberrationInspector::leaveTableEvent()
152 m_HighlightedRow = -1;
154 sensorGraphic->hide();
158void AberrationInspector::onStateChanged(
int state)
168 setExcludeTile(row, checked,
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
170 setTileSelection(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
176void AberrationInspector::onCellChanged(
int row,
int column)
185 int tile = getTileFromRow(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()), row);
187 if (tile >= 0 && tile < NUM_TILES)
189 m_minimum[tile] = value + m_minimum[TILE_CM];
191 setTileSelection(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
195int AberrationInspector::getTileFromRow(TileSelection tileSelection,
int row)
199 if (row < 0 || row >= NUM_TILES)
201 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 called with invalid row %2").
arg(__FUNCTION__).
arg(row);
205 switch(tileSelection)
207 case TileSelection::TILES_ALL:
212 case TileSelection::TILES_OUTER_CORNERS:
217 case TileSelection::TILES_INNER_DIAMOND:
220 tile = (row * 2) + 1;
224 tile = (row * 2) - 1;
228 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 called but TileSelection invalid").
arg(__FUNCTION__);
234void AberrationInspector::setExcludeTile(
int row,
bool checked, TileSelection tileSelection)
236 if (row < 0 || row >= NUM_TILES)
238 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 called with invalid row %2").
arg(__FUNCTION__).
arg(row);
242 int tile = getTileFromRow(tileSelection, row);
243 if (tile >= 0 && tile < NUM_TILES)
244 m_excludeTile[tile] = checked;
247void AberrationInspector::connectSettings()
250 for (
auto &oneWidget : findChildren<QComboBox*>())
254 for (
auto &oneWidget : findChildren<QCheckBox*>())
255 if (oneWidget != abInsSimMode)
259 for (
auto &oneWidget : findChildren<QSplitter*>())
263void AberrationInspector::loadSettings()
269 for (
auto &oneWidget : findChildren<QComboBox*>())
271 key = oneWidget->objectName();
272 value = Options::self()->property(key.
toLatin1());
274 oneWidget->setCurrentText(value.
toString());
276 qCDebug(KSTARS_EKOS_FOCUS) <<
"ComboBox Option" << key <<
"not found!";
280 for (
auto &oneWidget : findChildren<QCheckBox*>())
282 key = oneWidget->objectName();
283 if (key == abInsSimMode->objectName() || key ==
"")
288 value = Options::self()->property(key.
toLatin1());
290 oneWidget->setChecked(value.
toBool());
292 qCDebug(KSTARS_EKOS_FOCUS) <<
"Checkbox Option" << key <<
"not found!";
296 for (
auto &oneWidget : findChildren<QSplitter*>())
298 key = oneWidget->objectName();
299 value = Options::self()->property(key.
toLatin1());
304 oneWidget->restoreState(valueBA);
307 qCDebug(KSTARS_EKOS_FOCUS) <<
"Splitter Option" << key <<
"not found!";
311void AberrationInspector::syncSettings()
320 if ( (cbox = qobject_cast<QComboBox*>(sender())))
325 else if ( (cb = qobject_cast<QCheckBox*>(sender())))
330 else if ( (s = qobject_cast<QSplitter*>(sender())))
338 Options::self()->setProperty(key.
toLatin1(), value);
339 Options::self()->save();
343void AberrationInspector::setTileSelection(TileSelection tileSelection)
346 setupTiles(tileSelection);
348 m_plot->redrawCurve(m_useTile);
354 updateGraphic(tileSelection);
361void AberrationInspector::setupTiles(TileSelection tileSelection)
363 switch(tileSelection)
365 case TileSelection::TILES_ALL:
367 for (
int i = 0; i < NUM_TILES; i++)
371 case TileSelection::TILES_OUTER_CORNERS:
373 m_useTile[TILE_TL] = m_useTile[TILE_TR] = m_useTile[TILE_CM] = m_useTile[TILE_BL] = m_useTile[TILE_BR] =
true;
374 m_useTile[TILE_TM] = m_useTile[TILE_CL] = m_useTile[TILE_CR] = m_useTile[TILE_BM] =
false;
377 case TileSelection::TILES_INNER_DIAMOND:
379 m_useTile[TILE_TL] = m_useTile[TILE_TR] = m_useTile[TILE_BL] = m_useTile[TILE_BR] =
false;
380 m_useTile[TILE_TM] = m_useTile[TILE_CL] = m_useTile[TILE_CM] = m_useTile[TILE_CR] = m_useTile[TILE_BM] =
true;
384 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 called with invalid tile selection %2").
arg(__FUNCTION__).
arg(tileSelection);
389void AberrationInspector::setShowLabels(
bool setting)
391 m_plot->setShowLabels(setting);
395void AberrationInspector::setShowCFZ(
bool setting)
397 m_plot->setShowCFZ(setting);
402void AberrationInspector::setOptCentres(
bool setting)
405 setTileSelection(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
408void AberrationInspector::initAberrationInspector()
411 m_plot->init(m_data.yAxisLabel, m_data.starUnits, m_data.useWeights, abInsShowLabels->isChecked(),
412 abInsShowCFZ->isChecked());
416void AberrationInspector::tableResize()
424void AberrationInspector::fitCurves()
426 curveFitting.reset(
new CurveFitting());
428 const double expected = 0.0;
432 for (
int i = 0; i < m_positions.count(); i++)
436 minPos = maxPos = m_positions[i];
439 minPos = std::min(minPos, m_positions[i]);
440 maxPos = std::max(maxPos, m_positions[i]);
444 for (
int tile = 0; tile < m_measures.count(); tile++)
446 curveFitting->fitCurve(CurveFitting::FittingGoal::BEST, m_positions, m_measures[tile], m_weights[tile], outliers,
447 m_data.curveFit, m_data.useWeights, m_data.optDir);
449 double position = 0.0;
450 double measure = 0.0;
452 bool foundFit = curveFitting->findMinMax(expected,
static_cast<double>(minPos),
static_cast<double>(maxPos), &position,
453 &measure, m_data.curveFit, m_data.optDir);
455 R2 = curveFitting->calculateR2(m_data.curveFit);
457 position = round(position);
458 m_minimum.append(position);
459 m_minMeasure.append(measure);
460 m_fit.append(foundFit);
466 for (
int i = 0; i < m_measures[tile].count(); i++)
471 m_plot->addData(m_positions, m_measures[tile], m_weights[tile], outliers);
473 m_plot->drawCurve(tile, curveFitting.get(), position, measure, foundFit, R2);
475 m_plot->drawMaxMin(tile, position, measure);
478 m_plot->drawCFZ(position, measure, m_data.cfzSteps);
483void AberrationInspector::updateTable()
488 if (abInsTileSelection->currentIndex() == TILES_ALL)
489 abInsTable->setRowCount(NUM_TILES);
491 abInsTable->setRowCount(5);
494 for (
int i = 0; i < NUM_TILES; i++)
503 abInsTable->setItem(rowCounter, 0, tile);
506 abInsTable->setItem(rowCounter, 1, description);
510 abInsTable->setItem(rowCounter, 2, solution);
512 int ticks = m_minimum[i] - m_minimum[TILE_CM];
515 abInsTable->setItem(rowCounter, 3, deltaTicks);
517 int microns = ticks * m_data.focuserStepMicrons;
520 abInsTable->setItem(rowCounter, 4, deltaMicrons);
522 int minNumStars = *std::min_element(m_numStars[i].constBegin(), m_numStars[i].constEnd());
523 int maxNumStars = *std::max_element(m_numStars[i].constBegin(), m_numStars[i].constEnd());
526 abInsTable->setItem(rowCounter, 5, numStars);
530 abInsTable->setItem(rowCounter, 6, R2);
535 checkBox->
setChecked(!m_fit[i] || m_excludeTile[i]);
544 abInsTable->setCellWidget(rowCounter, 7, checkBoxWidget);
552 sensorGraphic->setTiles(m_useTile);
556void AberrationInspector::analyseResults()
561 bool backfocusOK = calcBackfocusDelta(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()), m_backfocus);
565 backfocus->setText(
i18n(
"N/A"));
569 if (m_backfocus < -0.9)
570 side =
i18n(
"Move sensor nearer flattener");
571 else if (m_backfocus > 0.9)
572 side =
i18n(
"Move sensor away from flattener");
573 backfocus->setText(
QString(
"%1μm. %2").arg(m_backfocus, 0,
'f', 0).arg(side));
577 bool tiltOK = calcTilt();
582 lrTilt->setText(
i18n(
"N/A"));
583 tbTilt->setText(
i18n(
"N/A"));
584 totalTilt->setText(
i18n(
"N/A"));
588 lrTilt->setText(
QString(
"%1μm / %2%").arg(m_LRMicrons, 0,
'f', 0).arg(m_LRTilt, 0,
'f', 2));
589 tbTilt->setText(
QString(
"%1μm / %2%").arg(m_TBMicrons, 0,
'f', 0).arg(m_TBTilt, 0,
'f', 2));
590 totalTilt->setText(
QString(
"%1μm / %2%").arg(m_diagonalMicrons, 0,
'f', 0)
591 .arg(m_diagonalTilt, 0,
'f', 2));
595 m_resultsOK = backfocusOK && tiltOK;
602bool AberrationInspector::calcBackfocusDelta(TileSelection tileSelection,
double &backfocusDelta)
604 backfocusDelta = 0.0;
607 if (!m_fit[TILE_CM] || m_excludeTile[TILE_CM])
610 double dist = 0.0, sum = 0.0, counter = 0.0;
612 switch(tileSelection)
614 case TileSelection::TILES_ALL:
616 for (
int i = 0; i < NUM_TILES; i++)
621 if (m_fit[i] && !m_excludeTile[i])
623 dist = getXYTileCentre(
static_cast<tileID
>(i)).length();
624 sum += m_minimum[i] * dist;
633 case TileSelection::TILES_OUTER_CORNERS:
636 if (m_fit[0] && !m_excludeTile[0])
641 if (m_fit[2] && !m_excludeTile[2])
646 if (m_fit[6] && !m_excludeTile[6])
651 if (m_fit[8] && !m_excludeTile[8])
662 case TileSelection::TILES_INNER_DIAMOND:
665 if (m_fit[TILE_TM] && !m_excludeTile[TILE_TM])
667 dist = getXYTileCentre(TILE_TM).length();
668 sum += m_minimum[TILE_TM] * dist;
671 if (m_fit[TILE_CL] && !m_excludeTile[TILE_CL])
673 dist = getXYTileCentre(TILE_CL).length();
674 sum += m_minimum[TILE_CL] * dist;
677 if (m_fit[TILE_CR] && !m_excludeTile[TILE_CR])
679 dist = getXYTileCentre(TILE_CR).length();
680 sum += m_minimum[TILE_CR] * dist;
683 if (m_fit[TILE_BM] && !m_excludeTile[TILE_BM])
685 dist = getXYTileCentre(TILE_BM).length();
686 sum += m_minimum[TILE_BM] * dist;
696 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 called with invalid tile selection %2").
arg(__FUNCTION__).
arg(tileSelection);
700 backfocusDelta = (m_minimum[TILE_CM] - (sum / counter)) * m_data.focuserStepMicrons;
704bool AberrationInspector::calcTilt()
707 if (!m_fit[TILE_CM] || m_excludeTile[TILE_CM])
712 for (
int tile = 0; tile < NUM_TILES; tile++)
713 m_deltas.append((m_minimum[TILE_CM] - m_minimum[tile]) * m_data.focuserStepMicrons);
717 double avLeft, avRight, avTop, avBottom;
718 int tilesL[3] = { 0, 3, 6 };
719 if (!avTiles(tilesL, avLeft))
721 int tilesR[3] = { 2, 5, 8 };
722 if (!avTiles(tilesR, avRight))
724 int tilesT[3] = { 0, 1, 2 };
725 if (!avTiles(tilesT, avTop))
727 int tilesB[3] = { 6, 7, 8 };
728 if(!avTiles(tilesB, avBottom))
731 m_LRMicrons = avLeft - avRight;
732 m_TBMicrons = avTop - avBottom;
733 m_diagonalMicrons = std::hypot(m_LRMicrons, m_TBMicrons);
736 const double LRSpan = (m_data.sensorWidth - m_data.tileWidth) * m_data.pixelSize;
737 const double TBSpan = (m_data.sensorHeight - m_data.tileWidth) * m_data.pixelSize;
740 m_LRTilt = m_LRMicrons / LRSpan * 100.0;
741 m_TBTilt = m_TBMicrons / TBSpan * 100.0;
742 m_diagonalTilt = std::hypot(m_LRTilt, m_TBTilt);
747bool AberrationInspector::avTiles(
int tiles[3],
double &average)
751 for (
int i = 0; i < 3; i++)
753 if (m_useTile[tiles[i]] && m_fit[tiles[i]] && !m_excludeTile[tiles[i]])
755 sum += m_deltas[tiles[i]];
760 average = sum / counter;
761 return (counter > 0);
765void AberrationInspector::initGraphic()
768 m_graphic =
new Q3DSurface();
773 abInsHSplitter =
new QSplitter(abInsVSplitter);
775 abInsHSplitter->addWidget(tableAndResultsWidget);
776 abInsHSplitter->addWidget(widget);
777 hLayout->insertWidget(0, container, 1);
778 auto value = Options::abInsHSplitter();
781 abInsHSplitter->restoreState(valueBA);
787 m_graphic->setSelectionMode(QAbstract3DGraph::SelectionNone);
789 m_graphic->setSelectionMode(QAbstract3DGraph::SelectionItem);
791 m_graphic->setSelectionMode(QAbstract3DGraph::SelectionItemAndColumn | QAbstract3DGraph::SelectionSlice |
792 QAbstract3DGraph::SelectionMultiSeries);
797 m_graphic->activeTheme()->setType(Q3DTheme::Theme(index));
802 m_graphicLabels = setting;
803 updateGraphic(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
808 m_graphicSensor = setting;
809 updateGraphic(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
814 m_graphicPetzvalWire = setting;
815 updateGraphic(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
819 m_graphicPetzvalSurface = setting;
820 updateGraphic(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
826 m_sensor =
new QSurface3DSeries;
827 m_sensorProxy =
new QSurfaceDataProxy();
828 m_sensor->setDataProxy(m_sensorProxy);
829 m_graphic->addSeries(m_sensor);
831 m_petzval =
new QSurface3DSeries;
832 m_petzvalProxy =
new QSurfaceDataProxy();
833 m_petzval->setDataProxy(m_petzvalProxy);
834 m_graphic->addSeries(m_petzval);
836 m_graphic->axisX()->setTitle(
"X Axis (μm) - Sensor Left to Right");
837 m_graphic->axisY()->setTitle(
"Y Axis (μm) - Sensor Top to Bottom");
838 m_graphic->axisZ()->setTitle(
"Z Axis (μm) - Axis of Telescope");
840 m_graphic->axisX()->setLabelFormat(
"%.0f");
841 m_graphic->axisY()->setLabelFormat(
"%.0f");
842 m_graphic->axisZ()->setLabelFormat(
"%.0f");
844 m_graphic->axisX()->setTitleVisible(
true);
845 m_graphic->axisY()->setTitleVisible(
true);
846 m_graphic->axisZ()->setTitleVisible(
true);
848 m_graphic->activeTheme()->setType(Q3DTheme::ThemePrimaryColors);
851 m_graphic->setOrthoProjection(
false);
852 m_graphic->setShadowQuality(QAbstract3DGraph::ShadowQualityNone);
854 m_graphic->setHorizontalAspectRatio(2.0);
858void AberrationInspector::simModeToggled(
bool setting)
861 abInsBackfocusSlider->setEnabled(setting);
862 abInsTiltLRSlider->setEnabled(setting);
863 abInsTiltTBSlider->setEnabled(setting);
867 abInsBackfocusSlider->setRange(0, 10);
868 abInsBackfocusSlider->setValue(0);
869 abInsTiltLRSlider->setRange(0, 10);
870 abInsTiltLRSlider->setValue(0);
871 abInsTiltTBSlider->setRange(0, 10);
872 abInsTiltTBSlider->setValue(0);
876 curveFitting.reset(
new CurveFitting());
881 disconnect(abInsBackfocusSlider, &
QSlider::valueChanged,
this, &AberrationInspector::simBackfocusChanged);
887 abInsBackfocusSlider->setRange(-range, range);
888 int sign = m_backfocus < 0.0 ? -1 : 1;
889 abInsBackfocusSlider->setValue(sign * 5);
890 abInsBackfocusSlider->setTickInterval(1);
891 m_simBackfocus = m_backfocus;
894 abInsTiltLRSlider->setRange(-range, range);
895 sign = m_LRTilt < 0.0 ? -1 : 1;
896 abInsTiltLRSlider->setValue(sign * 5);
897 abInsTiltLRSlider->setTickInterval(1);
898 m_simLRTilt = m_LRTilt;
901 abInsTiltTBSlider->setRange(-range, range);
902 sign = m_TBTilt < 0.0 ? -1 : 1;
903 abInsTiltTBSlider->setValue(sign * 5);
904 abInsTiltTBSlider->setTickInterval(1);
905 m_simTBTilt = m_TBTilt;
912 updateGraphic(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
916void AberrationInspector::updateGraphic(TileSelection tileSelection)
919 bool ok = m_resultsOK;
923 ok = processSensor();
928 processSensorLabels();
931 ok = processPetzval(tileSelection);
937 m_graphic->axisX()->setRange(-m_maxX, m_maxX);
938 m_graphic->axisY()->setRange(-m_maxY, m_maxY);
939 m_graphic->axisZ()->setRange(m_minZ * 1.1, m_maxZ * 1.1);
942 m_graphicSensor ? m_graphic->addSeries(m_sensor) : m_graphic->removeSeries(m_sensor);
945 QSurface3DSeries::DrawFlags petzvalDrawMode { 0 };
946 if (m_graphicPetzvalWire)
947 petzvalDrawMode = petzvalDrawMode | QSurface3DSeries::DrawWireframe;
948 if (m_graphicPetzvalSurface)
949 petzvalDrawMode = petzvalDrawMode | QSurface3DSeries::DrawSurface;
953 m_petzval->setDrawMode(petzvalDrawMode);
954 m_graphic->addSeries(m_petzval);
957 m_graphic->removeSeries(m_petzval);
961 ok ? m_graphic->show() : m_graphic->hide();
965bool AberrationInspector::processSensor()
973 CurveFitting::DataPoint3DT plane;
974 plane.useWeights =
false;
975 for (
int tile = 0; tile < NUM_TILES; tile++)
980 getBSDelta(
static_cast<Ekos::tileID
>(tile)));
981 plane.push_back(tileCentre.
x(), tileCentre.
y(), tileCentre.
z());
983 m_maxX = std::max(m_maxX, tileCentre.
x());
984 m_maxY = std::max(m_maxY, tileCentre.
y());
985 m_maxZ = std::max(m_maxZ, tileCentre.
z());
986 m_minZ = std::min(m_minZ, tileCentre.
z());
989 curveFitting->fitCurve3D(plane, CurveFitting::FOCUS_PLANE);
990 double R2 = curveFitting->calculateR2(CurveFitting::FOCUS_PLANE);
992 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 sensor plane solved R2=%2").
arg(__FUNCTION__).
arg(R2);
997 QSurfaceDataArray *data =
new QSurfaceDataArray;
998 QSurfaceDataRow *dataRow1 =
new QSurfaceDataRow;
999 QSurfaceDataRow *dataRow2 =
new QSurfaceDataRow;
1000 *dataRow1 << getSensorVertex(TILE_TL) << getSensorVertex(TILE_TR);
1001 *dataRow2 << getSensorVertex(TILE_BL) << getSensorVertex(TILE_BR);
1002 *data << dataRow1 << dataRow2;
1003 m_sensorProxy->resetArray(data);
1004 m_sensor->setDrawMode(QSurface3DSeries::DrawSurface);
1008void AberrationInspector::processSensorLabels()
1011 for (
int tile = 0; tile < NUM_TILES; tile++)
1013 if (m_label[tile] ==
nullptr)
1014 m_label[tile] =
new QCustom3DLabel();
1017 m_graphic->removeCustomItem(m_label[tile]);
1018 m_label[tile] =
new QCustom3DLabel();
1020 m_label[tile]->setText(TILE_NAME[tile]);
1021 m_label[tile]->setTextColor(TILE_COLOUR[tile]);
1022 QVector3D pos = getLabelCentre(
static_cast<tileID
>(tile));
1023 m_label[tile]->setPosition(pos);
1025 m_maxX = std::max(m_maxX, pos.
x());
1026 m_maxY = std::max(m_maxY, pos.
y());
1027 m_maxZ = std::max(m_maxZ, pos.
z());
1028 m_minZ = std::min(m_minZ, pos.
z());
1030 QFont font = m_label[tile]->font();
1032 m_label[tile]->setFont(font);
1033 m_label[tile]->setFacingCamera(
true);
1036 for (
int tile = 0; tile < NUM_TILES; tile++)
1038 if (m_useTile[tile] && m_graphicLabels)
1039 m_graphic->addCustomItem(m_label[tile]);
1051bool AberrationInspector::processPetzval(TileSelection tileSelection)
1055 double backfocus = m_simMode ? m_simBackfocus : m_backfocus;
1056 double sign = (backfocus < 0.0) ? -1.0 : 1.0;
1057 backfocus = std::abs(backfocus);
1058 switch (tileSelection)
1060 case TileSelection::TILES_ALL:
1062 for (
int i = 0; i < NUM_TILES; i++)
1066 sum += getXYTileCentre(
static_cast<tileID
>(i)).lengthSquared();
1068 a = sqrt(sum / (8 * backfocus));
1071 case TileSelection::TILES_OUTER_CORNERS:
1073 sum += getXYTileCentre(TILE_TL).lengthSquared() +
1074 getXYTileCentre(TILE_TR).lengthSquared() +
1075 getXYTileCentre(TILE_BL).lengthSquared() +
1076 getXYTileCentre(TILE_BR).lengthSquared();
1077 a = sqrt(sum / (4 * backfocus));
1080 case TileSelection::TILES_INNER_DIAMOND:
1082 sum += getXYTileCentre(TILE_TM).lengthSquared() +
1083 getXYTileCentre(TILE_CL).lengthSquared() +
1084 getXYTileCentre(TILE_CR).lengthSquared() +
1085 getXYTileCentre(TILE_BM).lengthSquared();
1086 a = sqrt(sum / (4 * backfocus));
1090 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 called with invalid tile selection %2").
arg(__FUNCTION__).
arg(tileSelection);
1095 auto *dataArray =
new QSurfaceDataArray;
1096 float x_step = m_data.sensorWidth * m_data.pixelSize * 2.0 / 21.0;
1097 float y_step = m_data.sensorHeight * m_data.pixelSize * 2.0 / 21.0;
1099 m_maxX = std::max(m_maxX,
static_cast<float>(m_data.sensorWidth));
1100 m_maxY = std::max(m_maxY,
static_cast<float>(m_data.sensorHeight));
1103 for (
int j = -10; j < 11; j++)
1105 auto *
newRow =
new QSurfaceDataRow;
1106 float y = y_step * j;
1107 for (
int i = -10; i < 11; i++)
1109 float x = x_step * i;
1110 float z = sign * (pow(x / a, 2.0) + pow(y / a, 2.0));
1111 newRow->append(QSurfaceDataItem({x, y, z}));
1112 if (i == 10 && j == 10)
1114 m_maxZ = std::max(m_maxZ, z);
1115 m_minZ = std::min(m_minZ, z);
1118 dataArray->append(newRow);
1120 m_petzvalProxy->resetArray(dataArray);
1125QVector2D AberrationInspector::getXYTileCentre(tileID tile)
1127 const double halfSW = m_data.sensorWidth * m_data.pixelSize / 2.0;
1128 const double halfSH = m_data.sensorHeight * m_data.pixelSize / 2.0;
1129 const double halfTS = m_data.tileWidth * m_data.pixelSize / 2.0;
1135 double xOffset = 0.0;
1136 double yOffset = 0.0;
1137 if (abInsOptCentres->isChecked())
1139 xOffset = m_tileOffsets[tile].x() * m_data.pixelSize;
1140 yOffset = m_tileOffsets[tile].y() * m_data.pixelSize;
1146 return QVector2D(-(halfSW - halfTS) + xOffset, halfSH - halfTS + yOffset);
1150 return QVector2D(xOffset, halfSH - halfTS + yOffset);
1154 return QVector2D(halfSW - halfTS + xOffset, halfSH - halfTS + yOffset);
1158 return QVector2D(-(halfSW - halfTS) + xOffset, yOffset);
1166 return QVector2D(halfSW - halfTS + xOffset, yOffset);
1170 return QVector2D(-(halfSW - halfTS) + xOffset, -(halfSH - halfTS) + yOffset);
1174 return QVector2D(xOffset, -(halfSH - halfTS) + yOffset);
1178 return QVector2D(halfSW - halfTS + xOffset, -(halfSH - halfTS) + yOffset);
1182 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 called with invalid tile %2").
arg(__FUNCTION__).
arg(tile);
1189QVector3D AberrationInspector::getLabelCentre(tileID tile)
1191 const double halfSW = m_data.sensorWidth * m_data.pixelSize / 2.0;
1192 const double halfSH = m_data.sensorHeight * m_data.pixelSize / 2.0;
1193 const double halfTS = m_data.tileWidth * m_data.pixelSize / 2.0;
1201 point.
setX(-halfSW - halfTS);
1202 point.
setY(halfSH + halfTS);
1207 point.
setY(halfSH + halfTS);
1211 point.
setX(halfSW + halfTS);
1212 point.
setY(halfSH + halfTS);
1216 point.
setX(-halfSW - halfTS);
1226 point.
setX(halfSW + halfTS);
1231 point.
setX(-halfSW - halfTS);
1232 point.
setY(-halfSH - halfTS);
1237 point.
setY(-halfSH - halfTS);
1241 point.
setX(halfSW + halfTS);
1242 point.
setY(-halfSH - halfTS);
1246 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 called with invalid tile %2").
arg(__FUNCTION__).
arg(tile);
1252 return rotatePoint(point);
1258QVector3D AberrationInspector::getSensorVertex(tileID tile)
1260 const double halfSW = m_data.sensorWidth * m_data.pixelSize / 2.0;
1261 const double halfSH = m_data.sensorHeight * m_data.pixelSize / 2.0;
1269 point.
setX(-halfSW);
1279 point.
setX(-halfSW);
1280 point.
setY(-halfSH);
1285 point.
setY(-halfSH);
1289 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 called with invalid tile %2").
arg(__FUNCTION__).
arg(tile);
1295 return rotatePoint(point);
1300double AberrationInspector::getBSDelta(tileID tile)
1302 if (tile == TILE_CM)
1305 return m_deltas[tile] - m_backfocus;
1323 float LtoRAngle, TtoBAngle;
1327 LtoRAngle = std::asin(m_simLRTilt / 100.0);
1328 TtoBAngle = std::asin(m_simTBTilt / 100.0);
1332 LtoRAngle = std::asin(m_LRTilt / 100.0);
1333 TtoBAngle = std::asin(m_TBTilt / 100.0);
1337 QQuaternion totalRotation = yRotation * xRotation;
1342void AberrationInspector::simBackfocusChanged(
int value)
1344 m_simBackfocus = abs(m_backfocus) *
static_cast<double>(value) / 5.0;
1345 updateGraphic(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
1349void AberrationInspector::simLRTiltChanged(
int value)
1351 m_simLRTilt = abs(m_LRTilt) *
static_cast<double>(value) / 5.0;
1352 updateGraphic(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
1356void AberrationInspector::simTBTiltChanged(
int value)
1358 m_simTBTilt = abs(m_TBTilt) *
static_cast<double>(value) / 5.0;
1359 updateGraphic(
static_cast<TileSelection
>(abInsTileSelection->currentIndex()));
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
void valueChanged(int value)
QByteArray fromBase64(const QByteArray &base64, Base64Options options)
QByteArray toBase64(Base64Options options) const const
void stateChanged(int state)
void activated(int index)
void currentIndexChanged(int index)
void setPointSize(int pointSize)
bool setAlignment(QLayout *l, Qt::Alignment alignment)
void append(QList< T > &&value)
QVariant property(const char *name) const const
QObject * sender() const const
bool setProperty(const char *name, QVariant &&value)
QQuaternion fromAxisAndAngle(const QVector3D &axis, float angle)
QVector3D rotatedVector(const QVector3D &vector) const const
QByteArray saveState() const const
void splitterMoved(int pos, int index)
QString arg(Args &&... args) const const
QString fromUtf8(QByteArrayView str)
QString number(double n, char format, int precision)
int toInt(bool *ok, int base) const const
QByteArray toLatin1() const const
QByteArray toUtf8() const const
void setTextAlignment(Qt::Alignment alignment)
QString text() const const
QTestData & newRow(const char *dataTag)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool isValid() const const
bool toBool() const const
int toInt(bool *ok) const const
QString toString() const const