34static bool compareIDPair(
const std::pair<int64_t, Mantid::Kernel::V3D> &
left,
35 const std::pair<int64_t, Mantid::Kernel::V3D> &
right) {
36 return (
left.second.norm() <
right.second.norm());
50 "Name of the input workspace, which is used only as a means "
51 "of retrieving the instrument geometry.");
53 "Name (and location) in which to save the file. Having a "
54 "suffix of ''.xml'' is recommended.");
55 declareProperty(
"SearchDistance", 2.5,
56 "The number of pixel widths in which "
57 "to search for neighbours of the "
59 declareProperty(
"GridSize", 3,
60 "The size of the grid that should be grouped. "
61 "i.e, 3 (the default) will select a group of "
62 "nine detectors centred in a 3 by 3 grid.");
72 size_t nNeighbours = (gridSize * gridSize) - 1;
75 const auto &spectrumInfo = inputWorkspace->spectrumInfo();
76 for (
size_t i = 0; i < inputWorkspace->getNumberHistograms(); ++i) {
77 const auto &spec = inputWorkspace->getSpectrum(i);
78 m_positions[spec.getSpectrumNo()] = spectrumInfo.position(i);
86 bool ignoreMaskedDetectors =
false;
87 m_neighbourInfo = std::make_unique<API::WorkspaceNearestNeighbourInfo>(*inputWorkspace, ignoreMaskedDetectors);
89 for (
size_t i = 0; i < inputWorkspace->getNumberHistograms(); ++i) {
92 const auto &spec = inputWorkspace->getSpectrum(i);
98 if (spectrumInfo.isMonitor(i)) {
109 std::map<detid_t, Mantid::Kernel::V3D> nearest;
114 createBox(spectrumInfo.detector(i), bbox, searchDist);
117 while ((nNeighbours > nearest.size()) && extend) {
118 extend =
expandNet(nearest, specNo, nNeighbours, bbox);
121 if (nearest.size() != nNeighbours)
125 std::vector<int> group;
128 group.emplace_back(specNo);
131 std::map<specnum_t, Mantid::Kernel::V3D>::iterator nrsIt;
132 for (nrsIt = nearest.begin(); nrsIt != nearest.end(); ++nrsIt) {
134 group.emplace_back(nrsIt->first);
146 std::vector<std::vector<detid_t>>::iterator grpIt;
151 size_t fnameXMLappend = fname.find(
".xml");
152 if (fnameXMLappend == std::string::npos) {
153 fnameXMLappend = fname.find(
".XML");
154 if (fnameXMLappend == std::string::npos)
155 fname = fname +
".xml";
161 xml.open(fname.c_str());
163 xml <<
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
164 <<
"<!-- XML Grouping File created by SpatialGrouping Algorithm -->\n"
165 <<
"<detector-grouping>\n";
169 xml <<
"<group name=\"group" << grpID++ <<
"\"><detids val=\"" << (*grpIt)[0];
170 for (
size_t i = 1; i < (*grpIt).size(); i++) {
173 size_t workspaceIndex = inputWorkspace->getIndexFromSpectrumNumber((*grpIt)[i]);
174 const auto &detIds = inputWorkspace->getSpectrum(workspaceIndex).getDetectorIDs();
175 for (
auto detId : detIds) {
179 xml <<
"\"/></group>\n";
182 xml <<
"</detector-grouping>";
203 const size_t incoming = nearest.size();
205 std::map<specnum_t, Mantid::Kernel::V3D> potentials;
211 for (
auto &nrsIt : nearest) {
212 std::map<specnum_t, Mantid::Kernel::V3D> results;
214 for (
auto &result : results) {
215 potentials[result.first] = result.second;
220 for (
auto &potential : potentials) {
223 if (potential.first == spec) {
229 auto nrsIt = nearest.find(potential.first);
230 if (nrsIt != nearest.end()) {
236 auto inclIt =
m_included.find(potential.first);
249 nearest[potential.first] = potential.second;
252 if (nearest.size() == incoming) {
256 if (nearest.size() > noNeighbours) {
272 std::vector<std::pair<detid_t, Mantid::Kernel::V3D>> order(nearest.begin(), nearest.end());
274 std::sort(order.begin(), order.end(), compareIDPair);
276 size_t current = order.size();
277 size_t lose = current - noNeighbours;
281 for (
size_t i = 1; i <= lose; i++) {
282 nearest.erase(order[current - i].first);
307 double xmax = bbox.
xMax();
308 double ymax = bbox.
yMax();
309 double zmax = bbox.
zMax();
310 double xmin = bbox.
xMin();
311 double ymin = bbox.
yMin();
312 double zmin = bbox.
zMin();
314 double factor = 2.0 * searchDist;
331 double rng = max - min;
332 double mid = (max + min) / 2.0;
333 double halfwid = rng / 2.0;
334 min = mid - (factor * halfwid);
335 max = mid + (factor * halfwid);
#define DECLARE_ALGORITHM(classname)
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
void setPropertyValue(const std::string &name, const std::string &value) override
Set the value of a property by string N.B.
@ Save
to specify a file to write to, the file may or may not exist
Helper class for reporting progress from algorithms.
A property class for workspaces.
This algorithm creates an XML Grouping File for use in the GroupDetectors (v2) or ReadGroupsFromFile ...
bool expandNet(std::map< specnum_t, Mantid::Kernel::V3D > &nearest, specnum_t spec, const size_t noNeighbours, const Mantid::Geometry::BoundingBox &bbox)
expand our search out to the next neighbours along
std::map< specnum_t, Kernel::V3D > m_positions
map of detectors in the instrument
void exec() override
Execution code.
std::vector< std::vector< int > > m_groups
first and last values for each group
void createBox(const Geometry::IDetector &det, Geometry::BoundingBox &bndbox, double searchDist)
create expanded bounding box for our purposes
std::unique_ptr< API::WorkspaceNearestNeighbourInfo > m_neighbourInfo
NearestNeighbourInfo used by expandNet()
std::set< specnum_t > m_included
flag which detectors are included in a group already
void growBox(double &min, double &max, const double factor)
grow dimensions of our bounding box to the factor
void sortByDistance(std::map< specnum_t, Mantid::Kernel::V3D > &nearest, const size_t noNeighbours)
sort by distance
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
bool isPointInside(const Kernel::V3D &point) const
Is the given point within the bounding box?
double xMax() const
Return the maximum value of X.
double zMin() const
Return the minimum value of Z.
double zMax() const
Return the maximum value of Z.
double yMax() const
Return the maximum value of Y.
double xMin() const
Return the minimum value of X.
double yMin() const
Return the minimum value of Y.
virtual void getBoundingBox(BoundingBox &boundingBox) const =0
Get the bounding box for this component and store it in the given argument.
Interface class for detector objects.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
int32_t specnum_t
Typedef for a spectrum Number.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
@ Input
An input workspace.