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>
#include <QDesktopServices>
#include <QUrl>
Gigg, Martyn Anthony
committed
#include "MantidQtCustomInterfaces/SANSEventSlicing.h"
#include <boost/assign.hpp>
#include <boost/foreach.hpp>
#include <boost/function.hpp>
#include <boost/tuple/tuple.hpp>
Steve Williams
committed
Gigg, Martyn Anthony
committed
//Add this class to the list of specialised dialogs in this namespace
namespace MantidQt
{
namespace CustomInterfaces
{
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);
}
/**
* Returns the value of the setting with given name, unless the setting does not
* exist in which case the given defaultValue is returned.
*
* @param settingName :: the name of the setting who's value to return
* @param defaultValue :: the value to return if the setting does not exist
*
* @returns the setting value else defaultValue if the setting does not exist
*/
QString getSettingWithDefault(const QString & settingName, const QString & defaultValue )
{
const auto settings = getReductionSettings();
if( settings->existsProperty(settingName.toStdString()) )
return QString::fromStdString(settings->getPropertyValue(settingName.toStdString()));
else
return defaultValue;
}
/**
* Convenience method to set the setting with given name to the given value.
* If a property with the given name does not exist, then one is created.
*
* We could have a templated method at some later date, but at the moment this
* only works for string properties.
*
* @param settingName :: the name of the setting to set
* @param settingValue :: the value to set this setting with
*/
void setStringSetting(const QString & settingName, const QString & settingValue )
{
const auto settings = getReductionSettings();
const auto name = settingName.toStdString();
const auto value = settingValue.toStdString();
if( !settings->existsProperty(name) )
settings->declareProperty(new Kernel::PropertyWithValue<std::string>(name, ""), value);
else
settings->setProperty(name, value);
}
//----------------------------------------------
Gigg, Martyn Anthony
committed
// Public member functions
//----------------------------------------------
Gigg, Martyn Anthony
committed
///Constructor
SANSRunWindow::SANSRunWindow(QWidget *parent)
: UserSubWindow(parent), m_addFilesTab(NULL), m_displayTab(NULL),
m_diagnosticsTab(NULL), m_saveWorkspaces(NULL), m_ins_defdir(""),
m_last_dir(""), m_cfg_loaded(true), m_userFname(false), m_sample_file(),
m_reducemapper(NULL), m_warnings_issued(false), m_force_reload(false),
m_newInDir(*this, &SANSRunWindow::handleInputDirChange),
m_delete_observer(*this, &SANSRunWindow::handleMantidDeleteWorkspace),
m_s2d_detlabels(), m_loq_detlabels(), m_allowed_batchtags(),
m_have_reducemodule(false), m_dirty_batch_grid(false),
m_tmp_batchfile(""), m_batch_paste(NULL), m_batch_clear(NULL),
m_mustBeDouble(NULL), m_doubleValidatorZeroToMax(NULL),
m_intValidatorZeroToMax(NULL),
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_uiForm.inst_opt->addItem("LARMOR");
m_uiForm.inst_opt->addItem("LOQ");
m_uiForm.inst_opt->addItem("SANS2D");
m_uiForm.inst_opt->addItem("SANS2DTUBES");
Gigg, Martyn Anthony
committed
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
const QString ISIS_SANS_WIKI = "http://www.mantidproject.org/ISIS_SANS:";
m_helpPageUrls[Tab::RUN_NUMBERS] = ISIS_SANS_WIKI + "_Run_Numbers";
m_helpPageUrls[Tab::REDUCTION_SETTINGS] = ISIS_SANS_WIKI + "_Reduction_Settings";
m_helpPageUrls[Tab::GEOMETRY] = ISIS_SANS_WIKI + "_Geometry";
m_helpPageUrls[Tab::MASKING] = ISIS_SANS_WIKI + "_Masking";
m_helpPageUrls[Tab::LOGGING] = ISIS_SANS_WIKI + "_Logging";
m_helpPageUrls[Tab::ADD_RUNS] = ISIS_SANS_WIKI + "_Add_Runs";
m_helpPageUrls[Tab::DIAGNOSTICS] = ISIS_SANS_WIKI + "_Diagnostics";
m_helpPageUrls[Tab::ONE_D_ANALYSIS] = ISIS_SANS_WIKI + "_1D_Analysis";
// 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()));
connect(m_uiForm.pushButton_Help, SIGNAL(clicked()), this, SLOT(openHelpPage()));
// Setup the Transmission Settings
initTransmissionSettings();
// Set the validators
setValidators();
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, m_uiForm.zeroErrorCheckBox->isChecked());
Steve Williams
committed
//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()));
// Connect the request for a zero-error-free workspace
// cpp-check does not understand that the input are two references
// cppcheck-suppress duplicateExpression
connect(m_saveWorkspaces, SIGNAL(createZeroErrorFreeWorkspace(QString& , QString&)),
this, SLOT(createZeroErrorFreeClone(QString&, QString&)));
// Connect the request for deleting a zero-error-free workspace
connect(m_saveWorkspaces, SIGNAL(deleteZeroErrorFreeWorkspace(QString&)),
this, SLOT(deleteZeroErrorFreeClone(QString&) ));
// Connect to change in the zero-error removal checkbox
connect(m_uiForm.zeroErrorCheckBox, SIGNAL(stateChanged(int)),
m_saveWorkspaces, SLOT(onSaveAsZeroErrorFreeChanged(int)));
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);
m_allowed_batchtags.insert("user_file",7);
Steve Williams
committed
// detector info
// SANS2D det names/label map
Gigg, Martyn Anthony
committed
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
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();
Steve Williams
committed
//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);
}
QString pyCode = "i.Clean()";
pyCode += "\ni." + getInstrumentClass();
Steve Williams
committed
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 auto settings = getReductionSettings();
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));
//EventsTime
m_uiForm.l_events_binning->setText(getSettingWithDefault("events.binning", "").trimmed());
Steve Williams
committed
//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");
// Transmission settings
setTransmissionSettingsFromUserFile();
Steve Williams
committed
//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();
// get the scale factor1 for the beam centre to scale it correctly
double dbl_paramsf = runReduceScriptFunction(
"print i.ReductionSingleton().get_beam_center_scale_factor1()").toDouble();
m_uiForm.rear_beam_x->setText(QString::number(dbl_param*dbl_paramsf));
// get scale factor2 for the beam centre to scale it correctly
dbl_paramsf = runReduceScriptFunction(
"print i.ReductionSingleton().get_beam_center_scale_factor2()").toDouble();
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*dbl_paramsf));
// 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);
}
// Read the extra length for the gravity correction
const double extraLengthParam = runReduceScriptFunction(
"print i.ReductionSingleton().to_Q.get_extra_length()").toDouble();
m_uiForm.gravity_extra_length_line_edit->setText(QString::number(extraLengthParam));
////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