Newer
Older
Russell Taylor
committed
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
Russell Taylor
committed
#include "MantidDataHandling/MaskDetectors.h"
#include "MantidDataObjects/EventWorkspace.h"
Russell Taylor
committed
#include "MantidAPI/SpectraDetectorMap.h"
#include "MantidKernel/ArrayProperty.h"
Russell Taylor
committed
#include <set>
Russell Taylor
committed
namespace Mantid
{
namespace DataHandling
{
// Register the algorithm into the algorithm factory
Russell Taylor
committed
DECLARE_ALGORITHM(MaskDetectors)
Russell Taylor
committed
Janik Zikovsky
committed
/// Sets documentation strings for this algorithm
void MaskDetectors::initDocs()
{
this->setWikiSummary("An algorithm to mask a detector, or set of detectors, as not to be used. The workspace spectra associated with those detectors are zeroed. ");
this->setOptionalMessage("An algorithm to mask a detector, or set of detectors, as not to be used. The workspace spectra associated with those detectors are zeroed.");
}
Russell Taylor
committed
using namespace Kernel;
using namespace API;
Gigg, Martyn Anthony
committed
using Geometry::Instrument;
Gigg, Martyn Anthony
committed
using Geometry::IDetector_sptr;
using namespace DataObjects;
Russell Taylor
committed
/// (Empty) Constructor
Russell Taylor
committed
MaskDetectors::MaskDetectors() {}
Russell Taylor
committed
/// Destructor
Russell Taylor
committed
MaskDetectors::~MaskDetectors() {}
Russell Taylor
committed
Russell Taylor
committed
void MaskDetectors::init()
Russell Taylor
committed
{
Steve Williams
committed
declareProperty(
new WorkspaceProperty<>("Workspace","", Direction::InOut),
"The name of the workspace that will be used as input and\n"
Steve Williams
committed
"output for the algorithm" );
declareProperty(new ArrayProperty<int>("SpectraList"),
"A comma separated list or array containing a list of spectra to\n"
"mask (DetectorList and WorkspaceIndexList are ignored if this\n"
Steve Williams
committed
"is set)" );
declareProperty(new ArrayProperty<int>("DetectorList"),
"A comma separated list or array containing a list of detector ID's\n"
Steve Williams
committed
"to mask (WorkspaceIndexList is ignored if this is set)" );
declareProperty(new ArrayProperty<int>("WorkspaceIndexList"),
"A comma separated list or array containing the workspace indices\n"
Steve Williams
committed
"to mask" );
Gigg, Martyn Anthony
committed
declareProperty(
new WorkspaceProperty<>("MaskedWorkspace","",Direction::Input, true),
"If given, the masking from this workspace will be copied.");
Russell Taylor
committed
}
Russell Taylor
committed
void MaskDetectors::exec()
Russell Taylor
committed
{
// Get the input workspace
const MatrixWorkspace_sptr WS = getProperty("Workspace");
Russell Taylor
committed
// Get the size of the vectors
Russell Taylor
committed
const int vectorSize = WS->blocksize();
Russell Taylor
committed
//Is it an event workspace?
EventWorkspace_sptr eventWS = boost::dynamic_pointer_cast<EventWorkspace>(WS);
Steve Williams
committed
std::vector<int> indexList = getProperty("WorkspaceIndexList");
std::vector<int> spectraList = getProperty("SpectraList");
const std::vector<int> detectorList = getProperty("DetectorList");
Gigg, Martyn Anthony
committed
const MatrixWorkspace_sptr prevMasking = getProperty("MaskedWorkspace");
Russell Taylor
committed
Gigg, Martyn Anthony
committed
//each one of these values is optional but the user can't leave all four blank
if ( indexList.empty() && spectraList.empty() && detectorList.empty() && !prevMasking )
Russell Taylor
committed
{
Gigg, Martyn Anthony
committed
g_log.information(name() + ": There is nothing to mask, the index, spectra, "
"detector lists and masked workspace properties are all empty");
Steve Williams
committed
return;
Russell Taylor
committed
}
Russell Taylor
committed
Gigg, Martyn Anthony
committed
// Check the provided workspace has the same number of spectra as the input
if( prevMasking && prevMasking->getNumberHistograms() != WS->getNumberHistograms() )
{
throw std::runtime_error("Size mismatch between two input workspaces.");
}
Russell Taylor
committed
// If the spectraList property has been set, need to loop over the workspace looking for the
// appropriate spectra number and adding the indices they are linked to the list to be processed
Steve Williams
committed
if ( ! spectraList.empty() )
Russell Taylor
committed
{
Russell Taylor
committed
fillIndexListFromSpectra(indexList,spectraList,WS);
}// End dealing with spectraList
Steve Williams
committed
else if ( ! detectorList.empty() )
Gigg, Martyn Anthony
committed
{
// Convert from detectors to spectra numbers
Russell Taylor
committed
std::vector<int> mySpectraList = WS->spectraMap().getSpectra(detectorList);
Russell Taylor
committed
//then from spectra numbers to indices
fillIndexListFromSpectra(indexList,mySpectraList,WS);
}
Gigg, Martyn Anthony
committed
// If we have a workspace that could contain masking,copy that in too
if( prevMasking )
{
appendToIndexListFromWS(indexList,prevMasking);
}
Russell Taylor
committed
Russell Taylor
committed
// Need to get hold of the parameter map
Geometry::ParameterMap& pmap = WS->instrumentParameters();
Russell Taylor
committed
// If explicitly given a list of detectors to mask, just mark those.
// Otherwise, mask all detectors pointing to the requested spectra in indexlist loop below
bool detsMasked = false;
std::vector<int>::const_iterator it;
boost::shared_ptr<Instrument> instrument = WS->getBaseInstrument();
if ( !detectorList.empty() )
{
for (it = detectorList.begin(); it != detectorList.end(); ++it)
{
Steve Williams
committed
try
Russell Taylor
committed
{
Steve Williams
committed
if ( Geometry::Detector* det = dynamic_cast<Geometry::Detector*>(instrument->getDetector(*it).get()) )
{
pmap.addBool(det,"masked",true);
}
}
catch(Kernel::Exception::NotFoundError &e)
Steve Williams
committed
{
g_log.warning() << e.what() << " Found while running MaskDetectors" << std::endl;
Russell Taylor
committed
}
}
detsMasked = true;
}
Russell Taylor
committed
if ( indexList.size() == 0 )
{
Russell Taylor
committed
g_log.warning("No spectra affected.");
Russell Taylor
committed
return;
Russell Taylor
committed
}
Russell Taylor
committed
// Get a reference to the spectra-detector map to get hold of detector ID's
const SpectraDetectorMap& specMap = WS->spectraMap();
Sofia Antony
committed
double prog=0.0;
Russell Taylor
committed
for (it = indexList.begin(); it != indexList.end(); ++it)
Russell Taylor
committed
{
Russell Taylor
committed
if (!detsMasked)
{
// In this case, mask all detectors contributing to spectrum
int spectrum_number = WS->getAxis(1)->spectraNo(*it);
const std::vector<int> dets = specMap.getDetectors(spectrum_number);
Russell Taylor
committed
for (std::vector<int>::const_iterator iter=dets.begin(); iter != dets.end(); ++iter)
{
Steve Williams
committed
try
Russell Taylor
committed
{
Steve Williams
committed
if ( Geometry::Detector* det = dynamic_cast<Geometry::Detector*>(instrument->getDetector(*iter).get()) )
{
pmap.addBool(det,"masked",true);
}
}
catch(Kernel::Exception::NotFoundError &e)
Steve Williams
committed
{
g_log.warning() << e.what() << " Found while running MaskDetectors" << std::endl;
Steve Williams
committed
}
Russell Taylor
committed
}
}
if (eventWS)
{
//Valid event workspace - clear the event list.
Janik Zikovsky
committed
eventWS->getEventList(*it).clear();
}
else
{
// Zero the workspace spectra (data and errors, not X values)
WS->dataY(*it).assign(vectorSize,0.0);
WS->dataE(*it).assign(vectorSize,0.0);
}
//Progress
prog+=(double( 1)/indexList.size());
progress(prog);
}
Sofia Antony
committed
if (eventWS)
{
//Also clear the MRU for event workspaces.
eventWS->clearMRU();
Russell Taylor
committed
}
Russell Taylor
committed
}
Gigg, Martyn Anthony
committed
/**
* Convert a list of spectra numbers into the corresponding workspace indices
Janik Zikovsky
committed
* @param indexList :: An output index list from the given spectra list
* @param spectraList :: A list of spectra numbers
* @param WS :: The input workspace to be masked
Gigg, Martyn Anthony
committed
*/
void MaskDetectors::fillIndexListFromSpectra(std::vector<int>& indexList, const std::vector<int>& spectraList,
const API::MatrixWorkspace_sptr WS)
Russell Taylor
committed
{
// Convert the vector of properties into a set for easy searching
std::set<int> spectraSet(spectraList.begin(),spectraList.end());
// Next line means that anything in Clear the index list first
indexList.clear();
Russell Taylor
committed
//get the spectra axis
Axis *spectraAxis = WS->getAxis(1);
for (int i = 0; i < WS->getNumberHistograms(); ++i)
{
int currentSpec = spectraAxis->spectraNo(i);
if ( spectraSet.find(currentSpec) != spectraSet.end() )
{
indexList.push_back(i);
}
}
Russell Taylor
committed
}
Gigg, Martyn Anthony
committed
/**
* Append the indices of the masked spectra from the given workspace list to the given list
Janik Zikovsky
committed
* @param indexList :: An existing list of indices
* @param maskedWorkspace :: An workspace with masked spectra
Gigg, Martyn Anthony
committed
*/
void MaskDetectors::appendToIndexListFromWS(std::vector<int>& indexList, const MatrixWorkspace_sptr maskedWorkspace)
{
// Convert the vector of properties into a set for easy searching
std::set<int> existingIndices(indexList.begin(), indexList.end());
const int numHistograms(maskedWorkspace->getNumberHistograms());
for (int i = 0; i < numHistograms; ++i)
{
Gigg, Martyn Anthony
committed
IDetector_sptr det;
try
{
det = maskedWorkspace->getDetector(i);
}
catch(Exception::NotFoundError &)
{
continue;
}
if( det->isMasked() && existingIndices.count(i) == 0 )
Gigg, Martyn Anthony
committed
{
indexList.push_back(i);
}
}
}
Russell Taylor
committed
} // namespace DataHandling
} // namespace Mantid