diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationControls.ui b/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationControls.ui index ac4a41972c..43aeb08f85 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationControls.ui +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationControls.ui @@ -1,405 +1,350 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>QmitkHistogramVisualizationControls</class> <widget class="QWidget" name="QmitkHistogramVisualizationControls"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>540</width> <height>460</height> </rect> </property> <property name="minimumSize"> <size> <width>540</width> <height>460</height> </size> </property> <property name="windowTitle"> <string>Form</string> </property> <widget class="QGroupBox" name="groupBoxHistogram"> <property name="enabled"> <bool>false</bool> </property> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>530</width> <height>450</height> </rect> </property> <property name="minimumSize"> <size> <width>400</width> <height>450</height> </size> </property> <property name="title"> <string/> </property> <property name="checkable"> <bool>false</bool> </property> <layout class="QVBoxLayout" name="verticalLayout_4"> <item> <widget class="QLabel" name="labelHistogramIsInvisibleWarning"> <property name="enabled"> <bool>false</bool> </property> <property name="palette"> <palette> <active> <colorrole role="WindowText"> <brush brushstyle="SolidPattern"> <color alpha="255"> <red>255</red> <green>0</green> <blue>0</blue> </color> </brush> </colorrole> <colorrole role="Text"> <brush brushstyle="SolidPattern"> <color alpha="255"> <red>255</red> <green>0</green> <blue>0</blue> </color> </brush> </colorrole> <colorrole role="ButtonText"> <brush brushstyle="SolidPattern"> <color alpha="255"> <red>255</red> <green>0</green> <blue>0</blue> </color> </brush> </colorrole> </active> <inactive> <colorrole role="WindowText"> <brush brushstyle="SolidPattern"> <color alpha="255"> <red>255</red> <green>0</green> <blue>0</blue> </color> </brush> </colorrole> <colorrole role="Text"> <brush brushstyle="SolidPattern"> <color alpha="255"> <red>255</red> <green>0</green> <blue>0</blue> </color> </brush> </colorrole> <colorrole role="ButtonText"> <brush brushstyle="SolidPattern"> <color alpha="255"> <red>255</red> <green>0</green> <blue>0</blue> </color> </brush> </colorrole> </inactive> <disabled> <colorrole role="WindowText"> <brush brushstyle="SolidPattern"> <color alpha="255"> <red>120</red> <green>120</green> <blue>120</blue> </color> </brush> </colorrole> <colorrole role="Text"> <brush brushstyle="SolidPattern"> <color alpha="255"> <red>120</red> <green>120</green> <blue>120</blue> </color> </brush> </colorrole> <colorrole role="ButtonText"> <brush brushstyle="SolidPattern"> <color alpha="255"> <red>120</red> <green>120</green> <blue>120</blue> </color> </brush> </colorrole> </disabled> </palette> </property> <property name="text"> <string/> </property> </widget> </item> <item> <widget class="QGroupBox" name="groupBoxPlot"> <property name="enabled"> <bool>false</bool> </property> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> <width>0</width> <height>0</height> </size> </property> <property name="maximumSize"> <size> <width>16777215</width> <height>16777215</height> </size> </property> <property name="title"> <string>Plot</string> </property> <layout class="QVBoxLayout" name="verticalLayout_5"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QRadioButton" name="radioButtonBarchart"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="styleSheet"> - <string notr="true"/> - </property> - <property name="text"> - <string>Barchart</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QRadioButton" name="radioButtonLinegraph"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>Linegraph</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> <item> <widget class="QCheckBox" name="checkBoxShowSubchart"> <property name="text"> <string>Show Subchart</string> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> <item> <widget class="QCheckBox" name="checkBoxUseDefaultNBins"> <property name="text"> <string>Use default #bins</string> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> <item> <widget class="QFrame" name="FrameBinSize"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_2"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <property name="spacing"> <number>0</number> </property> <item row="1" column="0"> <widget class="QLabel" name="labelNBins"> <property name="minimumSize"> <size> <width>60</width> <height>0</height> </size> </property> <property name="maximumSize"> <size> <width>100</width> <height>16777215</height> </size> </property> <property name="text"> <string># bins:</string> </property> </widget> </item> <item row="1" column="1"> <widget class="QSpinBox" name="spinBoxNBins"> <property name="enabled"> <bool>false</bool> </property> <property name="toolTip"> <string>Press enter to recalculate statistics with new bin size.</string> </property> <property name="minimum"> <number>1</number> </property> <property name="maximum"> <number>10000</number> </property> <property name="value"> <number>100</number> </property> </widget> </item> </layout> </widget> </item> </layout> </widget> </item> <item> <widget class="QStackedWidget" name="stackWidgetChart"> <property name="minimumSize"> <size> <width>0</width> <height>0</height> </size> </property> <property name="currentIndex"> <number>0</number> </property> <widget class="QmitkChartWidget" name="chartWidget"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> </widget> </widget> </item> <item> <widget class="QLabel" name="labelInfo"> <property name="text"> <string/> </property> </widget> </item> <item> <widget class="QWidget" name="widgetClipboard" native="true"> <layout class="QHBoxLayout" name="horizontalLayout_3"> <property name="spacing"> <number>0</number> </property> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item> <widget class="QPushButton" name="buttonCopyHistogramToClipboard"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> <string>Copy to Clipboard</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer_2"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> </layout> </widget> </item> </layout> </widget> </widget> <customwidgets> <customwidget> <class>QmitkChartWidget</class> <extends>QWidget</extends> <header location="global">QmitkChartWidget.h</header> </customwidget> </customwidgets> <resources/> <connections/> </ui> diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationWidget.cpp b/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationWidget.cpp index 022d5e848c..b744d26976 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationWidget.cpp +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationWidget.cpp @@ -1,69 +1,125 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkHistogramVisualizationWidget.h" +#include <qclipboard> + HistogramVisualizationWidget::HistogramVisualizationWidget(QWidget* parent) : QWidget(parent) { - if (m_Controls == nullptr) - { - m_Controls = new Ui::QmitkHistogramVisualizationControls; - } - setupUi(this); + m_Controls.setupUi(this); CreateConnections(); } -void HistogramVisualizationWidget::CreateConnections() +void HistogramVisualizationWidget::setHistogram(itk::Statistics::Histogram<double>::ConstPointer histogram, std::string dataLabel) { - connect(buttonCopyHistogramToClipboard, &QPushButton::clicked, this, &HistogramVisualizationWidget::OnClipboardButtonClicked); - connect(radioButtonBarchart, &QRadioButton::clicked, this, &HistogramVisualizationWidget::OnBarRadioButtonSelected); - connect(radioButtonLinegraph, &QRadioButton::clicked, this, &HistogramVisualizationWidget::OnLineRadioButtonSelected); - connect(checkBoxUseDefaultNBins, &QCheckBox::clicked, this, &HistogramVisualizationWidget::OnDefaultNBinsCheckBoxChanged); - connect(spinBoxNBins, &QSpinBox::editingFinished, this, &HistogramVisualizationWidget::OnNBinsSpinBoxValueChanged); - connect(checkBoxShowSubchart, &QCheckBox::clicked, this, &HistogramVisualizationWidget::OnShowSubchartCheckBoxChanged); + if (histogram == nullptr) + return; + + m_Histogram = histogram; + m_Controls.chartWidget->AddData2D(ConvertHistogramToMap(m_Histogram), dataLabel); + m_Controls.chartWidget->SetChartType(dataLabel, QmitkChartWidget::ChartType::bar); + m_Controls.chartWidget->SetXAxisLabel("Gray value"); + m_Controls.chartWidget->SetYAxisLabel("Frequency"); + + m_Controls.chartWidget->Show(m_Controls.checkBoxShowSubchart->isChecked()); + SetGUIElementsEnabled(true); } -void HistogramVisualizationWidget::EnableAllComponents() +void HistogramVisualizationWidget::Reset() { - this->setEnabled(true); - groupBoxHistogram->setEnabled(true); - groupBoxPlot->setEnabled(true); - buttonCopyHistogramToClipboard->setEnabled(true); + m_Controls.chartWidget->Clear(); + SetGUIElementsEnabled(false); } -void HistogramVisualizationWidget::OnClipboardButtonClicked() +void HistogramVisualizationWidget::CreateConnections() { + connect(m_Controls.buttonCopyHistogramToClipboard, &QPushButton::clicked, this, &HistogramVisualizationWidget::OnClipboardButtonClicked); + connect(m_Controls.checkBoxUseDefaultNBins, &QCheckBox::clicked, this, &HistogramVisualizationWidget::OnDefaultNBinsCheckBoxChanged); + connect(m_Controls.spinBoxNBins, &QSpinBox::editingFinished, this, &HistogramVisualizationWidget::OnNBinsSpinBoxValueChanged); + connect(m_Controls.checkBoxShowSubchart, &QCheckBox::clicked, this, &HistogramVisualizationWidget::OnShowSubchartCheckBoxChanged); } -void HistogramVisualizationWidget::OnDefaultNBinsCheckBoxChanged() +void HistogramVisualizationWidget::SetGUIElementsEnabled(bool enabled) { + this->setEnabled(enabled); + m_Controls.groupBoxHistogram->setEnabled(enabled); + m_Controls.groupBoxPlot->setEnabled(enabled); + m_Controls.checkBoxShowSubchart->setEnabled(enabled); + m_Controls.checkBoxUseDefaultNBins->setEnabled(enabled); + m_Controls.spinBoxNBins->setEnabled(!m_Controls.checkBoxUseDefaultNBins->isChecked()); + m_Controls.buttonCopyHistogramToClipboard->setEnabled(enabled); } -void HistogramVisualizationWidget::OnNBinsSpinBoxValueChanged() +std::map<double, double> HistogramVisualizationWidget::ConvertHistogramToMap(itk::Statistics::Histogram<double>::ConstPointer histogram) const { + std::map<double, double> histogramMap; + if (histogram) + { + auto endIt = histogram->End(); + auto it = histogram->Begin(); + + // generating Lists of measurement and frequencies + for (; it != endIt; ++it) + { + double frequency = it.GetFrequency(); + double measurement = it.GetMeasurementVector()[0]; + histogramMap.emplace(measurement, frequency); + } + + } + return histogramMap; } -void HistogramVisualizationWidget::OnShowSubchartCheckBoxChanged() +void HistogramVisualizationWidget::OnClipboardButtonClicked() { + if (m_Histogram) + { + QApplication::clipboard()->clear(); + QString clipboard("Measurement \t Frequency\n"); + for (auto it = m_Histogram->Begin(); it != m_Histogram->End(); ++it) + { + clipboard = clipboard.append("%L1 \t %L2\n") + .arg(it.GetMeasurementVector()[0], 0, 'f', 2) + .arg(it.GetFrequency()); + } + + QApplication::clipboard()->setText(clipboard, QClipboard::Clipboard); + } } -void HistogramVisualizationWidget::OnBarRadioButtonSelected() +void HistogramVisualizationWidget::OnDefaultNBinsCheckBoxChanged() { + if (m_Controls.checkBoxUseDefaultNBins->isChecked()) + { + m_Controls.spinBoxNBins->setEnabled(false); + m_Controls.spinBoxNBins->setValue(100); + } + else + { + m_Controls.spinBoxNBins->setEnabled(true); + } } -void HistogramVisualizationWidget::OnLineRadioButtonSelected() +void HistogramVisualizationWidget::OnNBinsSpinBoxValueChanged() { + emit RequestHistogramUpdate(m_Controls.spinBoxNBins->value()); } + +void HistogramVisualizationWidget::OnShowSubchartCheckBoxChanged() +{ + m_Controls.chartWidget->Show(m_Controls.checkBoxShowSubchart->isChecked()); +} \ No newline at end of file diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationWidget.h b/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationWidget.h index b92d5e4eab..ada433f974 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationWidget.h +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkHistogramVisualizationWidget.h @@ -1,61 +1,65 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #pragma once //Qt #include <QWidget> #include <MitkImageStatisticsUIExports.h> #include <ui_QmitkHistogramVisualizationControls.h> -class MITKIMAGESTATISTICSUI_EXPORT HistogramVisualizationWidget : public QWidget, private Ui::QmitkHistogramVisualizationControls +#include <itkHistogram.h> + +class MITKIMAGESTATISTICSUI_EXPORT HistogramVisualizationWidget : public QWidget { Q_OBJECT public: HistogramVisualizationWidget(QWidget* parent = nullptr); - - //void setHistogram(itk::Histogram<double>::ConstPointer h); + /** \brief Draws the histogram and enables the GUI elements */ + void setHistogram(itk::Statistics::Histogram<double>::ConstPointer histogram, std::string dataLabel); + /** \brief Clears the histogram and disables all GUI elements */ + void Reset(); signals: /** * \brief Signal to be emitted when the number of bins is changed by the user. The HistogramCalculator should connect to this signal and recalculate the data accordingly. */ void RequestHistogramUpdate(unsigned int nBins); private: void CreateConnections(); - void EnableAllComponents(); + void SetGUIElementsEnabled(bool enabled); + + std::map<double, double> ConvertHistogramToMap(itk::Statistics::Histogram<double>::ConstPointer histogram) const; //slots /** \brief Saves the histogram to the clipboard */ void OnClipboardButtonClicked(); /** \brief Toogle GUI elements if histogram default bin size checkbox value changed. */ void OnDefaultNBinsCheckBoxChanged(); void OnNBinsSpinBoxValueChanged(); void OnShowSubchartCheckBoxChanged(); - void OnBarRadioButtonSelected(); - - void OnLineRadioButtonSelected(); - private: - Ui::QmitkHistogramVisualizationControls* m_Controls; + Ui::QmitkHistogramVisualizationControls m_Controls; + + itk::Statistics::Histogram<double>::ConstPointer m_Histogram; }; \ No newline at end of file