Newer
Older
Gigg, Martyn Anthony
committed
//----------------------
// Includes
//----------------------
#include "MantidQtCustomInterfaces/SANSRunWindow.h"
Gigg, Martyn Anthony
committed
#include "MantidQtCustomInterfaces/SANSUtilityDialogs.h"
Steve Williams
committed
#include "MantidQtCustomInterfaces/SANSAddFiles.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/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"
Steve Williams
committed
#include "MantidKernel/Exception.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>
#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
Steve Williams
committed
#include "boost/lexical_cast.hpp"
Gigg, Martyn Anthony
committed
//Add this class to the list of specialised dialogs in this namespace
namespace MantidQt
{
namespace CustomInterfaces
{
DECLARE_SUBWINDOW(SANSRunWindow);
}
}
Steve Williams
committed
using namespace MantidQt::MantidWidgets;
Gigg, Martyn Anthony
committed
using namespace MantidQt::CustomInterfaces;
Steve Williams
committed
using namespace Mantid::Kernel;
using namespace Mantid::API;
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
// Initialize the logger
Steve Williams
committed
Logger& SANSRunWindow::g_log = Logger::get("SANSRunWindow");
Gigg, Martyn Anthony
committed
//----------------------------------------------
Gigg, Martyn Anthony
committed
// Public member functions
//----------------------------------------------
Gigg, Martyn Anthony
committed
///Constructor
SANSRunWindow::SANSRunWindow(QWidget *parent) :
Steve Williams
committed
UserSubWindow(parent), m_addFilesTab(NULL), m_saveWorkspaces(NULL),
m_data_dir(""), m_ins_defdir(""), m_last_dir(""),
m_cfg_loaded(true), m_userFname(false), m_sample_no(), m_run_no_boxes(),
Steve Williams
committed
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),
Gigg, Martyn Anthony
committed
m_have_reducemodule(false), m_dirty_batch_grid(false), m_tmp_batchfile("")
Gigg, Martyn Anthony
committed
{
}
Gigg, Martyn Anthony
committed
SANSRunWindow::~SANSRunWindow()
{
Gigg, Martyn Anthony
committed
if( isInitialized() )
Gigg, Martyn Anthony
committed
{
// Seems to crash on destruction of if I don't do this
AnalysisDataService::Instance().notificationCenter.removeObserver(m_delete_observer);
saveSettings();
delete m_addFilesTab;
}
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);
m_mode_mapper = 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();
// 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
for( int i = 1; i < 4; ++i)
{
m_uiForm.tabWidget->setTabEnabled(i, false);
}
//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 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);
m_uiForm.batch_table->addAction(m_batch_clear);
connect(m_batch_clear, SIGNAL(activated()), this, SLOT(clearBatchTable()));
//Logging
connect(this, SIGNAL(logMessageReceived(const QString&)), this, SLOT(updateLogWindow(const QString&)));
connect(m_uiForm.logger_clear, SIGNAL(clicked()), this, SLOT(clearLogger()));
m_uiForm.logging_field->ensureCursorVisible();
connect(m_uiForm.verbose_check, SIGNAL(stateChanged(int)), this, SLOT(verboseMode(int)));
//Create the widget hash maps
initWidgetMaps();
Steve Williams
committed
connectChangeSignals();
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");
m_uiForm.trans_opt->setItemData(0,"Log");
m_uiForm.trans_opt->setItemData(1,"Linear");
m_uiForm.trans_opt->setItemData(2,"Off");
if( ! m_addFilesTab )
{//sets up the AddFiles tab which must be deleted in the destructor
m_addFilesTab = new SANSAddFiles(this, &m_uiForm);
}
//List for Workspace delete signals
AnalysisDataService::Instance().notificationCenter.addObserver(m_delete_observer);
readSettings();
Gigg, Martyn Anthony
committed
}
/**
* Run local Python initialization code
*/
void SANSRunWindow::initLocalPython()
{
Steve Williams
committed
// Import 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);
}
}
Steve Williams
committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/** 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()));
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.saveCan_check, "SaveCanSAS1D");
m_savFormats.insert(m_uiForm.saveRKH_check, "SaveRKH");
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()
{
//this dialog must have delete on close selected to aviod a memory leak
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&)),
this, SIGNAL(runAsPythonScript(const QString&)));
//we need know if we have a pointer to a valid window or not
connect(m_saveWorkspaces, SIGNAL(closing()),
this, SLOT(saveWorkspacesClosed()));
m_uiForm.saveSel_btn->setEnabled(false);
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()));
connect(m_uiForm.clear_log, SIGNAL(clicked()), m_uiForm.centre_logging, SLOT(clear()));
}
Steve Williams
committed
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
/** Connect signals from the textChanged() signal from text boxes, index changed
* on ComboBoxes etc.
*/
void SANSRunWindow::connectChangeSignals()
{
//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()));
connect(m_uiForm.outfile_edit, SIGNAL(textEdited(const QString&)),
this, SLOT(enableOrDisableDefaultSave()));
// 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)));
// Default transmission switch
connect(m_uiForm.def_trans, SIGNAL(stateChanged(int)), this, SLOT(updateTransInfo(int)));
}
Gigg, Martyn Anthony
committed
/**
* Initialize the widget maps
*/
void SANSRunWindow::initWidgetMaps()
{
Steve Williams
committed
// single run mode settings
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);
Steve Williams
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);
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);
m_allowed_batchtags.insert("output_as",6);
// detector info
// SANS2D det names/label map
Gigg, Martyn Anthony
committed
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
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
Steve Williams
committed
m_ins_defdir = QString::fromStdString(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());
Steve Williams
committed
Gigg, Martyn Anthony
committed
value_store.endGroup();
Steve Williams
committed
readSaveSettings(value_store);
Gigg, Martyn Anthony
committed
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;
Steve Williams
committed
}
/** Sets the states of the checkboxes in the save box using those
* in the passed QSettings object
* @param valueStore where the settings will be stored
*/
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.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
/**
* 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();
Steve Williams
committed
saveSaveSettings(value_store);
}
/** Stores the state of the checkboxes in the save box with the
* passed QSettings object
* @param valueStore where the settings will be stored
*/
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("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
* @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
}
Steve Williams
committed
g_log.debug() << "Executing Python: " << pycode.toStdString() << std::endl;
QString code_torun = "SetNoPrintMode(True);";
code_torun += pycode + ";";
const static QString PYTHON_SEP("C++ImplementationReservedC++");
code_torun += "SetNoPrintMode(False);print '"+PYTHON_SEP+"'";
QString pythonOut = runPythonCode(code_torun).trimmed();
QStringList allOutput = pythonOut.split(PYTHON_SEP);
if ( allOutput.count() < 2 )
{
throw std::runtime_error("Error reported by Python script: " + pythonOut.toStdString());
}
return allOutput[0];
Gigg, Martyn Anthony
committed
}
/**
* 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
Steve Williams
committed
if ( runReduceScriptFunction("print MaskFile(r'"+filetext+"')") != "True\n" )
{
return false;
}
Gigg, Martyn Anthony
committed
Steve Williams
committed
handleInstrumentChange(m_uiForm.inst_opt->currentIndex());
Gigg, Martyn Anthony
committed
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
Steve Williams
committed
m_uiForm.monitor_spec->setText(runReduceScriptFunction(
Steve Williams
committed
"printParameter('INSTRUMENT.get_incident_mon()'),"));
Steve Williams
committed
m_uiForm.trans_monitor->setText(runReduceScriptFunction(
"printParameter('INSTRUMENT.incid_mon_4_trans_calc'),"));
Steve Williams
committed
m_uiForm.monitor_interp->setChecked(runReduceScriptFunction(
Steve Williams
committed
"printParameter('INSTRUMENT.is_interpolating_norm'),") == "True");
Steve Williams
committed
m_uiForm.trans_interp->setChecked(
Steve Williams
committed
runReduceScriptFunction("printParameter('INSTRUMENT.use_interpol_trans_calc'),") == "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
Doucet, Mathieu
committed
dbl_param = runReduceScriptFunction("printParameter('INSTRUMENT.SAMPLE_Z_CORR'),").toDouble();
Gigg, Martyn Anthony
committed
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
Steve Williams
committed
param = runReduceScriptFunction(
Steve Williams
committed
"printParameter('INSTRUMENT.cur_detector().name()')");
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
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
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
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
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
{
Steve Williams
committed
IInstrument_sptr instr = workspace->getInstrument();
if( instr == boost::shared_ptr<IInstrument>() ) return;
Gigg, Martyn Anthony
committed
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);
}
Steve Williams
committed
//buttons that are available as long as Python is available
Gigg, Martyn Anthony
committed
m_uiForm.oneDBtn->setEnabled(!running);
m_uiForm.twoDBtn->setEnabled(!running);
Steve Williams
committed
m_uiForm.saveSel_btn->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);
Steve Williams
committed
Gigg, Martyn Anthony
committed
if( running )
{
Steve Williams
committed
m_uiForm.saveDefault_btn->setEnabled(false);
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
{
Steve Williams
committed
enableOrDisableDefaultSave();
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
{
Steve Williams
committed
return AnalysisDataService::Instance().doesExist(ws_name.toStdString());
Gigg, Martyn Anthony
committed
}
/**
* @returns A list of the currently available workspaces
*/
QStringList SANSRunWindow::currentWorkspaceList() const
{
Steve Williams
committed
std::set<std::string> ws_list = 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) )