Kstars

starprofileviewer.cpp
1 /*
2  SPDX-FileCopyrightText: 2017 Robert Lancaster <[email protected]>
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 
13 using namespace QtDataVisualization;
14 
15 StarProfileViewer::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()) {
48  QMessageBox msgBox;
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);
58  container->setFocusPolicy(Qt::StrongFocus);
59 
60  this->setWindowTitle(i18nc("@title:window", "View Star Profile"));
61 
62  QVBoxLayout *mainLayout = new QVBoxLayout(this);
63  QHBoxLayout *topLayout = new QHBoxLayout();
64  QHBoxLayout *controlsLayout = new QHBoxLayout();
65  QWidget* rightWidget = new QWidget();
66  rightWidget->setVisible(false);
67  QVBoxLayout *rightLayout = new QVBoxLayout(rightWidget);
68  QGridLayout *sliderLayout = new QGridLayout();
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 
81  QCheckBox *toggleEnableCutoff= new QCheckBox(this);
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 
191  QPushButton *selectorsVisible = new QPushButton(this);
192  selectorsVisible->setIcon(QIcon::fromTheme("adjustlevels"));
193  selectorsVisible->setCheckable(true);
194  selectorsVisible->setMaximumSize(22, 22);
195  selectorsVisible->setAttribute(Qt::WA_LayoutUsesWidgetRect);
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);
201  controlsLayout->addWidget(selectorsVisible);
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 
212  QWidget *bottomSliderWidget= new QWidget(this);
213  QGridLayout *bottomSliders = new QGridLayout(bottomSliderWidget);
214  bottomSliderWidget->setLayout(bottomSliders);
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 
228  QWidget *bottomControlsWidget= new QWidget(this);
229  QHBoxLayout *bottomControlLayout = new QHBoxLayout(bottomControlsWidget);
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);
282  bottomControlLayout->addWidget(barSpacing);
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);
306  QObject::connect(showScaling, &QCheckBox::toggled,
307  rightWidget, &QWidget::setVisible);
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);
316  QObject::connect(selectorsVisible, &QCheckBox::toggled,
317  bottomSliderWidget, &QWidget::setVisible);
318  QObject::connect(selectorsVisible, &QCheckBox::toggled,
319  bottomControlsWidget, &QWidget::setVisible);
320  QObject::connect(toggleEnableCutoff, &QCheckBox::toggled,
321  this, &StarProfileViewer::toggleCutoffEnabled);
322  QObject::connect(m_3DPixelSeries, &QBar3DSeries::selectedBarChanged,
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
338  QList<QPushButton *> qButtons = findChildren<QPushButton *>();
339  for (auto &button : qButtons)
340  button->setAutoDefault(false);
341  #endif
342 
343  show();
344 }
345 
346 StarProfileViewer::~StarProfileViewer()
347 {
348  delete m_graph;
349 }
350 
351 void 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:
362  loadDataPrivate<uint8_t>();
363  break;
364 
365  case TSHORT:
366  loadDataPrivate<int16_t>();
367  break;
368 
369  case TUSHORT:
370  loadDataPrivate<uint16_t>();
371  break;
372 
373  case TLONG:
374  loadDataPrivate<int32_t>();
375  break;
376 
377  case TULONG:
378  loadDataPrivate<uint32_t>();
379  break;
380 
381  case TFLOAT:
382  loadDataPrivate<float>();
383  break;
384 
385  case TLONGLONG:
386  loadDataPrivate<int64_t>();
387  break;
388 
389  case TDOUBLE:
390  loadDataPrivate<double>();
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 
407 template <typename T>
408 void StarProfileViewer::loadDataPrivate()
409 {
410  // Create data arrays
411  dataSet = new QBarDataArray;
412  QBarDataRow *dataRow;
413  dataSet->reserve(subFrame.height());
414  QStringList rowLabels;
415  QStringList columnLabels;
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 )
423  rowLabels << QString::number(j);
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 )
431  columnLabels << QString::number(i);
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 
447 void StarProfileViewer::toggleCutoffEnabled(bool enable)
448 {
449  cutoffSlider->setEnabled(enable);
450  cutOffEnabled = enable;
451  updateDisplayData();
452 }
453 
454 void StarProfileViewer::updateScale()
455 {
456 
457  //We need to disconnect these so that changing their ranges doesn't affect things
458  QObject::disconnect(blackPointSlider, &QSlider::valueChanged,
459  this, &StarProfileViewer::updateVerticalAxis);
460  QObject::disconnect(whitePointSlider, &QSlider::valueChanged,
461  this, &StarProfileViewer::updateVerticalAxis);
463  this, &StarProfileViewer::updateDisplayData);
464 
465  float subFrameMin, subFrameMax;
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 
531 void StarProfileViewer::updateBarSpacing(int value)
532 {
533  float spacing = (float)value/100.0;
534  m_graph->setBarSpacing(QSizeF(spacing, spacing));
535 }
536 
537 void 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()
591  : QBar3DSeries::invalidSelectionPosition();
592  if (selectedBar != QBar3DSeries::invalidSelectionPosition())
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 
625 void 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 
649 void 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 
659 void 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 
672 void StarProfileViewer::updateSelectorBars(QPoint position)
673 {
674  //Note that we need to disconnect and then reconnect to avoid triggering changeSelection
675  QObject::disconnect(verticalSelector, &QSlider::valueChanged,
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 
691 void StarProfileViewer::updateSampleSize(const QString &text)
692 {
693  emit sampleSizeUpdated(text.toInt());
694 }
695 
696 void StarProfileViewer::enableTrackingBox(bool enable)
697 {
698  sampleSize->setVisible(enable);
699 }
700 
701 void 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  {
709  QBarDataArray *displayDataSet = new QBarDataArray;
710  displayDataSet->reserve(dataSet->size());
711 
712  for (int row = 0; row < dataSet->size(); row++)
713  {
714  QBarDataRow *dataRow = dataSet->at(row);
715  QBarDataRow *newDataRow;
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 
731 void 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
736  *subFrameMin = *dataMax;
737  *subFrameMax = *dataMin;
738 
739  switch (imageData->getStatistics().dataType)
740  {
741  case TBYTE:
742  getSubFrameMinMax<uint8_t>(subFrameMin, subFrameMax);
743  break;
744 
745  case TSHORT:
746  getSubFrameMinMax<int16_t>(subFrameMin, subFrameMax);
747  break;
748 
749  case TUSHORT:
750  getSubFrameMinMax<uint16_t>(subFrameMin, subFrameMax);
751  break;
752 
753  case TLONG:
754  getSubFrameMinMax<int32_t>(subFrameMin, subFrameMax);
755  break;
756 
757  case TULONG:
758  getSubFrameMinMax<uint32_t>(subFrameMin, subFrameMax);
759  break;
760 
761  case TFLOAT:
762  getSubFrameMinMax<float>(subFrameMin, subFrameMax);
763  break;
764 
765  case TLONGLONG:
766  getSubFrameMinMax<int64_t>(subFrameMin, subFrameMax);
767  break;
768 
769  case TDOUBLE:
770  getSubFrameMinMax<double>(subFrameMin, subFrameMax);
771  break;
772  }
773 }
774 
775 template <typename T>
776 void 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 
798 template <typename T>
799 float 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 
809 float StarProfileViewer::getImageDataValue(int x, int y)
810 {
811  switch (imageData->getStatistics().dataType)
812  {
813  case TBYTE:
814  return getImageDataValue<uint8_t>(x, y);
815  break;
816 
817  case TSHORT:
818  return getImageDataValue<int16_t>(x, y);
819  break;
820 
821  case TUSHORT:
822  return getImageDataValue<uint16_t>(x, y);
823  break;
824 
825  case TLONG:
826  return getImageDataValue<int32_t>(x, y);
827  break;
828 
829  case TULONG:
830  return getImageDataValue<uint32_t>(x, y);
831  break;
832 
833  case TFLOAT:
834  return getImageDataValue<float>(x, y);
835  break;
836 
837  case TLONGLONG:
838  return getImageDataValue<int64_t>(x, y);
839  break;
840 
841  case TDOUBLE:
842  return getImageDataValue<double>(x, y);
843  break;
844 
845  default:
846  return 0;
847  break;
848  }
849 }
850 
851 void 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()
864  : QBar3DSeries::invalidSelectionPosition();
865  if (selectedBar != QBar3DSeries::invalidSelectionPosition())
866  m_graph->scene()->setSlicingActive(true);
867  }
868  }
869 }
870 
871 void 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 
880 void StarProfileViewer::updateHFRandPeakSelection()
881 {
882  m_graph->removeCustomItems();
883 
884  reportBox->setText("");
885  QString reportString = "";
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);
900  QCustom3DLabel *label = new QCustom3DLabel();
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 
937 void 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 
953 void StarProfileViewer::setBlackToYellowGradient()
954 {
955  QLinearGradient gr;
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 
961  QLinearGradient highGr;
962  highGr.setColorAt(0.0, Qt::yellow);
963  highGr.setColorAt(1.0, Qt::yellow);
964 
965  QLinearGradient sinHighGr;
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 
975 void StarProfileViewer::setGreenToRedGradient()
976 {
977  QLinearGradient gr;
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 
983  QLinearGradient highGr;
984  highGr.setColorAt(0.0, Qt::black);
985  highGr.setColorAt(1.0, Qt::black);
986 
987  QLinearGradient sinHighGr;
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 
1001 int StarProfileViewer::convertToSliderValue(float value)
1002 {
1003  return (int) qSqrt((value * 1000000.0));
1004 }
1005 
1006 float StarProfileViewer::convertFromSliderValue(int value)
1007 {
1008  return qPow((float)value,2) / 1000000.0;
1009 }
1010 
void setColorAt(qreal position, const QColor &color)
AlignLeft
QWidget * createWindowContainer(QWindow *window, QWidget *parent, Qt::WindowFlags flags)
void setMinimum(int)
void setCheckable(bool)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QString number(int n, int base)
void setFocusPolicy(Qt::FocusPolicy policy)
void setSizePolicy(QSizePolicy)
QIcon fromTheme(const QString &name)
void setCurrentIndex(int index)
int x() const const
int y() const const
void setChecked(bool)
void setAttribute(Qt::WidgetAttribute attribute, bool on)
void setWrapping(bool on)
void setMinimumSize(const QSize &)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setMaximum(int)
void toggled(bool checked)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
void setMaximumWidth(int maxw)
void setValue(int)
virtual void setVisible(bool visible)
QString i18n(const char *text, const TYPE &arg...)
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
Vertical
bool isEmpty() const const
int toInt(bool *ok, int base) const const
void setMaximumSize(const QSize &)
void insert(int i, const T &value)
QString label(StandardShortcut id)
void setIcon(const QIcon &icon)
virtual int exec() override
void setText(const QString &text)
void setIconSize(const QSize &size)
void setToolTip(const QString &)
void setX(float x)
void setZ(float z)
void valueChanged(int value)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
QList::iterator begin()
float x() const const
float z() const const
bool setAlignment(QWidget *w, Qt::Alignment alignment)
void addItem(const QString &text, const QVariant &userData)
void addLayout(QLayout *layout, int stretch)
void setItemIcon(int index, const QIcon &icon)
void setLayout(QLayout *layout)
StrongFocus
QList::iterator end()
void setText(const QString &text)
WA_LayoutUsesWidgetRect
darkGreen
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Tue Aug 9 2022 04:06:07 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.