diff --git a/MantidPlot/CMakeLists.txt b/MantidPlot/CMakeLists.txt index 4f616470ce3d44232c3bb2f45b0858cdde66abf1..7e442feba61f7b8afa0ca769e22aa438d281ca86 100644 --- a/MantidPlot/CMakeLists.txt +++ b/MantidPlot/CMakeLists.txt @@ -168,6 +168,7 @@ set ( MANTID_SRCS src/Mantid/AlgorithmMonitor.cpp src/Mantid/IFunctionWrapper.cpp src/Mantid/ImportWorkspaceDlg.cpp src/Mantid/InputHistory.cpp + src/Mantid/LabelToolLogValuesDialog.cpp src/Mantid/LoadDAEDlg.cpp src/Mantid/ManageCustomMenus.cpp src/Mantid/ManageInterfaceCategories.cpp @@ -194,6 +195,7 @@ set ( MANTID_SRCS src/Mantid/AlgorithmMonitor.cpp src/Mantid/PeakPickerTool.cpp src/Mantid/Preferences.cpp src/Mantid/RemoveErrorsDialog.cpp + src/Mantid/SampleLogDialogBase.cpp src/Mantid/UserFitFunctionDialog.cpp src/Mantid/WorkspaceIcons.cpp src/Mantid/InstrumentWidget/InstrumentWindow.cpp @@ -362,6 +364,7 @@ set ( MANTID_HDRS src/Mantid/AlgorithmMonitor.h src/Mantid/ImportWorkspaceDlg.h src/Mantid/IMantidMatrixExtensionHandler.h src/Mantid/InputHistory.h + src/Mantid/LabelToolLogValuesDialog.h src/Mantid/LoadDAEDlg.h src/Mantid/ManageCustomMenus.h src/Mantid/ManageInterfaceCategories.h @@ -390,6 +393,7 @@ set ( MANTID_HDRS src/Mantid/AlgorithmMonitor.h src/Mantid/PeakPickerTool.h src/Mantid/Preferences.h src/Mantid/RemoveErrorsDialog.h + src/Mantid/SampleLogDialogBase.h src/Mantid/UserFitFunctionDialog.h src/Mantid/WorkspaceIcons.h src/Mantid/IProjectSerialisable.h @@ -596,6 +600,7 @@ set ( MANTID_MOC_FILES src/Mantid/AlgorithmMonitor.h src/Mantid/FirstTimeSetup.h src/Mantid/IFunctionWrapper.h src/Mantid/ImportWorkspaceDlg.h + src/Mantid/LabelToolLogValuesDialog.h src/Mantid/LoadDAEDlg.h src/Mantid/ManageCustomMenus.h src/Mantid/ManageInterfaceCategories.h @@ -618,6 +623,7 @@ set ( MANTID_MOC_FILES src/Mantid/AlgorithmMonitor.h src/Mantid/MantidTable.h src/Mantid/PeakPickerTool.h src/Mantid/RemoveErrorsDialog.h + src/Mantid/SampleLogDialogBase.h src/Mantid/UserFitFunctionDialog.h src/Mantid/InstrumentWidget/InstrumentWindow.h ) diff --git a/MantidPlot/src/Mantid/LabelToolLogValuesDialog.cpp b/MantidPlot/src/Mantid/LabelToolLogValuesDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c641f3879477ab3d9beac555cd3ca891fbb9df5 --- /dev/null +++ b/MantidPlot/src/Mantid/LabelToolLogValuesDialog.cpp @@ -0,0 +1,216 @@ +//---------------------------------- +// Includes +//---------------------------------- + +#include "LabelToolLogValuesDialog.h" + +// STD +#include <sstream> + +// Mantid +#include <LegendWidget.h> +#include <Mantid/MantidUI.h> +#include <MantidAPI/MultipleExperimentInfos.h> + +// Qt +#include <QHeaderView> +#include <QFormLayout> +#include <QGroupBox> +#include <QRadioButton> + + +//---------------------------------- +// Namespaces +//---------------------------------- + +using namespace Mantid; +using namespace Mantid::API; +using namespace Mantid::Kernel; + +//---------------------------------- +// Public methods +//---------------------------------- +/** +* Construct an object of this type +* @param wsname :: The name of the workspace object from which to retrieve the +* log files +* @param parentContainer :: The widget that is the container this dialog +* @param flags :: Window flags that are passed the the QDialog constructor +* @param experimentInfoIndex :: optional index in the array of +* ExperimentInfo objects. Should only be non-zero for MDWorkspaces. +*/ +LabelToolLogValuesDialog::LabelToolLogValuesDialog(const QString &wsname, QWidget *parentContainer, Qt::WFlags flags, size_t experimentInfoIndex): + SampleLogDialogBase(wsname, parentContainer, flags, experimentInfoIndex) { + + std::stringstream ss; + ss << "MantidPlot - " << wsname.toStdString().c_str() << " sample logs"; + setWindowTitle(QString::fromStdString(ss.str())); + + m_tree = new QTreeWidget; + + QStringList titles; + titles << "Name" + << "Type" + << "Value" + << "Units"; + m_tree->setHeaderLabels(titles); + m_tree->setSelectionMode(QAbstractItemView::SingleSelection); + QHeaderView *hHeader = (QHeaderView *)m_tree->header(); + hHeader->setResizeMode(2, QHeaderView::Stretch); + hHeader->setStretchLastSection(false); + + QHBoxLayout *uiLayout = new QHBoxLayout; + uiLayout->addWidget(m_tree); + + // -------------- Statistics on logs ------------------------ + std::string stats[NUM_STATS] = { + "Min:", "Max:", "Mean:", "Time Avg:", "Median:", "Std Dev:", "Duration:"}; + QGroupBox *statsBox = new QGroupBox("Log Statistics"); + QFormLayout *statsBoxLayout = new QFormLayout; + + for (size_t i = 0; i < NUM_STATS; i++) { + statRadioChoice[i] = new QRadioButton(stats[i].c_str()); + statValues[i] = new QLineEdit(""); + statValues[i]->setReadOnly(true); + + statsBoxLayout->addRow(statRadioChoice[i], statValues[i]); + } + // Set default checked radio button + statRadioChoice[0]->setChecked(true); + statsBox->setLayout(statsBoxLayout); + + // -------------- The Import/Close buttons ------------------------ + QHBoxLayout *topButtons = new QHBoxLayout; + buttonPlot = new QPushButton(tr("&Import selected log")); + buttonPlot->setAutoDefault(true); + buttonPlot->setToolTip( + "Import log file as a table and construct a 1D graph if appropriate"); + topButtons->addWidget(buttonPlot); + + buttonClose = new QPushButton(tr("Close")); + buttonClose->setToolTip("Close dialog"); + topButtons->addWidget(buttonClose); + + QVBoxLayout *hbox = new QVBoxLayout; + + // -------------- The ExperimentInfo selector------------------------ + boost::shared_ptr<Mantid::API::MultipleExperimentInfos> mei = AnalysisDataService::Instance().retrieveWS<MultipleExperimentInfos>( + m_wsname); + + if (mei) { + if (mei->getNumExperimentInfo() > 0) { + QHBoxLayout *numSelectorLayout = new QHBoxLayout; + QLabel *lbl = new QLabel("Experiment Info #"); + m_spinNumber = new QSpinBox; + m_spinNumber->setMinimum(0); + m_spinNumber->setMaximum(int(mei->getNumExperimentInfo()) - 1); + m_spinNumber->setValue(int(m_experimentInfoIndex)); + numSelectorLayout->addWidget(lbl); + numSelectorLayout->addWidget(m_spinNumber); + // Double-click imports a log file + connect(m_spinNumber, SIGNAL(valueChanged(int)), this, + SLOT(selectExpInfoNumber(int))); + hbox->addLayout(numSelectorLayout); + } + } + + // Finish laying out the right side + hbox->addLayout(topButtons); + hbox->addWidget(statsBox); + hbox->addStretch(1); + + //--- Main layout With 2 sides ----- + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->addLayout(uiLayout, 1); // the tree + mainLayout->addLayout(hbox, 0); + // mainLayout->addLayout(bottomButtons); + this->setLayout(mainLayout); + + // Call initialisation from base class + init(); + + resize(750, 400); + + connect(buttonPlot, SIGNAL(clicked()), this, SLOT(importSelectedLogs())); + connect(buttonClose, SIGNAL(clicked()), this, SLOT(close())); + // want a custom context menu + m_tree->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_tree, SIGNAL(customContextMenuRequested(const QPoint &)), this, + SLOT(popupMenu(const QPoint &))); + + // Double-click imports a log file + connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, + SLOT(importItem(QTreeWidgetItem *))); + + // Selecting shows the stats of it + connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, + SLOT(showLogStatistics())); + + // Selecting shows the stats of it + connect(m_tree, + SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), + this, SLOT(showLogStatistics())); +} + +//------------------------------------------------------------------------------------------------ +LabelToolLogValuesDialog::~LabelToolLogValuesDialog() { +} + +//------------------------------------------------------------------------------------------------ +/** Changes the LabelWidget parent object by using the setText +* method and constructing a label based on the selected log +* and value or generated statistics, and then calls close() +* inherited from the parent widget after importing the label. +* +* This is intentional because importing multiple labels will +* place them on the same spot and it can get unreadable. +* +* The parent container variable is dynamically cast up to LegendWidget. +* +* @param item :: The currently selected item from the log list +* @throws std::bad_cast :: The exception is throws if the dynamic_cast fails +* +*/ +void LabelToolLogValuesDialog::importItem(QTreeWidgetItem *item) { + + // Dynamic cast up to LegendWidget, which is the class of the + // one containing the label, in order to use setText + auto parentWidget = dynamic_cast<LegendWidget*>(m_parentContainer); + if(parentWidget == NULL) { // if dynamic cast fails, don't fail silently + throw new std::bad_cast; + } + + // find which radio box is checked + size_t activeRadioBoxPosition = 0; + for (size_t i = 0; i < NUM_STATS; ++i) { + if (statRadioChoice[i]->isChecked()) { + activeRadioBoxPosition = i; + break; // once found stop looking + } + } + + // Container for the full log description, + // starts with the name of the item from the tree + QString logValuesString = item->text(0) + '\n'; + + // Get the text from the selected stat value to determine + // if the item has any statistics calculated for it + // It's in a local variable to avoid repetition + QString statValuesText = statValues[activeRadioBoxPosition]->text(); + + //NOTE: + // If the log has no log statistics, import value field(2) and units(3) + if (statValuesText.isEmpty()) { + logValuesString += "Value: " + item->text(2) + " " + item->text(3); + } + else { + // else import the selected statistic + // constructing the log string using the hardcoded fields + logValuesString += statRadioChoice[activeRadioBoxPosition]->text() + + " " + statValuesText; + } + + parentWidget->setText(logValuesString); + close(); + +} diff --git a/MantidPlot/src/Mantid/LabelToolLogValuesDialog.h b/MantidPlot/src/Mantid/LabelToolLogValuesDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..27eabad54a9f31ef3121e4ff86e3d1c3cab6efa7 --- /dev/null +++ b/MantidPlot/src/Mantid/LabelToolLogValuesDialog.h @@ -0,0 +1,74 @@ +#ifndef LABELTOOLLOGVALUESDIALOG_H_ +#define LABELTOOLLOGVALUESDIALOG_H_ + +//---------------------------------- +// Includes +//---------------------------------- + +#include "MantidSampleLogDialog.h" +#include <MantidAPI/MultipleExperimentInfos.h> + +//---------------------------------- +// Forward declarations +//---------------------------------- + +class ApplicationWindow; +class QTreeWidgetItem; +class QTreeWidget; +class QPushButton; +class QRadioButton; +class QLabel; +class QLineEdit; +class QSpinBox; + +/** +This class display a Sample Log Dialog for the Label Tool, +it is used to select a Sample Log and import it on the plot +as a label. + +@author Dimitar Tasev, Mantid Development Team, STFC +@date 14/07/2016 + +Copyright © 2009 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 LabelToolLogValuesDialog : public SampleLogDialogBase { + Q_OBJECT +public: + /// Constructor + LabelToolLogValuesDialog(const QString &wsname, + QWidget *parentContainer, Qt::WFlags flags = nullptr, + size_t experimentInfoIndex = 0); + + virtual ~LabelToolLogValuesDialog() override; + +private slots: + + /// Override providing custom functionality to the import function + virtual void importItem(QTreeWidgetItem *item) override; + +private: + + /// Tracks which statistic of the log is selected + QRadioButton *statRadioChoice[NUM_STATS]; +}; + +#endif //LABELTOOLLOGVALUESDIALOG_H_ \ No newline at end of file diff --git a/MantidPlot/src/Mantid/MantidSampleLogDialog.cpp b/MantidPlot/src/Mantid/MantidSampleLogDialog.cpp index 8695165525881ff77bad918c8bfadfd378eb87bc..29640c8727c972698f25e776806b3b44a8747e06 100644 --- a/MantidPlot/src/Mantid/MantidSampleLogDialog.cpp +++ b/MantidPlot/src/Mantid/MantidSampleLogDialog.cpp @@ -2,483 +2,208 @@ // Includes //---------------------------------- #include "MantidSampleLogDialog.h" -#include "MantidUI.h" -#include "MantidKernel/TimeSeriesProperty.h" -#include "MantidKernel/ArrayProperty.h" +// Mantid +#include <MantidAPI/MultipleExperimentInfos.h> +#include "MantidUI.h" +// Qt #include <QHeaderView> +#include <QRadioButton> #include <QFormLayout> -#include <QMenu> #include <QGroupBox> -#include <QRadioButton> -#include <QFileInfo> -#include <sstream> -#include "MantidAPI/ExperimentInfo.h" -#include "MantidAPI/MultipleExperimentInfos.h" -#include <boost/shared_ptr.hpp> using namespace Mantid; using namespace Mantid::API; using namespace Mantid::Kernel; + //---------------------------------- // Public methods //---------------------------------- /** * Construct an object of this type -* @param wsname :: The name of the workspace object from which to retrieve the -* log files -* @param mui :: The MantidUI area -* @param flags :: Window flags that are passed the the QDialog constructor -* @param experimentInfoIndex :: optional index in the array of +* @param wsname :: The name of the workspace object from which to retrieve the +* log files +* @param mui :: The MantidUI area +* @param flags :: Window flags that are passed the the QDialog constructor +* @param experimentInfoIndex :: optional index in the array of * ExperimentInfo objects. Should only be non-zero for MDWorkspaces. */ MantidSampleLogDialog::MantidSampleLogDialog(const QString &wsname, - MantidUI *mui, Qt::WFlags flags, - size_t experimentInfoIndex) - : QDialog(mui->appWindow(), flags), m_wsname(wsname.toStdString()), - m_experimentInfoIndex(experimentInfoIndex), m_mantidUI(mui) { - std::stringstream ss; - ss << "MantidPlot - " << wsname.toStdString().c_str() << " sample logs"; - setWindowTitle(QString::fromStdString(ss.str())); - - m_tree = new QTreeWidget; - QStringList titles; - titles << "Name" - << "Type" - << "Value" - << "Units"; - m_tree->setHeaderLabels(titles); - m_tree->setSelectionMode(QAbstractItemView::ExtendedSelection); - QHeaderView *hHeader = (QHeaderView *)m_tree->header(); - hHeader->setResizeMode(2, QHeaderView::Stretch); - hHeader->setStretchLastSection(false); - - QHBoxLayout *uiLayout = new QHBoxLayout; - uiLayout->addWidget(m_tree); - - // ----- Filtering options -------------- - QGroupBox *groupBox = new QGroupBox(tr("Filter log values by")); - - filterNone = new QRadioButton("None"); - filterStatus = new QRadioButton("Status"); - filterPeriod = new QRadioButton("Period"); - filterStatusPeriod = new QRadioButton("Status + Period"); - filterStatusPeriod->setChecked(true); - - QVBoxLayout *vbox = new QVBoxLayout; - vbox->addWidget(filterNone); - vbox->addWidget(filterStatus); - vbox->addWidget(filterPeriod); - vbox->addWidget(filterStatusPeriod); - // vbox->addStretch(1); - groupBox->setLayout(vbox); - - // -------------- Statistics on logs ------------------------ - std::string stats[NUM_STATS] = { - "Min:", "Max:", "Mean:", "Time Avg:", "Median:", "Std Dev:", "Duration:"}; - QGroupBox *statsBox = new QGroupBox("Log Statistics"); - QFormLayout *statsBoxLayout = new QFormLayout; - for (size_t i = 0; i < NUM_STATS; i++) { - statLabels[i] = new QLabel(stats[i].c_str()); - statValues[i] = new QLineEdit(""); - statValues[i]->setReadOnly(1); - statsBoxLayout->addRow(statLabels[i], statValues[i]); - } - statsBox->setLayout(statsBoxLayout); - - // -------------- The Import/Close buttons ------------------------ - QHBoxLayout *topButtons = new QHBoxLayout; - buttonPlot = new QPushButton(tr("&Import selected log")); - buttonPlot->setAutoDefault(true); - buttonPlot->setToolTip( - "Import log file as a table and construct a 1D graph if appropriate"); - topButtons->addWidget(buttonPlot); - - buttonClose = new QPushButton(tr("Close")); - buttonClose->setToolTip("Close dialog"); - topButtons->addWidget(buttonClose); - - QVBoxLayout *hbox = new QVBoxLayout; - - // -------------- The ExperimentInfo selector------------------------ - boost::shared_ptr<MultipleExperimentInfos> mei = - AnalysisDataService::Instance().retrieveWS<MultipleExperimentInfos>( - m_wsname); - if (mei) { - if (mei->getNumExperimentInfo() > 0) { - QHBoxLayout *numSelectorLayout = new QHBoxLayout; - QLabel *lbl = new QLabel("Experiment Info #"); - m_spinNumber = new QSpinBox; - m_spinNumber->setMinimum(0); - m_spinNumber->setMaximum(int(mei->getNumExperimentInfo()) - 1); - m_spinNumber->setValue(int(m_experimentInfoIndex)); - numSelectorLayout->addWidget(lbl); - numSelectorLayout->addWidget(m_spinNumber); - // Double-click imports a log file - connect(m_spinNumber, SIGNAL(valueChanged(int)), this, - SLOT(selectExpInfoNumber(int))); - hbox->addLayout(numSelectorLayout); - } - } - - // Finish laying out the right side - hbox->addLayout(topButtons); - hbox->addWidget(groupBox); - hbox->addWidget(statsBox); - hbox->addStretch(1); - - //--- Main layout With 2 sides ----- - QHBoxLayout *mainLayout = new QHBoxLayout(this); - mainLayout->addLayout(uiLayout, 1); // the tree - mainLayout->addLayout(hbox, 0); - // mainLayout->addLayout(bottomButtons); - this->setLayout(mainLayout); - - init(); - - resize(750, 400); - - connect(buttonPlot, SIGNAL(clicked()), this, SLOT(importSelectedLogs())); - connect(buttonClose, SIGNAL(clicked()), this, SLOT(close())); - // want a custom context menu - m_tree->setContextMenuPolicy(Qt::CustomContextMenu); - connect(m_tree, SIGNAL(customContextMenuRequested(const QPoint &)), this, - SLOT(popupMenu(const QPoint &))); - - // Double-click imports a log file - connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, - SLOT(importItem(QTreeWidgetItem *))); - - // Selecting shows the stats of it - connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, - SLOT(showLogStatistics())); - - // Selecting shows the stats of it - connect(m_tree, - SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), - this, SLOT(showLogStatistics())); -} - -//---------------------------------- -// Private methods -//---------------------------------- -/** -* Plot the selected log entries (TimeSeriesProperty or PropertyWithValue) -*/ -void MantidSampleLogDialog::importSelectedLogs() { - QList<QTreeWidgetItem *> items = m_tree->selectedItems(); - QListIterator<QTreeWidgetItem *> pItr(items); - while (pItr.hasNext()) { - importItem(pItr.next()); - } + MantidUI *mui, Qt::WFlags flags, size_t experimentInfoIndex) + : SampleLogDialogBase(wsname, mui->appWindow(), flags, experimentInfoIndex), m_mantidUI(mui) { + std::stringstream ss; + ss << "MantidPlot - " << wsname.toStdString().c_str() << " sample logs"; + setWindowTitle(QString::fromStdString(ss.str())); + + QStringList titles; + titles << "Name" + << "Type" + << "Value" + << "Units"; + m_tree->setHeaderLabels(titles); + m_tree->setSelectionMode(QAbstractItemView::ExtendedSelection); + QHeaderView *hHeader = (QHeaderView *)m_tree->header(); + hHeader->setResizeMode(2, QHeaderView::Stretch); + hHeader->setStretchLastSection(false); + + QHBoxLayout *uiLayout = new QHBoxLayout; + uiLayout->addWidget(m_tree); + + // ----- Filtering options -------------- + QGroupBox *groupBox = new QGroupBox(tr("Filter log values by")); + + filterNone = new QRadioButton("None"); + filterStatus = new QRadioButton("Status"); + filterPeriod = new QRadioButton("Period"); + filterStatusPeriod = new QRadioButton("Status + Period"); + filterStatusPeriod->setChecked(true); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->addWidget(filterNone); + vbox->addWidget(filterStatus); + vbox->addWidget(filterPeriod); + vbox->addWidget(filterStatusPeriod); + // vbox->addStretch(1); + groupBox->setLayout(vbox); + + // -------------- Statistics on logs ------------------------ + std::string stats[NUM_STATS] = { + "Min:", "Max:", "Mean:", "Time Avg:", "Median:", "Std Dev:", "Duration:"}; + QGroupBox *statsBox = new QGroupBox("Log Statistics"); + QFormLayout *statsBoxLayout = new QFormLayout; + for (size_t i = 0; i < NUM_STATS; i++) { + statLabels[i] = new QLabel(stats[i].c_str()); + statValues[i] = new QLineEdit(""); + statValues[i]->setReadOnly(1); + statsBoxLayout->addRow(statLabels[i], statValues[i]); + } + statsBox->setLayout(statsBoxLayout); + + // -------------- The Import/Close buttons ------------------------ + QHBoxLayout *topButtons = new QHBoxLayout; + buttonPlot = new QPushButton(tr("&Import selected log")); + buttonPlot->setAutoDefault(true); + buttonPlot->setToolTip( + "Import log file as a table and construct a 1D graph if appropriate"); + topButtons->addWidget(buttonPlot); + + buttonClose = new QPushButton(tr("Close")); + buttonClose->setToolTip("Close dialog"); + topButtons->addWidget(buttonClose); + + QVBoxLayout *hbox = new QVBoxLayout; + + // -------------- The ExperimentInfo selector------------------------ + boost::shared_ptr<MultipleExperimentInfos> mei = + AnalysisDataService::Instance().retrieveWS<MultipleExperimentInfos>( + m_wsname); + if (mei) { + if (mei->getNumExperimentInfo() > 0) { + QHBoxLayout *numSelectorLayout = new QHBoxLayout; + QLabel *lbl = new QLabel("Experiment Info #"); + m_spinNumber = new QSpinBox; + m_spinNumber->setMinimum(0); + m_spinNumber->setMaximum(int(mei->getNumExperimentInfo()) - 1); + m_spinNumber->setValue(int(m_experimentInfoIndex)); + numSelectorLayout->addWidget(lbl); + numSelectorLayout->addWidget(m_spinNumber); + // Double-click imports a log file + connect(m_spinNumber, SIGNAL(valueChanged(int)), this, + SLOT(selectExpInfoNumber(int))); + hbox->addLayout(numSelectorLayout); + } + } + + // Finish laying out the right side + hbox->addLayout(topButtons); + hbox->addWidget(groupBox); + hbox->addWidget(statsBox); + hbox->addStretch(1); + + //--- Main layout With 2 sides ----- + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->addLayout(uiLayout, 1); // the tree + mainLayout->addLayout(hbox, 0); + // mainLayout->addLayout(bottomButtons); + this->setLayout(mainLayout); + + init(); + + resize(750, 400); + + connect(buttonPlot, SIGNAL(clicked()), this, SLOT(importSelectedLogs())); + connect(buttonClose, SIGNAL(clicked()), this, SLOT(close())); + // want a custom context menu + m_tree->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_tree, SIGNAL(customContextMenuRequested(const QPoint &)), this, + SLOT(popupMenu(const QPoint &))); + + // Double-click imports a log file + connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, + SLOT(importItem(QTreeWidgetItem *))); + + // Selecting shows the stats of it + connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, + SLOT(showLogStatistics())); + + // Selecting shows the stats of it + connect(m_tree, + SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), + this, SLOT(showLogStatistics())); } -/** -* Show Log Statistics when a line is selected -*/ -void MantidSampleLogDialog::showLogStatistics() { - QList<QTreeWidgetItem *> items = m_tree->selectedItems(); - QListIterator<QTreeWidgetItem *> pItr(items); - if (pItr.hasNext()) { - // Show only the first one - showLogStatisticsOfItem(pItr.next()); - } +MantidSampleLogDialog::~MantidSampleLogDialog() { } -//------------------------------------------------------------------------------------------------ -/** -* Show the stats of the log for the selected item -* -* @param item :: The item to be imported -* @throw invalid_argument if format identifier for the item is wrong -*/ -void MantidSampleLogDialog::showLogStatisticsOfItem(QTreeWidgetItem *item) { - // Assume that you can't show the stats - for (size_t i = 0; i < NUM_STATS; i++) { - statValues[i]->setText(QString("")); - } - - // used in numeric time series below, the default filter value - int key = item->data(1, Qt::UserRole).toInt(); - switch (key) { - case numeric: - case string: - case stringTSeries: - case numericArray: - return; - break; - - case numTSeries: - // Calculate the stats - // Get the workspace - if (!m_ei) - return; - - // Now the log - Mantid::Kernel::TimeSeriesPropertyStatistics stats; - Mantid::Kernel::Property *logData = - m_ei->run().getLogData(item->text(0).toStdString()); - // Get the stas if its a series of int or double; fail otherwise - Mantid::Kernel::TimeSeriesProperty<double> *tspd = - dynamic_cast<TimeSeriesProperty<double> *>(logData); - Mantid::Kernel::TimeSeriesProperty<int> *tspi = - dynamic_cast<TimeSeriesProperty<int> *>(logData); - double timeAvg = 0.; - if (tspd) { - stats = tspd->getStatistics(); - timeAvg = tspd->timeAverageValue(); - } else if (tspi) { - stats = tspi->getStatistics(); - timeAvg = tspi->timeAverageValue(); - } else - return; - - // --- Show the stats --- - statValues[0]->setText(QString::number(stats.minimum)); - statValues[1]->setText(QString::number(stats.maximum)); - statValues[2]->setText(QString::number(stats.mean)); - statValues[3]->setText(QString::number(timeAvg)); - statValues[4]->setText(QString::number(stats.median)); - statValues[5]->setText(QString::number(stats.standard_deviation)); - statValues[6]->setText(QString::number(stats.duration)); - return; - break; - } - throw std::invalid_argument("Error importing log entry, wrong data type"); -} //------------------------------------------------------------------------------------------------ /** * Import an item from sample logs * -* @param item :: The item to be imported -* @throw invalid_argument if format identifier for the item is wrong +* @param item :: The item to be imported +* @throw invalid_argument if format identifier for the item is wrong */ void MantidSampleLogDialog::importItem(QTreeWidgetItem *item) { - // used in numeric time series below, the default filter value - int filter = 0; - int key = item->data(1, Qt::UserRole).toInt(); - Mantid::Kernel::Property *logData = NULL; - QString caption = QString::fromStdString(m_wsname) + - QString::fromStdString("-") + item->text(0); - switch (key) { - case numeric: - case string: - m_mantidUI->importString( - item->text(0), item->data(0, Qt::UserRole).toString(), QString(""), - QString::fromStdString( - m_wsname)); // Pretty much just print out the string - break; - case numTSeries: - if (filterStatus->isChecked()) - filter = 1; - if (filterPeriod->isChecked()) - filter = 2; - if (filterStatusPeriod->isChecked()) - filter = 3; - m_mantidUI->importNumSeriesLog(QString::fromStdString(m_wsname), - item->text(0), filter); - break; - case stringTSeries: - m_mantidUI->importStrSeriesLog(item->text(0), - item->data(0, Qt::UserRole).toString(), - QString::fromStdString(m_wsname)); - break; - case numericArray: - logData = m_ei->getLog(item->text(0).toStdString()); - if (!logData) - return; - m_mantidUI->importString( - item->text(0), QString::fromStdString(logData->value()), - QString::fromStdString(","), QString::fromStdString(m_wsname)); - break; - default: - throw std::invalid_argument("Error importing log entry, wrong data type"); - } -} - -//------------------------------------------------------------------------------------------------ -/** -* Popup a custom context menu -*/ -void MantidSampleLogDialog::popupMenu(const QPoint &pos) { - if (!m_tree->itemAt(pos)) { - m_tree->selectionModel()->clear(); - return; - } - - QMenu *menu = new QMenu(m_tree); - - QAction *action = new QAction("Import", m_tree); - connect(action, SIGNAL(triggered()), this, SLOT(importSelectedLogs())); - menu->addAction(action); - - menu->popup(QCursor::pos()); -} - -//------------------------------------------------------------------------------------------------ -/** -* Initialize everything ub tge tree. -*/ -void MantidSampleLogDialog::init() { - m_tree->clear(); - - // ------------------- Retrieve the proper ExperimentInfo workspace - // ------------------------------- - IMDWorkspace_sptr ws = - AnalysisDataService::Instance().retrieveWS<IMDWorkspace>(m_wsname); - if (!ws) - throw std::runtime_error("Wrong type of a workspace (" + m_wsname + - " is not an IMDWorkspace)"); - // Is it MatrixWorkspace, which itself is ExperimentInfo? - m_ei = boost::dynamic_pointer_cast<const ExperimentInfo>(ws); - ; - if (!m_ei) { - boost::shared_ptr<MultipleExperimentInfos> mei = - boost::dynamic_pointer_cast<MultipleExperimentInfos>(ws); - if (mei) { - if (m_experimentInfoIndex >= mei->getNumExperimentInfo()) { - std::cerr << "ExperimentInfo requested (#" + - Strings::toString(m_experimentInfoIndex) + - ") is not available. There are " + - Strings::toString(mei->getNumExperimentInfo()) + - " in the workspace\n"; - // Make a blank experiment info object - m_ei = ExperimentInfo_const_sptr(new ExperimentInfo()); - } else - m_ei = mei->getExperimentInfo( - static_cast<uint16_t>(m_experimentInfoIndex)); - } - } - if (!m_ei) - throw std::runtime_error("Wrong type of a workspace (no ExperimentInfo)"); - - const std::vector<Mantid::Kernel::Property *> &logData = - m_ei->run().getLogData(); - auto pEnd = logData.end(); - int max_length(0); - for (auto pItr = logData.begin(); pItr != pEnd; ++pItr) { - // name() contains the full path, so strip to file name - QString filename = QFileInfo((**pItr).name().c_str()).fileName(); - if (filename.size() > max_length) - max_length = filename.size(); - QTreeWidgetItem *treeItem = new QTreeWidgetItem(QStringList(filename)); - - // store the log contents in the treeItem - // treeItem->setData(0, Qt::UserRole, - // QString::fromStdString((*pItr)->value())); - - // NOTE: The line above appears to be completely unused since it is - // overwritten. And it is real slow. - // So commented out, and putting this placeholder instead - treeItem->setData(0, Qt::UserRole, "value"); - - // Set the units text - treeItem->setText(3, QString::fromStdString((*pItr)->units())); - - // this specifies the format of the data it should be overridden below or - // there is a problem - treeItem->setData(1, Qt::UserRole, -1); - - Mantid::Kernel::TimeSeriesProperty<double> *tspd = - dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double> *>(*pItr); - Mantid::Kernel::TimeSeriesProperty<int> *tspi = - dynamic_cast<Mantid::Kernel::TimeSeriesProperty<int> *>(*pItr); - Mantid::Kernel::TimeSeriesProperty<bool> *tspb = - dynamic_cast<Mantid::Kernel::TimeSeriesProperty<bool> *>(*pItr); - - // See what type of data we have - if (tspd || tspi || tspb) { - treeItem->setText(1, "num. series"); - // state that the string we passed into data[0] is a time series -multiple - // lines with a time and then a number - treeItem->setData(1, Qt::UserRole, static_cast<int>(numTSeries)); - std::ostringstream msg; - if ((*pItr)->size() == 1) { - // Print out the only entry - if (tspd) - msg << tspd->nthValue(0); - else if (tspi) - msg << tspi->nthValue(0); - else if (tspb) - msg << tspb->nthValue(0); - } else { - // Show the # of entries - msg << "(" << (*pItr)->size() << " entries)"; - } - treeItem->setText(2, QString::fromStdString(msg.str())); - } else if (auto strSeries = dynamic_cast< - Mantid::Kernel::TimeSeriesProperty<std::string> *>(*pItr)) { - treeItem->setText(1, "str. series"); - treeItem->setData(1, Qt::UserRole, static_cast<int>(stringTSeries)); - treeItem->setData(0, Qt::UserRole, - QString::fromStdString((*pItr)->value())); - std::ostringstream msg; - if ((*pItr)->size() == 1) { - // Print out the only entry - strSeries->nthValue(1); - } else { - // Show the # of entries - msg << "(" << (*pItr)->size() << " entries)"; - } - treeItem->setText(2, QString::fromStdString(msg.str())); - } else if (dynamic_cast<Mantid::Kernel::PropertyWithValue<std::string> *>( - *pItr)) { - treeItem->setText(1, "string"); - treeItem->setData(1, Qt::UserRole, static_cast<int>(string)); - treeItem->setData(0, Qt::UserRole, - QString::fromStdString((*pItr)->value())); - treeItem->setText(2, QString::fromStdString((*pItr)->value())); - - } else if (dynamic_cast<Mantid::Kernel::PropertyWithValue<int> *>(*pItr) || - dynamic_cast<Mantid::Kernel::PropertyWithValue<double> *>( - *pItr)) { - treeItem->setText(1, "numeric"); - treeItem->setData( - 1, Qt::UserRole, - static_cast<int>(numeric)); // Save the "role" as numeric. - treeItem->setData(0, Qt::UserRole, - QString::fromStdString((*pItr)->value())); - treeItem->setText(2, QString::fromStdString((*pItr)->value())); - } else if (dynamic_cast<Mantid::Kernel::ArrayProperty<int> *>(*pItr) || - dynamic_cast<Mantid::Kernel::ArrayProperty<double> *>(*pItr) || - dynamic_cast< - Mantid::Kernel::PropertyWithValue<std::vector<double>> *>( - *pItr) || - dynamic_cast< - Mantid::Kernel::PropertyWithValue<std::vector<int>> *>( - *pItr)) { - treeItem->setText(1, "numeric array"); - treeItem->setData( - 1, Qt::UserRole, - static_cast<int>(numericArray)); // Save the "role" as numeric array. - treeItem->setData(0, Qt::UserRole, - QString::fromStdString((*pItr)->value())); - std::ostringstream msg; - msg << "(" << (*pItr)->size() << " entries)"; - treeItem->setText(2, QString::fromStdString(msg.str())); - } - - // Add tree item - m_tree->addTopLevelItem(treeItem); - } - - // Resize the columns - m_tree->header()->resizeSection(0, max_length * 10); - m_tree->header()->resizeSection(1, 100); - m_tree->header()->resizeSection(2, 170); - m_tree->header()->resizeSection(3, 90); // units column - m_tree->header()->setMovable(false); - m_tree->setSortingEnabled(true); - m_tree->sortByColumn(0, Qt::AscendingOrder); -} - -/** Slot called when selecting a different experiment info number */ -void MantidSampleLogDialog::selectExpInfoNumber(int num) { - m_experimentInfoIndex = size_t(num); - m_tree->blockSignals(true); - this->init(); - m_tree->blockSignals(false); + // used in numeric time series below, the default filter value + int filter = 0; + int key = item->data(1, Qt::UserRole).toInt(); + Mantid::Kernel::Property *logData = NULL; + QString caption = QString::fromStdString(m_wsname) + + QString::fromStdString("-") + item->text(0); + switch (key) { + case numeric: + case string: + m_mantidUI->importString( + item->text(0), item->data(0, Qt::UserRole).toString(), QString(""), + QString::fromStdString( + m_wsname)); // Pretty much just print out the string + break; + case numTSeries: + if (filterStatus->isChecked()) + filter = 1; + if (filterPeriod->isChecked()) + filter = 2; + if (filterStatusPeriod->isChecked()) + filter = 3; + m_mantidUI->importNumSeriesLog(QString::fromStdString(m_wsname), + item->text(0), filter); + break; + case stringTSeries: + m_mantidUI->importStrSeriesLog(item->text(0), + item->data(0, Qt::UserRole).toString(), + QString::fromStdString(m_wsname)); + break; + case numericArray: + logData = m_ei->getLog(item->text(0).toStdString()); + if (!logData) + return; + m_mantidUI->importString( + item->text(0), QString::fromStdString(logData->value()), + QString::fromStdString(","), QString::fromStdString(m_wsname)); + break; + default: + throw std::invalid_argument("Error importing log entry, wrong data type"); + } } diff --git a/MantidPlot/src/Mantid/MantidSampleLogDialog.h b/MantidPlot/src/Mantid/MantidSampleLogDialog.h index cb957d0f249e76cdc4d471691cfc64f5e9ae9295..0ae6ce6cf4fa1ba15d48e6b70e4ceab742624f46 100644 --- a/MantidPlot/src/Mantid/MantidSampleLogDialog.h +++ b/MantidPlot/src/Mantid/MantidSampleLogDialog.h @@ -4,12 +4,11 @@ //---------------------------------- // Includes //---------------------------------- -#include <QDialog> -#include <QPoint> -#include <QLabel> +#include "SampleLogDialogBase.h" + +// Qt #include <QTextEdit> #include <QLineEdit> -#include "MantidAPI/ExperimentInfo.h" #include <QDoubleSpinBox> //---------------------------------- @@ -20,6 +19,7 @@ class QTreeWidget; class QPushButton; class QRadioButton; class MantidUI; +class ApplicationWindow; /** This class displays a list of log files for a selected workspace. It @@ -49,78 +49,34 @@ 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 MantidSampleLogDialog : public QDialog { - Q_OBJECT +class MantidSampleLogDialog : public SampleLogDialogBase { + Q_OBJECT public: - /// Constructor - MantidSampleLogDialog(const QString &wsname, MantidUI *mui, - Qt::WFlags flags = 0, size_t experimentInfoIndex = 0); - -private slots: - /// Plot logs - void importSelectedLogs(); - - /// Show the stats of the selected log - void showLogStatistics(); - void showLogStatisticsOfItem(QTreeWidgetItem *item); - - /// Context menu popup - void popupMenu(const QPoint &pos); - - /// Import a single item - void importItem(QTreeWidgetItem *item); - - void selectExpInfoNumber(int num); - -private: - /// Initialize the layout - void init(); - - /// A tree widget - QTreeWidget *m_tree; - - /// The workspace name - std::string m_wsname; - - /// Index into the ExperimentInfo list. - size_t m_experimentInfoIndex; - - /// The actual experiment info being looked at. - Mantid::API::ExperimentInfo_const_sptr m_ei; + /// Constructor + MantidSampleLogDialog(const QString &wsname, MantidUI *mui, + Qt::WFlags flags = 0, size_t experimentInfoIndex = 0); - /// Buttons to do things - QPushButton *buttonPlot, *buttonClose; + /// Destructor + virtual ~MantidSampleLogDialog() override; - /// Filter radio buttons - QRadioButton *filterNone, *filterStatus, *filterPeriod, *filterStatusPeriod; +protected slots: - /// Number of statistic values - static const std::size_t NUM_STATS = 7; + /// Import a single item + virtual void importItem(QTreeWidgetItem *item) override; - /// Stats labels - QLabel *statLabels[NUM_STATS]; // minLabel, maxLabel, meanLabel, - // timeAverageLabel, medianLabel, stddevLabel, - // durationLabel; +protected: - /// Testboxes with stats data - QLineEdit *statValues[NUM_STATS]; + /// Filter radio buttons + QRadioButton *filterNone, *filterStatus, *filterPeriod, *filterStatusPeriod; - /// Widget to select the # of the experiment info to look at. - QSpinBox *m_spinNumber; + /// Stats labels + QLabel *statLabels[NUM_STATS]; // minLabel, maxLabel, meanLabel, + // timeAverageLabel, medianLabel, stddevLabel, + // durationLabel; - /// A pointer to the MantidUI object - MantidUI *m_mantidUI; - /// these values are used to specify the format of the log file, all of which - /// are stored as strings - enum logType { - string, ///< indicates the log is a string, no other known formating - numTSeries, ///< for time series properties that contain numbers - stringTSeries, ///< for logs that are string time series properties - numeric, ///< for logs that are single numeric values (int or double) - numericArray ///< for logs that are an array of numeric values (int or - /// double) - }; + /// A pointer to the MantidUI object + MantidUI *m_mantidUI; }; #endif // MANTIDSAMPLELOGDIALOG_H_ diff --git a/MantidPlot/src/Mantid/SampleLogDialogBase.cpp b/MantidPlot/src/Mantid/SampleLogDialogBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9b192cd999077bbfa6e636a7e460ed32d31ab0f --- /dev/null +++ b/MantidPlot/src/Mantid/SampleLogDialogBase.cpp @@ -0,0 +1,360 @@ +//---------------------------------- +// Includes +//---------------------------------- + +#include "SampleLogDialogBase.h" + +// Mantid API +#include <MantidAPI/MultipleExperimentInfos.h> +#include <MantidAPI/IMDWorkspace.h> + +// Mantid Kernel +#include <MantidKernel/TimeSeriesProperty.h> +#include <MantidKernel/ArrayProperty.h> + +// Qt +#include <QTreeWidget> +#include <QHeaderView> +#include <QFileInfo> +#include <QLineEdit> +#include <QMenu> + +using namespace Mantid; +using namespace Mantid::API; +using namespace Mantid::Kernel; + +/** Default constructor, initialises the variables but does not initialise +* any widgets on the window. Child classes must provide their own constructor. +* +* This is done in order to avoid confusion and provide full control +* over the initialisation order and placement of the widgets inside +* the window. +* +* @param wsname The name of the workspace for which the logs will be displayed +* @param parentContainer The parent container relative to which the window will be centered. +* Also delegates the parentContainer to the QDialog(QWidget, flags) constructor. +* @param flags Flags for QT +* Also delegates the flags to the QDialog(QWidget, flags) constructor +* @param experimentInfoIndex Index into the ExperimentInfo list. +* +* @author Martyn Gigg, Tessella Support Services plc +* @date 05/11/2009 +* +*/ +SampleLogDialogBase::SampleLogDialogBase(const QString &wsname, + QWidget *parentContainer, Qt::WFlags flags, size_t experimentInfoIndex) : + QDialog(parentContainer, flags), m_parentContainer(parentContainer), + m_wsname(wsname.toStdString()), m_experimentInfoIndex(experimentInfoIndex), + buttonPlot(nullptr), buttonClose(nullptr), m_spinNumber(nullptr), m_tree(nullptr) { + + // No further initialisation provided, must be done in derived classes + +} + + +SampleLogDialogBase::~SampleLogDialogBase() +{ +} + +//---------------------------------- +// Protected methods +//---------------------------------- +/** +* Plot the selected log entries (TimeSeriesProperty or PropertyWithValue) +* +* @author Martyn Gigg, Tessella Support Services plc +* @date 05/11/2009 +*/ +void SampleLogDialogBase::importSelectedLogs() { + QList<QTreeWidgetItem *> items = m_tree->selectedItems(); + QListIterator<QTreeWidgetItem *> pItr(items); + while (pItr.hasNext()) { + importItem(pItr.next()); + } +} + + +/** +* Show Log Statistics when a line is selected +* +* @author Martyn Gigg, Tessella Support Services plc +* @date 05/11/2009 +*/ +void SampleLogDialogBase::showLogStatistics() { + QList<QTreeWidgetItem *> items = m_tree->selectedItems(); + QListIterator<QTreeWidgetItem *> pItr(items); + if (pItr.hasNext()) { + // Show only the first one + showLogStatisticsOfItem(pItr.next()); + } +} + + +//------------------------------------------------------------------------------------------------ +/** +* Show the stats of the log for the selected item +* +* @param item :: The item to be imported +* @throw invalid_argument if format identifier for the item is wrong +* +* @author Martyn Gigg, Tessella Support Services plc +* @date 05/11/2009 +*/ +void SampleLogDialogBase::showLogStatisticsOfItem(QTreeWidgetItem *item) { + // Assume that you can't show the stats + for (size_t i = 0; i < NUM_STATS; i++) { + statValues[i]->setText(QString("")); + } + + // used in numeric time series below, the default filter value + int key = item->data(1, Qt::UserRole).toInt(); + switch (key) { + case numeric: + case string: + case stringTSeries: + case numericArray: + return; + break; + + case numTSeries: + // Calculate the stats + // Get the workspace + if (!m_ei) + return; + + // Now the log + Mantid::Kernel::TimeSeriesPropertyStatistics stats; + Mantid::Kernel::Property *logData = + m_ei->run().getLogData(item->text(0).toStdString()); + // Get the stas if its a series of int or double; fail otherwise + Mantid::Kernel::TimeSeriesProperty<double> *tspd = + dynamic_cast<TimeSeriesProperty<double> *>(logData); + Mantid::Kernel::TimeSeriesProperty<int> *tspi = + dynamic_cast<TimeSeriesProperty<int> *>(logData); + double timeAvg = 0.; + if (tspd) { + stats = tspd->getStatistics(); + timeAvg = tspd->timeAverageValue(); + } + else if (tspi) { + stats = tspi->getStatistics(); + timeAvg = tspi->timeAverageValue(); + } + else + return; + + // --- Show the stats --- + statValues[0]->setText(QString::number(stats.minimum)); + statValues[1]->setText(QString::number(stats.maximum)); + statValues[2]->setText(QString::number(stats.mean)); + statValues[3]->setText(QString::number(timeAvg)); + statValues[4]->setText(QString::number(stats.median)); + statValues[5]->setText(QString::number(stats.standard_deviation)); + statValues[6]->setText(QString::number(stats.duration)); + return; + break; + } + throw std::invalid_argument("Error importing log entry, wrong data type"); +} + + +//------------------------------------------------------------------------------------------------ +/** +* Popup a custom context menu +* +* @author Martyn Gigg, Tessella Support Services plc +* @date 05/11/2009 +*/ +void SampleLogDialogBase::popupMenu(const QPoint &pos) { + if (!m_tree->itemAt(pos)) { + m_tree->selectionModel()->clear(); + return; + } + + QMenu *menu = new QMenu(m_tree); + + QAction *action = new QAction("Import", m_tree); + connect(action, SIGNAL(triggered()), this, SLOT(importSelectedLogs())); + menu->addAction(action); + + menu->popup(QCursor::pos()); +} + + +//------------------------------------------------------------------------------------------------ +/** +* Initialize everything in the tree. Must be called after a QTreeWidget initialisation +* @author Martyn Gigg, Tessella Support Services plc +* @date 05/11/2009 +*/ +void SampleLogDialogBase::init() { + m_tree->clear(); + + // ------------------- Retrieve the proper ExperimentInfo workspace + // ------------------------------- + IMDWorkspace_sptr ws = + AnalysisDataService::Instance().retrieveWS<IMDWorkspace>(m_wsname); + if (!ws) + throw std::runtime_error("Wrong type of a workspace (" + m_wsname + + " is not an IMDWorkspace)"); + // Is it MatrixWorkspace, which itself is ExperimentInfo? + m_ei = boost::dynamic_pointer_cast<const ExperimentInfo>(ws); + ; + if (!m_ei) { + boost::shared_ptr<MultipleExperimentInfos> mei = + boost::dynamic_pointer_cast<MultipleExperimentInfos>(ws); + if (mei) { + if (m_experimentInfoIndex >= mei->getNumExperimentInfo()) { + std::cerr << "ExperimentInfo requested (#" + + Strings::toString(m_experimentInfoIndex) + + ") is not available. There are " + + Strings::toString(mei->getNumExperimentInfo()) + + " in the workspace\n"; + // Make a blank experiment info object + m_ei = ExperimentInfo_const_sptr(new ExperimentInfo()); + } + else + m_ei = mei->getExperimentInfo( + static_cast<uint16_t>(m_experimentInfoIndex)); + } + } + if (!m_ei) + throw std::runtime_error("Wrong type of a workspace (no ExperimentInfo)"); + + const std::vector<Mantid::Kernel::Property *> &logData = + m_ei->run().getLogData(); + auto pEnd = logData.end(); + int max_length(0); + for (auto pItr = logData.begin(); pItr != pEnd; ++pItr) { + // name() contains the full path, so strip to file name + QString filename = QFileInfo((**pItr).name().c_str()).fileName(); + if (filename.size() > max_length) + max_length = filename.size(); + QTreeWidgetItem *treeItem = new QTreeWidgetItem(QStringList(filename)); + + // store the log contents in the treeItem + // treeItem->setData(0, Qt::UserRole, + // QString::fromStdString((*pItr)->value())); + + // NOTE: The line above appears to be completely unused since it is + // overwritten. And it is real slow. + // So commented out, and putting this placeholder instead + treeItem->setData(0, Qt::UserRole, "value"); + + // Set the units text + treeItem->setText(3, QString::fromStdString((*pItr)->units())); + + // this specifies the format of the data it should be overridden below or + // there is a problem + treeItem->setData(1, Qt::UserRole, -1); + + Mantid::Kernel::TimeSeriesProperty<double> *tspd = + dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double> *>(*pItr); + Mantid::Kernel::TimeSeriesProperty<int> *tspi = + dynamic_cast<Mantid::Kernel::TimeSeriesProperty<int> *>(*pItr); + Mantid::Kernel::TimeSeriesProperty<bool> *tspb = + dynamic_cast<Mantid::Kernel::TimeSeriesProperty<bool> *>(*pItr); + + // See what type of data we have + if (tspd || tspi || tspb) { + treeItem->setText(1, "num. series"); + // state that the string we passed into data[0] is a time series -multiple + // lines with a time and then a number + treeItem->setData(1, Qt::UserRole, static_cast<int>(numTSeries)); + std::ostringstream msg; + if ((*pItr)->size() == 1) { + // Print out the only entry + if (tspd) + msg << tspd->nthValue(0); + else if (tspi) + msg << tspi->nthValue(0); + else if (tspb) + msg << tspb->nthValue(0); + } + else { + // Show the # of entries + msg << "(" << (*pItr)->size() << " entries)"; + } + treeItem->setText(2, QString::fromStdString(msg.str())); + } + else if (auto strSeries = dynamic_cast< + Mantid::Kernel::TimeSeriesProperty<std::string> *>(*pItr)) { + treeItem->setText(1, "str. series"); + treeItem->setData(1, Qt::UserRole, static_cast<int>(stringTSeries)); + treeItem->setData(0, Qt::UserRole, + QString::fromStdString((*pItr)->value())); + std::ostringstream msg; + if ((*pItr)->size() == 1) { + // Print out the only entry + strSeries->nthValue(1); + } + else { + // Show the # of entries + msg << "(" << (*pItr)->size() << " entries)"; + } + treeItem->setText(2, QString::fromStdString(msg.str())); + } + else if (dynamic_cast<Mantid::Kernel::PropertyWithValue<std::string> *>( + *pItr)) { + treeItem->setText(1, "string"); + treeItem->setData(1, Qt::UserRole, static_cast<int>(string)); + treeItem->setData(0, Qt::UserRole, + QString::fromStdString((*pItr)->value())); + treeItem->setText(2, QString::fromStdString((*pItr)->value())); + + } + else if (dynamic_cast<Mantid::Kernel::PropertyWithValue<int> *>(*pItr) || + dynamic_cast<Mantid::Kernel::PropertyWithValue<double> *>( + *pItr)) { + treeItem->setText(1, "numeric"); + treeItem->setData( + 1, Qt::UserRole, + static_cast<int>(numeric)); // Save the "role" as numeric. + treeItem->setData(0, Qt::UserRole, + QString::fromStdString((*pItr)->value())); + treeItem->setText(2, QString::fromStdString((*pItr)->value())); + } + else if (dynamic_cast<Mantid::Kernel::ArrayProperty<int> *>(*pItr) || + dynamic_cast<ArrayProperty<double> *>(*pItr) || + dynamic_cast< + Mantid::Kernel::PropertyWithValue<std::vector<double>> *>( + *pItr) || + dynamic_cast< + Mantid::Kernel::PropertyWithValue<std::vector<int>> *>( + *pItr)) { + treeItem->setText(1, "numeric array"); + treeItem->setData( + 1, Qt::UserRole, + static_cast<int>(numericArray)); // Save the "role" as numeric array. + treeItem->setData(0, Qt::UserRole, + QString::fromStdString((*pItr)->value())); + std::ostringstream msg; + msg << "(" << (*pItr)->size() << " entries)"; + treeItem->setText(2, QString::fromStdString(msg.str())); + } + + // Add tree item + m_tree->addTopLevelItem(treeItem); + } + + // Resize the columns + m_tree->header()->resizeSection(0, max_length * 10); + m_tree->header()->resizeSection(1, 100); + m_tree->header()->resizeSection(2, 170); + m_tree->header()->resizeSection(3, 90); // units column + m_tree->header()->setMovable(false); + m_tree->setSortingEnabled(true); + m_tree->sortByColumn(0, Qt::AscendingOrder); +} + +/** Slot called when selecting a different experiment info number +* +* @author Martyn Gigg, Tessella Support Services plc +* @date 05/11/2009 +*/ +void SampleLogDialogBase::selectExpInfoNumber(int num) { + m_experimentInfoIndex = size_t(num); + m_tree->blockSignals(true); + this->init(); + m_tree->blockSignals(false); +} diff --git a/MantidPlot/src/Mantid/SampleLogDialogBase.h b/MantidPlot/src/Mantid/SampleLogDialogBase.h new file mode 100644 index 0000000000000000000000000000000000000000..5d541de7aff14472b5dc5121014f25338f63cef7 --- /dev/null +++ b/MantidPlot/src/Mantid/SampleLogDialogBase.h @@ -0,0 +1,127 @@ +#ifndef SAMPLELOGDIALOGBASE_H_ +#define SAMPLELOGDIALOGBASE_H_ + +//---------------------------------- +// Includes +//---------------------------------- +#include <QDialog> +#include <MantidAPI/ExperimentInfo.h> + +//---------------------------------- +// Forward declarations +//---------------------------------- + +class QTreeWidgetItem; +class QTreeWidget; +class QPushButton; +class QRadioButton; +class MantidUI; +class ApplicationWindow; +class QLabel; +class QSpinBox; +class QLineEdit; + +/** +This is the base class for the Sample Log Dialog. +It provides methods to create, initialise and show the dialog window +with the log information loaded. + +Original author - Martyn Gigg, Tessella Support Services plc +Refactored into base class by Dimitar Tasev + +@author Dimitar Tasev, Mantid Development Team +@date 18/07/2016 + +Copyright © 2016 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 SampleLogDialogBase : public QDialog{ + Q_OBJECT +public: + /// Constructor + SampleLogDialogBase(const QString &wsname, QWidget *parentContainer, + Qt::WFlags flags = nullptr, size_t experimentInfoIndex = 0); + + /// Virtual Destructor for derived classes + virtual ~SampleLogDialogBase(); + +protected slots: + /// Plot logs + virtual void importSelectedLogs(); + + /// Show the stats of the selected log + virtual void showLogStatistics(); + virtual void showLogStatisticsOfItem(QTreeWidgetItem *item); + + /// Context menu popup + virtual void popupMenu(const QPoint &pos); + + /// Import a single item + virtual void importItem(QTreeWidgetItem *item) = 0; + + virtual void selectExpInfoNumber(int num); + +protected: + /// This function is not virtual because it is called from derived classes + /// without overriding + /// This function initalises everything in the tree widget + void init(); + + /// A tree widget + QTreeWidget *m_tree; + + /// The parent container of the window + QWidget *m_parentContainer; + + /// The workspace name + std::string m_wsname; + + /// Index into the ExperimentInfo list. + size_t m_experimentInfoIndex; + + /// The actual experiment info being looked at. + Mantid::API::ExperimentInfo_const_sptr m_ei; + + /// Buttons to do things + QPushButton *buttonPlot, *buttonClose; + + /// Number of statistic values + static const std::size_t NUM_STATS = 7; + + /// Testboxes with stats data + QLineEdit *statValues[NUM_STATS]; + + /// Widget to select the # of the experiment info to look at. + QSpinBox *m_spinNumber; + + /// these values are used to specify the format of the log file, all of which + /// are stored as strings + enum logType { + string, ///< indicates the log is a string, no other known formating + numTSeries, ///< for time series properties that contain numbers + stringTSeries, ///< for logs that are string time series properties + numeric, ///< for logs that are single numeric values (int or double) + numericArray ///< for logs that are an array of numeric values (int or + /// double) + }; +}; + +#endif //SAMPLELOGDIALOGBASE_H_ \ No newline at end of file