1 #ifndef GENESIS_POPULATION_WINDOW_SLIDING_WINDOW_GENERATOR_H_
2 #define GENESIS_POPULATION_WINDOW_SLIDING_WINDOW_GENERATOR_H_
45 namespace population {
172 template<
class D,
class A = EmptyAccumulator>
295 throw std::runtime_error(
"Cannot use SlidingWindowGenerator of width 0." );
300 if( stride_ > width_ ) {
301 throw std::runtime_error(
"Cannot use SlidingWindowGenerator with stride > width." );
367 return emit_incomplete_windows_;
379 emit_incomplete_windows_ = value;
423 return next_index_ == 0;
448 chromosome_start_plugins_.push_back(plugin);
457 chromosome_finish_plugins_.push_back(plugin);
466 enqueue_plugins_.push_back(plugin);
475 dequeue_plugins_.push_back(plugin);
484 emission_plugins_.push_back(plugin);
495 chromosome_start_plugins_.clear();
496 chromosome_finish_plugins_.clear();
497 enqueue_plugins_.clear();
498 dequeue_plugins_.clear();
499 emission_plugins_.clear();
537 enqueue_( position,
Data{ data });
548 enqueue_( position, std::move( data ));
564 enqueue_( position,
Data{ data });
574 enqueue_( position, std::move( data ));
616 if( next_index_ == 0 ) {
621 if( last_position == 0 ) {
622 last_position = current_start_ + width_;
628 size_t cur_end = window_.
entries().empty() ? 0 : window_.
entries().back().position;
629 cur_end = current_start_ > cur_end ? current_start_ - 1 : cur_end;
630 if( last_position <= cur_end ) {
631 throw std::runtime_error(
632 "Cannot call finish_chromosome() with position " +
std::to_string(last_position) +
633 ", as the current window/chromosome is already advanced up to position " +
640 synchronize_interval_( last_position );
641 assert( current_start_ <= last_position );
642 assert( last_position < current_start_ + width_ );
647 if( emit_incomplete_windows_ ) {
648 emit_window_( current_start_, last_position + 1, last_position + 1 );
652 throw std::runtime_error(
"Not yet implemented." );
658 for(
auto const& chromosome_finish_plugin : chromosome_finish_plugins_ ) {
659 if( chromosome_finish_plugin ) {
672 void enqueue_(
size_t position,
Data&& data )
676 if( next_index_ == 0 ) {
677 for(
auto const& chromosome_start_plugin : chromosome_start_plugins_ ) {
678 if( chromosome_start_plugin ) {
690 size_t cur_end = window_.
entries().empty() ? 0 : window_.
entries().back().position;
691 cur_end = current_start_ > cur_end ? current_start_ - 1 : cur_end;
692 if( position <= cur_end ) {
693 throw std::invalid_argument(
695 ", as the current window/chromosome is already advanced up to position " +
697 ". Either start a new window or a new chromosome within the window. "
698 "Note that this error might be caused by a VCF file that is not sorted by "
699 "chromosome and position."
702 assert( position >= current_start_ );
703 assert( window_.
entries().empty() || position > window_.
entries().back().position );
707 enqueue_interval_( position, std::move( data ));
709 throw std::runtime_error(
"Not yet implemented." );
724 void enqueue_interval_(
size_t position,
Data&& data )
729 synchronize_interval_( position );
730 assert( current_start_ <= position );
731 assert( position < current_start_ + width_ );
734 window_.
entries().emplace_back( next_index_, position, std::move( data ));
740 for(
auto const& enqueue_plugin : enqueue_plugins_ ) {
741 if( enqueue_plugin ) {
742 assert( window_.
entries().size() > 0 );
751 for(
auto it : window_.
entries() ) {
752 if( it.position < current_start_ || it.position >= current_start_ + width_ ) {
755 if( it.position < cur_pos ) {
758 cur_pos = it.position;
767 void synchronize_interval_(
size_t position )
773 assert( position >= current_start_ );
774 assert( window_.entries().empty() || window_.entries().back().position < position );
780 window_.entries().empty() || window_.entries().front().position >= current_start_
783 window_.entries().empty() || window_.entries().front().position < current_start_ + width_
786 window_.entries().empty() || window_.entries().back().position >= current_start_
789 window_.entries().empty() || window_.entries().back().position < current_start_ + width_
796 while( current_start_ + width_ <= position ) {
799 emit_window_( current_start_, current_start_ + width_, current_start_ + stride_ );
800 current_start_ += stride_;
804 assert( current_start_ <= position );
805 assert( position < current_start_ + width_ );
811 void emit_window_(
size_t first_position,
size_t last_position,
size_t dequeue_until )
819 for(
auto const& it : window_.entries() ) {
820 if( it.position < first_position || it.position >= last_position ) {
823 if( it.position < cur_pos ) {
826 cur_pos = it.position;
832 assert( last_position > first_position );
833 window_.first_position( first_position );
834 window_.last_position( last_position );
837 for(
auto const& emission_plugin : emission_plugins_ ) {
838 if( emission_plugin ) {
839 emission_plugin( window_ );
845 window_.entries().size() > 0 && window_.entries().front().position < dequeue_until
847 for(
auto const& dequeue_plugin : dequeue_plugins_ ) {
848 if( dequeue_plugin ) {
849 dequeue_plugin( window_.entries().front(), window_.accumulator() );
852 window_.entries().pop_front();
868 bool emit_incomplete_windows_ =
false;
871 size_t current_start_ = 0;
872 size_t next_index_ = 0;
876 std::vector<on_chromosome_start> chromosome_start_plugins_;
877 std::vector<on_chromosome_finish> chromosome_finish_plugins_;
878 std::vector<on_enqueue> enqueue_plugins_;
879 std::vector<on_dequeue> dequeue_plugins_;
880 std::vector<on_emission> emission_plugins_;
887 #endif // include guard