diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui index c61bdcaba05061761b57d5a60046ac404a497035..72c9d108c63a1449c6c40a6ed669b444091eae93 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectDataReduction.ui @@ -1798,7 +1798,7 @@ Later steps in the process (saving, renaming) will not be done.</string> </sizepolicy> </property> <property name="autoLoad" stdset="0"> - <bool>false</bool> + <bool>true</bool> </property> <property name="loadLabelText" stdset="0"> <string>Plot Input</string> diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSqw.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSqw.h index ad26ef5efddfb734edbf97b3fbc9df5b91a068c8..e616371e5669d291e430091d36006dc775777dd6 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSqw.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IndirectSqw.h @@ -47,8 +47,13 @@ namespace CustomInterfaces virtual bool validate(); private slots: - void sOfQwRebinE(bool state); - void sOfQwPlotInput(); + void energyRebinToggle(bool state); + void plotContour(); + void sqwAlgDone(bool error); + + private: + bool validateQRebin(); + bool validateEnergyRebin(); }; } // namespace CustomInterfaces diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSqw.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSqw.cpp index c736b1a73397a511ae8fdd36556d9ccde7858c5d..de3a0ecd662c03648ce30b4e45260c9bf46e4b77 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSqw.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectSqw.cpp @@ -4,6 +4,9 @@ #include <QFileInfo> +using namespace Mantid::API; +using MantidQt::API::BatchAlgorithmRunner; + namespace MantidQt { namespace CustomInterfaces @@ -14,184 +17,254 @@ namespace CustomInterfaces IndirectSqw::IndirectSqw(Ui::IndirectDataReduction& uiForm, QWidget * parent) : IndirectDataReductionTab(uiForm, parent) { - connect(m_uiForm.sqw_ckRebinE, SIGNAL(toggled(bool)), this, SLOT(sOfQwRebinE(bool))); - connect(m_uiForm.sqw_dsSampleInput, SIGNAL(loadClicked()), this, SLOT(sOfQwPlotInput())); - m_uiForm.sqw_leELow->setValidator(m_valDbl); m_uiForm.sqw_leEWidth->setValidator(m_valDbl); m_uiForm.sqw_leEHigh->setValidator(m_valDbl); m_uiForm.sqw_leQLow->setValidator(m_valDbl); m_uiForm.sqw_leQWidth->setValidator(m_valDbl); m_uiForm.sqw_leQHigh->setValidator(m_valDbl); + + connect(m_uiForm.sqw_ckRebinE, SIGNAL(toggled(bool)), this, SLOT(energyRebinToggle(bool))); + connect(m_uiForm.sqw_dsSampleInput, SIGNAL(loadClicked()), this, SLOT(plotContour())); + + connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this, SLOT(sqwAlgDone(bool))); } - + //---------------------------------------------------------------------------------------------- /** Destructor */ IndirectSqw::~IndirectSqw() { } - + void IndirectSqw::setup() { } - void IndirectSqw::run() + bool IndirectSqw::validate() { - QString rebinString = m_uiForm.sqw_leQLow->text() + "," + m_uiForm.sqw_leQWidth->text() + - "," + m_uiForm.sqw_leQHigh->text(); - - QString wsname; - if(m_uiForm.sqw_dsSampleInput->isFileSelectorVisible()) - { - // Load Nexus file into workspace - QString filename = m_uiForm.sqw_dsSampleInput->getFullFilePath(); - QFileInfo fi(filename); - wsname = fi.baseName(); - - if(!loadFile(filename, wsname)) - { - emit showMessageBox("Could not load Nexus file"); - } - } - else - { - // Get the workspace - wsname = m_uiForm.sqw_dsSampleInput->getCurrentDataName(); - } - - QString pyInput = "from mantid.simpleapi import *\n"; + bool valid = true; - // Create output name before rebinning - pyInput += "sqwInput = '" + wsname + "'\n"; - pyInput += "sqwOutput = sqwInput[:-3] + 'sqw'\n"; + UserInputValidator uiv; + uiv.checkDataSelectorIsValid("Sample", m_uiForm.sqw_dsSampleInput); + QString error = uiv.generateErrorMessage(); - if ( m_uiForm.sqw_ckRebinE->isChecked() ) + if(!error.isEmpty()) { - QString eRebinString = m_uiForm.sqw_leELow->text() + "," + m_uiForm.sqw_leEWidth->text() + - "," + m_uiForm.sqw_leEHigh->text(); - - pyInput += "Rebin(InputWorkspace=sqwInput, OutputWorkspace=sqwInput+'_r', Params='" + eRebinString + "')\n" - "sqwInput += '_r'\n"; + valid = false; + emit showMessageBox(error); } - pyInput += - "efixed = " + m_uiForm.leEfixed->text() + "\n" - "rebin = '" + rebinString + "'\n"; + if(m_uiForm.sqw_ckRebinE->isChecked() && !validateEnergyRebin()) + valid = false; - QString rebinType = m_uiForm.sqw_cbRebinType->currentText(); - if(rebinType == "Centre (SofQW)") - pyInput += "SofQW(InputWorkspace=sqwInput, OutputWorkspace=sqwOutput, QAxisBinning=rebin, EMode='Indirect', EFixed=efixed)\n"; - else if(rebinType == "Parallelepiped (SofQW2)") - pyInput += "SofQW2(InputWorkspace=sqwInput, OutputWorkspace=sqwOutput, QAxisBinning=rebin, EMode='Indirect', EFixed=efixed)\n"; - else if(rebinType == "Parallelepiped/Fractional Area (SofQW3)") - pyInput += "SofQW3(InputWorkspace=sqwInput, OutputWorkspace=sqwOutput, QAxisBinning=rebin, EMode='Indirect', EFixed=efixed)\n"; + if(!validateQRebin()) + valid = false; - pyInput += "AddSampleLog(Workspace=sqwOutput, LogName='rebin_type', LogType='String', LogText='"+rebinType+"')\n"; + return valid; + } - if ( m_uiForm.sqw_ckSave->isChecked() ) - { - pyInput += "SaveNexus(InputWorkspace=sqwOutput, Filename=sqwOutput+'.nxs')\n"; + /** + * Validates the Q rebinning parameters. + * + * @returns If the rebinning is valid + */ + bool IndirectSqw::validateQRebin() + { + bool valid = true; - if (m_uiForm.sqw_ckVerbose->isChecked()) - { - pyInput += "logger.notice(\"Resolution file saved to default save directory.\")\n"; - } + if ( m_uiForm.sqw_leQLow->text() == "" ) + { + valid = false; + m_uiForm.sqw_valQLow->setText("*"); + } + else + { + m_uiForm.sqw_valQLow->setText(" "); } - if ( m_uiForm.sqw_cbPlotType->currentText() == "Contour" ) + if ( m_uiForm.sqw_leQWidth->text() == "" ) { - pyInput += "importMatrixWorkspace(sqwOutput).plotGraph2D()\n"; + valid = false; + m_uiForm.sqw_valQWidth->setText("*"); + } + else + { + m_uiForm.sqw_valQWidth->setText(" "); } - else if ( m_uiForm.sqw_cbPlotType->currentText() == "Spectra" ) + if ( m_uiForm.sqw_leQHigh->text() == "" ) { - pyInput += - "nspec = mtd[sqwOutput].getNumberHistograms()\n" - "plotSpectrum(sqwOutput, range(0, nspec))\n"; + valid = false; + m_uiForm.sqw_valQHigh->setText("*"); + } + else + { + m_uiForm.sqw_valQHigh->setText(" "); } - QString pyOutput = m_pythonRunner.runPythonCode(pyInput).trimmed(); + return valid; } - bool IndirectSqw::validate() + /** + * Validates the energy rebinning parameters. + * + * @returns If the rebinning is valid + */ + bool IndirectSqw::validateEnergyRebin() { bool valid = true; - UserInputValidator uiv; - uiv.checkDataSelectorIsValid("Sample", m_uiForm.sqw_dsSampleInput); - QString error = uiv.generateErrorMessage(); - - if (!error.isEmpty()) + if ( m_uiForm.sqw_leELow->text() == "" ) { valid = false; - emit showMessageBox(error); + m_uiForm.sqw_valELow->setText("*"); } - - if ( m_uiForm.sqw_ckRebinE->isChecked() ) + else { - if ( m_uiForm.sqw_leELow->text() == "" ) - { - valid = false; - m_uiForm.sqw_valELow->setText("*"); - } - else - { - m_uiForm.sqw_valELow->setText(" "); - } - - if ( m_uiForm.sqw_leEWidth->text() == "" ) - { - valid = false; - m_uiForm.sqw_valEWidth->setText("*"); - } - else - { - m_uiForm.sqw_valEWidth->setText(" "); - } - - if ( m_uiForm.sqw_leEHigh->text() == "" ) - { - valid = false; - m_uiForm.sqw_valEHigh->setText("*"); - } - else - { - m_uiForm.sqw_valEHigh->setText(" "); - } + m_uiForm.sqw_valELow->setText(" "); } - if ( m_uiForm.sqw_leQLow->text() == "" ) + if ( m_uiForm.sqw_leEWidth->text() == "" ) { valid = false; - m_uiForm.sqw_valQLow->setText("*"); + m_uiForm.sqw_valEWidth->setText("*"); } else { - m_uiForm.sqw_valQLow->setText(" "); + m_uiForm.sqw_valEWidth->setText(" "); } - if ( m_uiForm.sqw_leQWidth->text() == "" ) + if ( m_uiForm.sqw_leEHigh->text() == "" ) { valid = false; - m_uiForm.sqw_valQWidth->setText("*"); + m_uiForm.sqw_valEHigh->setText("*"); } else { - m_uiForm.sqw_valQWidth->setText(" "); + m_uiForm.sqw_valEHigh->setText(" "); } - if ( m_uiForm.sqw_leQHigh->text() == "" ) + return valid; + } + + void IndirectSqw::run() + { + QString sampleWsName = m_uiForm.sqw_dsSampleInput->getCurrentDataName(); + QString sqwWsName = sampleWsName.left(sampleWsName.length() - 4) + "_sqw"; + QString eRebinWsName = sampleWsName.left(sampleWsName.length() - 4) + "_r"; + + QString rebinString = m_uiForm.sqw_leQLow->text() + "," + m_uiForm.sqw_leQWidth->text() + + "," + m_uiForm.sqw_leQHigh->text(); + + // Rebin in energy + bool rebinInEnergy = m_uiForm.sqw_ckRebinE->isChecked(); + if(rebinInEnergy) { - valid = false; - m_uiForm.sqw_valQHigh->setText("*"); + QString eRebinString = m_uiForm.sqw_leELow->text() + "," + m_uiForm.sqw_leEWidth->text() + + "," + m_uiForm.sqw_leEHigh->text(); + + IAlgorithm_sptr energyRebinAlg = AlgorithmManager::Instance().create("Rebin"); + energyRebinAlg->initialize(); + + energyRebinAlg->setProperty("InputWorkspace", sampleWsName.toStdString()); + energyRebinAlg->setProperty("OutputWorkspace", eRebinWsName.toStdString()); + energyRebinAlg->setProperty("Params", eRebinString.toStdString()); + + m_batchAlgoRunner->addAlgorithm(energyRebinAlg); } + + // Get correct S(Q, w) algorithm + QString efixed = m_uiForm.leEfixed->text(); + + IAlgorithm_sptr sqwAlg; + QString rebinType = m_uiForm.sqw_cbRebinType->currentText(); + + if(rebinType == "Centre (SofQW)") + sqwAlg = AlgorithmManager::Instance().create("SofQW"); + else if(rebinType == "Parallelepiped (SofQW2)") + sqwAlg = AlgorithmManager::Instance().create("SofQW2"); + else if(rebinType == "Parallelepiped/Fractional Area (SofQW3)") + sqwAlg = AlgorithmManager::Instance().create("SofQW3"); + + // S(Q, w) algorithm + sqwAlg->initialize(); + + BatchAlgorithmRunner::AlgorithmRuntimeProps sqwInputProps; + if(rebinInEnergy) + sqwInputProps["InputWorkspace"] = eRebinWsName.toStdString(); else + sqwInputProps["InputWorkspace"] = sampleWsName.toStdString(); + + sqwAlg->setProperty("OutputWorkspace", sqwWsName.toStdString()); + sqwAlg->setProperty("QAxisBinning", rebinString.toStdString()); + sqwAlg->setProperty("EMode", "Indirect"); + sqwAlg->setProperty("EFixed", efixed.toStdString()); + + m_batchAlgoRunner->addAlgorithm(sqwAlg, sqwInputProps); + + // Add sample log for S(Q, w) algorithm used + IAlgorithm_sptr sampleLogAlg = AlgorithmManager::Instance().create("AddSampleLog"); + sampleLogAlg->initialize(); + + sampleLogAlg->setProperty("LogName", "rebin_type"); + sampleLogAlg->setProperty("LogType", "String"); + sampleLogAlg->setProperty("LogText", rebinType.toStdString()); + + BatchAlgorithmRunner::AlgorithmRuntimeProps inputToAddSampleLogProps; + inputToAddSampleLogProps["Workspace"] = sqwWsName.toStdString(); + + m_batchAlgoRunner->addAlgorithm(sampleLogAlg, inputToAddSampleLogProps); + + // Save S(Q, w) workspace + if(m_uiForm.sqw_ckSave->isChecked()) { - m_uiForm.sqw_valQHigh->setText(" "); + QString saveFilename = sqwWsName + ".nxs"; + + IAlgorithm_sptr saveNexusAlg = AlgorithmManager::Instance().create("SaveNexus"); + saveNexusAlg->initialize(); + + saveNexusAlg->setProperty("Filename", saveFilename.toStdString()); + + BatchAlgorithmRunner::AlgorithmRuntimeProps inputToSaveNexusProps; + inputToSaveNexusProps["InputWorkspace"] = sqwWsName.toStdString(); + + m_batchAlgoRunner->addAlgorithm(saveNexusAlg, inputToSaveNexusProps); } - return valid; + m_batchAlgoRunner->executeBatch(); + } + + /** + * Handles plotting the S(Q, w) workspace when the algorithm chain is finished. + * + * @param error If the algorithm chain failed + */ + void IndirectSqw::sqwAlgDone(bool error) + { + if(error) + return; + + // Get the workspace name + QString sampleWsName = m_uiForm.sqw_dsSampleInput->getCurrentDataName(); + QString sqwWsName = sampleWsName.left(sampleWsName.length() - 4) + "_sqw"; + + QString pyInput = "sqw_ws = '" + sqwWsName + "'\n"; + QString plotType = m_uiForm.sqw_cbPlotType->currentText(); + + if(plotType == "Contour") + { + pyInput += "plot2D(sqw_ws)\n"; + } + + else if(plotType == "Spectra") + { + pyInput += + "n_spec = mtd[sqw_ws].getNumberHistograms()\n" + "plotSpectrum(sqw_ws, range(0, n_spec))\n"; + } + + m_pythonRunner.runPythonCode(pyInput).trimmed(); } /** @@ -199,11 +272,14 @@ namespace CustomInterfaces * * @param state :: True to enable RiE UI, false to disable */ - void IndirectSqw::sOfQwRebinE(bool state) + void IndirectSqw::energyRebinToggle(bool state) { QString val; - if ( state ) val = "*"; - else val = " "; + if(state) + val = "*"; + else + val = " "; + m_uiForm.sqw_leELow->setEnabled(state); m_uiForm.sqw_leEWidth->setEnabled(state); m_uiForm.sqw_leEHigh->setEnabled(state); @@ -223,32 +299,26 @@ namespace CustomInterfaces * * Creates a colour 2D plot of the data */ - void IndirectSqw::sOfQwPlotInput() + void IndirectSqw::plotContour() { - QString pyInput = "from mantid.simpleapi import *\n" - "from mantidplot import *\n"; - - if (m_uiForm.sqw_dsSampleInput->isValid()) + if(m_uiForm.sqw_dsSampleInput->isValid()) { - if(m_uiForm.sqw_dsSampleInput->isFileSelectorVisible()) - { - //Load file into workspacwe - pyInput += "filename = r'" + m_uiForm.sqw_dsSampleInput->getFullFilePath() + "'\n" - "(dir, file) = os.path.split(filename)\n" - "(sqwInput, ext) = os.path.splitext(file)\n" - "LoadNexus(Filename=filename, OutputWorkspace=sqwInput)\n"; - } - else - { - //Use existing workspace - pyInput += "sqwInput = '" + m_uiForm.sqw_dsSampleInput->getCurrentDataName() + "'\n"; - } - - pyInput += "ConvertSpectrumAxis(InputWorkspace=sqwInput, OutputWorkspace=sqwInput[:-4]+'_rqw', Target='ElasticQ', EMode='Indirect')\n" - "ws = importMatrixWorkspace(sqwInput[:-4]+'_rqw')\n" - "ws.plotGraph2D()\n"; - - QString pyOutput = m_pythonRunner.runPythonCode(pyInput).trimmed(); + QString sampleWsName = m_uiForm.sqw_dsSampleInput->getCurrentDataName(); + + QString convertedWsName = sampleWsName.left(sampleWsName.length() - 4) + "_rqw"; + + IAlgorithm_sptr convertSpecAlg = AlgorithmManager::Instance().create("ConvertSpectrumAxis"); + convertSpecAlg->initialize(); + + convertSpecAlg->setProperty("InputWorkspace", sampleWsName.toStdString()); + convertSpecAlg->setProperty("OutputWorkspace", convertedWsName.toStdString()); + convertSpecAlg->setProperty("Target", "ElasticQ"); + convertSpecAlg->setProperty("EMode", "Indirect"); + + convertSpecAlg->execute(); + + QString pyInput = "plot2D('" + convertedWsName + "')\n"; + m_pythonRunner.runPythonCode(pyInput).trimmed(); } else {