Skip to content
Snippets Groups Projects
IndirectDiagnostics.cpp 16.1 KiB
Newer Older
#include "MantidQtCustomInterfaces/IndirectDiagnostics.h"

Dan Nixon's avatar
Dan Nixon committed
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidKernel/Logger.h"
#include "MantidQtCustomInterfaces/UserInputValidator.h"
Dan Nixon's avatar
Dan Nixon committed

#include <QFileInfo>

Dan Nixon's avatar
Dan Nixon committed
using namespace Mantid::API;

namespace
{
  Mantid::Kernel::Logger g_log("IndirectDiagnostics");
}

namespace MantidQt
{
namespace CustomInterfaces
{
  //----------------------------------------------------------------------------------------------
  /** Constructor
   */
  IndirectDiagnostics::IndirectDiagnostics(Ui::IndirectDataReduction& uiForm, QWidget * parent) :
      IndirectDataReductionTab(uiForm, parent)
Dan Nixon's avatar
Dan Nixon committed
    // Property Tree
    m_propTrees["SlicePropTree"] = new QtTreePropertyBrowser();
    m_uiForm.slice_properties->addWidget(m_propTrees["SlicePropTree"]);
Dan Nixon's avatar
Dan Nixon committed

    // Editor Factories
    DoubleEditorFactory *doubleEditorFactory = new DoubleEditorFactory();
    QtCheckBoxFactory *checkboxFactory = new QtCheckBoxFactory();
    m_propTrees["SlicePropTree"]->setFactoryForManager(m_dblManager, doubleEditorFactory);
    m_propTrees["SlicePropTree"]->setFactoryForManager(m_blnManager, checkboxFactory);
Dan Nixon's avatar
Dan Nixon committed

    // Create Properties
    m_properties["SpecMin"] = m_dblManager->addProperty("Spectra Min");
    m_properties["SpecMax"] = m_dblManager->addProperty("Spectra Max");
    m_dblManager->setDecimals(m_properties["SpecMin"], 0);
    m_dblManager->setMinimum(m_properties["SpecMin"], 1);
    m_dblManager->setDecimals(m_properties["SpecMax"], 0);

    m_properties["PeakStart"] = m_dblManager->addProperty("Start");
    m_properties["PeakEnd"] = m_dblManager->addProperty("End");
    m_properties["BackgroundStart"] = m_dblManager->addProperty("Start");
    m_properties["BackgroundEnd"] = m_dblManager->addProperty("End");

    m_properties["UseTwoRanges"] = m_blnManager->addProperty("Use Two Ranges");

    m_properties["Range1"] = m_grpManager->addProperty("Peak");
    m_properties["Range1"]->addSubProperty(m_properties["PeakStart"]);
    m_properties["Range1"]->addSubProperty(m_properties["PeakEnd"]);
    m_properties["Range2"] = m_grpManager->addProperty("Background");
    m_properties["Range2"]->addSubProperty(m_properties["BackgroundStart"]);
    m_properties["Range2"]->addSubProperty(m_properties["BackgroundEnd"]);
    m_propTrees["SlicePropTree"]->addProperty(m_properties["SpecMin"]);
    m_propTrees["SlicePropTree"]->addProperty(m_properties["SpecMax"]);
    m_propTrees["SlicePropTree"]->addProperty(m_properties["Range1"]);
    m_propTrees["SlicePropTree"]->addProperty(m_properties["UseTwoRanges"]);
    m_propTrees["SlicePropTree"]->addProperty(m_properties["Range2"]);
    // Slice plot
    m_plots["SlicePlot"] = new QwtPlot(m_parentWidget);
    m_rangeSelectors["SlicePeak"] = new MantidWidgets::RangeSelector(m_plots["SlicePlot"]);
    m_rangeSelectors["SliceBackground"] = new MantidWidgets::RangeSelector(m_plots["SlicePlot"]);
    m_plots["SlicePlot"]->setAxisFont(QwtPlot::xBottom, parent->font());
    m_plots["SlicePlot"]->setAxisFont(QwtPlot::yLeft, parent->font());
    m_plots["SlicePlot"]->setCanvasBackground(Qt::white);
    m_uiForm.slice_plot->addWidget(m_plots["SlicePlot"]);
    // Setup second range
    m_rangeSelectors["SliceBackground"]->setColour(Qt::darkGreen); // Dark green for background
    m_rangeSelectors["SliceBackground"]->setRange(m_rangeSelectors["SlicePeak"]->getRange());
Dan Nixon's avatar
Dan Nixon committed

    // Refresh the plot window
    m_plots["SlicePlot"]->replot();
    // Preview plot
    m_plots["SlicePreviewPlot"] = new QwtPlot(m_parentWidget);
    m_plots["SlicePreviewPlot"]->setAxisFont(QwtPlot::xBottom, parent->font());
    m_plots["SlicePreviewPlot"]->setAxisFont(QwtPlot::yLeft, parent->font());
    m_plots["SlicePreviewPlot"]->setCanvasBackground(Qt::white);
    m_uiForm.slice_plotPreview->addWidget(m_plots["SlicePreviewPlot"]);
    m_plots["SlicePreviewPlot"]->replot();

    // SIGNAL/SLOT CONNECTIONS

    // Update properties when a range selector is changed
    /* connect(m_rangeSelectors["SlicePeak"], SIGNAL(minValueChanged(double)), this, SLOT(sliceMinChanged(double))); */
    /* connect(m_rangeSelectors["SlicePeak"], SIGNAL(maxValueChanged(double)), this, SLOT(sliceMaxChanged(double))); */
    /* connect(m_rangeSelectors["SliceBackground"], SIGNAL(minValueChanged(double)), this, SLOT(sliceMinChanged(double))); */
    /* connect(m_rangeSelectors["SliceBackground"], SIGNAL(maxValueChanged(double)), this, SLOT(sliceMaxChanged(double))); */

    // Update range selctors when a property is changed
    connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(sliceUpdateRS(QtProperty*, double)));
    // Enable/disable second range options when checkbox is toggled
    connect(m_blnManager, SIGNAL(valueChanged(QtProperty*, bool)), this, SLOT(sliceTwoRanges(QtProperty*, bool)));
    // Plot slice miniplot when file has finished loading
Dan Nixon's avatar
Dan Nixon committed
    connect(m_uiForm.slice_inputFile, SIGNAL(filesFound()), this, SLOT(slicePlotRaw()));
    // Enables/disables calibration file selection when user toggles Use Calibratin File checkbox
Dan Nixon's avatar
Dan Nixon committed
    connect(m_uiForm.slice_ckUseCalib, SIGNAL(toggled(bool)), this, SLOT(sliceCalib(bool)));
    // Update preview plot when slice algorithm completes
    connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this, SLOT(sliceAlgDone(bool)));

    // Set default UI state
    sliceTwoRanges(0, false);
    m_uiForm.slice_ckUseCalib->setChecked(false);
    sliceCalib(false);
  //----------------------------------------------------------------------------------------------
  /** Destructor
   */
  IndirectDiagnostics::~IndirectDiagnostics()
  {
  }
  void IndirectDiagnostics::setup()
  {
  }

  void IndirectDiagnostics::run()
  {
Dan Nixon's avatar
Dan Nixon committed
    QString suffix = "_" + m_uiForm.cbAnalyser->currentText() + m_uiForm.cbReflection->currentText() + "_slice";
Dan Nixon's avatar
Dan Nixon committed
    QString filenames = m_uiForm.slice_inputFile->getFilenames().join("', r'");

Dan Nixon's avatar
Dan Nixon committed
    std::vector<long> spectraRange;
    spectraRange.push_back(static_cast<long>(m_dblManager->value(m_properties["SpecMin"])));
    spectraRange.push_back(static_cast<long>(m_dblManager->value(m_properties["SpecMax"])));
Dan Nixon's avatar
Dan Nixon committed
    std::vector<double> peakRange;
    peakRange.push_back(m_dblManager->value(m_properties["PeakStart"]));
    peakRange.push_back(m_dblManager->value(m_properties["PeakEnd"]));

    IAlgorithm_sptr sliceAlg = AlgorithmManager::Instance().create("TimeSlice");
    sliceAlg->initialize();

    sliceAlg->setProperty("InputFiles", filenames.toStdString());
    sliceAlg->setProperty("SpectraRange", spectraRange);
    sliceAlg->setProperty("PeakRange", peakRange);
    sliceAlg->setProperty("Verbose", m_uiForm.slice_ckVerbose->isChecked());
    sliceAlg->setProperty("Plot", m_uiForm.slice_ckPlot->isChecked());
    sliceAlg->setProperty("Save", m_uiForm.slice_ckSave->isChecked());
    sliceAlg->setProperty("OutputNameSuffix", suffix.toStdString());
Dan Nixon's avatar
Dan Nixon committed
    if(m_uiForm.slice_ckUseCalib->isChecked())
    {
      QString calibWsName = m_uiForm.slice_dsCalibFile->getCurrentDataName();
      sliceAlg->setProperty("CalibrationWorkspace", calibWsName.toStdString());
Dan Nixon's avatar
Dan Nixon committed
    }

    if(m_blnManager->value(m_properties["UseTwoRanges"]))
    {
      std::vector<double> backgroundRange;
      backgroundRange.push_back(m_dblManager->value(m_properties["BackgroundStart"]));
      backgroundRange.push_back(m_dblManager->value(m_properties["BackgroundEnd"]));
      sliceAlg->setProperty("BackgroundRange", backgroundRange);
    }
Dan Nixon's avatar
Dan Nixon committed
    runAlgorithm(sliceAlg);
  }

  bool IndirectDiagnostics::validate()
  {
Dan Nixon's avatar
Dan Nixon committed
    UserInputValidator uiv;

Dan Nixon's avatar
Dan Nixon committed
    // Check raw input
Dan Nixon's avatar
Dan Nixon committed
    uiv.checkMWRunFilesIsValid("Input", m_uiForm.slice_inputFile);
Dan Nixon's avatar
Dan Nixon committed
    if(m_uiForm.slice_ckUseCalib->isChecked())
Dan Nixon's avatar
Dan Nixon committed
      uiv.checkMWRunFilesIsValid("Calibration", m_uiForm.slice_inputFile);

Dan Nixon's avatar
Dan Nixon committed
    // Check peak range
    auto rangeOne = std::make_pair(m_dblManager->value(m_properties["PeakStart"]), m_dblManager->value(m_properties["PeakEnd"]));
Dan Nixon's avatar
Dan Nixon committed
    uiv.checkValidRange("Range One", rangeOne);

Dan Nixon's avatar
Dan Nixon committed
    // Check background range
    bool useTwoRanges = m_blnManager->value(m_properties["UseTwoRanges"]);
Dan Nixon's avatar
Dan Nixon committed
    if(useTwoRanges)
      auto rangeTwo = std::make_pair(m_dblManager->value(m_properties["BackgroundStart"]), m_dblManager->value(m_properties["BackgroundEnd"]));
Dan Nixon's avatar
Dan Nixon committed
      uiv.checkValidRange("Range Two", rangeTwo);

      uiv.checkRangesDontOverlap(rangeOne, rangeTwo);
    }

Dan Nixon's avatar
Dan Nixon committed
    // Check spectra range
    auto specRange = std::make_pair(m_dblManager->value(m_properties["SpecMin"]), m_dblManager->value(m_properties["SpecMax"]) + 1);
Dan Nixon's avatar
Dan Nixon committed
    uiv.checkValidRange("Spectra Range", specRange);

    QString error = uiv.generateErrorMessage();
Dan Nixon's avatar
Dan Nixon committed
    bool isError = error != "";
Dan Nixon's avatar
Dan Nixon committed
    if(isError)
      g_log.warning(error.toStdString());

Dan Nixon's avatar
Dan Nixon committed
    return !isError;
Dan Nixon's avatar
Dan Nixon committed
   * Sets default spectra, peak and background ranges.
   */
  void IndirectDiagnostics::setDefaultInstDetails()
  {
    //Get spectra, peak and background details
    std::map<QString, QString> instDetails = getInstrumentDetails();

    //Set spectra range
    m_dblManager->setValue(m_properties["SpecMin"], instDetails["SpectraMin"].toDouble());
    m_dblManager->setValue(m_properties["SpecMax"], instDetails["SpectraMax"].toDouble());

    //Set peak and background ranges
    if(instDetails.size() >= 8)
    {
      setMiniPlotGuides("SlicePeak", m_properties["PeakStart"], m_properties["PeakEnd"],
          std::pair<double, double>(instDetails["PeakMin"].toDouble(), instDetails["PeakMax"].toDouble()));
      setMiniPlotGuides("SliceBackground", m_properties["BackStart"], m_properties["BackEnd"],
          std::pair<double, double>(instDetails["BackMin"].toDouble(), instDetails["BackMax"].toDouble()));
    }
  }

  /**
   * Redraw the raw input plot
   */
Dan Nixon's avatar
Dan Nixon committed
  void IndirectDiagnostics::slicePlotRaw()
  {
    disconnect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(updatePreviewPlot()));
    disconnect(m_blnManager, SIGNAL(valueChanged(QtProperty*, bool)), this, SLOT(updatePreviewPlot()));

    setDefaultInstDetails();

Dan Nixon's avatar
Dan Nixon committed
    if ( m_uiForm.slice_inputFile->isValid() )
    {
      QString filename = m_uiForm.slice_inputFile->getFirstFilename();
      QFileInfo fi(filename);
      QString wsname = fi.baseName();

      if(!loadFile(filename, wsname, m_uiForm.leSpectraMin->text().toInt(), m_uiForm.leSpectraMax->text().toInt()))
        emit showMessageBox("Unable to load file.\nCheck whether your file exists and matches the selected instrument in the EnergyTransfer tab.");
      Mantid::API::MatrixWorkspace_sptr input = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
          Mantid::API::AnalysisDataService::Instance().retrieve(wsname.toStdString()));

      const Mantid::MantidVec & dataX = input->readX(0);
      std::pair<double, double> range(dataX.front(), dataX.back());

      plotMiniPlot(input, 0, "SlicePlot");
      setXAxisToCurve("SlicePlot", "SlicePlot");

      setPlotRange("SlicePeak", m_properties["PeakStart"], m_properties["PeakEnd"], range);
      setPlotRange("SliceBackground", m_properties["BackgroundStart"], m_properties["BackgroundEnd"], range);

      replot("SlicePlot");
Dan Nixon's avatar
Dan Nixon committed
    }
    else
    {
      emit showMessageBox("Selected input files are invalid.");
    }

    connect(m_dblManager, SIGNAL(valueChanged(QtProperty*, double)), this, SLOT(updatePreviewPlot()));
    connect(m_blnManager, SIGNAL(valueChanged(QtProperty*, bool)), this, SLOT(updatePreviewPlot()));

    updatePreviewPlot();
   * Set if the second slice range selectors should be shown on the plot
   *
   * @param state :: True to show the second range selectors, false to hide
   */
Dan Nixon's avatar
Dan Nixon committed
  void IndirectDiagnostics::sliceTwoRanges(QtProperty*, bool state)
  {
    m_rangeSelectors["SliceBackground"]->setVisible(state);
  /**
   * Enables/disables the calibration file field and validator
   *
   * @param state :: True to enable calibration file, false otherwise
   */
Dan Nixon's avatar
Dan Nixon committed
  void IndirectDiagnostics::sliceCalib(bool state)
  {
    m_uiForm.slice_dsCalibFile->setEnabled(state);
  /**
   * Handles the value of a range selector minimum value being changed
   *
   * @param val :: New minimum value
   */
Dan Nixon's avatar
Dan Nixon committed
  void IndirectDiagnostics::sliceMinChanged(double val)
  {
    MantidWidgets::RangeSelector* from = qobject_cast<MantidWidgets::RangeSelector*>(sender());
    if ( from == m_rangeSelectors["SlicePeak"] )
      m_dblManager->setValue(m_properties["PeakStart"], val);
    else if ( from == m_rangeSelectors["SliceBackground"] )
      m_dblManager->setValue(m_properties["BackgroundStart"], val);
  /**
   * Handles the value of a range selector maximum value being changed
   *
   * @param val :: New maximum value
   */
Dan Nixon's avatar
Dan Nixon committed
  void IndirectDiagnostics::sliceMaxChanged(double val)
  {
    MantidWidgets::RangeSelector* from = qobject_cast<MantidWidgets::RangeSelector*>(sender());
    if ( from == m_rangeSelectors["SlicePeak"] )
      m_dblManager->setValue(m_properties["PeakEnd"], val);
    else if ( from == m_rangeSelectors["SliceBackground"] )
      m_dblManager->setValue(m_properties["BackgroundEnd"], val);
  /**
   * Update the value of a range selector given a QtProperty
   *
   * @param prop :: Pointer to the QtProperty
   * @param val :: New value of the range selector
   */
Dan Nixon's avatar
Dan Nixon committed
  void IndirectDiagnostics::sliceUpdateRS(QtProperty* prop, double val)
  {
Dan Nixon's avatar
Dan Nixon committed
    if(prop == m_properties["PeakStart"])             m_rangeSelectors["SlicePeak"]->setMinimum(val);
    else if(prop == m_properties["PeakEnd"])          m_rangeSelectors["SlicePeak"]->setMaximum(val);
    else if(prop == m_properties["BackgroundStart"])  m_rangeSelectors["SliceBackground"]->setMinimum(val);
    else if(prop == m_properties["BackgroundEnd"])    m_rangeSelectors["SliceBackground"]->setMaximum(val);
  /**
   * Runs the slice algorithm with preview properties.
   */
  void IndirectDiagnostics::updatePreviewPlot()
  {
    QString suffix = "_" + m_uiForm.cbAnalyser->currentText() + m_uiForm.cbReflection->currentText() + "_slice";
    QString filenames = m_uiForm.slice_inputFile->getFilenames().join("', r'");

    std::vector<long> spectraRange;
    spectraRange.push_back(static_cast<long>(m_dblManager->value(m_properties["SpecMin"])));
    spectraRange.push_back(static_cast<long>(m_dblManager->value(m_properties["SpecMax"])));

    std::vector<double> peakRange;
    peakRange.push_back(m_dblManager->value(m_properties["PeakStart"]));
    peakRange.push_back(m_dblManager->value(m_properties["PeakEnd"]));

    IAlgorithm_sptr sliceAlg = AlgorithmManager::Instance().create("TimeSlice");
    sliceAlg->initialize();

    sliceAlg->setProperty("InputFiles", filenames.toStdString());
    sliceAlg->setProperty("SpectraRange", spectraRange);
    sliceAlg->setProperty("PeakRange", peakRange);
    sliceAlg->setProperty("Verbose", m_uiForm.slice_ckVerbose->isChecked());
    sliceAlg->setProperty("Plot", false);
    sliceAlg->setProperty("Save", false);
    sliceAlg->setProperty("OutputNameSuffix", suffix.toStdString());

    if(m_uiForm.slice_ckUseCalib->isChecked())
    {
      QString calibWsName = m_uiForm.slice_dsCalibFile->getCurrentDataName();
      sliceAlg->setProperty("CalibrationWorkspace", calibWsName.toStdString());
    }

    if(m_blnManager->value(m_properties["UseTwoRanges"]))
    {
      std::vector<double> backgroundRange;
      backgroundRange.push_back(m_dblManager->value(m_properties["BackgroundStart"]));
      backgroundRange.push_back(m_dblManager->value(m_properties["BackgroundEnd"]));
      sliceAlg->setProperty("BackgroundRange", backgroundRange);
    }

    runAlgorithm(sliceAlg);
  }

  /**
   * Updates the preview plot when the algorithm is complete.
   *
   * @param error True if the algorithm was stopped due to error, false otherwise
   */
  void IndirectDiagnostics::sliceAlgDone(bool error)
  {
    if(error)
      return;

    QStringList filenames = m_uiForm.slice_inputFile->getFilenames();
    if(filenames.size() < 1)
      return;

    QString filename = filenames[0].toLower();
    QFileInfo rawFileInfo(filename);
    QString wsName = rawFileInfo.baseName() + "_" + m_uiForm.cbAnalyser->currentText() + m_uiForm.cbReflection->currentText() + "_slice";

    // Plot result spectrum
    plotMiniPlot(wsName, 0, "SlicePreviewPlot", "SlicePreviewCurve");

    // Set X range to data range
    setXAxisToCurve("SlicePreviewPlot", "SlicePreviewCurve");
    m_plots["SlicePreviewPlot"]->replot();
  }

} // namespace CustomInterfaces
} // namespace Mantid