-
Notifications
You must be signed in to change notification settings - Fork 0
Preprocessing script #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 11 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
6d0038a
Initial pre-processing script
david-mears-2 3b3e514
Add data inputs (examples) and output
david-mears-2 90d736c
Update pre-processing script to make use of tidyr and dplyr
david-mears-2 d929a23
Use a custom list of in-scope variants, per-STAVE release.
david-mears-2 3e78a93
Don't filter down STAVE data at all
david-mears-2 f247f1c
Extract R script from pre-processing draft md; use scripts dir for da…
david-mears-2 46631d6
Use command line args for R script
david-mears-2 2f56dbc
Potential fix for pull request finding
david-mears-2 263fc4a
mv .gitkeep
david-mears-2 965ed89
Small script refactors
david-mears-2 5b3ed13
Add README.md
david-mears-2 2c5b22c
Use cli package for messages and errors in process_stave.R
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # PARAmap API | ||
|
|
||
| This repo will contain an API serving two kinds of data to be rendered by PARAmap: | ||
|
|
||
| 1) data points of surveys of genetic markers, which come to us stored in the [STAVE](https://mrc-ide.github.io/STAVE/index.html) schema; | ||
| 2) and a surface of model outputs imputed from the survey data, which are essentially interpolated prevalences of the difference genetic markers per region. | ||
|
|
||
| ## How to update the data | ||
|
|
||
| ### Model outputs | ||
|
|
||
| TODO | ||
|
|
||
| The list of in-scope genes and mutations will vary over time, with model releases (rather than with STAVE data releases). Every model release has a dependency on one STAVE data release. | ||
|
|
||
| ### STAVE data | ||
|
|
||
| When a new STAVE data release is provided, it should be given a version name e.g. "2026.03.17", and committed in `scripts/input/stave/<version>/stave_data.rds`. Then, run the [process_stave.R](./scripts/process_stave.R) script: | ||
|
|
||
| ```sh | ||
| Rscript ./scripts/process_stave.R 2026.03.17 | ||
| ``` | ||
|
|
||
| This will create `./data/stave/<version>/survey_data.parquet`. |
Empty file.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| # Converts an .rds file containing a STAVE object of 3 tables (studies, surveys, counts) | ||
| # into an expanded version of the studies table, having one row per survey per variant, | ||
| # which is saved in parquet format. | ||
| # This results in a table of about 253,000 rows at time of writing. | ||
| # Most of the work and logic is done by the two packages STAVE and variantstring, | ||
| # particularly STAVE's `$get_prevalence` function. | ||
|
|
||
| library(arrow) | ||
| library(dplyr) | ||
| library(tidyr) | ||
| library(STAVE) | ||
| library(variantstring) | ||
| library(here) | ||
|
|
||
| args <- commandArgs(trailingOnly = TRUE) | ||
| if (length(args) == 0) { | ||
| stop("Usage: Rscript process_stave.R <stave_release>\nExample: Rscript process_stave.R 2026.03.17") | ||
| } | ||
|
|
||
| current_stave_release <- args[[1]] | ||
| output_filename = "survey_data.parquet" | ||
|
|
||
| input_dir <- here("scripts", "input", "stave", current_stave_release) | ||
| output_dir <- here("data", "stave", current_stave_release) | ||
|
|
||
| dir.create(output_dir, recursive = TRUE, showWarnings = FALSE) | ||
|
|
||
| stave_obj <- readRDS(file.path(input_dir, "stave_data.rds")) | ||
|
|
||
| variants <- stave_obj$get_variants() | ||
|
|
||
| # For each variant, calculate imputed prevalence per survey | ||
| # (only surveys with a non-zero denominator), and combine into one tibble. | ||
| prevalence_tbl <- variants |> | ||
| lapply(function(v) { | ||
| stave_obj$get_prevalence(target_variant = v, return_full = FALSE) |> | ||
| mutate(variant = v) | ||
| }) |> | ||
| bind_rows() | ||
|
|
||
| # Parse gene/locus/amino-acid from each variant string using variantstring's own parser. | ||
| # We validate that all variant strings define a single variant. | ||
| # If they do, they have only a single value between each colon. | ||
| # If they don't, `variant_to_long` will unpack the strings into multiple variants, and | ||
| # we'll catch this and abort. | ||
| parsed_list <- variant_to_long(variants) # one data.frame per variant | ||
| n_rows <- vapply(parsed_list, nrow, integer(1)) | ||
| if (any(n_rows != 1)) { | ||
| bad <- variants[n_rows != 1] | ||
| stop(sprintf( | ||
| "Expected each variant to parse to exactly 1 row via variant_to_long(), but got unexpected row counts for: %s.\n The variant string might not be single-locus. Did you call $get_variants(report_haplo=TRUE)?", | ||
| paste(unique(bad), collapse = ", ") | ||
| )) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So with cli - see if you like the below (both code and the appearance of the error...?) |
||
| } | ||
|
|
||
| parsed <- bind_rows(Map(function(df, v) mutate(df, variant = v), parsed_list, variants)) | ||
|
|
||
| prevalence_tbl <- prevalence_tbl |> | ||
| left_join( | ||
| parsed |> | ||
| transmute(variant, gene, mutation = paste0(pos, aa)), | ||
| by = "variant" | ||
| ) | ||
|
|
||
| # Because of encoding errors in paper titles, we need to force conversion to UTF-8. | ||
| # This function tries UTF-8 first, and if invalid, assumes Latin-1 | ||
| fix_utf8 <- function(x) { | ||
| bad <- !validEnc(x) | is.na(iconv(x, "UTF-8", "UTF-8")) # get vector of whether utf-8 encoding works for the string | ||
| x[bad] <- iconv(x[bad], from = "latin1", to = "UTF-8") # For just the flagged entries, reinterpret the raw bytes as Latin-1 and convert to utf-8 | ||
| enc2utf8(x) # tag every string as declared-UTF-8 | ||
| } | ||
|
|
||
| # Drop columns we don't need | ||
| drop_cols <- c("description", "access_level", "PMID", "country_name", | ||
| "location_method", "location_notes", "time_method", "time_notes") | ||
|
|
||
| prevalence_tbl <- prevalence_tbl |> | ||
| select(-all_of(drop_cols)) |> | ||
| mutate(across(where(is.character), fix_utf8)) | ||
|
david-mears-2 marked this conversation as resolved.
|
||
|
|
||
| write_parquet(prevalence_tbl, file.path(output_dir, output_filename)) | ||
|
|
||
| print(sprintf("Wrote %s with %d rows to %s", output_filename, nrow(prevalence_tbl), output_dir)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wonder if this looks nicer... |
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine - we've generally been using the
clipackage andcli_abortinstead of stop - it looks a little nicer and can do some clever message construction (which you don't really need here in this example - but perhaps later!)eg