1 #ifndef GENESIS_POPULATION_WINDOW_SLIDING_WINDOW_GENERATOR_H_
2 #define GENESIS_POPULATION_WINDOW_SLIDING_WINDOW_GENERATOR_H_
45 namespace population {
164 template<
class D,
class A = EmptyAccumulator>
287 throw std::runtime_error(
"Cannot use SlidingWindowGenerator of width 0." );
292 if( stride_ > width_ ) {
293 throw std::runtime_error(
"Cannot use SlidingWindowGenerator with stride > width." );
359 return emit_incomplete_windows_;
371 emit_incomplete_windows_ = value;
415 return next_index_ == 0;
440 chromosome_start_plugins_.push_back(plugin);
449 chromosome_finish_plugins_.push_back(plugin);
458 enqueue_plugins_.push_back(plugin);
467 dequeue_plugins_.push_back(plugin);
476 emission_plugins_.push_back(plugin);
487 chromosome_start_plugins_.clear();
488 chromosome_finish_plugins_.clear();
489 enqueue_plugins_.clear();
490 dequeue_plugins_.clear();
491 emission_plugins_.clear();
529 enqueue_( position,
Data{ data });
540 enqueue_( position, std::move( data ));
556 enqueue_( position,
Data{ data });
566 enqueue_( position, std::move( data ));
608 if( next_index_ == 0 ) {
613 if( last_position == 0 ) {
614 last_position = current_start_ + width_;
620 size_t cur_end = window_.
entries().empty() ? 0 : window_.
entries().back().position;
621 cur_end = current_start_ > cur_end ? current_start_ - 1 : cur_end;
622 if( last_position <= cur_end ) {
623 throw std::runtime_error(
624 "Cannot call finish_chromosome() with position " +
std::to_string(last_position) +
625 ", as the current window/chromosome is already advanced up to position " +
632 synchronize_interval_( last_position );
633 assert( current_start_ <= last_position );
634 assert( last_position < current_start_ + width_ );
639 if( emit_incomplete_windows_ ) {
640 emit_window_( current_start_, last_position + 1, last_position + 1 );
644 throw std::runtime_error(
"Not yet implemented." );
650 for(
auto const& chromosome_finish_plugin : chromosome_finish_plugins_ ) {
651 if( chromosome_finish_plugin ) {
664 void enqueue_(
size_t position,
Data&& data )
668 if( next_index_ == 0 ) {
669 for(
auto const& chromosome_start_plugin : chromosome_start_plugins_ ) {
670 if( chromosome_start_plugin ) {
682 size_t cur_end = window_.
entries().empty() ? 0 : window_.
entries().back().position;
683 cur_end = current_start_ > cur_end ? current_start_ - 1 : cur_end;
684 if( position <= cur_end ) {
685 throw std::invalid_argument(
687 ", as the current window/chromosome is already advanced up to position " +
689 ". Either start a new window or a new chromosome within the window. "
690 "Note that this error might be caused by a VCF file that is not sorted by "
691 "chromosome and position."
694 assert( position >= current_start_ );
695 assert( window_.
entries().empty() || position > window_.
entries().back().position );
699 enqueue_interval_( position, std::move( data ));
701 throw std::runtime_error(
"Not yet implemented." );
716 void enqueue_interval_(
size_t position,
Data&& data )
721 synchronize_interval_( position );
722 assert( current_start_ <= position );
723 assert( position < current_start_ + width_ );
726 window_.
entries().emplace_back( next_index_, position, std::move( data ));
732 for(
auto const& enqueue_plugin : enqueue_plugins_ ) {
733 if( enqueue_plugin ) {
734 assert( window_.
entries().size() > 0 );
743 for(
auto it : window_.
entries() ) {
744 if( it.position < current_start_ || it.position >= current_start_ + width_ ) {
747 if( it.position < cur_pos ) {
750 cur_pos = it.position;
759 void synchronize_interval_(
size_t position )
765 assert( position >= current_start_ );
766 assert( window_.entries().empty() || window_.entries().back().position < position );
772 window_.entries().empty() || window_.entries().front().position >= current_start_
775 window_.entries().empty() || window_.entries().front().position < current_start_ + width_
778 window_.entries().empty() || window_.entries().back().position >= current_start_
781 window_.entries().empty() || window_.entries().back().position < current_start_ + width_
788 while( current_start_ + width_ <= position ) {
791 emit_window_( current_start_, current_start_ + width_, current_start_ + stride_ );
792 current_start_ += stride_;
796 assert( current_start_ <= position );
797 assert( position < current_start_ + width_ );
803 void emit_window_(
size_t first_position,
size_t last_position,
size_t dequeue_until )
811 for(
auto const& it : window_.entries() ) {
812 if( it.position < first_position || it.position >= last_position ) {
815 if( it.position < cur_pos ) {
818 cur_pos = it.position;
824 assert( last_position > first_position );
825 window_.first_position( first_position );
826 window_.last_position( last_position );
829 for(
auto const& emission_plugin : emission_plugins_ ) {
830 if( emission_plugin ) {
831 emission_plugin( window_ );
837 window_.entries().size() > 0 && window_.entries().front().position < dequeue_until
839 for(
auto const& dequeue_plugin : dequeue_plugins_ ) {
840 if( dequeue_plugin ) {
841 dequeue_plugin( window_.entries().front(), window_.accumulator() );
844 window_.entries().pop_front();
860 bool emit_incomplete_windows_ =
false;
863 size_t current_start_ = 0;
864 size_t next_index_ = 0;
868 std::vector<on_chromosome_start> chromosome_start_plugins_;
869 std::vector<on_chromosome_finish> chromosome_finish_plugins_;
870 std::vector<on_enqueue> enqueue_plugins_;
871 std::vector<on_dequeue> dequeue_plugins_;
872 std::vector<on_emission> emission_plugins_;
879 #endif // include guard