Newer
Older
Gigg, Martyn Anthony
committed
//----------------------
// Includes
//----------------------
#include "MantidQtCustomInterfaces/SANSRunWindow.h"
Gigg, Martyn Anthony
committed
#include "MantidQtCustomInterfaces/SANSUtilityDialogs.h"
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
#include "MantidKernel/ConfigService.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"
Gigg, Martyn Anthony
committed
#include "MantidAPI/MatrixWorkspace.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/WorkspaceGroup.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/IInstrument.h"
#include "MantidAPI/SpectraDetectorMap.h"
Gigg, Martyn Anthony
committed
#include "MantidGeometry/IComponent.h"
Gigg, Martyn Anthony
committed
#include "MantidGeometry/V3D.h"
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
#include <QLineEdit>
#include <QFileDialog>
#include <QHash>
Gigg, Martyn Anthony
committed
#include <QTextStream>
Gigg, Martyn Anthony
committed
#include <QTreeWidgetItem>
Gigg, Martyn Anthony
committed
#include <QSettings>
Gigg, Martyn Anthony
committed
#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
//Add this class to the list of specialised dialogs in this namespace
namespace MantidQt
{
namespace CustomInterfaces
{
DECLARE_SUBWINDOW(SANSRunWindow);
}
}
using namespace MantidQt::CustomInterfaces;
Gigg, Martyn Anthony
committed
// Initialize the logger
Mantid::Kernel::Logger& SANSRunWindow::g_log = Mantid::Kernel::Logger::get("SANSRunWindow");
//----------------------------------------------
Gigg, Martyn Anthony
committed
// Public member functions
//----------------------------------------------
Gigg, Martyn Anthony
committed
///Constructor
SANSRunWindow::SANSRunWindow(QWidget *parent) :
UserSubWindow(parent), m_data_dir(""), m_ins_defdir(""), m_last_dir(""), m_cfg_loaded(true),
m_sample_no(), m_run_no_boxes(), m_period_lbls(), m_warnings_issued(false),
m_force_reload(false), m_log_warnings(false), m_delete_observer(*this,
&SANSRunWindow::handleMantidDeleteWorkspace), m_s2d_detlabels(),
m_loq_detlabels(), m_allowed_batchtags(), m_lastreducetype(-1),
m_have_reducemodule(false), m_dirty_batch_grid(false), m_tmp_batchfile("")
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
m_reducemapper = new QSignalMapper(this);
Gigg, Martyn Anthony
committed
m_mode_mapper = new QSignalMapper(this);
Gigg, Martyn Anthony
committed
Mantid::API::AnalysisDataService::Instance().notificationCenter.addObserver(m_delete_observer);
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);
Gigg, Martyn Anthony
committed
m_allowed_batchtags.insert("background_sans",-1);
m_allowed_batchtags.insert("background_trans",-1);
m_allowed_batchtags.insert("background_direct_beam",-1);
m_allowed_batchtags.insert("output_as",6);
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
SANSRunWindow::~SANSRunWindow()
{
Gigg, Martyn Anthony
committed
// Seems to crash on destruction of if I don't do this
Mantid::API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_delete_observer);
Gigg, Martyn Anthony
committed
saveSettings();
}
//--------------------------------------------
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");
Gigg, Martyn Anthony
committed
m_uiForm.setupUi(this);
Gigg, Martyn Anthony
committed
//Set column stretch on the mask table
m_uiForm.mask_table->horizontalHeader()->setStretchLastSection(true);
Gigg, Martyn Anthony
committed
//Button connections
connect(m_uiForm.data_dirBtn, SIGNAL(clicked()), this, SLOT(selectDataDir()));
connect(m_uiForm.userfileBtn, SIGNAL(clicked()), this, SLOT(selectUserFile()));
Gigg, Martyn Anthony
committed
connect(m_uiForm.csv_browse_btn,SIGNAL(clicked()), this, SLOT(selectCSVFile()));
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
connect(m_uiForm.load_dataBtn, SIGNAL(clicked()), this, SLOT(handleLoadButtonClick()));
Gigg, Martyn Anthony
committed
//connect(m_uiForm.plotBtn, SIGNAL(clicked()), this, SLOT(handlePlotButtonClick()));
Gigg, Martyn Anthony
committed
connect(m_uiForm.runcentreBtn, SIGNAL(clicked()), this, SLOT(handleRunFindCentre()));
connect(m_uiForm.saveBtn, SIGNAL(clicked()), this, SLOT(handleSaveButtonClick()));
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
// Disable most things so that load is the only thing that can be done
m_uiForm.oneDBtn->setEnabled(false);
Gigg, Martyn Anthony
committed
m_uiForm.twoDBtn->setEnabled(false);
Gigg, Martyn Anthony
committed
for( int i = 1; i < 4; ++i)
{
m_uiForm.tabWidget->setTabEnabled(i, false);
}
Gigg, Martyn Anthony
committed
// 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()));
connect(m_uiForm.clear_log, SIGNAL(clicked()), m_uiForm.centre_logging, SLOT(clear()));
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
//Mode switches
connect(m_uiForm.single_mode_btn, SIGNAL(clicked()), m_mode_mapper, SLOT(map()));
m_mode_mapper->setMapping(m_uiForm.single_mode_btn, SANSRunWindow::SingleMode);
connect(m_uiForm.batch_mode_btn, SIGNAL(clicked()), m_mode_mapper, SLOT(map()));
m_mode_mapper->setMapping(m_uiForm.batch_mode_btn, SANSRunWindow::BatchMode);
connect(m_mode_mapper, SIGNAL(mapped(int)), this, SLOT(switchMode(int)));
//Set a custom context 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);
m_uiForm.batch_table->addAction(m_batch_clear);
connect(m_batch_clear, SIGNAL(activated()), this, SLOT(clearBatchTable()));
Gigg, Martyn Anthony
committed
//Logging
connect(this, SIGNAL(logMessageReceived(const QString&)), this, SLOT(updateLogWindow(const QString&)));
Gigg, Martyn Anthony
committed
connect(m_uiForm.logger_clear, SIGNAL(clicked()), this, SLOT(clearLogger()));
Gigg, Martyn Anthony
committed
m_uiForm.logging_field->ensureCursorVisible();
Gigg, Martyn Anthony
committed
connect(m_uiForm.verbose_check, SIGNAL(stateChanged(int)), this, SLOT(verboseMode(int)));
Gigg, Martyn Anthony
committed
//Create the widget hash maps
initWidgetMaps();
//Connect each box's edited signal to flag if the box's text has changed
for( int idx = 0; idx < 9; ++idx )
{
connect(m_run_no_boxes.value(idx), SIGNAL(textEdited(const QString&)), this, SLOT(runChanged()));
}
connect(m_uiForm.smpl_offset, SIGNAL(textEdited(const QString&)), this, SLOT(runChanged()));
// Combo boxes
connect(m_uiForm.wav_dw_opt, SIGNAL(currentIndexChanged(int)), this,
SLOT(handleStepComboChange(int)));
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,
SLOT(handleInstrumentChange(int)));
Gigg, Martyn Anthony
committed
// Default transmission switch
connect(m_uiForm.def_trans, SIGNAL(stateChanged(int)), this, SLOT(updateTransInfo(int)));
Gigg, Martyn Anthony
committed
// Add Python set functions as underlying data
m_uiForm.inst_opt->setItemData(0, "LOQ()");
m_uiForm.inst_opt->setItemData(1, "SANS2D()");
//Add shortened forms of step types to step boxes
m_uiForm.wav_dw_opt->setItemData(0, "LIN");
m_uiForm.wav_dw_opt->setItemData(1, "LOG");
m_uiForm.q_dq_opt->setItemData(0, "LIN");
m_uiForm.q_dq_opt->setItemData(1, "LOG");
m_uiForm.qy_dqy_opt->setItemData(0, "LIN");
Gigg, Martyn Anthony
committed
m_uiForm.trans_opt->setItemData(0,"Log");
m_uiForm.trans_opt->setItemData(1,"Linear");
m_uiForm.trans_opt->setItemData(2,"Off");
Gigg, Martyn Anthony
committed
readSettings();
Gigg, Martyn Anthony
committed
}
/**
* Run local Python initialization code
*/
void SANSRunWindow::initLocalPython()
{
// Imoprt the SANS module and set the correct instrument
Gigg, Martyn Anthony
committed
QString result = runPythonCode("try:\n\tfrom SANSReduction import *\nexcept (ImportError,SyntaxError), details:\tprint 'Error importing SANSReduction: ' + str(details)");
Gigg, Martyn Anthony
committed
if( result.trimmed().isEmpty() )
{
m_have_reducemodule = true;
}
else
{
showInformationBox(result);
m_have_reducemodule = false;
setProcessingState(true, -1);
}
}
Gigg, Martyn Anthony
committed
/**
* Initialize the widget maps
*/
void SANSRunWindow::initWidgetMaps()
{
Gigg, Martyn Anthony
committed
//Text edit map
m_run_no_boxes.insert(0, m_uiForm.sct_sample_edit);
m_run_no_boxes.insert(1, m_uiForm.sct_can_edit);
m_run_no_boxes.insert(2, m_uiForm.sct_bkgd_edit);
m_run_no_boxes.insert(3, m_uiForm.tra_sample_edit);
m_run_no_boxes.insert(4, m_uiForm.tra_can_edit);
m_run_no_boxes.insert(5, m_uiForm.tra_bkgd_edit);
m_run_no_boxes.insert(6, m_uiForm.direct_sample_edit);
m_run_no_boxes.insert(7, m_uiForm.direct_can_edit);
m_run_no_boxes.insert(8, m_uiForm.direct_bkgd_edit);
Gigg, Martyn Anthony
committed
//Period label hash. Each label has a buddy set to its corresponding text edit field
Gigg, Martyn Anthony
committed
m_period_lbls.insert(0, m_uiForm.sct_prd_tot1);
m_period_lbls.insert(1, m_uiForm.sct_prd_tot2);
m_period_lbls.insert(2, m_uiForm.sct_prd_tot3);
m_period_lbls.insert(3, m_uiForm.tra_prd_tot1);
m_period_lbls.insert(4, m_uiForm.tra_prd_tot2);
m_period_lbls.insert(5, m_uiForm.tra_prd_tot3);
m_period_lbls.insert(6, m_uiForm.direct_prd_tot1);
m_period_lbls.insert(7, m_uiForm.direct_prd_tot2);
m_period_lbls.insert(8, m_uiForm.direct_prd_tot3);
Gigg, Martyn Anthony
committed
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
// SANS2D det names/label map
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
m_workspace_names.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");
m_uiForm.datadir_edit->setText(value_store.value("data_dir").toString());
m_uiForm.userfile_edit->setText(value_store.value("user_file").toString());
Gigg, Martyn Anthony
committed
m_last_dir = value_store.value("last_dir", "").toString();
Gigg, Martyn Anthony
committed
m_uiForm.inst_opt->setCurrentIndex(value_store.value("instrument", 0).toInt());
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(Mantid::Kernel::ConfigService::Instance().getString("instrumentDefinition.directory"));
Gigg, Martyn Anthony
committed
// Setup for instrument
handleInstrumentChange(m_uiForm.inst_opt->currentIndex());
Gigg, Martyn Anthony
committed
//Set old file extension
m_uiForm.file_opt->setCurrentIndex(value_store.value("fileextension", 0).toInt());
value_store.endGroup();
g_log.debug() << "Found previous data directory " << m_uiForm.datadir_edit->text().toStdString()
<< "\nFound previous user mask file" << m_uiForm.userfile_edit->text().toStdString()
<< "\nFound instrument definition directory " << m_ins_defdir.toStdString() << std::endl;
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
/**
* Save input for future use
*/
void SANSRunWindow::saveSettings()
{
QSettings value_store;
Gigg, Martyn Anthony
committed
value_store.beginGroup("CustomInterfaces/SANSRunWindow");
Gigg, Martyn Anthony
committed
if( !m_data_dir.isEmpty() )
{
value_store.setValue("data_dir", m_data_dir);
}
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);
Gigg, Martyn Anthony
committed
value_store.setValue("instrument", m_uiForm.inst_opt->currentIndex());
value_store.setValue("fileextension", m_uiForm.file_opt->currentIndex());
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();
}
Gigg, Martyn Anthony
committed
/**
* Run a function from the SANS reduction script, ensuring that the first call imports the module
* @param pycode The code to execute
* @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
}
//Ensure the correct instrument is set
Gigg, Martyn Anthony
committed
QString code_torun = "SetNoPrintMode(True)\n" + pycode + "\nSetNoPrintMode(False)";
Gigg, Martyn Anthony
committed
return runPythonCode(code_torun).trimmed();
}
/**
* Trim off Python markers surrounding things like strings or lists that have been
* printed by Python
*/
void SANSRunWindow::trimPyMarkers(QString & txt)
{
txt.remove(0,1);
txt.chop(1);
}
Gigg, Martyn Anthony
committed
/**
* Load the user file specified in the text field
* @returns Boolean indicating whether we were successful or not
*/
bool SANSRunWindow::loadUserFile()
{
QString filetext = m_uiForm.userfile_edit->text();
if( filetext.isEmpty() ) return false;
if( QFileInfo(filetext).isRelative() )
{
Gigg, Martyn Anthony
committed
filetext = QDir(m_data_dir).absoluteFilePath(filetext);
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
if( !QFileInfo(filetext).exists() ) return false;
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
QFile user_file(filetext);
if( !user_file.open(QIODevice::ReadOnly) ) return false;
Gigg, Martyn Anthony
committed
user_file.close();
Gigg, Martyn Anthony
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);
}
Gigg, Martyn Anthony
committed
// Use python function to read the file and then extract the fields
runReduceScriptFunction("MaskFile(r'" + filetext + "')");
double unit_conv(1000.);
// Radius
double dbl_param = runReduceScriptFunction("printParameter('RMIN'),").toDouble();
m_uiForm.rad_min->setText(QString::number(dbl_param*unit_conv));
dbl_param = runReduceScriptFunction("printParameter('RMAX'),").toDouble();
m_uiForm.rad_max->setText(QString::number(dbl_param*unit_conv));
//Wavelength
m_uiForm.wav_min->setText(runReduceScriptFunction("printParameter('WAV1'),"));
m_uiForm.wav_max->setText(runReduceScriptFunction("printParameter('WAV2'),"));
setLimitStepParameter("wavelength", runReduceScriptFunction("printParameter('DWAV'),"), m_uiForm.wav_dw, m_uiForm.wav_dw_opt);
//Q
QString text = runReduceScriptFunction("printParameter('Q_REBIN'),");
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);
}
Gigg, Martyn Anthony
committed
//Qxy
m_uiForm.qy_max->setText(runReduceScriptFunction("printParameter('QXY2'),"));
setLimitStepParameter("Qxy", runReduceScriptFunction("printParameter('DQXY'),"), m_uiForm.qy_dqy, m_uiForm.qy_dqy_opt);
Gigg, Martyn Anthony
committed
// Tranmission options
m_uiForm.trans_min->setText(runReduceScriptFunction("printParameter('TRANS_WAV1'),"));
m_uiForm.trans_max->setText(runReduceScriptFunction("printParameter('TRANS_WAV2'),"));
text = runReduceScriptFunction("printParameter('TRANS_FIT')");
int index = m_uiForm.trans_opt->findData(text, Qt::UserRole, Qt::MatchFixedString);
if( index >= 0 )
{
m_uiForm.trans_opt->setCurrentIndex(index);
}
Steve Williams
committed
//Monitor spectra
Gigg, Martyn Anthony
committed
m_uiForm.monitor_spec->setText(runReduceScriptFunction("printParameter('MONITORSPECTRUM'),"));
Steve Williams
committed
m_uiForm.trans_monitor->setText(runReduceScriptFunction("printParameter('TRANS_UDET_MON'),"));
m_uiForm.monitor_interp->setChecked(
runReduceScriptFunction("printParameter('SAMP_INTERPOLATE'),") == "True");
m_uiForm.trans_interp->setChecked(
runReduceScriptFunction("printParameter('TRANS_INTERPOLATE'),") == "True");
Gigg, Martyn Anthony
committed
//Direct efficiency correction
Gigg, Martyn Anthony
committed
m_uiForm.direct_file->setText(runReduceScriptFunction("printParameter('DIRECT_BEAM_FILE_R'),"));
m_uiForm.front_direct_file->setText(runReduceScriptFunction("printParameter('DIRECT_BEAM_FILE_F'),"));
Gigg, Martyn Anthony
committed
//Scale factor
dbl_param = runReduceScriptFunction("printParameter('RESCALE'),").toDouble();
m_uiForm.scale_factor->setText(QString::number(dbl_param/100.));
//Sample offset if one has been specified
dbl_param = runReduceScriptFunction("printParameter('SAMPLE_Z_CORR'),").toDouble();
m_uiForm.smpl_offset->setText(QString::number(dbl_param*unit_conv));
//Centre coordinates
dbl_param = runReduceScriptFunction("printParameter('XBEAM_CENTRE'),").toDouble();
m_uiForm.beam_x->setText(QString::number(dbl_param*1000.0));
dbl_param = runReduceScriptFunction("printParameter('YBEAM_CENTRE'),").toDouble();
m_uiForm.beam_y->setText(QString::number(dbl_param*1000.0));
Gigg, Martyn Anthony
committed
//Gravity switch
QString param = runReduceScriptFunction("printParameter('GRAVITY')");
if( param == "True" )
{
m_uiForm.gravity_check->setChecked(true);
}
else
{
m_uiForm.gravity_check->setChecked(false);
}
////Detector bank
param = runReduceScriptFunction("printParameter('DETBANK')");
Gigg, Martyn Anthony
committed
index = m_uiForm.detbank_sel->findText(param);
Gigg, Martyn Anthony
committed
if( index >= 0 && index < 2 )
{
m_uiForm.detbank_sel->setCurrentIndex(index);
}
Gigg, Martyn Anthony
committed
//Masking table
updateMaskTable();
Gigg, Martyn Anthony
committed
// Phi values
m_uiForm.phi_min->setText(runReduceScriptFunction("printParameter('PHIMIN')"));
m_uiForm.phi_max->setText(runReduceScriptFunction("printParameter('PHIMAX')"));
Steve Williams
committed
if ( runReduceScriptFunction("printParameter('PHIMIRROR')") == "True" )
{
m_uiForm.mirror_phi->setChecked(true);
}
else
{
m_uiForm.mirror_phi->setChecked(false);
}
Gigg, Martyn Anthony
committed
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);
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;
}
//Clear the current table
clearBatchTable();
Gigg, Martyn Anthony
committed
QTextStream file_in(&csv_file);
int errors(0);
while( !file_in.atEnd() )
{
QString line = file_in.readLine().simplified();
if( !line.isEmpty() )
{
errors += addBatchLine(line, ",");
}
}
if( errors > 0 )
Gigg, Martyn Anthony
committed
{
showInformationBox("Warning: " + QString::number(errors) + " malformed lines detected in \"" + filename + "\". Lines skipped.");
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
* @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("-") )
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
int index = step_type->findText("Logarithmic");
if( index < 0 )
{
Gigg, Martyn Anthony
committed
raiseOneTimeMessage("Warning: Unable to find logarithmic scale option for " + pname + ", setting as linear.", 1);
Gigg, Martyn Anthony
committed
index = step_type->findText("Linear");
}
step_type->setCurrentIndex(index);
step_value->setText(param.remove(0,1));
Gigg, Martyn Anthony
committed
}
else
{
Gigg, Martyn Anthony
committed
step_type->setCurrentIndex(step_type->findText("Linear"));
step_value->setText(param);
}
}
/**
* Construct the mask table on the Mask tab
*/
void SANSRunWindow::updateMaskTable()
{
//Clear the current contents
for( int i = m_uiForm.mask_table->rowCount() - 1; i >= 0; --i )
{
m_uiForm.mask_table->removeRow(i);
}
Gigg, Martyn Anthony
committed
QString reardet_name("rear-detector"), frontdet_name("front-detector");
if( m_uiForm.inst_opt->currentIndex() == 0 )
{
reardet_name = "main-detector-bank";
frontdet_name = "HAB";
}
Gigg, Martyn Anthony
committed
// First create 2 default mask cylinders at min and max radius for the beam stop and
// corners
m_uiForm.mask_table->insertRow(0);
Gigg, Martyn Anthony
committed
m_uiForm.mask_table->setItem(0, 0, new QTableWidgetItem("beam stop"));
m_uiForm.mask_table->setItem(0, 1, new QTableWidgetItem(reardet_name));
m_uiForm.mask_table->setItem(0, 2, new QTableWidgetItem("infinite-cylinder, r = rmin"));
Gigg, Martyn Anthony
committed
if( m_uiForm.rad_max->text() != "-1" )
{
m_uiForm.mask_table->insertRow(1);
Gigg, Martyn Anthony
committed
m_uiForm.mask_table->setItem(1, 0, new QTableWidgetItem("corners"));
m_uiForm.mask_table->setItem(1, 1, new QTableWidgetItem(reardet_name));
m_uiForm.mask_table->setItem(1, 2, new QTableWidgetItem("infinite-cylinder, r = rmax"));
Gigg, Martyn Anthony
committed
}
//Now add information from the mask file
//Spectrum mask
QString mask_string = runReduceScriptFunction("printParameter('SPECMASKSTRING')");
Gigg, Martyn Anthony
committed
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
addSpectrumMasksToTable(mask_string, "-");
//"Rear" det
mask_string = runReduceScriptFunction("printParameter('SPECMASKSTRING_R')");
addSpectrumMasksToTable(mask_string, reardet_name);
//"Front" det
mask_string = runReduceScriptFunction("printParameter('SPECMASKSTRING_F')");
addSpectrumMasksToTable(mask_string, frontdet_name);
//Time masks
mask_string = runReduceScriptFunction("printParameter('TIMEMASKSTRING')");
addTimeMasksToTable(mask_string, "-");
//Rear detector
mask_string = runReduceScriptFunction("printParameter('TIMEMASKSTRING_R')");
addTimeMasksToTable(mask_string, reardet_name);
//Front detectors
mask_string = runReduceScriptFunction("printParameter('TIMEMASKSTRING_F')");
addTimeMasksToTable(mask_string, frontdet_name);
}
/**
* Add a spectrum mask string to the mask table
* @param mask_string The string of mask information
* @param det_name The detector it relates to
*/
void SANSRunWindow::addSpectrumMasksToTable(const QString & mask_string, const QString & det_name)
{
Gigg, Martyn Anthony
committed
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
QStringList elements = mask_string.split(",", QString::SkipEmptyParts);
QStringListIterator sitr(elements);
while(sitr.hasNext())
{
QString item = sitr.next();
QString col1_txt;
if( item.startsWith('s', Qt::CaseInsensitive) )
{
col1_txt = "Spectrum";
}
else if( item.startsWith('h', Qt::CaseInsensitive) || item.startsWith('v', Qt::CaseInsensitive) )
{
if( item.contains('+') )
{
col1_txt = "Box";
}
else
{
col1_txt = "Strip";
}
}
else continue;
int row = m_uiForm.mask_table->rowCount();
//Insert line after last row
m_uiForm.mask_table->insertRow(row);
Gigg, Martyn Anthony
committed
m_uiForm.mask_table->setItem(row, 0, new QTableWidgetItem(col1_txt));
m_uiForm.mask_table->setItem(row, 1, new QTableWidgetItem(det_name));
m_uiForm.mask_table->setItem(row, 2, new QTableWidgetItem(item));
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
/**
* Add a time mask string to the mask table
* @param mask_string The string of mask information
* @param det_name The detector it relates to
*/
void SANSRunWindow::addTimeMasksToTable(const QString & mask_string, const QString & det_name)
{
QStringList elements = mask_string.split(";",QString::SkipEmptyParts);
QStringListIterator sitr(elements);
Gigg, Martyn Anthony
committed
while(sitr.hasNext())
{
int row = m_uiForm.mask_table->rowCount();
m_uiForm.mask_table->insertRow(row);
Gigg, Martyn Anthony
committed
m_uiForm.mask_table->setItem(row, 0, new QTableWidgetItem("time"));
m_uiForm.mask_table->setItem(row, 1, new QTableWidgetItem(det_name));
m_uiForm.mask_table->setItem(row, 2, new QTableWidgetItem(sitr.next()));
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
/**
* Retrieve and set the component distances
Gigg, Martyn Anthony
committed
* @param workspace The workspace pointer
Gigg, Martyn Anthony
committed
* @param lms The result of the moderator-sample distance
* @param lsda The result of the sample-detector bank 1 distance
* @param lsdb The result of the sample-detector bank 2 distance
*/
Gigg, Martyn Anthony
committed
void SANSRunWindow::componentLOQDistances(Mantid::API::MatrixWorkspace_sptr workspace, double & lms, double & lsda, double & lsdb)
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
Mantid::API::IInstrument_sptr instr = workspace->getInstrument();
Gigg, Martyn Anthony
committed
if( instr == boost::shared_ptr<Mantid::API::IInstrument>() ) return;
Mantid::Geometry::IObjComponent_sptr source = instr->getSource();
Gigg, Martyn Anthony
committed
if( source == boost::shared_ptr<Mantid::Geometry::IObjComponent>() ) return;
Mantid::Geometry::IObjComponent_sptr sample = instr->getSample();
Gigg, Martyn Anthony
committed
if( sample == boost::shared_ptr<Mantid::Geometry::IObjComponent>() ) return;
lms = source->getPos().distance(sample->getPos()) * 1000.;
Gigg, Martyn Anthony
committed
//Find the main detector bank
Gigg, Martyn Anthony
committed
boost::shared_ptr<Mantid::Geometry::IComponent> comp = instr->getComponentByName("main-detector-bank");
Gigg, Martyn Anthony
committed
if( comp != boost::shared_ptr<Mantid::Geometry::IComponent>() )
{
lsda = sample->getPos().distance(comp->getPos()) * 1000.;
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
comp = instr->getComponentByName("HAB");
Gigg, Martyn Anthony
committed
if( comp != boost::shared_ptr<Mantid::Geometry::IComponent>() )
{
lsdb = sample->getPos().distance(comp->getPos()) * 1000.;
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
/**
* Set the state of processing.
* @param running If we are processing then some interaction is disabled
Gigg, Martyn Anthony
committed
* @param type The reduction type, 0 = 1D and 1 = 2D
Gigg, Martyn Anthony
committed
*/
Gigg, Martyn Anthony
committed
void SANSRunWindow::setProcessingState(bool running, int type)
Gigg, Martyn Anthony
committed
{
if( m_uiForm.single_mode_btn->isChecked() )
{
m_uiForm.load_dataBtn->setEnabled(!running);
}
else
{
m_uiForm.load_dataBtn->setEnabled(false);
}
Gigg, Martyn Anthony
committed
m_uiForm.oneDBtn->setEnabled(!running);
m_uiForm.twoDBtn->setEnabled(!running);
Gigg, Martyn Anthony
committed
//m_uiForm.plotBtn->setEnabled(!running);
Gigg, Martyn Anthony
committed
m_uiForm.saveBtn->setEnabled(!running);
Gigg, Martyn Anthony
committed
m_uiForm.runcentreBtn->setEnabled(!running);
Gigg, Martyn Anthony
committed
m_uiForm.userfileBtn->setEnabled(!running);
m_uiForm.data_dirBtn->setEnabled(!running);
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
if( running )
{
Gigg, Martyn Anthony
committed
if( type == 0 )
{
m_uiForm.oneDBtn->setText("Running ...");
}
Gigg, Martyn Anthony
committed
else if( type == 1 )
Gigg, Martyn Anthony
committed
{
m_uiForm.twoDBtn->setText("Running ...");
}
Gigg, Martyn Anthony
committed
else {}
Gigg, Martyn Anthony
committed
}
else
{
Gigg, Martyn Anthony
committed
m_uiForm.oneDBtn->setText("1D Reduce");
m_uiForm.twoDBtn->setText("2D Reduce");
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
for( int i = 0; i < 4; ++i)
{
if( i == m_uiForm.tabWidget->currentIndex() ) continue;
m_uiForm.tabWidget->setTabEnabled(i, !running);
}
QCoreApplication::processEvents();
Gigg, Martyn Anthony
committed
}
/**
* Does the workspace exist in the AnalysisDataService
* @param ws_name The name of the workspace
* @returns A boolean indicatingif the given workspace exists in the AnalysisDataService
*/
bool SANSRunWindow::workspaceExists(const QString & ws_name) const
{
return Mantid::API::AnalysisDataService::Instance().doesExist(ws_name.toStdString());
}
/**
* @returns A list of the currently available workspaces
*/
QStringList SANSRunWindow::currentWorkspaceList() const
{
std::set<std::string> ws_list = Mantid::API::AnalysisDataService::Instance().getObjectNames();
std::set<std::string>::const_iterator iend = ws_list.end();
QStringList current_list;
for( std::set<std::string>::const_iterator itr = ws_list.begin(); itr != iend; ++itr )
{
current_list.append(QString::fromStdString(*itr));
}
return current_list;
}
Gigg, Martyn Anthony
committed
/**
* Is the user file loaded
* @returns A boolean indicating whether the user file has been parsed in to the details tab
*/
bool SANSRunWindow::isUserFileLoaded() const
{
return m_cfg_loaded;
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
/**
* Create the mask strings for spectra and times
Gigg, Martyn Anthony
committed
*/
Gigg, Martyn Anthony
committed
void SANSRunWindow::addUserMaskStrings(QString & exec_script)
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
//Clear current
Gigg, Martyn Anthony
committed
exec_script += "Mask('MASK/CLEAR')\nMask('MASK/CLEAR/TIME')\n";
Gigg, Martyn Anthony
committed
//Pull in the table details first, skipping the first two rows
int nrows = m_uiForm.mask_table->rowCount();
Gigg, Martyn Anthony
committed
for(int row = 0; row < nrows; ++row)
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
if( m_uiForm.mask_table->item(row, 2)->text().startsWith("inf") )
{
continue;
}
Gigg, Martyn Anthony
committed
//Details are in the third column
exec_script += "Mask('MASK";
if( m_uiForm.mask_table->item(row, 0)->text() == "time")
{
exec_script += "/TIME";
}
QString details = m_uiForm.mask_table->item(row, 2)->text();
QString detname = m_uiForm.mask_table->item(row, 1)->text();
if( detname == "-" )
{
exec_script += " " + details;
}
else if( detname == "rear-detector" || detname == "main-detector-bank" )
{
exec_script += "/REAR " + details;
}
else
{
exec_script += "/FRONT " + details;
}
exec_script += "')\n";
Gigg, Martyn Anthony
committed
}
//Spectra mask first
QStringList mask_params = m_uiForm.user_spec_mask->text().split(",", QString::SkipEmptyParts);
QStringListIterator sitr(mask_params);
QString bad_masks;
while(sitr.hasNext())
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
QString item = sitr.next().trimmed();
if( item.startsWith("REAR", Qt::CaseInsensitive) || item.startsWith("FRONT", Qt::CaseInsensitive) )
{
exec_script += "Mask('MASK/" + item + "')\n";
}
else if( item.startsWith('S', Qt::CaseInsensitive) || item.startsWith('H', Qt::CaseInsensitive) ||
Gigg, Martyn Anthony
committed
item.startsWith('V', Qt::CaseInsensitive) )
{
Gigg, Martyn Anthony
committed
exec_script += "Mask('MASK " + item + "')\n";
}
else
{
Gigg, Martyn Anthony
committed
bad_masks += item + ",";
}
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
if( !bad_masks.isEmpty() )
{
Gigg, Martyn Anthony
committed
m_uiForm.tabWidget->setCurrentIndex(3);
showInformationBox(QString("Warning: Could not parse the following spectrum masks: ") + bad_masks + ". Values skipped.");
}
//Time masks
mask_params = m_uiForm.user_time_mask->text().split(",", QString::SkipEmptyParts);
sitr = QStringListIterator(mask_params);
bad_masks = "";
while(sitr.hasNext())
{
Gigg, Martyn Anthony
committed
QString item = sitr.next().trimmed();
if( item.startsWith("REAR", Qt::CaseInsensitive) || item.startsWith("FRONT", Qt::CaseInsensitive) )
{
Gigg, Martyn Anthony
committed
int ndetails = item.split(" ").count();
if( ndetails == 3 || ndetails == 2 )
{
exec_script += "Mask('/TIME" + item + "')\n";
}
else
{
bad_masks += item + ",";
}
}
}
Gigg, Martyn Anthony
committed
if( !bad_masks.isEmpty() )
{
m_uiForm.tabWidget->setCurrentIndex(3);
showInformationBox(QString("Warning: Could not parse the following time masks: ") + bad_masks + ". Values skipped.");
}
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
/**
* Set the information about component distances on the geometry tab
*/
void SANSRunWindow::setGeometryDetails(const QString & sample_logs, const QString & can_logs)
resetGeometryDetailsBox();
Gigg, Martyn Anthony
committed
double unit_conv(1000.);
Gigg, Martyn Anthony
committed
QString workspace_name = getWorkspaceName(0);
if( workspace_name.isEmpty() ) return;
Gigg, Martyn Anthony
committed
Mantid::API::Workspace_sptr workspace_ptr = Mantid::API::AnalysisDataService::Instance().retrieve(workspace_name.toStdString());
Mantid::API::MatrixWorkspace_sptr sample_workspace = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(workspace_ptr);
Mantid::API::IInstrument_sptr instr = sample_workspace->getInstrument();
boost::shared_ptr<Mantid::Geometry::IComponent> source = instr->getSource();
Gigg, Martyn Anthony
committed
// Moderator-monitor distance is common to LOQ and S2D
int monitor_spectrum = m_uiForm.monitor_spec->text().toInt();
std::vector<int> dets = sample_workspace->spectraMap().getDetectors(monitor_spectrum);
if( dets.empty() ) return;
double dist_mm(0.0);
QString colour("black");
try
{
Mantid::Geometry::IDetector_sptr detector = instr->getDetector(dets[0]);
dist_mm = detector->getDistance(*source) * unit_conv;
}
catch(std::runtime_error&)
{
colour = "red";
}
Gigg, Martyn Anthony
committed
//LOQ
if( m_uiForm.inst_opt->currentIndex() == 0 )
Gigg, Martyn Anthony
committed
{
if( colour == "red" )
{
m_uiForm.dist_mod_mon->setText("<font color='red'>error<font>");
}
else
Gigg, Martyn Anthony
committed
m_uiForm.dist_mod_mon->setText(formatDouble(dist_mm, colour));
Gigg, Martyn Anthony
committed
setLOQGeometry(sample_workspace, 0);
QString can = getWorkspaceName(1);
if( !can.isEmpty() )
Gigg, Martyn Anthony
committed
Mantid::API::Workspace_sptr workspace_ptr = Mantid::API::AnalysisDataService::Instance().retrieve(can.toStdString());
Mantid::API::MatrixWorkspace_sptr can_workspace = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(workspace_ptr);
setLOQGeometry(can_workspace, 1);
if( colour == "red" )
m_uiForm.dist_mon_s2d->setText("<font color='red'>error<font>");
Gigg, Martyn Anthony
committed
}
else
{
m_uiForm.dist_mon_s2d->setText(formatDouble(dist_mm, colour));
}
Gigg, Martyn Anthony
committed
//SANS2D - Sample
setSANS2DGeometry(sample_workspace, sample_logs, 0);
//Get the can workspace if there is one
QString can = getWorkspaceName(1);
if( can.isEmpty() )
{
return;
}
Mantid::API::Workspace_sptr workspace_ptr;
try
{
workspace_ptr = Mantid::API::AnalysisDataService::Instance().retrieve(can.toStdString());
}
catch(std::runtime_error&)
{
return;
}
Mantid::API::MatrixWorkspace_sptr can_workspace = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(workspace_ptr);
setSANS2DGeometry(can_workspace, can_logs, 1);
Gigg, Martyn Anthony
committed
//Check for discrepancies
bool warn_user(false);
double lms_sample(m_uiForm.dist_sample_ms_s2d->text().toDouble()), lms_can(m_uiForm.dist_can_ms_s2d->text().toDouble());
if( std::fabs(lms_sample - lms_can) > 5e-03 )
{
warn_user = true;
markError(m_uiForm.dist_sample_ms_s2d);
markError(m_uiForm.dist_can_ms_s2d);