Warning, file /education/kstars/kstars/ekos/focus/aberrationinspector.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-FileCopyrightText: 2023 John Evans <john.e.evans.email@googlemail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <Q3DSurface>
0010 #include <QCustom3DLabel>
0011 
0012 #include "curvefit.h"
0013 #include "ui_aberrationinspector.h"
0014 #include "aberrationinspectorutils.h"
0015 
0016 // The AberrationInspector class manages the Aberration Inspector dialog.
0017 // Settings are managed in a global way, rather than per Optical Train which would be overkill. The approach is the same as Focus
0018 // using loadSettings, connectSettings & syncSettings.
0019 //
0020 // Aberration Inspector uses focus position of different parts of the sensor to examine backfocus and tilt. A single Autofocus run can
0021 // be used as the basis for the analysis.
0022 //
0023 // Note, Aberration Inspector assumes all focus differences between different tiles on the sensor are due to Backfocus and sensor tilt.
0024 // In reality many other aberrations (e.g. collimation, coma, etc.) could contribute to focus differences but are assumed to be negligible.
0025 // If other aberrations are significant then the analysis output of Aberration Inspector is likely to be invalid.
0026 //
0027 // Aberration Inspector can have 2 use cases:
0028 // 1. Analysis mode. Run the inspector and look at the output.
0029 // 2. Use the tool to help with adjustment of Backfocus and / or tilt with a device such as a PhotonCage or Octopi. In this mode, use of the
0030 //    tool will be iterative. Run the tool, look at the output, make an adjustment for Backfocus and / or tilt, rerun the tool and compare
0031 //    the new output. Make a further adjustment and repeat until happy with the output. For this reason, each time Aberration Inspector is
0032 //    run, a new Aberration Inspector Dialog (with incrementing Run number) is launched allowing comparision of results.
0033 //
0034 // To invoke Aberration Inspector:
0035 // 1. Setup focus to give the consistently good focus results. Point to a part of the sky with lots of stars.
0036 // 2. Set the Mosaic Mask on and set it up so that there are sufficient stars in each tile. This is important as each tile
0037 //    will be focused solved individually so there needs to be enough stars in each tile. Increase the tile size to get each tile to cover
0038 //    more of the sensor and therefore contain more stars; but don't overdo it as the bigger the tile the less accurate the results.
0039 // 3. Run Autofocus manually by pressing the Auto Focus button. Note, Aberration Inspector is not run when Focus is run in a sequence.
0040 // 4. Autofocus will run normally but will collect data for Aberration Inspector for each datapoint. If the Focus run isn't good then
0041 //    discard and retry. If basic Autofocus isn't good then Aberration Inspector will not be good.
0042 // 5. When Autofocus completes, the Aberration Inspector dialog is launched.
0043 // 6. To run Aberration Inspector again, simply rerun Autofocus.
0044 //
0045 // The Aberration Inspector dialog has 4 components:
0046 // 1. The v-curves. A curve is drawn for each tile dependent on the user setting of TileSelection. So either 5 or 9 curves are drawn.
0047 //    Like Focus, the v-curve shows measure (e.g. HFR) on the y-axis versus focuser position on the x-axis
0048 // 2. A table of results from the v-curves. A row is displayed per tile showing v-curve solution and delta from central tile
0049 // 3. Analysis of results table. Here the deltas between the solve position for the central tile is compared with other tiles and used
0050 //    to produce numbers for:
0051 //    Backfocus - The idea is that if backfocus is perfect then the average of tile deltas from the centre will be zero.
0052 //    Tilt      - Differences in tile deltas when backfocus is compensated for, are due to tilt. The analyse works on 2 axes of tilt,
0053 //                Left-to-Right and Top-to-Bottom.
0054 // 4. 3D Graphic. This helps to orient the user and explain the results. 2 Surfaces can be displayed:
0055 //    Sensor          - The sensor is drawn as a 3D plane to scale, with the tilt shown on the z-axis. Top, bottom, left and right are labelled.
0056 //    Petzval Surface - This is light surface that comes out of the telescope and hits the sensor. The surface is drawn as a simple,
0057 //                      circularly symmetrical paraboloid. In reality, the light surface coming out of the field flattener may be much more
0058 //                      complex.
0059 //    With the 3D graphic, it is possible to enter simulation mode, and adjust the Backfocus and tilt and see the effect on the Sensor and
0060 //    Petzval surface.
0061 //
0062 
0063 using namespace QtDataVisualization;
0064 
0065 namespace Ekos
0066 {
0067 
0068 class SensorGraphic;
0069 class AberrationInspectorPlot;
0070 
0071 class AberrationInspector : public QDialog, public Ui::aberrationInspectorDialog
0072 {
0073         Q_OBJECT
0074 
0075     public:
0076 
0077         typedef enum { TILES_ALL, TILES_OUTER_CORNERS, TILES_INNER_DIAMOND } TileSelection;
0078         typedef struct
0079         {
0080             int run;
0081             CurveFitting::CurveFit curveFit;
0082             bool useWeights;
0083             CurveFitting::OptimisationDirection optDir;
0084             int sensorWidth;
0085             int sensorHeight;
0086             double pixelSize;
0087             int tileWidth;
0088             double focuserStepMicrons;
0089             QString yAxisLabel;
0090             double starUnits;
0091             double cfzSteps;
0092             bool isPositionBased;
0093         } abInsData;
0094 
0095         /**
0096          * @brief create an AberrationInspector with the associated data
0097          * @param data is a structure describing the curve fitting methods
0098          * @param positions datapoints
0099          * @param measures datapoints for each tile
0100          * @param weights datapoints for each tile
0101          */
0102         AberrationInspector(const abInsData &data, const QVector<int> &positions, const QVector<QVector<double>> &measures,
0103                             const QVector<QVector<double>> &weights, const QVector<QVector<int>> &numStars,
0104                             const QVector<QPoint> &tileCenterOffset);
0105         ~AberrationInspector();
0106 
0107     private slots:
0108         /**
0109          * @brief mouse moved into table event. Used to show sensor graphic widget
0110          * @param row
0111          * @param column
0112          */
0113         void newMousePos(int row, int column);
0114 
0115         /**
0116          * @brief mouse left the table. Used to hide the sensor graphic widget
0117          */
0118         void leaveTableEvent();
0119 
0120         /**
0121          * @brief checkbox state changed event
0122          * @param new state
0123          */
0124         void onStateChanged(int state);
0125 
0126         /**
0127          * @brief table cell changed
0128          * @param new state
0129          */
0130         void onCellChanged(int row, int column);
0131 
0132     private:
0133         /**
0134          * @brief setup elements of the GUI
0135          */
0136         void setupGUI();
0137 
0138         /**
0139          * @brief connect settings in order to persist changes
0140          */
0141         void connectSettings();
0142 
0143         /**
0144          * @brief load persisted settings
0145          */
0146         void loadSettings();
0147 
0148         /**
0149          * @brief persist settings
0150          */
0151         void syncSettings();
0152 
0153         /**
0154          * @brief initialise Aberration Inspector
0155          */
0156         void initAberrationInspector();
0157 
0158         /**
0159          * @brief fit v-curves for each tile and update other widgets with results
0160          */
0161         void fitCurves();
0162 
0163         /**
0164          * @brief initialise the 3D graphic
0165          */
0166         void initGraphic();
0167 
0168         /**
0169          * @brief setTileSelection combobox
0170          * @param tileSelection
0171          */
0172         void setTileSelection(TileSelection tileSelection);
0173 
0174         /**
0175          * @brief setup an array of tiles to use / don't use
0176          * @param tileSelection
0177          */
0178         void setupTiles(TileSelection tileSelection);
0179 
0180         /**
0181          * @brief update table widget as per user selection
0182          */
0183         void updateTable();
0184 
0185         /**
0186          * @brief analyse and display the results for backfocus and tilt
0187          */
0188         void analyseResults();
0189 
0190         /**
0191          * @brief 3D graphic sim mode toggled by user
0192          * @param sim mode on / off
0193          */
0194         void simModeToggled(bool setting);
0195 
0196         /**
0197          * @brief update 3D graphic based on user selection
0198          * @param tileSelection
0199          */
0200         void updateGraphic(TileSelection tileSelection);
0201 
0202         /**
0203          * @brief draw Sensor on 3D graphic
0204          * @return success
0205          */
0206         bool processSensor();
0207 
0208         /**
0209          * @brief draw Sensor Labels on 3D graphic
0210          */
0211         void processSensorLabels();
0212 
0213         /**
0214          * @brief draw Petzval surface (light cone from flattener) on 3D graphic
0215          * @param tileSelection
0216          * @return success
0217          */
0218         bool processPetzval(TileSelection tileSelection);
0219 
0220         /**
0221          * @brief show / hide v-curve solution labels
0222          * @param show / hide setting
0223          */
0224         void setShowLabels(bool setting);
0225 
0226         /**
0227          * @brief show / hide CFZ
0228          * @param show / hide setting
0229          */
0230         void setShowCFZ(bool setting);
0231 
0232         /**
0233          * @brief Optimise tile centres based on weighted star position
0234          * @param setting
0235          */
0236         void setOptCentres(bool setting);
0237 
0238         /**
0239          * @brief resize table based on contents
0240          */
0241         void tableResize();
0242 
0243         /**
0244          * @brief calculate backfocus based on user selection
0245          * @param tileSelection
0246          * @param calculated backfocusDelta
0247          * @return success = true
0248          */
0249         bool calcBackfocusDelta(TileSelection tileSelection, double &backfocusDelta);
0250 
0251         /**
0252          * @brief calculate tilt based on user selection
0253          * @return success = true
0254          */
0255         bool calcTilt();
0256 
0257         /**
0258          * @brief calculates average of 3 tile values
0259          * @param tiles to average
0260          * @param retured tile average
0261          * @return success = true
0262          */
0263         bool avTiles(int tiles[3], double &average);
0264 
0265         /**
0266          * @brief set exclude tiles vector
0267          * @param row
0268          * @param checked
0269          * @param tile selection
0270          */
0271         void setExcludeTile(int row, bool checked, TileSelection tileSelection);
0272 
0273         /**
0274          * @brief get tile from table row
0275          * @param tileSelection
0276          * @param row
0277          * @return tile
0278          */
0279         int getTileFromRow(TileSelection tileSelection, int row);
0280 
0281         /**
0282          * @brief get the X,Y centre of the tile
0283          * @param tile
0284          * @return 2D vector of tile centre
0285          */
0286         QVector2D getXYTileCentre(tileID tile);
0287 
0288         /**
0289          * @brief get the label position for the passed in tile
0290          * @param tile
0291          * @return 3D vector of label position
0292          */
0293         QVector3D getLabelCentre(tileID tile);
0294 
0295         /**
0296          * @brief get the sensor vertex nearest the passed in tile
0297          * @param tile
0298          * @return 3D vector of sensor vertex
0299          */
0300         QVector3D getSensorVertex(tileID tile);
0301 
0302         /**
0303          * @brief get backspace adapted delta the passed in tile
0304          * @param tile
0305          * @return backspace adapted delta
0306          */
0307         double getBSDelta(tileID tile);
0308         QVector3D rotatePoint(QVector3D point);
0309 
0310         /**
0311          * @brief simulation of backfocus changed
0312          * @param value of slider
0313          */
0314         void simBackfocusChanged(int value);
0315 
0316         /**
0317          * @brief simulation of L-R tilt changed
0318          * @param value of slider
0319          */
0320         void simLRTiltChanged(int value);
0321 
0322         /**
0323          * @brief simulation of T-B tilt changed
0324          * @param value of slider
0325          */
0326         void simTBTiltChanged(int value);
0327 
0328         abInsData m_data;
0329         QVector<int> m_positions;
0330         QVector<QVector<double>> m_measures;
0331         QVector<QVector<double>> m_weights;
0332         QVector<QVector<int>> m_numStars;
0333         QVector<QPoint> m_tileOffsets;
0334 
0335         // Which tiles to use
0336         bool m_useTile[NUM_TILES] = { false, false, false, false, false, false, false, false, false };
0337         bool m_excludeTile[NUM_TILES] = { false, false, false, false, false, false, false, false, false };
0338 
0339         // Table
0340         SensorGraphic *sensorGraphic { nullptr };
0341         int m_HighlightedRow { -1 };
0342 
0343         // Curve fitting
0344         std::unique_ptr<CurveFitting> curveFitting;
0345         QVector<int> m_minimum;
0346         QVector<double> m_minMeasure;
0347         QVector<bool> m_fit;
0348         QVector<double> m_R2;
0349 
0350         // Analysis - the folowing members are in microns
0351         double m_backfocus = 0.0;
0352         QVector<double> m_deltas;
0353         double m_LRMicrons = 0.0;
0354         double m_TBMicrons = 0.0;
0355         double m_diagonalMicrons = 0.0;
0356         // Tilts are in % slope
0357         double m_LRTilt = 0.0;
0358         double m_TBTilt = 0.0;
0359         double m_diagonalTilt = 0.0;
0360         bool m_resultsOK = false;
0361 
0362         // Graphic simulation variables
0363         bool m_simMode { false };
0364         double m_simBackfocus { 0 };
0365         double m_simLRTilt { 0 };
0366         double m_simTBTilt { 0 };
0367         float m_maxX { 0.0 };
0368         float m_maxY { 0.0 };
0369         float m_minZ { 0.0 };
0370         float m_maxZ { 0.0 };
0371 
0372         // Plot widget
0373         AberrationInspectorPlot *m_plot;
0374 
0375         // Graphic
0376         Q3DSurface *m_graphic = nullptr;
0377         QSurface3DSeries *m_sensor = nullptr;
0378         QSurface3DSeries *m_petzval = nullptr;
0379         QSurfaceDataProxy *m_sensorProxy = nullptr;
0380         QSurfaceDataProxy *m_petzvalProxy = nullptr;
0381         QCustom3DLabel *m_label[NUM_TILES] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
0382         bool m_graphicLabels { true };
0383         bool m_graphicSensor { true };
0384         bool m_graphicPetzvalWire { true };
0385         bool m_graphicPetzvalSurface { false };
0386 };
0387 
0388 }