15#include <boost/algorithm/clamp.hpp>
35 "A PeaksWorkspace containing the peaks to centroid.");
38 "An input 2D Workspace.");
41 "Fixed radius around each peak position in which to calculate the "
45 "The number of pixels where peaks are removed at edges. Only "
46 "for instruments with RectangularDetectors. ");
49 "The output PeaksWorkspace will be a copy of the input PeaksWorkspace "
50 "with the peaks' positions modified by the new found centroids.");
64 if (peakWS != inPeakWS)
65 peakWS = inPeakWS->clone();
72 size_t Numberwi =
inWS->getNumberHistograms();
73 int NumberPeaks = peakWS->getNumberPeaks();
74 for (
int i = 0; i < NumberPeaks; ++i) {
75 Peak &peak = peakWS->getPeaks()[i];
81 if (MinPeaks == -1 && peak.
getRunNumber() ==
inWS->getRunNumber() && wi < Numberwi)
88 const auto inBlocksize =
static_cast<int>(
inWS->blocksize());
90 Progress prog(
this, MinPeaks, 1.0, MaxPeaks);
92 for (
int i = MinPeaks; i <= MaxPeaks; ++i) {
95 auto &peak = peakWS->getPeak(i);
96 int col = peak.getCol();
97 int row = peak.getRow();
98 int pixelID = peak.getDetectorID();
103 size_t workspaceIndex = detidIterator->second;
104 double TOFPeakd = peak.getTOF();
105 const auto &
X =
inWS->x(workspaceIndex);
107 std::string bankName = peak.getBankName();
108 int nCols = 0, nRows = 0;
111 double intensity = 0.0;
112 double chancentroid = 0.0;
114 int chanstart = std::max(0, chan - PeakRadius);
115 int chanend = std::min(
static_cast<int>(
X.size()), chan + PeakRadius);
116 double rowcentroid = 0.0;
117 int rowstart = std::max(0, row - PeakRadius);
118 int rowend = std::min(nRows - 1, row + PeakRadius);
119 double colcentroid = 0.0;
120 int colstart = std::max(0, col - PeakRadius);
121 int colend = std::min(nCols - 1, col + PeakRadius);
122 for (
int ichan = chanstart; ichan <= chanend; ++ichan) {
123 for (
int irow = rowstart; irow <= rowend; ++irow) {
124 for (
int icol = colstart; icol <= colend; ++icol) {
131 const auto &histogram =
inWS->y(it->second);
133 intensity += histogram[ichan];
134 rowcentroid += irow * histogram[ichan];
135 colcentroid += icol * histogram[ichan];
136 chancentroid += ichan * histogram[ichan];
141 row = (int)std::lround(rowcentroid / intensity);
142 boost::algorithm::clamp(row, 0, nRows - 1);
143 col = (int)std::lround(colcentroid / intensity);
144 boost::algorithm::clamp(col, 0, nCols - 1);
145 chan = (int)std::lround(chancentroid / intensity);
146 boost::algorithm::clamp(chan, 0, inBlocksize);
150 peak.setDetectorID(
findPixelID(bankName, col, row));
152 workspaceIndex = (detidIterator->second);
154 std::vector<double> timeflight;
155 timeflight.emplace_back(
inWS->x(workspaceIndex)[chan]);
156 double scattering = peak.getScattering();
157 double L1 = peak.getL1();
158 double L2 = peak.getL2();
159 wl.
fromTOF(timeflight, timeflight, L1, 0, {{UnitParams::l2, L2}, {UnitParams::twoTheta, scattering}});
160 const double lambda = timeflight[0];
163 peak.setWavelength(
lambda);
164 peak.setBinCount(
inWS->y(workspaceIndex)[chan]);
186 if (peakWS != inPeakWS)
187 peakWS = inPeakWS->clone();
194 size_t Numberwi =
inWS->getNumberHistograms();
195 int NumberPeaks = peakWS->getNumberPeaks();
197 for (
int i = 0; i < NumberPeaks; ++i) {
198 auto &peak = peakWS->getPeak(i);
199 int pixelID = peak.getDetectorID();
204 if (MinPeaks == -1 && peak.getRunNumber() ==
inWS->getRunNumber() && wi < Numberwi)
206 if (peak.getRunNumber() ==
inWS->getRunNumber() && wi < Numberwi)
212 Progress prog(
this, MinPeaks, 1.0, MaxPeaks);
214 for (
int i = MinPeaks; i <= MaxPeaks; ++i) {
217 auto &peak = peakWS->getPeak(i);
218 int col = peak.getCol();
219 int row = peak.getRow();
220 double TOFPeakd = peak.getTOF();
221 std::string bankName = peak.getBankName();
222 int nCols = 0, nRows = 0;
225 double intensity = 0.0;
226 double tofcentroid = 0.0;
230 double tofstart = TOFPeakd * std::pow(1.004, -PeakRadius);
231 double tofend = TOFPeakd * std::pow(1.004, PeakRadius);
232 double rowcentroid = 0.0;
233 int rowstart = std::max(0, row - PeakRadius);
234 int rowend = std::min(nRows - 1, row + PeakRadius);
235 double colcentroid = 0.0;
236 int colstart = std::max(0, col - PeakRadius);
237 int colend = std::min(nCols - 1, col + PeakRadius);
238 for (
int irow = rowstart; irow <= rowend; ++irow) {
239 for (
int icol = colstart; icol <= colend; ++icol) {
243 size_t workspaceIndex = (it1->second);
249 for (
const auto &event : events) {
250 double tof =
event.tof();
251 if (tof > tofstart && tof < tofend) {
252 double weight =
event.weight();
254 rowcentroid += irow * weight;
255 colcentroid += icol * weight;
256 tofcentroid += tof * weight;
262 row = int(rowcentroid / intensity);
263 boost::algorithm::clamp(row, 0, nRows - 1);
264 col = int(colcentroid / intensity);
265 boost::algorithm::clamp(col, 0, nCols - 1);
267 peak.setDetectorID(
findPixelID(bankName, col, row));
270 double tof = tofcentroid / intensity;
272 std::vector<double> timeflight;
273 timeflight.emplace_back(tof);
274 double scattering = peak.getScattering();
275 double L1 = peak.getL1();
276 double L2 = peak.getL2();
277 wl.
fromTOF(timeflight, timeflight, L1, 0, {{UnitParams::l2, L2}, {UnitParams::twoTheta, scattering}});
278 const double lambda = timeflight[0];
281 peak.setWavelength(
lambda);
282 peak.setBinCount(intensity);
302 eventW = std::dynamic_pointer_cast<const EventWorkspace>(
inWS);
312 std::shared_ptr<const IComponent> parent =
inst->getComponentByName(bankName);
313 if (parent->type() ==
"RectangularDetector") {
314 std::shared_ptr<const RectangularDetector> RDet = std::dynamic_pointer_cast<const RectangularDetector>(parent);
316 std::shared_ptr<Detector> pixel = RDet->getAtXY(col, row);
317 return pixel->getID();
319 std::string bankName0 = bankName;
321 bankName0.erase(0, 4);
322 std::ostringstream pixelString;
323 pixelString <<
inst->getName() <<
"/" << bankName0 <<
"/" << bankName <<
"/tube" << std::setw(3)
324 << std::setfill(
'0') << col <<
"/pixel" << std::setw(4) << std::setfill(
'0') << row;
325 std::shared_ptr<const Geometry::IComponent> component =
inst->getComponentByName(pixelString.str());
326 std::shared_ptr<const Detector> pixel = std::dynamic_pointer_cast<const Detector>(component);
327 return pixel->getID();
333 std::vector<int> badPeaks;
335 for (
int i = 0; i < static_cast<int>(numPeaks); i++) {
337 const auto &peak = peakWS.
getPeak(i);
339 int row = peak.getRow();
340 const std::string &bankName = peak.getBankName();
343 badPeaks.emplace_back(i);
350 if (bankName ==
"None")
357 auto bank =
inst->getComponentByName(bankName);
358 auto bankID = bank->getComponentID();
359 auto allBankDetectorIndexes = compInfo.detectorsInSubtree(compInfo.indexOf(bankID));
361 nRows =
static_cast<int>(compInfo.componentsInSubtree(compInfo.indexOf(bankID)).size() -
362 allBankDetectorIndexes.size() - 1);
363 nCols =
static_cast<int>(allBankDetectorIndexes.size()) / nRows;
365 if (nCols * nRows !=
static_cast<int>(allBankDetectorIndexes.size())) {
367 nRows =
static_cast<int>(compInfo.componentsInSubtree(compInfo.indexOf(bankID)).size() -
368 allBankDetectorIndexes.size() - 2);
369 nCols =
static_cast<int>(allBankDetectorIndexes.size()) / nRows;
#define DECLARE_ALGORITHM(classname)
const std::vector< double > * lambda
#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.
This class is shared by a few Workspace types and holds information related to a particular experimen...
const Geometry::ComponentInfo & componentInfo() const
void setInstrument(const Geometry::Instrument_const_sptr &instr)
Instrument accessors.
Helper class for reporting progress from algorithms.
A property class for workspaces.
void init() override
Initialise the properties.
int findPixelID(const std::string &bankName, int col, int row)
void integrateEvent()
Integrate the peaks of the workspace using parameters saved in the algorithm class.
void removeEdgePeaks(Mantid::DataObjects::PeaksWorkspace &peakWS)
void integrate()
Integrate the peaks of the workspace using parameters saved in the algorithm class.
API::MatrixWorkspace_sptr inWS
Input 2D Workspace.
Mantid::detid2index_map wi_to_detid_map
void exec() override
Run the algorithm.
Geometry::Instrument_const_sptr inst
void sizeBanks(const std::string &bankName, int &nCols, int &nRows)
DataObjects::EventWorkspace_const_sptr eventW
int getRunNumber() const override
Return the run number this peak was measured at.
std::vector< WeightedEventNoTime > & getWeightedEventsNoTime()
Return the list of WeightedEvent contained.
void switchTo(Mantid::API::EventType newType) override
Switch the EventList to use the given EventType (TOF, WEIGHTED, or WEIGHTED_NOTIME)
Structure describing a single-crystal peak.
int getCol() const override
For RectangularDetectors only, returns the column (x) of the pixel of the detector or -1 if not found...
int getDetectorID() const
Get the ID of the detector at the center of the peak
The class PeaksWorkspace stores information about a set of SCD peaks.
int getNumberPeaks() const override
Peak & getPeak(int peakNum) override
Return a reference to the Peak.
void removePeaks(std::vector< int > badPeaks) override
Removes multiple peaks.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
The concrete, templated class for properties.
void fromTOF(std::vector< double > &xdata, std::vector< double > &ydata, const double &_l1, const int &_emode, std::initializer_list< std::pair< const UnitParams, double > > params)
Convert from time-of-flight to the concrete unit.
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
MANTID_GEOMETRY_DLL bool edgePixel(const Geometry::Instrument_const_sptr &inst, const std::string &bankName, int col, int row, int Edge)
Function to find peaks near detector edge.
MANTID_KERNEL_DLL int getBinIndex(const std::vector< double > &bins, const double value)
Return the index into a vector of bin boundaries for a particular X value.
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.
@ Input
An input workspace.
@ Output
An output workspace.