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;
113 double intensity = 0.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);
136 intensity += histogram[ichan];
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;
230 double intensity = 0.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;
269 row = int(rowcentroid / intensity);
270 boost::algorithm::clamp(row, 0, nRows - 1);
271 col = int(colcentroid / intensity);
272 boost::algorithm::clamp(col, 0, nCols - 1);
273 if (!
edgePixel(compInfo, bankName, col, row, Edge)) {
274 peak.setDetectorID(
findPixelID(bankName, col, row));
277 double tof = tofcentroid / intensity;
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);
289 peak.setBinCount(intensity);
309 m_eventW = std::dynamic_pointer_cast<const EventWorkspace>(
m_inWS);
319 std::shared_ptr<const IComponent> parent =
m_inst->getComponentByName(bankName);
320 if (parent->type() ==
"RectangularDetector") {
321 std::shared_ptr<const RectangularDetector> RDet = std::dynamic_pointer_cast<const RectangularDetector>(parent);
323 std::shared_ptr<Detector> pixel = RDet->getAtXY(col, row);
324 return pixel->getID();
326 std::string bankName0 = bankName;
328 bankName0.erase(0, 4);
329 std::ostringstream pixelString;
330 pixelString <<
m_inst->getName() <<
"/" << bankName0 <<
"/" << bankName <<
"/tube" << std::setw(3)
331 << std::setfill(
'0') << col <<
"/pixel" << std::setw(4) << std::setfill(
'0') << row;
332 std::shared_ptr<const Geometry::IComponent> component =
m_inst->getComponentByName(pixelString.str());
333 std::shared_ptr<const Detector> pixel = std::dynamic_pointer_cast<const Detector>(component);
334 return pixel->getID();
340 std::vector<int> badPeaks;
343 for (
int i = 0; i < static_cast<int>(numPeaks); i++) {
345 const auto &peak = peakWS.
getPeak(i);
347 int row = peak.getRow();
348 const std::string &bankName = peak.getBankName();
350 if (
edgePixel(compInfo, bankName, col, row, Edge)) {
351 badPeaks.emplace_back(i);
358 if (bankName ==
"None")
365 auto bank =
m_inst->getComponentByName(bankName);
366 auto bankID = bank->getComponentID();
369 nRows =
static_cast<int>(compInfo.componentsInSubtree(compInfo.indexOf(bankID)).size() -
370 allBankDetectorIndexes.size() - 1);
371 nCols =
static_cast<int>(allBankDetectorIndexes.size()) / nRows;
373 if (nCols * nRows !=
static_cast<int>(allBankDetectorIndexes.size())) {
375 nRows =
static_cast<int>(compInfo.componentsInSubtree(compInfo.indexOf(bankID)).size() -
376 allBankDetectorIndexes.size() - 2);
377 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.
Geometry::Instrument_const_sptr m_inst
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.
std::vector< size_t > detectorsInSubtree(size_t componentIndex) const
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(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.