Skip to content
Snippets Groups Projects
SANSRunWindow.cpp 58.8 KiB
Newer Older
//----------------------
// Includes
//----------------------
#include "MantidQtCustomInterfaces/SANSRunWindow.h"
#include "MantidQtCustomInterfaces/SANSUtilityDialogs.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/Exception.h"
#include "MantidAPI/FrameworkManager.h"
#include "MantidAPI/IAlgorithm.h"
#include "MantidAPI/SpectraDetectorMap.h"
#include "MantidGeometry/IObjComponent.h"
#include "MantidGeometry/V3D.h"
#include <QLineEdit>
#include <QFileDialog>
#include <QHash>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QInputDialog>
#include <QRegExp>

//Add this class to the list of specialised dialogs in this namespace
namespace MantidQt
{
namespace CustomInterfaces
{
  DECLARE_SUBWINDOW(SANSRunWindow);
}
}

using namespace MantidQt::CustomInterfaces;

// Initialize the logger
Mantid::Kernel::Logger& SANSRunWindow::g_log = Mantid::Kernel::Logger::get("SANSRunWindow");

//----------------------------------------------
//----------------------------------------------
///Constructor
SANSRunWindow::SANSRunWindow(QWidget *parent) :
  UserSubWindow(parent), m_data_dir(""), m_ins_defdir(""), m_last_dir(""), m_cfg_loaded(true), m_run_no_boxes(), 
  m_period_lbls(), m_pycode_loqreduce(""), m_pycode_viewmask(""), m_run_changed(false), m_force_reload(false),
  m_delete_observer(*this,&SANSRunWindow::handleMantidDeleteWorkspace),
  m_logvalues(), m_maskcorrections(), m_lastreducetype(-1)
  m_reducemapper = new QSignalMapper(this);
  Mantid::API::AnalysisDataService::Instance().notificationCenter.addObserver(m_delete_observer);
  // Seems to crash on destruction of if I don't do this 
  Mantid::API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_delete_observer);
//--------------------------------------------
//--------------------------------------------
    m_uiForm.setupUi(this);

    //Button connections
    connect(m_uiForm.data_dirBtn, SIGNAL(clicked()), this, SLOT(selectDataDir()));
    connect(m_uiForm.userfileBtn, SIGNAL(clicked()), this, SLOT(selectUserFile()));

    connect(m_uiForm.load_dataBtn, SIGNAL(clicked()), this, SLOT(handleLoadButtonClick()));
    connect(m_uiForm.plotBtn, SIGNAL(clicked()), this, SLOT(handlePlotButtonClick()));
    connect(m_uiForm.runcentreBtn, SIGNAL(clicked()), this, SLOT(handleRunFindCentre()));
    connect(m_uiForm.saveBtn, SIGNAL(clicked()), this, SLOT(handleSaveButtonClick()));
    // Disable most things so that load is the only thing that can be done
    m_uiForm.oneDBtn->setEnabled(false);
    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)));

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

    //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(forceDataReload()));
    connect(m_uiForm.smpl_offset, SIGNAL(textEdited(const QString&)), this, SLOT(forceDataReload()));
    //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);

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

    // Combo boxes
    connect(m_uiForm.wav_dw_opt, SIGNAL(currentIndexChanged(int)), this, 
    connect(m_uiForm.q_dq_opt, SIGNAL(currentIndexChanged(int)), this, 
    connect(m_uiForm.qy_dqy_opt, SIGNAL(currentIndexChanged(int)), this, 
    connect(m_uiForm.inst_opt, SIGNAL(currentIndexChanged(int)), this, 
	    SLOT(handleInstrumentChange(int)));

    // file extensions
    m_uiForm.file_opt->setItemData(0, ".raw");
    m_uiForm.file_opt->setItemData(1, ".nxs");

    readSettings();
}    

/**
 * 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_uiForm.inst_opt->setCurrentIndex(value_store.value("instrument", 0).toInt());
  m_uiForm.file_opt->setCurrentIndex(value_store.value("fileextension", 0).toInt());
  //The instrument definition directory
  m_ins_defdir = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("instrumentDefinition.directory"));
  
  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;

  // Setup for instrument
  handleInstrumentChange(m_uiForm.inst_opt->currentIndex());

/**
 * 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());
  
/**
 * Load the data reduction template for the LOQ analysis. It is
 * currently assumed that this resides in the SANS subdirectory
 * pointed to by the pythonscripts.directory config varibale in
 * Mantid.properties
 */
bool SANSRunWindow::readPyReductionTemplate()
{
  QDir scriptsdir(QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("pythonscripts.directory")));
  QString reduce_script = scriptsdir.absoluteFilePath("SANS/SANSReductionGUI.py");
    
  if( !QFileInfo(reduce_script).exists() ) 
  {
    showInformationBox("Error: Unable to load template script, " + reduce_script + " does not exist");
    return false;
  }
  
  QFile py_script(reduce_script);
  if( !py_script.open(QIODevice::ReadOnly) ) 
  {
    showInformationBox("Error: Unable to access template script, " + reduce_script);
    return false;
  }
  QTextStream stream(&py_script);
  m_pycode_loqreduce.clear();
  while( !stream.atEnd() )
  {
    m_pycode_loqreduce.append(stream.readLine() + "\n");
  }
  py_script.close();
  return true;
}

/**
 * Load the mask template script for LOQ. It is
 * currently assumed that this resides in the SANS subdirectory
 * pointed to by the pythonscripts.directory config varibale in
 * Mantid.properties
 */
bool SANSRunWindow::readPyViewMaskTemplate()
{
  QDir scriptsdir(QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("pythonscripts.directory")));
  QString mask_script = scriptsdir.absoluteFilePath("SANS/SANSViewMask.py");
    
  if( !QFileInfo(mask_script).exists() ) 
  {
    showInformationBox("Error: Unable to load template script, " + mask_script + " does not exist");
    return false;
  }
  
  QFile py_script(mask_script);
  if( !py_script.open(QIODevice::ReadOnly) ) 
  {
    showInformationBox("Error: Unable to access template script, " + mask_script);
    return false;
  }
  QTextStream stream(&py_script);
  m_pycode_viewmask.clear();
  while( !stream.atEnd() )
  {
    m_pycode_viewmask.append(stream.readLine() + "\n");
  }
  py_script.close();
  return true;
}


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

  //Set a couple of things to default values that will get overwritten if present in the file
  handleInstrumentChange(m_uiForm.inst_opt->currentIndex());
  m_uiForm.dist_mod_mon->setText("-");
  //Setup mask file detector corrections
  m_maskcorrections.clear();
  m_maskcorrections["Front_Det_Z_corr"] = 0.0;
  m_maskcorrections["Front_Det_Y_corr"] = 0.0;
  m_maskcorrections["Front_Det_X_corr"] = 0.0;
  m_maskcorrections["Front_Det_Rot_corr"] = 0.0;
  m_maskcorrections["Rear_Det_Z_corr"] = 0.0;
  m_maskcorrections["Rear_Det_X_corr"] = 0.0;
 
  QDir work_dir = QDir(m_uiForm.datadir_edit->text());
  QTextStream stream(&user_file);
  QString data;
  while( !stream.atEnd() )
  {
    QString com_line = stream.readLine();
    //Skip comments lines
    if( com_line.startsWith("!") ) continue;
    
    if( com_line.startsWith("L/") )
    {
      readLimits(com_line.section("/", 1));
    }
    else if( com_line.startsWith("MON") )
    {
      //Line has the form MON/FIELD=...
      QString field = com_line.section("/", 1).section("=", 0, 0);
      if( field.compare("length", Qt::CaseInsensitive) == 0 )
        QStringList line_items = com_line.section('=',1).split(' ');
        if( line_items.count() == 2 )
        {
          m_uiForm.dist_mod_mon->setText(line_items[0]);
          m_uiForm.monitor_spec->setText(line_items[1]);
        }
        if( com_line.contains(']') ) filepath = com_line.section("]", 1);
        else filepath = com_line.section('=',1);

        //Check for relative or absolute path
        if( QFileInfo(filepath).isRelative() )
        {
          filepath = QFileInfo(user_file).absoluteDir().absoluteFilePath(filepath);
        if( field.compare("direct", Qt::CaseInsensitive) == 0 )
        {
      	  m_uiForm.direct_file->setText(filepath);
        }
        else if( field.compare("hab", Qt::CaseInsensitive) == 0 )
        {
	        m_uiForm.hab_file->setText(filepath);
        }
        else if( field.compare("flat", Qt::CaseInsensitive) == 0 )
        {
	        m_uiForm.flat_file->setText(filepath);
        }
        else {}
    else if( com_line.startsWith("set centre") )
    {
      m_uiForm.beam_x->setText(com_line.section(' ', 2, 2));
      m_uiForm.beam_y->setText(com_line.section(' ', 3, 3));
    }
    else if( com_line.startsWith("set scales") )
    {
      m_uiForm.scale_factor->setText(com_line.section(' ', 2, 2));
    }
    else if( com_line.startsWith("mask", Qt::CaseInsensitive) )
    {
      QString col1_txt(""), col2_txt("");
      QString type = com_line.section(' ',1);
      //TIME mask - MASK/T start end
      if( com_line.startsWith("mask/t", Qt::CaseInsensitive) )
	if( type.startsWith('s', Qt::CaseInsensitive) )
	  col1_txt = "Spectrum";
	  col2_txt = type;
	else if( type.startsWith('h', Qt::CaseInsensitive) || type.startsWith('v', Qt::CaseInsensitive) )
	  if( type.contains('+') )
	  {
	    col1_txt = "Box";
	  }
	  else
	  {
	    col1_txt = "Strip";
	  }
	  col2_txt = type;
      int row = m_uiForm.mask_table->rowCount();
      m_uiForm.mask_table->insertRow(row);
      QTableWidgetItem *item1 = new QTableWidgetItem(col1_txt);
      QTableWidgetItem *item2 = new QTableWidgetItem(col2_txt);
      m_uiForm.mask_table->setItem(row, 0, item1);
      m_uiForm.mask_table->setItem(row, 1, item2);
    else if( com_line.startsWith("DET/CORR", Qt::CaseInsensitive) )
    {
      QString det = com_line.section(' ',1, 1);
      QString axis = com_line.section(' ',2, 2);
      double value = com_line.section(' ',3, 3).toDouble();
      QString key;


      if( det.compare("rear", Qt::CaseInsensitive) == 0 )
      {
	if( axis.compare("x", Qt::CaseInsensitive) == 0 )
	{
	  key = "Rear_Det_X_corr";
	}
	else
	{
	  key = "Rear_Det_Z_corr";
	}
      }
      else
      {
	if( axis.compare("x", Qt::CaseInsensitive) == 0 )
	{
	  key = "Front_Det_X_corr";
	}
	else if( axis.compare("y", Qt::CaseInsensitive) == 0 )
	{
	  key = "Front_Det_Y_corr";
	}
	else if( axis.compare("z", Qt::CaseInsensitive) == 0 )
	{
	  key = "Front_Det_Z_corr";
	}
	else
	{
	  key = "Front_Det_Rot_corr";
	}
      }
      m_maskcorrections[key] = value;
    }
    else if(com_line.startsWith("SAMPLE/OFFSET"))
    {
      QString txt = com_line.section(' ', 1, 1);
      m_uiForm.smpl_offset->setText(txt);
    }
  m_uiForm.phi_min->setText("-90");
  m_uiForm.phi_max->setText("90");
  m_cfg_loaded = true;
  m_uiForm.userfileBtn->setText("Reload");
  m_uiForm.tabWidget->setTabEnabled(m_uiForm.tabWidget->count() - 1, true);
  return true;
}

/**
 * Read a limit line from the user file
 * @param com_line A line from the LOQ user file that started with "L/" (note that the tag has been removed)
 */
void SANSRunWindow::readLimits(const QString & com_line)
{
  QStringList pieces = com_line.split('/');
  QString quantity = pieces[0].section(' ', 0, 0);
  QString min = pieces[0].section(' ', 1, 1);
  QString max = pieces[0].section(' ', 2, 2);
  QString step = pieces[0].section(' ', 3, 3);

  //Ensure all doubles come out with a '0.' not just '.' prefix
  if( min.startsWith('.') ) min.prepend('0');
  if( max.startsWith('.') ) max.prepend('0');
  if( step.startsWith('.') ) step.prepend('0');

  if( quantity == "R" )
  {
    m_uiForm.rad_min->setText(min);
    m_uiForm.rad_max->setText(max);
    m_uiForm.rad_dr->setText(step);
    int row = m_uiForm.mask_table->rowCount();
    m_uiForm.mask_table->insertRow(row);
    QTableWidgetItem *item1 = new QTableWidgetItem("Beam stop");
    QTableWidgetItem *item2 = new QTableWidgetItem("infinite-cylinder");
    m_uiForm.mask_table->setItem(row, 0, item1);
    m_uiForm.mask_table->setItem(row, 1, item2);
    m_uiForm.mask_table->insertRow(++row);
    item2 = new QTableWidgetItem("infinite-cylinder");
    m_uiForm.mask_table->setItem(row, 0, item1);
    m_uiForm.mask_table->setItem(row, 1, item2);
    m_uiForm.all_spec_min->setText(min);
    m_uiForm.all_spec_max->setText(max);
  }
  else
  {
    int opt_index(0);
    if( pieces[1].compare("log", Qt::CaseInsensitive) == 0 ) 
    { 
      opt_index = 1;
    }
    if( quantity == "WAV" )
    {
      m_uiForm.wav_min->setText(min);
      m_uiForm.wav_max->setText(max);
      m_uiForm.wav_dw->setText(step);
      m_uiForm.wav_dw_opt->setCurrentIndex(opt_index);
      if( opt_index == 0 ) m_uiForm.wav_step_lbl->setText("stepping");
      else  m_uiForm.wav_step_lbl->setText("dW / W");
    }
    else if( quantity == "Q" )
    {
      m_uiForm.q_min->setText(min);
      m_uiForm.q_max->setText(max);
      m_uiForm.q_dq->setText(step);
      m_uiForm.q_dq_opt->setCurrentIndex(opt_index);
      if( opt_index == 0 ) m_uiForm.q_step_lbl->setText("stepping");
      else  m_uiForm.q_step_lbl->setText("dQ / Q");
    }
    else if( quantity == "QXY" )
    {
      m_uiForm.qy_max->setText(max);
      m_uiForm.qy_dqy->setText(step);
      m_uiForm.qy_dqy_opt->setCurrentIndex(opt_index);
      if( opt_index == 0 ) m_uiForm.qy_step_lbl->setText("stepping");
      else  m_uiForm.qy_step_lbl->setText("dQy / Qy");
    }
    else return;
  }
/**
 * Retrieve and set the component distances
 * @param wsname The name of the workspace
 * @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
 * @param lmm The moderator-monitor distance
void SANSRunWindow::componentDistances(const QString & wsname, double & lms, double & lsda, double & lsdb, double & lmm)
  Mantid::API::MatrixWorkspace_sptr workspace_ptr = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>
    (Mantid::API::AnalysisDataService::Instance().retrieve(wsname.toStdString()));

  Mantid::API::IInstrument_sptr instr = workspace_ptr->getInstrument();
  if( instr == boost::shared_ptr<Mantid::API::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.;
  std::string comp_name("main-detector-bank");
  bool isS2D(false);
  if( m_uiForm.inst_opt->currentIndex() == 1 ) 
  {
    isS2D = true;
  boost::shared_ptr<Mantid::Geometry::IComponent> comp = instr->getComponentByName(comp_name);
  if( comp != boost::shared_ptr<Mantid::Geometry::IComponent>() )
  {
    lsda = sample->getPos().distance(comp->getPos()) * 1000.;
  comp = instr->getComponentByName(comp_name);
  if( comp != boost::shared_ptr<Mantid::Geometry::IComponent>() )
  {
    lsdb = sample->getPos().distance(comp->getPos()) * 1000.;
  if( lmm < 0.0 ) return;
  int monitor_spectrum = m_uiForm.monitor_spec->text().toInt();
  std::vector<int> dets = workspace_ptr->spectraMap().getDetectors(monitor_spectrum);
  if( dets.empty() ) return;
  Mantid::Geometry::IDetector_sptr detector = instr->getDetector(dets[0]);
  lmm = detector->getDistance(*source) * 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)
  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);
  m_uiForm.runcentreBtn->setEnabled(!running);
    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 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;
}

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

/**
 * Get the path the the raw file indicated by the run number.This checks the given directory for the number 
 * given. Left-padding of zeroes is done as required.
QString SANSRunWindow::getRawFilePath(const QString & data_dir, const QString & run_no, const QString & ext) const
{
  //Do a quick check for the existence of the file with these exact credentials
  QDir directory(data_dir);
  QString prefix = m_uiForm.inst_opt->currentText();
  QString filename = directory.absoluteFilePath(prefix + run_no + ext);
  g_log.debug("Checking for run " + run_no.toStdString());
  // If nothing pad the number and check
  QString padded_no = run_no.rightJustified(8, '0', true);
  filename = directory.absoluteFilePath(prefix + padded_no + ext);
  g_log.debug("Not found. Checking padded name " + filename.toStdString());
  if( QFileInfo(filename).exists() ) return filename;
  else return QString();
 * Create the mask strings for spectra and times
void SANSRunWindow::createMaskStrings(QString & spectramask, QString & timemask) const
  int nrows = m_uiForm.mask_table->rowCount();
    QString detail = m_uiForm.mask_table->item(r, 1)->text();
    if( detail == "infinite-cylinder" ) continue;
    QString type = m_uiForm.mask_table->item(r, 0)->text();
    if( type == "Time" )
    {
      timemask += detail + ";";
    }
    else
    {
      spectramask += detail + ",";
    }
  
  QStringList guimask = m_uiForm.user_maskEdit->text().split(',');
  QStringListIterator itr(guimask);
  while(itr.hasNext())
  {
    QString item = itr.next();
    if( item.startsWith('t', Qt::CaseInsensitive) )
    {
      timemask += item.section('t',1) + ";";
    }
    else
    {
      spectramask += item + ",";
    }
  }
    
void SANSRunWindow::setupGeometryDetails()
{
  // Reset the geometry box
  resetGeometryDetailsBox();

  const char format('f');
  const int prec(3);
  bool warn_user(false);  
  // LOQ
  if( m_uiForm.inst_opt->currentIndex() == 0 )
  {
    QString wsname = m_workspace_names.value(0);
    if( m_uiForm.sct_smp_prd->text() != "1" ) wsname += "_" + m_uiForm.sct_smp_prd->text();
    // Set up distance information
    double dist_ms_smp(0.0), dist_sample_mdb(0.0), dist_smp_hab(0.0), dist_mm(-1.0);
    if( m_uiForm.dist_mod_mon->text() == "-" ) dist_mm = 0.0;
    componentDistances(wsname, dist_ms_smp, dist_sample_mdb, dist_smp_hab, dist_mm);
    m_uiForm.dist_sample_ms->setText(QString::number(dist_ms_smp, format, prec));
    m_uiForm.dist_smp_mdb->setText(QString::number(dist_sample_mdb, format, prec));
    m_uiForm.dist_smp_hab->setText(QString::number(dist_smp_hab, format, prec));

    if( dist_mm > 0.0 ) 
    {
      m_uiForm.dist_mod_mon->setText(QString::number(dist_mm, format, prec));
    }
    
    wsname = m_workspace_names.value(1);
    if( m_uiForm.sct_can_prd->text() != "1" ) wsname += "_" + m_uiForm.sct_can_prd->text();
    
    double dist_ms_can(0.0), dist_can_mdb(0.0), dist_sd2_can(0.0);
    // We only need the moderator-monitor from the sample so -1.0 flags not to calculate it
    dist_mm = -1.0;
    componentDistances(wsname, dist_ms_can, dist_can_mdb, dist_sd2_can, dist_mm);
    m_uiForm.dist_can_ms->setText(QString::number(dist_ms_can, format, prec));
    m_uiForm.dist_can_mdb->setText(QString::number(dist_can_mdb, format, prec));
    m_uiForm.dist_can_hab->setText(QString::number(dist_sd2_can, format, prec));
    if( dist_ms_can > 0.0 && abs(dist_ms_can - dist_ms_smp) > 5e-3 )
    {
      warn_user = true;
      m_uiForm.dist_sample_ms->setText("<font color='red'>" + m_uiForm.dist_sample_ms->text() + "</font>");
      m_uiForm.dist_can_ms->setText("<font color='red'>" + m_uiForm.dist_can_ms->text() + "</font>");
    }
    if( dist_can_mdb > 0.0  && abs(dist_can_mdb - dist_sample_mdb) > 5e-3 )
    {
      warn_user = true;
      m_uiForm.dist_smp_mdb->setText("<font color='red'>" + m_uiForm.dist_smp_mdb->text() + "</font>");
      m_uiForm.dist_can_mdb->setText("<font color='red'>" + m_uiForm.dist_can_mdb->text() + "</font>");
    }
    if( dist_sd2_can > 0.0 && abs(dist_sd2_can - dist_smp_hab) > 5e-3 )
    {
      warn_user = true;
      m_uiForm.dist_smp_hab->setText("<font color='red'>" + m_uiForm.dist_smp_hab->text() + "</font>");
      m_uiForm.dist_can_hab->setText("<font color='red'>" + m_uiForm.dist_can_hab->text() + "</font>");
    }
    wsname = m_workspace_names.value(2);
    if( m_uiForm.sct_bkgd_prd->text() != "1" ) wsname += "_" + m_uiForm.sct_bkgd_prd->text();
    
    double dist_ms_bckd(0.0), dist_sd1_bckd(0.0), dist_sd2_bckd(0.0);
    componentDistances(wsname, dist_ms_bckd, dist_sd1_bckd, dist_sd2_bckd, dist_mm);
    m_uiForm.dist_bkgd_ms->setText(QString::number(dist_ms_bckd, format, prec));
    m_uiForm.dist_bkgd_mdb->setText(QString::number(dist_sd1_bckd, format, prec));
    m_uiForm.dist_bkgd_hab->setText(QString::number(dist_sd2_bckd, format, prec));
    QString wsname = m_workspace_names.value(0);
    if( m_uiForm.sct_smp_prd->text() != "1" ) wsname += "_" + m_uiForm.sct_smp_prd->text();
    double dummy(0.0), dist_ms_smp(0.0), dist_mm(-1.0);
    if( m_uiForm.dist_mon_s2d->text() == "-" ) dist_mm = 0.0;
    componentDistances(wsname, dist_ms_smp, dummy, dummy, dist_mm);
    m_uiForm.dist_sample_ms_s2d->setText(QString::number(dist_ms_smp, format, prec));

    if( dist_mm > 0.0 ) 
    {
      m_uiForm.dist_mon_s2d->setText(QString::number(dist_mm, format, prec));
    }


    //Sample run
    //rear X
    double smp_rearX = m_logvalues.value("Rear_Det_X") + m_maskcorrections.value("Rear_Det_X_corr");
    m_uiForm.dist_smp_rearX->setText(formatDouble(smp_rearX, format, prec, "black"));
    //rear Z
    double smp_rearZ  = m_logvalues.value("Rear_Det_Z") + m_maskcorrections.value("Rear_Det_Z_corr");
    m_uiForm.dist_smp_rearZ->setText(formatDouble(smp_rearZ, format, prec, "black"));
    //front X
    double smp_frontX = m_logvalues.value("Front_Det_X") + m_maskcorrections.value("Front_Det_X_corr");
    m_uiForm.dist_smp_frontX->setText(QString::number(smp_frontX, format, prec));
    //front Z
    double smp_frontZ = m_logvalues.value("Front_Det_Z") + m_maskcorrections.value("Front_Det_Z_corr");
    m_uiForm.dist_smp_frontZ->setText(QString::number(smp_frontZ, format, prec));
    //front rot
    double smp_rot = m_logvalues.value("Front_Det_Rot") + m_maskcorrections.value("Front_Det_Rot_corr");
    m_uiForm.smp_rot->setText(QString::number(smp_rot, format, prec));
    wsname = m_workspace_names.value(1);
    if( !wsname.isEmpty() )
      if( m_uiForm.sct_can_prd->text() != "1" ) wsname += "_" + m_uiForm.sct_can_prd->text();
      dist_ms_smp = 0.0;
      dummy = -1.0;
      componentDistances(wsname, dist_ms_smp, dummy, dummy, dummy);
      m_uiForm.dist_can_ms_s2d->setText(QString::number(dist_ms_smp, format, prec));

      //Get log values for this workspace
      QHash<QString, double> logs = loadDetectorLogs(QDir(m_uiForm.datadir_edit->text()).absolutePath(), m_uiForm.sct_can_edit->text());
      //rear X
      double can_rearX = logs.value("Rear_Det_X") + m_maskcorrections.value("Rear_Det_X_corr");
      //Check for differences above 5mm with sample
      if( std::fabs(smp_rearX - can_rearX) > 5e-3 )
      {
	warn_user = true;
	m_uiForm.dist_can_rearX->setText(formatDouble(can_rearX, format, prec, "red"));
	m_uiForm.dist_smp_rearX->setText(formatDouble(smp_rearX, format, prec, "red"));
      }
      else
      {
	m_uiForm.dist_can_rearX->setText(formatDouble(can_rearX, format, prec, "black"));
      }

      //rear Z
      double can_rearZ = logs.value("Rear_Det_Z") + m_maskcorrections.value("Rear_Det_Z_corr");
      if( std::fabs(smp_rearZ - can_rearZ) > 5e-3 )
      {
	warn_user = true;
	m_uiForm.dist_can_rearZ->setText(formatDouble(can_rearZ, format, prec, "red"));
	m_uiForm.dist_smp_rearZ->setText(formatDouble(smp_rearZ, format, prec, "red"));
      }
      else
      {
	m_uiForm.dist_can_rearZ->setText(formatDouble(can_rearZ, format, prec, "black"));
      }
      //front X
      double can_frontX = logs.value("Front_Det_X") + m_maskcorrections.value("Front_Det_X_corr");
      if( std::fabs(smp_frontX - can_frontX) > 5e-3 )
      {
	warn_user = true;
	m_uiForm.dist_can_frontX->setText(formatDouble(can_frontX, format, prec, "red"));
	m_uiForm.dist_smp_frontX->setText(formatDouble(smp_frontX, format, prec, "red"));
      }
      else
      {
	m_uiForm.dist_can_frontX->setText(formatDouble(can_frontX, format, prec, "black"));
      }
      //front Z
      double can_frontZ = logs.value("Front_Det_Z") + m_maskcorrections.value("Front_Det_Z_corr");
      if( std::fabs(smp_frontZ - can_frontZ) > 5e-3 )
      {
	warn_user = true;
	m_uiForm.dist_can_frontZ->setText(formatDouble(can_frontZ, format, prec, "red"));
	m_uiForm.dist_smp_frontZ->setText(formatDouble(smp_frontZ, format, prec, "red"));
      }
      else
      {
	m_uiForm.dist_can_frontZ->setText(formatDouble(can_frontZ, format, prec, "black"));
      }
      //front rot
      double can_rot = logs.value("Front_Det_Rot") + m_maskcorrections.value("Front_Det_Rot_corr");
      if( std::fabs(smp_rot - can_rot) > 5e-3 )
      {
	warn_user = true;
	m_uiForm.can_rot->setText(formatDouble(can_rot, format, prec, "red"));
	m_uiForm.smp_rot->setText(formatDouble(smp_rot, format, prec, "red"));
      }
      else
      {
	m_uiForm.can_rot->setText(formatDouble(can_rot, format, prec, "black"));
      }
    }
    // Background
    wsname = m_workspace_names.value(2);
    if( !wsname.isEmpty() )
      if( m_uiForm.sct_bkgd_prd->text() != "1" ) wsname += "_" + m_uiForm.sct_bkgd_prd->text();
      dist_ms_smp = 0.0;
      componentDistances(wsname, dist_ms_smp, dummy, dummy, dummy);
      m_uiForm.dist_bkgd_ms_s2d->setText(QString::number(dist_ms_smp, format, prec));

      //Get log values for this workspace
      QHash<QString, double> logs = loadDetectorLogs(QDir(m_uiForm.datadir_edit->text()).absolutePath(), m_uiForm.sct_bkgd_edit->text());
      //rear X
      double bkgd_rearX = logs.value("Rear_Det_X") + m_maskcorrections.value("Rear_Det_X_corr");
      //Check for differences above 5mm with sample
      if( std::fabs(smp_rearX - bkgd_rearX) > 5e-3 )
      {
	warn_user = true;
	m_uiForm.dist_bkgd_rearX->setText(formatDouble(bkgd_rearX, format, prec, "red"));
	m_uiForm.dist_smp_rearX->setText(formatDouble(smp_rearX, format, prec, "red"));
      }
      else
      {
	m_uiForm.dist_bkgd_rearX->setText(formatDouble(bkgd_rearX, format, prec, "black"));
      }

      //rear Z
      double bkgd_rearZ = logs.value("Rear_Det_Z") + m_maskcorrections.value("Rear_Det_Z_corr");
      if( std::fabs(smp_rearZ - bkgd_rearZ) > 5e-3 )
      {
	warn_user = true;
	m_uiForm.dist_bkgd_rearZ->setText(formatDouble(bkgd_rearZ, format, prec, "red"));
	m_uiForm.dist_smp_rearZ->setText(formatDouble(smp_rearZ, format, prec, "red"));
      }
      else
      {
	m_uiForm.dist_bkgd_rearZ->setText(formatDouble(bkgd_rearZ, format, prec, "black"));
      }
      //front X
      double bkgd_frontX = logs.value("Front_Det_X") + m_maskcorrections.value("Front_Det_X_corr");
      if( std::fabs(smp_frontX - bkgd_frontX) > 5e-3 )
      {
	warn_user = true;
	m_uiForm.dist_bkgd_frontX->setText(formatDouble(bkgd_frontX, format, prec, "red"));
	m_uiForm.dist_smp_frontX->setText(formatDouble(smp_frontX, format, prec, "red"));
      }
      else
      {
	m_uiForm.dist_bkgd_frontX->setText(formatDouble(bkgd_frontX, format, prec, "black"));
      }
      //front Z
      double bkgd_frontZ = logs.value("Front_Det_Z") + m_maskcorrections.value("Front_Det_Z_corr");
      if( std::fabs(smp_frontZ - bkgd_frontZ) > 5e-3 )
      {
	warn_user = true;
	m_uiForm.dist_bkgd_frontZ->setText(formatDouble(bkgd_frontZ, format, prec, "red"));
	m_uiForm.dist_smp_frontZ->setText(formatDouble(smp_frontZ, format, prec, "red"));
      }
      else
      {
	m_uiForm.dist_bkgd_frontZ->setText(formatDouble(bkgd_frontZ, format, prec, "black"));
      }
      //front rot
      double bkgd_rot = logs.value("Front_Det_Rot") + m_maskcorrections.value("Front_Det_Rot_corr");
      if( std::fabs(smp_rot - bkgd_rot) > 5e-3 )
      {
	warn_user = true;
	m_uiForm.bkgd_rot->setText(formatDouble(bkgd_rot, format, prec, "red"));
	m_uiForm.smp_rot->setText(formatDouble(smp_rot, format, prec, "red"));
      }
      else
      {
	m_uiForm.bkgd_rot->setText(formatDouble(bkgd_rot, format, prec, "black"));