-
Arturs Bekasovs authored
Refs #7557
Arturs Bekasovs authoredRefs #7557
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MuonAnalysis.cpp 121.21 KiB
//----------------------
// Includes
//----------------------
#include "MantidQtCustomInterfaces/MuonAnalysis.h"
#include "MantidQtCustomInterfaces/MuonAnalysisHelper.h"
#include "MantidQtCustomInterfaces/MuonAnalysisOptionTab.h"
#include "MantidQtCustomInterfaces/MuonAnalysisFitDataTab.h"
#include "MantidQtCustomInterfaces/MuonAnalysisResultTableTab.h"
#include "MantidQtCustomInterfaces/IO_MuonGrouping.h"
#include "MantidQtAPI/FileDialogHandler.h"
#include "MantidQtMantidWidgets/FitPropertyBrowser.h"
#include "MantidQtMantidWidgets/MuonFitPropertyBrowser.h"
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/Exception.h"
#include "MantidAPI/FrameworkManager.h"
#include "MantidAPI/IAlgorithm.h"
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/WorkspaceGroup.h"
#include "MantidAPI/Run.h"
#include "MantidAPI/TableRow.h"
#include "MantidGeometry/IComponent.h"
#include "MantidGeometry/IDetector.h"
#include "MantidKernel/V3D.h"
#include "MantidKernel/Exception.h"
#include "MantidKernel/FacilityInfo.h"
#include "MantidGeometry/Instrument/XMLlogfile.h"
#include "MantidGeometry/Instrument/DetectorGroup.h"
#include "MantidKernel/cow_ptr.h"
#include <Poco/File.h>
#include <Poco/Path.h>
#include <Poco/StringTokenizer.h>
#include <boost/lexical_cast.hpp>
#include <algorithm>
#include <QLineEdit>
#include <QVariant>
#include <QtProperty>
#include <QFileDialog>
#include <QHash>
#include <QTextStream>
#include <QTreeWidgetItem>
#include <QSettings>
#include <QMessageBox>
#include <QInputDialog>
#include <QSignalMapper>
#include <QHeaderView>
#include <QApplication>
#include <QTemporaryFile>
#include <QDesktopServices>
#include <QUrl>
#include <fstream>
//Add this class to the list of specialised dialogs in this namespace
namespace MantidQt
{
namespace CustomInterfaces
{
DECLARE_SUBWINDOW(MuonAnalysis);
using namespace Mantid::API;
using namespace Mantid::Kernel;
using namespace MantidQt::MantidWidgets;
using namespace MantidQt::CustomInterfaces;
using namespace MantidQt::CustomInterfaces::Muon;
using namespace Mantid::Geometry;
// Initialize the logger
Logger& MuonAnalysis::g_log = Logger::get("MuonAnalysis");
// Static constants
const QString MuonAnalysis::NOT_AVAILABLE("N/A");
//----------------------
// Public member functions
//----------------------
///Constructor
MuonAnalysis::MuonAnalysis(QWidget *parent) :
UserSubWindow(parent), m_last_dir(), m_workspace_name("MuonAnalysis"), m_currentDataName(),
m_groupTableRowInFocus(0), m_pairTableRowInFocus(0),m_tabNumber(0), m_groupNames(),
m_settingsGroup("CustomInterfaces/MuonAnalysis/"), m_updating(false), m_loaded(false),
m_deadTimesChanged(false), m_textToDisplay(""), m_nexusTimeZero(0.0)
{}
/**
* Initialize local Python environmnet.
*/
void MuonAnalysis::initLocalPython()
{
QString code;
code += "from mantid.simpleapi import *\n";
// Needed for Python GUI API
code += "from PyQt4.QtGui import QPen, QBrush, QColor\n"
"from PyQt4.QtCore import QSize\n";
runPythonCode(code);
// TODO: Following shouldn't be here. It is now because ApplicationWindow sets up the Python
// environment only after the UserSubWindow is shown.
// Hide the toolbars, if user wants to
if(m_uiForm.hideToolbars->isChecked())
setToolbarsHidden(true);
}
/// Set up the dialog layout
void MuonAnalysis::initLayout()
{
m_uiForm.setupUi(this);
m_uiForm.fitBrowser->init();
// alow appending files
m_uiForm.mwRunFiles->allowMultipleFiles(true);
// Further set initial look
startUpLook();
createMicroSecondsLabels(m_uiForm);
m_uiForm.mwRunFiles->readSettings(m_settingsGroup + "mwRunFilesBrowse");
connect(m_uiForm.previousRun, SIGNAL(clicked()), this, SLOT(checkAppendingPreviousRun()));
connect(m_uiForm.nextRun, SIGNAL(clicked()), this, SLOT(checkAppendingNextRun()));
m_optionTab = new MuonAnalysisOptionTab(m_uiForm, m_settingsGroup);
m_optionTab->initLayout();
// Add the graphs back to mantid if the user selects not to hide graphs on settings tab.
connect(m_optionTab, SIGNAL(notHidingGraphs()), this, SLOT(showAllPlotWindows()));
m_fitDataTab = new MuonAnalysisFitDataTab(m_uiForm);
m_fitDataTab->init();
m_resultTableTab = new MuonAnalysisResultTableTab(m_uiForm);
connect(m_resultTableTab, SIGNAL(runPythonCode(const QString&, bool)),
this, SIGNAL(runAsPythonScript(const QString&, bool)));
setCurrentDataName(NOT_AVAILABLE);
// connect guess alpha
connect(m_uiForm.guessAlphaButton, SIGNAL(clicked()), this, SLOT(guessAlphaClicked()));
// signal/slot connections to respond to changes in instrument selection combo boxes
connect(m_uiForm.instrSelector, SIGNAL(instrumentSelectionChanged(const QString&)), this, SLOT(userSelectInstrument(const QString&)));
// Load current
connect(m_uiForm.loadCurrent, SIGNAL(clicked()), this, SLOT(runLoadCurrent()));
// If group table change
// currentCellChanged ( int currentRow, int currentColumn, int previousRow, int previousColumn )
connect(m_uiForm.groupTable, SIGNAL(cellChanged(int, int)), this, SLOT(groupTableChanged(int, int)));
connect(m_uiForm.groupTable, SIGNAL(cellClicked(int, int)), this, SLOT(groupTableClicked(int, int)));
connect(m_uiForm.groupTable->verticalHeader(), SIGNAL(sectionClicked(int)), SLOT(groupTableClicked(int)));
// group table plot button
connect(m_uiForm.groupTablePlotButton, SIGNAL(clicked()), this, SLOT(runGroupTablePlotButton()));
// If pair table change
connect(m_uiForm.pairTable, SIGNAL(cellChanged(int, int)), this, SLOT(pairTableChanged(int, int)));
connect(m_uiForm.pairTable, SIGNAL(cellClicked(int, int)), this, SLOT(pairTableClicked(int, int)));
connect(m_uiForm.pairTable->verticalHeader(), SIGNAL(sectionClicked(int)), SLOT(pairTableClicked(int)));
// Pair table plot button
connect(m_uiForm.pairTablePlotButton, SIGNAL(clicked()), this, SLOT(runPairTablePlotButton()));
// save grouping
connect(m_uiForm.saveGroupButton, SIGNAL(clicked()), this, SLOT(runSaveGroupButton()));
// load grouping
connect(m_uiForm.loadGroupButton, SIGNAL(clicked()), this, SLOT(runLoadGroupButton()));
// clear grouping
connect(m_uiForm.clearGroupingButton, SIGNAL(clicked()), this, SLOT(runClearGroupingButton()));
// front plot button
connect(m_uiForm.frontPlotButton, SIGNAL(clicked()), this, SLOT(runFrontPlotButton()));
// front group/ group pair combobox
connect(m_uiForm.frontGroupGroupPairComboBox, SIGNAL(currentIndexChanged(int)), this,
SLOT(runFrontGroupGroupPairComboBox(int)));
connect(m_uiForm.hideToolbars, SIGNAL(toggled(bool)), this, SLOT(setToolbarsHidden(bool)));
// connect "?" (Help) Button
connect(m_uiForm.muonAnalysisHelp, SIGNAL(clicked()), this, SLOT(muonAnalysisHelpClicked()));
connect(m_uiForm.muonAnalysisHelpGrouping, SIGNAL(clicked()), this, SLOT(muonAnalysisHelpGroupingClicked()));
// add combo boxes to pairTable
for (int i = 0; i < m_uiForm.pairTable->rowCount(); i++)
{
m_uiForm.pairTable->setCellWidget(i,1, new QComboBox);
m_uiForm.pairTable->setCellWidget(i,2, new QComboBox);
}
// file input
connect(m_uiForm.mwRunFiles, SIGNAL(fileFindingFinished()), this, SLOT(inputFileChanged_MWRunFiles()));
// Input check for First Good Data
connect(m_uiForm.firstGoodBinFront, SIGNAL(lostFocus()), this,
SLOT(runFirstGoodBinFront()));
// load previous saved values
loadAutoSavedValues(m_settingsGroup);
// connect the fit function widget buttons to their respective slots.
loadFittings();
// Detect when the tab is changed
connect(m_uiForm.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(changeTab(int)));
connectAutoUpdate();
// Muon scientists never fits peaks, hence they want the following parameter, set to a high number
ConfigService::Instance().setString("curvefitting.peakRadius","99");
connect(m_uiForm.deadTimeType, SIGNAL(currentIndexChanged(int)), this, SLOT(changeDeadTimeType(int) ) );
connect(m_uiForm.mwRunDeadTimeFile, SIGNAL(fileFindingFinished()), this, SLOT(deadTimeFileSelected() ) );
}
/**
* Muon Analysis help (slot)
*/
void MuonAnalysis::muonAnalysisHelpClicked()
{
QDesktopServices::openUrl(QUrl(QString("http://www.mantidproject.org/") +
"MuonAnalysis"));
}
/**
* Muon Analysis Grouping help (slot)
*/
void MuonAnalysis::muonAnalysisHelpGroupingClicked()
{
QDesktopServices::openUrl(QUrl(QString("http://www.mantidproject.org/") +
"MuonAnalysisGrouping"));
}
/**
* Set the connected workspace name.
* @param name The new connected ws name
*/
void MuonAnalysis::setCurrentDataName(const QString& name)
{
m_currentDataName = name;
// Update labels
m_uiForm.connectedDataHome->setText("Connected: " + m_currentDataName);
m_uiForm.connectedDataGrouping->setText("Connected: " + m_currentDataName);
m_uiForm.connectedDataSettings->setText("Connected: " + m_currentDataName);
}
/**
* Front group/ group pair combobox (slot)
*/
void MuonAnalysis::runFrontGroupGroupPairComboBox(int index)
{
if ( index >= 0 )
updateFront();
}
/**
* Check input is valid in input box (slot)
*/
void MuonAnalysis::runFirstGoodBinFront()
{
try
{
boost::lexical_cast<double>(m_uiForm.firstGoodBinFront->text().toStdString());
// if this value updated then also update 'Start at" Plot option if "Start at First Good Data" set
if (m_uiForm.timeComboBox->currentIndex() == 0 )
{
m_uiForm.timeAxisStartAtInput->setText(m_uiForm.firstGoodBinFront->text());
}
}
catch (...)
{
QMessageBox::warning(this,"Mantid - MuonAnalysis", "Number not recognised in First Good Data (ms)' input box. Reset to 0.3.");
m_uiForm.firstGoodBinFront->setText("0.3");
}
}
/**
* Front plot button (slot)
*/
void MuonAnalysis::runFrontPlotButton()
{
if(m_updating)
return;
if (m_deadTimesChanged)
{
inputFileChanged(m_previousFilenames);
return;
}
plotSelectedItem();
}
/**
* Creates a plot of selected group/pair.
*/
void MuonAnalysis::plotSelectedItem()
{
// Get current index
int index = m_uiForm.frontGroupGroupPairComboBox->currentIndex();
if (index < 0)
{
index = 0;
m_uiForm.frontGroupGroupPairComboBox->setCurrentIndex(index);
}
else if (index >= numGroups())
{
// i.e. index points to a pair
m_pairTableRowInFocus = m_pairToRow[index-numGroups()]; // this can be improved
std::string str = m_uiForm.frontPlotFuncs->currentText().toStdString();
plotPair(str);
}
else
{
m_groupTableRowInFocus = m_groupToRow[index];
std::string str = m_uiForm.frontPlotFuncs->currentText().toStdString();
plotGroup(str);
}
}
/**
* If the instrument selection has changed (slot)
*
* @param prefix :: instrument name from QComboBox object
*/
void MuonAnalysis::userSelectInstrument(const QString& prefix)
{
if ( prefix != m_curInterfaceSetup )
{
runClearGroupingButton();
m_curInterfaceSetup = prefix;
// save this new choice
QSettings group;
group.beginGroup(m_settingsGroup + "instrument");
group.setValue("name", prefix);
}
}
/**
* Save grouping button (slot)
*/
void MuonAnalysis::runSaveGroupButton()
{
if ( numGroups() <= 0 )
{
QMessageBox::warning(this, "MantidPlot - MuonAnalysis", "No grouping to save.");
return;
}
QSettings prevValues;
prevValues.beginGroup(m_settingsGroup + "SaveOutput");
// Get value for "dir". If the setting doesn't exist then use
// the the path in "defaultsave.directory"
QString prevPath = prevValues.value("dir", QString::fromStdString(
ConfigService::Instance().getString("defaultsave.directory"))).toString();
QString filter;
filter.append("Files (*.xml *.XML)");
filter += ";;AllFiles (*.*)";
QString groupingFile = MantidQt::API::FileDialogHandler::getSaveFileName(this,
"Save Grouping file as", prevPath, filter);
// Add extension if the groupingFile specified doesn't have one. (Solving Linux problem).
if (!groupingFile.endsWith(".xml"))
groupingFile += ".xml";
if( ! groupingFile.isEmpty() )
{
Grouping groupingToSave;
parseGroupingTable(m_uiForm, groupingToSave);
saveGroupingToXML(groupingToSave, groupingFile.toStdString());
QString directory = QFileInfo(groupingFile).path();
prevValues.setValue("dir", directory);
}
}
/**
* Load grouping button (slot)
*/
void MuonAnalysis::runLoadGroupButton()
{
m_updating = true;
// Get grouping file
QSettings prevValues;
prevValues.beginGroup(m_settingsGroup + "LoadGroupFile");
// Get value for "dir". If the setting doesn't exist then use
// the the path in "defaultsave.directory"
QString prevPath = prevValues.value("dir", QString::fromStdString(
ConfigService::Instance().getString("defaultload.directory"))).toString();
QString filter;
filter.append("Files (*.xml *.XML)");
filter += ";;AllFiles (*.*)";
QString groupingFile = QFileDialog::getOpenFileName(this, "Load Grouping file", prevPath, filter);
if( groupingFile.isEmpty() || QFileInfo(groupingFile).isDir() )
return;
QString directory = QFileInfo(groupingFile).path();
prevValues.setValue("dir", directory);
Grouping loadedGrouping;
try
{
loadGroupingFromXML(groupingFile.toStdString(), loadedGrouping);
}
catch (Exception::FileError& e)
{
g_log.error("Unable to load grouping. Data left unchanged");
g_log.error(e.what());
m_updating = false;
return;
}
clearTablesAndCombo();
fillGroupingTable(loadedGrouping, m_uiForm);
// add number of detectors column to group table
int numRows = m_uiForm.groupTable->rowCount();
for (int i = 0; i < numRows; i++)
{
QTableWidgetItem *item = m_uiForm.groupTable->item(i,1);
if (!item)
break;
if ( item->text().isEmpty() )
break;
std::stringstream detNumRead;
try
{
detNumRead << numOfDetectors(item->text().toStdString());
m_uiForm.groupTable->setItem(i, 2, new QTableWidgetItem(detNumRead.str().c_str()));
}
catch (...)
{
m_uiForm.groupTable->setItem(i, 2, new QTableWidgetItem("Invalid"));
}
}
updateFront();
m_updating = false;
}
/**
* Clear grouping button (slot)
*/
void MuonAnalysis::runClearGroupingButton()
{
clearTablesAndCombo();
}
/**
* Group table plot button (slot)
*/
void MuonAnalysis::runGroupTablePlotButton()
{
if(m_updating)
return;
if (m_deadTimesChanged)
{
inputFileChanged(m_previousFilenames);
return;
}
plotGroup(m_uiForm.groupTablePlotChoice->currentText().toStdString());
}
/**
* Load current (slot)
*/
void MuonAnalysis::runLoadCurrent()
{
QString instname = m_uiForm.instrSelector->currentText().toUpper();
// If Argus data then simple
if ( instname == "ARGUS" )
{
QString argusDAE = "\\\\ndw828\\argusdata\\current cycle\\nexus\\argus0000000.nxs";
Poco::File l_path( argusDAE.toStdString() );
try
{
if ( !l_path.exists() )
{
QMessageBox::warning(this,"Mantid - MuonAnalysis",
QString("Can't load ARGUS Current data since\n") +
argusDAE + QString("\n") +
QString("does not seem to exist"));
return;
}
}
catch(Poco::Exception&)
{
QMessageBox::warning(this, "MantidPlot - MuonAnalysis", "Can't read from the selected directory, either the computer you are trying"
"\nto access is down or your computer is not currently connected to the network.");
return;
}
m_uiForm.mwRunFiles->setUserInput(argusDAE);
m_uiForm.mwRunFiles->setText("CURRENT RUN");
return;
}
if ( instname == "EMU" || instname == "HIFI" || instname == "MUSR")
{
std::string autosavePointsTo = "";
std::string autosaveFile = "\\\\" + instname.toStdString() + "\\data\\autosave.run";
Poco::File pathAutosave( autosaveFile );
try // check if exists
{
if ( pathAutosave.exists() )
{
std::ifstream autofileIn(autosaveFile.c_str(), std::ifstream::in);
autofileIn >> autosavePointsTo;
}
}
catch(Poco::Exception&)
{
QMessageBox::warning(this, "MantidPlot - MuonAnalysis", "Can't read from the selected directory, either the computer you are trying"
"\nto access is down or your computer is not currently connected to the network.");
return;
}
QString psudoDAE;
if ( autosavePointsTo.empty() )
psudoDAE = "\\\\" + instname + "\\data\\" + instname + "auto_A.tmp";
else
psudoDAE = "\\\\" + instname + "\\data\\" + autosavePointsTo.c_str();
Poco::File l_path( psudoDAE.toStdString() );
try
{
if ( !l_path.exists() )
{
QMessageBox::warning(this,"Mantid - MuonAnalysis",
QString("Can't load ") + "Current data since\n" +
psudoDAE + QString("\n") +
QString("does not seem to exist"));
return;
}
}
catch(Poco::Exception&)
{
QMessageBox::warning(this,"Mantid - MuonAnalysis",
QString("Can't load ") + "Current data since\n" +
psudoDAE + QString("\n") +
QString("does not seem to exist"));
return;
}
m_uiForm.mwRunFiles->setUserInput(psudoDAE);
m_uiForm.mwRunFiles->setText("CURRENT RUN");
return;
}
QString daename = "NDX" + instname;
// Load dae file
AnalysisDataService::Instance().remove(m_workspace_name);
// " " + QString(m_workspace_name.c_str()) + "LoadDAE('" + daename + "')\n"
QString pyString =
"import sys\n"
"try:\n"
" " + QString(m_workspace_name.c_str()) + "LoadDAE('" + daename + "')\n"
"except SystemExit, message:\n"
" print str(message)";
QString pyOutput = runPythonCode( pyString ).trimmed();
// if output is none empty something has gone wrong
if ( !pyOutput.toStdString().empty() )
{
m_optionTab->noDataAvailable();
QMessageBox::warning(this, "MantidPlot - MuonAnalysis", "Can't read from " + daename + ". Plotting disabled");
return;
}
m_optionTab->nowDataAvailable();
// Get hold of a pointer to a matrix workspace and apply grouping if applicatable
Workspace_sptr workspace_ptr = AnalysisDataService::Instance().retrieve(m_workspace_name);
WorkspaceGroup_sptr wsPeriods = boost::dynamic_pointer_cast<WorkspaceGroup>(workspace_ptr);
MatrixWorkspace_sptr matrix_workspace;
int numPeriods = 1; // 1 may mean either a group with one period or simply just 1 normal matrix workspace
if (wsPeriods)
{
numPeriods = wsPeriods->getNumberOfEntries();
Workspace_sptr workspace_ptr1 = AnalysisDataService::Instance().retrieve(m_workspace_name + "_1");
matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(workspace_ptr1);
}
else
{
matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(workspace_ptr);
}
if ( !isGroupingSet() )
{
std::stringstream idstr;
idstr << "1-" << matrix_workspace->getNumberHistograms();
m_uiForm.groupTable->setItem(0, 0, new QTableWidgetItem("NoGroupingDetected"));
m_uiForm.groupTable->setItem(0, 1, new QTableWidgetItem(idstr.str().c_str()));
updateFrontAndCombo();
}
if ( !applyGroupingToWS(m_workspace_name, m_workspace_name+"Grouped") )
return;
// Populate instrument fields
std::stringstream str;
str << "Description: ";
int nDet = static_cast<int>(matrix_workspace->getInstrument()->getDetectorIDs().size());
str << nDet;
str << " detector spectrometer, main field ";
str << "unknown";
str << " to muon polarisation";
m_uiForm.instrumentDescription->setText(str.str().c_str());
// Populate run information text field
std::string infoStr = "Number of spectra in data = ";
infoStr += boost::lexical_cast<std::string>(matrix_workspace->getNumberHistograms()) + "\n";
infoStr += "Title: ";
infoStr += matrix_workspace->getTitle() + "\n" + "Comment: "
+ matrix_workspace->getComment();
m_uiForm.infoBrowser->setText(infoStr.c_str());
// If number of periods has changed -> update period widgets
if(numPeriods != m_uiForm.homePeriodBox1->count())
updatePeriodWidgets(numPeriods);
}
/**
* Pair table plot button (slot)
*/
void MuonAnalysis::runPairTablePlotButton()
{
if(m_updating)
return;
if (m_deadTimesChanged)
{
inputFileChanged(m_previousFilenames);
return;
}
m_uiForm.frontPlotFuncs->setCurrentIndex(m_uiForm.pairTablePlotChoice->currentIndex());
// if something sensible in row then update front
int currentSelection(m_uiForm.pairTable->currentRow());
if (currentSelection >= 0)
{
int index (numGroups() + currentSelection);
if (m_uiForm.frontGroupGroupPairComboBox->count() >= index)
{
m_uiForm.frontGroupGroupPairComboBox->setCurrentIndex(index);
plotPair(m_uiForm.pairTablePlotChoice->currentText().toStdString());
}
}
else
{
m_uiForm.frontGroupGroupPairComboBox->setCurrentIndex(numGroups()); //if two groups then index 2 will be pair group
plotPair(m_uiForm.pairTablePlotChoice->currentText().toStdString());
}
}
/**
* Pair table vertical lable clicked (slot)
*/
void MuonAnalysis::pairTableClicked(int row)
{
m_pairTableRowInFocus = row;
// if something sensible in row then update front
int pNum = getPairNumberFromRow(row);
if ( pNum >= 0 )
{
m_uiForm.frontGroupGroupPairComboBox->setCurrentIndex(pNum+numGroups());
updateFront();
}
}
/**
* Pair table clicked (slot)
*/
void MuonAnalysis::pairTableClicked(int row, int column)
{
(void) column;
pairTableClicked(row);
}
/**
* Group table clicked (slot)
*/
void MuonAnalysis::groupTableClicked(int row, int column)
{
(void) column;
groupTableClicked(row);
}
/**
* Group table clicked (slot)
*/
void MuonAnalysis::groupTableClicked(int row)
{
m_groupTableRowInFocus = row;
// if something sensible in row then update front
int gNum = getGroupNumberFromRow(row);
if ( gNum >= 0 )
{
m_uiForm.frontGroupGroupPairComboBox->setCurrentIndex(gNum);
updateFront();
m_uiForm.frontPlotFuncs->setCurrentIndex(m_uiForm.groupTablePlotChoice->currentIndex());
}
}
/**
* Group table changed, e.g. if: (slot)
*
* 1) user changed detector sequence
* 2) user type in a group name
*
* @param row :: row number
* @param column :: column number
*/
void MuonAnalysis::groupTableChanged(int row, int column)
{
// changes to the IDs
if ( column == 1 )
{
QTableWidgetItem* itemNdet = m_uiForm.groupTable->item(row,2);
QTableWidgetItem *item = m_uiForm.groupTable->item(row,1);
// if IDs list has been changed to empty string
if (item->text() == "")
{
if (itemNdet)
itemNdet->setText("");
}
else
{
int numDet = numOfDetectors(item->text().toStdString());
std::stringstream detNumRead;
if (numDet > 0 )
{
detNumRead << numDet;
if (itemNdet == NULL)
m_uiForm.groupTable->setItem(row,2, new QTableWidgetItem(detNumRead.str().c_str()));
else
{
itemNdet->setText(detNumRead.str().c_str());
}
}
else
{
if (itemNdet == NULL)
m_uiForm.groupTable->setItem(row,2, new QTableWidgetItem("Invalid IDs string"));
else
m_uiForm.groupTable->item(row, 2)->setText("Invalid IDs string");
}
}
}
// Change to group name
if ( column == 0 )
{
QTableWidgetItem *itemName = m_uiForm.groupTable->item(row,0);
if ( itemName == NULL ) // this should never happen
m_uiForm.groupTable->setItem(row,0, new QTableWidgetItem(""));
if ( itemName->text() != "" )
{
// check that the group name entered does not already exist
for (int i = 0; i < m_uiForm.groupTable->rowCount(); i++)
{
if (i==row)
continue;
QTableWidgetItem *item = m_uiForm.groupTable->item(i,0);
if (item)
{
if ( item->text() == itemName->text() )
{
QMessageBox::warning(this, "MantidPlot - MuonAnalysis", "Group names must be unique. Please re-enter Group name.");
itemName->setText("");
break;
}
}
}
}
}
whichGroupToWhichRow(m_uiForm, m_groupToRow);
applyGroupingToWS(m_workspace_name, m_workspace_name+"Grouped");
updatePairTable();
updateFrontAndCombo();
}
/**
* Pair table changed, e.g. if: (slot)
*
* 1) user changed alpha value
* 2) pair name changed
*
* @param row :: row number
* @param column:: column number
*/
void MuonAnalysis::pairTableChanged(int row, int column)
{
// alpha been modified
if ( column == 3 )
{
QTableWidgetItem* itemAlpha = m_uiForm.pairTable->item(row,3);
if ( !itemAlpha->text().toStdString().empty() )
{
try
{
boost::lexical_cast<double>(itemAlpha->text().toStdString().c_str());
} catch (boost::bad_lexical_cast&)
{
QMessageBox::warning(this, "MantidPlot - MuonAnalysis", "Alpha must be a number.");
itemAlpha->setText("");
return;
}
}
whichPairToWhichRow(m_uiForm, m_pairToRow);
updateFrontAndCombo();
}
// pair name been modified
if ( column == 0 )
{
QTableWidgetItem *itemName = m_uiForm.pairTable->item(row,0);
if ( itemName == NULL ) // this should never happen
m_uiForm.pairTable->setItem(row,0, new QTableWidgetItem(""));
if ( itemName->text() != "" )
{
// check that the group name entered does not already exist
for (int i = 0; i < m_uiForm.pairTable->rowCount(); i++)
{
if (i==row)
continue;
QTableWidgetItem *item = m_uiForm.pairTable->item(i,0);
if (item)
{
if ( item->text() == itemName->text() )
{
QMessageBox::warning(this, "MantidPlot - MuonAnalysis", "Pair names must be unique. Please re-enter Pair name.");
itemName->setText("");
}
}
}
}
whichPairToWhichRow(m_uiForm, m_pairToRow);
updateFrontAndCombo();
// check to see if alpha is specified (if name!="") and if not
// assign a default of 1.0
if ( itemName->text() != "" )
{
QTableWidgetItem* itemAlpha = m_uiForm.pairTable->item(row,3);
if (itemAlpha)
{
if ( itemAlpha->text().toStdString().empty() )
{
itemAlpha->setText("1.0");
}
}
else
{
m_uiForm.pairTable->setItem(row,3, new QTableWidgetItem("1.0"));
}
}
}
}
/**
* Update pair table
*/
void MuonAnalysis::updatePairTable()
{
// number of groups has dropped below 2 and pair names specified then
// clear pair table
if ( numGroups() < 2 && numPairs() > 0 )
{
m_uiForm.pairTable->clearContents();
for (int i = 0; i < m_uiForm.pairTable->rowCount(); i++)
{
m_uiForm.pairTable->setCellWidget(i,1, new QComboBox);
m_uiForm.pairTable->setCellWidget(i,2, new QComboBox);
}
updateFrontAndCombo();
return;
}
else if ( numGroups() < 2 && numPairs() <= 0 )
{
return;
}
// get previous number of groups as listed in the pair comboboxes
QComboBox* qwF = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(0,1));
int previousNumGroups = qwF->count(); // how many groups listed in pair combobox
int newNumGroups = numGroups();
// reset context of combo boxes
for (int i = 0; i < m_uiForm.pairTable->rowCount(); i++)
{
QComboBox* qwF = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(i,1));
QComboBox* qwB = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(i,2));
if (previousNumGroups < newNumGroups)
{
// then need to increase the number of entrees in combo box
for (int ii = 1; ii <= newNumGroups-previousNumGroups; ii++)
{
qwF->addItem(""); // effectively here just allocate space for extra items
qwB->addItem("");
}
}
else if (previousNumGroups > newNumGroups)
{
// then need to decrease the number of entrees in combo box
for (int ii = 1; ii <= previousNumGroups-newNumGroups; ii++)
{
qwF->removeItem(qwF->count()-1); // remove top items
qwB->removeItem(qwB->count()-1);
}
// further for this case check that none of the current combo box
// indexes are larger than the number of groups
if ( qwF->currentIndex()+1 > newNumGroups || qwB->currentIndex()+1 > newNumGroups )
{
qwF->setCurrentIndex(0);
qwB->setCurrentIndex(1);
}
}
if ( qwF->currentIndex() == 0 && qwB->currentIndex() == 0 )
qwB->setCurrentIndex(1);
// re-populate names in combo boxes with group names
for (int ii = 0; ii < newNumGroups; ii++)
{
qwF->setItemText(ii, m_uiForm.groupTable->item(m_groupToRow[ii],0)->text());
qwB->setItemText(ii, m_uiForm.groupTable->item(m_groupToRow[ii],0)->text());
}
}
}
/**
* Slot called when the input file is changed.
*/
void MuonAnalysis::inputFileChanged_MWRunFiles()
{
// Handle changed input, then turn buttons back on.
handleInputFileChanges();
allowLoading(true);
}
/**
* Do some check when reading from MWRun, before actually reading new data file, to see if file is valid
*/
void MuonAnalysis::handleInputFileChanges()
{
if ( m_uiForm.mwRunFiles->getText().isEmpty() )
return;
if ( !m_uiForm.mwRunFiles->isValid() )
{
QMessageBox::warning(this,"Mantid - MuonAnalysis", m_uiForm.mwRunFiles->getFileProblem() );
if (m_textToDisplay == "")
m_uiForm.mwRunFiles->setFileProblem("Error. No File specified.");
else
m_uiForm.mwRunFiles->setFileProblem("Error finding file. Reset to last working data.");
m_uiForm.mwRunFiles->setText(m_textToDisplay);
return;
}
if (!m_updating)
{
QStringList runFiles = m_uiForm.mwRunFiles->getFilenames();
m_previousFilenames.clear();
m_previousFilenames = runFiles;
m_textToDisplay = m_uiForm.mwRunFiles->getText();
// save selected browse file directory to be reused next time interface is started up
m_uiForm.mwRunFiles->saveSettings(m_settingsGroup + "mwRunFilesBrowse");
inputFileChanged(m_previousFilenames);
}
}
/**
* Input file changed. Update GUI accordingly. Note this method does no check of input filename assumed
* done elsewhere depending on e.g. whether filename came from MWRunFiles or 'get current run' button.
*
* @param files :: All file names for the files loading.
*/
void MuonAnalysis::inputFileChanged(const QStringList& files)
{
if (files.size() <= 0)
return;
m_updating = true;
m_uiForm.tabWidget->setTabEnabled(3, false);
try
{
// Whether the instrument in the file is different from the one used
bool instrumentChanged = false;
std::string mainFieldDirection("");
double timeZero(0.0);
double firstGoodData(0.0);
std::vector<double> deadTimes;
for (int i=0; i<files.size(); ++i)
{
QString filename = files[i];
Poco::File l_path( filename.toStdString() );
// and check if file is from a recognised instrument and update instrument combo box
QString filenamePart = (Poco::Path(l_path.path()).getFileName()).c_str();
filenamePart = filenamePart.toLower();
bool foundInst = false;
for (int j=0; j < m_uiForm.instrSelector->count(); j++)
{
QString instName = m_uiForm.instrSelector->itemText(j).toLower();
std::string sfilename = filenamePart.toStdString();
std::string sinstName = instName.toStdString();
size_t found;
found = sfilename.find(sinstName);
if ( found != std::string::npos )
{
foundInst = true;
// If currently used instrument has changed
if(j != m_uiForm.instrSelector->currentIndex())
{
m_uiForm.instrSelector->setCurrentIndex(j);
instrumentChanged = true;
}
break;
}
}
if ( !foundInst )
throw std::runtime_error("Muon file " + filename.toStdString() + " not recognised.");
// Setup Load Nexus Algorithm
Mantid::API::IAlgorithm_sptr loadMuonAlg = Mantid::API::AlgorithmManager::Instance().create("LoadMuonNexus");
loadMuonAlg->setPropertyValue("Filename", filename.toStdString() );
if (i > 0)
{
QString tempRangeNum;
tempRangeNum.setNum(i);
loadMuonAlg->setPropertyValue("OutputWorkspace", m_workspace_name + tempRangeNum.toStdString() );
}
else
{
loadMuonAlg->setPropertyValue("OutputWorkspace", m_workspace_name);
}
loadMuonAlg->setProperty("AutoGroup", false);
if (loadMuonAlg->execute() )
{
timeZero = loadMuonAlg->getProperty("TimeZero");
firstGoodData = loadMuonAlg->getProperty("FirstGoodData");
if (m_uiForm.instrSelector->currentText().toUpper() == "ARGUS")
{
// ARGUS doesn't support dead time correction, so leave deadTimes empty.
// Some of the ARGUS data files contain wrong information about the instrument main field
// direction. It is alway longitudinal.
mainFieldDirection = "longitudinal";
}
else
{
mainFieldDirection = loadMuonAlg->getPropertyValue("MainFieldDirection");
deadTimes = loadMuonAlg->getProperty("DeadTimes");
}
}
else
{
throw std::runtime_error("Problem when executing LoadMuonNexus algorithm.");
}
}
if (m_previousFilenames.size() > 1)
plusRangeWorkspaces();
try // ... to apply dead time correction
{
// ARGUS does not support dead time corr.
if (m_uiForm.instrSelector->currentText().toUpper() == "ARGUS" && m_uiForm.deadTimeType->currentIndex() != 0)
throw std::runtime_error("Dead times are currently not implemented in ARGUS files.");
// Get dead times from data.
if (m_uiForm.deadTimeType->currentIndex() == 1)
{
getDeadTimeFromData(deadTimes);
}
// Get dead times from file.
else if (m_uiForm.deadTimeType->currentIndex() == 2)
{
if(!m_uiForm.mwRunDeadTimeFile->isValid())
throw std::runtime_error("Specified Dead Time file is not valid.");
QString deadTimeFile(m_uiForm.mwRunDeadTimeFile->getFirstFilename() );
getDeadTimeFromFile(deadTimeFile);
}
}
// TODO: Shouldn't catch these exception. Done like this to minimize the impact of #8020.
catch(std::exception& e)
{
QString errorMsg(e.what());
errorMsg += "\n\nNo Dead Time correction applied.";
QMessageBox::warning(this, "Mantid - MuonAnalysis", errorMsg);
}
// Make the options available
m_optionTab->nowDataAvailable();
// Get hold of a pointer to a matrix workspace and apply grouping if applicatable
Workspace_sptr workspace_ptr = AnalysisDataService::Instance().retrieve(m_workspace_name);
WorkspaceGroup_sptr wsPeriods = boost::dynamic_pointer_cast<WorkspaceGroup>(workspace_ptr);
MatrixWorkspace_sptr matrix_workspace;
int numPeriods = 1; // 1 may mean either a group with one period or simply just 1 normal matrix workspace
if (wsPeriods)
{
numPeriods = wsPeriods->getNumberOfEntries();
Workspace_sptr workspace_ptr1 = AnalysisDataService::Instance().retrieve(m_workspace_name + "_1");
matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(workspace_ptr1);
}
else
{
matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(workspace_ptr);
}
// if grouping not set, first see if grouping defined in Nexus
if ( !isGroupingSet() )
setGroupingFromNexus(files[0]);
// if grouping still not set, then take grouping from IDF
if ( !isGroupingSet() )
setGroupingFromIDF(mainFieldDirection, matrix_workspace);
// finally if nothing else works set dummy grouping and display
// message to user
if ( !isGroupingSet() )
setDummyGrouping(static_cast<int>(matrix_workspace->getInstrument()->getDetectorIDs().size()));
if ( !applyGroupingToWS(m_workspace_name, m_workspace_name+"Grouped") )
throw std::runtime_error("Couldn't apply grouping");
// Populate instrument fields
std::stringstream str;
str << "Description: ";
int nDet = static_cast<int>(matrix_workspace->getInstrument()->getDetectorIDs().size());
str << nDet;
str << " detector spectrometer, main field ";
str << QString(mainFieldDirection.c_str()).toLower().toStdString();
str << " to muon polarisation";
m_uiForm.instrumentDescription->setText(str.str().c_str());
m_uiForm.timeZeroFront->setText(QString::number(timeZero, 'g',2));
// I want the nexus time to equal exactly how it is stored in time zero text box
// so that later I can check if user has altered it
m_nexusTimeZero = boost::lexical_cast<double>(m_uiForm.timeZeroFront->text().toStdString());
m_uiForm.firstGoodBinFront->setText(QString::number(firstGoodData-timeZero,'g',2));
// since content of first-good-bin changed run this slot
runFirstGoodBinFront();
std::string infoStr("");
// Populate run information with the run number
QString run(getGroupName());
if (m_previousFilenames.size() > 1)
infoStr += "Runs: ";
else
infoStr += "Run: ";
// Remove instrument and leading zeros
int zeroCount(0);
for (int i=0; i<run.size(); ++i)
{
if ( (run[i] == '0') || (run[i].isLetter() ) )
++zeroCount;
else
{
run = run.right(run.size() - zeroCount);
break;
}
}
// Add to run information.
infoStr += run.toStdString();
// Populate run information text field
m_title = matrix_workspace->getTitle();
infoStr += "\nTitle: ";
infoStr += m_title;
// Add the comment to run information
infoStr += "\nComment: ";
infoStr += matrix_workspace->getComment();
const Run& runDetails = matrix_workspace->run();
Mantid::Kernel::DateAndTime start, end;
// Add the start time for the run
infoStr += "\nStart: ";
if ( runDetails.hasProperty("run_start") )
{
start = runDetails.getProperty("run_start")->value();
infoStr += runDetails.getProperty("run_start")->value();
}
// Add the end time for the run
infoStr += "\nEnd: ";
if ( runDetails.hasProperty("run_end") )
{
end = runDetails.getProperty("run_end")->value();
infoStr += runDetails.getProperty("run_end")->value();
}
// Add counts to run information
infoStr += "\nCounts: ";
double counts(0.0);
for (size_t i=0; i<matrix_workspace->getNumberHistograms(); ++i)
{
for (size_t j=0; j<matrix_workspace->blocksize(); ++j)
{
counts += matrix_workspace->dataY(i)[j];
}
}
std::ostringstream ss;
ss << std::fixed << std::setprecision(12) << counts/1000000;
infoStr += ss.str();
infoStr += " MEv";
// Add average temperature.
infoStr += "\nAverage Temperature: ";
if ( runDetails.hasProperty("Temp_Sample") )
{
// Filter the temperatures by the start and end times for the run.
runDetails.getProperty("Temp_Sample")->filterByTime(start, end);
QString allRuns = QString::fromStdString(runDetails.getProperty("Temp_Sample")->value() );
QStringList runTemp = allRuns.split("\n");
int tempCount(0);
double total(0.0);
// Go through each temperature entry, remove the date and time, and total the temperatures.
for (int i=0; i<runTemp.size(); ++i)
{
if (runTemp[i].contains(" ") )
{
QStringList dateTimeTemperature = runTemp[i].split(" ");
total += dateTimeTemperature[dateTimeTemperature.size() - 1].toDouble();
++tempCount;
}
}
// Find the average and display it.
double average(total/tempCount);
if (average != 0.0)
{
std::ostringstream ss;
ss << std::fixed << std::setprecision(12) << average;
infoStr += ss.str();
}
else // Show appropriate error message.
infoStr += "Errror - Not set in data file.";
}
else // Show appropriate error message.
infoStr += "Errror - Not found in data file.";
// Include all the run information.
m_uiForm.infoBrowser->setText(infoStr.c_str());
// If instrument or number of periods has changed -> update period widgets
if(instrumentChanged || numPeriods != m_uiForm.homePeriodBox1->count())
updatePeriodWidgets(numPeriods);
// Populate bin width info in Plot options
double binWidth = matrix_workspace->dataX(0)[1]-matrix_workspace->dataX(0)[0];
static const QChar MU_SYM(956);
m_uiForm.optionLabelBinWidth->setText(QString("Data collected with histogram bins of ") + QString::number(binWidth) + QString(" %1s").arg(MU_SYM));
if(m_uiForm.frontPlotButton->isEnabled())
plotSelectedItem();
}
catch(std::exception& e)
{
deleteRangedWorkspaces();
QMessageBox::warning(this,"Mantid - MuonAnalysis", e.what());
}
m_uiForm.tabWidget->setTabEnabled(3, true);
m_updating = false;
m_deadTimesChanged = false;
}
/**
* Uses the algorithm plus to add all the workspaces from a range.
*/
void MuonAnalysis::plusRangeWorkspaces()
{
// Start at 1 because 0 is MuonAnalysis without a number
for (int i=1; i<m_previousFilenames.size(); ++i)
{
QString tempNum;
tempNum.setNum(i);
Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("Plus");
alg->setPropertyValue("LHSWorkspace", m_workspace_name);
alg->setPropertyValue("RHSWorkspace", m_workspace_name + tempNum.toStdString());
alg->setPropertyValue("OutputWorkspace", m_workspace_name);
if (!alg->execute())
throw std::runtime_error("Error in adding range together.");
}
deleteRangedWorkspaces();
}
/**
* Delete ranged workspaces.
*/
void MuonAnalysis::deleteRangedWorkspaces()
{
// Start at 1 because 0 is MuonAnalysis without a number
for (int i=1; i<m_previousFilenames.size(); ++i)
{
QString tempNum;
tempNum.setNum(i);
if (Mantid::API::AnalysisDataService::Instance().doesExist(m_workspace_name + tempNum.toStdString() ) )
Mantid::API::AnalysisDataService::Instance().remove(m_workspace_name + tempNum.toStdString() );
if (Mantid::API::AnalysisDataService::Instance().doesExist(m_workspace_name + tempNum.toStdString() + "_1") )
Mantid::API::AnalysisDataService::Instance().remove(m_workspace_name + tempNum.toStdString() + "_1");
if (Mantid::API::AnalysisDataService::Instance().doesExist(m_workspace_name + tempNum.toStdString() + "_2") )
Mantid::API::AnalysisDataService::Instance().remove(m_workspace_name + tempNum.toStdString() + "_2");
}
}
/**
* Create a table of dead times and apply them to the data.
*
* @param deadTimes :: a vector of all the dead times starting at spectrum 1.
*/
void MuonAnalysis::getDeadTimeFromData(const std::vector<double> & deadTimes)
{
int numData(0); // Number of data sets under muon analysis.
if (Mantid::API::AnalysisDataService::Instance().doesExist(m_workspace_name) )
{
++numData;
int loop(1);
while(loop == numData)
{
std::stringstream ss; //create a stringstream
ss << (numData + 1);
if (Mantid::API::AnalysisDataService::Instance().doesExist(m_workspace_name + '_' + ss.str() ) )
{
++numData;
}
++loop;
}
}
// Setup the dead time table.
for (int i=1; i<=numData; ++i)
{
std::string workspaceName("");
Mantid::API::ITableWorkspace_sptr deadTimeTable = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace");
deadTimeTable->addColumn("int","spectrum");
deadTimeTable->addColumn("double","dead-time");
Mantid::API::MatrixWorkspace_sptr muonData;
if (i==1 && 1==numData)
{
workspaceName = m_workspace_name;
muonData = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName) );
}
else
{
std::stringstream ss; //create a stringstream
ss << i;
workspaceName = m_workspace_name + '_' + ss.str();
muonData = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName) );
}
//check dead time size
if (deadTimes.size() >= (muonData->getNumberHistograms() + (i-1)*muonData->getNumberHistograms() ) )
{
for (size_t j=0; j<muonData->getNumberHistograms(); ++j)
{
Mantid::API::TableRow row = deadTimeTable->appendRow();
row << boost::lexical_cast<int>(j+1) << deadTimes[j+((i-1)*muonData->getNumberHistograms() ) ];
}
}
// Add to the ADS for use with algorithm. (Unique name chosen so not to cause conflict)
Mantid::API::AnalysisDataService::Instance().addOrReplace("tempMuonDeadTime123qwe", deadTimeTable);
// Setup and run the ApplyDeadTimeCorr algorithm.
Mantid::API::IAlgorithm_sptr applyDeadTimeAlg = Mantid::API::AlgorithmManager::Instance().create("ApplyDeadTimeCorr");
applyDeadTimeAlg->setPropertyValue("InputWorkspace", workspaceName );
applyDeadTimeAlg->setProperty("DeadTimeTable", deadTimeTable);
applyDeadTimeAlg->setPropertyValue("OutputWorkspace", workspaceName );
if (!applyDeadTimeAlg->execute())
throw std::runtime_error("Error in applying dead time.");
// Make sure to remove the table from the ADS because it isn't used anymore.
Mantid::API::AnalysisDataService::Instance().remove("tempMuonDeadTime123qwe");
}
}
/**
* Load up a dead time table or a group of dead time tables and apply them to the workspace.
*
* @param fileName :: The file where the dead times are kept.
*/
void MuonAnalysis::getDeadTimeFromFile(const QString & fileName)
{
Mantid::API::IAlgorithm_sptr loadDeadTimes = Mantid::API::AlgorithmManager::Instance().create("LoadNexusProcessed");
loadDeadTimes->setPropertyValue("Filename", fileName.toStdString() );
loadDeadTimes->setPropertyValue("OutputWorkspace", "tempMuonDeadTime123qwe");
if (loadDeadTimes->execute() )
{
Mantid::API::ITableWorkspace_sptr deadTimeTable = boost::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve("tempMuonDeadTime123qwe") );
if (deadTimeTable)
{
// Must be deadtime
Mantid::API::IAlgorithm_sptr applyDeadTimeAlg = Mantid::API::AlgorithmManager::Instance().create("ApplyDeadTimeCorr");
applyDeadTimeAlg->setPropertyValue("InputWorkspace", m_workspace_name );
applyDeadTimeAlg->setProperty("DeadTimeTable", deadTimeTable);
applyDeadTimeAlg->setPropertyValue("OutputWorkspace", m_workspace_name );
if (!applyDeadTimeAlg->execute())
throw std::runtime_error("Error in applying dead time.");
Mantid::API::AnalysisDataService::Instance().remove("tempMuonDeadTime123qwe");
}
else
{
// Check to see if it is a group of dead time tables
Mantid::API::WorkspaceGroup_sptr deadTimeTables = boost::dynamic_pointer_cast<Mantid::API::WorkspaceGroup>(Mantid::API::AnalysisDataService::Instance().retrieve("tempMuonDeadTime123qwe") );
if (deadTimeTables)
{
std::vector<std::string> groupNames(deadTimeTables->getNames() );
size_t numData(0); // Number of data sets under muon analysis.
if (Mantid::API::AnalysisDataService::Instance().doesExist(m_workspace_name) )
{
++numData;
size_t loop(1);
while(loop == numData)
{
std::stringstream ss; //create a stringstream
ss << (numData + 1);
if (Mantid::API::AnalysisDataService::Instance().doesExist(m_workspace_name + '_' + ss.str() ) )
{
++numData;
}
++loop;
}
}
if (numData == groupNames.size() )
{
bool allTables(true);
for (size_t i=0; i<groupNames.size(); ++i)
{
deadTimeTable = boost::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve(groupNames[i] ) );
if (!deadTimeTable)
allTables = false;
}
if (allTables == true)
{
for (size_t i=0; i<groupNames.size(); ++i)
{
std::string workspaceName("");
Mantid::API::MatrixWorkspace_sptr muonData;
if (i==0 && 1==numData)
{
workspaceName = m_workspace_name;
}
else
{
std::stringstream ss; //create a stringstream
ss << (i+1);
workspaceName = m_workspace_name + '_' + ss.str();
}
deadTimeTable = boost::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve(groupNames[i] ) );
Mantid::API::IAlgorithm_sptr applyDeadTimeAlg = Mantid::API::AlgorithmManager::Instance().create("ApplyDeadTimeCorr");
applyDeadTimeAlg->setPropertyValue("InputWorkspace", workspaceName );
applyDeadTimeAlg->setProperty("DeadTimeTable", deadTimeTable);
applyDeadTimeAlg->setPropertyValue("OutputWorkspace", workspaceName );
if (!applyDeadTimeAlg->execute())
throw std::runtime_error("Error in applying dead time.");
}
}
}
}
else
{
Mantid::API::AnalysisDataService::Instance().remove("tempMuonDeadTime123qwe");
throw std::runtime_error("This kind of workspace is not compatible with applying dead times");
}
Mantid::API::AnalysisDataService::Instance().remove("tempMuonDeadTime123qwe");
}
}
else
{
Mantid::API::AnalysisDataService::Instance().remove("tempMuonDeadTime123qwe");
throw std::runtime_error("Failed to load dead times from the file " + fileName.toStdString());
}
}
/**
* Get the group name for the workspace.
*
* @return wsGroupName :: The name of the group workspace.
*/
QString MuonAnalysis::getGroupName()
{
std::string workspaceGroupName("");
// Decide on name for workspaceGroup
if (m_previousFilenames.size() == 1)
{
Poco::File l_path( m_previousFilenames[0].toStdString() );
workspaceGroupName = Poco::Path(l_path.path()).getFileName();
changeCurrentRun(workspaceGroupName);
}
else
{
workspaceGroupName = getRangedName();
}
std::size_t extPos = workspaceGroupName.find(".");
if ( extPos!=std::string::npos)
workspaceGroupName = workspaceGroupName.substr(0,extPos);
QString wsGroupName(workspaceGroupName.c_str());
wsGroupName = wsGroupName.toUpper();
return wsGroupName;
}
/**
* Get ranged name.
*
* @return rangedName :: The name to be used to identify the workspace.
*/
std::string MuonAnalysis::getRangedName()
{
QString filePath("");
QString firstFile(m_previousFilenames[0]);
QString lastFile(m_previousFilenames[m_previousFilenames.size()-1]);
QString firstRun("");
QString lastRun("");
int runSize(-1);
separateMuonFile(filePath, firstFile, firstRun, runSize);
separateMuonFile(filePath, lastFile, lastRun, runSize);
for (int i=0; i<lastRun.size(); ++i)
{
if (firstRun[i] != lastRun[i])
{
lastRun = lastRun.right(lastRun.size() - i);
break;
}
}
if (firstFile.contains('.') )
firstFile.chop(firstFile.size()-firstFile.find('.') );
return (firstFile.toStdString() + '-' + lastRun.toStdString());
}
/**
* Guess Alpha (slot). For now include all data from first good data(bin)
*/
void MuonAnalysis::guessAlphaClicked()
{
m_updating = true;
if ( getPairNumberFromRow(m_pairTableRowInFocus) >= 0 )
{
QComboBox* qwF = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(m_pairTableRowInFocus,1));
QComboBox* qwB = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(m_pairTableRowInFocus,2));
if (!qwF || !qwB)
return;
// group IDs
QTableWidgetItem *idsF = m_uiForm.groupTable->item(m_groupToRow[qwF->currentIndex()],1);
QTableWidgetItem *idsB = m_uiForm.groupTable->item(m_groupToRow[qwB->currentIndex()],1);
if (!idsF || !idsB)
return;
QString inputWS = m_workspace_name.c_str();
if ( m_uiForm.homePeriodBox2->isEnabled() )
inputWS += "_" + m_uiForm.homePeriodBox1->currentText();
Mantid::API::IAlgorithm_sptr alphaAlg = Mantid::API::AlgorithmManager::Instance().create("AlphaCalc");
alphaAlg->setPropertyValue("InputWorkspace", inputWS.toStdString());
alphaAlg->setPropertyValue("ForwardSpectra", idsF->text().toStdString());
alphaAlg->setPropertyValue("BackwardSpectra", idsB->text().toStdString());
alphaAlg->setPropertyValue("FirstGoodValue", firstGoodBin().toStdString());
alphaAlg->execute();
const QString alpha(alphaAlg->getPropertyValue("Alpha").c_str());
QComboBox* qwAlpha = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(m_pairTableRowInFocus,3));
if (qwAlpha)
m_uiForm.pairTable->item(m_pairTableRowInFocus,3)->setText(alpha);
else
m_uiForm.pairTable->setItem(m_pairTableRowInFocus,3, new QTableWidgetItem(alpha));
}
m_updating = false;
// See if auto-update is on and if so update the plot
groupTabUpdatePair();
}
/**
* Return number of groups defined (not including pairs)
*
* @return number of groups
*/
int MuonAnalysis::numGroups()
{
whichGroupToWhichRow(m_uiForm, m_groupToRow);
return static_cast<int>(m_groupToRow.size());
}
/**
* Return number of pairs
*
* @return number of pairs
*/
int MuonAnalysis::numPairs()
{
whichPairToWhichRow(m_uiForm, m_pairToRow);
return static_cast<int>(m_pairToRow.size());
}
/**
* Update front "group / group-pair" combo-box based on what the currentIndex now is
*/
void MuonAnalysis::updateFront()
{
// get current index
int index = m_uiForm.frontGroupGroupPairComboBox->currentIndex();
m_uiForm.frontPlotFuncs->clear();
int numG = numGroups();
if (numG)
{
if (index >= numG && numG >= 2)
{
// i.e. index points to a pair
m_uiForm.frontPlotFuncs->addItems(m_pairPlotFunc);
m_uiForm.frontAlphaLabel->setVisible(true);
m_uiForm.frontAlphaNumber->setVisible(true);
m_uiForm.frontAlphaNumber->setText(m_uiForm.pairTable->item(m_pairToRow[index-numG],3)->text());
m_uiForm.frontAlphaNumber->setCursorPosition(0);
}
else
{
// i.e. index points to a group
m_uiForm.frontPlotFuncs->addItems(m_groupPlotFunc);
m_uiForm.frontAlphaLabel->setVisible(false);
m_uiForm.frontAlphaNumber->setVisible(false);
}
}
}
/**
* Update front including first re-populate pair list combo box
*/
void MuonAnalysis::updateFrontAndCombo()
{
// for now brute force clearing and adding new context
// could go for softer approach and check if is necessary
// to complete reset this combo box
int currentI = m_uiForm.frontGroupGroupPairComboBox->currentIndex();
if (currentI < 0) // in case this combobox has not been set yet
currentI = 0;
m_uiForm.frontGroupGroupPairComboBox->clear();
int numG = numGroups();
int numP = numPairs();
for (int i = 0; i < numG; i++)
m_uiForm.frontGroupGroupPairComboBox->addItem(
m_uiForm.groupTable->item(m_groupToRow[i],0)->text());
for (int i = 0; i < numP; i++)
m_uiForm.frontGroupGroupPairComboBox->addItem(
m_uiForm.pairTable->item(m_pairToRow[i],0)->text());
if ( currentI >= m_uiForm.frontGroupGroupPairComboBox->count() )
m_uiForm.frontGroupGroupPairComboBox->setCurrentIndex(0);
else
m_uiForm.frontGroupGroupPairComboBox->setCurrentIndex(currentI);
updateFront();
}
/**
* Updates widgets related to period algebra
* @param newNumPeriods Number of periods available
*/
void MuonAnalysis::updatePeriodWidgets(int numPeriods)
{
QString periodLabel = "Data collected in " + QString::number(numPeriods)
+ " periods. Plot/analyse period: ";
m_uiForm.homePeriodsLabel->setText(periodLabel);
// Remove all the previous items
m_uiForm.homePeriodBox1->clear();
m_uiForm.homePeriodBox2->clear();
m_uiForm.homePeriodBox2->addItem("None");
for ( int i = 1; i <= numPeriods; i++ )
{
m_uiForm.homePeriodBox1->addItem(QString::number(i));
m_uiForm.homePeriodBox2->addItem(QString::number(i));
}
// We only need period widgets enabled if we have more than 1 period
if(numPeriods > 1)
{
m_uiForm.homePeriodBox2->setEnabled(true);
m_uiForm.homePeriodBoxMath->setEnabled(true);
}
else
{
m_uiForm.homePeriodBox2->setEnabled(false);
m_uiForm.homePeriodBoxMath->setEnabled(false);
}
}
/**
* Return the group-number for the group in a row. Return -1 if
* invalid group in row
*
* @param row :: A row in the group table
* @return Group number
*/
int MuonAnalysis::getGroupNumberFromRow(int row)
{
whichGroupToWhichRow(m_uiForm, m_groupToRow);
for (unsigned int i = 0; i < m_groupToRow.size(); i++)
{
if ( m_groupToRow[i] == row )
return i;
}
return -1;
}
/**
* Return the pair-number for the pair in a row. Return -1 if
* invalid pair in row
*
* @param row :: A row in the pair table
* @return Pair number
*/
int MuonAnalysis::getPairNumberFromRow(int row)
{
whichPairToWhichRow(m_uiForm, m_pairToRow);
for (unsigned int i = 0; i < m_pairToRow.size(); i++)
{
if ( m_pairToRow[i] == row )
return i;
}
return -1;
}
/**
* Return the pair which is in focus and -1 if none
*/
int MuonAnalysis::pairInFocus()
{
// plus some code here which double checks that pair
// table in focus actually sensible
return m_pairTableRowInFocus;
}
/**
* Clear tables and front combo box
*/
void MuonAnalysis::clearTablesAndCombo()
{
m_uiForm.groupTable->clearContents();
m_uiForm.frontGroupGroupPairComboBox->clear();
m_uiForm.frontPlotFuncs->clear();
m_uiForm.pairTable->clearContents();
for (int i = 0; i < m_uiForm.pairTable->rowCount(); i++)
{
m_uiForm.pairTable->setCellWidget(i,1, new QComboBox);
m_uiForm.pairTable->setCellWidget(i,2, new QComboBox);
}
}
/**
* Create WS contained the data for a plot
* Take the MuonAnalysisGrouped WS and reduce(crop) histograms according to Plot Options.
* If period data then the resulting cropped WS is on for the period, or sum/difference of, selected
* by the user on the front panel. Also create raw workspace for fitting against if the user wants.
* @param groupName WorkspaceGroup name to add created workspace to
* @param inputWS Name of the input workspace equal unprocessed data, but which have been groupped
* @param outWS Name of output workspace created by this method
*/
void MuonAnalysis::createPlotWS(const std::string& groupName,
const std::string& inputWS, const std::string& outWS)
{
m_loaded = true;
// adjust for time zero if necessary
if ( m_nexusTimeZero != timeZero())
{
try {
double shift = m_nexusTimeZero - timeZero();
Mantid::API::IAlgorithm_sptr rebinAlg = Mantid::API::AlgorithmManager::Instance().create("ChangeBinOffset");
rebinAlg->setPropertyValue("InputWorkspace", inputWS);
rebinAlg->setPropertyValue("OutputWorkspace", outWS);
rebinAlg->setProperty("Offset", shift);
rebinAlg->execute();
}
catch(...) {
QMessageBox::information(this, "Mantid - Muon Analysis", "The workspace couldn't be corrected for time zero.");
}
}
Mantid::API::IAlgorithm_sptr cropAlg = Mantid::API::AlgorithmManager::Instance().create("CropWorkspace");
if ( m_nexusTimeZero != timeZero() )
cropAlg->setPropertyValue("InputWorkspace", outWS);
else
cropAlg->setPropertyValue("InputWorkspace", inputWS);
cropAlg->setPropertyValue("OutputWorkspace", outWS);
cropAlg->setProperty("Xmin", plotFromTime());
if ( !m_uiForm.timeAxisFinishAtInput->text().isEmpty() )
cropAlg->setProperty("Xmax", plotToTime());
cropAlg->execute();
// Copy the data and keep as raw for later
m_fitDataTab->makeRawWorkspace(outWS);
// rebin data if option set in Plot Options
if (m_uiForm.rebinComboBox->currentIndex() != 0)
{
try
{
Mantid::API::MatrixWorkspace_sptr tempWs = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve(outWS));
std::string rebinParams("");
double binSize = tempWs->dataX(0)[1]-tempWs->dataX(0)[0];
if(m_uiForm.rebinComboBox->currentIndex() == 1) // Fixed
{
double bunchedBinSize = binSize*m_uiForm.optionStepSizeText->text().toDouble();
rebinParams = boost::lexical_cast<std::string>(bunchedBinSize);
}
else // Variable
{
rebinParams = m_uiForm.binBoundaries->text().toStdString();
}
// bunch data
Mantid::API::IAlgorithm_sptr rebinAlg = Mantid::API::AlgorithmManager::Instance().create("Rebin");
rebinAlg->setPropertyValue("InputWorkspace", outWS);
rebinAlg->setPropertyValue("OutputWorkspace", outWS);
rebinAlg->setPropertyValue("Params", rebinParams);
rebinAlg->execute();
// however muon group don't want last bin if shorter than previous bins
tempWs = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve(outWS));
binSize = tempWs->dataX(0)[1]-tempWs->dataX(0)[0];
double firstX = tempWs->dataX(0)[0];
double lastX = tempWs->dataX(0)[tempWs->dataX(0).size()-1];
double numberOfFullBunchedBins = std::floor((lastX - firstX) / binSize );
if ( numberOfFullBunchedBins )
{
lastX = firstX + numberOfFullBunchedBins*binSize;
Mantid::API::IAlgorithm_sptr cropAlg = Mantid::API::AlgorithmManager::Instance().create("CropWorkspace");
cropAlg->setPropertyValue("InputWorkspace", outWS);
cropAlg->setPropertyValue("OutputWorkspace", outWS);
cropAlg->setPropertyValue("Xmax", boost::lexical_cast<std::string>(lastX));
cropAlg->setProperty("Xmax", lastX);
cropAlg->execute();
}
}
catch(std::exception&)
{
QMessageBox::information(this, "Mantid - Muon Analysis", "The workspace couldn't be rebunched.");
}
}
// Make group to display more organised in Mantidplot workspace list
if ( !AnalysisDataService::Instance().doesExist(groupName) )
{
QString rubbish = "boevsMoreBoevs";
QString groupStr = rubbish + QString("=CloneWorkspace(InputWorkspace='") + outWS.c_str() + "')\n";
groupStr += groupName.c_str() + QString("=GroupWorkspaces(InputWorkspaces='") + outWS.c_str() + "," + rubbish
+ "')\n";
runPythonCode( groupStr ).trimmed();
AnalysisDataService::Instance().remove(rubbish.toStdString());
}
else
{
QString groupStr = QString(groupName.c_str()) + QString("=GroupWorkspaces(InputWorkspaces='") + outWS.c_str() + "," + groupName.c_str()
+ "')\n";
runPythonCode( groupStr ).trimmed();
}
// Group the raw workspace
std::vector<std::string> groupWorkspaces;
groupWorkspaces.push_back(groupName);
groupWorkspaces.push_back(outWS + "_Raw");
m_fitDataTab->groupWorkspaces(groupWorkspaces, groupName);
}
/**
* Used by plotGroup and plotPair.
*/
void MuonAnalysis::handlePeriodChoice(const QString wsName, const QStringList& periodLabel, const QString& /*groupName*/)
{
if ( periodLabel.size() == 2 )
{
if ( m_uiForm.homePeriodBoxMath->currentText()=="+" )
{
Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("Plus");
alg->setPropertyValue("LHSWorkspace", wsName.toStdString() + periodLabel.at(0).toStdString());
alg->setPropertyValue("RHSWorkspace", wsName.toStdString() + periodLabel.at(1).toStdString());
alg->setPropertyValue("OutputWorkspace", wsName.toStdString() + periodLabel.at(0).toStdString());
alg->execute();
alg = Mantid::API::AlgorithmManager::Instance().create("Plus");
alg->setPropertyValue("LHSWorkspace", wsName.toStdString() + periodLabel.at(0).toStdString() + "_Raw");
alg->setPropertyValue("RHSWorkspace", wsName.toStdString() + periodLabel.at(1).toStdString() + "_Raw");
alg->setPropertyValue("OutputWorkspace", wsName.toStdString() + periodLabel.at(0).toStdString() + "_Raw");
alg->execute();
}
else
{
Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("Minus");
alg->setPropertyValue("LHSWorkspace", wsName.toStdString() + periodLabel.at(0).toStdString());
alg->setPropertyValue("RHSWorkspace", wsName.toStdString() + periodLabel.at(1).toStdString());
alg->setPropertyValue("OutputWorkspace", wsName.toStdString() + periodLabel.at(0).toStdString());
alg->execute();
alg = Mantid::API::AlgorithmManager::Instance().create("Minus");
alg->setPropertyValue("LHSWorkspace", wsName.toStdString() + periodLabel.at(0).toStdString() + "_Raw");
alg->setPropertyValue("RHSWorkspace", wsName.toStdString() + periodLabel.at(1).toStdString() + "_Raw");
alg->setPropertyValue("OutputWorkspace", wsName.toStdString() + periodLabel.at(0).toStdString() + "_Raw");
alg->execute();
}
Mantid::API::AnalysisDataService::Instance().remove((wsName + periodLabel.at(1)).toStdString() );
Mantid::API::AnalysisDataService::Instance().remove((wsName + periodLabel.at(1) + "_Raw").toStdString() );
Mantid::API::AnalysisDataService::Instance().rename((wsName + periodLabel.at(0)).toStdString(), wsName.toStdString());
Mantid::API::AnalysisDataService::Instance().rename((wsName + periodLabel.at(0)+"_Raw").toStdString(), (wsName+"_Raw").toStdString());
}
else
{
if ( periodLabel.at(0) != "" )
{
Mantid::API::AnalysisDataService::Instance().rename((wsName + periodLabel.at(0)).toStdString(), wsName.toStdString());
Mantid::API::AnalysisDataService::Instance().rename((wsName + periodLabel.at(0)+"_Raw").toStdString(), (wsName+"_Raw").toStdString());
}
}
}
/**
* Get period labels for the periods selected in the GUI
* @return Return empty string if no periods (well just one period). If more
* one period then return "_#" string for the periods selected by user
*/
QStringList MuonAnalysis::getPeriodLabels() const
{
QStringList retVal;
if ( m_uiForm.homePeriodBox2->isEnabled() && m_uiForm.homePeriodBox2->currentText()!="None" )
{
retVal.append( "_" + m_uiForm.homePeriodBox1->currentText());
retVal.append( "_" + m_uiForm.homePeriodBox2->currentText());
}
else if ( m_uiForm.homePeriodBox2->isEnabled() )
{
retVal.append( "_" + m_uiForm.homePeriodBox1->currentText());
}
else
retVal.append("");
return retVal;
}
/**
* plots specific WS spectrum (used by plotPair and plotGroup)
* @param wsName workspace name
* @param wsIndex workspace index
*/
void MuonAnalysis::plotSpectrum(const QString& wsName, const int wsIndex, const bool ylogscale)
{
// create first part of plotting Python string
QString gNum = QString::number(wsIndex);
QString pyS;
// Plot error bars by default. If not needed they will get hidden when plot style if applied.
pyS = "gs = plotSpectrum(\"" + wsName + "\"," + gNum + ",True)\n";
// Add the objectName for the peakPickerTool to find
pyS += "gs.setObjectName(\"" + wsName + "\")\n"
"l = gs.activeLayer()\n"
"l.setCurveTitle(0, \"" + wsName + "\")\n"
"l.setTitle(\"" + m_title.c_str() + "\")\n";
if ( ylogscale )
pyS += "l.logYlinX()\n";
// plot the spectrum
runPythonCode( pyS );
}
/**
* Set various style parameters for the plot of the given ws
* @param wsName Workspace which plot to style
* @param params Maps of the parameters, see MuonAnalysisOptionTab::parsePlotStyleParams for list
of possible keys
*/
void MuonAnalysis::setPlotStyle(const QString& wsName, const QMap<QString, QString>& params)
{
QString code;
// Get the active layer of the graph
code += "l = graph('"+ wsName + "-1').activeLayer()\n";
// Set whether to show symbols
QString symbolStyle = (params["ConnectType"] == "0") ? QString("PlotSymbol.NoSymbol") : QString("PlotSymbol.Ellipse");
code += "l.setCurveSymbol(0, PlotSymbol(" + symbolStyle +", QBrush(), QPen(), QSize(5,5)))\n";
// Set whether to show line
QString penStyle = (params["ConnectType"] == "1") ? QString("Qt.NoPen") : QString("Qt.SolidLine");
code += "pen = QPen(Qt.black)\n"
"pen.setStyle(" + penStyle +")\n"
"l.setCurvePen(0, pen)\n";
// Set error settings
QString showErrors = (params["ShowErrors"] == "True") ? QString("True") : QString("False");
code += "errorSettings = l.errorBarSettings(0, 0)\n"
"errorSettings.drawMinusSide(" + showErrors + ")\n"
"errorSettings.drawPlusSide(" + showErrors + ")\n";
// If autoscaling disabled - set manual Y axis values
if(params["YAxisAuto"] == "False")
code += "l.setAxisScale(Layer.Left," + params["YAxisMin"] + "," + params["YAxisMax"] + ")\n";
else
code += "l.setAutoScale()\n";
// Replot
code += "l.replot()\n";
runPythonCode(code);
}
/**
* Get current plot style parameters. wsName and wsIndex are used to get default values if
* something is not specified.
* @param wsName Workspace plot of which we want to style
* @param wsIndex Workspace index of the plot data
* @return Maps of the parameters, see MuonAnalysisOptionTab::parsePlotStyleParams for list
of possible keys
*/
QMap<QString, QString> MuonAnalysis::getPlotStyleParams(const QString& wsName, const int wsIndex)
{
// Get parameter values from the options tab
QMap<QString, QString> params = m_optionTab->parsePlotStyleParams();
// If autoscale disabled
if(params["YAxisAuto"] == "False")
{
// Get specified min/max values for Y axis
QString min = params["YAxisMin"];
QString max = params["YAxisMax"];
// If any of those is not specified - get min and max by default
if(min.isEmpty() || max.isEmpty())
{
Workspace_sptr ws_ptr = AnalysisDataService::Instance().retrieve(wsName.toStdString());
MatrixWorkspace_sptr matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(ws_ptr);
const Mantid::MantidVec& dataY = matrix_workspace->readY(wsIndex);
if(min.isEmpty())
params["YAxisMin"] = QString::number(*min_element(dataY.begin(), dataY.end()));
if(max.isEmpty())
params["YAxisMax"] = QString::number(*max_element(dataY.begin(), dataY.end()));
}
}
return params;
}
/**
* Closes the window with the plot of the given ws.
* @param wsName Name of the workspace which plot window to close
*/
void MuonAnalysis::closePlotWindow(const QString& wsName)
{
QString code;
code += "g = graph('"+ wsName + "-1')\n"
"if g != None:\n"
" g.confirmClose(False)\n"
" g.close()\n";
runPythonCode(code);
}
/**
* Checks if the plot for the workspace does exist.
* @param wsName Name of the workspace
* @return True if exists, false if not
*/
bool MuonAnalysis::plotExists(const QString& wsName)
{
QString code;
code += "g = graph('%1-1')\n"
"if g != None:\n"
" print('1')\n"
"else:\n"
" print('0')\n";
QString output = runPythonCode(code.arg(wsName));
bool ok;
int outputCode = output.toInt(&ok);
if(!ok)
throw std::logic_error("Script should print 0 or 1");
return (outputCode == 1);
}
/**
* Enable PP tool for the plot of the given WS.
* @param wsName Name of the WS which plot PP tool will be attached to.
*/
void MuonAnalysis::selectMultiPeak(const QString& wsName)
{
disableAllTools();
QString code;
code += "g = graph('" + wsName + "-1')\n"
"if g != None:\n"
" g.show()\n"
" g.setFocus()\n"
" selectMultiPeak(g)\n";
runPythonCode(code);
}
/**
* Disable tools for all the graphs within MantidPlot.
*/
void MuonAnalysis::disableAllTools()
{
runPythonCode("disableTools()");
}
/**
* Hides all the plot windows (MultiLayer ones)
*/
void MuonAnalysis::hideAllPlotWindows()
{
QString code;
code += "for w in windows():\n"
" if w.inherits('MultiLayer'):\n"
" w.hide()\n";
runPythonCode(code);
}
/**
* Shows all the plot windows (MultiLayer ones)
*/
void MuonAnalysis::showAllPlotWindows()
{
QString code;
code += "for w in windows():\n"
" if w.inherits('MultiLayer'):\n"
" w.show()\n";
runPythonCode(code);
}
/**
* Show a plot for a given workspace. Closes previous plot if exists.
* @param wsName The name of workspace to be plotted. Should exist in ADS.
*/
void MuonAnalysis::showPlot(const QString& wsName)
{
// TODO: use selected wsIndex, as two groups might be in one ws (before we make ws contain
// only one groups)
// If empty -> no workspaces available to choose (e.g. all were deleted)
if(wsName.isEmpty())
{
setCurrentDataName(NOT_AVAILABLE);
}
// Just in case, check if exists. Shouldn't happen normally.
// TODO: can happen if currently connected ws gets deleted. Observe deletion event and do
// something in that case
else if(!AnalysisDataService::Instance().doesExist(wsName.toStdString()))
{
g_log.warning("Can't show workspace which doesn't exist.");
}
else
{
setCurrentDataName(wsName);
if(!plotExists(wsName))
{
plotSpectrum(m_currentDataName, 0, false);
setPlotStyle(m_currentDataName, getPlotStyleParams(m_currentDataName, 0));
}
selectMultiPeak(m_currentDataName);
}
}
/**
* Plot group
*/
void MuonAnalysis::plotGroup(const std::string& plotType)
{
if (plotToTime() <= plotFromTime())
return;
m_updating = true;
int groupNum = getGroupNumberFromRow(m_groupTableRowInFocus);
if ( groupNum >= 0 )
{
QTableWidgetItem *itemName = m_uiForm.groupTable->item(m_groupTableRowInFocus,0);
QString groupName = itemName->text();
QString wsGroupName(getGroupName());
// create plot workspace name
QString plotTypeTitle("");
if (plotType == "Asymmetry")
{
plotTypeTitle = "Asym";
}
else
{
if(plotType == "Counts")
plotTypeTitle = "Counts";
else
plotTypeTitle = "Logs";
}
QString cropWSfirstPart = wsGroupName + "; Group="
+ groupName + "; " + plotTypeTitle + "";
// decide on name for workspace to be plotted
QString cropWS(getNewPlotName(cropWSfirstPart));
// curve plot label
QString titleLabel = cropWS;
// Hide all the previous plot windows, if requested by user
if (m_uiForm.hideGraphs->isChecked())
hideAllPlotWindows();
// check if user specified periods - if multiple period data
QStringList periodLabel = getPeriodLabels();
// create the binned etc plot workspace for the first period
QString cropWS_1 = cropWS + periodLabel.at(0);
QString cropWS_2 = ""; // user may not have selected a 2nd period in GUI
createPlotWS(wsGroupName.toStdString(),
m_workspace_name + "Grouped" + periodLabel.at(0).toStdString(),
cropWS_1.toStdString());
// and the binned etc plot workspace for the second period
if (periodLabel.size() == 2)
{
cropWS_2 = cropWS + periodLabel.at(1);
createPlotWS(wsGroupName.toStdString(),
m_workspace_name + "Grouped" + periodLabel.at(1).toStdString(),
cropWS_2.toStdString());
}
// set to true if plot y axis on log scale
bool plotOnLogScale = false;
if (plotType.compare("Counts") == 0)
{
// nothing to do
}
else if (plotType.compare("Asymmetry") == 0)
{
Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("RemoveExpDecay");
alg->setPropertyValue("InputWorkspace", cropWS_1.toStdString());
alg->setPropertyValue("OutputWorkspace", cropWS_1.toStdString());
alg->execute();
alg = Mantid::API::AlgorithmManager::Instance().create("RemoveExpDecay");
alg->setPropertyValue("InputWorkspace", cropWS_1.toStdString() + "_Raw");
alg->setPropertyValue("OutputWorkspace", cropWS_1.toStdString() + "_Raw");
alg->execute();
if (periodLabel.size() == 2)
{
alg = Mantid::API::AlgorithmManager::Instance().create("RemoveExpDecay");
alg->setPropertyValue("InputWorkspace", cropWS_2.toStdString());
alg->setPropertyValue("OutputWorkspace", cropWS_2.toStdString());
alg->execute();
alg = Mantid::API::AlgorithmManager::Instance().create("RemoveExpDecay");
alg->setPropertyValue("InputWorkspace", cropWS_2.toStdString() + "_Raw");
alg->setPropertyValue("OutputWorkspace", cropWS_2.toStdString() + "_Raw");
alg->execute();
}
}
else if (plotType.compare("Logorithm") == 0)
{
// nothing to do since plot as count but with the y-axis set to logarithm scale
plotOnLogScale = true;
}
else
{
g_log.error("Unknown group table plot function");
m_updating = false;
return;
}
// If user has specified this do algebra on periods
// note after running this method you are just left with the processed cropWS (and curresponding _Raw)
handlePeriodChoice(cropWS, periodLabel, wsGroupName);
// set the workspace Y Unit label
Workspace_sptr ws_ptr = AnalysisDataService::Instance().retrieve(cropWS.toStdString());
MatrixWorkspace_sptr matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(ws_ptr);
matrix_workspace->setYUnitLabel(plotType);
ws_ptr = AnalysisDataService::Instance().retrieve((cropWS+"_Raw").toStdString());
matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(ws_ptr);
matrix_workspace->setYUnitLabel(plotType);
// plot the spectrum
plotSpectrum(cropWS, groupNum, plotOnLogScale);
// Change the plot style of the graph so that it matches what is selected on
// the plot options tab.
setPlotStyle(titleLabel, getPlotStyleParams(titleLabel, groupNum));
setCurrentDataName(titleLabel);
}
m_updating = false;
}
/**
* Plot pair
*
* @param plotType :: Whether it is Asym, count, etc
*/
void MuonAnalysis::plotPair(const std::string& plotType)
{
if (plotToTime() <= plotFromTime())
return;
m_updating = true;
int pairNum = getPairNumberFromRow(m_pairTableRowInFocus);
if ( pairNum >= 0 )
{
QTableWidgetItem *itemAlpha = m_uiForm.pairTable->item(m_pairTableRowInFocus,3);
QTableWidgetItem *itemName = m_uiForm.pairTable->item(m_pairTableRowInFocus,0);
QString pairName = itemName->text();
QString wsGroupName(getGroupName());
// create plot workspace name
QString plotTypeTitle("");
if (plotType == "Asymmetry")
{
plotTypeTitle = "Asym";
}
QString cropWSfirstPart = wsGroupName + "; Group=" + pairName + "; " + plotTypeTitle + "";
// decide on name for workspace to be plotted
QString cropWS(getNewPlotName(cropWSfirstPart));
// curve plot label
QString titleLabel = cropWS;
// Hide all the previous plot windows, if requested by user
if (m_uiForm.hideGraphs->isChecked())
hideAllPlotWindows();
// check if user specified periods - if multiple period data
QStringList periodLabel = getPeriodLabels();
// create the binned etc plot workspace for the first period
QString cropWS_1 = cropWS + periodLabel.at(0);
QString cropWS_2 = ""; // user may not have selected a 2nd period in GUI
createPlotWS(wsGroupName.toStdString(),
m_workspace_name + "Grouped" + periodLabel.at(0).toStdString(),
cropWS_1.toStdString());
// and the binned etc plot workspace for the second period
if (periodLabel.size() == 2)
{
cropWS_2 = cropWS + periodLabel.at(1);
createPlotWS(wsGroupName.toStdString(),
m_workspace_name + "Grouped" + periodLabel.at(1).toStdString(),
cropWS_2.toStdString());
}
if (plotType.compare("Asymmetry") == 0)
{
QComboBox* qw1 = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(m_pairTableRowInFocus,1));
QComboBox* qw2 = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(m_pairTableRowInFocus,2));
Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("AsymmetryCalc");
alg->setPropertyValue("InputWorkspace", cropWS_1.toStdString());
alg->setPropertyValue("OutputWorkspace", cropWS_1.toStdString());
alg->setPropertyValue("ForwardSpectra", QString::number(qw1->currentIndex()).toStdString());
alg->setPropertyValue("BackwardSpectra", QString::number(qw2->currentIndex()).toStdString());
alg->setPropertyValue("Alpha", itemAlpha->text().toStdString());
alg->execute();
alg = Mantid::API::AlgorithmManager::Instance().create("AsymmetryCalc");
alg->setPropertyValue("InputWorkspace", cropWS_1.toStdString() + "_Raw");
alg->setPropertyValue("OutputWorkspace", cropWS_1.toStdString() + "_Raw");
alg->setPropertyValue("ForwardSpectra", QString::number(qw1->currentIndex()).toStdString());
alg->setPropertyValue("BackwardSpectra", QString::number(qw2->currentIndex()).toStdString());
alg->setPropertyValue("Alpha", itemAlpha->text().toStdString());
alg->execute();
if (periodLabel.size() == 2)
{
Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("AsymmetryCalc");
alg->setPropertyValue("InputWorkspace", cropWS_2.toStdString());
alg->setPropertyValue("OutputWorkspace", cropWS_2.toStdString());
alg->setPropertyValue("ForwardSpectra", QString::number(qw1->currentIndex()).toStdString());
alg->setPropertyValue("BackwardSpectra", QString::number(qw2->currentIndex()).toStdString());
alg->setPropertyValue("Alpha", itemAlpha->text().toStdString());
alg->execute();
alg = Mantid::API::AlgorithmManager::Instance().create("AsymmetryCalc");
alg->setPropertyValue("InputWorkspace", cropWS_2.toStdString() + "_Raw");
alg->setPropertyValue("OutputWorkspace", cropWS_2.toStdString() + "_Raw");
alg->setPropertyValue("ForwardSpectra", QString::number(qw1->currentIndex()).toStdString());
alg->setPropertyValue("BackwardSpectra", QString::number(qw2->currentIndex()).toStdString());
alg->setPropertyValue("Alpha", itemAlpha->text().toStdString());
alg->execute();
}
}
else
{
g_log.error("Unknown pair table plot function");
m_updating = false;
return;
}
// If user has specified this do algebra on periods
// note after running this method you are just left with the processed cropWS (and curresponding _Raw)
handlePeriodChoice(cropWS, periodLabel, wsGroupName);
// set the workspace Y Unit label
Workspace_sptr ws_ptr = AnalysisDataService::Instance().retrieve(cropWS.toStdString());
MatrixWorkspace_sptr matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(ws_ptr);
matrix_workspace->setYUnitLabel(plotType);
ws_ptr = AnalysisDataService::Instance().retrieve((cropWS+"_Raw").toStdString());
matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(ws_ptr);
matrix_workspace->setYUnitLabel(plotType);
// plot the spectrum
plotSpectrum(cropWS, 0);
// Change the plot style of the graph so that it matches what is selected on
// the plot options tab
setPlotStyle(titleLabel, getPlotStyleParams(titleLabel, 0));
setCurrentDataName(titleLabel);
}
m_updating = false;
}
QString MuonAnalysis::getNewPlotName(const QString & cropWSfirstPart)
{
// check if this workspace already exist to avoid replotting an existing workspace
QString cropWS("");
int plotNum = 1;
while (1==1)
{
cropWS = cropWSfirstPart + "; #" + boost::lexical_cast<std::string>(plotNum).c_str();
if ( AnalysisDataService::Instance().doesExist(cropWS.toStdString()) )
{
if((m_uiForm.plotCreation->currentIndex() == 0) || (m_uiForm.plotCreation->currentIndex() == 2) )
{
closePlotWindow(cropWS);
AnalysisDataService::Instance().remove(cropWS.toStdString());
break;
}
else
plotNum++;
}
else
{
break;
}
}
return cropWS;
}
/**
* Is Grouping set.
*
* @return true if set
*/
bool MuonAnalysis::isGroupingSet()
{
std::vector<int> dummy;
whichGroupToWhichRow(m_uiForm, dummy);
if (dummy.empty())
return false;
else
return true;
}
/**
* Apply whatever grouping is specified in GUI tables to workspace.
*/
bool MuonAnalysis::applyGroupingToWS( const std::string& inputWsName, const std::string& outputWsName)
{
if (!isGroupingSet() || !AnalysisDataService::Instance().doesExist(inputWsName))
return false;
std::string complaint = isGroupingAndDataConsistent();
if (!( complaint.empty() ) )
{
if (m_uiForm.frontPlotButton->isEnabled() )
QMessageBox::warning(this, "MantidPlot - MuonAnalysis", complaint.c_str());
m_optionTab->noDataAvailable();
return false;
}
else
{
if (!m_uiForm.frontPlotButton->isEnabled() )
m_optionTab->nowDataAvailable();
}
// If output workspace exists, remove explicitly, so even if something goes wrong - old data
// is not used
if(AnalysisDataService::Instance().doesExist(outputWsName))
{
// Using DeleteWorkspace algorithm so if outputWs is a group - it is fully removed
Mantid::API::IAlgorithm_sptr rmWs = AlgorithmManager::Instance().create("DeleteWorkspace");
rmWs->initialize();
rmWs->setPropertyValue("Workspace", outputWsName);
rmWs->execute();
}
Grouping tableGrouping;
parseGroupingTable(m_uiForm, tableGrouping);
// Retrieve input workspace
Workspace_sptr inputWs = AnalysisDataService::Instance().retrieve(inputWsName);
Workspace_sptr outputWs;
try // ... to group
{
// Single workspace
if(MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast<MatrixWorkspace>(inputWs))
{
outputWs = groupWorkspace(ws, tableGrouping);
}
// Workspace group
else if(WorkspaceGroup_sptr group = boost::dynamic_pointer_cast<WorkspaceGroup>(inputWs))
{
// Create output group
WorkspaceGroup_sptr outputGroup = boost::make_shared<WorkspaceGroup>();
for(size_t i = 0; i < group->size(); i++)
{
if(MatrixWorkspace_sptr member = boost::dynamic_pointer_cast<MatrixWorkspace>(group->getItem(i)))
{
MatrixWorkspace_sptr groupedMember = groupWorkspace(member, tableGrouping);
outputGroup->addWorkspace(groupedMember);
}
else
throw std::invalid_argument("Group contains unsupported workspace type");
}
outputWs = outputGroup;
}
else
throw std::invalid_argument("Unsupported workspace type");
}
catch(std::exception& e)
{
m_optionTab->noDataAvailable();
g_log.error(e.what());
return false;
}
AnalysisDataService::Instance().add(outputWsName, outputWs);
return true;
}
/**
* Calculate number of detectors from string of type 1-3, 5, 10-15
*
* @param str :: String of type "1-3, 5, 10-15"
* @return Number of detectors. Return 0 if not recognised
*/
int MuonAnalysis::numOfDetectors(const std::string& str) const
{
return static_cast<int>(spectrumIDs(str).size());
}
/**
* Return a vector of IDs for row number from string of type 1-3, 5, 10-15
*
* @param str :: String of type "1-3, 5, 10-15"
* @return Vector of IDs
*/
std::vector<int> MuonAnalysis::spectrumIDs(const std::string& str) const
{
std::vector<int> retVal;
if (str.empty())
return retVal;
typedef Poco::StringTokenizer tokenizer;
tokenizer values(str, ",", tokenizer::TOK_TRIM);
for (int i = 0; i < static_cast<int>(values.count()); i++)
{
std::size_t found= values[i].find("-");
if (found!=std::string::npos)
{
tokenizer aPart(values[i], "-", tokenizer::TOK_TRIM);
if ( aPart.count() != 2 )
{
retVal.clear();
return retVal;
}
else
{
if ( !(isNumber(aPart[0]) && isNumber(aPart[1])) )
{
retVal.clear();
return retVal;
}
}
int leftInt;
std::stringstream leftRead(aPart[0]);
leftRead >> leftInt;
int rightInt;
std::stringstream rightRead(aPart[1]);
rightRead >> rightInt;
if (leftInt > rightInt)
{
retVal.clear();
return retVal;
}
for (int step = leftInt; step <= rightInt; step++)
retVal.push_back(step);
}
else
{
if (isNumber(values[i]))
retVal.push_back(boost::lexical_cast<int>(values[i].c_str()));
else
{
retVal.clear();
return retVal;
}
}
}
return retVal;
}
/**
* Change the workspace group name to the instrument and run number if load current run was pressed.
*
* @param workspaceGroupName :: The name of the group that needs to be changed or is already in correct format.
*/
void MuonAnalysis::changeCurrentRun(std::string & workspaceGroupName)
{
QString tempGroupName(QString::fromStdString(workspaceGroupName) );
if ( (tempGroupName.contains("auto") ) || (tempGroupName.contains("argus0000000") ) )
{
Workspace_sptr workspace_ptr = AnalysisDataService::Instance().retrieve(m_workspace_name);
MatrixWorkspace_sptr matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(workspace_ptr);
if(!matrix_workspace) // Data collected in periods.
{
// Get run number from first period data.
workspace_ptr = AnalysisDataService::Instance().retrieve(m_workspace_name + "_1");
matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(workspace_ptr);
if(!matrix_workspace)
{
QMessageBox::information(this, "Mantid - Muon Analysis", "Mantid expected period data but no periods were found.\n"
"Default plot name will be used insead of run number.");
return;
}
}
const Run& runDetails = matrix_workspace->run();
std::string runNumber = runDetails.getProperty("run_number")->value();
QString instname = m_uiForm.instrSelector->currentText().toUpper();
size_t zeroPadding(8);
if (instname == "ARGUS")
zeroPadding = 7;
for (size_t i=runNumber.size(); i<zeroPadding; ++i)
{
runNumber = '0' + runNumber;
}
workspaceGroupName = instname.toStdString() + runNumber;
}
}
/** Is input string a number?
*
* @param s :: The input string
* @return True is input string is a number
*/
bool MuonAnalysis::isNumber(const std::string& s) const
{
if( s.empty() )
{
return false;
}
const std::string allowed("0123456789");
for (unsigned int i = 0; i < s.size(); i++)
{
if (allowed.find_first_of(s[i]) == std::string::npos)
{
return false;
}
}
return true;
}
/**
* Return true if data are loaded
*/
bool MuonAnalysis::areDataLoaded()
{
return AnalysisDataService::Instance().doesExist(m_workspace_name);
}
/**
* Set start up interface look and populate local attributes
* initiated from info set in QT designer
*/
void MuonAnalysis::startUpLook()
{
// populate group plot functions
for (int i = 0; i < m_uiForm.groupTablePlotChoice->count(); i++)
m_groupPlotFunc.append(m_uiForm.groupTablePlotChoice->itemText(i));
// pair plot functions
for (int i = 0; i < m_uiForm.pairTablePlotChoice->count(); i++)
m_pairPlotFunc.append(m_uiForm.pairTablePlotChoice->itemText(i));
// Set initial front
m_uiForm.frontAlphaLabel->setVisible(false);
m_uiForm.frontAlphaNumber->setVisible(false);
m_uiForm.frontAlphaNumber->setEnabled(false);
m_uiForm.homePeriodBox2->setEditable(false);
m_uiForm.homePeriodBox2->setEnabled(false);
// Only allow numbers in the time zero text box
m_uiForm.timeZeroFront->setValidator(new QDoubleValidator(m_uiForm.timeZeroFront));
// set various properties of the group table
m_uiForm.groupTable->setColumnWidth(0, 100);
m_uiForm.groupTable->setColumnWidth(1, 200);
for (int i = 0; i < m_uiForm.groupTable->rowCount(); i++)
{
QTableWidgetItem* item = m_uiForm.groupTable->item(i,2);
if (!item)
{
QTableWidgetItem* it = new QTableWidgetItem("");
it->setFlags(it->flags() & (~Qt::ItemIsEditable));
m_uiForm.groupTable->setItem(i,2, it);
}
else
{
item->setFlags(item->flags() & (~Qt::ItemIsEditable));
}
item = m_uiForm.groupTable->item(i,0);
if (!item)
{
QTableWidgetItem* it = new QTableWidgetItem("");
m_uiForm.groupTable->setItem(i,0, it);
}
}
}
/**
* set grouping in table from information from nexus raw file
*/
void MuonAnalysis::setGroupingFromNexus(const QString& nexusFile)
{
if ( isGroupingSet() )
return;
std::string groupedWS = m_workspace_name+"Grouped";
// Setup Load Nexus Algorithm
Mantid::API::IAlgorithm_sptr loadMuonAlg = Mantid::API::AlgorithmManager::Instance().create("LoadMuonNexus");
loadMuonAlg->setPropertyValue("Filename", nexusFile.toStdString());
loadMuonAlg->setPropertyValue("OutputWorkspace", groupedWS);
loadMuonAlg->setProperty("AutoGroup", true);
if (! (loadMuonAlg->execute() ) )
{
QMessageBox::warning(this,"Mantid - MuonAnalysis", "Problem when executing LoadMuonNexus algorithm.");
}
// get hold of a matrix-workspace. If period data assume each period has
// the same grouping
Workspace_sptr ws_ptr = AnalysisDataService::Instance().retrieve(groupedWS);
WorkspaceGroup_sptr wsPeriods = boost::dynamic_pointer_cast<WorkspaceGroup>(ws_ptr);
MatrixWorkspace_sptr matrix_workspace;
if (wsPeriods)
{
Workspace_sptr ws_ptr1 = AnalysisDataService::Instance().retrieve(groupedWS + "_1");
matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(ws_ptr1);
}
else
{
matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(ws_ptr);
}
// check if there is any grouping in file
bool thereIsGrouping = false;
int numOfHist = static_cast<int>(matrix_workspace->getNumberHistograms()); //Qt has no size_t understanding
for (int wsIndex = 0; wsIndex < numOfHist; wsIndex++)
{
IDetector_const_sptr det;
try // for some bizarry reason when reading EMUautorun_A.tmp this
// underlying nexus file think there are more histogram than there is
// hence the reason for this try/catch here
{
det = matrix_workspace->getDetector(wsIndex);
}
catch (...)
{
break;
}
if( boost::dynamic_pointer_cast<const DetectorGroup>(det) )
{
// prepare IDs string
boost::shared_ptr<const DetectorGroup> detG = boost::dynamic_pointer_cast<const DetectorGroup>(det);
std::vector<Mantid::detid_t> detIDs = detG->getDetectorIDs();
if (detIDs.size() > 1)
{
thereIsGrouping = true;
break;
}
}
}
// if no grouping in nexus then return
if ( thereIsGrouping == false )
{
return;
}
// Add info about grouping from Nexus file to group table
for (int wsIndex = 0; wsIndex < numOfHist; wsIndex++)
{
IDetector_const_sptr det = matrix_workspace->getDetector(wsIndex);
if( boost::dynamic_pointer_cast<const DetectorGroup>(det) )
{
// prepare IDs string
boost::shared_ptr<const DetectorGroup> detG = boost::dynamic_pointer_cast<const DetectorGroup>(det);
std::vector<Mantid::detid_t> detIDs = detG->getDetectorIDs();
std::stringstream idstr;
int leftInt = detIDs[0]; // meaning left as in the left number of the range 8-18 for instance
int numIDs = static_cast<int>(detIDs.size());
idstr << detIDs[0];
for (int i = 1; i < numIDs; i++)
{
if (detIDs[i] != detIDs[i-1]+1 )
{
if (detIDs[i-1] == leftInt)
{
idstr << ", " << detIDs[i];
leftInt = detIDs[i];
}
else
{
idstr << "-" << detIDs[i-1] << ", " << detIDs[i];
leftInt = detIDs[i];
}
}
else if ( i == numIDs-1 )
{
idstr << "-" << detIDs[i];
}
}
// prepare group name string
std::stringstream gName;
gName << wsIndex;
// create table row
QTableWidgetItem* it = m_uiForm.groupTable->item(wsIndex, 0);
if (it)
it->setText(gName.str().c_str());
else
{
m_uiForm.groupTable->setItem(wsIndex, 0, new QTableWidgetItem(gName.str().c_str()));
}
it = m_uiForm.groupTable->item(wsIndex, 1);
if (it)
it->setText(idstr.str().c_str());
else
m_uiForm.groupTable->setItem(wsIndex, 1, new QTableWidgetItem(idstr.str().c_str()));
}
} // end loop over wsIndex
// check if exactly two groups added in which case assume these are forward/backward groups
// and automatically then create a pair from which, where the first group is assumed to be
// the forward group
updatePairTable();
if ( numGroups() == 2 && numPairs() <= 0 )
{
QTableWidgetItem* it = m_uiForm.pairTable->item(0, 0);
if (it)
it->setText("pair");
else
{
m_uiForm.pairTable->setItem(0, 0, new QTableWidgetItem("long"));
}
it = m_uiForm.pairTable->item(0, 3);
if (it)
it->setText("1.0");
else
{
m_uiForm.pairTable->setItem(0, 3, new QTableWidgetItem("1.0"));
}
updatePairTable();
updateFrontAndCombo();
m_uiForm.frontGroupGroupPairComboBox->setCurrentIndex(2);
runFrontGroupGroupPairComboBox(2);
}
updatePairTable();
updateFrontAndCombo();
}
/**
* If nothing else work set dummy grouping and display comment to user
*/
void MuonAnalysis::setDummyGrouping(const int numDetectors)
{
// if no grouping in nexus then set dummy grouping and display warning to user
std::stringstream idstr;
idstr << "1-" << numDetectors;
m_uiForm.groupTable->setItem(0, 0, new QTableWidgetItem("NoGroupingDetected"));
m_uiForm.groupTable->setItem(0, 1, new QTableWidgetItem(idstr.str().c_str()));
updateFrontAndCombo();
QMessageBox::warning(this, "MantidPlot - MuonAnalysis", QString("No grouping detected in Nexus file.\n")
+ "and no default grouping file specified in IDF\n"
+ "therefore dummy grouping created.");
}
/**
* Try to load default grouping file specified in IDF
*/
void MuonAnalysis::setGroupingFromIDF(const std::string& mainFieldDirection, MatrixWorkspace_sptr matrix_workspace)
{
Instrument_const_sptr inst = matrix_workspace->getInstrument();
QString instname = m_uiForm.instrSelector->currentText().toUpper();
QString groupParameter = "Default grouping file";
// for now hard coded in the special case of MUSR
if (instname == "MUSR")
{
if ( mainFieldDirection == "Transverse" )
groupParameter += " - Transverse";
else
groupParameter += " - Longitudinal";
}
std::vector<std::string> groupFile = inst->getStringParameter(groupParameter.toStdString());
// get search directory for XML instrument definition files (IDFs)
std::string directoryName = ConfigService::Instance().getInstrumentDirectory();
if ( groupFile.size() == 1 )
{
Grouping loadedGrouping;
try
{
loadGroupingFromXML(directoryName+groupFile[0], loadedGrouping);
}
catch (...)
{
QMessageBox::warning(this, "MantidPlot - MuonAnalysis",
QString("Can't load default grouping file in IDF. \n With name: ") + groupFile[0].c_str());
return;
}
fillGroupingTable(loadedGrouping, m_uiForm);
}
}
/**
* Time zero returend in ms
*/
double MuonAnalysis::timeZero()
{
QString boxText = m_uiForm.timeZeroFront->text();
double timeZero = 0.0;
try
{
timeZero = boost::lexical_cast<double>(boxText.toStdString());
}
catch(boost::bad_lexical_cast)
{
QMessageBox::warning(this, "MantidPlot - Muon Analysis", "Unable to interpret time zero as number, setting to 0.0");
m_uiForm.timeZeroFront->setText("0.0");
}
return timeZero;
}
/**
* first good bin returend in ms
* returned as the absolute value of first-good-bin minus time zero
*/
QString MuonAnalysis::firstGoodBin()
{
return m_uiForm.firstGoodBinFront->text();
}
/**
* According to Plot Options what time should we plot from in ms
* @return time to plot from in ms
*/
double MuonAnalysis::plotFromTime()
{
double retVal;
try
{
retVal = boost::lexical_cast<double>(m_uiForm.timeAxisStartAtInput->text().toStdString());
}
catch (...)
{
retVal = 0.0;
QMessageBox::warning(this,"Mantid - MuonAnalysis", "Number not recognised in Plot Option 'Start at (ms)' input box. Plot from time zero.");
}
return retVal;
}
/**
* According to Plot Options what time should we plot to in ms
* @return time to plot to in ms
*/
double MuonAnalysis::plotToTime()
{
double retVal;
try
{
retVal = boost::lexical_cast<double>(m_uiForm.timeAxisFinishAtInput->text().toStdString());
}
catch (...)
{
retVal = 1.0;
QMessageBox::warning(this,"Mantid - MuonAnalysis", "Number not recognised in Plot Option 'Finish at (ms)' input box. Plot to time=1.0.");
}
return retVal;
}
/**
* Check if grouping in table is consistent with data file
*
* @return empty string if OK otherwise a complaint
*/
std::string MuonAnalysis::isGroupingAndDataConsistent()
{
std::string complaint = "Grouping inconsistent with data file. Plotting disabled.\n";
// should probably farm the getting of matrix workspace out into separate method or store
// as attribute assigned in inputFileChanged
Workspace_sptr workspace_ptr = AnalysisDataService::Instance().retrieve(m_workspace_name);
WorkspaceGroup_sptr wsPeriods = boost::dynamic_pointer_cast<WorkspaceGroup>(workspace_ptr);
MatrixWorkspace_sptr matrix_workspace;
if (wsPeriods)
{
Workspace_sptr workspace_ptr1 = AnalysisDataService::Instance().retrieve(m_workspace_name + "_1");
matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(workspace_ptr1);
}
else
{
matrix_workspace = boost::dynamic_pointer_cast<MatrixWorkspace>(workspace_ptr);
}
int nDet = static_cast<int>(matrix_workspace->getNumberHistograms());
complaint += "Number of spectra in data = " + boost::lexical_cast<std::string>(nDet) + ". ";
int numG = numGroups();
bool returnComplaint = false;
for (int iG = 0; iG < numG; iG++)
{
typedef Poco::StringTokenizer tokenizer;
tokenizer values(m_uiForm.groupTable->item(m_groupToRow[iG],1)->text().toStdString(), ",", tokenizer::TOK_TRIM);
for (int i = 0; i < static_cast<int>(values.count()); i++)
{
std::size_t found= values[i].find("-");
if (found!=std::string::npos)
{
tokenizer aPart(values[i], "-", tokenizer::TOK_TRIM);
int rightInt;
std::stringstream rightRead(aPart[1]);
rightRead >> rightInt;
if ( rightInt > nDet )
{
complaint += " Group-table row " + boost::lexical_cast<std::string>(m_groupToRow[iG]+1) + " refers to spectrum "
+ boost::lexical_cast<std::string>(rightInt) + ".";
returnComplaint = true;
break;
}
}
else
{
if ( (boost::lexical_cast<int>(values[i].c_str()) > nDet) || (boost::lexical_cast<int>(values[i].c_str()) < 1) )
{
complaint += " Group-table row " + boost::lexical_cast<std::string>(m_groupToRow[iG]+1) + " refers to spectrum "
+ values[i] + ".";
returnComplaint = true;
break;
}
}
}
}
if ( returnComplaint )
return complaint;
else
return std::string("");
}
/**
* Check if dublicate ID between different rows
*/
void MuonAnalysis::checkIf_ID_dublicatesInTable(const int row)
{
QTableWidgetItem *item = m_uiForm.groupTable->item(row,1);
// row of IDs to compare against
std::vector<int> idsNew = spectrumIDs(item->text().toStdString());
int numG = numGroups();
int rowInFocus = getGroupNumberFromRow(row);
for (int iG = 0; iG < numG; iG++)
{
if (iG != rowInFocus)
{
std::vector<int> ids = spectrumIDs(m_uiForm.groupTable->item(m_groupToRow[iG],1)->text().toStdString());
for (unsigned int i = 0; i < ids.size(); i++)
{
for (unsigned int j = 0; j < idsNew.size(); j++)
{
if ( ids[i] == idsNew[j] )
{
item->setText(QString("Dublicate ID: " + item->text()));
return;
}
}
}
}
}
}
/**
* Load auto saved values
*/
void MuonAnalysis::loadAutoSavedValues(const QString& group)
{
QSettings prevInstrumentValues;
prevInstrumentValues.beginGroup(group + "instrument");
QString instrumentName = prevInstrumentValues.value("name", "MUSR").toString();
m_uiForm.instrSelector->setCurrentIndex(m_uiForm.instrSelector->findText(instrumentName));
// load Plot Style options
QSettings prevPlotStyle;
prevPlotStyle.beginGroup(group + "plotStyleOptions");
double timeAxisStart = prevPlotStyle.value("timeAxisStart", 0.3).toDouble();
double timeAxisFinish = prevPlotStyle.value("timeAxisFinish", 16.0).toDouble();
m_uiForm.timeAxisStartAtInput->setText(QString::number(timeAxisStart));
m_uiForm.timeAxisFinishAtInput->setText(QString::number(timeAxisFinish));
m_optionTab->setStoredCustomTimeValue(prevPlotStyle.value("customTimeValue").toString());
int timeComboBoxIndex = prevPlotStyle.value("timeComboBoxIndex", 0).toInt();
m_uiForm.timeComboBox->setCurrentIndex(timeComboBoxIndex);
m_optionTab->runTimeComboBox(timeComboBoxIndex);
bool axisAutoScaleOnOff = prevPlotStyle.value("axisAutoScaleOnOff", 1).toBool();
m_uiForm.yAxisAutoscale->setChecked(axisAutoScaleOnOff);
m_optionTab->runyAxisAutoscale(axisAutoScaleOnOff);
QStringList kusse = prevPlotStyle.childKeys();
if ( kusse.contains("yAxisStart") )
{
if( ! m_uiForm.yAxisAutoscale->isChecked() )
{
double yAxisStart = prevPlotStyle.value("yAxisStart").toDouble();
m_uiForm.yAxisMinimumInput->setText(QString::number(yAxisStart));
}
else
{
m_optionTab->setStoredYAxisMinimum(prevPlotStyle.value("yAxisStart").toString());
}
}
if ( kusse.contains("yAxisFinish") )
{
if( ! m_uiForm.yAxisAutoscale->isChecked() )
{
double yAxisFinish = prevPlotStyle.value("yAxisFinish").toDouble();
m_uiForm.yAxisMaximumInput->setText(QString::number(yAxisFinish));
}
else
{
m_optionTab->setStoredYAxisMaximum(prevPlotStyle.value("yAxisFinish").toString());
}
}
// Load Plot Binning Options
QSettings prevPlotBinning;
prevPlotBinning.beginGroup(group + "BinningOptions");
int rebinFixed = prevPlotBinning.value("rebinFixed", 1).toInt();
m_uiForm.optionStepSizeText->setText(QString::number(rebinFixed));
m_uiForm.binBoundaries->setText(prevPlotBinning.value("rebinVariable", 1).toCString());
int rebinComboBoxIndex = prevPlotBinning.value("rebinComboBoxIndex", 0).toInt();
m_uiForm.rebinComboBox->setCurrentIndex(rebinComboBoxIndex);
m_optionTab->runRebinComboBox(rebinComboBoxIndex);
// Load Setting tab options
QSettings prevSettingTabOptions;
prevSettingTabOptions.beginGroup(group + "SettingOptions");
int plotCreationIndex = prevSettingTabOptions.value("plotCreation", 0).toInt();
m_uiForm.plotCreation->setCurrentIndex(plotCreationIndex);
int connectPlotStyleIndex = prevSettingTabOptions.value("connectPlotStyle", 0).toInt();
m_uiForm.connectPlotType->setCurrentIndex(connectPlotStyleIndex);
bool errorBars = prevSettingTabOptions.value("errorBars", 1).toBool();
m_uiForm.showErrorBars->setChecked(errorBars);
bool hideTools = prevSettingTabOptions.value("toolbars", 1).toBool();
m_uiForm.hideToolbars->setChecked(hideTools);
bool hideGraphs = prevSettingTabOptions.value("hiddenGraphs", 1).toBool();
m_uiForm.hideGraphs->setChecked(hideGraphs);
// Load dead time options.
QSettings deadTimeOptions;
deadTimeOptions.beginGroup(group + "DeadTimeOptions");
int deadTimeTypeIndex = deadTimeOptions.value("deadTimes", 0).toInt();
m_uiForm.deadTimeType->setCurrentIndex(deadTimeTypeIndex);
QString savedDeadTimeFile = deadTimeOptions.value("deadTimeFile").toString();
m_uiForm.mwRunDeadTimeFile->setUserInput(savedDeadTimeFile);
if (deadTimeTypeIndex != 2)
m_uiForm.mwRunDeadTimeFile->setVisible(false);
}
/**
* Loads up the options for the fit browser so that it works in a muon analysis tab
*/
void MuonAnalysis::loadFittings()
{
// Title of the fitting dock widget that now lies within the fittings tab. Should be made
// dynamic so that the Chi-sq can be displayed alongside like original fittings widget
m_uiForm.fitBrowser->setWindowTitle("Fit Function");
// Make sure that the window can't be moved or closed within the tab.
m_uiForm.fitBrowser->setFeatures(QDockWidget::NoDockWidgetFeatures);
}
/**
* Allow/disallow loading.
*/
void MuonAnalysis::allowLoading(bool enabled)
{
m_uiForm.nextRun->setEnabled(enabled);
m_uiForm.previousRun->setEnabled(enabled);
m_uiForm.loadCurrent->setEnabled(enabled);
m_uiForm.mwRunFiles->setEnabled(enabled);
}
/**
* Check to see if the appending option is true when the previous button has been pressed and acts accordingly
*/
void MuonAnalysis::checkAppendingPreviousRun()
{
if ( m_uiForm.mwRunFiles->getText().isEmpty() )
{
return;
}
allowLoading(false);
if (m_uiForm.mwRunFiles->getText().contains("-"))
{
setAppendingRun(-1);
}
else
{
//Subtact one from the current run and load
changeRun(-1);
}
}
/**
* Check to see if the appending option is true when the next button has been pressed and acts accordingly
*/
void MuonAnalysis::checkAppendingNextRun()
{
if (m_uiForm.mwRunFiles->getText().isEmpty() )
return;
allowLoading(false);
if (m_uiForm.mwRunFiles->getText().contains("-"))
{
setAppendingRun(1);
}
else
{
//Add one to current run and laod
changeRun(1);
}
}
/**
* This sets up an appending lot of files so that when the user hits enter
* all files within the range will open.
*
* @param inc :: The number to increase the run by, this can be
* -1 if previous has been selected.
*/
void MuonAnalysis::setAppendingRun(int inc)
{
QString filePath("");
// Get hold of the files to increment or decrement the range to.
QStringList currentFiles(m_uiForm.mwRunFiles->getFilenames() );
if (currentFiles.empty())
currentFiles = m_previousFilenames;
// Name and size of the run to change.
QString run("");
int runSize(-1);
// The file number that needs to be incremented or decremented.
int fileNumber(-1);
if (inc < 0) // If the files list only includes one file.
{
fileNumber = 0; // Pick the first file in the list to decrement.
}
else // must be next that has been clicked.
{
fileNumber = currentFiles.size() - 1; // Pick the last file to increment.
}
// File path should be the same for both.
separateMuonFile(filePath, currentFiles[fileNumber], run, runSize);
int fileExtensionSize(currentFiles[fileNumber].size()-currentFiles[fileNumber].find('.') );
QString fileExtension = currentFiles[fileNumber].right(fileExtensionSize);
currentFiles[fileNumber].chop(fileExtensionSize);
int firstRunNumber = currentFiles[fileNumber].right(runSize).toInt();
currentFiles[fileNumber].chop(runSize);
firstRunNumber = firstRunNumber + inc;
QString newRun("");
newRun.setNum(firstRunNumber);
getFullCode(runSize, newRun);
// Increment is positive (next button)
if (inc < 0)
{
// Add the file to the beginning of mwRunFiles text box.
QString lastName = m_previousFilenames[m_previousFilenames.size()-1];
separateMuonFile(filePath, lastName, run, runSize);
getFullCode(runSize, run);
m_uiForm.mwRunFiles->setUserInput(newRun + '-' + run);
}
else // Increment is negative (previous button)
{
// Add the file onto the end of mwRunFiles text box
QString firstName = m_previousFilenames[0];
separateMuonFile(filePath, firstName, run, runSize);
getFullCode(runSize, run);
m_uiForm.mwRunFiles->setUserInput(run + '-' + newRun);
}
}
/**
* Opens up the next file if clicked next or previous on the muon analysis
*
* @param amountToChange :: if clicked next then you need to open the next
* file so 1 is passed, -1 is passed if previous was clicked by the user.
*/
void MuonAnalysis::changeRun(int amountToChange)
{
QString filePath("");
QString currentFile = m_uiForm.mwRunFiles->getFirstFilename();
if ( (currentFile.isEmpty() ) )
currentFile = m_previousFilenames[0];
QString run("");
int runSize(-1);
// If load current run get the correct run number.
if (currentFile.contains("auto") || currentFile.contains("argus0000000"))
{
separateMuonFile(filePath, currentFile, run, runSize);
currentFile = filePath + getGroupName() + ".nxs";
}
separateMuonFile(filePath, currentFile, run, runSize);
int fileExtensionSize(currentFile.size()-currentFile.find('.') );
QString fileExtension(currentFile.right(fileExtensionSize) );
currentFile.chop(fileExtensionSize);
int runNumber = currentFile.right(runSize).toInt();
currentFile.chop(runSize);
runNumber = runNumber + amountToChange;
QString newRun("");
newRun.setNum(runNumber);
getFullCode(runSize, newRun);
if (m_textToDisplay.contains("\\") || m_textToDisplay.contains("/") || m_textToDisplay == "CURRENT RUN")
m_uiForm.mwRunFiles->setUserInput(filePath + currentFile + newRun);
else
m_uiForm.mwRunFiles->setUserInput(newRun);
}
/**
* Seperates the a given file into instrument, code and size of the code.
* i.e c:/data/MUSR0002419.nxs becomes c:/data/, MUSR0002419.nxs, 2419, 7.
*
* @param filePath :: The file path of the data file.
* @param currentFile :: This is the file with path. Can be network path. Return as file with extension.
* @param run :: The run as a string without 0's at the beginning.
* @param runSize :: contains the size of the run number.
*/
void MuonAnalysis::separateMuonFile(QString &filePath, QString ¤tFile, QString &run, int &runSize)
{
int fileStart(-1);
int firstRunDigit(-1);
//Find where the file begins
for (int i = 0; i<currentFile.size(); i++)
{
if(currentFile[i] == '/' || currentFile[i] == '\\') //.isDigit())
{
fileStart = i+1;
}
}
filePath = currentFile.left(fileStart);
currentFile = currentFile.right(currentFile.size() - fileStart);
for (int i = 0; i<currentFile.size(); i++)
{
if(currentFile[i].isDigit()) //.isDigit())
{
firstRunDigit = i;
break;
}
}
runSize = 0;
if (! (firstRunDigit < 0) )
{
//Find where the run number ends
for (int i = firstRunDigit; i<currentFile.size(); i++)
{
if(currentFile[i] == '.')
break;
if(currentFile[i].isDigit())
{
++runSize;
}
}
}
run = currentFile.right(currentFile.size()-firstRunDigit);
run = run.left(runSize);
}
/**
* Adds the 0's back onto the run which were lost when converting it to an integer.
*
* @param originalSize :: The size of the original run before conversion
* @param run :: This is the run after it was incremented or decremented.
*/
void MuonAnalysis::getFullCode(int originalSize, QString & run)
{
while (originalSize > run.size())
{
run = "0" + run;
}
}
/**
* Is called every time when tab gets changed
*
* @param tabNumber The index value of the current tab
*/
void MuonAnalysis::changeTab(int newTabNumber)
{
int oldTabNumber = m_tabNumber;
m_tabNumber = newTabNumber;
// Make sure all toolbars are still not visible. May have brought them back to do a plot.
if (m_uiForm.hideToolbars->isChecked())
setToolbarsHidden(true);
m_uiForm.fitBrowser->setStartX(m_uiForm.timeAxisStartAtInput->text().toDouble());
m_uiForm.fitBrowser->setEndX(m_uiForm.timeAxisFinishAtInput->text().toDouble());
if(oldTabNumber == 3) // Closing DA tab
{
// Say MantidPlot to use default fit prop. browser
emit setFitPropertyBrowser(NULL);
// Remove PP tool from any plots it was attached to
disableAllTools();
// Disconnect to avoid problems when filling list of workspaces in fit prop. browser
disconnect(m_uiForm.fitBrowser, SIGNAL(workspaceNameChanged(const QString&)),
this, SLOT(showPlot(const QString&)));
}
if (newTabNumber == 3) // Opening DA tab
{
// Say MantidPlot to use Muon Analysis fit prop. browser
emit setFitPropertyBrowser(m_uiForm.fitBrowser);
// Show connected plot and attach PP tool to it (if has been assigned)
if(m_currentDataName != NOT_AVAILABLE)
showPlot(m_currentDataName);
// In future, when workspace gets changed, show its plot and attach PP tool to it
connect(m_uiForm.fitBrowser, SIGNAL(workspaceNameChanged(const QString&)),
this, SLOT(showPlot(const QString&)), Qt::QueuedConnection);
}
else if(newTabNumber == 4) // Opening results table tab
{
m_resultTableTab->populateTables(m_uiForm.fitBrowser->getWorkspaceNames());
}
}
/**
* Set up the signals and slots for auto updating the plots
*/
void MuonAnalysis::connectAutoUpdate()
{
// Home tab Auto Updates
connect(m_uiForm.timeZeroFront, SIGNAL(returnPressed ()), this, SLOT(homeTabUpdatePlot()));
connect(m_uiForm.firstGoodBinFront, SIGNAL(returnPressed ()), this, SLOT(homeTabUpdatePlot()));
connect(m_uiForm.homePeriodBox1, SIGNAL(currentIndexChanged(int)), this, SLOT(firstPeriodSelectionChanged()));
connect(m_uiForm.homePeriodBoxMath, SIGNAL(currentIndexChanged(int)), this, SLOT(homeTabUpdatePlot()));
connect(m_uiForm.homePeriodBox2, SIGNAL(currentIndexChanged(int)), this, SLOT(secondPeriodSelectionChanged()));
connect(m_uiForm.frontPlotFuncs, SIGNAL(currentIndexChanged(int)), this, SLOT(changeHomeFunction()));
connect(m_uiForm.frontAlphaNumber, SIGNAL(returnPressed ()), this, SLOT(homeTabUpdatePlot()));
// Grouping tab Auto Updates
// Group Table
connect(m_uiForm.groupTablePlotChoice, SIGNAL(currentIndexChanged(int)), this, SLOT(groupTabUpdateGroup()));
// Pair Table (Guess Alpha button attached in another function)
connect(m_uiForm.pairTablePlotChoice, SIGNAL(currentIndexChanged(int)), this, SLOT(groupTabUpdatePair()));
// Settings tab Auto Updates
connect(m_uiForm.binBoundaries, SIGNAL(editingFinished()), this, SLOT(settingsTabUpdatePlot()));
connect(m_uiForm.optionStepSizeText, SIGNAL(editingFinished()), this, SLOT(settingsTabUpdatePlot()));
connect(m_optionTab, SIGNAL(settingsTabUpdatePlot()), this, SLOT(settingsTabUpdatePlot()));
connect(m_optionTab, SIGNAL(plotStyleChanged()), this, SLOT(updateCurrentPlotStyle()));
}
void MuonAnalysis::changeHomeFunction()
{
if (m_tabNumber == 0)
{
m_uiForm.groupTablePlotChoice->setCurrentIndex(m_uiForm.frontPlotFuncs->currentIndex());
homeTabUpdatePlot();
}
}
void MuonAnalysis::firstPeriodSelectionChanged()
{
if ( m_uiForm.homePeriodBox2->currentText() == m_uiForm.homePeriodBox1->currentText() )
{
m_uiForm.homePeriodBox2->setCurrentIndex(0);
}
else
homeTabUpdatePlot();
}
void MuonAnalysis::secondPeriodSelectionChanged()
{
if ( m_uiForm.homePeriodBox2->currentText() == m_uiForm.homePeriodBox1->currentText() )
{
m_uiForm.homePeriodBox2->setCurrentIndex(0);
}
else
homeTabUpdatePlot();
}
void MuonAnalysis::homeTabUpdatePlot()
{
if (isAutoUpdateEnabled() && m_tabNumber == 0 && m_loaded)
runFrontPlotButton();
}
void MuonAnalysis::groupTabUpdateGroup()
{
if (m_tabNumber == 1)
{
if (m_uiForm.frontPlotFuncs->count() <= 1)
{
m_uiForm.frontGroupGroupPairComboBox->setCurrentIndex(0);
updateFront();
}
m_uiForm.frontPlotFuncs->setCurrentIndex(m_uiForm.groupTablePlotChoice->currentIndex());
if (isAutoUpdateEnabled() && m_loaded == true)
runGroupTablePlotButton();
}
}
void MuonAnalysis::groupTabUpdatePair()
{
if (isAutoUpdateEnabled() && m_tabNumber == 1 && m_loaded == true)
runPairTablePlotButton();
}
void MuonAnalysis::settingsTabUpdatePlot()
{
if (isAutoUpdateEnabled() && m_tabNumber == 2 && m_loaded == true)
runFrontPlotButton();
}
/**
* Updates the style of the current plot according to actual parameters on settings tab.
*/
void MuonAnalysis::updateCurrentPlotStyle()
{
if (isAutoUpdateEnabled() && m_currentDataName != NOT_AVAILABLE)
{
if(plotExists(m_currentDataName))
{
// TODO: This index magic wouldn't be needed if we'd store only a single group in a workspace.
// Get selected group index
int index = m_uiForm.frontGroupGroupPairComboBox->currentIndex();
// Check if pair is selected
if(index >= numGroups())
index = 0;
setPlotStyle(m_currentDataName, getPlotStyleParams(m_currentDataName, index));
}
else
runFrontPlotButton();
}
}
bool MuonAnalysis::isAutoUpdateEnabled()
{
int choice(m_uiForm.plotCreation->currentIndex());
return (choice == 0 || choice == 1);
}
/**
* Executed when interface gets hidden or closed
*/
void MuonAnalysis::hideEvent(QHideEvent *e)
{
// Show the toolbars
if (m_uiForm.hideToolbars->isChecked())
setToolbarsHidden(false);
// If closed while on DA tab, reassign fit property browser to default one
if(m_tabNumber == 3)
emit setFitPropertyBrowser(NULL);
// Delete the peak picker tool because it is no longer needed.
disableAllTools();
e->accept();
}
/**
* Executed when interface gets shown
*/
void MuonAnalysis::showEvent(QShowEvent *e)
{
const std::string facility = ConfigService::Instance().getFacility().name();
if (facility != "ISIS")
{
QMessageBox::critical(this, "Unsupported facility", QString("Only the ISIS facility is supported by this interface.\n")
+ "Select ISIS as your default facility in View->Preferences...->Mantid to continue.");
m_uiForm.loadCurrent->setDisabled(true);
}
else
{
m_uiForm.loadCurrent->setDisabled(false);
}
// Hide the toolbars
if (m_uiForm.hideToolbars->isChecked() )
setToolbarsHidden(true);
e->accept();
}
/**
* Hide/show MantidPlot toolbars.
* @param hidden If true, toolbars will be hidden, if false - shown
*/
void MuonAnalysis::setToolbarsHidden(bool hidden)
{
if (hidden == true)
runPythonCode("setToolbarsVisible(False)");
else
runPythonCode("setToolbarsVisible(True)");
}
/**
* Change what type of deadtime to use and the options available for the user's choice.
*
* @param choice :: The current index of dead time type combo box.
*/
void MuonAnalysis::changeDeadTimeType(int choice)
{
m_deadTimesChanged = true;
if (choice == 0 || choice == 1) // if choice == none || choice == from file
{
m_uiForm.mwRunDeadTimeFile->setVisible(false);
homeTabUpdatePlot();
}
else // choice must be from workspace
{
m_uiForm.mwRunDeadTimeFile->setVisible(true);
m_uiForm.mwRunDeadTimeFile->setUserInput("");
}
QSettings group;
group.beginGroup(m_settingsGroup + "DeadTimeOptions");
group.setValue("deadTimes", choice);
}
/**
* If the user selects/changes the file to be used to apply the dead times then
* see if the plot needs updating and make sure next time the user plots that the
* dead times are applied.
*/
void MuonAnalysis::deadTimeFileSelected()
{
if(!m_uiForm.mwRunDeadTimeFile->isValid())
return;
// Remember the filename for the next time interface is opened
QSettings group;
group.beginGroup(m_settingsGroup + "DeadTimeOptions");
group.setValue("deadTimeFile", m_uiForm.mwRunDeadTimeFile->getText());
m_deadTimesChanged = true;
homeTabUpdatePlot();
}
}//namespace MantidQT
}//namespace CustomInterfaces