Skip to content
Snippets Groups Projects
SANSRunWindow.cpp 82.9 KiB
Newer Older
//----------------------
// Includes
//----------------------
#include "MantidQtCustomInterfaces/SANSRunWindow.h"
#include "MantidQtCustomInterfaces/SANSUtilityDialogs.h"
#include "MantidQtCustomInterfaces/SANSAddFiles.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/Exception.h"
#include "MantidAPI/FrameworkManager.h"
#include "MantidAPI/IAlgorithm.h"
#include "MantidAPI/SpectraDetectorMap.h"
#include <QLineEdit>
#include <QFileDialog>
#include <QHash>
#include <QTreeWidgetItem>
#include <QMessageBox>
#include <QInputDialog>
#include <QApplication>
#include <QClipboard>
#include <QTemporaryFile>
//Add this class to the list of specialised dialogs in this namespace
namespace MantidQt
{
namespace CustomInterfaces
{
  DECLARE_SUBWINDOW(SANSRunWindow);
}
}

using namespace MantidQt::MantidWidgets;
using namespace MantidQt::CustomInterfaces;
using namespace Mantid::Kernel;
using namespace Mantid::API;
Logger& SANSRunWindow::g_log = Logger::get("SANSRunWindow");
//----------------------------------------------
//----------------------------------------------
///Constructor
SANSRunWindow::SANSRunWindow(QWidget *parent) :
  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(),
  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("")
  {
    // Seems to crash on destruction of if I don't do this 
    AnalysisDataService::Instance().notificationCenter.removeObserver(m_delete_observer);
    saveSettings();
    delete m_addFilesTab;
  }
//--------------------------------------------
//--------------------------------------------
  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);

  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);
  m_uiForm.saveDefault_btn->setEnabled(false);
  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();


  // 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();
}

/**
 * Run local Python initialization code
 */
void SANSRunWindow::initLocalPython()
{
  // Import the SANS module and set the correct instrument
  QString result = runPythonCode("try:\n\tfrom SANSReduction import *\nexcept (ImportError,SyntaxError), details:\tprint 'Error importing SANSReduction: ' + str(details)");
  if( result.trimmed().isEmpty() )
  {
    m_have_reducemodule = true;
  }
  else
  {
    showInformationBox(result);
    m_have_reducemodule = false;
    setProcessingState(true, -1);    
  }
}
/** 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;
}
/** 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()));
}
/** 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)));
}
/**
 * Initialize the widget maps
 */
void SANSRunWindow::initWidgetMaps()
{
    //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);

    //Period label hash. Each label has a buddy set to its corresponding text edit field
    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);

  //       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
    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);

    // Full workspace names as they appear in the service
    m_workspace_names.clear();


/**
 * Restore previous input
 */
void SANSRunWindow::readSettings()
{
  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());
  m_last_dir = value_store.value("last_dir", "").toString();

  m_uiForm.inst_opt->setCurrentIndex(value_store.value("instrument", 0).toInt());
  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();
  }

  m_ins_defdir = QString::fromStdString(ConfigService::Instance().getString("instrumentDefinition.directory"));

  // Setup for instrument
  handleInstrumentChange(m_uiForm.inst_opt->currentIndex());
  //Set old file extension
  m_uiForm.file_opt->setCurrentIndex(value_store.value("fileextension", 0).toInt());

  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;

}
/** 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());

/**
 * Save input for future use
 */
void SANSRunWindow::saveSettings()
{
  QSettings value_store;
  value_store.beginGroup("CustomInterfaces/SANSRunWindow");
  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());
  }
  value_store.setValue("instrument", m_uiForm.inst_opt->currentIndex());
  value_store.setValue("fileextension", m_uiForm.file_opt->currentIndex());
  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);
  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());
/**
 * 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 )
  {
  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];
}

/**
 * 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);
}

/**
 * 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() )
  {
    filetext = QDir(m_data_dir).absoluteFilePath(filetext);
  if( !QFileInfo(filetext).exists() ) return false;
  QFile user_file(filetext);
  if( !user_file.open(QIODevice::ReadOnly) ) return false;
  //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);
  }
  // Use python function to read the file and then extract the fields
  if ( runReduceScriptFunction("print MaskFile(r'"+filetext+"')") != "True\n" )
  {
    return false;
  }
  handleInstrumentChange(m_uiForm.inst_opt->currentIndex());

  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);
  }
  //Qxy
  m_uiForm.qy_max->setText(runReduceScriptFunction("printParameter('QXY2'),"));
  setLimitStepParameter("Qxy", runReduceScriptFunction("printParameter('DQXY'),"), m_uiForm.qy_dqy, m_uiForm.qy_dqy_opt);

  // 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);
  }

  m_uiForm.monitor_spec->setText(runReduceScriptFunction(
    "printParameter('INSTRUMENT.get_incident_mon()'),"));
  m_uiForm.trans_monitor->setText(runReduceScriptFunction(
    "printParameter('INSTRUMENT.incid_mon_4_trans_calc'),"));
  m_uiForm.monitor_interp->setChecked(runReduceScriptFunction(
    "printParameter('INSTRUMENT.is_interpolating_norm'),") == "True");
    runReduceScriptFunction("printParameter('INSTRUMENT.use_interpol_trans_calc'),") == "True");
  m_uiForm.direct_file->setText(runReduceScriptFunction("printParameter('DIRECT_BEAM_FILE_R'),"));
  m_uiForm.front_direct_file->setText(runReduceScriptFunction("printParameter('DIRECT_BEAM_FILE_F'),"));

  //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('INSTRUMENT.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));

  //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
    "printParameter('INSTRUMENT.cur_detector().name()')");
  index = m_uiForm.detbank_sel->findText(param);  
  if( index >= 0 && index < 2 )
  {
    m_uiForm.detbank_sel->setCurrentIndex(index);
  }

  // Phi values 
  m_uiForm.phi_min->setText(runReduceScriptFunction("printParameter('PHIMIN')"));
  m_uiForm.phi_max->setText(runReduceScriptFunction("printParameter('PHIMAX')"));

  if ( runReduceScriptFunction("printParameter('PHIMIRROR')") == "True" )
  {
    m_uiForm.mirror_phi->setChecked(true);
  }
  else
  {
    m_uiForm.mirror_phi->setChecked(false);
  }
  m_cfg_loaded = true;
  m_uiForm.userfileBtn->setText("Reload");
  m_uiForm.tabWidget->setTabEnabled(m_uiForm.tabWidget->count() - 1, true);
/**
 * 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();
  int errors(0);
  while( !file_in.atEnd() )
  {
    QString line = file_in.readLine().simplified();
    if( !line.isEmpty() )
    {
      errors += addBatchLine(line, ",");
    }
  }
  if( errors > 0 )
    showInformationBox("Warning: " + QString::number(errors) + " malformed lines detected in \"" + filename + "\". Lines skipped.");
 * 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
void SANSRunWindow::setLimitStepParameter(const QString& pname, QString param, QLineEdit* step_value, QComboBox* step_type)
    int index = step_type->findText("Logarithmic");
    if( index < 0 )
    {
     raiseOneTimeMessage("Warning: Unable to find logarithmic scale option for " + pname + ", setting as linear.", 1);
     index = step_type->findText("Linear");
    }
    step_type->setCurrentIndex(index);
    step_value->setText(param.remove(0,1));
    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);
	}

  QString reardet_name("rear-detector"), frontdet_name("front-detector");
  if( m_uiForm.inst_opt->currentIndex() == 0 )
  {
    reardet_name = "main-detector-bank";
    frontdet_name = "HAB";
  }
  
  // First create 2 default mask cylinders at min and max radius for the beam stop and 
  // corners
  m_uiForm.mask_table->insertRow(0);
  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"));
  if( m_uiForm.rad_max->text() != "-1" )
  {  
    m_uiForm.mask_table->insertRow(1);
    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"));
  }

  //Now add information from the mask file
  //Spectrum mask
  QString mask_string = runReduceScriptFunction("printParameter('SPECMASKSTRING')");
  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)
{
  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);
    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));
/**
 * 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);
  while(sitr.hasNext())
  {
    int row = m_uiForm.mask_table->rowCount();
    m_uiForm.mask_table->insertRow(row);
    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()));
 * @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
 */
void SANSRunWindow::componentLOQDistances(Mantid::API::MatrixWorkspace_sptr workspace, double & lms, double & lsda, double & lsdb)
  IInstrument_sptr instr = workspace->getInstrument();
  if( instr == boost::shared_ptr<IInstrument>() ) return;
  Mantid::Geometry::IObjComponent_sptr source = instr->getSource();
  if( source == boost::shared_ptr<Mantid::Geometry::IObjComponent>() ) return;
  Mantid::Geometry::IObjComponent_sptr sample = instr->getSample();
  if( sample == boost::shared_ptr<Mantid::Geometry::IObjComponent>() ) return;

  lms = source->getPos().distance(sample->getPos()) * 1000.;
  boost::shared_ptr<Mantid::Geometry::IComponent> comp = instr->getComponentByName("main-detector-bank");
  if( comp != boost::shared_ptr<Mantid::Geometry::IComponent>() )
  {
    lsda = sample->getPos().distance(comp->getPos()) * 1000.;
  if( comp != boost::shared_ptr<Mantid::Geometry::IComponent>() )
  {
    lsdb = sample->getPos().distance(comp->getPos()) * 1000.;
/**
 * Set the state of processing.
 * @param running If we are processing then some interaction is disabled
 * @param type The reduction type, 0 = 1D and 1 = 2D
void SANSRunWindow::setProcessingState(bool running, int type)
  if( m_uiForm.single_mode_btn->isChecked() )
  {
    m_uiForm.load_dataBtn->setEnabled(!running);
  }
  else
  {
    m_uiForm.load_dataBtn->setEnabled(false);
  }

  //buttons that are available as long as Python is available
  m_uiForm.oneDBtn->setEnabled(!running);
  m_uiForm.twoDBtn->setEnabled(!running);
  m_uiForm.saveSel_btn->setEnabled(!running);
  m_uiForm.runcentreBtn->setEnabled(!running);
  m_uiForm.userfileBtn->setEnabled(!running);
  m_uiForm.data_dirBtn->setEnabled(!running);
    m_uiForm.saveDefault_btn->setEnabled(false);

    if( type == 0 )
    {   
      m_uiForm.oneDBtn->setText("Running ...");
    }
    m_uiForm.oneDBtn->setText("1D Reduce");
    m_uiForm.twoDBtn->setText("2D Reduce");

  for( int i = 0; i < 4; ++i)
  {
    if( i == m_uiForm.tabWidget->currentIndex() ) continue;
    m_uiForm.tabWidget->setTabEnabled(i, !running);
  }

  QCoreApplication::processEvents();
}

/**
 * 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 AnalysisDataService::Instance().doesExist(ws_name.toStdString());
/**
 * @returns A list of the currently available workspaces
 */
QStringList SANSRunWindow::currentWorkspaceList() const
{
  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;
}

/**
 * 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;
}

 * Create the mask strings for spectra and times
void SANSRunWindow::addUserMaskStrings(QString & exec_script)
  exec_script += "Mask('MASK/CLEAR')\nMask('MASK/CLEAR/TIME')\n";

  //Pull in the table details first, skipping the first two rows
  int nrows = m_uiForm.mask_table->rowCount();
    if( m_uiForm.mask_table->item(row, 2)->text().startsWith("inf") )
    {
      continue;
    }
    //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";    
  }

  //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())
    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) ||