Kstars

starprofileviewer.cpp
1/*
2 SPDX-FileCopyrightText: 2017 Robert Lancaster <rlancaste@gmail.com>
3
4 Based on the QT Surface Example https://doc.qt.io/qt-5.9/qtdatavisualization-surface-example.html
5 and the QT Bars Example https://doc-snapshots.qt.io/qt5-5.9/qtdatavisualization-bars-example.html
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9
10#include "starprofileviewer.h"
11#include <KLocalizedString>
12
13using namespace QtDataVisualization;
14
15StarProfileViewer::StarProfileViewer(QWidget *parent) : QDialog(parent)
16{
17
18#ifdef Q_OS_OSX
19 setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
20#endif
21
22 m_graph = new Q3DBars();
23 m_pixelValueAxis = m_graph->valueAxis();
24 m_xPixelAxis = m_graph->columnAxis();
25 m_yPixelAxis = m_graph->rowAxis();
26
27 m_pixelValueAxis->setTitle(i18n("Pixel Values"));
28 m_pixelValueAxis->setLabelAutoRotation(30.0f);
29 m_pixelValueAxis->setTitleVisible(true);
30
31 m_xPixelAxis->setTitle(i18n("Horizontal"));
32 m_xPixelAxis->setLabelAutoRotation(30.0f);
33 m_xPixelAxis->setTitleVisible(true);
34 m_yPixelAxis->setTitle(i18n("Vertical"));
35 m_yPixelAxis->setLabelAutoRotation(30.0f);
36 m_yPixelAxis->setTitleVisible(true);
37
38 m_3DPixelSeries = new QBar3DSeries;
39
40 m_3DPixelSeries->setMesh(QAbstract3DSeries::MeshBevelBar);
41 m_graph->addSeries(m_3DPixelSeries);
42
43 m_graph->activeTheme()->setLabelBackgroundEnabled(false);
44
45 QWidget *container = QWidget::createWindowContainer(m_graph);
46
47 if (!m_graph->hasContext()) {
49 msgBox.setText(i18n("Couldn't initialize the OpenGL context."));
50 msgBox.exec();
51 return;
52 }
53
54 QSize screenSize = m_graph->screen()->size();
55 container->setMinimumSize(QSize(300, 500));
56 container->setMaximumSize(screenSize);
59
60 this->setWindowTitle(i18nc("@title:window", "View Star Profile"));
61
62 QVBoxLayout *mainLayout = new QVBoxLayout(this);
66 rightWidget->setVisible(false);
67 QVBoxLayout *rightLayout = new QVBoxLayout(rightWidget);
69
70 topLayout->addWidget(container, 1);
71 topLayout->addWidget(rightWidget);
72 mainLayout->addLayout(topLayout);
73 mainLayout->addLayout(controlsLayout);
74 controlsLayout->setAlignment(Qt::AlignLeft);
75
76 maxValue=new QLabel(this);
77 maxValue->setToolTip(i18n("Maximum Value on the graph"));
78 cutoffValue=new QLabel(this);
79 cutoffValue->setToolTip(i18n("Cuttoff Maximum for eliminating hot pixels and bright stars."));
80
82 toggleEnableCutoff->setToolTip(i18n("Enable or Disable the Max Value Cutoff"));
83 toggleEnableCutoff->setText(i18n("Toggle Cutoff"));
84 toggleEnableCutoff->setChecked(false);
85
86 blackPointSlider=new QSlider( Qt::Vertical, this);
87 blackPointSlider->setToolTip(i18n("Sets the Minimum Value on the graph"));
88 sliderLayout->addWidget(blackPointSlider,0,0);
89 sliderLayout->addWidget(new QLabel(i18n("Min")),1,0);
90
91 whitePointSlider=new QSlider( Qt::Vertical, this);
92 whitePointSlider->setToolTip(i18n("Sets the Maximum Value on the graph"));
93 sliderLayout->addWidget(whitePointSlider,0,1);
94 sliderLayout->addWidget(new QLabel(i18n("Max")),1,1);
95
96 cutoffSlider=new QSlider( Qt::Vertical, this);
97 cutoffSlider->setToolTip(i18n("Sets the Cuttoff Maximum for eliminating hot pixels and bright stars."));
98 sliderLayout->addWidget(cutoffSlider,0,2);
99 sliderLayout->addWidget(new QLabel(i18n("Cut")),1,2);
100 cutoffSlider->setEnabled(false);
101
102 minValue = new QLabel(this);
103 minValue->setToolTip(i18n("Minimum Value on the graph"));
104
105 autoScale = new QCheckBox(this);
106 autoScale->setText(i18n("AutoScale"));
107 autoScale->setToolTip(i18n("Automatically scales the sliders for the subFrame.\nUncheck to leave them unchanged when you pan around."));
108 autoScale->setChecked(true);
109
110 showScaling = new QPushButton(this);
111 showScaling->setIcon(QIcon::fromTheme("transform-move-vertical"));
112 showScaling->setCheckable(true);
113 showScaling->setMaximumSize(22, 22);
114 showScaling->setAttribute(Qt::WA_LayoutUsesWidgetRect);
115 showScaling->setToolTip(i18n("Hides and shows the scaling side panel"));
116 showScaling->setChecked(false);
117
118 rightLayout->addWidget(toggleEnableCutoff);
119 rightLayout->addWidget(cutoffValue);
120 rightLayout->addWidget(maxValue);
121 rightLayout->addLayout(sliderLayout);
122 rightLayout->addWidget(minValue);
123 rightLayout->addWidget(autoScale);
124
125 selectionType = new QComboBox(this);
126 selectionType->setToolTip(i18n("Changes the type of selection"));
127 selectionType->addItem(i18n("Item"));
128 selectionType->addItem(i18n("Horizontal"));
129 selectionType->addItem(i18n("Vertical"));
130 selectionType->setCurrentIndex(0);
131
132 sliceB = new QPushButton(this);
133 sliceB->setIcon(QIcon::fromTheme("view-object-histogram-linear"));
134 sliceB->setCheckable(true);
135 sliceB->setMaximumSize(22, 22);
136 sliceB->setAttribute(Qt::WA_LayoutUsesWidgetRect);
137 sliceB->setToolTip(i18n("Toggles the slice view when horizontal or vertical items are selected"));
138 sliceB->setCheckable(true);
139 sliceB->setChecked(false);
140 sliceB->setEnabled(false);
141 sliceB->setDefault(false);
142
143 showCoordinates = new QPushButton(this);
144 showCoordinates->setIcon(QIcon::fromTheme("coordinate"));
145 showCoordinates->setCheckable(true);
146 showCoordinates->setMaximumSize(22, 22);
147 showCoordinates->setAttribute(Qt::WA_LayoutUsesWidgetRect);
148 showCoordinates->setToolTip(i18n("Shows the x, y coordinates of star centers in the frame"));
149 showCoordinates->setChecked(false);
150
151 HFRReport = new QPushButton(this);
152 HFRReport->setToolTip(i18n("Shows the HFR of stars in the frame"));
153 HFRReport->setIcon(QIcon::fromTheme("tool-measure"));
154 HFRReport->setCheckable(true);
155 HFRReport->setMaximumSize(22, 22);
156 HFRReport->setAttribute(Qt::WA_LayoutUsesWidgetRect);
157 HFRReport->setChecked(true);
158
159 reportBox = new QLabel(this);
160
161 showPeakValues = new QPushButton(this);
162 showPeakValues->setIcon(QIcon::fromTheme("kruler-east"));
163 showPeakValues->setCheckable(true);
164 showPeakValues->setMaximumSize(22, 22);
165 showPeakValues->setAttribute(Qt::WA_LayoutUsesWidgetRect);
166 showPeakValues->setToolTip(i18n("Shows the peak values of star centers in the frame"));
167 showPeakValues->setChecked(true);
168
169 sampleSize = new QComboBox(this);
170 sampleSize->setToolTip(i18n("Changes the sample size shown in the graph"));
171 sampleSize->addItem(QString::number(16));
172 sampleSize->addItem(QString::number(32));
173 sampleSize->addItem(QString::number(64));
174 sampleSize->addItem(QString::number(128));
175 sampleSize->addItem(QString::number(256));
176 sampleSize->addItem(QString::number(512));
177 sampleSize->setCurrentIndex(3);
178 sampleSize->setVisible(false);
179
180 zoomView = new QComboBox(this);
181 zoomView->setToolTip(i18n("Zooms the view to preset locations."));
182 zoomView->addItem(i18n("ZoomTo"));
183 zoomView->addItem(i18n("Front"));
184 zoomView->addItem(i18n("Front High"));
185 zoomView->addItem(i18n("Overhead"));
186 zoomView->addItem(i18n("Iso. L"));
187 zoomView->addItem(i18n("Iso. R"));
188 zoomView->addItem(i18n("Selected"));
189 zoomView->setCurrentIndex(0);
190
192 selectorsVisible->setIcon(QIcon::fromTheme("adjustlevels"));
193 selectorsVisible->setCheckable(true);
194 selectorsVisible->setMaximumSize(22, 22);
196 selectorsVisible->setToolTip(i18n("Hides and shows the Vertical and Horizontal Selection Sliders"));
197 selectorsVisible->setChecked(false);
198
199 controlsLayout->addWidget(sampleSize);
200 controlsLayout->addWidget(selectionType);
202 controlsLayout->addWidget(sliceB);
203 controlsLayout->addWidget(showScaling);
204 //bottomLayout->addWidget(barSpacing);
205 controlsLayout->addWidget(zoomView);
206 //bottomLayout->addWidget(color);
207 controlsLayout->addWidget(showCoordinates);
208 controlsLayout->addWidget(HFRReport);
209 controlsLayout->addWidget(showPeakValues);
210 controlsLayout->addWidget(reportBox);
211
215 mainLayout->addWidget(bottomSliderWidget);
216 bottomSliderWidget->setVisible(false);
217
218 verticalSelector = new QSlider(Qt::Horizontal, this);
219 verticalSelector->setToolTip(i18n("Selects the Vertical Value"));
220 horizontalSelector = new QSlider(Qt::Horizontal, this);
221 horizontalSelector->setToolTip(i18n("Selects the Horizontal Value"));
222
223 bottomSliders->addWidget(new QLabel(i18n("Vertical: ")), 0, 0);
224 bottomSliders->addWidget(verticalSelector, 0, 1);
225 bottomSliders->addWidget(new QLabel(i18n("Horizontal: ")), 1, 0);
226 bottomSliders->addWidget(horizontalSelector, 1, 1);
227
230 mainLayout->addWidget(bottomControlsWidget);\
231 bottomControlsWidget->setVisible(false);
232
233 exploreMode = new QPushButton(this);
234 exploreMode->setIcon(QIcon::fromTheme("visibility"));
235 exploreMode->setCheckable(true);
236 exploreMode->setMaximumSize(22, 22);
237 exploreMode->setAttribute(Qt::WA_LayoutUsesWidgetRect);
238 exploreMode->setToolTip(i18n("Zooms automatically as the sliders change"));
239 exploreMode->setChecked(true);
240
241 QDial *barSpacing=new QDial(this);
242 barSpacing->setMinimum(0);
243 barSpacing->setMaximum(100);
244 barSpacing->setValue(50);
245 barSpacing->setMaximumSize(32, 32);
246 barSpacing->setWrapping(false);
247 m_graph->setBarSpacing(QSizeF(0.5,0.5));
248
249 QComboBox *color = new QComboBox(this);
250 color->setToolTip(i18n("Changes the color scheme"));
251
252 QLinearGradient grGtoR(50, 1, 0, 0);
253 grGtoR.setColorAt(1.0, Qt::darkGreen);
254 grGtoR.setColorAt(0.5, Qt::yellow);
255 grGtoR.setColorAt(0.2, Qt::red);
256 grGtoR.setColorAt(0.0, Qt::darkRed);
257 QPixmap pm(50, 10);
258 QPainter pmp(&pm);
259 pmp.setPen(Qt::NoPen);
260 pmp.setBrush(QBrush(grGtoR));
261 pmp.drawRect(0, 0, 50, 10);
262 color->addItem("");
263 color->setItemIcon(0,QIcon(pm));
264
265 QLinearGradient grBtoY(50, 1, 0, 0);
266 grBtoY.setColorAt(1.0, Qt::black);
267 grBtoY.setColorAt(0.67, Qt::blue);
268 grBtoY.setColorAt(0.33, Qt::red);
269 grBtoY.setColorAt(0.0, Qt::yellow);
270 pmp.setBrush(QBrush(grBtoY));
271 pmp.drawRect(0, 0, 50, 10);
272 color->addItem("");
273 color->setItemIcon(1,QIcon(pm));
274
275 color->setIconSize(QSize(50, 10));
276 color->setCurrentIndex(0);
277 color->setMaximumWidth(80);
278
279 pixelReport = new QLabel("", bottomControlsWidget);
280
281 bottomControlLayout->addWidget(exploreMode);
283 bottomControlLayout->addWidget(color);
284 bottomControlLayout->addWidget(pixelReport);
285
286 QObject::connect(selectionType, SIGNAL(currentIndexChanged(int)),
287 this, SLOT(changeSelectionType(int)));
288 QObject::connect(zoomView, SIGNAL(currentIndexChanged(int)),
289 this, SLOT(zoomViewTo(int)));
291 this, &StarProfileViewer::toggleSlice);
292 QObject::connect(showCoordinates, &QCheckBox::toggled,
293 this, &StarProfileViewer::updateHFRandPeakSelection);
295 this, &StarProfileViewer::updateHFRandPeakSelection);
296 QObject::connect(showPeakValues, &QCheckBox::toggled,
297 this, &StarProfileViewer::updateHFRandPeakSelection);
298 QObject::connect(blackPointSlider, &QSlider::valueChanged,
299 this, &StarProfileViewer::updateVerticalAxis);
300 QObject::connect(whitePointSlider, &QSlider::valueChanged,
301 this, &StarProfileViewer::updateVerticalAxis);
303 this, &StarProfileViewer::updateDisplayData);
305 this, &StarProfileViewer::updateScale);
308 QObject::connect(sampleSize, SIGNAL(currentIndexChanged(QString)),
309 this, SLOT(updateSampleSize(QString)));
310 QObject::connect(color, SIGNAL(currentIndexChanged(int)),
311 this, SLOT(updateColor(int)));
312 QObject::connect(verticalSelector, &QSlider::valueChanged,
313 this, &StarProfileViewer::changeSelection);
314 QObject::connect(horizontalSelector, &QSlider::valueChanged,
315 this, &StarProfileViewer::changeSelection);
321 this, &StarProfileViewer::toggleCutoffEnabled);
323 this, &StarProfileViewer::updateSelectorBars);
325 this, &StarProfileViewer::updateBarSpacing);
326
327 m_graph->activeTheme()->setType(Q3DTheme::Theme(3)); //Stone Moss
328
329 setGreenToRedGradient();
330
331 m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
332 m_graph->scene()->activeCamera()->setTarget(QVector3D(0.0f, 0.0f, 0.0f));
333 m_graph->scene()->activeCamera()->setZoomLevel(110);
334
335 //Note: This is to prevent a button from being called the default button
336 //and then executing when the user hits the enter key such as when on a Text Box
337 #ifdef Q_OS_OSX
339 for (auto &button : qButtons)
340 button->setAutoDefault(false);
341 #endif
342
343 show();
344}
345
346StarProfileViewer::~StarProfileViewer()
347{
348 delete m_graph;
349}
350
351void StarProfileViewer::loadData(QSharedPointer<FITSData> data, QRect sub, QList<Edge *> centers)
352{
353 if(data)
354 {
355 imageData = data;
356 subFrame=sub;
357 starCenters=centers;
358
359 switch (data->getStatistics().dataType)
360 {
361 case TBYTE:
363 break;
364
365 case TSHORT:
367 break;
368
369 case TUSHORT:
371 break;
372
373 case TLONG:
375 break;
376
377 case TULONG:
379 break;
380
381 case TFLOAT:
383 break;
384
385 case TLONGLONG:
387 break;
388
389 case TDOUBLE:
391 break;
392 }
393
394 updateScale();
395
396 // Add data to the data proxy (the data proxy assumes ownership of it)
397 // We will retain a copy of the data set so that we can update the display
398 updateDisplayData();
399
400 updateHFRandPeakSelection();
401
402 horizontalSelector->setRange(0, subFrame.width()-1);
403 verticalSelector->setRange(0, subFrame.width()-1); //Width and height are the same
404 }
405}
406
407template <typename T>
408void StarProfileViewer::loadDataPrivate()
409{
410 // Create data arrays
411 dataSet = new QBarDataArray;
413 dataSet->reserve(subFrame.height());
416
417 auto *buffer = reinterpret_cast<T const *>(imageData->getImageBuffer());
418 int width = imageData->width();
419
420 for (int j = subFrame.y(); j < subFrame.y() + subFrame.height(); j++)
421 {
422 if( j % 10 == 0 )
424 else
425 rowLabels << "";
426 dataRow = new QBarDataRow(subFrame.width());
427 int x = 0;
428 for (int i = subFrame.x(); i < subFrame.x() + subFrame.width(); i++)
429 {
430 if( i % 10 == 0 )
432 else
433 columnLabels << "";
434 if( i > 0 && i < imageData->width() && j > 0 && j < imageData->height())
435 (*dataRow)[x].setValue(*(buffer + i + j * width));
436 x++;
437 }
438 dataSet->insert(0, dataRow); //Note the row axis is displayed in the opposite direction of the y axis in the image.
439 }
440
441 std::reverse(rowLabels.begin(), rowLabels.end());
442
443 m_3DPixelSeries->dataProxy()->setRowLabels(rowLabels);
444 m_3DPixelSeries->dataProxy()->setColumnLabels(columnLabels);
445}
446
447void StarProfileViewer::toggleCutoffEnabled(bool enable)
448{
449 cutoffSlider->setEnabled(enable);
450 cutOffEnabled = enable;
451 updateDisplayData();
452}
453
454void StarProfileViewer::updateScale()
455{
456
457 //We need to disconnect these so that changing their ranges doesn't affect things
459 this, &StarProfileViewer::updateVerticalAxis);
461 this, &StarProfileViewer::updateVerticalAxis);
463 this, &StarProfileViewer::updateDisplayData);
464
466 double dataMin, dataMax;
467 float min, max;
468 getSubFrameMinMax(&subFrameMin, &subFrameMax, &dataMin, &dataMax);
469
470 int sliderDataMin = convertToSliderValue(dataMin) - 1; //Expands the slider range a little beyond the max and min values
471 int sliderDataMax = convertToSliderValue(dataMax) + 1;
472
473 if(autoScale->isChecked())
474 {
475 min = subFrameMin;
476 max = subFrameMax;
477 int sliderMin = convertToSliderValue(min) - 1; //Expands the slider range a little beyond the max and min values
478 int sliderMax = convertToSliderValue(max) + 1;
479 blackPointSlider->setRange(sliderMin, sliderMax);
480 blackPointSlider->setTickInterval((sliderMax - sliderMin) / 100);
481 whitePointSlider->setRange(sliderMin, sliderMax);
482 whitePointSlider->setTickInterval((sliderMax - sliderMin) / 100);
483 cutoffSlider->setRange(sliderMin, sliderDataMax);
484 cutoffSlider->setTickInterval((sliderDataMax - sliderMin) / 100);
485 blackPointSlider->setValue(sliderMin);
486 whitePointSlider->setValue(sliderMax);
487 cutoffSlider->setValue(sliderDataMax);
488 }
489 else
490 {
491 min = convertFromSliderValue(blackPointSlider->value());
492 max = convertFromSliderValue(whitePointSlider->value());
493 blackPointSlider->setRange(sliderDataMin, sliderDataMax);
494 blackPointSlider->setTickInterval((sliderDataMax - sliderDataMin) / 100);
495 whitePointSlider->setRange(sliderDataMin, sliderDataMax);
496 whitePointSlider->setTickInterval((sliderDataMax - sliderDataMin) / 100);
497 cutoffSlider->setRange(sliderDataMin, sliderDataMax);
498 cutoffSlider->setTickInterval((sliderDataMax - sliderDataMin) / 100);
499
500 }
501 m_pixelValueAxis->setRange(min, max);
502
503 if(cutOffEnabled)
504 cutoffValue->setText(i18n("Cut: %1", roundf(convertFromSliderValue(cutoffSlider->value()) * 100) / 100));
505 else
506 cutoffValue->setText("Cut Disabled");
507
508 if(max < 10 )
509 {
510 m_pixelValueAxis->setLabelFormat(QString(QStringLiteral("%.3f ")));
511 m_3DPixelSeries->setItemLabelFormat(QString(QStringLiteral("%.3f ")));
512 maxValue->setText(i18n("Max: %1", roundf(max * 100) / 100));
513 minValue->setText(i18n("Min: %1", roundf(min * 100) / 100));
514 }
515 else
516 {
517 m_pixelValueAxis->setLabelFormat(QString(QStringLiteral("%.0f ")));
518 m_3DPixelSeries->setItemLabelFormat(QString(QStringLiteral("%.0f ")));
519 maxValue->setText(i18n("Max: %1", max));
520 minValue->setText(i18n("Min: %1", min));
521 }
522
523 QObject::connect(blackPointSlider, &QSlider::valueChanged,
524 this, &StarProfileViewer::updateVerticalAxis);
525 QObject::connect(whitePointSlider, &QSlider::valueChanged,
526 this, &StarProfileViewer::updateVerticalAxis);
528 this, &StarProfileViewer::updateDisplayData);
529}
530
531void StarProfileViewer::updateBarSpacing(int value)
532{
533 float spacing = (float)value/100.0;
534 m_graph->setBarSpacing(QSizeF(spacing, spacing));
535}
536
537void StarProfileViewer::zoomViewTo(int where)
538{
539 if(where > 6) //One of the star centers
540 {
541 int star = where - 7;
542 int x = starCenters[star]->x - subFrame.x();
543 int y = subFrame.height() - (starCenters[star]->y - subFrame.y());
544 m_graph->primarySeries()->setSelectedBar(QPoint( y , x )); //Note row, column y, x
545 where = 6; //This is so it will zoom to the target.
546 }
547
548 switch (where) {
549 case 0: //Zoom To
550 break;
551
552 case 1: //Front
553 m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
554 m_graph->scene()->activeCamera()->setTarget(QVector3D(0.0f, 0.0f, 0.0f));
555 m_graph->scene()->activeCamera()->setZoomLevel(110);
556 zoomView->setCurrentIndex(0);
557 break;
558
559 case 2: //Front High
560 m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFrontHigh);
561 m_graph->scene()->activeCamera()->setTarget(QVector3D(0.0f, 0.0f, 0.0f));
562 m_graph->scene()->activeCamera()->setZoomLevel(110);
563 zoomView->setCurrentIndex(0);
564 break;
565
566 case 3: //Overhead
567 m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetDirectlyAbove);
568 m_graph->scene()->activeCamera()->setTarget(QVector3D(0.0f, 0.0f, 0.0f));
569 m_graph->scene()->activeCamera()->setZoomLevel(110);
570 zoomView->setCurrentIndex(0);
571 break;
572
573 case 4: //Isometric L
574 m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetIsometricLeftHigh);
575 m_graph->scene()->activeCamera()->setTarget(QVector3D(0.0f, 0.0f, 0.0f));
576 m_graph->scene()->activeCamera()->setZoomLevel(110);
577 zoomView->setCurrentIndex(0);
578 break;
579
580 case 5: //Isometric R
581 m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetIsometricRightHigh);
582 m_graph->scene()->activeCamera()->setTarget(QVector3D(0.0f, 0.0f, 0.0f));
583 m_graph->scene()->activeCamera()->setZoomLevel(110);
584 zoomView->setCurrentIndex(0);
585 break;
586
587 case 6: //Selected Item
588 {
589 QPoint selectedBar = m_graph->selectedSeries()
590 ? m_graph->selectedSeries()->selectedBar()
593 {
594 QVector3D target;
595 float xMin = m_graph->columnAxis()->min();
596 float xRange = m_graph->columnAxis()->max() - xMin;
597 float zMin = m_graph->rowAxis()->min();
598 float zRange = m_graph->rowAxis()->max() - zMin;
599 target.setX((selectedBar.y() - xMin) / xRange * 2.0f - 1.0f);
600 target.setZ((selectedBar.x() - zMin) / zRange * 2.0f - 1.0f);
601
602 qreal endAngleX = qAtan(qreal(target.z() / target.x())) / M_PI * -180.0 + 90.0;
603 if (target.x() > 0.0f)
604 endAngleX -= 180.0f;
605 float barValue = m_graph->selectedSeries()->dataProxy()->itemAt(selectedBar.x(),
606 selectedBar.y())->value();
607 float endAngleY = 60.0f;
608 float zoom = 150 * 1/qSqrt(barValue / convertFromSliderValue(whitePointSlider->value()));
609 m_graph->scene()->activeCamera()->setCameraPosition(endAngleX, endAngleY, zoom);
610 m_graph->scene()->activeCamera()->setTarget(target);
611
612
613 }
614 zoomView->setCurrentIndex(0);
615 break;
616 }
617
618
619 default:
620 zoomView->setCurrentIndex(0);
621 break;
622 }
623}
624
625void StarProfileViewer::changeSelectionType(int type)
626{
627 switch (type) {
628 case 0:
629 m_graph->setSelectionMode(QAbstract3DGraph::SelectionItem);
630 m_graph->scene()->setSlicingActive(false);
631 sliceB->setEnabled(false);
632 break;
633
634 case 1:
635 m_graph->setSelectionMode(QAbstract3DGraph::SelectionItemAndRow);
636 sliceB->setEnabled(true);
637 break;
638
639 case 2:
640 m_graph->setSelectionMode(QAbstract3DGraph::SelectionItemAndColumn);
641 sliceB->setEnabled(true);
642 break;
643
644 default:
645 break;
646 }
647}
648
649void StarProfileViewer::changeSelection()
650{
651 int x = horizontalSelector->value();
652 int y = verticalSelector->value();
653 m_graph->primarySeries()->setSelectedBar(QPoint( y , x )); //Note row, column y, x
654 if(exploreMode->isChecked())
655 zoomViewTo(6); //Zoom to SelectedItem
656 updatePixelReport();
657}
658
659void StarProfileViewer::updatePixelReport()
660{
661 int x = horizontalSelector->value();
662 int y = verticalSelector->value();
663 //They need to be shifted to the location of the subframe
664 x += subFrame.x();
665 y = (subFrame.height() - 1 - y) + subFrame.y(); //Note: Y is in reverse order on the graph.
666 float barValue = getImageDataValue(x, y);
667 pixelReport->setText(i18n("Selected Pixel: (%1, %2): %3", x + 1, y + 1, roundf(barValue * 100) / 100)); //Have to add 1 because humans start counting at 1
668
669}
670
671
672void StarProfileViewer::updateSelectorBars(QPoint position)
673{
674 //Note that we need to disconnect and then reconnect to avoid triggering changeSelection
676 this, &StarProfileViewer::changeSelection);
677 QObject::disconnect(horizontalSelector, &QSlider::valueChanged,
678 this, &StarProfileViewer::changeSelection);
679
680 //Note row, column y, x
681 verticalSelector->setValue(position.x());
682 horizontalSelector->setValue(position.y());
683 updatePixelReport();
684
685 QObject::connect(verticalSelector, &QSlider::valueChanged,
686 this, &StarProfileViewer::changeSelection);
687 QObject::connect(horizontalSelector, &QSlider::valueChanged,
688 this, &StarProfileViewer::changeSelection);
689}
690
691void StarProfileViewer::updateSampleSize(const QString &text)
692{
693 emit sampleSizeUpdated(text.toInt());
694}
695
696void StarProfileViewer::enableTrackingBox(bool enable)
697{
698 sampleSize->setVisible(enable);
699}
700
701void StarProfileViewer::updateDisplayData()
702{
703 if(cutOffEnabled)
704 cutoffValue->setText(i18n("Cut: %1", roundf(convertFromSliderValue(cutoffSlider->value()) * 100) / 100));
705 else
706 cutoffValue->setText(i18n("Cut Disabled"));
707 if(dataSet != nullptr)
708 {
710 displayDataSet->reserve(dataSet->size());
711
712 for (int row = 0; row < dataSet->size(); row++)
713 {
714 QBarDataRow *dataRow = dataSet->at(row);
716 newDataRow = new QBarDataRow(dataRow->size());
717 for (int column = 0; column < dataRow->size(); column++)
718 {
719 if(cutOffEnabled && dataRow->value(column).value() > convertFromSliderValue(cutoffSlider->value()))
720 (*newDataRow)[column].setValue(0.0f);
721 else
722 (*newDataRow)[column].setValue(dataRow->value(column).value());
723 }
724 displayDataSet->append(newDataRow);
725
726 }
727 m_3DPixelSeries->dataProxy()->resetArray(displayDataSet); //, m_3DPixelSeries->dataProxy()->rowLabels(), m_3DPixelSeries->dataProxy()->columnLabels()
728 }
729}
730
731void StarProfileViewer::getSubFrameMinMax(float *subFrameMin, float *subFrameMax, double *dataMin, double *dataMax)
732{
733 imageData->getMinMax(dataMin,dataMax);
734
735 //Backwards so that we can find the min and max in subFrame
738
739 switch (imageData->getStatistics().dataType)
740 {
741 case TBYTE:
743 break;
744
745 case TSHORT:
747 break;
748
749 case TUSHORT:
751 break;
752
753 case TLONG:
755 break;
756
757 case TULONG:
759 break;
760
761 case TFLOAT:
763 break;
764
765 case TLONGLONG:
767 break;
768
769 case TDOUBLE:
771 break;
772 }
773}
774
775template <typename T>
776void StarProfileViewer::getSubFrameMinMax(float *subFrameMin, float *subFrameMax)
777{
778 auto *buffer = reinterpret_cast<T const *>(imageData->getImageBuffer());
779 T min = std::numeric_limits<T>::max();
780 T max = std::numeric_limits<T>::min();
781 int width = imageData->width();
782 for (int y = subFrame.y(); y < subFrame.y() + subFrame.height(); y++)
783 {
784 for (int x = subFrame.x(); x < subFrame.x() + subFrame.width(); x++)
785 {
786 if( x > 0 && x < imageData->width() && y > 0 && y < imageData->height())
787 {
788 min = qMin(min, *(buffer + x + y * width));
789 max = qMax(max, *(buffer + x + y * width));
790 }
791 }
792 }
793
794 *subFrameMin = min;
795 *subFrameMax = max;
796}
797
798template <typename T>
799float StarProfileViewer::getImageDataValue(int x, int y)
800{
801 if(!imageData)
802 return 0;
803 auto *buffer = reinterpret_cast<T const *>(imageData->getImageBuffer());
804 return (float) buffer[y * imageData->width() + x];
805}
806
807
808
809float StarProfileViewer::getImageDataValue(int x, int y)
810{
811 switch (imageData->getStatistics().dataType)
812 {
813 case TBYTE:
815 break;
816
817 case TSHORT:
819 break;
820
821 case TUSHORT:
823 break;
824
825 case TLONG:
827 break;
828
829 case TULONG:
831 break;
832
833 case TFLOAT:
835 break;
836
837 case TLONGLONG:
839 break;
840
841 case TDOUBLE:
843 break;
844
845 default:
846 return 0;
847 break;
848 }
849}
850
851void StarProfileViewer::toggleSlice()
852{
853 if(m_graph->selectionMode() == QAbstract3DGraph::SelectionItemAndRow || m_graph->selectionMode() == QAbstract3DGraph::SelectionItemAndColumn)
854 {
855
856 if(m_graph->scene()->isSlicingActive())
857 {
858 m_graph->scene()->setSlicingActive(false);
859 }
860 else
861 {
862 QPoint selectedBar = m_graph->selectedSeries()
863 ? m_graph->selectedSeries()->selectedBar()
866 m_graph->scene()->setSlicingActive(true);
867 }
868 }
869}
870
871void StarProfileViewer::updateVerticalAxis()
872{
873 float blackPoint = convertFromSliderValue(blackPointSlider->value());
874 float whitePoint = convertFromSliderValue(whitePointSlider->value());
875 m_pixelValueAxis->setRange(blackPoint, whitePoint);
876 maxValue->setText(i18n("Max: %1", roundf(whitePoint * 100) / 100));
877 minValue->setText(i18n("Min: %1", roundf(blackPoint * 100) / 100));
878}
879
880void StarProfileViewer::updateHFRandPeakSelection()
881{
882 m_graph->removeCustomItems();
883
884 reportBox->setText("");
886
887 //Removes all the stars from the combo box.
888 while(zoomView->count() > 7)
889 zoomView->removeItem(7);
890
891 for (int i = 0; i < starCenters.count(); i++)
892 {
893 int x = starCenters[i]->x;
894 int row = x - subFrame.x();
895 int y = starCenters[i]->y;
896 int col = subFrame.height() - (y - subFrame.y());
897 if(subFrame.contains(x,y)){
898 double newHFR = imageData->getHFR(x,y);
899 int value = getImageDataValue(x, y);
901 label->setFacingCamera(true);
902 QString labelString = i18n("Star %1: ", i + 1);
903 if(showCoordinates->isChecked())
904 {
905 labelString = labelString + i18n("(%1, %2) ", x + 1, y + 1);
906 }
907 if(HFRReport->isChecked())
908 {
909 labelString = labelString + i18n("HFR: %1 ", roundf(newHFR * 100) / 100);
910 }
911 if(showPeakValues->isChecked())
912 {
913 labelString = labelString + i18n("Peak: %1", value);
914
915 }
916 if(showCoordinates->isChecked() || HFRReport->isChecked() || showPeakValues->isChecked())
917 {
918 if (!reportString.isEmpty())
919 reportString += '\n';
920
921 reportString += labelString;
922 label->setText(labelString);
923 label->setPosition(QVector3D(row, value, col));
924 label->setScaling(QVector3D(1.0f, 1.0f, 1.0f));
925 m_graph->addCustomItem(label);
926 }
927 //Adds this star to the combo box.
928 zoomView->addItem(i18n("Star %1", i + 1));
929 }
930 }
931 if (!reportString.isEmpty())
932 {
933 reportBox->setText(reportString);
934 }
935}
936
937void StarProfileViewer::updateColor(int selection)
938{
939 switch (selection) {
940 case 0:
941 setGreenToRedGradient();
942 break;
943
944 case 1:
945 setBlackToYellowGradient();
946 break;
947
948 default:
949 break;
950 }
951}
952
953void StarProfileViewer::setBlackToYellowGradient()
954{
956 gr.setColorAt(0.0, Qt::black);
957 gr.setColorAt(0.33, Qt::blue);
958 gr.setColorAt(0.67, Qt::red);
959 gr.setColorAt(1.0, Qt::yellow);
960
962 highGr.setColorAt(0.0, Qt::yellow);
963 highGr.setColorAt(1.0, Qt::yellow);
964
966 sinHighGr.setColorAt(0.0, Qt::red);
967 sinHighGr.setColorAt(1.0, Qt::red);
968
969 m_3DPixelSeries->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
970 m_3DPixelSeries->setBaseGradient(gr);
971 m_3DPixelSeries->setSingleHighlightGradient(sinHighGr);
972 m_3DPixelSeries->setMultiHighlightGradient(highGr);
973}
974
975void StarProfileViewer::setGreenToRedGradient()
976{
978 gr.setColorAt(0.0, Qt::darkGreen);
979 gr.setColorAt(0.5, Qt::yellow);
980 gr.setColorAt(0.8, Qt::red);
981 gr.setColorAt(1.0, Qt::darkRed);
982
984 highGr.setColorAt(0.0, Qt::black);
985 highGr.setColorAt(1.0, Qt::black);
986
988 sinHighGr.setColorAt(0.0, Qt::red);
989 sinHighGr.setColorAt(1.0, Qt::red);
990
991 m_3DPixelSeries->setBaseGradient(gr);
992 m_3DPixelSeries->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
993 m_3DPixelSeries->setSingleHighlightGradient(sinHighGr);
994 m_3DPixelSeries->setMultiHighlightGradient(highGr);
995}
996
997//Multiplying by 1000000 will take care of preserving decimals in an int slider
998//The sqrt function makes the slider non-linear, emphasising the lower values
999//Note that it is actually multiplying the number on the slider by 1000 or so since it is square rooted.
1000
1001int StarProfileViewer::convertToSliderValue(float value)
1002{
1003 return (int) qSqrt((value * 1000000.0));
1004}
1005
1006float StarProfileViewer::convertFromSliderValue(int value)
1007{
1008 return qPow((float)value,2) / 1000000.0;
1009}
1010
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
QString label(StandardShortcut id)
bool isChecked() const const
void toggled(bool checked)
void setRange(int min, int max)
void setValue(int)
void valueChanged(int value)
void addLayout(QLayout *layout, int stretch)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
void addItem(const QIcon &icon, const QString &text, const QVariant &userData)
void setCurrentIndex(int index)
void setIconSize(const QSize &size)
void removeItem(int index)
void setItemIcon(int index, const QIcon &icon)
QIcon fromTheme(const QString &name)
void setText(const QString &)
qsizetype count() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
int x() const const
int y() const const
bool contains(const QPoint &point, bool proper) const const
int height() const const
int width() const const
int x() const const
int y() const const
void setTickInterval(int ti)
QString number(double n, char format, int precision)
int toInt(bool *ok, int base) const const
AlignLeft
StrongFocus
darkGreen
Vertical
WA_LayoutUsesWidgetRect
void setX(float x)
void setZ(float z)
float x() const const
float z() const const
QWidget * createWindowContainer(QWindow *window, QWidget *parent, Qt::WindowFlags flags)
void setEnabled(bool)
void setFocusPolicy(Qt::FocusPolicy policy)
void setMaximumSize(const QSize &)
void setMaximumWidth(int maxw)
void setMinimumSize(const QSize &)
void setSizePolicy(QSizePolicy)
void setToolTip(const QString &)
virtual void setVisible(bool visible)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:48:26 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.