Newer
Older
Gigg, Martyn Anthony
committed
//----------------------
// Includes
//----------------------
#include "MantidQtCustomInterfaces/SANSRunWindow.h"
#include "MantidQtCustomInterfaces/SANSAddFiles.h"
#include "MantidQtAPI/ManageUserDirectories.h"
Steve Williams
committed
#include "MantidQtAPI/FileDialogHandler.h"
Gigg, Martyn Anthony
committed
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/FacilityInfo.h"
Gigg, Martyn Anthony
committed
#include "MantidKernel/Logger.h"
#include "MantidKernel/Exception.h"
#include "MantidAPI/FrameworkManager.h"
#include "MantidAPI/IAlgorithm.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/AlgorithmManager.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/PropertyManagerDataService.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/WorkspaceGroup.h"
#include "MantidAPI/IEventWorkspace.h"
Russell Taylor
committed
#include "MantidGeometry/Instrument.h"
Gigg, Martyn Anthony
committed
#include "MantidGeometry/IComponent.h"
Gigg, Martyn Anthony
committed
#include "MantidKernel/V3D.h"
Steve Williams
committed
#include "MantidKernel/Exception.h"
#include "MantidAPI/Run.h"
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
#include <QLineEdit>
#include <QHash>
Gigg, Martyn Anthony
committed
#include <QTextStream>
Gigg, Martyn Anthony
committed
#include <QTreeWidgetItem>
#include <QMessageBox>
#include <QInputDialog>
Gigg, Martyn Anthony
committed
#include <QSignalMapper>
Gigg, Martyn Anthony
committed
#include <QHeaderView>
#include <QApplication>
#include <QClipboard>
#include <QTemporaryFile>
Gigg, Martyn Anthony
committed
#include <QDateTime>
Gigg, Martyn Anthony
committed
#include <Poco/StringTokenizer.h>
#include <boost/lexical_cast.hpp>
#include "MantidQtCustomInterfaces/SANSEventSlicing.h"
Steve Williams
committed
Gigg, Martyn Anthony
committed
//Add this class to the list of specialised dialogs in this namespace
namespace MantidQt
{
namespace CustomInterfaces
{
DECLARE_SUBWINDOW(SANSRunWindow);
Gigg, Martyn Anthony
committed
Steve Williams
committed
using namespace MantidQt::MantidWidgets;
Steve Williams
committed
using namespace MantidQt::API;
Gigg, Martyn Anthony
committed
using namespace MantidQt::CustomInterfaces;
Steve Williams
committed
using namespace Mantid::Kernel;
using namespace Mantid::API;
Russell Taylor
committed
using Mantid::Geometry::Instrument_const_sptr;
Gigg, Martyn Anthony
committed
namespace
{
/// static logger for main window
Logger g_log("SANSRunWindow");
/// static logger for centre finding
Logger g_centreFinderLog("CentreFinder");
typedef boost::shared_ptr<Kernel::PropertyManager> ReductionSettings_sptr;
/**
* Returns the PropertyManager object that is used to store the settings
* used by the reduction.
*
* There is a corresponding function in scripts/SANS/isis_reducer.py with
* more information.
*
* @returns the reduction settings.
*/
ReductionSettings_sptr getReductionSettings()
{
// Must match name of the PropertyManager used in the reduction.
static const std::string SETTINGS_PROP_MAN_NAME = "ISISSANSReductionSettings";
if( !PropertyManagerDataService::Instance().doesExist(SETTINGS_PROP_MAN_NAME) )
{
g_log.debug() << "Creating reduction settings PropertyManager object, with name "
<< SETTINGS_PROP_MAN_NAME << ".";
const auto propertyManager = boost::make_shared<Kernel::PropertyManager>();
PropertyManagerDataService::Instance().add(SETTINGS_PROP_MAN_NAME, propertyManager);
return propertyManager;
}
return PropertyManagerDataService::Instance().retrieve(SETTINGS_PROP_MAN_NAME);
}
//----------------------------------------------
Gigg, Martyn Anthony
committed
// Public member functions
//----------------------------------------------
Gigg, Martyn Anthony
committed
///Constructor
SANSRunWindow::SANSRunWindow(QWidget *parent) :
Michael Whitty
committed
UserSubWindow(parent), m_addFilesTab(NULL), m_displayTab(NULL), m_diagnosticsTab(NULL),
m_saveWorkspaces(NULL), m_ins_defdir(""), m_last_dir(""),
Steve Williams
committed
m_cfg_loaded(true), m_userFname(false), m_sample_file(),
Steve Williams
committed
m_warnings_issued(false), m_force_reload(false),
m_newInDir(*this, &SANSRunWindow::handleInputDirChange),
Steve Williams
committed
m_delete_observer(*this, &SANSRunWindow::handleMantidDeleteWorkspace),
Steve Williams
committed
m_s2d_detlabels(), m_loq_detlabels(), m_allowed_batchtags(),
m_have_reducemodule(false), m_dirty_batch_grid(false), m_tmp_batchfile(""),
slicingWindow(NULL)
Gigg, Martyn Anthony
committed
{
ConfigService::Instance().addObserver(m_newInDir);
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
SANSRunWindow::~SANSRunWindow()
{
try
Gigg, Martyn Anthony
committed
{
ConfigService::Instance().removeObserver(m_newInDir);
if( isInitialized() )
{
// Seems to crash on destruction of if I don't do this
AnalysisDataService::Instance().notificationCenter.removeObserver(m_delete_observer);
saveSettings();
delete m_addFilesTab;
}
Michael Whitty
committed
delete m_displayTab;
Sofia Antony
committed
delete m_diagnosticsTab;
}
catch(...)
//we've cleaned up the best we can, move on
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
}
//--------------------------------------------
Gigg, Martyn Anthony
committed
// Private member functions
//--------------------------------------------
Gigg, Martyn Anthony
committed
/**
* Set up the dialog layout
*/
Gigg, Martyn Anthony
committed
void SANSRunWindow::initLayout()
{
Gigg, Martyn Anthony
committed
g_log.debug("Initializing interface layout");
m_uiForm.setupUi(this);
m_reducemapper = new QSignalMapper(this);
//Set column stretch on the mask table
m_uiForm.mask_table->horizontalHeader()->setStretchLastSection(true);
Steve Williams
committed
setupSaveBox();
Gigg, Martyn Anthony
committed
connectButtonSignals();
Steve Williams
committed
m_uiForm.tabWidget->setCurrentWidget(m_uiForm.runNumbers);
Gigg, Martyn Anthony
committed
// Disable most things so that load is the only thing that can be done
m_uiForm.oneDBtn->setEnabled(false);
m_uiForm.twoDBtn->setEnabled(false);
Steve Williams
committed
m_uiForm.saveDefault_btn->setEnabled(false);
Gigg, Martyn Anthony
committed
for( int i = 1; i < 4; ++i)
{
m_uiForm.tabWidget->setTabEnabled(i, false);
}
//Mode switches
Steve Williams
committed
connect(m_uiForm.single_mode_btn, SIGNAL(clicked()),this,SLOT(switchMode()));
connect(m_uiForm.batch_mode_btn, SIGNAL(clicked()), this,SLOT(switchMode()));
Gigg, Martyn Anthony
committed
//Set a custom context menu for the batch table
m_uiForm.batch_table->setContextMenuPolicy(Qt::ActionsContextMenu);
m_batch_paste = new QAction(tr("&Paste"),m_uiForm.batch_table);
m_batch_paste->setShortcut(tr("Ctrl+P"));
connect(m_batch_paste, SIGNAL(activated()), this, SLOT(pasteToBatchTable()));
m_uiForm.batch_table->addAction(m_batch_paste);
m_batch_clear = new QAction(tr("&Clear"),m_uiForm.batch_table);
Gigg, Martyn Anthony
committed
m_uiForm.batch_table->addAction(m_batch_clear);
connect(m_batch_clear, SIGNAL(activated()), this, SLOT(clearBatchTable()));
// Main Logging
m_uiForm.logging_field->attachLoggingChannel();
connect(m_uiForm.logging_field, SIGNAL(warningReceived(const QString &)), this, SLOT(setLoggerTabTitleToWarn()));
Gigg, Martyn Anthony
committed
connect(m_uiForm.logger_clear, SIGNAL(clicked()), this, SLOT(clearLogger()));
// Centre finder logger
m_uiForm.centre_logging->attachLoggingChannel();
connect(m_uiForm.clear_centre_log, SIGNAL(clicked()), m_uiForm.centre_logging, SLOT(clear()));
Gigg, Martyn Anthony
committed
//Create the widget hash maps
initWidgetMaps();
Steve Williams
committed
m_runFiles.reserve(6);
//Text edit map
m_runFiles.push_back(m_uiForm.scatterSample);
m_runFiles.push_back(m_uiForm.scatCan);
m_runFiles.push_back(m_uiForm.transmis);
m_runFiles.push_back(m_uiForm.transCan);
m_runFiles.push_back(m_uiForm.direct);
m_runFiles.push_back(m_uiForm.dirCan);
std::vector<MWRunFiles *>::const_iterator it = m_runFiles.begin();
for ( ; it != m_runFiles.end(); ++it )
{
(*it)->doButtonOpt(MWRunFiles::Icon);
}
connectFirstPageSignals();
Gigg, Martyn Anthony
committed
Steve Williams
committed
initAnalysDetTab();
if( ! m_addFilesTab )
{//sets up the AddFiles tab which must be deleted in the destructor
m_addFilesTab = new SANSAddFiles(this, &m_uiForm);
Michael Whitty
committed
}
Sofia Antony
committed
//diagnostics tab
if(!m_diagnosticsTab)
{
m_diagnosticsTab = new SANSDiagnostics(this,&m_uiForm);
Steve Williams
committed
}
Sofia Antony
committed
connect(this,SIGNAL(userfileLoaded()),m_diagnosticsTab,SLOT(enableMaskFileControls()));
Steve Williams
committed
//Listen for Workspace delete signals
AnalysisDataService::Instance().notificationCenter.addObserver(m_delete_observer);
Steve Williams
committed
// Create the "Display" tab
if ( ! m_displayTab )
{
m_displayTab = new SANSPlotSpecial(this);
m_uiForm.displayLayout->addWidget(m_displayTab);
}
Steve Williams
committed
// connect up phi masking on analysis tab to be in sync with info on masking tab
connect(m_uiForm.mirror_phi, SIGNAL(clicked()), this, SLOT(phiMaskingChanged()));
connect(m_uiForm.detbank_sel, SIGNAL(currentIndexChanged(int)), this, SLOT(phiMaskingChanged(int)));
connect(m_uiForm.phi_min, SIGNAL(editingFinished()), this, SLOT(phiMaskingChanged()));
connect(m_uiForm.phi_max, SIGNAL(editingFinished()), this, SLOT(phiMaskingChanged()));
connect(m_uiForm.slicePb, SIGNAL(clicked()), this, SLOT(handleSlicePushButton()));
Steve Williams
committed
readSettings();
}
/** Ssetup the controls for the Analysis Tab on this form
*/
Steve Williams
committed
void SANSRunWindow::initAnalysDetTab()
{
Gigg, Martyn Anthony
committed
//Add shortened forms of step types to step boxes
m_uiForm.q_dq_opt->setItemData(0, "LIN");
m_uiForm.q_dq_opt->setItemData(1, "LOG");
m_uiForm.qy_dqy_opt->setItemData(0, "LIN");
Steve Williams
committed
//remove the following two lines once the beamfinder is in the new framework
m_uiForm.wav_dw_opt->setItemData(0, "LIN");
m_uiForm.wav_dw_opt->setItemData(1, "LOG");
Steve Williams
committed
//the file widget always has a *.* filter, passing an empty list means we get only that
m_uiForm.floodRearFile->setAlgorithmProperty("CorrectToFile|Filename");
m_uiForm.floodRearFile->isOptional(true);
m_uiForm.floodFrontFile->setAlgorithmProperty("CorrectToFile|Filename");
m_uiForm.floodFrontFile->isOptional(true);
Steve Williams
committed
Steve Williams
committed
//the unicode code for the angstrom symbol is 197, doing the below keeps this file ASCII compatible
static const QChar ANGSROM_SYM(197);
m_uiForm.wavlength_lb->setText(QString("Wavelength (%1)").arg(ANGSROM_SYM));
m_uiForm.qx_lb->setText(QString("Qx (%1^-1)").arg(ANGSROM_SYM));
Steve Williams
committed
m_uiForm.qxy_lb->setText(QString("Qxy (%1^-1)").arg(ANGSROM_SYM));
m_uiForm.transFitOnOff->setText(QString("Trans Fit (%1)").arg(ANGSROM_SYM));
m_uiForm.transFitOnOff_can->setText(QString("Trans Fit (%1)").arg(ANGSROM_SYM));
Anders Markvardsen
committed
m_uiForm.q_rebin->setToolTip("Any string allowed by the Rebin algorithm may be used");
Sofia Antony
committed
Sofia Antony
committed
Steve Williams
committed
makeValidator(m_uiForm.wavRanVal_lb, m_uiForm.wavRanges, m_uiForm.tab_2,
"A comma separated list of numbers is required here");
connectAnalysDetSignals();
Steve Williams
committed
}
Steve Williams
committed
/** Formats a Qlabel to be a validator and adds it to the list
Janik Zikovsky
committed
* @param newValid :: a QLabel to use as a validator
* @param control :: the control whose entry the validator is validates
* @param tab :: the tab that contains this widgets
* @param errorMsg :: the tooltip message that the validator should have
Steve Williams
committed
*/
void SANSRunWindow::makeValidator(QLabel * const newValid, QWidget * control, QWidget * tab, const QString & errorMsg)
{
QPalette pal = newValid->palette();
pal.setColor(QPalette::WindowText, Qt::darkRed);
newValid->setPalette(pal);
newValid->setToolTip(errorMsg);
Gigg, Martyn Anthony
committed
Steve Williams
committed
// regester the validator and say where it's control is
m_validators[newValid] = std::pair<QWidget *, QWidget *>(control, tab);
Gigg, Martyn Anthony
committed
}
/**
* Run local Python initialization code
*/
void SANSRunWindow::initLocalPython()
{
Steve Williams
committed
// Import the SANS module and set the correct instrument
QString result = runPythonCode("try:\n\timport isis_reducer\nexcept (ImportError,SyntaxError), details:\tprint 'Error importing isis_reducer: ' + str(details)\n");
Gigg, Martyn Anthony
committed
if( result.trimmed().isEmpty() )
{
m_have_reducemodule = true;
}
else
{
showInformationBox(result);
m_have_reducemodule = false;
Steve Williams
committed
setProcessingState(NoSample);
Gigg, Martyn Anthony
committed
}
runPythonCode("import ISISCommandInterface as i\nimport copy");
runPythonCode("import isis_instrument\nimport isis_reduction_steps");
loadUserFile();
handleInstrumentChange();
m_cfg_loaded = true;
Gigg, Martyn Anthony
committed
}
Steve Williams
committed
/** Initialise some of the data and signal connections in the save box
*/
void SANSRunWindow::setupSaveBox()
{
connect(m_uiForm.saveDefault_btn, SIGNAL(clicked()), this, SLOT(handleDefSaveClick()));
connect(m_uiForm.saveSel_btn, SIGNAL(clicked()),
this, SLOT(saveWorkspacesDialog()));
connect(m_uiForm.saveFilename_btn, SIGNAL(clicked()),
this, SLOT(saveFileBrowse()));
Steve Williams
committed
connect(m_uiForm.outfile_edit, SIGNAL(textEdited(const QString &)),
this, SLOT(setUserFname()));
//link the save option tick boxes to their save algorithm
m_savFormats.insert(m_uiForm.saveNex_check, "SaveNexus");
m_savFormats.insert(m_uiForm.saveNIST_Qxy_check, "SaveNISTDAT");
Steve Williams
committed
m_savFormats.insert(m_uiForm.saveCan_check, "SaveCanSAS1D");
m_savFormats.insert(m_uiForm.saveRKH_check, "SaveRKH");
Steve Williams
committed
m_savFormats.insert(m_uiForm.saveCSV_check, "SaveCSV");
for(SavFormatsConstIt i=m_savFormats.begin(); i != m_savFormats.end(); ++i)
{
connect(i.key(), SIGNAL(stateChanged(int)),
this, SLOT(enableOrDisableDefaultSave()));
}
}
/** Raises a saveWorkspaces dialog which allows people to save any workspace or
* workspaces the user chooses
*/
void SANSRunWindow::saveWorkspacesDialog()
{
Steve Williams
committed
//Qt::WA_DeleteOnClose must be set for the dialog to aviod a memory leak
Steve Williams
committed
m_saveWorkspaces =
new SaveWorkspaces(this, m_uiForm.outfile_edit->text(), m_savFormats);
//this dialog sometimes needs to run Python, pass this to Mantidplot via our runAsPythonScript() signal
connect(m_saveWorkspaces, SIGNAL(runAsPythonScript(const QString&, bool)),
this, SIGNAL(runAsPythonScript(const QString&, bool)));
Steve Williams
committed
//we need know if we have a pointer to a valid window or not
connect(m_saveWorkspaces, SIGNAL(closing()),
this, SLOT(saveWorkspacesClosed()));
Steve Williams
committed
m_uiForm.saveSel_btn->setEnabled(false);
Steve Williams
committed
m_saveWorkspaces->show();
}
/**When the save workspaces dialog box is closes its pointer, m_saveWorkspaces,
* is set to NULL and the raise dialog button is re-enabled
*/
void SANSRunWindow::saveWorkspacesClosed()
{
m_uiForm.saveSel_btn->setEnabled(true);
m_saveWorkspaces = NULL;
}
Steve Williams
committed
/** Connection the buttons to their signals
*/
void SANSRunWindow::connectButtonSignals()
{
connect(m_uiForm.data_dirBtn, SIGNAL(clicked()), this, SLOT(selectDataDir()));
connect(m_uiForm.userfileBtn, SIGNAL(clicked()), this, SLOT(selectUserFile()));
connect(m_uiForm.csv_browse_btn,SIGNAL(clicked()), this, SLOT(selectCSVFile()));
connect(m_uiForm.load_dataBtn, SIGNAL(clicked()), this, SLOT(handleLoadButtonClick()));
connect(m_uiForm.runcentreBtn, SIGNAL(clicked()), this, SLOT(handleRunFindCentre()));
// Reduction buttons
connect(m_uiForm.oneDBtn, SIGNAL(clicked()), m_reducemapper, SLOT(map()));
m_reducemapper->setMapping(m_uiForm.oneDBtn, "1D");
connect(m_uiForm.twoDBtn, SIGNAL(clicked()), m_reducemapper, SLOT(map()));
m_reducemapper->setMapping(m_uiForm.twoDBtn, "2D");
connect(m_reducemapper, SIGNAL(mapped(const QString &)), this, SLOT(handleReduceButtonClick(const QString &)));
connect(m_uiForm.showMaskBtn, SIGNAL(clicked()), this, SLOT(handleShowMaskButtonClick()));
}
/** Calls connect to fix up all the slots for the run tab to their events
Steve Williams
committed
*/
void SANSRunWindow::connectFirstPageSignals()
Steve Williams
committed
{
Steve Williams
committed
//controls on the first tab page
Steve Williams
committed
Steve Williams
committed
connect(m_uiForm.outfile_edit, SIGNAL(textEdited(const QString&)),
this, SLOT(enableOrDisableDefaultSave()));
Steve Williams
committed
Steve Williams
committed
connect(m_uiForm.allowPeriods_ck, SIGNAL(stateChanged(int)), this,
SLOT(disOrEnablePeriods(const int)));
}
/** Calls connect to fix up all the slots for the analysis details tab to their events
*/
void SANSRunWindow::connectAnalysDetSignals()
{
Steve Williams
committed
//controls on the second page
Steve Williams
committed
connect(m_uiForm.wav_dw_opt, SIGNAL(currentIndexChanged(int)), this,
Steve Williams
committed
SLOT(handleWavComboChange(int)));
Steve Williams
committed
connect(m_uiForm.q_dq_opt, SIGNAL(currentIndexChanged(int)), this,
SLOT(handleStepComboChange(int)));
connect(m_uiForm.qy_dqy_opt, SIGNAL(currentIndexChanged(int)), this,
SLOT(handleStepComboChange(int)));
connect(m_uiForm.inst_opt, SIGNAL(currentIndexChanged(int)), this,
Steve Williams
committed
SLOT(handleInstrumentChange()));
connect(m_uiForm.transFit_ck, SIGNAL(stateChanged(int)), this, SLOT(updateTransInfo(int)));
connect(m_uiForm.transFit_ck_can, SIGNAL(stateChanged(int)), this, SLOT(updateTransInfo(int)));
updateTransInfo(m_uiForm.transFit_ck->state());
m_uiForm.transFit_ck_can->toggle();
Steve Williams
committed
connect(m_uiForm.frontDetQrangeOnOff, SIGNAL(stateChanged(int)), this, SLOT(updateFrontDetQrange(int)));
updateFrontDetQrange(m_uiForm.frontDetQrangeOnOff->state());
connect(m_uiForm.enableRearFlood_ck, SIGNAL(stateChanged(int)), this, SLOT(prepareFlood(int)));
connect(m_uiForm.enableFrontFlood_ck, SIGNAL(stateChanged(int)), this, SLOT(prepareFlood(int)));
connect(m_uiForm.trans_selector_opt, SIGNAL(currentIndexChanged(int)), this, SLOT(transSelectorChanged(int)));
transSelectorChanged(0);
connect(m_uiForm.wavRanges, SIGNAL(editingFinished()),
this, SLOT(checkList()));
Steve Williams
committed
}
Gigg, Martyn Anthony
committed
/**
* Initialize the widget maps
*/
void SANSRunWindow::initWidgetMaps()
{
Steve Williams
committed
// batch mode settings
m_allowed_batchtags.insert("sample_sans",0);
m_allowed_batchtags.insert("sample_trans",1);
m_allowed_batchtags.insert("sample_direct_beam",2);
m_allowed_batchtags.insert("can_sans",3);
m_allowed_batchtags.insert("can_trans",4);
m_allowed_batchtags.insert("can_direct_beam",5);
m_allowed_batchtags.insert("background_sans",-1);
m_allowed_batchtags.insert("background_trans",-1);
m_allowed_batchtags.insert("background_direct_beam",-1);
Steve Williams
committed
m_allowed_batchtags.insert("output_as",6);
Steve Williams
committed
// detector info
// SANS2D det names/label map
Gigg, Martyn Anthony
committed
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
QHash<QString, QLabel*> labelsmap;
labelsmap.insert("Front_Det_Z", m_uiForm.dist_smp_frontZ);
labelsmap.insert("Front_Det_X", m_uiForm.dist_smp_frontX);
labelsmap.insert("Front_Det_Rot", m_uiForm.smp_rot);
labelsmap.insert("Rear_Det_X", m_uiForm.dist_smp_rearX);
labelsmap.insert("Rear_Det_Z", m_uiForm.dist_smp_rearZ);
m_s2d_detlabels.append(labelsmap);
labelsmap.clear();
labelsmap.insert("Front_Det_Z", m_uiForm.dist_can_frontZ);
labelsmap.insert("Front_Det_X", m_uiForm.dist_can_frontX);
labelsmap.insert("Front_Det_Rot", m_uiForm.can_rot);
labelsmap.insert("Rear_Det_X", m_uiForm.dist_can_rearX);
labelsmap.insert("Rear_Det_Z", m_uiForm.dist_can_rearZ);
m_s2d_detlabels.append(labelsmap);
labelsmap.clear();
labelsmap.insert("Front_Det_Z", m_uiForm.dist_bkgd_frontZ);
labelsmap.insert("Front_Det_X", m_uiForm.dist_bkgd_frontX);
labelsmap.insert("Front_Det_Rot", m_uiForm.bkgd_rot);
labelsmap.insert("Rear_Det_X", m_uiForm.dist_bkgd_rearX);
labelsmap.insert("Rear_Det_Z", m_uiForm.dist_bkgd_rearZ);
m_s2d_detlabels.append(labelsmap);
//LOQ labels
labelsmap.clear();
labelsmap.insert("moderator-sample", m_uiForm.dist_sample_ms);
labelsmap.insert("sample-main-detector-bank", m_uiForm.dist_smp_mdb);
labelsmap.insert("sample-HAB",m_uiForm.dist_smp_hab);
m_loq_detlabels.append(labelsmap);
labelsmap.clear();
labelsmap.insert("moderator-sample", m_uiForm.dist_can_ms);
labelsmap.insert("sample-main-detector-bank", m_uiForm.dist_can_mdb);
labelsmap.insert("sample-HAB",m_uiForm.dist_can_hab);
m_loq_detlabels.append(labelsmap);
labelsmap.clear();
labelsmap.insert("moderator-sample", m_uiForm.dist_bkgd_ms);
labelsmap.insert("sample-main-detector-bank", m_uiForm.dist_bkgd_mdb);
labelsmap.insert("sample-HAB", m_uiForm.dist_bkgd_hab);
m_loq_detlabels.append(labelsmap);
Gigg, Martyn Anthony
committed
// Full workspace names as they appear in the service
Steve Williams
committed
m_workspaceNames.clear();
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
/**
* Restore previous input
*/
void SANSRunWindow::readSettings()
{
Gigg, Martyn Anthony
committed
g_log.debug("Reading settings.");
Gigg, Martyn Anthony
committed
QSettings value_store;
value_store.beginGroup("CustomInterfaces/SANSRunWindow");
Steve Williams
committed
Gigg, Martyn Anthony
committed
m_uiForm.userfile_edit->setText(value_store.value("user_file").toString());
Steve Williams
committed
Gigg, Martyn Anthony
committed
m_last_dir = value_store.value("last_dir", "").toString();
Steve Williams
committed
int index = m_uiForm.inst_opt->findText(
value_store.value("instrum", "LOQ").toString());
// if the saved instrument no longer exists set index to zero
index = index < 0 ? 0 : index;
m_uiForm.inst_opt->setCurrentIndex(index);
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
int mode_flag = value_store.value("runmode", 0).toInt();
if( mode_flag == SANSRunWindow::SingleMode )
{
m_uiForm.single_mode_btn->click();
}
else
{
m_uiForm.batch_mode_btn->click();
}
Gigg, Martyn Anthony
committed
//The instrument definition directory
m_ins_defdir = QString::fromStdString(
ConfigService::Instance().getString("instrumentDefinition.directory"));
upDateDataDir();
Gigg, Martyn Anthony
committed
Steve Williams
committed
// Set allowed extensions
m_uiForm.file_opt->clear();
m_uiForm.file_opt->addItem("nexus", QVariant(".nxs"));
m_uiForm.file_opt->addItem("raw", QVariant(".raw"));
Gigg, Martyn Anthony
committed
//Set old file extension
m_uiForm.file_opt->setCurrentIndex(value_store.value("fileextension", 0).toInt());
Steve Williams
committed
m_uiForm.allowPeriods_ck->setChecked(
value_store.value("allow_periods",false).toBool());
Steve Williams
committed
Steve Williams
committed
int i = m_uiForm.wav_dw_opt->findText(
value_store.value("wave_binning", "Linear").toString());
i = i > -1 ? i : 0;
m_uiForm.wav_dw_opt->setCurrentIndex(i);
//ensure this is called once even if the index hadn't changed
handleWavComboChange(i);
Gigg, Martyn Anthony
committed
value_store.endGroup();
Steve Williams
committed
readSaveSettings(value_store);
Gigg, Martyn Anthony
committed
g_log.debug() << "Found previous data directory " << "\nFound previous user mask file "
<< m_uiForm.userfile_edit->text().toStdString()
Gigg, Martyn Anthony
committed
<< "\nFound instrument definition directory " << m_ins_defdir.toStdString() << std::endl;
Steve Williams
committed
}
/** Sets the states of the checkboxes in the save box using those
* in the passed QSettings object
Janik Zikovsky
committed
* @param valueStore :: where the settings will be stored
Steve Williams
committed
*/
void SANSRunWindow::readSaveSettings(QSettings & valueStore)
{
valueStore.beginGroup("CustomInterfaces/SANSRunWindow/SaveOutput");
m_uiForm.saveNex_check->setChecked(valueStore.value("nexus",false).toBool());
m_uiForm.saveCan_check->setChecked(valueStore.value("canSAS",false).toBool());
m_uiForm.saveNIST_Qxy_check->setChecked(valueStore.value("NIST_Qxy",false).toBool());
Steve Williams
committed
m_uiForm.saveRKH_check->setChecked(valueStore.value("RKH", false).toBool());
m_uiForm.saveCSV_check->setChecked(valueStore.value("CSV", false).toBool());
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
/**
Steve Williams
committed
* Save input through QSettings (-> .mantidplot or -> windows registerary) for future use
Gigg, Martyn Anthony
committed
*/
void SANSRunWindow::saveSettings()
{
QSettings value_store;
Gigg, Martyn Anthony
committed
value_store.beginGroup("CustomInterfaces/SANSRunWindow");
Gigg, Martyn Anthony
committed
if( !m_uiForm.userfile_edit->text().isEmpty() )
{
value_store.setValue("user_file", m_uiForm.userfile_edit->text());
}
Gigg, Martyn Anthony
committed
value_store.setValue("last_dir", m_last_dir);
Steve Williams
committed
value_store.setValue("instrum", m_uiForm.inst_opt->currentText());
Gigg, Martyn Anthony
committed
value_store.setValue("fileextension", m_uiForm.file_opt->currentIndex());
Steve Williams
committed
value_store.setValue("allow_periods", m_uiForm.allowPeriods_ck->isChecked());
Steve Williams
committed
Steve Williams
committed
value_store.setValue("wave_binning", m_uiForm.wav_dw_opt->currentText());
Gigg, Martyn Anthony
committed
unsigned int mode_id(0);
if( m_uiForm.single_mode_btn->isChecked() )
{
mode_id = SANSRunWindow::SingleMode;
}
else
{
mode_id = SANSRunWindow::BatchMode;
}
value_store.setValue("runmode",mode_id);
Gigg, Martyn Anthony
committed
value_store.endGroup();
Steve Williams
committed
saveSaveSettings(value_store);
}
/** Stores the state of the checkboxes in the save box with the
* passed QSettings object
Janik Zikovsky
committed
* @param valueStore :: where the settings will be stored
Steve Williams
committed
*/
void SANSRunWindow::saveSaveSettings(QSettings & valueStore)
{
valueStore.beginGroup("CustomInterfaces/SANSRunWindow/SaveOutput");
valueStore.setValue("nexus", m_uiForm.saveNex_check->isChecked());
valueStore.setValue("canSAS", m_uiForm.saveCan_check->isChecked());
valueStore.setValue("NIST_Qxy", m_uiForm.saveNIST_Qxy_check->isChecked());
Steve Williams
committed
valueStore.setValue("RKH", m_uiForm.saveRKH_check->isChecked());
valueStore.setValue("CSV", m_uiForm.saveCSV_check->isChecked());
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
/**
* Run a function from the SANS reduction script, ensuring that the first call imports the module
Janik Zikovsky
committed
* @param pycode :: The code to execute
Gigg, Martyn Anthony
committed
* @returns A trimmed string containing the output of the code execution
*/
QString SANSRunWindow::runReduceScriptFunction(const QString & pycode)
{
if( !m_have_reducemodule )
{
Gigg, Martyn Anthony
committed
return QString();
Gigg, Martyn Anthony
committed
}
Steve Williams
committed
g_log.debug() << "Executing Python: " << pycode.toStdString() << std::endl;
const static QString PYTHON_SEP("C++runReduceScriptFunctionC++");
QString code_torun = pycode + ";print '"+PYTHON_SEP+"p'";
Steve Williams
committed
QString pythonOut = runPythonCode(code_torun).trimmed();
QStringList allOutput = pythonOut.split(PYTHON_SEP);
if ( allOutput.count() < 2 )
{
Steve Williams
committed
QMessageBox::critical(this, "Fatal error found during reduction", "Error reported by Python script, more information maybe found in the scripting console and results log");
Steve Williams
committed
return "Error";
Steve Williams
committed
}
return allOutput[0].trimmed();
Gigg, Martyn Anthony
committed
}
/**
* Trim off Python markers surrounding things like strings or lists that have been
* printed by Python by removing the first and last character
Gigg, Martyn Anthony
committed
*/
void SANSRunWindow::trimPyMarkers(QString & txt)
{
txt.remove(0,1);
txt.chop(1);
}
/** Issues a Python command to load the user file and returns any output if
* there are warnings or errors
* @return the output printed by the Python commands
*/
bool SANSRunWindow::loadUserFile()
Steve Williams
committed
{
const std::string facility = ConfigService::Instance().getFacility().name();
if (facility != "ISIS"){
return false;
}
Steve Williams
committed
QString filetext = m_uiForm.userfile_edit->text().trimmed();
if( filetext.isEmpty() )
{
QMessageBox::warning(this, "Error loading user file", "No user file has been specified");
m_cfg_loaded = false;
return false;
}
Steve Williams
committed
QFile user_file(filetext);
if( !user_file.open(QIODevice::ReadOnly) )
{
QMessageBox::critical(this, "Error loading user file", "Could not open user file \""+filetext+"\"");
m_cfg_loaded = false;
return false;
}
Steve Williams
committed
user_file.close();
//Clear the def masking info table.
int mask_table_count = m_uiForm.mask_table->rowCount();
for( int i = mask_table_count - 1; i >= 0; --i )
{
m_uiForm.mask_table->removeRow(i);
}
Steve Williams
committed
QString pyCode = "i.Clean()";
Steve Williams
committed
pyCode += "\ni.ReductionSingleton().set_instrument(isis_instrument.";
pyCode += getInstrumentClass()+")";
pyCode += "\ni.ReductionSingleton().user_settings =";
Steve Williams
committed
// Use python function to read the settings file and then extract the fields
Steve Williams
committed
pyCode += "isis_reduction_steps.UserFile(r'"+filetext+"')";
Steve Williams
committed
Steve Williams
committed
runReduceScriptFunction(pyCode);
Steve Williams
committed
QString errors = runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().user_settings.execute(i.ReductionSingleton())").trimmed();
// create a string list with a string for each line
const QStringList allOutput = errors.split("\n");
errors.clear();
bool canContinue = false;
for (int i = 0; i < allOutput.count(); ++i)
{
if ( i < allOutput.count()-1 )
{
errors += allOutput[i]+"\n";
}
else
{
canContinue = allOutput[i].trimmed() == "True";
}
}
if ( ! canContinue )
Steve Williams
committed
{
m_cfg_loaded = false;
Steve Williams
committed
return false;
}
const double unit_conv(1000.);
Steve Williams
committed
// Radius
double dbl_param = runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().mask.min_radius").toDouble();
Steve Williams
committed
m_uiForm.rad_min->setText(QString::number(dbl_param*unit_conv));
dbl_param = runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().mask.max_radius").toDouble();
Steve Williams
committed
m_uiForm.rad_max->setText(QString::number(dbl_param*unit_conv));
//Wavelength
m_uiForm.wav_min->setText(runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().to_wavelen.wav_low"));
Steve Williams
committed
m_uiForm.wav_max->setText(runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().to_wavelen.wav_high").trimmed());
Steve Williams
committed
const QString wav_step = runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().to_wavelen.wav_step").trimmed();
Steve Williams
committed
setLimitStepParameter("wavelength", wav_step, m_uiForm.wav_dw,
m_uiForm.wav_dw_opt);
//Q
QString text = runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().to_Q.binning");
Steve Williams
committed
QStringList values = text.split(",");
if( values.count() == 3 )
{
m_uiForm.q_min->setText(values[0].trimmed());
m_uiForm.q_max->setText(values[2].trimmed());
setLimitStepParameter("Q", values[1].trimmed(), m_uiForm.q_dq,
m_uiForm.q_dq_opt);
}
else
{
m_uiForm.q_rebin->setText(text.trimmed());
m_uiForm.q_dq_opt->setCurrentIndex(2);
}
Steve Williams
committed
//Qxy
m_uiForm.qy_max->setText(runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().QXY2"));
Steve Williams
committed
setLimitStepParameter("Qxy", runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().DQXY"), m_uiForm.qy_dqy,
Steve Williams
committed
m_uiForm.qy_dqy_opt);
// The tramission line of the Limits section (read settings for sample and can)
loadTransmissionSettings();
Steve Williams
committed
// The front rescale/shift section
m_uiForm.frontDetRescale->setText(runReduceScriptFunction(
"print i.ReductionSingleton().instrument.getDetector('FRONT').rescaleAndShift.scale").trimmed());
m_uiForm.frontDetShift->setText(runReduceScriptFunction(
"print i.ReductionSingleton().instrument.getDetector('FRONT').rescaleAndShift.shift").trimmed());
QString fitScale = runReduceScriptFunction("print i.ReductionSingleton().instrument.getDetector('FRONT').rescaleAndShift.fitScale").trimmed();
QString fitShift = runReduceScriptFunction("print i.ReductionSingleton().instrument.getDetector('FRONT').rescaleAndShift.fitShift").trimmed();
if ( fitScale == "True" )
m_uiForm.frontDetRescaleCB->setChecked(true);
else
m_uiForm.frontDetRescaleCB->setChecked(false);
if ( fitShift == "True" )
m_uiForm.frontDetShiftCB->setChecked(true);
else
m_uiForm.frontDetShiftCB->setChecked(false);
QString qRangeUserSelected = runReduceScriptFunction("print i.ReductionSingleton().instrument.getDetector('FRONT').rescaleAndShift.qRangeUserSelected").trimmed();
if ( qRangeUserSelected == "True" )
{
m_uiForm.frontDetQrangeOnOff->setChecked(true);
m_uiForm.frontDetQmin->setText(runReduceScriptFunction(
"print i.ReductionSingleton().instrument.getDetector('FRONT').rescaleAndShift.qMin").trimmed());
m_uiForm.frontDetQmax->setText(runReduceScriptFunction(
"print i.ReductionSingleton().instrument.getDetector('FRONT').rescaleAndShift.qMax").trimmed());
}
else
m_uiForm.frontDetQrangeOnOff->setChecked(false);
Steve Williams
committed
//Monitor spectra
m_uiForm.monitor_spec->setText(runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().instrument.get_incident_mon()").trimmed());
Steve Williams
committed
m_uiForm.trans_monitor->setText(runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().instrument.incid_mon_4_trans_calc").trimmed());
Steve Williams
committed
m_uiForm.monitor_interp->setChecked(runReduceScriptFunction(
"print i.ReductionSingleton().instrument.is_interpolating_norm()").trimmed() == "True");
Steve Williams
committed
m_uiForm.trans_interp->setChecked(runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().transmission_calculator.interpolate"
Steve Williams
committed
).trimmed() == "True");
//Direct efficiency correction
m_uiForm.direct_file->setText(runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().instrument.detector_file('rear')"));
Steve Williams
committed
m_uiForm.front_direct_file->setText(runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().instrument.detector_file('front')"));
Steve Williams
committed
QString file = runReduceScriptFunction(
"print i.ReductionSingleton().prep_normalize.getPixelCorrFile('REAR')");
Steve Williams
committed
file = file.trimmed();
//Check if the file name is set to Python's None object and then adjust the controls if there is an empty entry
m_uiForm.floodRearFile->setFileTextWithSearch(file == "None" ? "" : file);
m_uiForm.enableRearFlood_ck->setChecked( ! m_uiForm.floodRearFile->isEmpty() );
m_uiForm.floodRearFile->setEnabled(m_uiForm.enableRearFlood_ck->checkState()
== Qt::Checked);
file = runReduceScriptFunction(
"print i.ReductionSingleton().prep_normalize.getPixelCorrFile('FRONT')");
file = file.trimmed();
m_uiForm.floodFrontFile->setFileTextWithSearch(file == "None" ? "" : file);
m_uiForm.enableFrontFlood_ck->setChecked( ! m_uiForm.floodFrontFile->isEmpty() );
m_uiForm.floodFrontFile->setEnabled(m_uiForm.enableFrontFlood_ck->checkState()
== Qt::Checked);
Steve Williams
committed
//Scale factor
dbl_param = runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton()._corr_and_scale.rescale").toDouble();
Steve Williams
committed
m_uiForm.scale_factor->setText(QString::number(dbl_param/100.));
//Sample offset if one has been specified
dbl_param = runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().instrument.SAMPLE_Z_CORR").toDouble();
Steve Williams
committed
m_uiForm.smpl_offset->setText(QString::number(dbl_param*unit_conv));
//Centre coordinates
// from the ticket #5942 both detectors have center coordinates
Steve Williams
committed
dbl_param = runReduceScriptFunction(
"print i.ReductionSingleton().get_beam_center('rear')[0]").toDouble();
m_uiForm.rear_beam_x->setText(QString::number(dbl_param*1000.0));
Steve Williams
committed
dbl_param = runReduceScriptFunction(
"print i.ReductionSingleton().get_beam_center('rear')[1]").toDouble();
m_uiForm.rear_beam_y->setText(QString::number(dbl_param*1000.0));
// front
dbl_param = runReduceScriptFunction(
"print i.ReductionSingleton().get_beam_center('front')[0]").toDouble();
m_uiForm.front_beam_x->setText(QString::number(dbl_param*1000.0));
dbl_param = runReduceScriptFunction(
"print i.ReductionSingleton().get_beam_center('front')[1]").toDouble();
m_uiForm.front_beam_y->setText(QString::number(dbl_param*1000.0));
Steve Williams
committed
//Gravity switch
QString param = runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().to_Q.get_gravity()").trimmed();
Steve Williams
committed
if( param == "True" )
{
m_uiForm.gravity_check->setChecked(true);
}
else
{
m_uiForm.gravity_check->setChecked(false);
}
////Detector bank: support REAR, FRONT, HAB, BOTH, MERGED, MERGE options
Steve Williams
committed
QString detName = runReduceScriptFunction(
"print i.ReductionSingleton().instrument.det_selection").trimmed();
if (detName == "REAR" || detName == "MAIN"){
m_uiForm.detbank_sel->setCurrentIndex(0);
}else if (detName == "FRONT" || detName == "HAB"){
m_uiForm.detbank_sel->setCurrentIndex(1);
}else if (detName == "BOTH"){
m_uiForm.detbank_sel->setCurrentIndex(2);
}else if (detName == "MERGED" || detName== "MERGE"){
m_uiForm.detbank_sel->setCurrentIndex(3);
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
// Phi values
Steve Williams
committed
m_uiForm.phi_min->setText(runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().mask.phi_min"));
Steve Williams
committed
m_uiForm.phi_max->setText(runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().mask.phi_max"));
Steve Williams
committed
//Masking table
updateMaskTable();
Steve Williams
committed
if ( runReduceScriptFunction(
Steve Williams
committed
"print i.ReductionSingleton().mask.phi_mirror").trimmed() == "True" )
Steve Williams
committed
{
m_uiForm.mirror_phi->setChecked(true);
}
else
{
m_uiForm.mirror_phi->setChecked(false);
}
if ( ! errors.isEmpty() )
{
showInformationBox("User file opened with some warnings:\n"+errors);
}
Gigg, Martyn Anthony
committed
m_cfg_loaded = true;
m_uiForm.userfileBtn->setText("Reload");
Gigg, Martyn Anthony
committed
m_uiForm.tabWidget->setTabEnabled(m_uiForm.tabWidget->count() - 1, true);
m_cfg_loaded = true;
emit userfileLoaded();
m_uiForm.tabWidget->setTabEnabled(1, true);
m_uiForm.tabWidget->setTabEnabled(2, true);
m_uiForm.tabWidget->setTabEnabled(3, true);
Gigg, Martyn Anthony
committed
return true;
}
Gigg, Martyn Anthony
committed
/**
* Load a CSV file specifying information run numbers and populate the batch mode grid
*/
bool SANSRunWindow::loadCSVFile()
{
QString filename = m_uiForm.csv_filename->text();
QFile csv_file(filename);
if( !csv_file.open(QIODevice::ReadOnly | QIODevice::Text) )
{
showInformationBox("Error: Cannot open CSV file \"" + filename + "\"");
return false;
Steve Williams
committed
}
//Clear the current table
clearBatchTable();
QTextStream file_in(&csv_file);
int errors(0);
while( !file_in.atEnd() )
{
QString line = file_in.readLine().simplified();
if( !line.isEmpty() )
{
// if first line of batch contain string MANTID_BATCH_FILE this is a 'metadata' line
if ( !line.upper().contains("MANTID_BATCH_FILE") )
errors += addBatchLine(line, ",");
Steve Williams
committed
}
}
if( errors > 0 )
{
showInformationBox("Warning: " + QString::number(errors) + " malformed lines detected in \"" + filename + "\". Lines skipped.");
}
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
// In order to allow the user to populate the single mode Widgets from a csv file,
// this code takes the first line of a valid csv batch file and insert inside the
// single mode widgets. It is usefull for testing.
QTableWidgetItem * batch_items [] ={
m_uiForm.batch_table->item(0,0),
m_uiForm.batch_table->item(0,1),
m_uiForm.batch_table->item(0,2),
m_uiForm.batch_table->item(0,3),
m_uiForm.batch_table->item(0,4),
m_uiForm.batch_table->item(0,5)
};
MWRunFiles * run_files [] = {
m_uiForm.scatterSample,
m_uiForm.transmis,
m_uiForm.direct,
m_uiForm.scatCan,
m_uiForm.transCan,
m_uiForm.dirCan};
// if the cell is not empty, set the text to the single mode file
for (unsigned short i=0; i<6; i++){
if (batch_items[i])
run_files[i]->setUserInput(batch_items[i]->text());
else
run_files[i]->setUserInput("");
}
Gigg, Martyn Anthony
committed
return true;
}
Gigg, Martyn Anthony
committed
/**
Gigg, Martyn Anthony
committed
* Set a pair of an QLineEdit field and type QComboBox using the parameter given
Janik Zikovsky
committed
* @param pname :: The name of the parameter
* @param param :: A string representing a value that maybe prefixed with a minus to indicate a different step type
* @param step_value :: The field to store the actual value
* @param step_type :: The combo box with the type options
Gigg, Martyn Anthony
committed
*/
void SANSRunWindow::setLimitStepParameter(const QString& pname, QString param, QLineEdit* step_value, QComboBox* step_type)
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
if( param.startsWith("-") )