Commit aa8478a6 authored by Roman Tolchenov's avatar Roman Tolchenov
Browse files

Re #6159. Refactored MaskTab to use the mask workspace

parent 514256fe
......@@ -38,6 +38,14 @@ namespace API
virtual const std::string id() const { return "IMaskWorkspace"; }
/// Total number of masked pixels
virtual std::size_t getNumberMasked() const = 0;
/// Check if a detector is masked
virtual bool isMasked(const detid_t detectorID) const = 0;
/// Check if all detectors in a set are masked
virtual bool isMasked(const std::set<detid_t> &detectorIDs) const = 0;
/// Set / remove mask of a detector
virtual void setMasked(const detid_t detectorID, const bool mask=true) = 0;
/// Set / remove masks of all detectors in a set
virtual void setMasked(const std::set<detid_t> &detectorIDs, const bool mask=true) = 0;
};
///shared pointer to the matrix workspace base class
......
......@@ -86,9 +86,7 @@ namespace Mantid
const int nHist = static_cast<int>(inputWS->getNumberHistograms());
// Create a new workspace for the results, copy from the input to ensure that we copy over the instrument and current masking
maskWS = DataObjects::MaskWorkspace_sptr(new DataObjects::MaskWorkspace(instr, true));
maskWS->initialize(nHist, 1, 1);
WorkspaceFactory::Instance().initializeFromParent(inputWS, maskWS, false);
maskWS = DataObjects::MaskWorkspace_sptr(new DataObjects::MaskWorkspace(inputWS));
maskWS->setTitle(inputWS->getTitle());
Progress prog(this,0.0,1.0,nHist);
......
......@@ -19,6 +19,7 @@ namespace DataObjects
MaskWorkspace(std::size_t numvectors);
MaskWorkspace(Mantid::Geometry::Instrument_const_sptr instrument,
const bool includeMonitors=false);
MaskWorkspace(const API::MatrixWorkspace_const_sptr parent);
~MaskWorkspace();
bool isMasked(const detid_t detectorID) const;
......
......@@ -35,6 +35,7 @@ namespace DataObjects
public:
SpecialWorkspace2D();
SpecialWorkspace2D(Geometry::Instrument_const_sptr inst, const bool includeMonitors=false);
SpecialWorkspace2D(API::MatrixWorkspace_const_sptr parent);
~SpecialWorkspace2D();
/** Gets the name of the workspace type
......
......@@ -55,7 +55,18 @@ namespace DataObjects
MaskWorkspace::MaskWorkspace(Mantid::Geometry::Instrument_const_sptr instrument, const bool includeMonitors)
: SpecialWorkspace2D(instrument, includeMonitors), m_hasInstrument(true)
{
this->clearMask();
this->clearMask();
}
/**
* Constructor - using a MatrixWorkspace.
* @param[in] A matrix workspace that is the base for this workspace. It must have an instrument.
* @return MaskWorkspace
*/
MaskWorkspace::MaskWorkspace(const API::MatrixWorkspace_const_sptr parent)
: SpecialWorkspace2D(parent), m_hasInstrument(true)
{
this->clearMask();
}
//--------------------------------------------------------------------------
......
......@@ -4,6 +4,8 @@
#include "MantidAPI/SpectraDetectorMap.h"
#include "MantidAPI/SpectraAxis.h"
#include <fstream>
using Mantid::API::SpectraAxis;
using Mantid::API::SpectraDetectorMap;
using std::set;
......@@ -55,6 +57,28 @@ namespace DataObjects
}
}
//----------------------------------------------------------------------------------------------
/** Constructor, building from a MatrixWorkspace
*
* @param parent :: input workspace that is the base for this workspace
* @return created SpecialWorkspace2D
*/
SpecialWorkspace2D::SpecialWorkspace2D(API::MatrixWorkspace_const_sptr parent)
{
this->init(parent->getNumberHistograms(), 1, 1);
API::WorkspaceFactory::Instance().initializeFromParent(parent, API::MatrixWorkspace_sptr(this,Mantid::NoDeleting()), false);
// Make the mapping, which will be used for speed later.
detID_to_WI.clear();
for (size_t wi=0; wi<m_noVectors; wi++)
{
set<detid_t> dets = getSpectrum(wi)->getDetectorIDs();
for (auto det = dets.begin(); det != dets.end(); ++det)
{
detID_to_WI[*det] = wi;
}
}
}
//----------------------------------------------------------------------------------------------
/** Destructor
......
......@@ -168,6 +168,69 @@ MatrixWorkspace_const_sptr InstrumentActor::getWorkspace() const
return shared_workspace;
}
/** Returns the mask workspace relating to this instrument view as a MatrixWorkspace
*/
MatrixWorkspace_sptr InstrumentActor::getMaskMatrixWorkspace() const
{
if ( !m_maskWorkspace )
{
initMaskHelper();
}
return m_maskWorkspace;
}
/**
* Returns the mask workspace relating to this instrument view as a IMaskWorkspace.
* Guarantees to return a valid pointer
*/
IMaskWorkspace_sptr InstrumentActor::getMaskWorkspace() const
{
if ( !m_maskWorkspace )
{
initMaskHelper();
}
return boost::dynamic_pointer_cast<IMaskWorkspace>( m_maskWorkspace );
}
/**
* Returns the mask workspace relating to this instrument view as a IMaskWorkspace
* if it exists or empty pointer if it doesn't.
*/
IMaskWorkspace_sptr InstrumentActor::getMaskWorkspaceIfExists() const
{
if ( !m_maskWorkspace ) return IMaskWorkspace_sptr();
return boost::dynamic_pointer_cast<IMaskWorkspace>( m_maskWorkspace );
}
/**
* Apply mask stored in the helper mask workspace to the data workspace.
*/
void InstrumentActor::applyMaskWorkspace()
{
if ( !m_maskWorkspace ) return;
Mantid::API::IAlgorithm * alg = Mantid::API::FrameworkManager::Instance().createAlgorithm("MaskDetectors",-1);
alg->setPropertyValue( "Workspace", getWorkspace()->name() );
alg->setProperty( "MaskedWorkspace", m_maskWorkspace );
alg->execute();
}
/**
* Removes the mask workspace.
*/
void InstrumentActor::clearMaskWorkspace()
{
bool needColorRecalc = false;
if ( m_maskWorkspace )
{
needColorRecalc = getMaskWorkspace()->getNumberMasked() > 0;
}
m_maskWorkspace.reset();
if ( needColorRecalc )
{
resetColors();
}
}
Instrument_const_sptr InstrumentActor::getInstrument() const
{
Instrument_const_sptr retval;
......@@ -311,6 +374,7 @@ void InstrumentActor::resetColors()
auto shared_workspace = getWorkspace();
Instrument_const_sptr inst = getInstrument();
IMaskWorkspace_sptr mask = getMaskWorkspaceIfExists();
//PARALLEL_FOR1(m_workspace)
for (int iwi=0; iwi < int(m_specIntegrs.size()); iwi++)
......@@ -321,7 +385,16 @@ void InstrumentActor::resetColors()
{
// Find if the detector is masked
const std::set<detid_t>& dets = shared_workspace->getSpectrum(wi)->getDetectorIDs();
bool masked = inst->isDetectorMasked(dets);
bool masked = false;
if ( mask )
{
masked = mask->isMasked( dets );
}
else
{
masked = inst->isDetectorMasked(dets);
}
if (masked)
{
......@@ -515,7 +588,7 @@ void InstrumentActor::setAutoscaling(bool on)
/**
* Initialize the helper mask workspace with the mask from the data workspace.
*/
void InstrumentActor::initMaskHelper()
void InstrumentActor::initMaskHelper() const
{
if ( m_maskWorkspace ) return;
// extract the mask (if any) from the data to the mask workspace
......@@ -527,7 +600,7 @@ void InstrumentActor::initMaskHelper()
try
{
m_maskWorkspace = boost::dynamic_pointer_cast<Mantid::API::IMaskWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve(maskName));
m_maskWorkspace = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve(maskName));
Mantid::API::AnalysisDataService::Instance().remove( maskName );
}
catch( ... )
......
......@@ -80,6 +80,10 @@ public:
boost::shared_ptr<const Mantid::Geometry::Instrument> getInstrument() const;
boost::shared_ptr<const Mantid::API::MatrixWorkspace> getWorkspace() const;
boost::shared_ptr<Mantid::API::MatrixWorkspace> getMaskMatrixWorkspace() const;
boost::shared_ptr<Mantid::API::IMaskWorkspace> getMaskWorkspace() const;
void applyMaskWorkspace();
void clearMaskWorkspace();
const MantidColorMap & getColorMap() const;
void loadColorMap(const QString& ,bool reset_colors = true);
......@@ -123,7 +127,7 @@ public:
/* Masking */
void initMaskHelper();
void initMaskHelper() const;
signals:
void colorMapChanged();
protected:
......@@ -133,11 +137,12 @@ protected:
void saveSettings();
size_t push_back_detid(Mantid::detid_t)const;
boost::shared_ptr<Mantid::API::IMaskWorkspace> getMaskWorkspaceIfExists() const;
/// The workspace whose data are shown
const boost::weak_ptr<const Mantid::API::MatrixWorkspace> m_workspace;
/// The helper masking workspace keeping the mask build in the mask tab but not applied to the data workspace.
boost::shared_ptr<Mantid::API::IMaskWorkspace> m_maskWorkspace;
mutable boost::shared_ptr<Mantid::API::MatrixWorkspace> m_maskWorkspace;
/// The colormap
MantidColorMap m_colorMap;
/// integrated spectra
......
......@@ -1468,6 +1468,7 @@ void InstrumentWindow::updateInstrumentView()
/// Recalculate the colours and redraw the instrument view
void InstrumentWindow::updateInstrumentDetectors()
{
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
if ( isGLEnabled() )
{
m_InstrumentDisplay->updateDetectors();
......@@ -1476,6 +1477,7 @@ void InstrumentWindow::updateInstrumentDetectors()
{
m_simpleDisplay->updateDetectors();
}
QApplication::restoreOverrideCursor();
}
/**
......
......@@ -6,7 +6,9 @@
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/FrameworkManager.h"
#include "MantidAPI/IMaskWorkspace.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/Strings.h"
#include "qttreepropertybrowser.h"
#include "qtpropertymanager.h"
......@@ -49,9 +51,9 @@ InstrumentWindowMaskTab::InstrumentWindowMaskTab(InstrumentWindow* instrWindow):
QFrame(instrWindow),
m_instrumentWindow(instrWindow),
m_activity(Select),
m_hasMaskToApply(false),
m_userEditing(true)
{
m_instrumentDisplay = m_instrumentWindow->getInstrumentDisplay();
// main layout
QVBoxLayout* layout=new QVBoxLayout(this);
......@@ -151,29 +153,30 @@ m_userEditing(true)
m_save_as_file_include = new QAction("As ROI to file",this);
connect(m_save_as_file_include,SIGNAL(activated()),this,SLOT(saveInvertedMaskToFile()));
QPushButton* saveButton = new QPushButton("Save");
m_saveButton = new QPushButton("Save");
QMenu* saveMenu = new QMenu(this);
saveMenu->addAction(m_save_as_workspace_include);
saveMenu->addAction(m_save_as_workspace_exclude);
saveMenu->addAction(m_save_as_file_include);
saveMenu->addAction(m_save_as_file_exclude);
saveButton->setMenu(saveMenu);
m_saveButton->setMenu(saveMenu);
QGridLayout* buttons = new QGridLayout();
buttons->addWidget(m_apply,0,0);
buttons->addWidget(m_clear_all,0,1);
buttons->addWidget(saveButton,1,0,1,2);
buttons->addWidget(m_saveButton,1,0,1,2);
layout->addLayout(buttons);
}
void InstrumentWindowMaskTab::init()
{
connect(m_instrumentDisplay->getSurface(),SIGNAL(shapeCreated()),this,SLOT(shapeCreated()));
connect(m_instrumentDisplay->getSurface(),SIGNAL(shapeSelected()),this,SLOT(shapeSelected()));
connect(m_instrumentDisplay->getSurface(),SIGNAL(shapesDeselected()),this,SLOT(shapesDeselected()));
connect(m_instrumentDisplay->getSurface(),SIGNAL(shapeChanged()),this,SLOT(shapeChanged()));
m_instrumentWindow->getInstrumentActor()->initMaskHelper();
connect(m_instrumentWindow->getSurface(),SIGNAL(shapeCreated()),this,SLOT(shapeCreated()));
connect(m_instrumentWindow->getSurface(),SIGNAL(shapeSelected()),this,SLOT(shapeSelected()));
connect(m_instrumentWindow->getSurface(),SIGNAL(shapesDeselected()),this,SLOT(shapesDeselected()));
connect(m_instrumentWindow->getSurface(),SIGNAL(shapeChanged()),this,SLOT(shapeChanged()));
enableApply( m_instrumentWindow->getSurface()->hasMasks() );
}
void InstrumentWindowMaskTab::setActivity()
......@@ -183,42 +186,43 @@ void InstrumentWindowMaskTab::setActivity()
if (m_move->isChecked())
{
m_activity = Move;
m_instrumentDisplay->getSurface()->setInteractionModeMove();
m_instrumentWindow->getSurface()->setInteractionModeMove();
}
else if (m_pointer->isChecked())
{
m_activity = Select;
m_instrumentDisplay->getSurface()->setInteractionModeDraw();
m_instrumentWindow->getSurface()->setInteractionModeDraw();
}
else if (m_ellipse->isChecked())
{
m_activity = DrawEllipse;
m_instrumentDisplay->getSurface()->startCreatingShape2D("ellipse",borderColor,fillColor);
m_instrumentDisplay->getSurface()->setInteractionModeDraw();
m_instrumentWindow->getSurface()->startCreatingShape2D("ellipse",borderColor,fillColor);
m_instrumentWindow->getSurface()->setInteractionModeDraw();
}
else if (m_rectangle->isChecked())
{
m_activity = DrawEllipse;
m_instrumentDisplay->getSurface()->startCreatingShape2D("rectangle",borderColor,fillColor);
m_instrumentDisplay->getSurface()->setInteractionModeDraw();
m_instrumentWindow->getSurface()->startCreatingShape2D("rectangle",borderColor,fillColor);
m_instrumentWindow->getSurface()->setInteractionModeDraw();
}
else if (m_ring_ellipse->isChecked())
{
m_activity = DrawEllipse;
m_instrumentDisplay->getSurface()->startCreatingShape2D("ring ellipse",borderColor,fillColor);
m_instrumentDisplay->getSurface()->setInteractionModeDraw();
m_instrumentWindow->getSurface()->startCreatingShape2D("ring ellipse",borderColor,fillColor);
m_instrumentWindow->getSurface()->setInteractionModeDraw();
}
else if (m_ring_rectangle->isChecked())
{
m_activity = DrawEllipse;
m_instrumentDisplay->getSurface()->startCreatingShape2D("ring rectangle",borderColor,fillColor);
m_instrumentDisplay->getSurface()->setInteractionModeDraw();
m_instrumentWindow->getSurface()->startCreatingShape2D("ring rectangle",borderColor,fillColor);
m_instrumentWindow->getSurface()->setInteractionModeDraw();
}
}
void InstrumentWindowMaskTab::shapeCreated()
{
m_pointer->setChecked(true);
setSelectActivity();
enableApply(true);
}
void InstrumentWindowMaskTab::shapeSelected()
......@@ -235,31 +239,39 @@ void InstrumentWindowMaskTab::shapeChanged()
{
if (!m_left) return; // check that everything is ok
m_userEditing = false; // this prevents resetting shape proeprties by doubleChanged(...)
QRectF rect = m_instrumentDisplay->getSurface()->getCurrentBoundingRect();
QRectF rect = m_instrumentWindow->getSurface()->getCurrentBoundingRect();
m_doubleManager->setValue(m_left,rect.left());
m_doubleManager->setValue(m_top,rect.top());
m_doubleManager->setValue(m_right,rect.right());
m_doubleManager->setValue(m_bottom,rect.bottom());
for(QMap<QtProperty *,QString>::iterator it = m_doublePropertyMap.begin(); it != m_doublePropertyMap.end(); ++it)
{
m_doubleManager->setValue(it.key(),m_instrumentDisplay->getSurface()->getCurrentDouble(it.value()));
m_doubleManager->setValue(it.key(),m_instrumentWindow->getSurface()->getCurrentDouble(it.value()));
}
for(QMap<QString,QtProperty *>::iterator it = m_pointPropertyMap.begin(); it != m_pointPropertyMap.end(); ++it)
{
QtProperty* prop = it.value();
QList<QtProperty*> subs = prop->subProperties();
if (subs.size() != 2) continue;
QPointF p = m_instrumentDisplay->getSurface()->getCurrentPoint(it.key());
QPointF p = m_instrumentWindow->getSurface()->getCurrentPoint(it.key());
m_doubleManager->setValue(subs[0],p.x());
m_doubleManager->setValue(subs[1],p.y());
}
m_userEditing = true;
}
/**
* Removes the mask shapes from the screen.
*/
void InstrumentWindowMaskTab::clearShapes()
{
m_instrumentWindow->getSurface()->clearMask();
}
void InstrumentWindowMaskTab::showEvent (QShowEvent *)
{
setActivity();
m_instrumentDisplay->setMouseTracking(true);
m_instrumentWindow->setMouseTracking(true);
}
void InstrumentWindowMaskTab::clearProperties()
......@@ -292,7 +304,7 @@ void InstrumentWindowMaskTab::setProperties()
boundingRectGroup->addSubProperty(m_bottom);
// point properties
QStringList pointProperties = m_instrumentDisplay->getSurface()->getCurrentPointNames();
QStringList pointProperties = m_instrumentWindow->getSurface()->getCurrentPointNames();
foreach(QString name,pointProperties)
{
QtProperty* point = m_groupManager->addProperty(name);
......@@ -307,7 +319,7 @@ void InstrumentWindowMaskTab::setProperties()
}
// double properties
QStringList doubleProperties = m_instrumentDisplay->getSurface()->getCurrentDoubleNames();
QStringList doubleProperties = m_instrumentWindow->getSurface()->getCurrentDoubleNames();
foreach(QString name,doubleProperties)
{
QtProperty* prop = m_doubleManager->addProperty(name);
......@@ -325,14 +337,14 @@ void InstrumentWindowMaskTab::doubleChanged(QtProperty* prop)
{
QRectF rect(QPointF(m_doubleManager->value(m_left),m_doubleManager->value(m_top)),
QPointF(m_doubleManager->value(m_right),m_doubleManager->value(m_bottom)));
m_instrumentDisplay->getSurface()->setCurrentBoundingRect(rect);
m_instrumentWindow->getSurface()->setCurrentBoundingRect(rect);
}
else
{
QString name = m_doublePropertyMap[prop];
if (!name.isEmpty())
{
m_instrumentDisplay->getSurface()->setCurrentDouble(name,m_doubleManager->value(prop));
m_instrumentWindow->getSurface()->setCurrentDouble(name,m_doubleManager->value(prop));
}
else
{
......@@ -343,74 +355,60 @@ void InstrumentWindowMaskTab::doubleChanged(QtProperty* prop)
QList<QtProperty*> subs = point_prop->subProperties();
if (subs.size() != 2) return;
QPointF p(m_doubleManager->value(subs[0]),m_doubleManager->value(subs[1]));
m_instrumentDisplay->getSurface()->setCurrentPoint(name,p);
m_instrumentWindow->getSurface()->setCurrentPoint(name,p);
}
}
}
m_instrumentDisplay->update();
m_instrumentWindow->update();
}
/**
* Apply the constructed mask to the data workspace. This operation cannot be reverted.
*/
void InstrumentWindowMaskTab::applyMask()
{
storeMask();
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
m_pointer->setChecked(true);
setActivity();
m_instrumentDisplay->repaint(); // to refresh the pick image
QList<int> dets;
m_instrumentDisplay->getSurface()->getMaskedDetectors(dets);
if (!dets.isEmpty())
{
QStringList detList;
foreach(int id,dets)
{
try {
detList << QString::number(m_instrumentWindow->getInstrumentActor()->getWorkspaceIndex(id));
} catch (Mantid::Kernel::Exception::NotFoundError &) {
continue; // Detector doesn't have a workspace index relating to it
}
}
if ( !detList.empty() )
{
QString param_list = "Workspace=%1;WorkspaceIndexList=%2";
param_list = param_list.arg(m_instrumentWindow->getWorkspaceName(),detList.join(","));
emit executeAlgorithm("MaskDetectors",param_list);
}
}
clearMask();
m_instrumentWindow->getInstrumentActor()->applyMaskWorkspace();
enableApply(false);
QApplication::restoreOverrideCursor();
}
/**
* Remove all masking that has not been applied to the data workspace.
*/
void InstrumentWindowMaskTab::clearMask()
{
m_instrumentDisplay->getSurface()->clearMask();
m_instrumentDisplay->update();
clearShapes();
m_instrumentWindow->getInstrumentActor()->clearMaskWorkspace();
m_instrumentWindow->updateInstrumentView();
enableApply(false);
}
/*
* parameters
* @invertMask: if true, the selected mask will be inverted
* if false, the mask will be used as is
/**
* Create a MaskWorkspace from the mask defined in this tab.
* @param invertMask :: if true, the selected mask will be inverted; if false, the mask will be used as is
* @param temp :: Set true to create a temporary workspace with a fixed name. If false the name will be unique.
*/
Mantid::API::MatrixWorkspace_sptr InstrumentWindowMaskTab::createMaskWorkspace(bool invertMask)
Mantid::API::MatrixWorkspace_sptr InstrumentWindowMaskTab::createMaskWorkspace(bool invertMask, bool temp)
{
m_instrumentDisplay->repaint(); // to refresh the pick image
Mantid::API::MatrixWorkspace_const_sptr inputWS = m_instrumentWindow->getInstrumentActor()->getWorkspace();
m_instrumentWindow->updateInstrumentView(); // to refresh the pick image
Mantid::API::MatrixWorkspace_sptr inputWS = m_instrumentWindow->getInstrumentActor()->getMaskMatrixWorkspace();
Mantid::API::MatrixWorkspace_sptr outputWS;
const std::string outputWorkspaceName = generateMaskWorkspaceName(temp);
Mantid::API::IAlgorithm * alg = Mantid::API::FrameworkManager::Instance().createAlgorithm("ExtractMask",-1);
alg->setPropertyValue("InputWorkspace", inputWS->name());
alg->setPropertyValue("OutputWorkspace","MaskWorkspace");
alg->setProperty("InputWorkspace", inputWS);
alg->setPropertyValue("OutputWorkspace",outputWorkspaceName);
alg->execute();
outputWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve("MaskWorkspace"));
outputWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve( outputWorkspaceName ));
if (invertMask)
{
Mantid::API::IAlgorithm * invertAlg = Mantid::API::FrameworkManager::Instance().createAlgorithm("BinaryOperateMasks",-1);
invertAlg->setPropertyValue("InputWorkspace1", "MaskWorkspace");
invertAlg->setPropertyValue("OutputWorkspace", "MaskWorkspace");
invertAlg->setPropertyValue("InputWorkspace1", outputWorkspaceName);
invertAlg->setPropertyValue("OutputWorkspace", outputWorkspaceName);
invertAlg->setPropertyValue("OperationType", "NOT");
invertAlg->execute();
......@@ -444,38 +442,41 @@ void InstrumentWindowMaskTab::saveMaskToFile()
saveMaskingToFile(false);
}
/**
* Save the constructed mask to a workspace with unique name of type "MaskWorkspace_#".
* The mask is not applied to the data workspace being displayed.
* @param invertMask :: if true, the selected mask will be inverted; if false, the mask will be used as is
*/
void InstrumentWindowMaskTab::saveMaskingToWorkspace(bool invertMask)
{
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
// Make sure we have applied the Mask
applyMask();
// Make sure we have stored the Mask in the helper MaskWorkspace