From e06ecc6861dd6d536438c6ea38703fc0d9745692 Mon Sep 17 00:00:00 2001 From: guy joseph Date: Tue, 13 Aug 2024 08:42:00 -0700 Subject: [PATCH 1/3] Update automation documentation (#61) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index cdff5e5..66ba673 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,10 @@ remotes::install_github("10XGenomics/loupeR") loupeR::setup() ``` +### Automated installation and execution + +If you are interested in automating LoupeR installation and execution (and are blocked by interactive license acceptance), please write to [support@10xgenomics.com](mailto:support@10xgenomics.com) for further assistance. + ## Loupe Browser Compatibility With new versions of the Loupe Browser, new version of LoupeR need to be released. The table below shows version requirements between the two. From 75343f1147943aaf8b2935ee354e6baa2c6c274c Mon Sep 17 00:00:00 2001 From: guy joseph Date: Tue, 1 Oct 2024 13:12:36 -0700 Subject: [PATCH 2/3] Validate Barcodes * Drop sanitize barcodes in favor of validating them with regexs. * Update documentation to reflect the sanitization to validation change. * Other assorted README updates. --------- Co-authored-by: Dylan Webster --- DESCRIPTION | 2 +- NAMESPACE | 2 +- R/hdf5.R | 8 +- R/util.R | 59 ------------- R/validate.R | 42 +++++++--- README.md | 49 +++++++++-- man/validate_barcodes.Rd | 17 ++++ tests/testthat/helper.R | 4 +- tests/testthat/test-util.R | 38 --------- tests/testthat/test-validate.R | 147 ++++++++++++++++++++++++++++++--- 10 files changed, 233 insertions(+), 135 deletions(-) create mode 100644 man/validate_barcodes.Rd diff --git a/DESCRIPTION b/DESCRIPTION index d1add4d..25ef893 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -13,7 +13,7 @@ Encoding: UTF-8 Depends: R (>= 4.0.0) Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.2 Suggests: testthat (>= 3.0.0), Matrix, diff --git a/NAMESPACE b/NAMESPACE index f91a3b1..b358de2 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -10,6 +10,7 @@ export(select_assay) export(select_clusters) export(select_projections) export(setup) +export(validate_barcodes) export(validate_clusters) export(validate_count_mat) export(validate_projections) @@ -24,4 +25,3 @@ importFrom(utils,download.file) importFrom(utils,packageVersion) importFrom(utils,read.csv) importFrom(utils,sessionInfo) -importFrom(utils,strcapture) diff --git a/R/hdf5.R b/R/hdf5.R index 6a22826..c90e9d8 100644 --- a/R/hdf5.R +++ b/R/hdf5.R @@ -46,17 +46,15 @@ create_hdf5 <- function( #' @noRd write_mat <- function(f, count_mat, feature_ids) { features <- rownames(count_mat) - barcodes_unmodified <- colnames(count_mat) - barcodes_formatted <- sanitize_barcodes(barcodes_unmodified) + barcodes <- colnames(count_mat) feature_count <- length(features) - barcode_count <- length(barcodes_formatted ) + barcode_count <- length(barcodes) # create groups matrix_group <- f$create_group("matrix") features_group <- matrix_group$create_group("features") - create_str_dataset(matrix_group, "barcodes", barcodes_formatted ) - create_str_dataset(matrix_group, "barcodes_unmodified", barcodes_unmodified) + create_str_dataset(matrix_group, "barcodes", barcodes) create_dataset(matrix_group, "data", as.integer(count_mat@x)) create_dataset(matrix_group, "indices", as.integer(count_mat@i)) create_dataset(matrix_group, "indptr", as.integer(count_mat@p)) diff --git a/R/util.R b/R/util.R index 9ca708c..6baf4f4 100644 --- a/R/util.R +++ b/R/util.R @@ -250,65 +250,6 @@ cluster_levels_word_like <- function(cluster) { }) } -#' Sanitize barcodes into expected format -#' -#' @param barcodes character vector of barcodes names -#' -#' @importFrom utils strcapture -#' -#' @return character vector of sanitized barcode names -#' -#' @noRd -sanitize_barcodes <- function(barcodes) { - if (are_barcodes_valid(barcodes)) { - return(barcodes) - } - - # Some examples that we have seen - # - # Seurat Integrate will add a prefix to the barcode "12U_ACTGACTGACTG-1" - # Other users tend to add a prefix "SOMEPREFIX:ACTGACTGACTG" - pattern <-"^(.*?)(_|-|:)?([ACTG]{6,})(-\\d+)?(_|-|:)?(.*?)$" - - # only santize barcodes if all match the pattern - if (length(grep(pattern, barcodes)) != length(barcodes)) { - return(barcodes) - } - - # capture subgroups of pattern (prefix, barcode, suffix) - # NOTE: need to use perl regexs to support non-greedy matching - groups <- strcapture( - pattern=pattern, - x=barcodes, - perl=TRUE, - proto=list(prefix = character(), - sep1 = character(), - barcode = character(), - barcodeDashNum = character(), - sep2 = character(), - suffix = character())) - - # rewrite barcodes "BARCODE-PREFIX-SUFFIX" - updated_barcodes <- character(length(barcodes)) - for (i in 1:nrow(groups)) { - row <- groups[i,] - - prefix <- "" - if (nchar(row$prefix) > 0) { - prefix <- sprintf("-%s", row$prefix) - } - - suffix <- "" - if (nchar(row$suffix) > 0) { - suffix <- sprintf("-%s", row$suffix) - } - - updated_barcodes[[i]] = sprintf("%s%s%s%s", row$barcode, row$barcodeDashNum, prefix, suffix) - } - - updated_barcodes -} - #' Gets the systems OS. #' #' @return "windows", "mac", "unix" diff --git a/R/validate.R b/R/validate.R index bd484f4..ebd1375 100644 --- a/R/validate.R +++ b/R/validate.R @@ -45,13 +45,12 @@ validate_count_mat <- function(count_mat, feature_ids = NULL) { return(err("features cannot be the empty string")) } - barcodes <- sanitize_barcodes(barcodes) - - if (!are_barcodes_valid(barcodes)) { + resp <- validate_barcodes(barcodes) + if (!resp$success) { barcode_msg <- paste( - 'There is an issue with the formatting of your barcodes.', - 'Barcodes should begin with base pairs and end with an optional hyphen and suffix.', - 'For further information, please see the documentation: 10xgen.com/louper' + 'There is an issue with the formatting of your barcodes:', + resp$msg, + 'Please see the readme at github.com/10xGenomics/loupeR' ) return(err(barcode_msg)) @@ -81,12 +80,33 @@ validate_count_mat <- function(count_mat, feature_ids = NULL) { #' #' @param barcodes a character vector #' -#' @return A boolean true or false +#' @return A list with two elements: +#' \itemize{ +#' \item success: a logical value indicating success (TRUE) or failure (FALSE) +#' \item msg: an optional error message (NULL if success is TRUE) +#' } +#' +#' @importFrom methods is #' -#' @noRd -are_barcodes_valid <- function(barcodes) { - pattern <-"^([ACTG]{6,})(-.*?)?$" - return(all(grepl(pattern, barcodes))) +#' @export +validate_barcodes <- function(barcodes) { + barcodeRegex <- "^(.*[:_])?([ACGT]{14,})([:_].*)?$" + barcodeGemRegex <- "^(.*[:_])?([ACGT]{14,})-(\\d+)([:_].*)?$" + visiumHDRegex <- "^(.*[:_])?(s_\\d{3}um_\\d{5}_\\d{5})([:_].*)?$" + visiumHDGemRegex <- "^(.*[:_])?(s_\\d{3}um_\\d{5}_\\d{5})-(\\d+)([:_].*)?$" + xeniumCellIdRegex <- "^(.*[:_])?([a-p]{1,8})-(\\d+)([:_].*)?$" + + for (barcode in barcodes) { + if (!grepl(barcodeRegex, barcode) && + !grepl(barcodeGemRegex, barcode) && + !grepl(visiumHDRegex, barcode) && + !grepl(visiumHDGemRegex, barcode) && + !grepl(xeniumCellIdRegex, barcode)) { + return(err(paste("Invalid barcode:", barcode))) + } + } + + SUCCESS } #' Validate the seurat clusters diff --git a/README.md b/README.md index 66ba673..15f8f2f 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Troubleshooting

-`loupeR` creates a 10x Genomics Loupe file from a Seurat object. 10x Genomics Loupe Browser can visualize single-cell and spatial data from 10x Genomics. *Only single-cell gene expression datasets are supported*. +`loupeR` creates 10x Genomics Loupe files from Seurat objects and other 10x Genomics data in R. 10x Genomics Loupe Browser can visualize single-cell and spatial data from 10x Genomics. _Only single-cell gene expression datasets are supported in LoupeR_. ## How to Use @@ -54,7 +54,7 @@ create_loupe( ) ``` -Additionally, use the utility function `read_feature_ids_from_tsv` to read the Ensemble ids from the 10x dataset. A Seurat object will only have imported the feature names or ids and attached these as rownames to the count matrix. In order for the Ensemble id links to work correctly within Loupe Browser, one must manually import them and include them. +Additionally, use the utility function `read_feature_ids_from_tsv` to read the Ensemble ids from the 10x dataset. A Seurat object will only have imported the feature names or ids and attached these as rownames to the count matrix. In order for the Ensemble id links to work correctly within Loupe Browser, one must manually import them and include them. ```R # import the library @@ -73,7 +73,7 @@ create_loupe_from_seurat(seurat_obj, feature_ids = feature_ids) ### HDF5 -Before using `loupeR`, make sure that your system has installed [HDF5](https://www.hdfgroup.org/downloads/hdf5). The HDF5 organization requires registration before being able to download the installer. Below are some other more convenient methods for installing HDF5 if you happen to have these package managers installed. +Before using `loupeR`, make sure that your system has installed [HDF5](https://www.hdfgroup.org/downloads/hdf5). The HDF5 organization requires registration before being able to download the installer. Below are some other more convenient methods for installing HDF5 if you happen to have these package managers installed. - macOS with [Homebrew](https://brew.sh/) - `brew install hdf5`
- windows with [vcpkg](https://vcpkg.io/en/index.html) - `.\vcpkg install hdf5` @@ -95,9 +95,9 @@ install.packages(url, repos = NULL, type = "source") ### Installing loupeR using the `remotes` package -Another installation option is to use the `remotes` package to directly install `loupeR` and its dependencies. The installed package won't include the prebundled louper executable, so you must invoke the `loupeR::setup()` function which will go and download it. +Another installation option is to use the `remotes` package to directly install `loupeR` and its dependencies. The installed package won't include the prebundled louper executable, so you must invoke the `loupeR::setup()` function which will go and download it. -``` r +```r remotes::install_github("10XGenomics/loupeR") loupeR::setup() ``` @@ -111,14 +111,47 @@ If you are interested in automating LoupeR installation and execution (and are b With new versions of the Loupe Browser, new version of LoupeR need to be released. The table below shows version requirements between the two. | LoupeR Version | Loupe Browser Version | -| ------------- | ------------- | +| -------------- | --------------------- | | v1.0.x | Loupe Browser >= 7.0 | -| v1.1.x | Loupe Browser >= 8.0 | +| v1.1.1 | Loupe Browser >= 8.0 | +| v1.1.2 | Loupe Browser >= 8.1 | ## Tutorials -* [Demo notebook](https://colab.research.google.com/github/10XGenomics/loupeR/blob/main/misc/tutorials/5k_mouse_brain.ipynb) with basic processing of an example 10x dataset [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/10XGenomics/loupeR/blob/main/misc/tutorials/5k_mouse_brain.ipynb) +- [Demo notebook](https://colab.research.google.com/github/10XGenomics/loupeR/blob/main/misc/tutorials/5k_mouse_brain.ipynb) with basic processing of an example 10x dataset [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/10XGenomics/loupeR/blob/main/misc/tutorials/5k_mouse_brain.ipynb) + +## Barcode Formatting + +Barcodes must be from 10x Genomics exeriments to work with LoupeR. Valid 10x Genomics Single Cell Gene Expression barcodes have the characters ACGT repeated 16 times, followed by an optional GEM well suffix, for example: + +``` +AAACCCAAGAAATTGC +AAACCCAAGAAATTGC-1 +``` + +Barcodes can also have an additional optional prefix or suffix. These optional prefixes and suffixes must be delineated either by a `:` or a `_`: + +``` +prefix_AAACCCAAGAAATTGC +AAACCCAAGAAATTGC_suffix +prefix_AAACCCAAGAAATTGC_suffix + +prefix:AAACATACAAACAG +AAACATACAAACAG:suffix +prefix:AAACATACAAACAG:suffix + +prefix_AAACCCAAGAAATTGC-1 +AAACCCAAGAAATTGC-1_suffix +prefix_AAACCCAAGAAATTGC-1_suffix + +prefix:AAACCCAAGAAATTGC-1 +AAACCCAAGAAATTGC-1:suffix +prefix:AAACCCAAGAAATTGC-1:suffix +``` + +**Note**: Visium and Xenium barcodes are formatted differently. Visium and Xenium data are currently enabled for use with LoupeR, but **_not_** fully supported. Expression data for these assays can be processed by loupeR, but **_not_** image data. +See `test-validate.R` for further examples of both valid and invalid barcode formatting, as well as `validater.R` for the exact formatting requirements as code. ## Troubleshooting diff --git a/man/validate_barcodes.Rd b/man/validate_barcodes.Rd new file mode 100644 index 0000000..b36d13a --- /dev/null +++ b/man/validate_barcodes.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/validate.R +\name{validate_barcodes} +\alias{validate_barcodes} +\title{Validate the format of the barcodes} +\usage{ +validate_barcodes(barcodes) +} +\arguments{ +\item{barcodes}{a character vector} +} +\value{ +A boolean true or false +} +\description{ +Validate the format of the barcodes +} diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R index 3057315..ca99d61 100644 --- a/tests/testthat/helper.R +++ b/tests/testthat/helper.R @@ -1,5 +1,5 @@ #' Create random barcode -random_barcode <- function(size = 10) { +random_barcode <- function(size = 14) { paste0(sample(c("A", "C", "T", "G"), size, replace=TRUE), collapse="") } @@ -17,7 +17,7 @@ create_count_mat <- function(rows, cols, valid_barcodes = FALSE) { colnames <- as.character() if (cols > 0) { if (valid_barcodes) { - colnames <- lapply(rep(10, cols), random_barcode) + colnames <- lapply(rep(14, cols), random_barcode) } else { colnames <- paste0("col", 1:cols) } diff --git a/tests/testthat/test-util.R b/tests/testthat/test-util.R index 0ba587f..b45d7b8 100644 --- a/tests/testthat/test-util.R +++ b/tests/testthat/test-util.R @@ -95,41 +95,3 @@ test_that("deduplicate_clusters prefers named factors", { expect_length(clusters, 1) expect_equal(clusters[[1]], cell_types) }) - -test_that("sanitize_barcodes corrects barcodes", { - # no change - expect_equal(sanitize_barcodes("ACTGAA"), "ACTGAA") - - # no change + lane numbers - expect_equal(sanitize_barcodes("ACTGAA-1"), "ACTGAA-1") - - # prefix - expect_equal(sanitize_barcodes("prefix_ACTGAA"), "ACTGAA-prefix") - expect_equal(sanitize_barcodes("prefix-ACTGAA"), "ACTGAA-prefix") - expect_equal(sanitize_barcodes("prefix:ACTGAA"), "ACTGAA-prefix") - - # barcodes with lane numbers + prefix - expect_equal(sanitize_barcodes("prefix_ACTGAA-1"), "ACTGAA-1-prefix") - expect_equal(sanitize_barcodes("prefix-ACTGAA-1"), "ACTGAA-1-prefix") - expect_equal(sanitize_barcodes("prefix:ACTGAA-1"), "ACTGAA-1-prefix") - - # barcodes + prefix_with_underscore - expect_equal(sanitize_barcodes("pre_fix_ACTGAA"), "ACTGAA-pre_fix") - expect_equal(sanitize_barcodes("pre_fix-ACTGAA"), "ACTGAA-pre_fix") - expect_equal(sanitize_barcodes("pre_fix:ACTGAA"), "ACTGAA-pre_fix") - - # barcodes with lane numbers + prefix_with_underscore - expect_equal(sanitize_barcodes("pre_fix_ACTGAA-1"), "ACTGAA-1-pre_fix") - expect_equal(sanitize_barcodes("pre_fix-ACTGAA-1"), "ACTGAA-1-pre_fix") - expect_equal(sanitize_barcodes("pre_fix:ACTGAA-1"), "ACTGAA-1-pre_fix") - - # barcodes with prefix_with_underscore and suffix_with_underscore - expect_equal(sanitize_barcodes("pre_fix_ACTGAA-suf_fix"), "ACTGAA-pre_fix-suf_fix") - expect_equal(sanitize_barcodes("pre_fix-ACTGAA-suf_fix"), "ACTGAA-pre_fix-suf_fix") - expect_equal(sanitize_barcodes("pre_fix:ACTGAA-suf_fix"), "ACTGAA-pre_fix-suf_fix") - - # barcodes with lane lane numbers with prefix_with_underscore and suffix_with_underscore - expect_equal(sanitize_barcodes("pre_fix_ACTGAA-1-suf_fix"), "ACTGAA-1-pre_fix-suf_fix") - expect_equal(sanitize_barcodes("pre_fix-ACTGAA-1-suf_fix"), "ACTGAA-1-pre_fix-suf_fix") - expect_equal(sanitize_barcodes("pre_fix:ACTGAA-1-suf_fix"), "ACTGAA-1-pre_fix-suf_fix") -}) diff --git a/tests/testthat/test-validate.R b/tests/testthat/test-validate.R index 6b04f39..172b569 100644 --- a/tests/testthat/test-validate.R +++ b/tests/testthat/test-validate.R @@ -40,14 +40,14 @@ test_that("validate count matrix", { # non unique barcodes mat <- create_count_mat(3, 3) - colnames(mat) <- c("ACTGAA-1", "ACTGAA-1", "ACTGAA-1") + colnames(mat) <- c("AAACATACAAACAG-1", "AAACATACAAACAG-1", "AAACATACAAACAG-1") resp <- validate_count_mat(mat) expect_false(resp$success) expect_match(resp$msg, "should be unique") # empty barcode mat <- create_count_mat(3, 3) - colnames(mat) <- c("ACTGAA-1", "ACTGAA-1", "") + colnames(mat) <- c("AAACATACAAACAG-1", "AGACATACAAACAG-1", "") resp <- validate_count_mat(mat) expect_false(resp$success) expect_match(resp$msg, "cannot be the empty string") @@ -60,42 +60,42 @@ test_that("validate count matrix", { # good mat <- create_count_mat(3, 3) - colnames(mat) <- c("ACTGAA-1", "ACTAAA-1", "CTAGAA-1") + colnames(mat) <- c("AAACATACAAACAG-1", "AGACATACAAACAG-1", "ACACATACAAACAG-1") resp <- validate_count_mat(mat) expect_true(resp$success) - # bad, but fixable barcodes - barcodes <- c("prefix-ACTGAA-1", "prefix-ACTAAA-1", "prefix-CTAGAA-1") + # bad + barcodes <- c("prefix-AAACATACAAACAG-1", "prefix-AGACATACAAACAG-1", "prefix-ACACATACAAACAG-1") mat <- create_count_mat(3, 3) colnames(mat) <- barcodes resp <- validate_count_mat(mat) - expect_true(resp$success) + expect_false(resp$success) # feature_ids good mat <- create_count_mat(3, 3) feature_ids <- c("one", "two", "three") - colnames(mat) <- c("ACTGAA-1", "ACTAAA-1", "CTAGAA-1") + colnames(mat) <- c("AAACATACAAACAG-1", "AGACATACAAACAG-1", "ACACATACAAACAG-1") resp <- validate_count_mat(mat, feature_ids = feature_ids) expect_true(resp$success) # feature_ids wrong size mat <- create_count_mat(3, 3) feature_ids <- c("one", "two") - colnames(mat) <- c("ACTGAA-1", "ACTAAA-1", "CTAGAA-1") + colnames(mat) <- c("AAACATACAAACAG-1", "AGACATACAAACAG-1", "ACACATACAAACAG-1") resp <- validate_count_mat(mat, feature_ids = feature_ids) expect_false(resp$success) # feature_ids not unique mat <- create_count_mat(3, 3) feature_ids <- c("one", "one", "one") - colnames(mat) <- c("ACTGAA-1", "ACTAAA-1", "CTAGAA-1") + colnames(mat) <- c("AAACATACAAACAG-1", "AGACATACAAACAG-1", "ACACATACAAACAG-1") resp <- validate_count_mat(mat, feature_ids = feature_ids) expect_false(resp$success) # feature_ids empty string mat <- create_count_mat(3, 3) feature_ids <- c("one", "two", "") - colnames(mat) <- c("ACTGAA-1", "ACTAAA-1", "CTAGAA-1") + colnames(mat) <- c("AAACATACAAACAG-1", "AGACATACAAACAG-1", "ACACATACAAACAG-1") resp <- validate_count_mat(mat, feature_ids = feature_ids) expect_false(resp$success) }) @@ -216,3 +216,130 @@ test_that("validate projections", { resp <- validate_projections(list("p1" = proj), barcode_count) expect_true(resp$success) }) + +test_that("validate_barcodes checks barcodes for proper formatting", { + # no change + expect_true(validate_barcodes("AAACATACAAACAG")$success) + + # no change + lane numbers + expect_true(validate_barcodes("AAACATACAAACAG-1")$success) + + # prefix + expect_true(validate_barcodes("prefix_AAACATACAAACAG")$success) + expect_true(validate_barcodes("prefix:AAACATACAAACAG")$success) + expect_false(validate_barcodes("prefix-AAACATACAAACAG")$success) + + # barcodes with lane numbers + prefix + expect_true(validate_barcodes("prefix_AAACATACAAACAG-1")$success) + expect_true(validate_barcodes("prefix:AAACATACAAACAG-1")$success) + expect_false(validate_barcodes("prefix-AAACATACAAACAG-1")$success) + + # barcodes + prefix_with_underscore + expect_true(validate_barcodes("pre_fix_AAACATACAAACAG")$success) + expect_true(validate_barcodes("pre_fix:AAACATACAAACAG")$success) + expect_false(validate_barcodes("pre_fix-AAACATACAAACAG")$success) + + # other various test cases for the barcode + expect_true(validate_barcodes("_AAACCTGAGAAACG")$success) + expect_true(validate_barcodes("AAACCTGAGAAACG_")$success) + expect_true(validate_barcodes("_AAACCTGAGAAACG_")$success) + expect_true(validate_barcodes(":AAACCTGAGAAACG")$success) + expect_true(validate_barcodes("AAACCTGAGAAACG:")$success) + expect_true(validate_barcodes(":AAACCTGAGAAACG:")$success) + expect_true(validate_barcodes("abc-:AAACCTGAGAAACG:-def")$success) + expect_true(validate_barcodes("AAACATACAAACAG-1")$success) + expect_false(validate_barcodes("abcAAACATACAAACAGxyz")$success) + expect_false(validate_barcodes("AAACATACAAACA")$success) + expect_false(validate_barcodes("AAACATACAAACAD")$success) + expect_false(validate_barcodes("aaacatacaaaacag")$success) + expect_false(validate_barcodes("-aaacatacaaaacag")$success) + expect_false(validate_barcodes("aaacatacaaaacag-")$success) + + # barcodes with lane numbers + prefix_with_underscore + expect_true(validate_barcodes("pre_fix_AAACATACAAACAG-1")$success) + expect_true(validate_barcodes("pre_fix:AAACATACAAACAG-1")$success) + expect_false(validate_barcodes("pre_fix-AAACATACAAACAG-1")$success) + + # barcodes with prefix_with_underscore and suffix_with_underscore + expect_true(validate_barcodes("pre_fix_AAACATACAAACAG_suf_fix")$success) + expect_true(validate_barcodes("pre_fix:AAACATACAAACAG:suf_fix")$success) + expect_false(validate_barcodes("pre_fix-AAACATACAAACAG-suf_fix")$success) + + # barcodes with lane numbers with prefix_with_underscore and suffix_with_underscore + expect_true(validate_barcodes("pre_fix_AAACATACAAACAG-1_suf_fix")$success) + expect_true(validate_barcodes("pre_fix:AAACATACAAACAG-1:suf_fix")$success) + + # unsupported suffixes and prefixes + expect_false(validate_barcodes("pre_fix-AAACATACAAACAG-1-suf_fix")$success) + expect_false(validate_barcodes("pre_fix:AAACATACAAACAG-1-suf_fix")$success) + expect_false(validate_barcodes("pre_fix-AAACATACAAACAG:1-suf_fix")$success) + + # visium hd suffixes and prefixes + expect_true(validate_barcodes("s_008um_00425_00829")$success) + expect_true(validate_barcodes("s_000um_00000_00000")$success) + expect_true(validate_barcodes("_s_008um_00425_00829")$success) + expect_true(validate_barcodes("s_008um_00425_00829_")$success) + expect_true(validate_barcodes("_s_008um_00425_00829_")$success) + expect_true(validate_barcodes(":s_008um_00425_00829")$success) + expect_true(validate_barcodes("s_008um_00425_00829:")$success) + expect_true(validate_barcodes(":s_008um_00425_00829:")$success) + expect_true(validate_barcodes("abc-:s_008um_00425_00829:-def")$success) + + expect_false(validate_barcodes("abcs_000um_00000_00000xyz")$success) + expect_false(validate_barcodes("s_008um_00425_00829-")$success) + expect_false(validate_barcodes("a008um_00425_00829")$success) + expect_false(validate_barcodes("a_008um_00425_00829")$success) + expect_false(validate_barcodes("s_01um_00425_00829")$success) + expect_false(validate_barcodes("s_001am_00425_00829")$success) + expect_false(validate_barcodes("s_008ux_00425_00829")$success) + expect_false(validate_barcodes("s_008um00425_00829")$success) + expect_false(validate_barcodes("s_008um_0425_00829")$success) + expect_false(validate_barcodes("s_008um_0042500829")$success) + expect_false(validate_barcodes("s_008um_00425_0829")$success) + expect_false(validate_barcodes("abcs_008um_00425_0082xyz")$success) + + # visium hd with lane numbers, prefixes and suffixes + expect_true(validate_barcodes("s_008um_00425_00829-1")$success) + expect_true(validate_barcodes("s_000um_00000_00000-2")$success) + expect_true(validate_barcodes("s_000um_00000_00000-10000")$success) + + expect_true(validate_barcodes("_s_008um_00425_00829-1")$success) + expect_true(validate_barcodes("s_008um_00425_00829-2_")$success) + expect_true(validate_barcodes("_s_008um_00425_00829-03_")$success) + expect_true(validate_barcodes(":s_008um_00425_00829-004")$success) + expect_true(validate_barcodes("s_008um_00425_00829-59:")$success) + expect_true(validate_barcodes(":s_008um_00425_00829-0008:")$success) + expect_true(validate_barcodes("abc-:s_008um_00425_00829-0:-def")$success) + + expect_false(validate_barcodes("asdfs_000um_00000_00000-10000")$success) + expect_false(validate_barcodes("abcs_000um_00000_00000-1xyz")$success) + expect_false(validate_barcodes("a008um_00425_00829-1")$success) + expect_false(validate_barcodes("a_008um_00425_00829-1")$success) + expect_false(validate_barcodes("s_01um_00425_00829-1")$success) + expect_false(validate_barcodes("s_001am_00425_00829-1")$success) + expect_false(validate_barcodes("s_008ux_00425_00829-1")$success) + expect_false(validate_barcodes("s_008um00425_00829-1")$success) + expect_false(validate_barcodes("s_008um_0425_00829-1")$success) + expect_false(validate_barcodes("s_008um_0042500829-1")$success) + expect_false(validate_barcodes("s_008um_00425_0829-1")$success) + expect_false(validate_barcodes("s_008um_00425_00829-")$success) + expect_false(validate_barcodes("s_008um_00425_00829-a")$success) + expect_false(validate_barcodes("abcs_000um_00000_00000-xyz")$success) + + # xenium cell ids + expect_true(validate_barcodes("ffkpbaba-1")$success) + expect_true(validate_barcodes("a-1")$success) + expect_true(validate_barcodes("abc-100")$success) + + expect_true(validate_barcodes("_ffkpbaba-1")$success) + expect_true(validate_barcodes("ffkpbaba-3_")$success) + expect_true(validate_barcodes("_ffkpbaba-3_")$success) + expect_true(validate_barcodes(":jjkpbaba-1")$success) + expect_true(validate_barcodes("ffkpbaba-009:")$success) + expect_true(validate_barcodes(":ffkpbaba-123:")$success) + expect_true(validate_barcodes("abc-:ffkpbaba-1:-def")$success) + + expect_false(validate_barcodes("ffkpbabq-10000")$success) + expect_false(validate_barcodes("abcs_ffkpbaba-1xyz")$success) + expect_false(validate_barcodes("affkpbaba-1")$success) +}) From b6e1056a154afd029485e65d4c21d83365e5fc4f Mon Sep 17 00:00:00 2001 From: guy Date: Tue, 15 Oct 2024 10:27:29 -0700 Subject: [PATCH 3/3] Prepare Binary List * Point to the correct binaries and update their md5 sums. --- R/setup.R | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/R/setup.R b/R/setup.R index 2dcedd6..6824e06 100644 --- a/R/setup.R +++ b/R/setup.R @@ -171,16 +171,16 @@ executable_basename <- function() { #' @noRd artifacts = list( linux = list( - url = "https://github.com/10XGenomics/loupeR/releases/download/v1.1.1/louper-linux-x64", - md5 = "99903df7a3bc7b1b06d7509ddddf9a13" + url = "https://github.com/10XGenomics/loupeR/releases/download/v1.1.2/louper-linux-x64", + md5 = "b3fd93fd88a43fbcf3f6e40af3186eaa" ), mac = list( - url = "https://github.com/10XGenomics/loupeR/releases/download/v1.1.1/louper-macos-x64", - md5 = "bf4ff652b88e0b9a88fb306b11a9c066" + url = "https://github.com/10XGenomics/loupeR/releases/download/v1.1.2/louper-macos-x64", + md5 = "ea65a2ec372d623c54d45c51793014e2" ), windows = list( - url = "https://github.com/10XGenomics/loupeR/releases/download/v1.1.1/louper-windows-x64.exe", - md5 = "f40833260e3d4c14d8534a1f3349096d" + url = "https://github.com/10XGenomics/loupeR/releases/download/v1.1.2/louper-windows-x64.exe", + md5 = "f5d1e99138e840169a19191d10bb25ab" ) )