Mantid
Loading...
Searching...
No Matches
InstrumentSpectraMapping.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2026 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
11#include "MantidAPI/Workspace.h"
14#include "MantidKernel/Logger.h"
15
16#include <algorithm>
17#include <memory>
18#include <string>
19#include <unordered_set>
20#include <vector>
21
22namespace Mantid::DataHandling {
23
24using namespace API;
25using Kernel::Logger;
26
27const std::string SPECTRA_MAP_SOURCE = "spectra-map-source";
28const std::string SPECTRA_MAP_FROM_INSTRUMENT = "instrument";
29
30namespace {
31
33bool isCorrectionEnabled(const Geometry::Instrument &instrument) {
34 const auto values = instrument.getStringParameter(SPECTRA_MAP_SOURCE);
35 return !values.empty() && values.front() == SPECTRA_MAP_FROM_INSTRUMENT;
36}
37
39void correctWorkspace(const Workspace_sptr &workspace, Logger &log) {
40 if (!workspace)
41 return;
42
43 if (const auto group = std::dynamic_pointer_cast<WorkspaceGroup>(workspace)) {
44 for (int i = 0; i < group->getNumberOfEntries(); ++i)
45 correctWorkspace(group->getItem(i), log);
46 return;
47 }
48
49 if (const auto matrixWorkspace = std::dynamic_pointer_cast<MatrixWorkspace>(workspace))
50 correctSpectraMapping(*matrixWorkspace, log);
51}
52
53} // namespace
54
56 const auto instrument = workspace.getInstrument();
57 if (!instrument || !isCorrectionEnabled(*instrument))
58 return false;
59
60 const auto detectorIDs = instrument->getDetectorIDs(false);
61 if (detectorIDs.empty())
62 return false;
63 const std::unordered_set<detid_t> knownIDs(detectorIDs.cbegin(), detectorIDs.cend());
64
65 // A spectrum needs correcting when the file gave it a detector the instrument does not define. It is mapped to the
66 // detector of its own number where one exists, and otherwise left with its histogram and no detectors. Spectra whose
67 // file detectors are all known are not touched, so a mapping the file got right survives even if it is not
68 // one-to-one.
69 std::size_t corrected = 0;
70 std::size_t unmappable = 0;
71 for (std::size_t i = 0; i < workspace.getNumberHistograms(); ++i) {
72 auto &spectrum = workspace.getSpectrum(i);
73 const auto &fileIDs = spectrum.getDetectorIDs();
74 if (std::all_of(fileIDs.cbegin(), fileIDs.cend(), [&knownIDs](const detid_t id) { return knownIDs.count(id) > 0; }))
75 continue;
76
77 const auto matchingID = static_cast<detid_t>(spectrum.getSpectrumNo());
78 if (knownIDs.count(matchingID)) {
79 spectrum.setDetectorID(matchingID);
80 ++corrected;
81 } else {
82 spectrum.clearDetectorIDs();
83 ++unmappable;
84 }
85 }
86
87 if (corrected == 0 && unmappable == 0)
88 return false;
89
90 if (corrected > 0)
91 log.information() << instrument->getName() << ": " << corrected
92 << " spectra referenced detectors not in the instrument definition and were mapped to the "
93 "detector of the same ID.\n";
94 if (unmappable > 0)
95 log.information() << unmappable << " spectra had no detector of a matching ID and were left without detectors.\n";
96
97 return true;
98}
99
101 // A group's members are reached through the group, so the per-period properties need no separate visit.
102 for (const auto *name : {"OutputWorkspace", "MonitorWorkspace"}) {
103 if (!loader.existsProperty(name))
104 continue;
106 correctWorkspace(workspace, log);
107 }
108}
109
110} // namespace Mantid::DataHandling
std::string name
Definition Run.cpp:60
IPeaksWorkspace_sptr workspace
Base class from which all concrete algorithm classes should be derived.
Definition Algorithm.h:76
bool existsProperty(const std::string &name) const override
Checks whether the named property is already in the list of managed property.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Base MatrixWorkspace Abstract Class.
std::vector< std::string > getStringParameter(const std::string &pname, bool recursive=true) const override
Get a parameter defined as a string.
Definition Component.h:244
Base Instrument Class.
Definition Instrument.h:49
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition Logger.h:51
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
MANTID_DATAHANDLING_DLL void correctLoadedWorkspaces(const API::Algorithm &loader, Kernel::Logger &log)
Applies correctSpectraMapping to whichever workspaces a loader declared: its output,...
MANTID_DATAHANDLING_DLL bool correctSpectraMapping(API::MatrixWorkspace &workspace, Kernel::Logger &log)
Corrects spectrum-to-detector mappings for files that use detector IDs not recognized by the instrume...
MANTID_DATAHANDLING_DLL const std::string SPECTRA_MAP_SOURCE
The specific instrument parameter and target value that enables the correction.
MANTID_DATAHANDLING_DLL const std::string SPECTRA_MAP_FROM_INSTRUMENT
int32_t detid_t
Typedef for a detector ID.