All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SlidingWindowCombinerAlg.cxx
Go to the documentation of this file.
1 /**
2  * @file icaruscode/PMT/Trigger/Algorithms/SlidingWindowCombinerAlg.cxx
3  * @brief Algorihtm to combine trigger channels into sliding windows.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date January 6, 2020
6  * @see icaruscode/PMT/Algorithms/Trigger/SlidingWindowCombinerAlg.h
7  */
8 
9 
10 // library header
12 
13 // C/C++ standard libraries
14 #include <algorithm> // std::sort()
15 #include <utility> // std::move()
16 
17 
18 // -----------------------------------------------------------------------------
20  Windows_t const& windows,
21  std::vector<raw::Channel_t> missingChannels /* = {} */,
22  bool requireFullCoverage /* = true */,
23  std::string logCategory /* = "SlidingWindowCombinerAlg" */
24  )
25  : fWindowChannels(sortedWindowChannels(windows))
26  , fMissingChannels(sortChannels(std::move(missingChannels)))
27  , fRequireFullCoverage(requireFullCoverage)
28  , fLogCategory(std::move(logCategory))
29  {}
30 
31 
32 // -----------------------------------------------------------------------------
34  (std::vector<TrackedTriggerGate_t> const& gates) const
35  -> std::vector<TrackedTriggerGate_t>
36 {
37 
38  TriggerGateIndex_t gateIndex { gates };
39 
40  checkInput(gateIndex);
41 
42  std::vector<TrackedTriggerGate_t> combinedGates;
43  for (std::vector<raw::Channel_t> const& channels: fWindowChannels) {
44  assert(!channels.empty());
45 
46  combinedGates.push_back(combineChannels(gateIndex, channels));
47 
48  } // for
49 
50  return combinedGates;
51 } // icarus::trigger::SlidingWindowCombinerAlg::combine()
52 
53 
54 // -----------------------------------------------------------------------------
56  (TriggerGateIndex_t const& gateIndex) const
57 {
58  /*
59  * Checks:
60  *
61  * * no gate is only partially contained in a window
62  * * no channel in the gates is skipped (optional)
63  *
64  */
65 
66  auto const isChannelInWindow
67  = [](raw::Channel_t channel, std::vector<raw::Channel_t> const& window)
68  { return std::binary_search(window.begin(), window.end(), channel); };
69 
70  std::set<TrackedTriggerGate_t const*> usedGates;
71  for (std::vector<raw::Channel_t> const& window: fWindowChannels) {
72 
73  for (raw::Channel_t const channel: window) {
74 
75  if (isMissingChannel(channel)) continue;
76 
77  //
78  // check that we have all the channels we need
79  //
80  TrackedTriggerGate_t const* gate = gateIndex.find(channel);
81  if (!gate) {
82  cet::exception e("SlidingWindowCombinerAlg");
83  e << "SlidingWindowCombinerAlg::checkInput(): No gate has channel "
84  << channel << ", required in the window including channels: ";
85  for (raw::Channel_t const channel: window) e << " " << channel;
86  e << ".\n";
87  throw e;
88  }
89 
90  //
91  // check that all channels of this gate are in this window
92  //
93  for (raw::Channel_t const gateChannel: gate->channels()) {
94  if (isChannelInWindow(gateChannel, window)) continue;
95 
96  cet::exception e("SlidingWindowCombinerAlg");
97  e << "SlidingWindowCombinerAlg::checkInput(): gate with channels {";
98  for (raw::Channel_t const channel: gate->channels())
99  e << " " << channel;
100  e << " } is not fully included in window including channels: ";
101  for (raw::Channel_t const channel: window) e << " " << channel;
102  e << " (" << gateChannel << " is missing).\n";
103  throw e;
104  } // for gate channels
105 
106  usedGates.insert(gate);
107  } // for channel in window
108 
109  } // for windows
110 
111  //
112  // check for channels that should be missing but are here
113  //
114  std::vector<raw::Channel_t> spuriousChannels;
115  for (raw::Channel_t const channel: fMissingChannels) {
116  if (gateIndex.find(channel)) spuriousChannels.push_back(channel);
117  } // for
118  if (!spuriousChannels.empty()) {
119  cet::exception e("SlidingWindowCombinerAlg");
120  e << "SlidingWindowCombinerAlg::checkInput(): "
121  << spuriousChannels.size() << " of the " << fMissingChannels.size()
122  << " supposedly missing channels are actually included:";
123  for (raw::Channel_t const channel: spuriousChannels) e << " " << channel;
124  e << "\n";
125  throw e;
126  }
127 
128  //
129  // check that all channels are here (except known missing ones)
130  //
131  if (fRequireFullCoverage) {
132  std::set<TrackedTriggerGate_t const*> allGates;
133  for (auto const channel: util::counter<raw::Channel_t >(gateIndex.nChannels())) {
134  if (isMissingChannel(channel)) continue;
135  allGates.insert(&(gateIndex[channel]));
136  }
137 
138  std::vector<TrackedTriggerGate_t const*> unusedGates;
139  std::set_difference(
140  allGates.cbegin(), allGates.cend(), usedGates.cbegin(), usedGates.cend(),
141  std::back_inserter(unusedGates)
142  );
143  if (!unusedGates.empty()) {
144  // we don't have much information to identify "which" gates...
145  cet::exception e("SlidingWindowCombinerAlg");
146  e << "SlidingWindowCombinerAlg::checkInput(): "
147  << "used only " << usedGates.size() << "/" << allGates.size()
148  << " input trigger gates, " << unusedGates.size() << " were not used:";
149  for (TrackedTriggerGate_t const* gate: unusedGates) {
150  e << "{";
151  for (raw::Channel_t const channel: gate->channels())
152  e << " ch:" << std::to_string(channel);
153  e << " }";
154  } // for
155  e << "\n";
156  throw e;
157  } // if unused
158  } // if full coverage
159 
160 } // icarus::trigger::SlidingWindowCombinerAlg::checkInput()
161 
162 
163 // -----------------------------------------------------------------------------
165  (TriggerGateIndex_t const& gates, WindowChannels_t const& channels) const
167 {
168  assert(!channels.empty());
169 
170  auto iChannel = firstChannelPresent(channels);
171  auto const cend = channels.end();
172  if (iChannel == cend) return {}; // empty gate, no channels inside
173 
174  TrackedTriggerGate_t const& firstGate = gates[*iChannel];
175 
176  // add the first gate
177  TrackedTriggerGate_t gate { firstGate };
178 
179  mf::LogTrace(fLogCategory) << "Input: " << firstGate;
180  while (++iChannel != cend) {
181  if (isMissingChannel(*iChannel)) continue;
182 
183  TrackedTriggerGate_t const& inputGate = gates[*iChannel];
184 
185  mf::LogTrace(fLogCategory) << "Input: " << inputGate;
186  mergeGateInto(gate, inputGate);
187 
188  } // while
189  mf::LogTrace(fLogCategory) << "Output: " << gate;
190 
191  return gate;
192 
193 } // icarus::trigger::SlidingWindowCombinerAlg::combineChannel()
194 
195 
196 // -----------------------------------------------------------------------------
198  (WindowChannels_t const& channels) const -> WindowChannels_t::const_iterator
199 {
200  auto iChannel = channels.begin();
201  auto const cend = channels.end();
202  while (iChannel != cend) if (!isMissingChannel(*iChannel)) return iChannel;
203  return cend;
204 } // icarus::trigger::SlidingWindowCombinerAlg::firstChannelPresent()
205 
206 
207 //------------------------------------------------------------------------------
210 {
211  // loose check: assumes channel sets of all possible inputs do not overlap
212  // and checks whether the destination has already any one of input channels
213  auto const& channels = dest.gate().channels();
214  if (inList(channels, *(input.gate().channels().begin()))) return false;
215 
216  dest = icarus::trigger::sumGates(std::move(dest), input);
217 
218  return true;
219 
220 } // icarus::trigger::SlidingWindowCombinerAlg::mergeGateInto()
221 
222 
223 // -----------------------------------------------------------------------------
225  (Windows_t const& windows) -> Windows_t
226 {
227  Windows_t newWindows { windows };
228  for (auto& window: newWindows) std::sort(window.begin(), window.end());
229  return newWindows;
230 } // icarus::trigger::SlidingWindowCombinerAlg::sortWindowChannels()
231 
232 
233 // -----------------------------------------------------------------------------
235  (std::vector<raw::Channel_t> channels) -> std::vector<raw::Channel_t>
236 {
237  std::sort(channels.begin(), channels.end());
238  return channels;
239 } // icarus::trigger::SlidingWindowCombinerAlg::sortChannels
240 
241 
242 // -----------------------------------------------------------------------------
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
void checkInput(TriggerGateIndex_t const &gates) const
Throws an exception if the gates are not suitable for input.
icarus::trigger::TriggerWindowChannels_t WindowChannels_t
Type of optical detector channel list in a window.
A wrapper to trigger gate objects tracking the input of operations.
icarus::trigger::TriggerWindowDefs_t Windows_t
Type of content of all windows.
TriggerGate_t const * find(raw::Channel_t const channel) const
Returns the gate corresponding to the specified channel.
auto cend(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:579
WindowChannels_t::const_iterator firstChannelPresent(WindowChannels_t const &channels) const
Returns an iterator to the first of the channels which is not missing.
fDetProps &fDetProps fDetProps &fDetProps fLogCategory
Algorithm to combine trigger channels into sliding windows.
auto sumGates(GateColl const &gates)
Sums all the gates in a collection.
static Windows_t sortedWindowChannels(Windows_t const &windows)
Returns windows with numerically sorted channel numbers.
TrackedTriggerGate_t combineChannels(TriggerGateIndex_t const &gates, WindowChannels_t const &channels) const
Returns the combination of the channels selected from the gates.
static bool mergeGateInto(TrackedTriggerGate_t &dest, TrackedTriggerGate_t const &input)
TriggerGate_t const & gate() const &
Returns the enclosed gate.
static std::vector< raw::Channel_t > sortChannels(std::vector< raw::Channel_t > channels)
Returns a sorted copy of channels.
std::string to_string(WindowPattern const &pattern)
std::vector< TrackedTriggerGate_t > combine(std::vector< TrackedTriggerGate_t > const &gates) const
Combines the gates according to the configured grouping.
do i e
Associates each optical detector channel to a gate.
decltype(auto) channels() const
Returns the list of channels of the enclosed gate.
SlidingWindowCombinerAlg(Windows_t const &windows, std::vector< raw::Channel_t > missingChannels={}, bool requireFullCoverage=true, std::string logCategory="SlidingWindowCombinerAlg")
Constructor: learns about the window pattern (keeps a reference).
unsigned int nChannels() const
Returns the total number of registered channels.