Cheetah - SKA - PSS - Prototype Time Domain Search Pipeline
TimeFrequencyContainer.cpp
1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2016 The SKA organisation
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "cheetah/data/TimeFrequencyContainer.h"
25 #include "panda/MultiIterator.h"
26 
27 
28 namespace ska {
29 namespace cheetah {
30 namespace data {
31 namespace {
32 
33 template<class TimeFrequencyType>
34 class TimeFrequencySampleIterator {
35  typedef typename TimeFrequencyType::ConstSpectra IteratorType;
36 
37  public:
38  TimeFrequencySampleIterator() // required for multiIterator
39  : _sample_number(0)
40  {
41  }
42 
43  TimeFrequencySampleIterator(TimeFrequencyType& tf) // end iterator constructor
44  : _sample_number(tf.number_of_spectra())
45  , _it(new IteratorType(tf.spectrum(_sample_number)))
46  {
47  }
48 
49  TimeFrequencySampleIterator(TimeFrequencyType& tf, std::size_t sample_number)
50  : _tf(tf.shared_from_this())
51  , _sample_number(sample_number)
52  , _it(new IteratorType(tf.spectrum(sample_number)))
53  {
54  }
55 
56 
57  bool operator==(TimeFrequencySampleIterator const& o) const
58  {
59  if(_tf == o._tf) {
60  return _sample_number == o._sample_number;
61  }
62  if(!_tf) { // local _tf is null
63  return o._sample_number == o._tf->number_of_spectra();
64  }
65  if(!o._tf) { // o._tf is null
66  return _sample_number == _tf->number_of_spectra();
67  }
68  return false; // o and t refere to different tf objects
69  }
70 
71  bool operator!=(TimeFrequencySampleIterator const& o) const
72  {
73  return !(o==*this);
74  }
75 
76  typename TimeFrequencyType::ConstSpectra& operator*() const
77  {
78  return *_it;
79  }
80 
81  TimeFrequencySampleIterator& operator++()
82  {
83  *_it = this->_tf->spectrum(++this->_sample_number);
84  return *this;
85  }
86 
87  TimeFrequencySampleIterator operator++(int)
88  {
89  TimeFrequencySampleIterator tmp(*this);
90  ++*this;
91  return tmp;
92  }
93 
94  protected:
95  std::shared_ptr<TimeFrequencyType> _tf;
96  std::size_t _sample_number;
97  mutable typename std::shared_ptr<IteratorType> _it;
98 };
99 
100 template<typename T, typename TimeFrequencyType, class ChannelIterationEndHandler, class TimeDiscontinuityHandler>
101 struct MultiIteratorDepthTraitsImpl : panda::DefaultIteratorDepthTraits<T>
102 {
103 };
104 
105 template<typename TimeFrequencyType, class ChannelIterationEndHandler, class TimeDiscontinuityHandler>
106 struct MultiIteratorDepthTraitsImpl<typename TimeFrequencyType::ConstSpectra::const_iterator, TimeFrequencyType, ChannelIterationEndHandler, TimeDiscontinuityHandler>
107  : public panda::IteratorDepthTraits<typename TimeFrequencyType::ConstSpectra::const_iterator, ChannelIterationEndHandler>
108 {
109  typedef panda::IteratorDepthTraits<typename TimeFrequencyType::ConstSpectra::const_iterator, ChannelIterationEndHandler> BaseT;
110  MultiIteratorDepthTraitsImpl()
111  {}
112  //using BaseT::IteratorDepthTraits;
113 };
114 
115 template<typename TimeFrequencyType, class ChannelIterationEndHandler, class TimeDiscontinuityHandler>
116 struct MultiIteratorDepthTraitsImpl<typename TimeFrequencyType::ConstSpectra, TimeFrequencyType, ChannelIterationEndHandler, TimeDiscontinuityHandler>
117  : public panda::IteratorDepthTraits<typename TimeFrequencyType::ConstSpectra, ChannelIterationEndHandler>
118 {
119  typedef panda::IteratorDepthTraits<typename TimeFrequencyType::ConstSpectra, ChannelIterationEndHandler> BaseT;
120  MultiIteratorDepthTraitsImpl(ChannelIterationEndHandler ch_handler)
121  : BaseT(ch_handler) {}
122  //using BaseT::IteratorDepthTraits;
123 };
124 
125 
126 // specialisation for TimeFrequency objects
127 template<typename TimeFrequencyType, class ChannelIterationEndHandler, class TimeDiscontinuityHandler>
128 struct MultiIteratorDepthTraitsImpl<const std::shared_ptr<TimeFrequencyType>, TimeFrequencyType, ChannelIterationEndHandler, TimeDiscontinuityHandler>
129  : public panda::IteratorDepthTraits<const std::shared_ptr<TimeFrequencyType>>
130 {
131  typedef TimeFrequencySampleIterator<const TimeFrequencyType> Iterator; // can be the end iterator
132 
133  MultiIteratorDepthTraitsImpl(TimeDiscontinuityHandler td_handler)
134  : _td_handler(td_handler)
135  , _expected_time(TimeFrequencyType::TimePointType::min())
136  , _last_interval(0.0 * boost::units::si::seconds)
137  {
138  }
139 
140  Iterator begin(TimeFrequencyType const& tf)
141  {
142  // check the time is as expected, or call the handler
143  auto const& interval = tf.sample_interval();
144  if(((tf.start_time() - _expected_time) >= 0.5 * interval) || interval != _last_interval)
145  {
146  _td_handler(tf.start_time(), tf.sample_interval());
147  }
148  _expected_time = tf.end_time() + interval;
149  _last_interval = interval;
150  return Iterator(tf, 0);
151  }
152 
153  Iterator begin(std::shared_ptr<TimeFrequencyType> const& tf)
154  {
155  if(tf) return begin(*tf);
156  throw panda::Error("shared_ptr not initialised");
157  }
158 
159  Iterator end(TimeFrequencyType const& tf)
160  {
161  return Iterator(tf);
162  }
163 
164  Iterator end(std::shared_ptr<TimeFrequencyType> const& tf)
165  {
166  return end(*tf);
167  }
168 
169  private:
170  TimeDiscontinuityHandler _td_handler;
171  typename TimeFrequencyType::TimePointType _expected_time;
172  typedef typename TimeFrequencyType::TimePointType::rep Rep;
173  typename TimeFrequencyType::TimeType _last_interval;
174 };
175 
176 template<typename TimeFrequencyType, class ChannelIterationEndHandler, class TimeDiscontinuityHandler>
177 struct MultiIteratorDepthTraits
178 {
179  template <typename T> using DepthTraits = MultiIteratorDepthTraitsImpl<T, TimeFrequencyType, ChannelIterationEndHandler, TimeDiscontinuityHandler>;
180 };
181 
182 } // namespace
183 
184 template <class Arch, typename NumericalT>
186 {
187 };
188 
189 template <class Arch, typename NumericalT>
190 template <class ChannelIterationEndHandler, class TimeDiscontinuityHandler>
192  : public panda::MultiIterator<panda::MultiIteratorTraits
193  < const decltype(TimeFrequencyContainer<Arch, NumericalT>::_data)
194  , decltype(TimeFrequencyContainer<Arch, NumericalT>::_data.cbegin())
195  , MultiIteratorDepthTraits
196  <typename TimeFrequencyContainer<Arch, NumericalT>::TimeFrequencyType
197  , ChannelIterationEndHandler
198  , TimeDiscontinuityHandler
199  >::template DepthTraits
200  >
201  >
202 {
203  typedef decltype(TimeFrequencyContainer<Arch, NumericalT>::_data) ContainerType;
204  typedef panda::MultiIterator<panda::MultiIteratorTraits
205  < const ContainerType
207  , MultiIteratorDepthTraits
209  , ChannelIterationEndHandler
210  , TimeDiscontinuityHandler
211  >::template DepthTraits
212  >
213  > BaseT;
214 
215  ConstChannelIterator(TimeFrequencyContainer const& ts, ChannelIterationEndHandler ch_handler, TimeDiscontinuityHandler td_handler)
216  : BaseT(ts._data.begin(), ts._data.end()
217  , MultiIteratorDepthTraitsImpl<typename TimeFrequencyType::ConstSpectra, TimeFrequencyType, ChannelIterationEndHandler, TimeDiscontinuityHandler>(ch_handler)
218  , MultiIteratorDepthTraitsImpl<const std::shared_ptr<TimeFrequencyType>, TimeFrequencyType, ChannelIterationEndHandler, TimeDiscontinuityHandler>(td_handler))
219  {
220  }
221 
222  // the end iterator constructor
224  : BaseT(ts._data.begin(), ts._data.end()
225  , MultiIteratorDepthTraitsImpl<typename TimeFrequencyType::ConstSpectra, TimeFrequencyType, ChannelIterationEndHandler, TimeDiscontinuityHandler>(ChannelIterationEndHandler())
226  , MultiIteratorDepthTraitsImpl<const std::shared_ptr<TimeFrequencyType>, TimeFrequencyType, ChannelIterationEndHandler, TimeDiscontinuityHandler>(TimeDiscontinuityHandler()))
227  {
228  }
229 
230  template<class ChannelEndHandler, class TimeDiscoHandler>
231  bool operator==(ConstChannelIterator<ChannelEndHandler, TimeDiscoHandler> const& o) const
232  {
233  return BaseT::operator==(o);
234  }
235 
236  inline bool operator==(ConstEndChannelIterator) const
237  {
238  return BaseT::end();
239  }
240 
241  inline bool operator!=(ConstEndChannelIterator) const
242  {
243  return !BaseT::end();
244  }
245 
246  template<class ChannelEndHandler, class TimeDiscoHandler>
247  bool operator!=(ConstChannelIterator<ChannelEndHandler, TimeDiscoHandler> const& o) const
248  {
249  return BaseT::operator!=(o);
250  }
251 };
252 
253 template <class Arch, typename NumericalT>
255 {
256 }
257 
258 template <class Arch, typename NumericalT>
260 {
261 }
262 
263 template <class Arch, typename NumericalT>
265 {
266  _data.clear();
267  _number_of_spectra = 0;
268 }
269 
270 template <class Arch, typename NumericalT>
272 {
273  return _data.empty();
274 }
275 
276 template <class Arch, typename NumericalT>
277 void TimeFrequencyContainer<Arch, NumericalT>::add(std::shared_ptr<TimeFrequencyType> const& data)
278 {
279  if(!_data.empty()) {
280  if(data->number_of_channels() != number_of_channels()) {
281  panda::Error e("expecting ");
282  e << number_of_channels() << " channels, got " << data->number_of_channels();
283  throw e;
284  }
285  }
286  _number_of_spectra += data->number_of_spectra();
287  _data.push_back(data);
288 }
289 
290 template <class Arch, typename NumericalT>
292 {
293  this->add(data.shared_from_this());
294 }
295 
296 template <class Arch, typename NumericalT>
298 {
299  return _data[0]->number_of_channels();
300 }
301 
302 template <class Arch, typename NumericalT>
304 {
305  return _number_of_spectra;
306 }
307 
308 template <class Arch, typename NumericalT>
309 typename TimeFrequencyContainer<Arch, NumericalT>::TimePointType const& TimeFrequencyContainer<Arch, NumericalT>::start_time() const
310 {
311  return _data[0]->start_time();
312 }
313 
314 template <class Arch, typename NumericalT>
315 typename TimeFrequencyContainer<Arch, NumericalT>::TimeType TimeFrequencyContainer<Arch, NumericalT>::sample_interval() const
316 {
317  return _data[0]->sample_interval();
318 }
319 
320 template <class Arch, typename NumericalT>
321 std::vector<typename TimeFrequencyContainer<Arch, NumericalT>::TimeFrequencyType::FrequencyType> const& TimeFrequencyContainer<Arch, NumericalT>::channel_frequencies() const
322 {
323  return _data[0]->channel_frequencies();
324 }
325 
326 template<class Arch, typename NumericalT>
327 template<class ChannelIterationEndHandler, class TimeDiscontinuityHandler>
329 {
331 }
332 
333 /*
334 template<class Arch, typename NumericalT>
335 TimeFrequencyContainer<Arch, NumericalT>::ConstChannelIterator<> TimeFrequencyContainer<Arch, NumericalT>::end() const
336 {
337  //return EndConstChannelIterator<ConstChannelIterator<>>(*this);
338  return EndConstChannelIterator<TimeFrequencyContainer<Arch, NumericalT>, panda::NoOp, panda::NoOp>(_data.end(), panda::NoOp(), panda::NoOp());
339 }
340 */
341 
342 template<class Arch, typename NumericalT>
344 {
345  return ConstEndChannelIterator();
346 }
347 
348 } // namespace data
349 } // namespace cheetah
350 } // namespace ska
bool empty() const
return true if there is no data
Definition: Units.h:112
Provides the TimeFrequency API over a set of TimeFrequency objects.
Some limits and constants for FLDO.
Definition: Brdz.h:35
ConstEndChannelIterator end() const
return the end iterator
void add(TimeFrequencyType &data)
add data to the collection
ConstChannelIterator< ChannelIterationEndHandler, TimeDiscontinuityHandler > begin(ChannelIterationEndHandler, TimeDiscontinuityHandler) const
std::vector< FrequencyType > const & channel_frequencies() const