Newer
Older
Russell Taylor
committed
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidDataHandling/GroupDetectors.h"
Russell Taylor
committed
#include "MantidAPI/WorkspaceValidators.h"
Russell Taylor
committed
#include "MantidAPI/SpectraDetectorMap.h"
Russell Taylor
committed
#include "MantidKernel/ArrayProperty.h"
Russell Taylor
committed
#include <set>
Russell Taylor
committed
namespace Mantid
{
namespace DataHandling
{
// Register the algorithm into the algorithm factory
DECLARE_ALGORITHM(GroupDetectors)
Janik Zikovsky
committed
/// Sets documentation strings for this algorithm
void GroupDetectors::initDocs()
{
this->setWikiSummary("Sums spectra bin-by-bin, equivalent to grouping the data from a set of detectors. Individual groups can be specified by passing the algorithm a list of spectrum numbers, detector IDs or workspace indices. Many spectra groups can be created in one execution via an input file. ");
this->setOptionalMessage("Sums spectra bin-by-bin, equivalent to grouping the data from a set of detectors. Individual groups can be specified by passing the algorithm a list of spectrum numbers, detector IDs or workspace indices. Many spectra groups can be created in one execution via an input file.");
Janik Zikovsky
committed
}
Russell Taylor
committed
using namespace Kernel;
using namespace API;
/// (Empty) Constructor
GroupDetectors::GroupDetectors() {}
/// Destructor
GroupDetectors::~GroupDetectors() {}
void GroupDetectors::init()
{
Russell Taylor
committed
declareProperty(new WorkspaceProperty<>("Workspace","",Direction::InOut,
new CommonBinsValidator<>),
"The name of the workspace2D on which to perform the algorithm");
Janik Zikovsky
committed
Gigg, Martyn Anthony
committed
declareProperty(new ArrayProperty<specid_t>("SpectraList"),
Steve Williams
committed
"An array containing a list of the indexes of the spectra to combine\n"
"(DetectorList and WorkspaceIndexList are ignored if this is set)" );
Janik Zikovsky
committed
Gigg, Martyn Anthony
committed
declareProperty(new ArrayProperty<detid_t>("DetectorList"),
Steve Williams
committed
"An array of detector ID's (WorkspaceIndexList is ignored if this is\n"
"set)" );
Janik Zikovsky
committed
Gigg, Martyn Anthony
committed
declareProperty(new ArrayProperty<size_t>("WorkspaceIndexList"),
Steve Williams
committed
"An array of workspace indices to combine" );
Janik Zikovsky
committed
Steve Williams
committed
declareProperty("ResultIndex", -1,
Steve Williams
committed
"The workspace index of the summed spectrum (or -1 on error)",
Direction::Output);
Russell Taylor
committed
}
void GroupDetectors::exec()
{
// Get the input workspace
Russell Taylor
committed
const MatrixWorkspace_sptr WS = getProperty("Workspace");
Russell Taylor
committed
std::vector<size_t> indexList = getProperty("WorkspaceIndexList");
std::vector<specid_t> spectraList = getProperty("SpectraList");
const std::vector<detid_t> detectorList = getProperty("DetectorList");
Roman Tolchenov
committed
Russell Taylor
committed
// Could create a Validator to replace the below
Steve Williams
committed
if ( indexList.empty() && spectraList.empty() && detectorList.empty() )
Russell Taylor
committed
{
Steve Williams
committed
g_log.information(name() +
": WorkspaceIndexList, SpectraList, and DetectorList properties are all empty, no grouping done");
return;
Russell Taylor
committed
}
// Bin boundaries need to be the same, so check if they actually are
Russell Taylor
committed
if (!API::WorkspaceHelpers::commonBoundaries(WS))
Russell Taylor
committed
{
g_log.error("Can only group if the histograms have common bin boundaries");
throw std::runtime_error("Can only group if the histograms have common bin boundaries");
Russell Taylor
committed
}
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
{
WS->getIndicesFromSpectra(spectraList,indexList);
}// End dealing with spectraList
Steve Williams
committed
else if ( ! detectorList.empty() )
{// Dealing with DetectorList
std::vector<specid_t> mySpectraList = WS->spectraMap().getSpectra(detectorList);
WS->getIndicesFromSpectra(mySpectraList,indexList);
}
if ( indexList.size() == 0 )
{
g_log.warning("Nothing to group");
return;
Russell Taylor
committed
}
Janik Zikovsky
committed
const specid_t firstIndex = static_cast<specid_t>(indexList[0]);
Janik Zikovsky
committed
ISpectrum * firstSpectrum = WS->getSpectrum(firstIndex);
setProperty("ResultIndex",firstIndex);
Gigg, Martyn Anthony
committed
const Geometry::ISpectraDetectorMap & inputSpectra = WS->spectraMap();
API::SpectraDetectorMap *groupedMap = dynamic_cast<API::SpectraDetectorMap*>(inputSpectra.clone());
if( !groupedMap )
{
throw std::invalid_argument("Input workspace with a 1:1 spectra-detector map is not supported "
"by this algorithm.");
}
// loop over the spectra to group
Progress progress(this, 0.0, 1.0, static_cast<int>(indexList.size()-1));
Russell Taylor
committed
{
Janik Zikovsky
committed
// The current spectrum
Janik Zikovsky
committed
ISpectrum * spec = WS->getSpectrum(currentIndex);
// Add the current detector to belong to the first spectrum
firstSpectrum->addDetectorIDs(spec->getDetectorIDs());
//groupedMap->remap(spectraAxis->spectraNo(currentIndex), firstSpectrum);
Russell Taylor
committed
// Add up all the Y spectra and store the result in the first one
// Need to keep the next 3 lines inside loop for now until ManagedWorkspace mru-list works properly
MantidVec &firstY = WS->dataY(firstIndex);
MantidVec::iterator fYit;
Janik Zikovsky
committed
MantidVec::iterator fEit = firstSpectrum->dataE().begin();
MantidVec::iterator Yit = spec->dataY().begin();
MantidVec::iterator Eit = spec->dataE().begin();
for (fYit = firstY.begin(); fYit != firstY.end(); ++fYit, ++fEit, ++Yit, ++Eit)
{
*fYit += *Yit;
// Assume 'normal' (i.e. Gaussian) combination of errors
*fEit = sqrt( (*fEit)*(*fEit) + (*Eit)*(*Eit) );
}
Janik Zikovsky
committed
Russell Taylor
committed
// Now zero the now redundant spectrum and set its spectraNo to indicate this (using -1)
Russell Taylor
committed
// N.B. Deleting spectra would cause issues for ManagedWorkspace2D, hence the the approach taken here
Janik Zikovsky
committed
spec->dataY().assign(vectorSize,0.0);
spec->dataE().assign(vectorSize,0.0);
spec->setSpectrumNo(-1);
spec->clearDetectorIDs();
Gigg, Martyn Anthony
committed
progress.report();
Russell Taylor
committed
}
Gigg, Martyn Anthony
committed
g_log.information() << "Testing " << groupedMap->nElements() << "\n";
Russell Taylor
committed
Gigg, Martyn Anthony
committed
// Replace the old map
Janik Zikovsky
committed
WS->generateSpectraMap();
// WS->replaceSpectraMap(groupedMap);
Russell Taylor
committed
}
} // namespace DataHandling
} // namespace Mantid