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/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>
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) :
Gigg, Martyn Anthony
committed
UserSubWindow(parent), m_data_dir(""), m_ins_defdir(""), m_last_dir(""), m_cfg_loaded(true), m_run_no_boxes(),
Gigg, Martyn Anthony
committed
m_period_lbls(), m_pycode_viewmask(""), m_warnings_issued(false), m_force_reload(false),
m_delete_observer(*this,&SANSRunWindow::handleMantidDeleteWorkspace), m_s2d_detlabels(),
m_loq_detlabels(), m_lastreducetype(-1), m_have_reducemodule(false)
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);
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()));
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);
}
// Connect
connect(m_uiForm.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(handleTabChange(int)));
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
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//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)));
//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)));
// 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");
readSettings();
}
/**
* 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
184
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
// 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
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
/**
* 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 )
{
runPythonCode("from SANSReduction import *", false);
m_have_reducemodule = true;
}
//Ensure the correct instrument is set
QString code_torun = "SetQuietMode(True)\n" + m_uiForm.inst_opt->itemData(m_uiForm.inst_opt->currentIndex()).toString()
+ "\n" + pycode + "\nSetQuietMode(False)";
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
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
// 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
m_uiForm.q_min->setText(runReduceScriptFunction("printParameter('Q1'),"));
m_uiForm.q_max->setText(runReduceScriptFunction("printParameter('Q2'),"));
setLimitStepParameter("Q", runReduceScriptFunction("printParameter('DQ'),"), m_uiForm.q_dq, m_uiForm.q_dq_opt);
//Qxy
m_uiForm.qy_max->setText(runReduceScriptFunction("printParameter('QXY2'),"));
setLimitStepParameter("Qxy", runReduceScriptFunction("printParameter('DQXY'),"), m_uiForm.qy_dqy, m_uiForm.qy_dqy_opt);
//Monitor spectrum
m_uiForm.monitor_spec->setText(runReduceScriptFunction("printParameter('MONITORSPECTRUM'),"));
//Direct efficiency correction
m_uiForm.direct_file->setText(runReduceScriptFunction("printParameter('DIRECT_BEAM_FILE'),"));
//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));
//Masking table
updateMaskTable();
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
// Phi values default to -90 and 90
Gigg, Martyn Anthony
committed
m_uiForm.phi_min->setText("-90");
m_uiForm.phi_max->setText("90");
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;
}
QTextStream file_in(&csv_file);
while(!file_in.atEnd())
{
addBatchLine(file_in.readLine());
}
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
*/
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 )
{
m_uiForm.tabWidget->setCurrentIndex(1);
raiseOneTimeMessage("Warning: Unable to find logarithmic scale option for " + pname + ", setting as linear.");
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
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
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);
}
// First create 2 default mask cylinders at min and max radius for the beam stop and
// corners
m_uiForm.mask_table->insertRow(0);
QTableWidgetItem *item1 = new QTableWidgetItem("beam stop");
QTableWidgetItem *item2 = new QTableWidgetItem("infinite-cylinder, r = rmin");
m_uiForm.mask_table->setItem(0, 0, item1);
m_uiForm.mask_table->setItem(0, 1, item2);
if( m_uiForm.rad_max->text() != "-1" )
{
m_uiForm.mask_table->insertRow(1);
item1 = new QTableWidgetItem("corners");
item2 = new QTableWidgetItem("infinite-cylinder, r = rmax");
m_uiForm.mask_table->setItem(1, 0, item1);
m_uiForm.mask_table->setItem(1, 1, item2);
}
//Now add information from the mask file
//Spectrum mask
QString mask_string = runReduceScriptFunction("printParameter('SPECMASKSTRING')");
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);
QTableWidgetItem *col1 = new QTableWidgetItem(col1_txt);
QTableWidgetItem *col2 = new QTableWidgetItem(item);
m_uiForm.mask_table->setItem(row, 0, col1);
m_uiForm.mask_table->setItem(row, 1, col2);
}
mask_string = runReduceScriptFunction("printParameter('TIMEMASKSTRING')");
elements = mask_string.split(";",QString::SkipEmptyParts);
sitr = QStringListIterator(elements);
while(sitr.hasNext())
{
int row = m_uiForm.mask_table->rowCount();
m_uiForm.mask_table->insertRow(row);
QTableWidgetItem *item1 = new QTableWidgetItem("time");
QTableWidgetItem *item2 = new QTableWidgetItem(sitr.next());
m_uiForm.mask_table->setItem(row, 0, item1);
m_uiForm.mask_table->setItem(row, 1, item2);
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
{
Gigg, Martyn Anthony
committed
m_uiForm.load_dataBtn->setEnabled(!running);
m_uiForm.oneDBtn->setEnabled(!running);
m_uiForm.twoDBtn->setEnabled(!running);
m_uiForm.plotBtn->setEnabled(!running);
m_uiForm.saveBtn->setEnabled(!running);
Gigg, Martyn Anthony
committed
m_uiForm.runcentreBtn->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
exec_script += "Mask('/CLEAR')\nMask('/CLEAR/TIME')\n";
//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 = 2; row < nrows; ++row)
{
//Details are in the second column
exec_script += "Mask('" + m_uiForm.mask_table->item(row, 1)->text() + "')\n";
}
//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();
if( item.startsWith('S', Qt::CaseInsensitive) || item.startsWith('H', Qt::CaseInsensitive) ||
item.startsWith('V', Qt::CaseInsensitive) )
{
Gigg, Martyn Anthony
committed
exec_script += "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())
{
QString item = sitr.next();
if( item.split(" ").count() == 2 )
{
Gigg, Martyn Anthony
committed
exec_script += "Mask('/T" + item + "')\n";
}
else
{
Gigg, Martyn Anthony
committed
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();
const char format('f');
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.dist_mod_mon->text() != "-" )
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);
Gigg, Martyn Anthony
committed
//Check for mismatches
QGridLayout *grid = qobject_cast<QGridLayout*>(m_uiForm.loq_geometry->layout());
for( int row = 2; row < 5; ++row )
Gigg, Martyn Anthony
committed
QLabel *sample = qobject_cast<QLabel*>(grid->itemAtPosition(row,1)->widget());
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);
Gigg, Martyn Anthony
committed
QString marked_dets = runReduceScriptFunction("print GetMismatchedDetList(),").trimmed();
Gigg, Martyn Anthony
committed
trimPyMarkers(marked_dets);
Gigg, Martyn Anthony
committed
if( !marked_dets.isEmpty() )
Gigg, Martyn Anthony
committed
QStringList detnames = marked_dets.split(",");
QStringListIterator itr(detnames);
while( itr.hasNext() )
Gigg, Martyn Anthony
committed
QString name = itr.next().trimmed();
trimPyMarkers(name);
for( int i = 0; i < 2; ++i )
{
markError(m_s2d_detlabels[i].value(name));
warn_user = true;
}
Gigg, Martyn Anthony
committed
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
}
if( warn_user )
{
raiseOneTimeMessage("Warning: Some detector distances do not match for the assigned Sample/Can runs, see Geometry tab for details.");
}
}
}
/**
* Set SANS2D geometry info
* @param workspace The workspace
* @param logs The log information
*/
void SANSRunWindow::setSANS2DGeometry(Mantid::API::MatrixWorkspace_sptr workspace, const QString & logs, int wscode)
{
double unitconv = 1000.;
Mantid::API::IInstrument_sptr instr = workspace->getInstrument();
boost::shared_ptr<Mantid::Geometry::IComponent> sample = instr->getSample();
boost::shared_ptr<Mantid::Geometry::IComponent> source = instr->getSource();
double distance = source->getDistance(*sample) * unitconv;
//Moderator-sample
QLabel *dist_label(NULL);
if( wscode == 0 )
{
dist_label = m_uiForm.dist_sample_ms_s2d;
}
else if( wscode == 1 )
{
dist_label = m_uiForm.dist_can_ms_s2d;
}
else
{
dist_label = m_uiForm.dist_bkgd_ms_s2d;
}
dist_label->setText(formatDouble(distance, "black"));
//Detectors
QStringList det_info = logs.split(",");
QStringListIterator itr(det_info);
while( itr.hasNext() )
{
QString line = itr.next();
QStringList values = line.split(":");
QString detname = values[0].trimmed();
QString distance = values[1].trimmed();
trimPyMarkers(detname);
trimPyMarkers(distance);
QLabel *lbl = m_s2d_detlabels[wscode].value(detname);
if( lbl ) lbl->setText(distance);
}
}
Gigg, Martyn Anthony
committed
/**
* Set LOQ geometry information
* @param workspace The workspace to operate on
*/
void SANSRunWindow::setLOQGeometry(Mantid::API::MatrixWorkspace_sptr workspace, int wscode)
{
double dist_ms(0.0), dist_mdb(0.0), dist_hab(0.0);
//Sample
componentLOQDistances(workspace, dist_ms, dist_mdb, dist_hab);
QHash<QString, QLabel*> & labels = m_loq_detlabels[wscode];
QLabel *detlabel = labels.value("moderator-sample");
if( detlabel )
{
detlabel->setText(QString::number(dist_ms));
}
Gigg, Martyn Anthony
committed
detlabel = labels.value("sample-main-detector-bank");
if( detlabel )
{
detlabel->setText(QString::number(dist_mdb));
}
detlabel = labels.value("sample-HAB");
if( detlabel )
{
detlabel->setText(QString::number(dist_hab));
Gigg, Martyn Anthony
committed
}
/**
* Mark an error on a label
* @param label A pointer to a QLabel instance
*/
void SANSRunWindow::markError(QLabel* label)
{
if( label )
Gigg, Martyn Anthony
committed
label->setText("<font color=\"red\">" + label->text() + "</font>");
}
Gigg, Martyn Anthony
committed
//-------------------------------------
// Private SLOTS
//------------------------------------
Gigg, Martyn Anthony
committed
/**
* Select the base directory for the data
*/
void SANSRunWindow::selectDataDir()
{
QString data_dir = QFileDialog::getExistingDirectory(this, tr("Choose a directory"), m_last_dir);
Gigg, Martyn Anthony
committed
if( !data_dir.isEmpty() && QDir(data_dir).exists() )
Gigg, Martyn Anthony
committed
{
m_last_dir = data_dir;
Gigg, Martyn Anthony
committed
m_data_dir = data_dir;
Gigg, Martyn Anthony
committed
m_uiForm.datadir_edit->setText(data_dir);
}
}
/**
Gigg, Martyn Anthony
committed
* Select and load the user file
Gigg, Martyn Anthony
committed
*/
void SANSRunWindow::selectUserFile()
{
Gigg, Martyn Anthony
committed
if( !browseForFile("Select a user file", m_uiForm.userfile_edit) )
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
return;
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
runReduceScriptFunction("UserPath('" + QFileInfo(m_uiForm.userfile_edit->text()).path() + "')");
if( !loadUserFile() )
{
m_cfg_loaded = false;
showInformationBox("Error loading user file '" + m_uiForm.userfile_edit->text() + "', cannot continue.");
return;
}
m_cfg_loaded = true;
m_uiForm.tabWidget->setTabEnabled(1, true);
m_uiForm.tabWidget->setTabEnabled(2, true);
m_uiForm.tabWidget->setTabEnabled(3, true);
Gigg, Martyn Anthony
committed
//path() returns the directory
Gigg, Martyn Anthony
committed
m_last_dir = QFileInfo(m_uiForm.userfile_edit->text()).path();
}
/**
* Select and load a CSV file
*/
void SANSRunWindow::selectCSVFile()
{
Gigg, Martyn Anthony
committed
if( !browseForFile("Select CSV file",m_uiForm.csv_filename, "CSV files (*.csv)") )
Gigg, Martyn Anthony
committed
{
return;
}
Gigg, Martyn Anthony
committed
if( !loadCSVFile() )
{
return;
}
//path() returns the directory
m_last_dir = QFileInfo(m_uiForm.csv_filename->text()).path();
Gigg, Martyn Anthony
committed
}
/**
* Mark that a run number has changed
*/
void SANSRunWindow::runChanged()
{
m_warnings_issued = false;
forceDataReload(true);
Gigg, Martyn Anthony
committed
}