42 "The name of the input workspace.");
44 "The name of the output MaskWorkspace which will contain the result "
46 auto mustBePosDbl = std::make_shared<BoundedValidator<double>>();
47 mustBePosDbl->setLower(0.0);
48 declareProperty(
"MaxTubeFramerate", -1.0, mustBePosDbl,
"The maximum rate allowed for a tube in counts/us/frame.");
49 auto mustBePosInt = std::make_shared<BoundedValidator<int>>();
50 mustBePosInt->setLower(0);
51 declareProperty(
"NIgnoredCentralPixels", 80, mustBePosInt,
"The number of pixels about the centre to ignore.");
52 declareProperty(
"NumberOfFailures", 0, std::make_shared<Kernel::NullValidator>(),
62 if (!inputWorkspace->run().hasProperty(
"goodfrm")) {
63 throw std::invalid_argument(
"InputWorkspace does not contain the number of \"good frames\".\n"
64 "(The sample log named: goodfrm with value, specifying number of good "
70 throw std::invalid_argument(
"InputWorkspace has the number of \"good "
71 "frames\" property (goodfrm log value)"
72 "but this property value is not integer.");
75 int goodFrames = (*frameProp)();
78 double maxFramerate =
getProperty(
"MaxTubeFramerate");
82 double maxRate = maxFramerate * goodFrames;
83 int numIgnoredPixels =
getProperty(
"NIgnoredCentralPixels");
90 const auto numSpectra =
static_cast<int>(inputWorkspace->getNumberHistograms());
92 using TubeIndex = std::map<Geometry::ComponentID, std::vector<int>>;
97 const auto &spectrumInfo = inputWorkspace->spectrumInfo();
106 for (
int i = 0; i < numSpectra; ++i) {
107 if (!spectrumInfo.hasDetectors(i))
110 if (spectrumInfo.isMonitor(i))
113 auto &det = spectrumInfo.detector(i);
114 std::shared_ptr<const Geometry::IComponent> parent;
116 if (!spectrumInfo.hasUniqueDetector(i)) {
120 parent = det.getParent();
128 if (tubeMap.find(parentID) != tubeMap.end()) {
129 tubeMap[parentID].emplace_back(i);
133 tubeMap.emplace(parentID, TubeIndex::mapped_type(1, i));
140 const auto numTubes =
static_cast<int>(tubeMap.size());
142 int numSpectraMasked(0), numTubesMasked(0);
146 progress.resetNumSteps(numTubes, 0, 1);
149 for (
int i = 0; i < numTubes; ++i) {
151 auto current = std::next(tubeMap.begin(), i);
152 const TubeIndex::mapped_type tubeIndices = current->second;
153 bool mask =
performBleedTest(tubeIndices, inputWorkspace, maxRate, numIgnoredPixels);
155 maskTube(tubeIndices, outputWorkspace);
157 numSpectraMasked +=
static_cast<int>(tubeIndices.size());
162 progress.report(
"Performing Bleed Test");
168 g_log.
information() << numTubesMasked <<
" tube(s) failed the bleed tests.";
169 if (numTubesMasked > 0) {
170 g_log.
information() <<
" The " << numSpectraMasked <<
" spectra have been masked on the output workspace.\n";
190 int numIgnoredPixels) {
196 const size_t numSpectra(tubeIndices.size());
197 const size_t midIndex(numSpectra / 2);
198 const size_t topEnd(midIndex - numIgnoredPixels / 2);
199 const size_t bottomBegin(midIndex + numIgnoredPixels / 2);
203 bool isRawCounts = !(inputWS->isDistribution());
205 const auto numBins =
static_cast<int>(inputWS->blocksize());
206 std::vector<double> totalRate(numBins, 0.0);
207 size_t top = 0, bot = bottomBegin;
208 for (;
top < topEnd; ++
top, ++bot) {
209 const int topIndex = tubeIndices[
top];
210 const int botIndex = tubeIndices[bot];
211 auto &topY = inputWS->y(topIndex);
212 auto &botY = inputWS->y(botIndex);
213 auto &topX = inputWS->x(topIndex);
214 auto &botX = inputWS->x(botIndex);
215 for (
int j = 0; j < numBins; ++j) {
216 double topRate(topY[j]), botRate(botY[j]);
218 topRate /= (topX[j + 1] - topX[j]);
219 botRate /= (botX[j + 1] - botX[j]);
221 totalRate[j] += topRate + botRate;
223 if (totalRate[j] > maxRate) {
230 g_log.
error() <<
"Error in tube processing, loop variable has an unexpected value.\n";
231 throw std::runtime_error(
"top != topEnd in CreatePSDBleedMask::performBleedTest()");
233 if (bot != numSpectra) {
234 g_log.
error() <<
"Error in tube processing, loop variable has an unexpected value.\n";
235 throw std::runtime_error(
"bot != numSpectra in CreatePSDBleedMask::performBleedTest()");
247 const double deadValue(1.0);
248 for (
auto tubeIndice : tubeIndices) {
249 workspace->mutableY(tubeIndice)[0] = deadValue;
#define DECLARE_ALGORITHM(classname)
IPeaksWorkspace_sptr workspace
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Helper class for reporting progress from algorithms.
A property class for workspaces.
This algorithm implements a "bleed" diagnostic for PSD detectors (i.e.
void exec() override
Execute the algorithm.
void init() override
Initialize the algorithm properties.
bool performBleedTest(const std::vector< int > &tubeIndices, const API::MatrixWorkspace_const_sptr &inputWS, double maxRate, int numIgnoredPixels)
Process a tube.
CreatePSDBleedMask()
Default constructor.
void maskTube(const std::vector< int > &tubeIndices, const API::MatrixWorkspace_sptr &workspace)
Mask a tube with the given workspace indices.
DataObjects::MaskWorkspace_sptr generateEmptyMask(const API::MatrixWorkspace_const_sptr &inputWS)
Create a masking workspace to return.
Holds a collection of detectors.
std::vector< IDetector_const_sptr > getDetectors() const
What detectors are contained in the group?
base class for Geometric IComponent
virtual ComponentID getComponentID() const =0
Returns the ComponentID - a unique identifier of the component.
BoundedValidator is a validator that requires the values to be between upper or lower bounds,...
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void error(const std::string &msg)
Logs at error level.
void information(const std::string &msg)
Logs at information level.
The concrete, templated class for properties.
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< MaskWorkspace > MaskWorkspace_sptr
shared pointer to the MaskWorkspace class
std::shared_ptr< const Mantid::Geometry::IDetector > IDetector_const_sptr
Shared pointer to IDetector (const version)
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
Describes the direction (within an algorithm) of a Property.
@ Input
An input workspace.
@ Output
An output workspace.