Hi,
I'm studying your implementation of SyncmerIterator, and I'm a bit confused. It's possible there's a bug in the code, but I think it's much more likely that I just don't understand the intended semantics correctly.
The code runs accumulators for for the current k-mer and the current s-mer, keeping both the forward and reverse complement *-mers, which makes sense.
It then makes a canonical choice of which s-mer to hash, and adds that to the queue.
What follows is a set of cases that evaluate or re-evaluate the position of the minimising s-mer.
The first question I have is whether it matters that the branch at
|
if (qs.size() == k - s + 1) { // We are at the last s-mer within the first k-mer, need to decide if we add it |
and the branch at
|
for (int j = qs.size() - 1; j >= 0; j--) { //Iterate in reverse to choose the rightmost minimizer in a window |
iterate in opposite directions? In the case of equal hashes, they will select a different minimum position, which could result in the selection of different strobemers. It is a very corner case, I concede, since the former branch in the code handles the very first k-mer, but unless I'm wrong, this could result in inconsistent strobmer choice. This is really a very minor detail, but I mention it since I have been examining the area of the code in detail.
The more important question pertains to the canonical choice of k-mers. I note that the code at
|
uint64_t yk = std::min(xk[0], xk[1]); |
makes a canonical choice between the forward and reverse complement sequences, and reports that hash as the syncmer.
However, if I present the code with the reverse complement of the original sequence, the same set of s-mers will be derived, but in the opposite order, so that the position of the minimiser will be at the opposite end of the queue, and so the test will not pass.
My understanding of the intended semantics is that the set of syncmers would be the same regardless of which strand the original sequence is on, and certainly by reporting the hash of the min k-mer, the code creates that impression.
I'd love to understand where my reasoning has gone off the rails!
Thanks,
Tom.
Hi,
I'm studying your implementation of
SyncmerIterator, and I'm a bit confused. It's possible there's a bug in the code, but I think it's much more likely that I just don't understand the intended semantics correctly.The code runs accumulators for for the current k-mer and the current s-mer, keeping both the forward and reverse complement *-mers, which makes sense.
It then makes a canonical choice of which s-mer to hash, and adds that to the queue.
What follows is a set of cases that evaluate or re-evaluate the position of the minimising s-mer.
The first question I have is whether it matters that the branch at
strobealign/src/randstrobes.cpp
Line 92 in d7e73cc
strobealign/src/randstrobes.cpp
Line 107 in d7e73cc
The more important question pertains to the canonical choice of k-mers. I note that the code at
strobealign/src/randstrobes.cpp
Line 119 in d7e73cc
However, if I present the code with the reverse complement of the original sequence, the same set of s-mers will be derived, but in the opposite order, so that the position of the minimiser will be at the opposite end of the queue, and so the test will not pass.
My understanding of the intended semantics is that the set of syncmers would be the same regardless of which strand the original sequence is on, and certainly by reporting the hash of the min k-mer, the code creates that impression.
I'd love to understand where my reasoning has gone off the rails!
Thanks,
Tom.