A library for working with phylogenetic and population genetic data.
v0.32.0
queue_window_stream.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_POPULATION_WINDOW_QUEUE_WINDOW_STREAM_H_
2 #define GENESIS_POPULATION_WINDOW_QUEUE_WINDOW_STREAM_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2024 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lucas.czech@sund.ku.dk>
23  University of Copenhagen, Globe Institute, Section for GeoGenetics
24  Oster Voldgade 5-7, 1350 Copenhagen K, Denmark
25 */
26 
38 
39 #include <cassert>
40 #include <deque>
41 #include <functional>
42 #include <stdexcept>
43 #include <string>
44 #include <tuple>
45 #include <type_traits>
46 #include <utility>
47 
48 namespace genesis {
49 namespace population {
50 
51 // =================================================================================================
52 // Queue Window Stream
53 // =================================================================================================
54 
130 template<class InputStreamIterator, class DataType = typename InputStreamIterator::value_type>
131 class QueueWindowStream final : public BaseWindowStream<InputStreamIterator, DataType>
132 {
133 public:
134 
135  // -------------------------------------------------------------------------
136  // Typedefs and Enums
137  // -------------------------------------------------------------------------
138 
141 
143  using Entry = typename Window::Entry;
144  using InputType = typename InputStreamIterator::value_type;
145 
146  using iterator_category = std::input_iterator_tag;
148  using pointer = value_type*;
150  using const_reference = value_type const&;
151 
152  // -------------------------------------------------------------------------
153  // Public Functors
154  // -------------------------------------------------------------------------
155 
165  std::function<bool( InputType const& )> entry_selection_function;
166 
167  // ======================================================================================
168  // Internal Iterator
169  // ======================================================================================
170 
174  class DerivedIterator final : public BaseWindowStream<InputStreamIterator, DataType>::BaseIterator
175  {
176  // -------------------------------------------------------------------------
177  // Typedefs and Enums
178  // -------------------------------------------------------------------------
179 
180  public:
181 
182  using self_type = typename QueueWindowStream<
183  InputStreamIterator, DataType
185 
186  using base_iterator_type = typename BaseWindowStream<
187  InputStreamIterator, DataType
189 
191  using Entry = typename Window::Entry;
192  using InputType = typename InputStreamIterator::value_type;
193 
194  using iterator_category = std::input_iterator_tag;
196  using pointer = value_type*;
198  using const_reference = value_type const&;
199 
200  // -------------------------------------------------------------------------
201  // Constructors and Rule of Five
202  // -------------------------------------------------------------------------
203 
204  private:
205 
206  DerivedIterator() = default;
207 
209  QueueWindowStream const* parent
210  )
211  : base_iterator_type( parent )
212  , parent_( parent )
213  {
214  // Edge case check. See Base for details.
215  if( ! parent_ ) {
216  return;
217  }
218 
219  // Check that our selection functor is set up. The other three are already checked
220  // in the base class, which is called from the delegated constructor call above.
221  if( ! parent->entry_selection_function ) {
222  throw std::runtime_error(
223  "Need to set BaseWindowStream::entry_selection_function "
224  "before iterating over Windows with a QueueWindowStream."
225  );
226  }
227 
228  // Check our own the settings.
229  if( parent_->count_ == 0 ) {
230  throw std::runtime_error(
231  "Cannot use QueueWindowStream with count == 0."
232  );
233  }
234  if( parent_->stride_ == 0 ) {
235  parent_->stride_ = parent_->count_;
236  }
237  if( parent_->stride_ > parent_->count_ ) {
238  throw std::runtime_error(
239  "Cannot use QueueWindowStream with stride > count."
240  );
241  }
242 
243  // Let's get going.
244  init_chromosome_();
245 
246  // If the input is empty (no data at all), we might already be done.
247  // If not, fill the window with data.
248  if( parent_ ) {
249  update_();
250  }
251  }
252 
253  public:
254 
255  virtual ~DerivedIterator() override = default;
256 
257  DerivedIterator( self_type const& ) = default;
258  DerivedIterator( self_type&& ) = default;
259 
260  DerivedIterator& operator= ( self_type const& ) = default;
261  DerivedIterator& operator= ( self_type&& ) = default;
262 
264 
265  // -------------------------------------------------------------------------
266  // Internal and Virtual Members
267  // -------------------------------------------------------------------------
268 
269  private:
270 
271  void init_chromosome_()
272  {
273  // Check that we are still good. If not, this function being called is likely a user
274  // error by trying to increment a past-the-end iterator.
275  assert( parent_ );
276 
277  // At the beginning of a chromosome, we should never have anything buffered.
278  assert( tail_buffer_.empty() );
279  assert( input_chromosome_finished_() );
280 
281  // Saveguard. This might be called on an empty range, in which case we just do nothing.
282  if( base_iterator_type::current_ == base_iterator_type::end_ ) {
283  parent_ = nullptr;
284  return;
285  }
286 
287  // Clear the window and prepare for new chromosome.
288  window_.clear();
289  window_.chromosome( parent_->chromosome_function( *base_iterator_type::current_ ));
290  next_index_ = 0;
291  current_queue_pop_count_.clear();
292  base_iterator_type::is_first_window_ = true;
293  base_iterator_type::is_last_window_ = false;
294  }
295 
296  void increment_() override final
297  {
298  // Basic check again.
299  assert( parent_ );
300 
301  // Special case: If we have no more underlying data, the iterator still needs to stop
302  // at the last window(s), so that they can be processed. After that, when this
303  // increment_() function is called again by the user, we then set parent_ = nullptr
304  // to indicate that now we are done for good.
305  if(
306  base_iterator_type::current_ == base_iterator_type::end_ &&
307  tail_buffer_.empty()
308  ) {
309  // If current_ == end_, we have definitely reached the end of the input, so we need
310  // to have set is_last_window_ previously. If not set, that means it was already
311  // reset, so that this is an iteration past the end.
312  if( ! base_iterator_type::is_last_window_ ) {
313  throw std::runtime_error( "QueueWindowStream: Incrementing past the end" );
314  }
315 
316  // Indicate that we are done now.
317  parent_ = nullptr;
318  return;
319  }
320 
321  // Check if this call moves to the next chromosome. If so, we clear everything and
322  // start all windows and buffers fresh for the new chromosome.
323  if( base_iterator_type::is_last_window_ ) {
324  assert( input_chromosome_finished_() );
325  init_chromosome_();
326  } else {
327  base_iterator_type::is_first_window_ = false;
328  }
329 
330  // Fill window with data.
331  update_();
332  }
333 
334  void update_()
335  {
336  // This function is only called when there is still data to be processed, which is
337  // either the case when the input has data, or at least the buffer has some.
338  assert( parent_ );
339  assert(
340  base_iterator_type::current_ != base_iterator_type::end_ ||
341  ! tail_buffer_.empty()
342  );
343 
344  // Two steps to update the queue.
345  pop_old_entries_();
346  push_new_entries_();
347 
348  // Update the window positions.
349  assert( ! window_.empty() );
350  window_.first_position( window_.entries().front().position );
351  window_.last_position( window_.entries().back().position );
352 
353  // Assert that all is good. We have some data, either the right amount,
354  // or less if we are at the end of the input or chromosome.
355  // In particular, after the update, we either have the window full of entries
356  // according to the count, or not, if it is the last window for the chromosome.
357  assert( window_.size() > 0 );
358  assert(
359  base_iterator_type::is_last_window_ ||
360  current_queue_pop_count_.size() == parent_->count_
361  );
362  assert(
363  base_iterator_type::is_last_window_ ||
364  window_.size() >= current_queue_pop_count_.front()
365  );
366 
367  // If we are at the last window, for sure we also must have finished the chromosome.
368  // The other way is not necessarily true (the two are not equivalent): It can be that
369  // the buffer contains the very last element of the current chromosome, but the input
370  // is already at the next. In that case, we are not yet at the last window (because we
371  // need to move and process the buffer first), but the input already is done with the
372  // chromosome. We test this as a logical implication here.
373  assert( ! base_iterator_type::is_last_window_ || input_chromosome_finished_() );
374 
375  // Unless it's the last window, we have some data in the buffer.
376  // If we are not yet in the last window, the push above will have put one entry in the
377  // buffer. If we _are_ at the last window, we have moved all remaining buffer data
378  // into the window already.
379  assert( tail_buffer_.empty() ^ !base_iterator_type::is_last_window_ );
380  }
381 
382  void pop_old_entries_()
383  {
384  // Before we update the window, we either have it full of entries, or its the first
385  // window for the chromosome (or first window at all).
386  assert(
387  ( current_queue_pop_count_.size() == parent_->count_ ) ||
388  ( current_queue_pop_count_.size() == 0 && base_iterator_type::is_first_window_ )
389  );
390 
391  // Dequeue everything that we do not want to keep. If stride == count (default case),
392  // we can simply remove everything at once, for speed. Otherwise, we pop as many
393  // entries as we have stride, but only counting the considered ones.
394  if( parent_->stride_ == parent_->count_ ) {
395  window_.entries().clear();
396  current_queue_pop_count_.clear();
397  } else if( current_queue_pop_count_.empty() ) {
398  // Edge case when we start with a new empty window.
399  assert( window_.empty() );
400  assert( current_queue_pop_count_.empty() );
401  assert( base_iterator_type::is_first_window_ );
402  } else {
403  assert( ! window_.empty() );
404  assert( ! current_queue_pop_count_.empty() );
405  assert( ! base_iterator_type::is_first_window_ );
406 
407  // Remove as many selected entries as the stride tells us.
408  // This means we also need to remove all non-selected entries along,
409  // which is what current_queue_pop_count_ tells us. For each selected entry,
410  // it tells us the number of total entries that we need to remove: itself,
411  // and all non-selected ones that came before it.
412  size_t removed_cnt = 0;
413  while( removed_cnt < parent_->stride_ ) {
414  // Remove a single selected entry form the window, along with all preceeding
415  // non-selected ones. The current_queue_pop_count_ queue tells us how many
416  // those are.
417  assert( ! current_queue_pop_count_.empty() );
418  assert( window_.size() >= current_queue_pop_count_.front() );
419  for( size_t i = 0; i < current_queue_pop_count_.front(); ++i ) {
420  assert( ! window_.empty() );
421  window_.entries().pop_front();
422  }
423  current_queue_pop_count_.pop_front();
424  ++removed_cnt;
425  }
426  assert( current_queue_pop_count_.size() > 0 );
427  assert( removed_cnt == parent_->stride_ );
428  }
429 
430  // We always have either an empty window, or one where we made room for another stride.
431  assert(
432  current_queue_pop_count_.size() == 0 ||
433  current_queue_pop_count_.size() == parent_->count_ - parent_->stride_
434  );
435  }
436 
437  void push_new_entries_()
438  {
439  // We need to keep track of how many entries were added for each stride.
440  // Otherwise, the user might modify the entries, and so we cannot check the
441  // entry_selection_function again when popping. Hence, instead, when pushing entries,
442  // we keep a queue of how many entries need to be popped in the next iteration.
443 
444  // Keep track of how many entries this function added, for some assertions only.
445  size_t add_cnt = 0;
446  (void) add_cnt;
447 
448  // First make sure we process any trailing entries from the previous iteration. If there
449  // is data in the tail buffer, that means it contains the next selected entry (and all
450  // the unselected ones before it) on the current chromosome.
451  if( tail_buffer_.empty() ) {
452  // The buffer is only empty when we start the iteration or end it, at the data end
453  // or at the end of the current chromosome. The assertion captures that.
454  assert(
455  ( base_iterator_type::is_first_window_ && window_.empty() ) ||
456  ( base_iterator_type::is_last_window_ && input_chromosome_finished_() )
457  );
458  } else {
459  // Here, we have a tail buffer, which means, we are still on the same chromosome,
460  // and have a selected entry at the end of the buffer. We first assert that then
461  // our window has some data from the previous iteration (or not, if the stride
462  // is the count, so that each window starts empty).
463  assert( ! window_.empty() || parent_->stride_ == parent_->count_ );
464  assert(
465  parent_->chromosome_function( tail_buffer_.back().data ) == window_.chromosome()
466  );
467  assert( parent_->entry_selection_function( tail_buffer_.back().data ) );
468 
469  // We now move the tail with the selected entry and all unselected before it
470  // from the buffer to our window, and increment the queue count accordingly.
471  current_queue_pop_count_.push_back( tail_buffer_.size() );
472  move_tail_buffer_to_window_();
473  assert( tail_buffer_.empty() );
474  ++add_cnt;
475  }
476 
477  // Now enqueue new entries to fill the queue.
478  bool finished_chromosome = false;
479  while( current_queue_pop_count_.size() < parent_->count_ ) {
480  // Try to find and enqueue the next selected entry into the window,
481  // as well as all unselected entries before it.
482  auto const& cur_chr = window_.chromosome();
483  auto const cur_pos = window_.size() == 0 ? 0 : window_.entries().back().position;
484  auto const add_result = add_entries_until_selected_to_queue_(
485  cur_chr, cur_pos, window_.entries()
486  );
487 
488  // Check if we got a selected entry. If so, we count it.
489  // If not, we reached the end of the chromosome or data, and so we leave this loop
490  // prematurely, without having filled the full queue.
491  if( add_result.second ) {
492  assert( add_result.first > 0 );
493  current_queue_pop_count_.push_back( add_result.first );
494  ++add_cnt;
495  } else {
496  finished_chromosome = true;
497  break;
498  }
499  }
500 
501  // The above loop filled the window with as many selected entries as we need.
502  // It could however be that there are no more selected entries on the chromosome
503  // after that, which we need to know now.
504  // So we read into the buffer, and test that. If so, we need to add that tail to
505  // the window as well. If not, we keep it in the buffer for the next iteration.
506  if( ! finished_chromosome ) {
507  assert( tail_buffer_.empty() );
508  assert( ! window_.empty() );
509 
510  // Read the next selected entry into the tail buffer
511  auto const& cur_chr = window_.chromosome();
512  auto const cur_pos = window_.size() == 0 ? 0 : window_.entries().back().position;
513  auto const add_result = add_entries_until_selected_to_queue_(
514  cur_chr, cur_pos, tail_buffer_
515  );
516 
517  // If we did not find a selected entry (only unselected, or nothing at all on this
518  // chromosome), we mark that we reached the end of the chromosome, for below.
519  if( add_result.second == false ) {
520  finished_chromosome = true;
521  }
522  }
523 
524  // If we ended the above loop without fully filling the window, or in the condition
525  // afterwards found that we are at the end of the chromosome, we are done with a
526  // chromosome (or the whole data). The tail buffer then contains all remaining
527  // unselected entries, which we hence need to add to the window, as this is the last
528  // window on the chromosome.
529  if( finished_chromosome ) {
530  assert(
531  tail_buffer_.empty() ||
532  ! parent_->entry_selection_function( tail_buffer_.back().data )
533  );
534  assert( input_chromosome_finished_() );
535  move_tail_buffer_to_window_();
536  base_iterator_type::is_last_window_ = true;
537  assert( tail_buffer_.empty() );
538  }
539 
540  // Either we have added as many new entries as the stride tells us, or, if this
541  // was a new empty window, we have added a full count of entries,
542  // or we reached the end of the data or the end of the chromosome.
543  // Also, we can never have _more_ entries in the window, and we cannot have an empty
544  // window, as in that case this update function should not have been called at all.
545  assert(
546  add_cnt == parent_->stride_ ||
547  ( add_cnt == parent_->count_ && base_iterator_type::is_first_window_ ) ||
548  ( base_iterator_type::is_last_window_ && input_chromosome_finished_() )
549  );
550  assert( add_cnt <= parent_->count_ );
551  assert( add_cnt <= window_.size() );
552  }
553 
554  std::pair<size_t, bool> add_entries_until_selected_to_queue_(
555  std::string const& prev_chr, size_t prev_pos, std::deque<typename Window::Entry>& target
556  ) {
557  // The caller needs to know how many entries we added in total,
558  // and whether we found a selected entry, or reached the end of the chr/data instead.
559  size_t added_count = 0;
560  bool found_selected = false;
561 
562  // Add entries from the input source to the target queue, stopping at the first entry
563  // for which the selection function is true, or when we reach the end of the chr or data.
564  while( true ) {
565  // If we are at the end of the data, there is no selected entry here.
566  if( base_iterator_type::current_ == base_iterator_type::end_ ) {
567  break;
568  }
569 
570  // Get the chr and pos of this entry.
571  auto const cur_chr = parent_->chromosome_function( *base_iterator_type::current_ );
572  auto const cur_pos = parent_->position_function( *base_iterator_type::current_ );
573 
574  // If we are at the next chromosome, we are done with this window,
575  // again not having found a selected entry.
576  if( cur_chr != prev_chr ) {
577  break;
578  }
579 
580  // Check that we are not going backwards in the chromosome,
581  // i.e., if we got unsorted data. That would lead to unwanted behaviour.
582  if( prev_pos >= cur_pos ) {
583  throw std::runtime_error(
584  "Invalid entry in queue window that not in sequence with other entries. "
585  "Previous entry is " + prev_chr + ":" + std::to_string( prev_pos ) +
586  ", current (invalid) entry is " + prev_chr + ":" + std::to_string( cur_pos )
587  );
588  }
589 
590  // Finally, enqueue the entry, and move to the next entry of the input,
591  // as well as update all involved counters and helpers.
592  using WindowEntry = typename Window::Entry;
593  target.push_back(
594  WindowEntry(
595  next_index_,
596  cur_pos,
597  parent_->entry_input_function( *base_iterator_type::current_ )
598  )
599  );
600  ++base_iterator_type::current_;
601  ++next_index_;
602  ++added_count;
603  prev_pos = cur_pos;
604 
605  // We check if this entry is a selected one according to the function.
606  // If so, we are done here - we found the next selected entry.
607  assert( ! target.empty() );
608  if( parent_->entry_selection_function( target.back() )) {
609  found_selected = true;
610  break;
611  }
612  }
613  return { added_count, found_selected };
614  }
615 
616  void move_tail_buffer_to_window_()
617  {
618  // Move everything from the trailing list to our actual window.
619  // We can move, because we are sure not to need those entries in the buffer any more.
620  while( ! tail_buffer_.empty() ) {
621  // The trailing ones need to be non-selected, except potentially for the very last
622  // entry. This is because the add_entries_until_selected_to_queue_() functions,
623  // which we use to add entries to the trail buffer, stops when it reaches the first
624  // selected entry. As we have not exposed those entries to the user, they are
625  // unmodified from the input data, so we can evaluate the selection function here
626  // again, to assert this.
627  assert(
628  ! parent_->entry_selection_function( tail_buffer_.front().data ) ||
629  tail_buffer_.size() == 1
630  );
631 
632  // We also check that the chromosome is the same and the entries are in order.
633  assert(
634  window_.empty() || (
635  window_.chromosome() == parent_->chromosome_function( tail_buffer_.front() ) &&
636  window_.entries().back().position <
637  parent_->position_function( tail_buffer_.front() )
638  )
639  );
640 
641  // Now move the entry from the trailing list to our actual window.
642  window_.entries().push_back( std::move( tail_buffer_.front() ));
643  tail_buffer_.pop_front();
644  }
645  }
646 
647  inline bool input_chromosome_finished_() const
648  {
649  // Helper function used in assertions to test that the input iterator is at another
650  // chromosome compared to the current window (or the end of the data).
651  return (
652  base_iterator_type::current_ == base_iterator_type::end_ ||
653  parent_->chromosome_function( *base_iterator_type::current_ ) !=
654  window_.chromosome()
655  );
656  }
657 
658  value_type& get_current_window_() const override final
659  {
660  return const_cast<value_type&>( window_ );
661  }
662 
663  BaseWindowStream<InputStreamIterator, DataType> const* get_parent_() const override final
664  {
665  return parent_;
666  }
667 
668  private:
669 
670  // Parent. Needs to live here to have the correct derived type.
671  QueueWindowStream const* parent_ = nullptr;
672 
673  // Current window and its position
674  Window window_;
675  size_t next_index_ = 0;
676 
677  // Keep track of the current number of queued (selected) entries in the window, as well
678  // as how many non-selected there are as well. We do this as follows: each item in the
679  // current_queue_pop_count_ list represents one entry of our input data for which the
680  // entry_selection_function returned true (i.e., one entry that we queue in the window).
681  // The value of the item here then indicates the _total_ number of entries from our input
682  // that came along with that one selected entry - in addition to that entry itself, this
683  // is the number of all non-selected entries from our input that came before the selected
684  // one (but after the previous selected one).
685  // We need this to keep track of how many selected entries (the ones considered due to the
686  // entry_selection_function) we have in each step of the iteration, so that we can remove
687  // the right amount for each stride. This counts _all_ entries. We need this as otherwise
688  // we would need to evaluate the entry_selection_function again when dequeueing, which
689  // could lead to wrong results if the user has changed the data during iteration.
690  // So, we only evaluate entry_selection_function when pushing items, and here keep track
691  // of how many need to be popped later again.
692  // For each selected entry, the queue contains the total number of entries that need to be
693  // popped from the front in order to remove that selected entry. That is, it contains the
694  // count of all non-selected entries before the selected one, plus that one itself.
695  std::deque<size_t> current_queue_pop_count_;
696 
697  // Furthermore, in order to be able to handle the last window correclty, we need to have
698  // an intermediate storage of the trailing entries up until either the next selected entry,
699  // or the end of the chromosome or data. Otherwise, we could have a last window
700  // that just happens to have the exact right number of selected entries, but when there are
701  // no more selected entries afterwards in the input data, all not-selected ones would be
702  // missed. So whenever we have filled a window with all selected entries, we need to keep
703  // one next set of entries (up until the next selected one) here first.
704  std::deque<typename Window::Entry> tail_buffer_;
705  };
706 
707  // ======================================================================================
708  // Main Class
709  // ======================================================================================
710 
711  // -------------------------------------------------------------------------
712  // Constructors and Rule of Five
713  // -------------------------------------------------------------------------
714 
716  InputStreamIterator begin, InputStreamIterator end,
717  size_t count = 0, size_t stride = 0
718  )
719  : base_type( begin, end )
720  , count_( count )
721  , stride_( stride )
722  {}
723 
724  virtual ~QueueWindowStream() override = default;
725 
726  QueueWindowStream( QueueWindowStream const& ) = default;
727  QueueWindowStream( QueueWindowStream&& ) = default;
728 
729  QueueWindowStream& operator= ( QueueWindowStream const& ) = default;
731 
733 
734  // -------------------------------------------------------------------------
735  // Settings
736  // -------------------------------------------------------------------------
737 
746  self_type& count( size_t value )
747  {
748  count_ = value;
749  return *this;
750  }
751 
752  size_t count() const
753  {
754  return count_;
755  }
756 
766  self_type& stride( size_t value )
767  {
768  stride_ = value;
769  return *this;
770  }
771 
772  size_t stride() const
773  {
774  return stride_;
775  }
776 
777  // -------------------------------------------------------------------------
778  // Virtual Members
779  // -------------------------------------------------------------------------
780 
781 protected:
782 
783  std::unique_ptr<typename BaseWindowStream<InputStreamIterator, DataType>::BaseIterator>
784  get_begin_iterator_() override final
785  {
786  // Cannot use make_unique here, as the Iterator constructor is private,
787  // and trying to make make_unique a friend does not seem to be working...
788  return std::unique_ptr<DerivedIterator>( new DerivedIterator( this ));
789  // return utils::make_unique<DerivedIterator>( this );
790  }
791 
792  std::unique_ptr<typename BaseWindowStream<InputStreamIterator, DataType>::BaseIterator>
793  get_end_iterator_() override final
794  {
795  return std::unique_ptr<DerivedIterator>( new DerivedIterator( nullptr ));
796  // return utils::make_unique<DerivedIterator>( nullptr );
797  }
798 
799  // -------------------------------------------------------------------------
800  // Data Members
801  // -------------------------------------------------------------------------
802 
803 private:
804 
805  // Settings. We make stride_ mutable so that the iterator can set it to the count.
806  size_t count_ = 0;
807  mutable size_t stride_ = 0;
808 
809 };
810 
811 // =================================================================================================
812 // Make Queue Window Stream
813 // =================================================================================================
814 
822 template<class InputStreamIterator, class DataType = typename InputStreamIterator::value_type>
823 QueueWindowStream<InputStreamIterator, DataType>
825  InputStreamIterator begin, InputStreamIterator end, size_t count = 0, size_t stride = 0
826 ) {
827  auto it = QueueWindowStream<InputStreamIterator, DataType>( begin, end );
828  it.count( count );
829  it.stride( stride );
830  return it;
831 }
832 
853 template<class InputStreamIterator>
854 QueueWindowStream<InputStreamIterator>
856  InputStreamIterator begin, InputStreamIterator end, size_t count = 0, size_t stride = 0
857 ) {
858  using DataType = typename InputStreamIterator::value_type;
859 
860  // Set functors.
861  auto it = QueueWindowStream<InputStreamIterator>( begin, end );
862  it.entry_input_function = []( DataType const& variant ) {
863  return variant;
864  };
865  it.chromosome_function = []( DataType const& variant ) {
866  return variant.chromosome;
867  };
868  it.position_function = []( DataType const& variant ) {
869  return variant.position;
870  };
871  it.entry_selection_function = []( DataType const& variant ) {
872  (void) variant;
873  return true;
874  };
875 
876  // Set properties.
877  it.count( count );
878  it.stride( stride );
879  return it;
880 }
881 
893 template<class InputStreamIterator>
894 WindowViewStream<InputStreamIterator>
896  InputStreamIterator begin, InputStreamIterator end, size_t count, size_t stride = 0
897 ) {
899  make_default_queue_window_stream( begin, end, count, stride )
900  );
901 }
902 
917 template<class InputStreamIterator>
918 QueueWindowStream<InputStreamIterator>
920  InputStreamIterator begin, InputStreamIterator end, size_t count = 0, size_t stride = 0
921 ) {
922  using DataType = typename InputStreamIterator::value_type;
923 
924  // Set functors.
925  auto it = QueueWindowStream<InputStreamIterator>( begin, end );
926  it.entry_input_function = []( DataType const& variant ) {
927  return variant;
928  };
929  it.chromosome_function = []( DataType const& variant ) {
930  return variant.chromosome;
931  };
932  it.position_function = []( DataType const& variant ) {
933  return variant.position;
934  };
935  it.entry_selection_function = []( DataType const& variant ) {
936  return variant.status.passing();
937  };
938 
939  // Set properties.
940  it.count( count );
941  it.stride( stride );
942  return it;
943 }
944 
956 template<class InputStreamIterator>
957 WindowViewStream<InputStreamIterator>
959  InputStreamIterator begin, InputStreamIterator end, size_t count, size_t stride = 0
960 ) {
962  make_passing_variant_queue_window_stream( begin, end, count, stride )
963  );
964 }
965 
966 } // namespace population
967 } // namespace genesis
968 
969 #endif // include guard
genesis::population::BaseWindowStream
Base class for streams of Windows over the chromosomes of a genome.
Definition: base_window_stream.hpp:119
genesis::population::BaseWindowStream::BaseIterator::iterator_category
std::input_iterator_tag iterator_category
Definition: base_window_stream.hpp:491
base_window_stream.hpp
genesis::population::BaseWindowStream::chromosome_function
std::function< std::string(InputType const &)> chromosome_function
Functor that yields the current chromosome, given the input stream data.
Definition: base_window_stream.hpp:152
genesis::population::QueueWindowStream::DerivedIterator::QueueWindowStream
friend QueueWindowStream
Definition: queue_window_stream.hpp:263
genesis::population::BaseWindowStream< InputStreamIterator, typename InputStreamIterator::value_type >::end
Iterator end()
Definition: base_window_stream.hpp:759
genesis::population::QueueWindowStream::~QueueWindowStream
virtual ~QueueWindowStream() override=default
genesis::population::make_default_queue_window_view_stream
WindowViewStream< InputStreamIterator > make_default_queue_window_view_stream(InputStreamIterator begin, InputStreamIterator end, size_t count, size_t stride=0)
Helper class that creates a QueueWindowStream with default functors and wraps it in a WindowViewStrea...
Definition: queue_window_stream.hpp:895
genesis::population::QueueWindowStream::stride
size_t stride() const
Definition: queue_window_stream.hpp:772
genesis::population::Window< DataType >
genesis::population::make_default_queue_window_stream
QueueWindowStream< InputStreamIterator > make_default_queue_window_stream(InputStreamIterator begin, InputStreamIterator end, size_t count=0, size_t stride=0)
Helper function to instantiate a QueueWindowStream for a default use case.
Definition: queue_window_stream.hpp:855
genesis::population::QueueWindowStream::QueueWindowStream
QueueWindowStream(InputStreamIterator begin, InputStreamIterator end, size_t count=0, size_t stride=0)
Definition: queue_window_stream.hpp:715
genesis::population::QueueWindowStream::Entry
typename Window::Entry Entry
Definition: queue_window_stream.hpp:143
window_view.hpp
genesis::population::QueueWindowStream::InputType
typename InputStreamIterator::value_type InputType
Definition: queue_window_stream.hpp:144
genesis::population::BaseWindowStream::BaseIterator::value_type
WindowType value_type
Definition: base_window_stream.hpp:492
genesis::population::QueueWindowStream::operator=
QueueWindowStream & operator=(QueueWindowStream const &)=default
genesis::population::make_queue_window_stream
QueueWindowStream< InputStreamIterator, DataType > make_queue_window_stream(InputStreamIterator begin, InputStreamIterator end, size_t count=0, size_t stride=0)
Helper function to instantiate a QueueWindowStream without the need to specify the template parameter...
Definition: queue_window_stream.hpp:824
genesis::population::BaseWindowStream::BaseIterator::const_reference
value_type const & const_reference
Definition: base_window_stream.hpp:495
genesis::population::BaseWindowStream< InputStreamIterator, typename InputStreamIterator::value_type >::DataType
typename InputStreamIterator::value_type DataType
Definition: base_window_stream.hpp:128
genesis::population::QueueWindowStream::DerivedIterator
Internal iterator that produces Windows.
Definition: queue_window_stream.hpp:174
genesis::population::QueueWindowStream::count
size_t count() const
Definition: queue_window_stream.hpp:752
genesis::population::Window::size
size_t size() const
Get the number of D/Data Entries that are stored in the Window.
Definition: window.hpp:237
genesis::population::QueueWindowStream
Stream for Windows contaiing a queue of entries, i.e., sliding Windows of a fixed number of selected ...
Definition: queue_window_stream.hpp:131
genesis::population::QueueWindowStream::DerivedIterator::Entry
typename Window::Entry Entry
Definition: queue_window_stream.hpp:191
genesis::population::to_string
std::string to_string(GenomeLocus const &locus)
Definition: function/genome_locus.hpp:52
genesis::population::QueueWindowStream::DerivedIterator
friend DerivedIterator
Definition: queue_window_stream.hpp:732
genesis::population::make_passing_variant_queue_window_stream
QueueWindowStream< InputStreamIterator > make_passing_variant_queue_window_stream(InputStreamIterator begin, InputStreamIterator end, size_t count=0, size_t stride=0)
Helper function to instantiate a QueueWindowStream for a default use case with underlying data of typ...
Definition: queue_window_stream.hpp:919
genesis::population::BaseWindow::chromosome
std::string const & chromosome() const
Get the chromosome name that this Window belongs to.
Definition: base_window.hpp:90
genesis::population::Window::empty
bool empty() const
Return whether the Window is empty, that is, if it does not contain any Entries.
Definition: window.hpp:246
genesis::population::QueueWindowStream::DerivedIterator::base_iterator_type
typename BaseWindowStream< InputStreamIterator, DataType >::BaseIterator base_iterator_type
Definition: queue_window_stream.hpp:188
genesis::population::QueueWindowStream::const_reference
value_type const & const_reference
Definition: queue_window_stream.hpp:150
genesis::population::Window::entries
container const & entries() const
Immediate container access to the Data Entries.
Definition: window.hpp:362
genesis::population::BaseWindowStream::position_function
std::function< size_t(InputType const &)> position_function
Functor that yields the current position on the chromosome, given the input stream data.
Definition: base_window_stream.hpp:158
genesis::population::BaseWindowStream::BaseIterator::BaseIterator
BaseIterator()=default
genesis::population::BaseWindowStream::BaseIterator::self_type
typename BaseWindowStream< InputStreamType, DataType, WindowType >::BaseIterator self_type
Definition: base_window_stream.hpp:488
genesis::population::QueueWindowStream::DerivedIterator::value_type
Window value_type
Definition: queue_window_stream.hpp:195
genesis::population::QueueWindowStream::stride
self_type & stride(size_t value)
Stride of the Window, that is, how many entries to move forward with each iteration.
Definition: queue_window_stream.hpp:766
window_view_stream.hpp
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::population::QueueWindowStream::DerivedIterator::~DerivedIterator
virtual ~DerivedIterator() override=default
genesis::population::Window::Entry
Data that is stored per entry that was enqueued in a window.
Definition: window.hpp:125
genesis::population::BaseWindowStream< InputStreamIterator, typename InputStreamIterator::value_type >::begin
Iterator begin()
Definition: base_window_stream.hpp:747
genesis::population::QueueWindowStream::Window
::genesis::population::Window< DataType > Window
Definition: queue_window_stream.hpp:142
genesis::population::BaseWindow::clear
void clear()
Clear all data from the Window.
Definition: base_window.hpp:234
window.hpp
genesis::population::BaseWindowStream::entry_input_function
std::function< DataType(InputType const &)> entry_input_function
Functor to convert from the underlying input stream that provides the data to fill the windows to the...
Definition: base_window_stream.hpp:147
genesis::population::make_window_view_stream
WindowViewStream< typename T::InputStreamType, typename T::DataType > make_window_view_stream(T const &window_iterator)
Create a WindowViewStream that iterates some underlying BaseWindowStream.
Definition: window_view_stream.hpp:317
genesis::population::BaseWindowStream::BaseIterator::pointer
value_type * pointer
Definition: base_window_stream.hpp:493
genesis::population::QueueWindowStream::get_begin_iterator_
std::unique_ptr< typename BaseWindowStream< InputStreamIterator, DataType >::BaseIterator > get_begin_iterator_() override final
Get the begin iterator.
Definition: queue_window_stream.hpp:784
genesis::population::QueueWindowStream::entry_selection_function
std::function< bool(InputType const &)> entry_selection_function
Functor that takes an entry of the underlying input stream and returns whether that entry should be s...
Definition: queue_window_stream.hpp:165
genesis::population::BaseWindow::first_position
size_t first_position() const
Get the first position in the chromosome of the Window, that is, where the Window starts.
Definition: base_window.hpp:114
genesis::population::QueueWindowStream::DerivedIterator::operator=
DerivedIterator & operator=(self_type const &)=default
genesis::population::BaseWindow::last_position
size_t last_position() const
Get the last position in the chromosome of the Window, that is, where the Window ends.
Definition: base_window.hpp:134
genesis::population::BaseWindowStream::BaseIterator::reference
value_type & reference
Definition: base_window_stream.hpp:494
genesis::population::make_passing_variant_queue_window_view_stream
WindowViewStream< InputStreamIterator > make_passing_variant_queue_window_view_stream(InputStreamIterator begin, InputStreamIterator end, size_t count, size_t stride=0)
Helper class that creates a QueueWindowStream with default functions for Variant data,...
Definition: queue_window_stream.hpp:958
genesis::population::QueueWindowStream::iterator_category
std::input_iterator_tag iterator_category
Definition: queue_window_stream.hpp:146
genesis::population::QueueWindowStream::DerivedIterator::Window
::genesis::population::Window< DataType > Window
Definition: queue_window_stream.hpp:190
genesis::population::BaseWindowStream::BaseIterator::InputType
typename InputStreamType::value_type InputType
Definition: base_window_stream.hpp:489
genesis::population::QueueWindowStream::count
self_type & count(size_t value)
Number of selected entries in each Window.
Definition: queue_window_stream.hpp:746
genesis::population::QueueWindowStream::get_end_iterator_
std::unique_ptr< typename BaseWindowStream< InputStreamIterator, DataType >::BaseIterator > get_end_iterator_() override final
Get the end iterator.
Definition: queue_window_stream.hpp:793