Skip to content
Snippets Groups Projects
ISISEnergyTransfer.cpp 26 KiB
Newer Older
#include "ISISEnergyTransfer.h"
#include "MantidAPI/WorkspaceGroup.h"
#include "../General/UserInputValidator.h"
#include <QFileInfo>
using namespace Mantid::API;
using MantidQt::API::BatchAlgorithmRunner;
Dan Nixon's avatar
Dan Nixon committed
namespace MantidQt {
namespace CustomInterfaces {
//----------------------------------------------------------------------------------------------
/** Constructor
 */
ISISEnergyTransfer::ISISEnergyTransfer(IndirectDataReduction *idrUI,
                                       QWidget *parent)
    : IndirectDataReductionTab(idrUI, parent) {
  m_uiForm.setupUi(parent);

  // SIGNAL/SLOT CONNECTIONS
  // Update instrument information when a new instrument config is selected
  connect(this, SIGNAL(newInstrumentConfiguration()), this,
          SLOT(setInstrumentDefault()));
  // Shows required mapping option UI widgets when a new mapping option is
  // selected from drop down
  connect(m_uiForm.cbGroupingOptions,
          SIGNAL(currentIndexChanged(const QString &)), this,
          SLOT(mappingOptionSelected(const QString &)));
  // Plots raw input data when user clicks Plot Time
  connect(m_uiForm.pbPlotTime, SIGNAL(clicked()), this, SLOT(plotRaw()));
  // Shows message on run button when user is inputting a run number
  connect(m_uiForm.dsRunFiles, SIGNAL(fileTextChanged(const QString &)), this,
          SLOT(pbRunEditing()));
  // Shows message on run button when Mantid is finding the file for a given run
  // number
  connect(m_uiForm.dsRunFiles, SIGNAL(findingFiles()), this,
          SLOT(pbRunFinding()));
  // Reverts run button back to normal when file finding has finished
  connect(m_uiForm.dsRunFiles, SIGNAL(fileFindingFinished()), this,
          SLOT(pbRunFinished()));
  // Handle plotting and saving
  connect(m_uiForm.pbPlot, SIGNAL(clicked()), this, SLOT(plotClicked()));
Louise McCann's avatar
Louise McCann committed
  connect(m_uiForm.pbSave, SIGNAL(clicked()), this, SLOT(saveClicked()));
Dan Nixon's avatar
Dan Nixon committed

  // Update UI widgets to show default values
  mappingOptionSelected(m_uiForm.cbGroupingOptions->currentText());

  // Add validation to custom detector grouping
  QRegExp re("([0-9]+[-:+]?[0-9]*,[ ]?)*[0-9]+[-:+]?[0-9]*");
  m_uiForm.leCustomGroups->setValidator(new QRegExpValidator(re, this));
Dan Nixon's avatar
Dan Nixon committed
  // Validate to remove invalid markers
  validateTab();
}

//----------------------------------------------------------------------------------------------
/** Destructor
 */
ISISEnergyTransfer::~ISISEnergyTransfer() {}

void ISISEnergyTransfer::setup() {}

bool ISISEnergyTransfer::validate() {
  UserInputValidator uiv;

  // Run files input
  if (!m_uiForm.dsRunFiles->isValid()) {
Dan Nixon's avatar
Dan Nixon committed
    uiv.addErrorMessage("Run file range is invalid.");
Dan Nixon's avatar
Dan Nixon committed

  // Calibration file input
  if (m_uiForm.ckUseCalib->isChecked() &&
      !m_uiForm.dsCalibrationFile->isValid()) {
Dan Nixon's avatar
Dan Nixon committed
    uiv.addErrorMessage("Calibration file/workspace is invalid.");
  QString groupingError = validateDetectorGrouping();
  if (!groupingError.isEmpty())
    uiv.addErrorMessage(groupingError);
Dan Nixon's avatar
Dan Nixon committed

  // Rebinning
  if (!m_uiForm.ckDoNotRebin->isChecked()) {
    if (m_uiForm.cbRebinType->currentText() == "Single") {
      double rebinWidth = m_uiForm.spRebinWidth->value();
      if (rebinWidth < 0) {
        // Ensure negative bin width is intentionally logarithmic
        const char *text =
            "The Binning width is currently negative, this suggests "
            "you wish to use logarithmic binning.\n"
            " Do you want to use Logarithmic Binning?";
        int result = QMessageBox::question(
            nullptr, tr("Logarithmic Binning"), tr(text), QMessageBox::Yes,
            QMessageBox::No, QMessageBox::NoButton);
        if (result == QMessageBox::Yes) {
          // Treat rebin width as a positive for validation
          rebinWidth = std::abs(rebinWidth);
        }
      }
      bool rebinValid = !uiv.checkBins(m_uiForm.spRebinLow->value(), rebinWidth,
Dan Nixon's avatar
Dan Nixon committed
                                       m_uiForm.spRebinHigh->value());
      m_uiForm.valRebinLow->setVisible(rebinValid);
      m_uiForm.valRebinWidth->setVisible(rebinValid);
      m_uiForm.valRebinHigh->setVisible(rebinValid);
    } else {
      uiv.checkFieldIsNotEmpty("Rebin string", m_uiForm.leRebinString,
                               m_uiForm.valRebinString);
    }
  } else {
    m_uiForm.valRebinLow->setVisible(false);
    m_uiForm.valRebinWidth->setVisible(false);
    m_uiForm.valRebinHigh->setVisible(false);
    m_uiForm.valRebinString->setVisible(false);
  // DetailedBalance
  if (m_uiForm.ckDetailedBalance->isChecked()) {
    if (m_uiForm.spDetailedBalance->value() == 0.0) {
      uiv.addErrorMessage("Detailed Balance must be more than 0K");
    }
  }

  // Spectra Number check
  const int specMin = m_uiForm.spSpectraMin->value();
  const int specMax = m_uiForm.spSpectraMax->value();
  if (specMin > specMax) {
    uiv.addErrorMessage("Spectra Min must be less than Spectra Max");
  // Background Removal (TOF)
  if (m_uiForm.ckBackgroundRemoval->isChecked()) {
    const int start = m_uiForm.spBackgroundStart->value();
    const int end = m_uiForm.spBackgroundEnd->value();
    if (start > end) {
      uiv.addErrorMessage("Background Start must be less than Background End");
    }
  if (m_uiForm.dsRunFiles->isValid()) {
    int detectorMin = m_uiForm.spPlotTimeSpecMin->value();
    int detectorMax = m_uiForm.spPlotTimeSpecMax->value();

    QString rawFile = m_uiForm.dsRunFiles->getFirstFilename();
    auto pos = rawFile.lastIndexOf(".");
    auto extension = rawFile.right(rawFile.length() - pos);
    QFileInfo rawFileInfo(rawFile);
    std::string name = rawFileInfo.baseName().toStdString();

    IAlgorithm_sptr loadAlg = AlgorithmManager::Instance().create("Load");
    loadAlg->initialize();
    loadAlg->setProperty("Filename", rawFile.toStdString());
    loadAlg->setProperty("OutputWorkspace", name);
    if (extension.compare(".nxs") == 0) {
      int64_t detectorMin =
          static_cast<int64_t>(m_uiForm.spPlotTimeSpecMin->value());
      int64_t detectorMax =
          static_cast<int64_t>(m_uiForm.spPlotTimeSpecMax->value());
      loadAlg->setProperty("SpectrumMin", detectorMin);
      loadAlg->setProperty("SpectrumMax", detectorMax);
    } else {
      loadAlg->setProperty("SpectrumMin", detectorMin);
      loadAlg->setProperty("SpectrumMax", detectorMax);
    }

    loadAlg->execute();

    if (m_uiForm.ckBackgroundRemoval->isChecked()) {
      MatrixWorkspace_sptr tempWs =
          AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(name);
      const double minBack = tempWs->x(0)[0];
      const double maxBack = tempWs->x(0)[tempWs->blocksize()];

      if (m_uiForm.spBackgroundStart->value() < minBack) {
        uiv.addErrorMessage("The Start of Background Removal is less than the "
                            "minimum of the data range");
      }

      if (m_uiForm.spBackgroundEnd->value() > maxBack) {
        uiv.addErrorMessage("The End of Background Removal is more than the "
                            "maximum of the data range");
      }
    }
  }

  QString error = uiv.generateErrorMessage();
  showMessageBox(error);

Dan Nixon's avatar
Dan Nixon committed
  return uiv.isAllInputValid();
}

QString ISISEnergyTransfer::validateDetectorGrouping() {
  if (m_uiForm.cbGroupingOptions->currentText() == "File") {
    if (!m_uiForm.dsMapFile->isValid())
      return "Mapping file is invalid.";
  }
  if (m_uiForm.cbGroupingOptions->currentText() == "Custom") {
    if (m_uiForm.leCustomGroups->text() == "")
      return "Please supply a custom grouping for detectors.";
  }
Dan Nixon's avatar
Dan Nixon committed
void ISISEnergyTransfer::run() {
  IAlgorithm_sptr reductionAlg =
      AlgorithmManager::Instance().create("ISISIndirectEnergyTransfer");
  reductionAlg->initialize();
  BatchAlgorithmRunner::AlgorithmRuntimeProps reductionRuntimeProps;

  QString instName = getInstrumentConfiguration()->getInstrumentName();

  reductionAlg->setProperty("Instrument", instName.toStdString());
Dan Nixon's avatar
Dan Nixon committed
  reductionAlg->setProperty(
      "Analyser",
      getInstrumentConfiguration()->getAnalyserName().toStdString());
  reductionAlg->setProperty(
      "Reflection",
      getInstrumentConfiguration()->getReflectionName().toStdString());

  // Override the efixed for QENS spectrometers only
  QStringList qens;
  qens << "IRIS"
       << "OSIRIS";
  if (qens.contains(instName))
    reductionAlg->setProperty("Efixed", m_uiForm.spEfixed->value());
Dan Nixon's avatar
Dan Nixon committed

  QString files = m_uiForm.dsRunFiles->getFilenames().join(",");
  reductionAlg->setProperty("InputFiles", files.toStdString());

  reductionAlg->setProperty("SumFiles", m_uiForm.ckSumFiles->isChecked());
  reductionAlg->setProperty("LoadLogFiles",
                            m_uiForm.ckLoadLogFiles->isChecked());

  if (m_uiForm.ckUseCalib->isChecked()) {
    QString calibWorkspaceName =
        m_uiForm.dsCalibrationFile->getCurrentDataName();
    reductionAlg->setProperty("CalibrationWorkspace",
                              calibWorkspaceName.toStdString());
Dan Nixon's avatar
Dan Nixon committed
  std::vector<long> detectorRange;
  detectorRange.push_back(m_uiForm.spSpectraMin->value());
  detectorRange.push_back(m_uiForm.spSpectraMax->value());
  reductionAlg->setProperty("SpectraRange", detectorRange);
Dan Nixon's avatar
Dan Nixon committed
  if (m_uiForm.ckBackgroundRemoval->isChecked()) {
    std::vector<double> backgroundRange;
    backgroundRange.push_back(m_uiForm.spBackgroundStart->value());
    backgroundRange.push_back(m_uiForm.spBackgroundEnd->value());
    reductionAlg->setProperty("BackgroundRange", backgroundRange);
Dan Nixon's avatar
Dan Nixon committed
  if (!m_uiForm.ckDoNotRebin->isChecked()) {
    QString rebin;
    if (m_uiForm.cbRebinType->currentIndex() == 0)
      rebin = m_uiForm.spRebinLow->text() + "," +
              m_uiForm.spRebinWidth->text() + "," +
              m_uiForm.spRebinHigh->text();
Dan Nixon's avatar
Dan Nixon committed
    else
Dan Nixon's avatar
Dan Nixon committed
      rebin = m_uiForm.leRebinString->text();
Dan Nixon's avatar
Dan Nixon committed
    reductionAlg->setProperty("RebinString", rebin.toStdString());
Dan Nixon's avatar
Dan Nixon committed
  if (m_uiForm.ckDetailedBalance->isChecked())
    reductionAlg->setProperty("DetailedBalance",
                              m_uiForm.spDetailedBalance->value());

  if (m_uiForm.ckScaleMultiplier->isChecked())
    reductionAlg->setProperty("ScaleFactor",
                              m_uiForm.spScaleMultiplier->value());

  if (m_uiForm.ckCm1Units->isChecked())
    reductionAlg->setProperty("UnitX", "DeltaE_inWavenumber");

  std::pair<std::string, std::string> grouping =
      createMapFile(m_uiForm.cbGroupingOptions->currentText().toStdString());
  reductionAlg->setProperty("GroupingMethod", grouping.first);
    reductionAlg->setProperty("MapFile", grouping.second);
  else if (grouping.first == "Custom")
    reductionAlg->setProperty("GroupingString", grouping.second);
Dan Nixon's avatar
Dan Nixon committed

  reductionAlg->setProperty("FoldMultipleFrames", m_uiForm.ckFold->isChecked());
  reductionAlg->setProperty("OutputWorkspace",
                            "IndirectEnergyTransfer_Workspaces");

  m_batchAlgoRunner->addAlgorithm(reductionAlg, reductionRuntimeProps);

  connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this,
          SLOT(algorithmComplete(bool)));
  disconnect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this,
             SLOT(plotRawComplete(bool)));
  m_batchAlgoRunner->executeBatchAsync();
}

/**
 * Handles completion of the algorithm.
 *
 * Sets result workspace for Python export and ungroups result WorkspaceGroup.
 *
 * @param error True if the algorithm was stopped due to error, false otherwise
 */
void ISISEnergyTransfer::algorithmComplete(bool error) {
  disconnect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this,
             SLOT(algorithmComplete(bool)));

  if (error)
    return;

  WorkspaceGroup_sptr energyTransferOutputGroup =
      AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(
          "IndirectEnergyTransfer_Workspaces");
  if (energyTransferOutputGroup->size() == 0)
    return;

  // Set workspace for Python export as the first result workspace
  m_pythonExportWsName = energyTransferOutputGroup->getNames()[0];
  m_outputWorkspaces = energyTransferOutputGroup->getNames();
Dan Nixon's avatar
Dan Nixon committed
  // Ungroup the output workspace
  energyTransferOutputGroup->removeAll();
  AnalysisDataService::Instance().remove("IndirectEnergyTransfer_Workspaces");

  // Enable plotting and saving
  m_uiForm.pbPlot->setEnabled(true);
  m_uiForm.cbPlotType->setEnabled(true);
  m_uiForm.pbSave->setEnabled(true);
  m_uiForm.ckSaveAclimax->setEnabled(true);
  m_uiForm.ckSaveASCII->setEnabled(true);
  m_uiForm.ckSaveDaveGrp->setEnabled(true);
  m_uiForm.ckSaveNexus->setEnabled(true);
  m_uiForm.ckSaveNXSPE->setEnabled(true);
  m_uiForm.ckSaveSPE->setEnabled(true);
Dan Nixon's avatar
Dan Nixon committed
}

/**
 * Called when the instrument has changed, used to update default values.
 */
void ISISEnergyTransfer::setInstrumentDefault() {
  QMap<QString, QString> instDetails = getInstrumentDetails();

  // Set the search instrument for runs
  m_uiForm.dsRunFiles->setInstrumentOverride(instDetails["instrument"]);

  QStringList qens;
  qens << "IRIS"
       << "OSIRIS";
  m_uiForm.spEfixed->setEnabled(qens.contains(instDetails["instrument"]));

Dan Nixon's avatar
Dan Nixon committed
  if (instDetails["spectra-min"].isEmpty() ||
      instDetails["spectra-max"].isEmpty()) {
    emit showMessageBox("Could not gather necessary data from parameter file.");
    return;
  }
  // Set spectra min/max for spinners in UI
  const int specMin = instDetails["spectra-min"].toInt();
  const int specMax = instDetails["spectra-max"].toInt();
  // Spectra spinners
Dan Nixon's avatar
Dan Nixon committed
  m_uiForm.spSpectraMin->setMinimum(specMin);
  m_uiForm.spSpectraMin->setMaximum(specMax);
  m_uiForm.spSpectraMin->setValue(specMin);

  m_uiForm.spSpectraMax->setMinimum(specMin);
  m_uiForm.spSpectraMax->setMaximum(specMax);
  m_uiForm.spSpectraMax->setValue(specMax);

  // Plot time spectra spinners
  m_uiForm.spPlotTimeSpecMin->setMinimum(1); // 1 to allow for monitors
  m_uiForm.spPlotTimeSpecMin->setMaximum(specMax);
  m_uiForm.spPlotTimeSpecMin->setValue(1);

  m_uiForm.spPlotTimeSpecMax->setMinimum(1);
  m_uiForm.spPlotTimeSpecMax->setMaximum(specMax);
  m_uiForm.spPlotTimeSpecMax->setValue(1);

Dan Nixon's avatar
Dan Nixon committed
  if (!instDetails["Efixed"].isEmpty())
    m_uiForm.spEfixed->setValue(instDetails["Efixed"].toDouble());
  else
    m_uiForm.spEfixed->setValue(0.0);

  // Default rebinning parameters can be set in instrument parameter file
  if (!instDetails["rebin-default"].isEmpty()) {
    m_uiForm.leRebinString->setText(instDetails["rebin-default"]);
    m_uiForm.ckDoNotRebin->setChecked(false);
    QStringList rbp =
        instDetails["rebin-default"].split(",", QString::SkipEmptyParts);
    if (rbp.size() == 3) {
      m_uiForm.spRebinLow->setValue(rbp[0].toDouble());
      m_uiForm.spRebinWidth->setValue(rbp[1].toDouble());
      m_uiForm.spRebinHigh->setValue(rbp[2].toDouble());
      m_uiForm.cbRebinType->setCurrentIndex(0);
    } else {
      m_uiForm.cbRebinType->setCurrentIndex(1);
Dan Nixon's avatar
Dan Nixon committed
  } else {
    m_uiForm.ckDoNotRebin->setChecked(true);
    m_uiForm.spRebinLow->setValue(0.0);
    m_uiForm.spRebinWidth->setValue(0.0);
    m_uiForm.spRebinHigh->setValue(0.0);
    m_uiForm.leRebinString->setText("");
Dan Nixon's avatar
Dan Nixon committed
  if (!instDetails["cm-1-convert-choice"].isEmpty()) {
    bool defaultOptions = instDetails["cm-1-convert-choice"] == "true";
    m_uiForm.ckCm1Units->setChecked(defaultOptions);
Dan Nixon's avatar
Dan Nixon committed
  if (!instDetails["save-nexus-choice"].isEmpty()) {
    bool defaultOptions = instDetails["save-nexus-choice"] == "true";
    m_uiForm.ckSaveNexus->setChecked(defaultOptions);
Dan Nixon's avatar
Dan Nixon committed
  if (!instDetails["save-ascii-choice"].isEmpty()) {
    bool defaultOptions = instDetails["save-ascii-choice"] == "true";
    m_uiForm.ckSaveASCII->setChecked(defaultOptions);
Dan Nixon's avatar
Dan Nixon committed
  if (!instDetails["fold-frames-choice"].isEmpty()) {
    bool defaultOptions = instDetails["fold-frames-choice"] == "true";
    m_uiForm.ckFold->setChecked(defaultOptions);
Dan Nixon's avatar
Dan Nixon committed
}

/**
 * This function runs when the user makes a selection on the cbGroupingOptions
 * QComboBox.
 * @param groupType :: Value of selection made by user.
 */
void ISISEnergyTransfer::mappingOptionSelected(const QString &groupType) {
  if (groupType == "File")
Dan Nixon's avatar
Dan Nixon committed
    m_uiForm.swGrouping->setCurrentIndex(0);
  else if (groupType == "Groups")
Dan Nixon's avatar
Dan Nixon committed
    m_uiForm.swGrouping->setCurrentIndex(1);
  else if (groupType == "Custom")
Dan Nixon's avatar
Dan Nixon committed
    m_uiForm.swGrouping->setCurrentIndex(2);
Matthew Bowles's avatar
Matthew Bowles committed
    m_uiForm.swGrouping->setCurrentIndex(3);
Dan Nixon's avatar
Dan Nixon committed
}

/**
 * This function creates the mapping/grouping file for the data analysis.
 * @param groupType :: Type of grouping (All, Group, Indiviual)
 * @return path to mapping file, or an empty string if file could not be
 * created.
 */
std::pair<std::string, std::string>
ISISEnergyTransfer::createMapFile(const std::string &groupType) {
Dan Nixon's avatar
Dan Nixon committed
  QString specRange =
      m_uiForm.spSpectraMin->text() + "," + m_uiForm.spSpectraMax->text();

  if (groupType == "File") {
    QString groupFile = m_uiForm.dsMapFile->getFirstFilename();
    if (groupFile == "")
      emit showMessageBox("You must enter a path to the .map file.");

    return std::make_pair("File", groupFile.toStdString());
  } else if (groupType == "Groups")
    return std::make_pair("Custom", createDetectorGroupingString());
  else if (groupType == "Default")
Matthew Bowles's avatar
Matthew Bowles committed
    return std::make_pair("IPF", "");
  else if (groupType == "Custom")
    return std::make_pair("Custom",
                          m_uiForm.leCustomGroups->text().toStdString());
  else {
Dan Nixon's avatar
Dan Nixon committed
    // Catch All and Individual
    return std::make_pair(groupType, "");
const std::string ISISEnergyTransfer::createDetectorGroupingString() {

  const unsigned int nGroups = m_uiForm.spNumberGroups->value();
  const unsigned int nSpectra =
Matthew Bowles's avatar
Matthew Bowles committed
      m_uiForm.spSpectraMax->value() - m_uiForm.spSpectraMin->value();
  const unsigned int groupSize = nSpectra / nGroups;
  auto n = groupSize;
  std::stringstream groupingString;
  groupingString << "0-" << std::to_string(n);
  for (auto i = 1u; i < nGroups; ++i) {
    groupingString << ", " << std::to_string(n + 1) << "-";
    n += groupSize;
    groupingString << std::to_string(n);
  }
Matthew Bowles's avatar
Matthew Bowles committed
  if (n != nSpectra) // add remainder as extra group
    groupingString << ", " << std::to_string(n + 1) << "-"
                   << std::to_string(nSpectra);
Dan Nixon's avatar
Dan Nixon committed
/**
 * Converts the checkbox selection to a comma delimited list of save formats for
 *the
 * ISISIndirectEnergyTransfer algorithm.
 *
 * @return A vector of save formats
 */
std::vector<std::string> ISISEnergyTransfer::getSaveFormats() {
  std::vector<std::string> fileFormats;

  if (m_uiForm.ckSaveNexus->isChecked())
    fileFormats.emplace_back("nxs");
Dan Nixon's avatar
Dan Nixon committed
  if (m_uiForm.ckSaveSPE->isChecked())
    fileFormats.emplace_back("spe");
Dan Nixon's avatar
Dan Nixon committed
  if (m_uiForm.ckSaveNXSPE->isChecked())
    fileFormats.emplace_back("nxspe");
Dan Nixon's avatar
Dan Nixon committed
  if (m_uiForm.ckSaveASCII->isChecked())
    fileFormats.emplace_back("ascii");
Dan Nixon's avatar
Dan Nixon committed
  if (m_uiForm.ckSaveAclimax->isChecked())
    fileFormats.emplace_back("aclimax");
Dan Nixon's avatar
Dan Nixon committed
  if (m_uiForm.ckSaveDaveGrp->isChecked())
    fileFormats.emplace_back("davegrp");
Dan Nixon's avatar
Dan Nixon committed

  return fileFormats;
}

/**
 * Plots raw time data from .raw file before any data conversion has been
 * performed.
 */
void ISISEnergyTransfer::plotRaw() {
  using Mantid::specnum_t;
Dan Nixon's avatar
Dan Nixon committed
  using MantidQt::API::BatchAlgorithmRunner;

  if (!m_uiForm.dsRunFiles->isValid()) {
    emit showMessageBox("You must select a run file.");
    return;
  int detectorMin = m_uiForm.spPlotTimeSpecMin->value();
  int detectorMax = m_uiForm.spPlotTimeSpecMax->value();
Dan Nixon's avatar
Dan Nixon committed
  if (detectorMin > detectorMax) {
    emit showMessageBox(
        "Minimum spectra must be less than or equal to maximum spectra.");
    return;
  const int startBack = m_uiForm.spBackgroundStart->value();
  const int endBack = m_uiForm.spBackgroundEnd->value();
  if (m_uiForm.ckBackgroundRemoval->isChecked() == true) {
    if (startBack > endBack) {
      emit showMessageBox("Background Start must be less than Background End");
      return;
    }
  }

Dan Nixon's avatar
Dan Nixon committed
  QString rawFile = m_uiForm.dsRunFiles->getFirstFilename();
  auto pos = rawFile.lastIndexOf(".");
  auto extension = rawFile.right(rawFile.length() - pos);
Dan Nixon's avatar
Dan Nixon committed
  QFileInfo rawFileInfo(rawFile);
  std::string name = rawFileInfo.baseName().toStdString();

  IAlgorithm_sptr loadAlg = AlgorithmManager::Instance().create("Load");
Dan Nixon's avatar
Dan Nixon committed
  loadAlg->initialize();
  loadAlg->setProperty("Filename", rawFile.toStdString());
  loadAlg->setProperty("OutputWorkspace", name);
  loadAlg->setProperty("LoadLogFiles", false);
  if (extension.compare(".nxs") == 0) {
    int64_t detectorMin =
        static_cast<int64_t>(m_uiForm.spPlotTimeSpecMin->value());
    int64_t detectorMax =
        static_cast<int64_t>(m_uiForm.spPlotTimeSpecMax->value());
    loadAlg->setProperty("SpectrumMin", detectorMin);
    loadAlg->setProperty("SpectrumMax", detectorMax);
  } else {
    loadAlg->setProperty("SpectrumMin", detectorMin);
    loadAlg->setProperty("SpectrumMax", detectorMax);
  }

  loadAlg->execute();

  if (m_uiForm.ckBackgroundRemoval->isChecked()) {
    MatrixWorkspace_sptr tempWs =
        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(name);
    const double minBack = tempWs->x(0)[0];
    const double maxBack = tempWs->x(0)[tempWs->blocksize()];

    if (startBack < minBack) {
      emit showMessageBox("The Start of Background Removal is less than the "
                          "minimum of the data range");
      return;
    }

    if (endBack > maxBack) {
      emit showMessageBox("The End of Background Removal is more than the "
                          "maximum of the data range");
      return;
    }
  }
Dan Nixon's avatar
Dan Nixon committed

  // Rebin the workspace to its self to ensure constant binning
  BatchAlgorithmRunner::AlgorithmRuntimeProps inputToRebin;
  inputToRebin["WorkspaceToMatch"] = name;
  inputToRebin["WorkspaceToRebin"] = name;
  inputToRebin["OutputWorkspace"] = name;

  IAlgorithm_sptr rebinAlg =
      AlgorithmManager::Instance().create("RebinToWorkspace");
  rebinAlg->initialize();
  m_batchAlgoRunner->addAlgorithm(rebinAlg, inputToRebin);

  BatchAlgorithmRunner::AlgorithmRuntimeProps inputFromRebin;
  inputFromRebin["InputWorkspace"] = name;

  std::vector<specnum_t> detectorList;
  for (specnum_t i = detectorMin; i <= detectorMax; i++)
Dan Nixon's avatar
Dan Nixon committed
    detectorList.push_back(i);

  if (m_uiForm.ckBackgroundRemoval->isChecked()) {
    std::vector<double> range;
    range.push_back(m_uiForm.spBackgroundStart->value());
    range.push_back(m_uiForm.spBackgroundEnd->value());

    IAlgorithm_sptr calcBackAlg =
        AlgorithmManager::Instance().create("CalculateFlatBackground");
    calcBackAlg->initialize();
    calcBackAlg->setProperty("OutputWorkspace", name + "_bg");
    calcBackAlg->setProperty("Mode", "Mean");
    calcBackAlg->setProperty("StartX", range[0]);
    calcBackAlg->setProperty("EndX", range[1]);
    m_batchAlgoRunner->addAlgorithm(calcBackAlg, inputFromRebin);

    BatchAlgorithmRunner::AlgorithmRuntimeProps inputFromCalcBG;
    inputFromCalcBG["InputWorkspace"] = name + "_bg";

    IAlgorithm_sptr groupAlg =
        AlgorithmManager::Instance().create("GroupDetectors");
    groupAlg->initialize();
    groupAlg->setProperty("OutputWorkspace", name + "_grp");
    groupAlg->setProperty("DetectorList", detectorList);
    m_batchAlgoRunner->addAlgorithm(groupAlg, inputFromCalcBG);

    IAlgorithm_sptr rawGroupAlg =
        AlgorithmManager::Instance().create("GroupDetectors");
    rawGroupAlg->initialize();
    rawGroupAlg->setProperty("OutputWorkspace", name + "_grp_raw");
    rawGroupAlg->setProperty("DetectorList", detectorList);
    m_batchAlgoRunner->addAlgorithm(rawGroupAlg, inputFromRebin);
  } else {
    IAlgorithm_sptr rawGroupAlg =
        AlgorithmManager::Instance().create("GroupDetectors");
    rawGroupAlg->initialize();
    rawGroupAlg->setProperty("OutputWorkspace", name + "_grp");
    rawGroupAlg->setProperty("DetectorList", detectorList);
    m_batchAlgoRunner->addAlgorithm(rawGroupAlg, inputFromRebin);
Dan Nixon's avatar
Dan Nixon committed
  disconnect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this,
             SLOT(algorithmComplete(bool)));
  connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this,
          SLOT(plotRawComplete(bool)));
  m_batchAlgoRunner->executeBatchAsync();
}

/**
 * Handles plotting the result of Plot Raw
 *
 * @param error Indicates if the algorithm chain failed
 */
void ISISEnergyTransfer::plotRawComplete(bool error) {
  disconnect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this,
             SLOT(plotRawComplete(bool)));

  if (error)
    return;

  QString rawFile = m_uiForm.dsRunFiles->getFirstFilename();
  QFileInfo rawFileInfo(rawFile);
  std::string name = rawFileInfo.baseName().toStdString();

  plotSpectrum(QString::fromStdString(name) + "_grp");
}

/**
 * Called when a user starts to type / edit the runs to load.
 */
void ISISEnergyTransfer::pbRunEditing() {
  emit updateRunButton(false, "Editing...",
                       "Run numbers are currently being edited.");
}

/**
 * Called when the FileFinder starts finding the files.
 */
void ISISEnergyTransfer::pbRunFinding() {
  emit updateRunButton(
      false, "Finding files...",
      "Searching for data files for the run numbers entered...");
  m_uiForm.dsRunFiles->setEnabled(false);
}

/**
 * Called when the FileFinder has finished finding the files.
 */
void ISISEnergyTransfer::pbRunFinished() {
  if (!m_uiForm.dsRunFiles->isValid()) {
    emit updateRunButton(
        false, "Invalid Run(s)",
        "Cannot find data files for some of the run numbers entered.");
  } else {
    emit updateRunButton();
Dan Nixon's avatar
Dan Nixon committed
  m_uiForm.dsRunFiles->setEnabled(true);
}
/**
 * Handle mantid plotting of workspaces
 */
void ISISEnergyTransfer::plotClicked() {
  for (const auto &it : m_outputWorkspaces) {
    if (checkADSForPlotSaveWorkspace(it, true)) {
      const auto plotType = m_uiForm.cbPlotType->currentText();
      QString pyInput = "from IndirectReductionCommon import plot_reduction\n";
      pyInput += "plot_reduction('";
      pyInput += QString::fromStdString(it) + "', '";
      pyInput += plotType + "')\n";
      m_pythonRunner.runPythonCode(pyInput);
    }
  }

/**
 * Handle saving of workspaces
 */
void ISISEnergyTransfer::saveClicked() {
  auto saveFormats = getSaveFormats();
  QString pyInput = "from IndirectReductionCommon import save_reduction\n";
  pyInput += "save_reduction([";
  for (const auto &it : m_outputWorkspaces) {
    pyInput += "'" + QString::fromStdString(it) + "', ";
  }
  pyInput += "], [";
  for (const auto &it : saveFormats) {
    pyInput += "'" + QString::fromStdString(it) + "', ";
  pyInput += "]";
  if (m_uiForm.ckCm1Units->isChecked())
    pyInput += ", 'DeltaE_inWavenumber'";
  pyInput += ")\n";
  m_pythonRunner.runPythonCode(pyInput);
}

} // namespace CustomInterfaces
} // namespace Mantid