Genome metadata QC filtering - #31
Conversation
Added ability to filter BV-BRC genomes based on genome stat metadata, including CheckM completeness and CheckM contamination as defaults. Also enabled optional checking of genome length, CDS count, and GC content based on deviations from median distribution per bug. Updated genome downloader functions to use ftpes_download_one instead of old ftp_download_one, and moved a dot function helper to inside the ftpes_download_one loop to avoid issues with BiocParallel workers not understanding what that helper is.
Uncommenting a helper that was still needed for several calls. Fixing stuff I broke myself!
Updating to remove BiocParallel implementation that caused bugs. Patching back to prior Future implementation instead. CLI version of genome downloading appears to have issues that may be separate and requires further troubleshooting.
data_processing.R runDataProcessing() missing(ref_file_path) check ignores if the default path is used. Updated to accept the default path if a user doesn't specify rather than erroring at the end of the processing steps.
Updated default workers to 8 for CLI and FTP downloads, made two-try FTP download option the default, added a helper to purge broken file sets (i.e., if .faa is missing for an AccID but .fna and .gff download successfully).
|
Update: |
ftpes --> ftps is_complete --> .is_complete
jananiravi
left a comment
There was a problem hiding this comment.
Few comments on chunks that didn't need a review!
eboyer221
left a comment
There was a problem hiding this comment.
future, future.apply, and furrr are used in data_curation.R and data_processing.R (e.g. future::plan(), future.apply::future_lapply(), furrr::future_map()) but aren't declared in DESCRIPTION. All the calls in this PR are already ::-qualified, so I don't think any NAMESPACE/roxygen changes are needed. The suggestion is just to add these three to Imports:
Imports: arrow, BiocParallel, Biostrings, DBI, data.table, dplyr, duckdb, furrr, future, future.apply, glue, purrr, readr, reshape2, stringr, tibble, tidyr
While testing, I saw prepareGenomes("Staphylococcus argenteus") resolve to different genome counts across runs (248 genomes / 1 taxon ID vs. 21 genomes / 3 taxon IDs) for the identical input. The difference in numbers only showed up after an earlier run had hit a future::multisession error (from testing via devtools::load_all() before fully installing the branch. Restarting R fully resolved the issue, so it seems like an orphaned worker process left a stale lock on bvbrcData.duckdb that a later run then hit.
Might be worth a line in the docs/README recommending a full R session restart (not just load_all()) after any future::multisession error before re-testing, so this doesn't get mistaken for a genuine QC/parallelism bug by the next person who hits it.
A few smaller things I noticed while reviewing, none blocking:
- No test coverage yet for
.apply_metadata_qc()or.parse_bvbrc_tsv()which are the two new core functions this PR adds. So we may want to add a couple oftestthatcases for those in a separate PR. retrieveMetadata()defaults tocheckm_contam = 10, checkm_complete = 90, whileprepareGenomes()defaults tocheckm_contam = 5, checkm_complete = 95(stricter). Is that intentional, or should these match?- The new
is_complete()closure inside.ftpes_download_one()duplicates the existing.is_complete_set()helper (still used by.list_complete()/.missing_any()/.audit_gaps()/retrieveGenomes()). Could just call.is_complete_set()directly instead of re-implementing it.
|
good catch, Emily. @epbrenner happy to re-review once you make these changes. |
… consolidate on furrr
Cleaning up parallel implementation in data_curation.R, standardizing with furrr and dropping old duplicated within-loop helper function that was needed for earlier BiocParallel implementation. Standardized values for contamination and completeness across functions. Added a parameter in prepareGenomes to allow users to set number of workers. Reduced console clutter for final "out" print.
Changes I pushed to this PR: Verified: package loads clean, all existing tests pass. |
jananiravi
left a comment
There was a problem hiding this comment.
I didn't notice anything from my quick manual inspection, but here are 3 from C -- flagging for @epbrenner @eboyer221. Please check to make sure these won't cause immediate or downstream issues.
prepareGenomes()'s broken return value (wrong key, no live connection, connection leak).ftps_download_two_pass()'s missing early-return + lost Pass-1 logging when everything succeeds first tryretrieveMetadata()'s missing "no drug data returned" guard.
Detailed version:
Three regressions in d658224:
prepareGenomes()return value is now broken. It used to return out (the actual result of genomeList(), containing a live duckdbConnection). It now returns a hand-builtinvisible(list(duckdb_path = paths$db_path, table_name = "files"))instead — wrong key name (duckdb_pathvs. the documentedduckdbConnection), and a path string instead of an open connection.prepareGenomes()'s own roxygen @return still promises "Active DBI connection to the per-bug DuckDB" — this commit breaks that contract. Any caller doing out$duckdbConnection (which the README's own workflow examples imply) will get NULL. It also silently leaks the connection genomeList() opened, since it's never captured or disconnected now. Looks like an overcorrection for "reduced console clutter for final 'out' print" — the fix should have been invisible(out), not replacing out's contents..ftps_download_two_pass()lost its "all passed in pass 1" early return. The old code hadif (!length(fail_ids)) { ...; return(ok_ids_1) }right after Pass 1. That's gone now — so even when every genome succeeds in pass 1, the function still unconditionally spins up a second future::multisession worker pool and callsfurrr::future_map()over an empty fail_ids. Not fatal (mapping over a length-0 vector is a no-op), but it's wasted worker-pool startup/teardown on every single successful run, and — given eboyer's finding that orphaned future::multisession workers are exactly what caused the stale-DuckDB-lock flakiness — adding an unnecessary extra worker-pool spin-up on every call cuts against the fix this whole PR is for. Same edit also dropped the "Pass 1: ok=X fail=Y" console message and its log_file line, so that pass's outcome is no longer logged at all.retrieveMetadata()lost its "no drug data returned" guard. The old code had if(nrow(combined_drug_data_tbl) == 0L) { message("No drug data returned."); return(NULL) }right after building combined_drug_data_tbl. That block is gone (only the equivalent check for combined_genome_data_tbl survived). Now if BV-BRC returns zero AMR rows for a query, the function proceeds anyway, writes an empty amr_phenotype table, and the downstream INNER JOIN into metadata_full silently produces an empty result instead of a clear early message — trading a clear failure for a silent empty one.
Fixed two code reversions that 1) didn't stop pass 2 from being attempted for the FTPS downloader even if everything worked in pass 1, and 2) caught if no drug data was returned in a query and halted the script. Also updated an output continue providing `out`, just invisibly, rather than custom outputs that were by default hidden. These updates were also applied to a separate branch for table exports. (Thanks Janani!) Co-Authored-By: Janani Ravi <8397074+jananiravi@users.noreply.github.com>
Adding new functionality.
@amcim Most importantly for you, I know you've been working on the BiocParallel stuff and had since moved on to another implementation (futures?). I just want to confirm that this script is working for me locally after my patches, but this is just based off main. If we're changing implementations, some of my updates aren't necessary.
For testers:
Open GitHub Desktop or your preferred method of fetching a PR, fetch this PR, source data_curation.R into your favorite CLI, and try
retrieveMetadata(user_bacs = "Shigella flexneri")for a quick bug, orprepareGenomes(user_bacs = "Shigella flexneri")to also test the genome downloader. I have tried this out locally for Enterobacter spp., K. pnumoniae, and Campylobacter jejuni. Give it a spin!