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();
74 size_t Numberwi =
m_inWS->getNumberHistograms();
75 int NumberPeaks = peakWS->getNumberPeaks();
76 for (
int i = 0; i < NumberPeaks; ++i) {
77 Peak const &peak = peakWS->getPeaks()[i];
90 const auto inBlocksize =
static_cast<int64_t
>(
m_inWS->blocksize());
92 Progress prog(
this, MinPeaks, 1.0, MaxPeaks);
94 for (
int i = MinPeaks; i <= MaxPeaks; ++i) {
97 auto &peak = peakWS->getPeak(i);
98 int col = peak.getCol();
99 int row = peak.getRow();
100 int pixelID = peak.getDetectorID();
105 size_t workspaceIndex = detidIterator->second;
106 double TOFPeakd = peak.getTOF();
107 const auto &
X =
m_inWS->x(workspaceIndex);
109 std::string bankName = peak.getBankName();
110 int nCols = 0, nRows = 0;
114 double chancentroid = 0.0;
116 int chanstart = std::max(0, chan - PeakRadius);
117 int chanend = std::min(
static_cast<int>(
X.size()), chan + PeakRadius);
118 double rowcentroid = 0.0;
119 int rowstart = std::max(0, row - PeakRadius);
120 int rowend = std::min(nRows - 1, row + PeakRadius);
121 double colcentroid = 0.0;
122 int colstart = std::max(0, col - PeakRadius);
123 int colend = std::min(nCols - 1, col + PeakRadius);
124 for (
int ichan = chanstart; ichan <= chanend; ++ichan) {
125 for (
int irow = rowstart; irow <= rowend; ++irow) {
126 for (
int icol = colstart; icol <= colend; ++icol) {
127 if (
edgePixel(compInfo, bankName, icol, irow, Edge)) {
134 const auto &histogram =
m_inWS->y(it->second);
137 rowcentroid += irow * histogram[ichan];
138 colcentroid += icol * histogram[ichan];
139 chancentroid += ichan * histogram[ichan];
144 row = (int)std::lround(rowcentroid /
intensity);
145 boost::algorithm::clamp(row, 0, nRows - 1);
146 col = (int)std::lround(colcentroid /
intensity);
147 boost::algorithm::clamp(col, 0, nCols - 1);
148 chan = (int)std::lround(chancentroid /
intensity);
149 boost::algorithm::clamp(chan, 0,
static_cast<int>(inBlocksize));
152 if (!
edgePixel(compInfo, bankName, col, row, Edge)) {
153 peak.setDetectorID(
findPixelID(bankName, col, row));
155 workspaceIndex = (detidIterator->second);
157 std::vector<double> timeflight;
158 timeflight.emplace_back(
m_inWS->x(workspaceIndex)[chan]);
159 double scattering = peak.getScattering();
160 double L1 = peak.getL1();
161 double L2 = peak.getL2();
162 wl.
fromTOF(timeflight, timeflight, L1, 0, {{UnitParams::l2, L2}, {UnitParams::twoTheta, scattering}});
163 const double lambda = timeflight[0];
166 peak.setWavelength(
lambda);
167 peak.setBinCount(
m_inWS->y(workspaceIndex)[chan]);
189 if (peakWS != inPeakWS)
190 peakWS = inPeakWS->clone();
199 size_t Numberwi =
m_inWS->getNumberHistograms();
200 int NumberPeaks = peakWS->getNumberPeaks();
202 for (
int i = 0; i < NumberPeaks; ++i) {
203 auto &peak = peakWS->getPeak(i);
204 int pixelID = peak.getDetectorID();
209 if (MinPeaks == -1 && peak.getRunNumber() ==
m_inWS->getRunNumber() && wi < Numberwi)
211 if (peak.getRunNumber() ==
m_inWS->getRunNumber() && wi < Numberwi)
217 Progress prog(
this, MinPeaks, 1.0, MaxPeaks);
219 for (
int i = MinPeaks; i <= MaxPeaks; ++i) {
222 auto &peak = peakWS->getPeak(i);
223 int col = peak.getCol();
224 int row = peak.getRow();
225 double TOFPeakd = peak.getTOF();
226 std::string bankName = peak.getBankName();
227 int nCols = 0, nRows = 0;
231 double tofcentroid = 0.0;
232 if (
edgePixel(compInfo, bankName, col, row, Edge)) {
236 double tofstart = TOFPeakd * std::pow(1.004, -PeakRadius);
237 double tofend = TOFPeakd * std::pow(1.004, PeakRadius);
238 double rowcentroid = 0.0;
239 int rowstart = std::max(0, row - PeakRadius);
240 int rowend = std::min(nRows - 1, row + PeakRadius);
241 double colcentroid = 0.0;
242 int colstart = std::max(0, col - PeakRadius);
243 int colend = std::min(nCols - 1, col + PeakRadius);
244 for (
int irow = rowstart; irow <= rowend; ++irow) {
245 for (
int icol = colstart; icol <= colend; ++icol) {
246 if (
edgePixel(compInfo, bankName, icol, irow, Edge)) {
250 size_t workspaceIndex = (it1->second);
256 for (
const auto &event : events) {
257 double tof =
event.tof();
258 if (tof > tofstart && tof < tofend) {
259 double weight =
event.weight();
261 rowcentroid += irow * weight;
262 colcentroid += icol * weight;
263 tofcentroid += tof * weight;
270 boost::algorithm::clamp(row, 0, nRows - 1);
272 boost::algorithm::clamp(col, 0, nCols - 1);
273 if (!
edgePixel(compInfo, bankName, col, row, Edge)) {
274 peak.setDetectorID(
findPixelID(bankName, col, row));
279 std::vector<double> timeflight;
280 timeflight.emplace_back(tof);
281 double scattering = peak.getScattering();
282 double L1 = peak.getL1();
283 double L2 = peak.getL2();
284 wl.
fromTOF(timeflight, timeflight, L1, 0, {{UnitParams::l2, L2}, {UnitParams::twoTheta, scattering}});
285 const double lambda = timeflight[0];
288 peak.setWavelength(
lambda);
308 m_eventW = std::dynamic_pointer_cast<const EventWorkspace>(
m_inWS);
318 const auto &componentInfo =
m_inWS->componentInfo();
319 const size_t bankIndex = componentInfo.indexOfAny(bankName);
320 if (componentInfo.isGridDetector(bankIndex)) {
321 const auto &detectorInfo =
m_inWS->detectorInfo();
322 return detectorInfo.detid(componentInfo.detectorIndexAtXYZ(bankIndex, col, row, 0));
324 auto children = componentInfo.children(bankIndex);
325 auto grandChildren = componentInfo.children(children[col - 1]);
326 auto const &detectorInfo =
m_inWS->detectorInfo();
327 return detectorInfo.detid(grandChildren[row - 1]);
333 std::vector<int> badPeaks;
336 for (
int i = 0; i < static_cast<int>(numPeaks); i++) {
338 const auto &peak = peakWS.
getPeak(i);
340 int row = peak.getRow();
341 const std::string &bankName = peak.getBankName();
343 if (
edgePixel(compInfo, bankName, col, row, Edge)) {
344 badPeaks.emplace_back(i);
351 if (bankName ==
"None")
353 const auto &compInfo =
m_inWS->componentInfo();
356 const size_t bankIndex = compInfo.indexOfAny(bankName);
357 auto allBankDetectorIndexes = compInfo.detectorsInSubtree(bankIndex);
359 nRows =
static_cast<int>(compInfo.componentsInSubtree(bankIndex).size() - allBankDetectorIndexes.size() - 1);
360 nCols =
static_cast<int>(allBankDetectorIndexes.size()) / nRows;
362 if (nCols * nRows !=
static_cast<int>(allBankDetectorIndexes.size())) {
364 nRows =
static_cast<int>(compInfo.componentsInSubtree(bankIndex).size() - allBankDetectorIndexes.size() - 2);
365 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.
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.
void exec() override
Run the algorithm.
Mantid::detid2index_map m_wi_to_detid_map
DataObjects::EventWorkspace_const_sptr m_eventW
API::MatrixWorkspace_sptr m_inWS
Input 2D Workspace.
void sizeBanks(const std::string &bankName, int &nCols, int &nRows)
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 override
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
void removePeaks(std::vector< int > badPeaks) override
Removes multiple peaks.
Peak & getPeak(size_t const peakNum) override
Return a reference to the Peak.
ComponentInfo : Provides a component centric view on to the instrument.
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 > const &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(ComponentInfo const &info, const std::string &bankName, int col, int row, int Edge)
Function to find peaks near detector edge.
MANTID_KERNEL_DLL int getBinIndex(std::span< double const > 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.