Kstars

aberrationinspectorplot.cpp
1/*
2 SPDX-FileCopyrightText: 2023 John Evans <john.e.evans.email@googlemail.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "aberrationinspectorplot.h"
8#include "curvefit.h"
9#include "klocalizedstring.h"
10
11namespace Ekos
12{
13
14#define DEFAULT_BASIC_FONT_SIZE 10
15
16AberrationInspectorPlot::AberrationInspectorPlot(QWidget *parent) : QCustomPlot (parent)
17{
18 setBackground(QBrush(Qt::black));
19
20 xAxis->setBasePen(QPen(Qt::white, 1));
21 yAxis->setBasePen(QPen(Qt::white, 1));
22
23 xAxis->setTickPen(QPen(Qt::white, 1));
24 yAxis->setTickPen(QPen(Qt::white, 1));
25
26 xAxis->setSubTickPen(QPen(Qt::white, 1));
27 yAxis->setSubTickPen(QPen(Qt::white, 1));
28
29 xAxis->setTickLabelColor(Qt::white);
30 yAxis->setTickLabelColor(Qt::white);
31
32 xAxis->setLabelColor(Qt::white);
33 yAxis->setLabelColor(Qt::white);
34
35 xAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
36 yAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
37 xAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
38 yAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
39 xAxis->grid()->setZeroLinePen(Qt::NoPen);
40 yAxis->grid()->setZeroLinePen(Qt::NoPen);
41
42 setInteractions(QCP::iRangeZoom);
43 setInteraction(QCP::iRangeDrag, true);
44
55
56 this->setAutoAddPlottableToLegend(true);
57 for (int i = 0; i < NUM_TILES; i++)
58 {
59 m_graph[i] = addGraph();
60 m_graph[i]->setLineStyle(QCPGraph::lsLine);
61 m_graph[i]->setPen(QPen(QColor(TILE_COLOUR[i]), 2, Qt::SolidLine));
62 m_graph[i]->setScatterStyle(shapes[i]);
63 m_graph[i]->setName(TILE_NAME[i]);
64
65 // Store the auto generated legends array for later manipulation
66 m_legendItems[i] = this->legend->item(i);
67 }
68
69 this->setAutoAddPlottableToLegend(false);
70 for (int i = 0; i < NUM_TILES; i++)
71 {
72 // Add focus point graphs
73 focusPoint[i] = addGraph();
74 focusPoint[i]->setLineStyle(QCPGraph::lsImpulse);
75 focusPoint[i]->setPen(QPen(QColor(TILE_COLOUR[i]), 2, Qt::SolidLine));
76 focusPoint[i]->setScatterStyle(QCPScatterStyle(shapes[i], TILE_COLOUR[i], TILE_COLOUR[i], 10));
77 }
78
79 // determine font size
80 if (parent != nullptr)
81 setBasicFontSize(parent->font().pointSize());
82 else
83 setBasicFontSize(DEFAULT_BASIC_FONT_SIZE);
84
85 connect(this, &QCustomPlot::mouseMove, [this](QMouseEvent * event)
86 {
87 double key = xAxis->pixelToCoord(event->localPos().x());
88 if (xAxis->range().contains(key))
89 {
90 QCPGraph *graph = qobject_cast<QCPGraph *>(plottableAt(event->pos(), false));
91
92 if (graph)
93 {
94 for (int i = 0; i < NUM_TILES; i++)
95 {
96 if (graph == focusPoint[i])
97 {
98 if (focusPoint[i]->visible())
99 {
100 int positionKey = focusPoint[i]->findBegin(key);
101 double focusPosition = focusPoint[i]->dataMainKey(positionKey);
102 double focusMeasure = focusPoint[i]->dataMainValue(positionKey);
104 event->globalPos(),
105 i18nc("Graphics tooltip; %2 is tile code; %3 is tile name, %4 is Focus Position; %5 is Focus Measure;",
106 "<style>table { background-color: white;}</style>"
107 "<font color='%1'><table>"
108 "<tr><td>Tile: </td><td>%2 (%3)</td></tr>"
109 "<tr><td>Pos: </td><td>%4</td></tr>"
110 "<tr><td>Val: </td><td>%5</td></tr>"
111 "</table></font>",
112 TILE_COLOUR[i],
113 TILE_NAME[i], TILE_LONGNAME[i],
114 QString::number(focusPosition, 'f', 0),
115 QString::number(focusMeasure, 'g', 3)));
116 }
117 break;
118 }
119 }
120 }
121 }
122 });
123}
124
125void AberrationInspectorPlot::init(QString yAxisLabel, double starUnits, bool useWeights, bool showLabels, bool showCFZ)
126{
127 Q_UNUSED(useWeights);
128
129 yAxis->setLabel(yAxisLabel);
130 m_starUnits = starUnits;
131 m_showLabels = showLabels;
132 m_showCFZ = showCFZ;
133 for (int i = 0; i < NUM_TILES; i++)
134 {
135 m_graph[i]->data()->clear();
136 focusPoint[i]->data().clear();
137 focusPoint[i]->setData(QVector<double> {}, QVector<double> {});
138 }
139 // Displat the legend
140 this->legend->setVisible(true);
141}
142
143void AberrationInspectorPlot::setAxes(const int tile)
144{
145 if (tile == -1)
146 {
147 // Recalculate axes based on current setting of member variables
148 const double xborder = (m_maxPosition - m_minPosition) / 10.0;
149 xAxis->setRange(m_minPosition - xborder, m_maxPosition + xborder);
150
151 const double yborder = (m_maxMeasure - m_minMeasure) / 10.0;
152 yAxis->setRange(m_minMeasure - yborder, m_maxMeasure + yborder);
153 return;
154 }
155 // x-range - since its the same for each curve only do it once
156 if (tile == 0)
157 {
158 if (m_positions.empty())
159 return;
160
161 m_minPosition = *std::min_element(m_positions.constBegin(), m_positions.constEnd());
162 m_maxPosition = *std::max_element(m_positions.constBegin(), m_positions.constEnd());
163 const double border = (m_maxPosition - m_minPosition) / 10.0;
164 xAxis->setRange(m_minPosition - border, m_maxPosition + border);
165 }
166
167 // y range
168 if (m_measures[tile].empty())
169 return;
170
171 if (tile == 0)
172 {
173 m_minMeasure = *std::min_element(m_measures[tile].constBegin(), m_measures[tile].constEnd());
174 m_maxMeasure = *std::max_element(m_measures[tile].constBegin(), m_measures[tile].constEnd());
175 }
176 else
177 {
178 m_minMeasure = std::min(m_minMeasure, *std::min_element(m_measures[tile].constBegin(), m_measures[tile].constEnd()));
179 m_maxMeasure = std::max(m_maxMeasure, *std::max_element(m_measures[tile].constBegin(), m_measures[tile].constEnd()));
180 }
181 const double border = (m_maxMeasure - m_minMeasure) / 10.0;
182 yAxis->setRange(m_minMeasure - border, m_maxMeasure + border);
183}
184
185void AberrationInspectorPlot::addData(QVector<int> positions, QVector<double> measures, QVector<double> weights,
186 QVector<bool> outliers)
187{
188 Q_UNUSED(weights);
189 Q_UNUSED(outliers);
190 if (m_positions.count() == 0)
191 m_positions.append(positions);
192
193 // Convert the incoming measures (e.g. pixels) to display measures (e.g. arc-secs)
194 QVector<double> displayMeasures;
195 for (int i = 0; i < measures.count(); i++)
196 displayMeasures.push_back(getDisplayMeasure(measures[i]));
197 m_measures.append(displayMeasures);
198
199 setAxes(m_measures.count() - 1);
200}
201
202void AberrationInspectorPlot::drawMaxMin(int tile, double solutionPosition, double solutionMeasure)
203{
204 // Do nothing for invalid positions
205 if (solutionPosition <= 0)
206 return;
207
208 double displayMeasure = getDisplayMeasure(solutionMeasure);
209 m_minMeasure = std::min(m_minMeasure, displayMeasure);
210 m_maxMeasure = std::max(m_maxMeasure, displayMeasure);
211
212 focusPoint[tile]->addData(solutionPosition, displayMeasure);
213 m_labelItems[tile] = new QCPItemText(this);
214 m_labelItems[tile]->setPositionAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
215 m_labelItems[tile]->setColor(TILE_COLOUR[tile]);
216 m_labelItems[tile]->setBrush(Qt::white);
217 m_labelItems[tile]->setPen(Qt::NoPen);
218 m_labelItems[tile]->setFont(QFont(font().family(), (int) std::round(0.8 * basicFontSize())));
219 m_labelItems[tile]->position->setType(QCPItemPosition::ptPlotCoords);
220 m_labelItems[tile]->setText(QString::number(solutionPosition, 'f', 0));
221 m_labelItems[tile]->position->setCoords(solutionPosition, displayMeasure * 0.8);
222 m_labelItems[tile]->setVisible(m_showLabels);
223}
224
225void AberrationInspectorPlot::drawCFZ(double solutionPosition, double solutionMeasure, int cfzSteps)
226{
227 // Do nothing for invalid positions
228 if (solutionPosition <= 0 || solutionMeasure <= 0)
229 return;
230
231 if (!m_CFZ)
232 m_CFZ = new QCPItemBracket(this);
233
234 m_CFZ->left->setType(QCPItemPosition::ptPlotCoords);
235 m_CFZ->right->setType(QCPItemPosition::ptPlotCoords);
236
237 double y = m_minMeasure * 0.95;
238
239 m_CFZ->left->setCoords(solutionPosition + cfzSteps / 2.0, y);
240 m_CFZ->right->setCoords(solutionPosition - cfzSteps / 2.0, y);
241 m_CFZ->setLength(15);
242 m_CFZ->setAntialiased(false);
243 m_CFZ->setPen(QPen(QColor(Qt::yellow)));
244 m_CFZ->setVisible(m_showCFZ);
245}
246
247void AberrationInspectorPlot::setShowCFZ(bool setting)
248{
249 m_showCFZ = setting;
250 if (m_CFZ)
251 m_CFZ->setVisible(setting);
252}
253
254void AberrationInspectorPlot::setShowLabels(bool setting)
255{
256 m_showLabels = setting;
257 for (int tile = 0; tile < NUM_TILES; tile++)
258 {
259 if (m_labelItems[tile])
260 m_labelItems[tile]->setVisible(setting);
261 }
262}
263
264void AberrationInspectorPlot::drawCurve(int tile, Ekos::CurveFitting *curveFit, int maxmin, double measure, bool fit,
265 double R2)
266{
267 Q_UNUSED(fit);
268 Q_UNUSED(R2);
269
270 if (curveFit == nullptr)
271 return;
272
273 if (!fit)
274 return;
275
276 // Extend max/mins if appropriate
277 m_minPosition = std::min(m_minPosition, maxmin);
278 m_maxPosition = std::max(m_maxPosition, maxmin);
279 m_minMeasure = std::min(m_minMeasure, measure);
280 m_maxMeasure = std::max(m_maxMeasure, measure);
281 setAxes(-1);
282
283 if (m_graph[tile] != nullptr)
284 {
285 m_graph[tile]->data()->clear();
286 QCPRange range = xAxis->range();
287 double interval = range.size() / 40.0;
288
289 for(double x = range.lower; x < range.upper; x += interval)
290 {
291 double y = getDisplayMeasure(curveFit->f(x));
292 m_graph[tile]->addData(x, y);
293 }
294 }
295}
296
297// Show only the graph elements relevant to the passed in useTile array
298void AberrationInspectorPlot::redrawCurve(bool useTile[NUM_TILES])
299{
300 for (int i = 0; i < NUM_TILES; i++)
301 {
302 // Show / hide the appropriate curves
303 if (m_graph[i])
304 m_graph[i]->setVisible(useTile[i]);
305
306 // Only display legend entries for displayed graphs
307 this->legend->item(i)->setVisible(useTile[i]);
308
309 // Show / hide the focus point and text labels appopriate to the selected curves
310 if (focusPoint[i])
311 focusPoint[i]->setVisible(useTile[i]);
312 if (m_labelItems[i])
313 m_labelItems[i]->setVisible(useTile[i] && m_showLabels);
314 }
315}
316
317void AberrationInspectorPlot::setBasicFontSize(int basicFontSize)
318{
319 m_basicFontSize = basicFontSize;
320
321 // Axis Labels Settings
322 yAxis->setLabelFont(QFont(font().family(), basicFontSize));
323 xAxis->setTickLabelFont(QFont(font().family(), (int) std::round(0.9 * basicFontSize)));
324 yAxis->setTickLabelFont(QFont(font().family(), (int) std::round(0.9 * basicFontSize)));
325}
326
327// Internally calculations are done in units of pixels for HFR and FWHM
328// If user preference is arcsecs then convert measures for display purposes.
329double AberrationInspectorPlot::getDisplayMeasure(const double measure)
330{
331 return measure * m_starUnits;
332}
333
334}
A plottable representing a graph in a plot.
@ lsLine
data points are connected by a straight line
@ lsImpulse
each data point is represented by a line parallel to the value axis, which reaches from the data poin...
A bracket for referencing/highlighting certain parts in the plot.
@ ptPlotCoords
Dynamic positioning at a plot coordinate defined by two axes (see setAxes).
A text label.
Represents the range an axis is encompassing.
double size() const
Represents the visual appearance of scatter points.
@ ssSquare
\enumimage{ssSquare.png} a square
@ ssDisc
\enumimage{ssDisc.png} a circle which is filled with the pen's color (not the brush as with ssCircle)
@ ssPlus
\enumimage{ssPlus.png} a plus
@ ssDiamond
\enumimage{ssDiamond.png} a diamond
@ ssStar
\enumimage{ssStar.png} a star with eight arms, i.e. a combination of cross and plus
@ ssTriangleInverted
\enumimage{ssTriangleInverted.png} an equilateral triangle, standing on corner
@ ssTriangle
\enumimage{ssTriangle.png} an equilateral triangle, standing on baseline
@ ssCircle
\enumimage{ssCircle.png} a circle
@ ssCross
\enumimage{ssCross.png} a cross
The central class of the library. This is the QWidget which displays the plot and interacts with the ...
void mouseMove(QMouseEvent *event)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:79
@ iRangeDrag
0x001 Axis ranges are draggable (see QCPAxisRect::setRangeDrag, QCPAxisRect::setRangeDragAxes)
@ iRangeZoom
0x002 Axis ranges are zoomable with the mouse wheel (see QCPAxisRect::setRangeZoom,...
qsizetype count() const const
void push_back(parameter_type value)
QString number(double n, char format, int precision)
AlignVCenter
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect, int msecDisplayTime)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 4 2024 12:01:02 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.