Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions R/gwas-catalog.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
#' @param study_id A single character string with study ID, e.g. "GCST90475332"
#' @param quiet TRUE/FALSE - controls progress bar for downloading
#'
#' @details Uses internal scraping helpers to locate harmonised summary
#' statistics when they are available; otherwise falls back to any matching
#' summary statistics in the study directory.
#'
#' @returns a filepath to downloaded summary statistics
#' @export
#'
Expand Down Expand Up @@ -58,27 +62,46 @@ from_gwas_catalog <- function(study_id, quiet = FALSE) {
gwas_file
}

#' Scrape a directory listing and return matching entries
#'
#' @param url The directory URL to inspect.
#' @param pattern Regex pattern of file names to keep (set to NULL to keep all
#' files). Directory entries are always retained to allow recursive scraping.
#'
#' @return Character vector of matching file names and subdirectories.
#' @noRd
.href_drop_pattern <- "^\\?|^\\.{2}/|^/pub|^$"
.scrape <- function(url, pattern = "\\.(gz|tsv|yaml|tbi|log|txt)$") {
html_raw <- curl::curl_fetch_memory(url)$content
page <- xml2::read_html(rawToChar(html_raw))
hrefs <- rvest::html_attr(rvest::html_nodes(page, "a"), "href")
hrefs <- hrefs[!grepl("^\\?|^\\.{2}/|^/pub|^$", hrefs)]
hrefs <- hrefs[!is.na(hrefs) & !grepl(.href_drop_pattern, hrefs)]

dirs <- stringr::str_subset(hrefs, "/$")
files <- hrefs[!grepl("/$", hrefs)]

matches <- if (is.null(pattern)) files else stringr::str_subset(files, pattern)

unique(c(dirs, matches))
}


scrape_dir <- function(url, pattern = "\\.(gz|tsv|yaml|tbi|log|txt)$") {
files <- .scrape(url)
files <- .scrape(url, pattern)

if(any(grepl("harmonised/", files))) {
harmonised <- .scrape(file.path(url, files[grepl("harmonised/", files)]))
harmonised <- file.path(url, files[grepl("harmonised/", files)], harmonised)
harmonised_dir <- files[grepl("harmonised/", files)][1]
harmonised <- .scrape(
file.path(url, harmonised_dir),
pattern
)
harmonised <- file.path(url, harmonised_dir, harmonised)
files <- c(file.path(url, files[!grepl("harmonised/", files)]), harmonised)
} else {
files <- file.path(url, files)

}
files

files
}

check_sumstats_avail <- function(
Expand Down
4 changes: 4 additions & 0 deletions man/from_gwas_catalog.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions tests/testthat/test-gwas-catalog.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,53 @@ test_that("multiplication works", {


})

test_that(".scrape keeps directories and filters by pattern", {
html <- paste0(
"<html><body>",
"<a href=\"harmonised/\">harmonised</a>",
"<a href=\"results.tsv\">results</a>",
"<a href=\"notes.pdf\">notes</a>",
"<a href=\"../parent\">parent</a>",
"<a href=\"?query\">query</a>",
"</body></html>"
)

mock_fetch <- function(url) list(content = charToRaw(html))

result <- with_mocked_bindings(
tidyGWAS:::`.scrape`("http://example.com", pattern = "\\.(tsv|yaml)$"),
curl::curl_fetch_memory = mock_fetch
)

expect_equal(result, c("harmonised/", "results.tsv"))
})

test_that("scrape_dir retains harmonised files and applies patterns", {
base_links <- c("harmonised/", "main.tsv", "main.tbi", "readme.txt")
harmonised_links <- c("harmonised.tsv.gz", "meta.yaml", "other.log")

mock_scrape <- function(url, pattern) {
if (grepl("/harmonised/?$", url)) {
return(harmonised_links)
}
base_links
}

files <- with_mocked_bindings(
tidyGWAS:::scrape_dir("http://example.com"),
tidyGWAS:::`.scrape` = mock_scrape
)

expect_equal(
files,
c(
"http://example.com/main.tsv",
"http://example.com/main.tbi",
"http://example.com/readme.txt",
"http://example.com/harmonised/harmonised.tsv.gz",
"http://example.com/harmonised/meta.yaml",
"http://example.com/harmonised/other.log"
)
)
})