Cheetah - SKA - PSS - Prototype Time Domain Search Pipeline
SpCclTest.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/test/SpCclTest.h"
25 #include "cheetah/data/SpCcl.h"
26 #include "cheetah/data/SpCandidate.h"
27 #include "cheetah/data/DedispersionMeasure.h"
28 #include "cheetah/data/Units.h"
29 #include "cheetah/data/TimeFrequency.h"
30 #include "panda/Architecture.h"
31 #include <memory>
32 
33 namespace ska {
34 namespace cheetah {
35 namespace data {
36 namespace test {
37 
38 
39 SpCclTest::SpCclTest() : ::testing::Test()
40 {
41 }
42 
43 SpCclTest::~SpCclTest()
44 {
45 }
46 
47 void SpCclTest::SetUp()
48 {
49 }
50 
51 void SpCclTest::TearDown()
52 {
53 }
54 
58 TEST_F(SpCclTest, test_tf_blocks)
59 {
60  typedef typename SpCcl<uint8_t>::TimeFrequencyType TimeFrequencyType;
61 
62  //Generate two blocks of TF data and push to the block list
63  typename SpCcl<uint8_t>::BlocksType blocks;
64  {
65  std::shared_ptr<TimeFrequencyType> b1(new TimeFrequencyType(data::DimensionSize<data::Time>(1000), data::DimensionSize<data::Frequency>(10)));
66  std::shared_ptr<TimeFrequencyType> b2(new TimeFrequencyType(data::DimensionSize<data::Time>(100), data::DimensionSize<data::Frequency>(10)));
67  blocks.emplace_back(b1);
68  blocks.emplace_back(b2);
69  }
70 
71  //Create new SpCcl<uint8_t> instance
72  SpCcl<uint8_t> cand_list(blocks);
73 
74  //Retreive tf_blocks
75  auto const& blocks_ref = cand_list.tf_blocks();
76 
77  ASSERT_EQ(blocks_ref.size(), std::size_t(2));
78  ASSERT_EQ(blocks_ref[0]->number_of_spectra(), std::size_t(1000));
79  ASSERT_EQ(blocks_ref[1]->number_of_spectra(), std::size_t(100));
80 }
81 
82 TEST_F(SpCclTest, test_candidate_vector_behaviour)
83 {
84 
85  typedef SpCandidate<Cpu, float> SpCandidateType;
86  typedef SpCcl<uint8_t>::BlocksType::value_type::element_type TimeFrequencyType;
87 
88  std::size_t idx;
89 
90  //Create new SpCcl<uint8_t> instance
91  SpCcl<uint8_t> cand_list;
92 
93  ASSERT_EQ(cand_list.tf_blocks().size(),std::size_t(0));
94 
95  //set single pulse candidate dispersion measure
96  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
97  //set the single pulse candidate width to 1.24 ms
98  SpCandidateType::MsecTimeType width(0.001 * boost::units::si::seconds);
99  //set the single pulse start time to 2.23 seconds
100  SpCandidateType::MsecTimeType tstart(2.0 * boost::units::si::seconds);
101  //set the candidate significance
102  float sigma = 20.0;
103 
104  for (idx=0; idx<10; ++idx)
105  {
106  SpCandidateType candidate(dm, tstart, width, sigma, idx);
107  cand_list.push_back(candidate);
108  }
109 
110  // real check
111  ASSERT_EQ(cand_list.size(), std::size_t(10));
112 
113  for (idx=0; idx<10; ++idx)
114  {
115  auto const& cand = cand_list[idx];
116  ASSERT_EQ(cand.dm(), dm);
117  ASSERT_EQ(cand.tstart(), tstart);
118  ASSERT_EQ(cand.width(), width);
119  ASSERT_EQ(cand.sigma(), sigma);
120  ASSERT_EQ(cand.ident(), idx);
121  }
122 
123  SpCcl<uint8_t> cand_list2;
124 
125  for (idx=0; idx<10; ++idx)
126  {
127  SpCandidateType candidate(dm, tstart, width, sigma, idx);
128  cand_list2.emplace_back(std::move(candidate));
129  }
130 
131  // real check
132  ASSERT_EQ(cand_list.size(), std::size_t(10));
133 
134  for (idx=0; idx<10; ++idx)
135  {
136  auto const& cand = cand_list2[idx];
137  ASSERT_EQ(cand.dm(), dm);
138  ASSERT_EQ(cand.tstart(), tstart);
139  ASSERT_EQ(cand.width(), width);
140  ASSERT_EQ(cand.sigma(), sigma);
141  ASSERT_EQ(cand.ident(), idx);
142  }
143 }
144 
145 TEST_F(SpCclTest, test_candidate_dm_range)
146 {
147 
148  typedef SpCandidate<Cpu, float> SpCandidateType;
149  typedef SpCcl<uint8_t>::BlocksType::value_type::element_type TimeFrequencyType;
150 
151  std::size_t idx;
152 
153  //Create new SpCcl<uint8_t> instance
154  SpCcl<uint8_t> cand_list;
155 
156  ASSERT_EQ(cand_list.tf_blocks().size(),std::size_t(0));
157 
158  //set single pulse candidate dispersion measure
159  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
160  //set the single pulse candidate width to 1.24 ms
161  SpCandidateType::MsecTimeType width(0.001 * boost::units::si::seconds);
162  //set the single pulse start time to 2.23 seconds
163  SpCandidateType::MsecTimeType tstart(2.0 * boost::units::si::seconds);
164  //set the candidate significance
165  float sigma = 20.0;
166 
167  for (idx=0; idx<10; ++idx)
168  {
169  SpCandidateType candidate(dm, tstart, width, sigma, idx);
170  dm += SpCandidateType::Dm(1.0 * parsecs_per_cube_cm);
171  cand_list.push_back(candidate);
172  }
173 
174  ASSERT_EQ(cand_list.dm_range().first, SpCandidateType::Dm(12.0 * parsecs_per_cube_cm));
175  ASSERT_EQ(cand_list.dm_range().second, SpCandidateType::Dm(21.0 * parsecs_per_cube_cm));
176 
177  // Test removing candidates with the lowest Dm
178  cand_list.remove_if([](SpCandidateType const& s)
179  {
180  return s.dm() == SpCandidateType::Dm(12.0 * parsecs_per_cube_cm);
181  });
182  ASSERT_EQ(cand_list.dm_range().first, SpCandidateType::Dm(13.0 * parsecs_per_cube_cm));
183  ASSERT_EQ(cand_list.dm_range().second, SpCandidateType::Dm(21.0 * parsecs_per_cube_cm));
184 
185  // Test removing candidates with the highest Dm
186  cand_list.remove_if([](SpCandidateType const& s)
187  {
188  return s.dm() == SpCandidateType::Dm(21.0 * parsecs_per_cube_cm);
189  });
190  ASSERT_EQ(cand_list.dm_range().first, SpCandidateType::Dm(13.0 * parsecs_per_cube_cm));
191  ASSERT_EQ(cand_list.dm_range().second, SpCandidateType::Dm(20.0 * parsecs_per_cube_cm));
192 
193  // Test removing candidates neither highest or lowest
194  cand_list.remove_if([](SpCandidateType const& s)
195  {
196  return s.dm() == SpCandidateType::Dm(17.0 * parsecs_per_cube_cm);
197  });
198  ASSERT_EQ(cand_list.dm_range().first, SpCandidateType::Dm(13.0 * parsecs_per_cube_cm));
199  ASSERT_EQ(cand_list.dm_range().second, SpCandidateType::Dm(20.0 * parsecs_per_cube_cm));
200 
201 }
202 
203 TEST_F(SpCclTest, test_equalto_operator_no_data)
204 {
208  // Generate SpCcl instance
209  SpCcl<uint8_t> cand_list;
210  CandidateWindow window;
211  ASSERT_NO_THROW(cand_list.data_begin(window));
212  SpCcl<uint8_t>::ConstDataIterator it_begin = cand_list.data_begin(window);
213  SpCcl<uint8_t>::ConstDataIterator it_end = cand_list.data_end();
214  SpCcl<uint8_t>::ConstDataIterator it_end2 = cand_list.data_end();
215 
216  ASSERT_TRUE(it_end == it_end2);
217  ASSERT_FALSE(it_end != it_end2);
218  ASSERT_TRUE(it_begin == it_end);
219 }
220 
221 TEST_F(SpCclTest, test_emplace_back)
222 {
223  typedef SpCandidate<Cpu, float> SpCandidateType;
224  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
225  SpCandidateType::MsecTimeType width(0.001 * boost::units::si::seconds);
226  SpCandidateType::MsecTimeType tstart(2.0 * boost::units::si::seconds);
227  float sigma = 20.0;
228 
229  // just add a single candidate
230  SpCcl<uint8_t> cand_list;
231  SpCandidateType candidate(dm, tstart, width, sigma);
232  cand_list.emplace_back(std::move(candidate));
233  ASSERT_EQ(cand_list.size(), 1U);
234  auto const& cand = cand_list[0];
235  ASSERT_EQ(cand.dm(), dm);
236  ASSERT_EQ(cand.tstart(), tstart);
237  ASSERT_EQ(cand.width(), width);
238  ASSERT_EQ(cand.sigma(), sigma);
239 
240  // add an out of order candidate
241  SpCandidateType::MsecTimeType tstart2(1.0 * boost::units::si::seconds);
242  SpCandidateType candidate2(dm, tstart2, width, sigma);
243  cand_list.emplace_back(std::move(candidate2));
244  ASSERT_EQ(cand_list.size(), 2U);
245  auto const& cand0 = cand_list[0];
246  auto const& cand1 = cand_list[1];
247  ASSERT_EQ(cand0.tstart(), tstart2);
248  ASSERT_EQ(cand1.tstart(), tstart);
249 }
250 
251 TEST_F(SpCclTest, test_emplace_back_constructor_list)
252 {
253  typedef SpCandidate<Cpu, float> SpCandidateType;
254  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
255  SpCandidateType::MsecTimeType width(0.001 * boost::units::si::seconds);
256  SpCandidateType::MsecTimeType tstart(2.0 * boost::units::si::seconds);
257  float sigma = 20.0;
258 
259  typedef typename std::remove_const<SpCcl<uint8_t>::BlocksType::value_type::element_type>::type TimeFrequencyType;
260  data::DimensionSize<data::Time> number_of_spectra(4U);
261  data::DimensionSize<data::Frequency> number_of_channels(10U);
262 
263  auto f1 = data::TimeFrequency<Cpu, uint8_t>::FrequencyType(10.0 * boost::units::si::hertz);
264  auto f2 = data::TimeFrequency<Cpu, uint8_t>::FrequencyType(20.0 * boost::units::si::hertz);
265  auto delta = (f2 - f1)/ (double)(number_of_channels-1);
266  boost::units::quantity<MilliSeconds, double> delay =
267  (4.15 * 1000000.0 * boost::units::si::milli * boost::units::si::seconds) * ( dm * ( (1/(f1 * f1)) - (1/(f2 * f2)) )).value();
268 
269  std::shared_ptr<TimeFrequencyType> tf = std::make_shared<TimeFrequencyType>(number_of_spectra, number_of_channels);
270  tf->set_channel_frequencies_const_width( f2, -1.0 * delta );
271 
272  SpCcl<uint8_t> cand_list({tf});
273  cand_list.emplace_back(dm, tstart, width, sigma);
274 
275  ASSERT_EQ(cand_list.size(), 1U);
276  auto const& cand = cand_list[0];
277  ASSERT_EQ(cand.dm(), dm);
278  ASSERT_EQ(cand.tstart(), tstart);
279  ASSERT_DOUBLE_EQ(cand.tend().value(), (tstart + delay).value());
280  ASSERT_EQ(cand.width(), width);
281  ASSERT_EQ(cand.sigma(), sigma);
282 }
283 
284 TEST_F(SpCclTest, test_sort_behaviour)
285 {
286 
287  typedef SpCandidate<Cpu, float> SpCandidateType;
288  typedef SpCcl<uint8_t>::BlocksType::value_type::element_type TimeFrequencyType;
289 
290  std::size_t idx;
291 
292  //Create new SpCcl<uint8_t> instance
293  SpCcl<uint8_t> cand_list;
294 
295  SpCcl<uint8_t> cand_list2;
296 
297  ASSERT_EQ(cand_list.tf_blocks().size(),std::size_t(0));
298 
299  //set single pulse candidate dispersion measure
300  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
301  //set the single pulse candidate width to 1.24 ms
302  SpCandidateType::MsecTimeType width(0.001 * boost::units::si::seconds);
303  //set the single pulse start time to 2.23 seconds
304  SpCandidateType::MsecTimeType tstart(2.0 * boost::units::si::seconds);
305  //set the candidate significance
306  float sigma = 20.0;
307 
308  for (idx=0; idx<10; ++idx)
309  {
310 
311  SpCandidateType candidate(dm, tstart, width, sigma, idx);
312  cand_list.push_back(candidate);
313 
314  cand_list2.emplace(std::move(candidate));
315 
316  tstart += SpCandidateType::MsecTimeType(1.0*boost::units::si::seconds);
317  }
318 
319  // real check
320  ASSERT_EQ(cand_list.size(), std::size_t(10));
321 
322  SpCandidateType::MsecTimeType ststart(2.0 * boost::units::si::seconds);
323  for (idx=0; idx<10; ++idx)
324  {
325  SCOPED_TRACE(idx);
326  auto const& cand = cand_list[idx];
327  auto const& cand2 = cand_list2[idx];
328  ASSERT_EQ(cand.dm(), dm);
329  ASSERT_EQ(cand2.dm(), dm);
330  ASSERT_EQ(cand.tstart(), ststart);
331  ASSERT_EQ(cand2.tstart(), ststart);
332  ASSERT_EQ(cand.width(), width);
333  ASSERT_EQ(cand2.width(), width);
334  ASSERT_EQ(cand.sigma(), sigma);
335  ASSERT_EQ(cand2.sigma(), sigma);
336  ASSERT_EQ(cand.ident(), idx);
337  ASSERT_EQ(cand2.ident(), idx);
338  ststart += SpCandidateType::MsecTimeType(1.0*boost::units::si::seconds);
339  }
340 }
341 
342 TEST_F(SpCclTest, test_disordered_input_sort_behaviour)
343 {
344 
345  typedef SpCandidate<Cpu, float> SpCandidateType;
346  typedef SpCcl<uint8_t>::BlocksType::value_type::element_type TimeFrequencyType;
347  data::DimensionSize<data::Time> number_of_spectra(4U);
348  data::DimensionSize<data::Frequency> number_of_channels(10U);
349 
350  auto f1 = data::TimeFrequency<Cpu, uint8_t>::FrequencyType(10.0 * boost::units::si::hertz);
351  auto f2 = data::TimeFrequency<Cpu, uint8_t>::FrequencyType(20.0 * boost::units::si::hertz);
352  auto delta = (f2 - f1)/ (double)(number_of_channels-1);
353 
354 
355  std::shared_ptr<data::TimeFrequency<Cpu, uint8_t>> tf = std::make_shared<data::TimeFrequency<Cpu, uint8_t>>(number_of_spectra, number_of_channels);
356  tf->set_channel_frequencies_const_width( f2, -1.0 * delta );
357  ASSERT_EQ(tf->low_high_frequencies().first, f1);
358  ASSERT_EQ(tf->low_high_frequencies().second, f2);
359 
360  //Create new SpCcl<uint8_t> instance
361  SpCcl<uint8_t> cand_list({tf});
362  ASSERT_EQ(cand_list.tf_blocks().size(),std::size_t(1));
363  ASSERT_EQ(cand_list.tf_blocks()[0]->low_high_frequencies().first, f1);
364 
365  SpCcl<uint8_t> cand_list2({tf});
366  ASSERT_EQ(cand_list2.tf_blocks().size(),std::size_t(1));
367 
368  //set single pulse candidate dispersion measure
369  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
370  boost::units::quantity<MilliSeconds, double> delay =
371  (4.15 * 1000000.0 * boost::units::si::milli * boost::units::si::seconds) * ( dm * ( (1/(f1 * f1)) - (1/(f2 * f2)) )).value();
372 
373  //set the single pulse candidate width to 1.24 ms
374  SpCandidateType::MsecTimeType width(0.001 * boost::units::si::seconds);
375  //set the single pulse start time to 2.23 seconds
376  SpCandidateType::MsecTimeType tstart(11.0 * boost::units::si::seconds);
377  //set the candidate significance
378  float sigma = 20.0;
379 
380  for (std::size_t idx=0; idx<10; ++idx)
381  {
382 
383  SpCandidateType candidate(dm, tstart, width, sigma, idx);
384  cand_list.push_back_calculate_duration(candidate);
385  cand_list2.emplace_calculate_duration(std::move(candidate));
386  tstart -= SpCandidateType::MsecTimeType(1.0*boost::units::si::seconds);
387  }
388 
389  // real check
390  ASSERT_EQ(cand_list.size(), std::size_t(10));
391 
392  SpCandidateType::MsecTimeType ststart(2.0 * boost::units::si::seconds);
393  for (std::size_t idx=0; idx<10; ++idx)
394  {
395  SCOPED_TRACE(idx);
396  auto const& cand = cand_list[idx];
397  auto const& cand2 = cand_list2[idx];
398  ASSERT_EQ(cand.dm(), dm);
399  ASSERT_EQ(cand2.dm(), dm);
400  ASSERT_EQ(cand.tstart(), ststart);
401  ASSERT_DOUBLE_EQ(cand.tend().value(), (ststart + delay).value());
402  ASSERT_EQ(cand2.tstart(), ststart);
403  ASSERT_DOUBLE_EQ(cand2.tend().value(), (ststart + delay).value());
404  ASSERT_EQ(cand.width(), width);
405  ASSERT_EQ(cand2.width(), width);
406  ASSERT_EQ(cand.sigma(), sigma);
407  ASSERT_EQ(cand2.sigma(), sigma);
408  ASSERT_EQ(cand.ident(), 9-idx);
409  ASSERT_EQ(cand2.ident(), 9-idx);
410  ststart += SpCandidateType::MsecTimeType(1.0*boost::units::si::seconds);
411  }
412 }
413 
414 
415 TEST_F(SpCclTest, test_candidates_extraction)
416 {
417  typedef SpCandidate<Cpu, float> SpCandidateType;
418  typedef SpCcl<uint8_t>::BlocksType::value_type::element_type TimeFreqType;
419  TimeFrequency<Cpu, uint8_t> tf1(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(1024));
420  TimeFrequency<Cpu, uint8_t> tf2(data::DimensionSize<data::Time>(200),data::DimensionSize<data::Frequency>(1024));
421  TimeFrequency<Cpu, uint8_t> tf3(data::DimensionSize<data::Time>(300),data::DimensionSize<data::Frequency>(1024));
422 
423  tf1.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1000 * boost::units::si::milli * boost::units::si::seconds));
424  tf2.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1000 * boost::units::si::milli * boost::units::si::seconds));
425  tf3.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1000 * boost::units::si::milli * boost::units::si::seconds));
426 
427  SpCcl<uint8_t>::BlocksType tf_v;
428  // fill data
429  std::fill(tf1.begin(),tf1.end(),0);
430  std::fill(tf2.begin(),tf2.end(),1);
431  std::fill(tf3.begin(),tf3.end(),2);
432 
433  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf1));
434  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf2));
435  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf3));
436 
437  // Generate SpCcl instance
438  SpCcl<uint8_t> cand_list(tf_v);
439 
440  // Generate Candidates
441  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
442  //set the single pulse candidate width to 1.24 ms
443  SpCandidateType::MsecTimeType width(1 * boost::units::si::milli * boost::units::si::seconds);
444  //set the single pulse start time to 2.23 seconds
445  SpCandidateType::MsecTimeType tstart(5.0 * boost::units::si::seconds);
446  //set the candidate significance
447  float sigma = 20.0;
448  //set the tend;
449  SpCandidateType::MsecTimeType tend(2000 * boost::units::si::milli * boost::units::si::seconds);
450 
451  for (std::uint32_t idx=0; idx<30; ++idx)
452  {
453  SpCandidateType candidate(dm, tstart, width, sigma, idx);
454  candidate.duration_end(tend);
455  cand_list.push_back(candidate);
456  tstart += SpCandidateType::MsecTimeType(10*boost::units::si::seconds);
457  }
458 
459  // Run Data iterator instance here to extract candidates
460 
461  CandidateWindow window( 1000 * data::milliseconds, 1000 * data::milliseconds);
462 
463 
464 
465  SpCcl<uint8_t>::ConstDataIterator it_begin = cand_list.data_begin( window );
466  SpCcl<uint8_t>::ConstDataIterator it_end = cand_list.data_end();
467 
468  unsigned count=0;
469  while(it_begin != it_end)
470  {
471  // Check output
472  auto slice = *it_begin;
473  auto start_time = it_begin.start_time();
474  ASSERT_EQ(static_cast<std::size_t>(slice.size<data::Frequency>()),tf1.number_of_channels());
475  ASSERT_EQ(static_cast<std::size_t>(slice.size<data::Time>()), 4); // 1ms before and after for windowing, 2 ms wide candidates = 4ms
476  double ts = (pss::astrotypes::units::duration_cast<boost::units::quantity<MilliSeconds, double>>(start_time - tf1.start_time())).value();
477  double cts = (cand_list[count].tstart() - window.ms_before()).value();
478  ASSERT_DOUBLE_EQ(ts, cts);
479  ASSERT_NO_THROW(++it_begin);
480  ++count;
481  }
482 
483  ASSERT_EQ(count,cand_list.size());
484 }
485 
486 TEST_F(SpCclTest, test_candidate_extraction_begin_range)
487 {
488  /*
489  * @brief: Test case where the candidate is either at the beginning of the block
490  * or the end of the block. The test should resize the candidate window
491  * before extracting the slice of data.
492  */
493  typedef SpCandidate<Cpu, float> SpCandidateType;
494  typedef SpCcl<uint8_t>::BlocksType::value_type::element_type TimeFreqType;
495  TimeFrequency<Cpu, uint8_t> tf1(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(1024));
496 
497  tf1.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1*boost::units::si::seconds));
498  float sigma=20.0;
499 
500  SpCcl<uint8_t>::BlocksType tf_v;
501  // fill data
502  unsigned n=0;
503  std::generate(tf1.begin(),tf1.end(),[&](){return ++n;});
504 
505  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf1));
506  // Generate SpCcl instance
507  SpCcl<uint8_t> cand_list(tf_v);
508 
509  // Generate Candidates
510  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
511  //set the single pulse candidate width to 1 ms
512  SpCandidateType::MsecTimeType width(0.001 * boost::units::si::seconds);
513  //set the single pulse start time to the beginning
514  SpCandidateType::MsecTimeType tstart3(0.1 * boost::units::si::seconds);
515  // set the end time
516  SpCandidateType::MsecTimeType tend(2000 * boost::units::si::milli * boost::units::si::seconds);
517 
518 
519 
520  SpCandidateType candidate3(dm,tstart3,width,sigma, 3);
521  candidate3.duration_end(tend);
522  cand_list.push_back(candidate3);
523 
524  CandidateWindow window(150 * data::milliseconds,150 * data::milliseconds);
525 
526  SpCcl<uint8_t>::ConstDataIterator it_begin = cand_list.data_begin(window);
527  SpCcl<uint8_t>::ConstDataIterator it_end = cand_list.data_end();
528 
529  //unsigned ind=0;
530  auto tf_it = tf1.begin();
531  auto sl_it = (*it_begin).begin();
532 
533 
534  for (uint32_t ii=0; ii < 5120 ; ++ii )
535  {
536  ASSERT_EQ(*sl_it,*tf_it);
537  ++tf_it;
538  ++sl_it;
539  }
540 
541  unsigned count=0;
542  while(it_begin != it_end)
543  {
544  ASSERT_NO_THROW(++it_begin);
545  ++count;
546  }
547 
548  ASSERT_EQ(count,cand_list.size());
549 }
550 
551 TEST_F(SpCclTest, test_candidate_extraction_end_range)
552 {
553  /*
554  * @brief: Test case where the candidate is either at the beginning of the block
555  * or the end of the block. The test should resize the candidate window
556  * before extracting the slice of data.
557  */
558  typedef SpCandidate<Cpu, float> SpCandidateType;
559  typedef SpCcl<uint8_t>::BlocksType::value_type::element_type TimeFreqType;
560  TimeFrequency<Cpu, uint8_t> tf1(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(1024));
561 
562  tf1.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1*boost::units::si::seconds));
563  float sigma=20.0;
564 
565  SpCcl<uint8_t>::BlocksType tf_v;
566  // fill data
567  std::fill(tf1.begin(),tf1.end(),0);
568 
569  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf1));
570  // Generate SpCcl instance
571  SpCcl<uint8_t> cand_list(tf_v);
572 
573  // Generate Candidates
574  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
575  //set the single pulse candidate width to 1 ms
576  SpCandidateType::MsecTimeType width(0.001 * boost::units::si::seconds);
577  //set the single pulse start time to the end
578  SpCandidateType::MsecTimeType tstart(99.9 * boost::units::si::seconds);
579  // set end time
580  SpCandidateType::MsecTimeType tend(2000 * boost::units::si::milli * boost::units::si::seconds);
581 
582  SpCandidateType candidate(dm, tstart, width, sigma, 1);
583  candidate.duration_end(tend);
584  cand_list.push_back(candidate);
585 
586  CandidateWindow window(2000 * data::milliseconds,2000 * data::milliseconds);
587 
588  SpCcl<uint8_t>::ConstDataIterator it_begin = cand_list.data_begin(window);
589  SpCcl<uint8_t>::ConstDataIterator it_end = cand_list.data_end();
590 
591  auto tf_it = tf1.end();
592  tf_it = tf_it - 2048;
593  auto sl_it = (*it_begin).begin();
594 
595  for (uint32_t ii=0; ii < 2048; ++ii )
596  {
597  ASSERT_EQ(*sl_it,*tf_it);
598  ++tf_it;
599  ++sl_it;
600  }
601  unsigned count=0;
602  while(it_begin != it_end)
603  {
604  ASSERT_NO_THROW(++it_begin);
605  ++count;
606  }
607 
608  ASSERT_EQ(count,cand_list.size());
609 }
610 
611 TEST_F(SpCclTest, test_candidate_extraction_overlap)
612 {
613  /*
614  * @brief: Test when there are two candidates within the window of the first candidate.
615  * The expected behaviour is that the extractor should ignore the candidate i.e should not repeat the same data
616  * and move on to the next one.
617  */
618  typedef SpCandidate<Cpu, float> SpCandidateType;
619  typedef SpCcl<uint8_t>::BlocksType::value_type::element_type TimeFreqType;
620  TimeFrequency<Cpu, uint8_t> tf1(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(1024));
621 
622  tf1.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1*boost::units::si::seconds));
623  float sigma=20.0;
624 
625  SpCcl<uint8_t>::BlocksType tf_v;
626  // fill data
627  std::fill(tf1.begin(),tf1.end(),0);
628 
629  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf1));
630  // Generate SpCcl instance
631  SpCcl<uint8_t> cand_list(tf_v);
632 
633  // Generate Candidates
634  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
635  //set the single pulse candidate width to 1 ms
636  SpCandidateType::MsecTimeType width(0.001 * boost::units::si::seconds);
637  //set the single pulse start time to the beginning, middle and the end
638  SpCandidateType::MsecTimeType tstart(30 * boost::units::si::seconds);
639  SpCandidateType::MsecTimeType tstart2(29 * boost::units::si::seconds);
640  SpCandidateType::MsecTimeType tstart3(31 * boost::units::si::seconds);
641  // set tend
642  SpCandidateType::MsecTimeType tend(2000 * boost::units::si::milli * boost::units::si::seconds);
643 
644 
645  SpCandidateType candidate(dm, tstart, width, sigma, 1);
646  SpCandidateType candidate2(dm,tstart2,width,sigma, 2);
647  SpCandidateType candidate3(dm,tstart3,width,sigma, 3);
648  candidate.duration_end(tend);
649  candidate2.duration_end(tend);
650  candidate3.duration_end(tend);
651  cand_list.push_back(candidate);
652  cand_list.push_back(candidate2);
653  cand_list.push_back(candidate3);
654 
655  CandidateWindow window(1000 * data::milliseconds,1000 * data::milliseconds);
656 
657  SpCcl<uint8_t>::ConstDataIterator it_begin = cand_list.data_begin(window);
658  SpCcl<uint8_t>::ConstDataIterator it_end = cand_list.data_end();
659 
660  unsigned count=0;
661  while(it_begin != it_end)
662  {
663  ASSERT_NO_THROW(++it_begin);
664  count++;
665  }
666  ASSERT_EQ(count,cand_list.size()-2);
667 
668 }
669 
670 TEST_F(SpCclTest, test_candidate_spanning_multiple_blocks)
671 {
672  /*
673  * @brief: Tests whether a candidate that spans multiple blocks is extracted properly.
674  * checks that the data extracted match with the candidate
675  */
676  typedef SpCandidate<Cpu, float> SpCandidateType;
677  typedef SpCcl<uint8_t>::BlocksType::value_type::element_type TimeFreqType;
678  TimeFrequency<Cpu, uint8_t> tf1(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(16));
679  TimeFrequency<Cpu, uint8_t> tf2(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(16));
680  TimeFrequency<Cpu, uint8_t> tf3(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(16));
681 
682  tf1.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1000 * boost::units::si::milli * boost::units::si::seconds));
683  tf2.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1000 * boost::units::si::milli * boost::units::si::seconds));
684  tf3.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1000 * boost::units::si::milli * boost::units::si::seconds));
685 
686  SpCcl<uint8_t>::BlocksType tf_v;
687  // fill data
688  std::fill(tf1.begin(),tf1.end(),0);
689  std::fill(tf2.begin(),tf2.end(),1);
690  std::fill(tf3.begin(),tf3.end(),2);
691 
692  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf1));
693  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf2));
694  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf3));
695 
696  // Generate SpCcl instance
697  SpCcl<uint8_t> cand_list(tf_v);
698 
699  // Generate Candidates
700  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
701  //set the single pulse candidate width to 1.24 ms
702  SpCandidateType::MsecTimeType width(1 * boost::units::si::milli * boost::units::si::seconds);
703  //set the single pulse start time to 2.23 seconds
704  SpCandidateType::MsecTimeType tstart(5 * boost::units::si::seconds);
705  //set the candidate significance
706  float sigma = 20.0;
707  //set end time
708  SpCandidateType::MsecTimeType tend(2000 * boost::units::si::milli * boost::units::si::seconds);
709 
710 
711 
712  SpCandidateType candidate(dm, tstart, width, sigma, 1);
713  candidate.duration_end(tend);
714  cand_list.push_back(candidate);
715 
716  CandidateWindow window(2000 * data::milliseconds,200000 * data::milliseconds);
717 
718  SpCcl<uint8_t>::ConstDataIterator it_begin = cand_list.data_begin(window);
719  SpCcl<uint8_t>::ConstDataIterator it_end = cand_list.data_end();
720 
721  // Check if we get all the data where the candidate exists
722  auto tf_it = tf1.begin();
723  tf_it = tf_it + 48;
724  auto sl_it1 = (*it_begin).begin();
725  for (uint32_t ii=0; ii < 1552; ++ii)
726  {
727  ASSERT_EQ(*sl_it1,*tf_it);
728  ++sl_it1;
729  ++tf_it;
730  }
731  ++it_begin;
732  auto sl_it2 = (*it_begin).begin();
733  auto tf_it2 = tf2.begin();
734  for (uint32_t ii=0; ii < 1600; ++ii)
735  {
736  ASSERT_EQ(*sl_it2,*tf_it2);
737  ++sl_it2;
738  ++tf_it2;
739  }
740  ++it_begin;
741  auto sl_it3 = (*it_begin).begin();
742  auto tf_it3 = tf3.begin();
743  for (uint32_t ii=0 ; ii < 112; ++ii)
744  {
745  ASSERT_EQ(*sl_it3,*tf_it3);
746  ++sl_it3;
747  ++tf_it3;
748  }
749 
750  ASSERT_NO_THROW(++it_begin);
751 
752 }
753 
754 TEST_F(SpCclTest, test_candidate_start_beyond_end)
755 {
756  /*
757  * @brief: Tests whether a candidate that starts beyond the end of block throws an exception.
758  *
759  */
760  typedef SpCandidate<Cpu, float> SpCandidateType;
761  typedef SpCcl<uint8_t>::BlocksType::value_type::element_type TimeFreqType;
762  TimeFrequency<Cpu, uint8_t> tf1(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(16));
763 
764  tf1.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1000 * boost::units::si::milli * boost::units::si::seconds));
765 
766  SpCcl<uint8_t>::BlocksType tf_v;
767  // fill data
768  std::fill(tf1.begin(),tf1.end(),0);
769 
770  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf1));
771 
772  // Generate SpCcl instance
773  SpCcl<uint8_t> cand_list(tf_v);
774 
775  // Generate Candidates
776  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
777  //set the single pulse candidate width to 1.24 ms
778  SpCandidateType::MsecTimeType width(1 * boost::units::si::milli * boost::units::si::seconds);
779  //set the single pulse start time to 2.23 seconds
780  SpCandidateType::MsecTimeType tstart(105 * boost::units::si::seconds);
781  //set the candidate significance
782  float sigma = 20.0;
783  //set end time
784  SpCandidateType::MsecTimeType tend(2000 * boost::units::si::milli * boost::units::si::seconds);
785 
786 
787 
788  SpCandidateType candidate(dm, tstart, width, sigma, 1);
789  candidate.duration_end(tend);
790  cand_list.push_back(candidate);
791 
792  CandidateWindow window(2000 * data::milliseconds,2000 * data::milliseconds);
793 
794  //SpCcl<uint8_t>::ConstDataIterator it_begin = cand_list.data_begin(window);
795  //SpCcl<uint8_t>::ConstDataIterator it_end = cand_list.data_end();
796 
797  // Check if we exception is thrown
798  ASSERT_ANY_THROW(cand_list.data_begin(window));
799 
800 }
801 
802 TEST_F(SpCclTest, test_no_candidates)
803 {
807  // Generate SpCcl instance
808  SpCcl<uint8_t> cand_list;
809  CandidateWindow window;
810  ASSERT_NO_THROW(cand_list.data_begin(window));
811  SpCcl<uint8_t>::ConstDataIterator it_begin = cand_list.data_begin(window);
812  SpCcl<uint8_t>::ConstDataIterator it_end = cand_list.data_end();
813  while (it_begin != it_end)
814  {
815  ASSERT_NO_THROW(++it_begin);
816  }
817 
818 }
819 
820 TEST_F(SpCclTest, test_offset_time)
821 {
822  typedef SpCcl<uint8_t> SpCclType;
823  typedef SpCclType::BlocksType BlocksType;
824  typedef BlocksType::value_type::element_type TimeFrequencyType;
825 
826  TimeFrequencyType::TimeType sample_interval(64 * boost::units::si::milli * boost::units::si::seconds);
827 
828  BlocksType tf_v;
829  typename std::remove_const<TimeFrequencyType>::type tf1(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(16));
830  tf1.sample_interval(sample_interval);
831  tf_v.push_back(std::make_shared<TimeFrequencyType>(tf1));
832 
833  for(data::DimensionIndex<data::Time> offset(0); offset < tf1.number_of_spectra(); ++offset) {
834  SpCclType cand_list(tf_v, offset);
835  ASSERT_DOUBLE_EQ(pss::astrotypes::units::duration_cast<TimeFrequencyType::TimeType>(cand_list.offset_time()).value(), (offset * sample_interval).value());
836  }
837 }
838 
839 TEST_F(SpCclTest, test_candidate_start_multiple_blocks_behind)
840 {
841  /*
842  * @brief: Tests whether a candidate that has the window spanning multiple blocks behind the actual start time is extracted properly.
843  * checks that the data extracted match with the candidate
844  */
845  typedef SpCandidate<Cpu, float> SpCandidateType;
846  typedef SpCcl<uint8_t>::BlocksType::value_type::element_type TimeFreqType;
847  TimeFrequency<Cpu, uint8_t> tf1(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(16));
848  TimeFrequency<Cpu, uint8_t> tf2(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(16));
849  TimeFrequency<Cpu, uint8_t> tf3(data::DimensionSize<data::Time>(100),data::DimensionSize<data::Frequency>(16));
850 
851  tf1.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1000 * boost::units::si::milli * boost::units::si::seconds));
852  tf2.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1000 * boost::units::si::milli * boost::units::si::seconds));
853  tf3.sample_interval(data::TimeFrequency<Cpu, uint8_t>::TimeType(1000 * boost::units::si::milli * boost::units::si::seconds));
854 
855  SpCcl<uint8_t>::BlocksType tf_v;
856  // fill data
857  std::fill(tf1.begin(),tf1.end(),0);
858  std::fill(tf2.begin(),tf2.end(),1);
859  std::fill(tf3.begin(),tf3.end(),2);
860 
861  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf1));
862  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf2));
863  tf_v.push_back(std::make_shared<TimeFrequency<Cpu, uint8_t>>(tf3));
864 
865  // Generate SpCcl instance
866  SpCcl<uint8_t> cand_list(tf_v);
867 
868  // Generate Candidates
869  typename SpCandidateType::Dm dm(12.0 * parsecs_per_cube_cm);
870  //set the single pulse candidate width to 1.24 ms
871  SpCandidateType::MsecTimeType width(1 * boost::units::si::milli * boost::units::si::seconds);
872  //set the single pulse start time to 2.23 seconds
873  SpCandidateType::MsecTimeType tstart(250 * boost::units::si::seconds);
874  //set the candidate significance
875  float sigma = 20.0;
876  //set end time
877  SpCandidateType::MsecTimeType tend(2000 * boost::units::si::milli * boost::units::si::seconds);
878 
879 
880 
881  SpCandidateType candidate(dm, tstart, width, sigma, 1);
882  candidate.duration_end(tend);
883  cand_list.push_back(candidate);
884 
885  CandidateWindow window(200000 * data::milliseconds,10000 * data::milliseconds);
886 
887  SpCcl<uint8_t>::ConstDataIterator it_begin = cand_list.data_begin(window);
888  SpCcl<uint8_t>::ConstDataIterator it_end = cand_list.data_end();
889 
890  // Check if we get all the data where the candidate exists
891  auto tf_it = tf1.begin();
892  tf_it = tf_it + 800;
893  auto sl_it1 = (*it_begin).begin();
894  for (uint32_t ii=0; ii < 800; ++ii)
895  {
896  ASSERT_EQ(*sl_it1,*tf_it);
897  ++sl_it1;
898  ++tf_it;
899  }
900  ++it_begin;
901  auto sl_it2 = (*it_begin).begin();
902  auto tf_it2 = tf2.begin();
903  for (uint32_t ii=0; ii < 1600; ++ii)
904  {
905  ASSERT_EQ(*sl_it2,*tf_it2);
906  ++sl_it2;
907  ++tf_it2;
908  }
909  ++it_begin;
910  auto sl_it3 = (*it_begin).begin();
911  auto tf_it3 = tf3.begin();
912  for (uint32_t ii=0 ; ii < 992; ++ii)
913  {
914  ASSERT_EQ(*sl_it3,*tf_it3);
915  ++sl_it3;
916  ++tf_it3;
917  }
918 
919  ASSERT_NO_THROW(++it_begin);
920 
921 }
922 
923 } // namespace test
924 } // namespace data
925 } // namespace cheetah
926 } // namespace ska
Some limits and constants for FLDO.
Definition: Brdz.h:35