Repository navigation
Conversation
|
This PR more or less duplicates the contents of several functions. If it turns out to be generally useful and something we want to keep long term, we'll need to consider how to refactor the code to minimize duplication and maintenance burden. Note, we've already acknowledged the need for some cleanup in #1378. |
Codecov Report
@@ Coverage Diff @@
## master #1571 +/- ##
==========================================
- Coverage 64.16% 64.13% -0.03%
==========================================
Files 79 79
Lines 12189 12244 +55
Branches 3072 3096 +24
==========================================
+ Hits 7821 7853 +32
- Misses 2670 2674 +4
- Partials 1698 1717 +19
Continue to review full report at Codecov.
|
|
Ready for initial review @ctb @luizirber @camillescott @betatim. This may be easier to merge before #1511. If so I'll clean it up for final review. |
| delete parser; | ||
| } | ||
|
|
||
| void Hashtable::consume_fasta_bitsplit( |
There was a problem hiding this comment.
bitsplit doesn't mean anything to me :-/ Coudl we call it consume_fasta_sampling or some such?
There was a problem hiding this comment.
I agree the name is wonky. consume_fasta_sampling is better but honestly I've thought of half a dozen names and I'm not in love with any of them.
There was a problem hiding this comment.
my suggestion for the name is "banding".
There was a problem hiding this comment.
Yeah, I quite like banding. And I think num_batches and batch are good replacements for num_bins and tag.
| { | ||
| bool powerof2 = !(num_bins == 0) && !(num_bins & (num_bins - 1)); | ||
| if (!powerof2 || tag >= num_bins) { | ||
| return; |
|
tables use murmurhash |
And to be clear, the concern with the hash function isn't correctness per se, but getting a roughly even split. Unless the sequence is truly random (simulated and biologically uninteresting), some k-mer suffixes are going to be overrepresented and skew the split. At least for my purposes, this wouldn't be a problem for correctness as much as for performance. I want to be able to split the work into evenly sized bins. |
|
I did some basic profiling. For very small memory sizes, there is little difference in runtime between |
|
But regardless, increasing memory only has a marginal effect on runtime. Perhaps it becomes more I/O bound? |
|
When you say increasing memory you mean making the hashtable bigger? So for small hashtable sizes we spend most of our time doing I/O, hence throwing away kmers after reading them in doesn't speed things up. For large hashtables we spend most of our effort on entering stuff into the hashtable, so reading in kmers and then chucking them makes things faster?! Interesting. |
|
excellent. @betatim I've lost track (vacation brain) of your results on cache misses; this is probably not due to cache missing, right? |
|
@standage, you should be able to separate out the IO effects from the memory size effects by an affine fit, yes? |
|
What's old is new: #70 |
|
Commit 786a3be |
| (21, 5e7, 2, 16), | ||
| ]) | ||
| def test_banding_in_memory(ksize, memory, epsilon, numbands): | ||
| infile = utils.get_test_data('test-reads.fa') |
There was a problem hiding this comment.
I'm not sure this function meets @ctb's simplicity criteria for automated tests. I'm not sure there's a simpler, clearer way to iterate over the data.
| def test_banding_to_disk(ksize, memory, numbands): | ||
| infile = utils.get_test_data('test-reads.fa') | ||
| path1 = utils.get_temp_filename('normal.ct') | ||
| path2 = utils.get_temp_filename('banding.ct') |
There was a problem hiding this comment.
This function is simple enough, and it provides a stronger guarantee. Perhaps it's all we need?
|
*shrug* I don't like procedural complexity. At least this is declarative :)
|
|
Procedural complexity == branching? |
|
My recent tests have put my concerns regarding the hash functions and banding to rest. Now that #1511 is merged, this is now ready for review and merge. @ctb @betatim @camillescott @luizirber |
| continue; | ||
| } | ||
|
|
||
| bool is_valid = true; |
There was a problem hiding this comment.
Can I persuade you to use read.set_clean_seq(); plus read.cleaned_seq != read.sequence instead of doing your own processing/normalising?
There was a problem hiding this comment.
Maybe what we need is a method that does the toupper() for us to avoid having "loop-over-seq-and-uppercase-then-check" here.
There was a problem hiding this comment.
Two concerns / observations.
- Comparing cleaned seq vs original seq will disqualify reads with lowercase ACGT, which I think is a lousy default with unexpected consequences.
- The current
consume_fastafunction in Hashtable doesn't use this utility yet either.
As @ctb mentioned, there's some work to be done with removing redundant read cleaning code (see #1590), and that's not all going to be resolved in this PR. Ultimately this will be handled by the parser instead of the consume function, right?
There was a problem hiding this comment.
Ah yes, humm, so we definitely need a method that can do the comparison that is centralised. And with cython'isation things will move again. Punt?
| code... | ||
| """ | ||
|
|
||
| from __future__ import absolute_import |
There was a problem hiding this comment.
Was this missing before? Puzzled how travis didn't find it.
There was a problem hiding this comment.
Now we need it to make the tests pass or do they work without as well?
|
Do you want to add one more test that computes the hash of two kmers, one that should be added and one that shouldn't, and explicitly checks that they ended up in the CT? A bit like https://github.com/dib-lab/khmer/pull/1571/files#diff-7352ff13b9e5cdbeacb24c9e7bcb49b1R1136 except here I am guessing that this is what you wanted because I don't know the hash values off the top of my head. |
|
see also #1590
|
|
@betatim Yeah, that's exactly what I was going for with that test. Are you saying to test the hash value instead of the k-mer itself? Please clarify. |
|
I was going for a test like this: we could even add the assert for the hash value to the current test. The motivation is to leave an explicit clue as to why you expect a certain kmer to be present and which ones not. |
|
On Thu, Feb 09, 2017 at 08:21:10PM -0800, Daniel Standage wrote:
Procedural complexity == branching?
yes, specifically 'if' statements suck. if we have to debug our test code
itself, it adds complexity.
|
|
Closing in favor of #1720. |

WIP that, when finished, closes #1570. Implements a variant of
consume_fasta(and all of the functions it calls) that consumes a subset of the observed k-mers. Givennum_batches = 2^nandbatch \in range(num_batches), the function only stores k-mers whose n least significant bits encodebatch.Remaining tasks:
num_binsis a power of 2 andtag < num_binsmake testDid it pass the tests?make clean diff-coverIf it introduces new functionality inscripts/is it tested?make format diff_pylint_report cppcheck doc pydocstyleIs it wellformatted?
additions are allowed without a major version increment. Changing file
formats also requires a major version number increment.
documented in
CHANGELOG.md? See keepachangelogfor more details.
changes were made?
tested for streaming IO?)