diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/DynamicPDF/SliceSelector.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/DynamicPDF/SliceSelector.h index 11fdf411a2dbc64764b8208e318590e6895ef17a..d0db08153955fafebca3ba2500515de1b0913618 100644 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/DynamicPDF/SliceSelector.h +++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/DynamicPDF/SliceSelector.h @@ -4,8 +4,12 @@ #include "MantidQtCustomInterfaces/DllConfig.h" #include "MantidQtAPI/UserSubWindow.h" #include "ui_SliceSelector.h" +#include <qwt_plot_spectrogram.h> namespace MantidQt { +namespace MantidWidgets { + class SafeQwtPlot; +} namespace CustomInterfaces { namespace DynamicPDF { @@ -25,6 +29,11 @@ public: std::string m_label; }; +/// A wrapper for all elements associated to the 2D view +struct slices2DviewStruct { + MantidQt::MantidWidgets::MWSpectrogram* plot2D; + QwtPlotSpectrogram* spectrogram; +}; class MANTIDQT_CUSTOMINTERFACES_DLL SliceSelector : public MantidQt::API::UserSubWindow { @@ -56,6 +65,7 @@ private: void initLayout(); /// The form generated by Qt Designer Ui::SliceSelector m_uiForm; + slices2DviewStruct m_view2D; boost::shared_ptr<WorkspaceRecord> m_loadedWorkspace; size_t m_selectedWorkspaceIndex; /// The child dialog to remove the multiphonon background diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/DynamicPDF/SliceSelector.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/DynamicPDF/SliceSelector.ui index 07ce00809984ec533b66dd41102c646622d1c28e..ffb7f469a51bbad08f906c1b7223dee1899ba638 100644 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/DynamicPDF/SliceSelector.ui +++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/DynamicPDF/SliceSelector.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>432</width> + <width>535</width> <height>654</height> </rect> </property> @@ -40,7 +40,7 @@ <number>0</number> </property> <item row="0" column="0"> - <widget class="MantidQt::MantidWidgets::DataSelector" name="dataSelector" native="true"/> + <widget class="MantidQt::MantidWidgets::DataSelector" name="dataSelector"/> </item> </layout> </widget> @@ -94,6 +94,9 @@ </property> </widget> </item> + <item> + <widget class="MantidQt::MantidWidgets::MWSpectrogram" name="slices2DPlot"/> + </item> </layout> </item> <item> @@ -184,6 +187,17 @@ </widget> </widget> <customwidgets> + <customwidget> + <class>QwtPlot</class> + <extends>QFrame</extends> + <header>qwt_plot.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>MantidQt::MantidWidgets::MWSpectrogram</class> + <extends>QwtPlot</extends> + <header>MantidQtMantidWidgets/MWSpectrogram.h</header> + </customwidget> <customwidget> <class>MantidQt::MantidWidgets::DataSelector</class> <extends>QWidget</extends> diff --git a/MantidQt/CustomInterfaces/src/DynamicPDF/SliceSelector.cpp b/MantidQt/CustomInterfaces/src/DynamicPDF/SliceSelector.cpp index 142e12169b6d7d1fda22df77a60a2bdd30c7591c..364a82c67744b7b5ffe3e73e8e64d0c83213533f 100644 --- a/MantidQt/CustomInterfaces/src/DynamicPDF/SliceSelector.cpp +++ b/MantidQt/CustomInterfaces/src/DynamicPDF/SliceSelector.cpp @@ -4,6 +4,10 @@ #include "MantidAPI/MatrixWorkspace.h" #include "MantidQtAPI/HelpWindow.h" #include "MantidQtCustomInterfaces/DynamicPDF/SliceSelector.h" +// includes for the 2D view +#include "MantidQtMantidWidgets/SafeQwtPlot.h" +#include <qwt_plot_spectrogram.h> + //#include "MantidQtCustomInterfaces/DynamicPDF/BackgroundRemover.h" namespace { @@ -37,7 +41,8 @@ DECLARE_SUBWINDOW(SliceSelector) // SliceSelector::SliceSelector(QWidget *parent) : UserSubWindow{parent}, // m_loadedWorkspace{nullptr}, m_BackgroundRemover{nullptr} { SliceSelector::SliceSelector(QWidget *parent) - : UserSubWindow{parent}, m_loadedWorkspace{nullptr} {} + : UserSubWindow{parent}, m_view2D{nullptr,nullptr}, + m_loadedWorkspace{nullptr} {} SliceSelector::~SliceSelector() { m_selectedWorkspaceIndex = 0; } @@ -57,13 +62,12 @@ void SliceSelector::initLayout() { /// void SliceSelector::loadSlices(const QString &workspaceName) { - m_loadedWorkspace = boost::make_shared<WorkspaceRecord>(workspaceName.toStdString()); m_selectedWorkspaceIndex = 0; m_loadedWorkspace->updateMetadata(m_selectedWorkspaceIndex); - size_t maximumWorkspaceIndex = - m_loadedWorkspace->m_ws->getNumberHistograms() - 1; + int maximumWorkspaceIndex = + static_cast<int>(m_loadedWorkspace->m_ws->getNumberHistograms()) - 1; /// initialize the label displaying the energy m_uiForm.labelSliceEnergy->setText( @@ -71,18 +75,21 @@ void SliceSelector::loadSlices(const QString &workspaceName) { /// initialize the spin box that selects the energy slice m_uiForm.spinboxSliceSelector->setMinimum(0); - m_uiForm.spinboxSliceSelector->setMaximum( - static_cast<int>(maximumWorkspaceIndex)); - m_uiForm.spinboxSliceSelector->setValue( - static_cast<int>(0)); + m_uiForm.spinboxSliceSelector->setMaximum(maximumWorkspaceIndex); + m_uiForm.spinboxSliceSelector->setValue(0); m_uiForm.spinboxSliceSelector->setSingleStep(1); - /// initialize the slider in the 2D view + /// initialize the slider next to the 2D view m_uiForm.sliderSelectSlice->setMinimum(0); - m_uiForm.sliderSelectSlice->setMaximum( - static_cast<int>(maximumWorkspaceIndex)); - m_uiForm.spinboxSliceSelector->setValue( - static_cast<int>(0)); + m_uiForm.sliderSelectSlice->setMaximum(maximumWorkspaceIndex); + m_uiForm.spinboxSliceSelector->setValue(0); + + /// initialize the 2D view of the histogram; + m_view2D.plot2D = m_uiForm.slices2DPlot; + m_view2D.spectrogram = new QwtPlotSpectrogram(); + m_view2D.spectrogram->attach(m_view2D.plot2D); + m_view2D.plot2D->setWorkspace(m_loadedWorkspace->m_ws); + m_view2D.plot2D->replot(); /// initialize the preview plot updatePlotSelectedSlice(); @@ -98,13 +105,17 @@ void SliceSelector::updatePlotSelectedSlice() { /// Update all widgets in the form with the new selected index void SliceSelector::updateSelectedSlice(const int &newSelectedIndex) { - m_selectedWorkspaceIndex = newSelectedIndex; - m_loadedWorkspace->updateMetadata(m_selectedWorkspaceIndex); - m_uiForm.labelSliceEnergy->setText( - QString::fromStdString(m_loadedWorkspace->m_label)); - m_uiForm.spinboxSliceSelector->setValue(m_selectedWorkspaceIndex); - m_uiForm.sliderSelectSlice->setValue(m_selectedWorkspaceIndex); - updatePlotSelectedSlice(); + m_selectedWorkspaceIndex = static_cast<size_t>(newSelectedIndex); + /// Check pointer m_loadedWorkspace because the user may attemp to manipulate + /// the widgets before (s)he loads any data + if (m_loadedWorkspace) { + m_loadedWorkspace->updateMetadata(m_selectedWorkspaceIndex); + m_uiForm.labelSliceEnergy->setText( + QString::fromStdString(m_loadedWorkspace->m_label)); + m_uiForm.spinboxSliceSelector->setValue(newSelectedIndex); + m_uiForm.sliderSelectSlice->setValue(newSelectedIndex); + updatePlotSelectedSlice(); + } } /// Initialize and/or update the dialog to remove the multiphonon background diff --git a/MantidQt/DesignerPlugins/inc/MantidQtDesignerPlugins/PluginCollectionInterface.h b/MantidQt/DesignerPlugins/inc/MantidQtDesignerPlugins/PluginCollectionInterface.h index 750f699700f5448d7bfc959544fe333eeddc0f4c..da49af0e566d5cfcce45114fd511a9eaa1b6f762 100644 --- a/MantidQt/DesignerPlugins/inc/MantidQtDesignerPlugins/PluginCollectionInterface.h +++ b/MantidQt/DesignerPlugins/inc/MantidQtDesignerPlugins/PluginCollectionInterface.h @@ -16,6 +16,7 @@ #include "MantidQtSliceViewer/SliceViewer.h" #include "MantidQtSliceViewer/LineViewer.h" #include "MantidQtMantidWidgets/SafeQwtPlot.h" +#include "MantidQtMantidWidgets/MWSpectrogram.h" #include "MantidQtAPI/AlgorithmPropertiesWidget.h" #include "MantidQtMantidWidgets/ProcessingAlgoWidget.h" #include "MantidQtMantidWidgets/MessageDisplay.h" @@ -132,6 +133,10 @@ DECLARE_WIDGET_PLUGIN(SafeQwtPlotPlugin, MantidQt::MantidWidgets::SafeQwtPlot, "Version of QwtPlot with workspace-level thread safety"); +DECLARE_WIDGET_PLUGIN(MWSpectrogramPlugin, + MantidQt::MantidWidgets::MWSpectrogram, + "2D view of a MatrixWorkspace"); + DECLARE_WIDGET_PLUGIN(AlgorithmPropertiesWidgetPlugin, MantidQt::API::AlgorithmPropertiesWidget, "List of algorithm properties"); @@ -147,5 +152,4 @@ DECLARE_WIDGET_PLUGIN(MessageDisplayPlugin, DECLARE_WIDGET_PLUGIN(DataSelectorPlugin, MantidQt::MantidWidgets::DataSelector, "Choose a file path or workspace to work with"); - #endif diff --git a/MantidQt/DesignerPlugins/src/PluginCollectionInterface.cpp b/MantidQt/DesignerPlugins/src/PluginCollectionInterface.cpp index 9c0c20347d400675752165a278e60114bcd71b9f..b405b8d22444a0cd3b6ff8aa6574cdac7b0b9dec 100644 --- a/MantidQt/DesignerPlugins/src/PluginCollectionInterface.cpp +++ b/MantidQt/DesignerPlugins/src/PluginCollectionInterface.cpp @@ -21,6 +21,7 @@ PluginCollectionInterface::PluginCollectionInterface(QObject *parent) : QObject( m_widgets.append(new SliceViewerPlugin(this)); m_widgets.append(new LineViewerPlugin(this)); m_widgets.append(new SafeQwtPlotPlugin(this)); + m_widgets.append(new MWSpectrogramPlugin(this)); m_widgets.append(new AlgorithmPropertiesWidgetPlugin(this)); m_widgets.append(new ProcessingAlgoWidgetPlugin(this)); m_widgets.append(new DataSelectorPlugin(this)); diff --git a/MantidQt/MantidWidgets/CMakeLists.txt b/MantidQt/MantidWidgets/CMakeLists.txt index 40dd50bb70f502f7cf73332e4750463f0d0d5197..837080244e9f6e4805baa66844437b3076966604 100644 --- a/MantidQt/MantidWidgets/CMakeLists.txt +++ b/MantidQt/MantidWidgets/CMakeLists.txt @@ -22,6 +22,7 @@ set ( SRC_FILES src/InputController.cpp src/MantidHelpWindow.cpp src/MWDiag.cpp + src/MWSpectrogram.cpp src/MWRunFiles.cpp src/MessageDisplay.cpp src/MultifitSetupDialog.cpp @@ -124,6 +125,7 @@ set ( MOC_FILES inc/MantidQtMantidWidgets/MuonFitPropertyBrowser.h inc/MantidQtMantidWidgets/MuonSequentialFitDialog.h inc/MantidQtMantidWidgets/MWDiag.h + inc/MantidQtMantidWidgets/MWSpectrogram.h inc/MantidQtMantidWidgets/MWRunFiles.h inc/MantidQtMantidWidgets/PeakPicker.h inc/MantidQtMantidWidgets/PeriodicTableWidget.h diff --git a/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWSpectrogram.h b/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWSpectrogram.h new file mode 100644 index 0000000000000000000000000000000000000000..85558f7500d4753b12dd4832c154b59eec097897 --- /dev/null +++ b/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWSpectrogram.h @@ -0,0 +1,70 @@ +#ifndef MANTID_MANTIDWIDGETS_MWSPECTROGRAM_H_ +#define MANTID_MANTIDWIDGETS_MWSPECTROGRAM_H_ + +#include "MantidQtMantidWidgets/WidgetDllOption.h" +#include <qwt_plot.h> +#include <qpainter.h> +#include "qwt_text.h" +#include "MantidAPI/MatrixWorkspace_fwd.h" +#include "WidgetDllOption.h" + +namespace MantidQt +{ +namespace MantidWidgets +{ + + /** A version of QwtPlot that adds a layer of thread safety. + * + * Each SafeQwtPlot has a workspace associated with it. + * Before drawing, it acquires a ReadLock to prevent + * an algorithm from modifying the underlying workspace while it is + * drawing. + * + * If no workspace is set, no drawing occurs (silently). + + @date 2012-01-24 + + Copyright © 2012 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge National Laboratory & European Spallation Source + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + File change history is stored at: <https://github.com/mantidproject/mantid> + Code Documentation is available at: <http://doxygen.mantidproject.org> + */ + class EXPORT_OPT_MANTIDQT_MANTIDWIDGETS MWSpectrogram : public QwtPlot + { + Q_OBJECT + + public: + explicit MWSpectrogram(QWidget * parent = NULL); + explicit MWSpectrogram(const QwtText &title, QWidget *p = NULL); + + virtual ~MWSpectrogram(); + + virtual void drawCanvas(QPainter * painter); + + void setWorkspace(Mantid::API::MatrixWorkspace_sptr ws); + + private: + /// Workspace being read-locked + Mantid::API::MatrixWorkspace_sptr m_ws; + }; + + +} // namespace MantidWidgets +} // namespace MantidQt + +#endif /* MANTID_MANTIDWIDGETS_MWSPECTROGRAM_H_ */ diff --git a/MantidQt/MantidWidgets/src/MWSpectrogram.cpp b/MantidQt/MantidWidgets/src/MWSpectrogram.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70d99deff32b194a4658d159fd879589b8021d85 --- /dev/null +++ b/MantidQt/MantidWidgets/src/MWSpectrogram.cpp @@ -0,0 +1,66 @@ +#include "MantidQtMantidWidgets/MWSpectrogram.h" +#include "MantidAPI/MatrixWorkspace.h" +#include "MantidKernel/System.h" +#include "MantidKernel/ReadLock.h" + + +namespace MantidQt +{ +namespace MantidWidgets +{ + + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + MWSpectrogram::MWSpectrogram(QWidget * parent) + : QwtPlot(parent) + { + } + + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + MWSpectrogram::MWSpectrogram(const QwtText &title, QWidget * parent) + : QwtPlot(title, parent) + { + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + MWSpectrogram::~MWSpectrogram() + { + } + + + //---------------------------------------------------------------------------------------------- + /** Set the workspace that we read-lock when drawing. + * + * @param ws :: shared ptr to workspace + */ + void MWSpectrogram::setWorkspace(Mantid::API::MatrixWorkspace_sptr ws) + { + m_ws = ws; + } + + //---------------------------------------------------------------------------------------------- + /** Overridden drawCanvas() that protects the + * workspace from being overwritten while being drawn + * + * @param painter :: QPainter + */ + void MWSpectrogram::drawCanvas(QPainter * painter) + { + // Do nothing if the workspace is not valid. + if (!m_ws) return; + // Get the scoped read lock. + Mantid::Kernel::ReadLock lock(*m_ws); + // Draw using the usual procedure. + QwtPlot::drawCanvas(painter); + // lock is released when it goes out of scope. + } + +} // namespace MantidQt +} // namespace MantidWidgets