@@ -84,34 +84,53 @@ pub struct QueryRandstrobe {
8484/// Generate randstrobes for a query sequence and its reverse complement.
8585/// TODO move to strobes.rs?
8686pub fn randstrobes_query ( seq : & [ u8 ] , parameters : & IndexParameters ) -> [ Vec < QueryRandstrobe > ; 2 ] {
87- let mut randstrobes= [ Vec :: < QueryRandstrobe > :: new ( ) , Vec :: < QueryRandstrobe > :: new ( ) ] ;
87+ let mut randstrobes = [ vec ! [ ] , vec ! [ ] ] ;
8888 if seq. len ( ) < parameters. randstrobe . w_max {
8989 return randstrobes;
9090 }
9191
92- // TODO
93- // For the reverse complement, we could re-use the syncmers of the forward
92+ // Generate syncmers for the forward sequence
93+ let mut syncmer_iter = SyncmerIterator :: new ( seq, parameters. syncmer . k , parameters. syncmer . s , parameters. syncmer . t ) ;
94+ let mut syncmers: Vec < _ > = syncmer_iter. collect ( ) ;
95+
96+ // Generate randstrobes for the forward sequence
97+ let randstrobe_iter = RandstrobeIterator :: new ( syncmers. iter ( ) . cloned ( ) , parameters. randstrobe . clone ( ) ) ;
98+
99+ for randstrobe in randstrobe_iter {
100+ randstrobes[ 0 ] . push (
101+ QueryRandstrobe {
102+ hash : randstrobe. hash ,
103+ hash_revcomp : randstrobe. hash_revcomp ,
104+ start : randstrobe. strobe1_pos ,
105+ end : randstrobe. strobe2_pos + parameters. syncmer . k ,
106+ }
107+ ) ;
108+ }
109+
110+ // For the reverse complement, we can re-use the syncmers of the forward
94111 // sequence because canonical syncmers are invariant under reverse
95112 // complementing. Only the coordinates need to be adjusted.
96-
97- let seq_rc = reverse_complement ( seq) ;
98- for ( s, is_revcomp) in [ ( seq, false ) , ( & seq_rc, true ) ] {
99- // Generate randstrobes for the forward sequence
100- let mut syncmer_iter = SyncmerIterator :: new ( s, parameters. syncmer . k , parameters. syncmer . s , parameters. syncmer . t ) ;
101- let randstrobe_iter = RandstrobeIterator :: new ( & mut syncmer_iter, & parameters. randstrobe ) ;
102-
103- for randstrobe in randstrobe_iter {
104- randstrobes[ is_revcomp as usize ] . push (
105- QueryRandstrobe {
106- hash : randstrobe. hash ,
107- hash_revcomp : randstrobe. hash_revcomp ,
108- start : randstrobe. strobe1_pos ,
109- end : randstrobe. strobe2_pos + parameters. syncmer . k ,
110- }
111- ) ;
112- }
113+ syncmers. reverse ( ) ;
114+ for i in 0 ..syncmers. len ( ) {
115+ syncmers[ i] . position = seq. len ( ) - syncmers[ i] . position - parameters. syncmer . k ;
113116 }
114117
118+ // Randstrobes cannot be re-used for the reverse complement:
119+ // If in the forward direction, syncmer[i] and syncmer[j] were paired up, it
120+ // is not necessarily the case that syncmer[j] is going to be paired with
121+ // syncmer[i] in the reverse direction because i is fixed in the forward
122+ // direction and j is fixed in the reverse direction.
123+ let rc_randstrobe_iter = RandstrobeIterator :: new ( syncmers. into_iter ( ) , parameters. randstrobe . clone ( ) ) ;
124+ for randstrobe in rc_randstrobe_iter {
125+ randstrobes[ 1 ] . push (
126+ QueryRandstrobe {
127+ hash : randstrobe. hash ,
128+ hash_revcomp : randstrobe. hash_revcomp ,
129+ start : randstrobe. strobe1_pos ,
130+ end : randstrobe. strobe2_pos + parameters. syncmer . k ,
131+ }
132+ ) ;
133+ }
115134 randstrobes
116135}
117136
0 commit comments