SpectrumDetectorMapping.cpp 4.59 KB
Newer Older
1
2
3
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4
5
//   NScD Oak Ridge National Laboratory, European Spallation Source,
//   Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6
// SPDX - License - Identifier: GPL - 3.0 +
7
8
#include "MantidAPI/SpectrumDetectorMapping.h"
#include "MantidAPI/MatrixWorkspace.h"
9
#include <exception>
10

11
12
13
14
15
16
17
namespace Mantid {
namespace API {
/** Constructor that fills the map from the spectrum-detector relationships in
 * the given workspace.
 *  @throws std::invalid_argument if a null workspace pointer is passed in
 */
SpectrumDetectorMapping::SpectrumDetectorMapping(
David Fairbrother's avatar
David Fairbrother committed
18
    const MatrixWorkspace_const_sptr &workspace, const bool useSpecNoIndex)
19
    : m_indexIsSpecNo(useSpecNoIndex) {
20
21
  if (!workspace) {
    throw std::invalid_argument(
22
        "SpectrumDetectorMapping: Null shared workspace pointer passed");
23
24
  }

25
  for (size_t i = 0; i < workspace->getNumberHistograms(); ++i) {
26
    auto &spectrum = workspace->getSpectrum(i);
27
28

    int index;
29
    if (m_indexIsSpecNo)
30
      index = spectrum.getSpectrumNo();
31
32
33
    else
      index = static_cast<int>(i);

34
    m_mapping[index] = spectrum.getDetectorIDs();
35
  }
36
}
37

38
39
40
41
42
43
/** Constructor that fills the map from a pair of vectors, ignoring the IDs in
 * the optional ignore list
 *  @throws std::invalid_argument if the spectrumNumbers & detectorIDs vectors
 * are not of equal length
 */
SpectrumDetectorMapping::SpectrumDetectorMapping(
44
    const std::vector<specnum_t> &spectrumNumbers,
45
    const std::vector<detid_t> &detectorIDs,
46
47
    const std::vector<detid_t> &ignoreDetIDs)
    : m_indexIsSpecNo(true) {
48
49
50
  if (spectrumNumbers.size() != detectorIDs.size()) {
    throw std::invalid_argument("SpectrumDetectorMapping: Different length "
                                "spectrum number & detector ID array passed");
51
52
  }

53
54
  fillMapFromVector(spectrumNumbers, detectorIDs, ignoreDetIDs);
}
55

56
57
58
59
60
/** Constructor that fills the map from a pair c-style arrays.
 *  Not safe! Prefer the vector constructor where possible!
 *  @throws std::invalid_argument if a null array pointer is passed in
 */
SpectrumDetectorMapping::SpectrumDetectorMapping(
61
    const specnum_t *const spectrumNumbers, const detid_t *const detectorIDs,
62
63
    size_t arrayLengths)
    : m_indexIsSpecNo(true) {
64
  if (spectrumNumbers == nullptr || detectorIDs == nullptr) {
65
66
    throw std::invalid_argument(
        "SpectrumDetectorMapping: Null array pointer passed");
67
  }
68

69
70
  fillMapFromArray(spectrumNumbers, detectorIDs, arrayLengths);
}
71

72
/// Called by the c-array constructors to do the actual filling
73
void SpectrumDetectorMapping::fillMapFromArray(
74
    const specnum_t *const spectrumNumbers, const detid_t *const detectorIDs,
75
    const size_t arrayLengths) {
76
77
78
79
  for (size_t i = 0; i < arrayLengths; ++i) {
    m_mapping[spectrumNumbers[i]].insert(detectorIDs[i]);
  }
}
80

81
82
/// Called by the vector constructors to do the actual filling
void SpectrumDetectorMapping::fillMapFromVector(
83
    const std::vector<specnum_t> &spectrumNumbers,
84
85
86
87
88
89
90
91
    const std::vector<detid_t> &detectorIDs,
    const std::vector<detid_t> &ignoreDetIDs) {
  std::set<detid_t> ignoreIDs(ignoreDetIDs.begin(), ignoreDetIDs.end());
  const size_t nspec(spectrumNumbers.size());
  for (size_t i = 0; i < nspec; ++i) {
    auto id = detectorIDs[i];
    if (ignoreIDs.count(id) == 0)
      m_mapping[spectrumNumbers[i]].insert(id);
92
  }
93
94
}
/// Default constructor;
95
96
SpectrumDetectorMapping::SpectrumDetectorMapping()
    : m_indexIsSpecNo(false), m_mapping() {}
97

98
/// @returns An ordered set of the unique spectrum numbers
99
100
std::set<specnum_t> SpectrumDetectorMapping::getSpectrumNumbers() const {
  std::set<specnum_t> specs;
101
102
103
  auto itend = m_mapping.end();
  for (auto it = m_mapping.begin(); it != itend; ++it) {
    specs.insert(it->first);
104
  }
105
106
  return specs;
}
107

108
const std::set<detid_t> &SpectrumDetectorMapping::getDetectorIDsForSpectrumNo(
109
    const specnum_t spectrumNo) const {
110
  if (!m_indexIsSpecNo)
Nick Draper's avatar
Nick Draper committed
111
112
    throw std::runtime_error(
        "Indices are in the spectrum detector map, not spectrum number.");
113
114
115
  return m_mapping.at(spectrumNo);
}

116
117
const std::set<detid_t> &
SpectrumDetectorMapping::getDetectorIDsForSpectrumIndex(
118
    const size_t spectrumIndex) const {
119
  if (m_indexIsSpecNo)
Nick Draper's avatar
Nick Draper committed
120
121
    throw std::runtime_error(
        "Spectrum numbers are in the spectrum detector map, not index.");
122
123
124
  return m_mapping.at(static_cast<int>(spectrumIndex));
}

125
126
127
128
const SpectrumDetectorMapping::sdmap &
SpectrumDetectorMapping::getMapping() const {
  return m_mapping;
}
129

130
131
132
133
bool SpectrumDetectorMapping::indexIsSpecNumber() const {
  return m_indexIsSpecNo;
}

134
135
} // namespace API
} // namespace Mantid