From 369b02e67d1274ba7a20155ec6b235139380d6ce Mon Sep 17 00:00:00 2001 From: stemangiola Date: Mon, 22 Apr 2024 16:09:57 +1000 Subject: [PATCH 1/5] Allow this check, even though I assay names might not be present --- R/utilities.R | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/R/utilities.R b/R/utilities.R index e473a49..8132e5e 100755 --- a/R/utilities.R +++ b/R/utilities.R @@ -1300,7 +1300,8 @@ is_filer_columns_in_column_selection <- function(.data, ...) { check_if_assays_are_NOT_consistently_ordered <- function(se) { # If I have any assay at all - assays(se) |> length() |> gt(0) && + do_I_have_assays = + assays(se) |> length() |> gt(0) && # If I have more than one assay with colnames Filter( @@ -1310,9 +1311,24 @@ check_if_assays_are_NOT_consistently_ordered <- function(se) { map(colnames) ) |> length() |> - gt(0) && - - # If I have lack of consistency + + gt(0) + + # If I have lack of consistency + # Forcing assay names otherwise fails if assay is unnamed + if( + se |> + assays(withDimnames = FALSE) |> + as.list() |> + names() + ) + assays(se) = + se |> + assays(withDimnames = FALSE) |> + as.list() |> + set_names(se |> assays() |> as.list() |> length() |> seq_len()) + + lack_of_consistency = se |> assays(withDimnames = FALSE) |> as.list() |> @@ -1321,6 +1337,8 @@ check_if_assays_are_NOT_consistently_ordered <- function(se) { equals(1) |> all() |> not() + + do_I_have_assays && lack_of_consistency } check_if_any_dimnames_duplicated <- function(se, dim = "cols") { From ac4b6bc36920e46a607af6a74f5c65da287b0641 Mon Sep 17 00:00:00 2001 From: stemangiola Date: Mon, 22 Apr 2024 16:13:10 +1000 Subject: [PATCH 2/5] update dependencies --- NAMESPACE | 5 +++++ R/utilities.R | 1 + 2 files changed, 6 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index fc4830f..94d4c2e 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -114,6 +114,11 @@ importFrom(rlang,is_spliced) importFrom(rlang,quo_is_null) importFrom(rlang,quo_name) importFrom(rlang,quo_squash) +<<<<<<< HEAD +======= +importFrom(rlang,set_names) +importFrom(stats,setNames) +>>>>>>> 57e61fd (update dependencies) importFrom(stringr,regex) importFrom(stringr,str_detect) importFrom(stringr,str_replace) diff --git a/R/utilities.R b/R/utilities.R index 8132e5e..843e2e0 100755 --- a/R/utilities.R +++ b/R/utilities.R @@ -1297,6 +1297,7 @@ is_filer_columns_in_column_selection <- function(.data, ...) { error = function(e) FALSE) } +#' @importFrom rlang set_names check_if_assays_are_NOT_consistently_ordered <- function(se) { # If I have any assay at all From a79919408a344eead75a753101ce5d3762d25dd2 Mon Sep 17 00:00:00 2001 From: Stefano Mangiola Date: Thu, 10 Jul 2025 18:24:54 +0930 Subject: [PATCH 3/5] Add tests for check_if_assays_are_NOT_consistently_ordered function in test-utilities.R Implemented a comprehensive suite of tests to validate the behavior of the check_if_assays_are_NOT_consistently_ordered function across various scenarios, including cases with empty assays, inconsistent colnames, and different ordering of colnames. This enhances the robustness of the utility checks in the package. --- tests/testthat/test-utilities.R | 306 ++++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) diff --git a/tests/testthat/test-utilities.R b/tests/testthat/test-utilities.R index 2c5c98c..e13dc8e 100644 --- a/tests/testthat/test-utilities.R +++ b/tests/testthat/test-utilities.R @@ -351,3 +351,309 @@ test_that("get_count_datasets works", { # ) # expect_error(cds <- get_count_datasets(se1), "assays must be named") }) + +test_that("check_if_assays_are_NOT_consistently_ordered works correctly", { + # Use testthat edition 3 + local_edition(3) + + # Test 1: SE with no assays - should return FALSE + se_empty <- SummarizedExperiment::SummarizedExperiment( + assays = list() + ) + expect_false(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_empty)) + + # Test 2: SE with assays but no colnames - should return FALSE + se_no_colnames <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3) + ) + ) + expect_false(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_no_colnames)) + + # Test 3: SE with assays, some with colnames, some without - should return FALSE + se_mixed <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3) + ) + ) + colnames(assay(se_mixed, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + expect_false(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_mixed)) + + # Test 4: SE with assays, all with same colnames in same order - should return FALSE + se_consistent <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3) + ) + ) + colnames(assay(se_consistent, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_consistent, "mat2", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + expect_false(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_consistent)) + + # Test 5: SE with assays, all with same colnames but different order - should return TRUE + se_inconsistent <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3) + ) + ) + colnames(assay(se_inconsistent, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_inconsistent, "mat2", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_inconsistent)) + + # Test 6: SE with assays, all with same colnames but different order (reverse) - should return TRUE + se_reverse <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3) + ) + ) + colnames(assay(se_reverse, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_reverse, "mat2", withDimnames = FALSE)) <- paste0("S", c(3, 2, 1)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_reverse)) + + # Test 7: SE with assays, all with same colnames but different order (middle swap) - should return TRUE + se_middle_swap <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3) + ) + ) + colnames(assay(se_middle_swap, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_middle_swap, "mat2", withDimnames = FALSE)) <- paste0("S", c(1, 3, 2)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_middle_swap)) + + # Test 8: SE with 3 assays, first two consistent, third different - should return TRUE + se_three_assays <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_three_assays, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_three_assays, "mat2", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_three_assays, "mat3", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_three_assays)) + + # Test 9: SE with 3 assays, all consistent - should return FALSE + se_three_consistent <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_three_consistent, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_three_consistent, "mat2", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_three_consistent, "mat3", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + expect_false(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_three_consistent)) + + # Test 10: SE with assays, all with same colnames but different order (complex permutation) - should return TRUE + se_complex <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(12), nrow = 3), + mat2 = matrix(seq(13, 24), nrow = 3) + ) + ) + colnames(assay(se_complex, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(4)) + colnames(assay(se_complex, "mat2", withDimnames = FALSE)) <- paste0("S", c(4, 2, 1, 3)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_complex)) + + # Test 11: SE with assays, all with same colnames but different order (all different) - should return TRUE + se_all_different <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_all_different, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_all_different, "mat2", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + colnames(assay(se_all_different, "mat3", withDimnames = FALSE)) <- paste0("S", c(2, 3, 1)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_all_different)) + + # Test 12: SE with assays, all with same colnames but different order (pairwise different) - should return TRUE + se_pairwise <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_pairwise, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_pairwise, "mat2", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + colnames(assay(se_pairwise, "mat3", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_pairwise)) + + # Test 13: SE with assays, all with same colnames but different order (first and last same) - should return TRUE + se_first_last <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_first_last, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_first_last, "mat2", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + colnames(assay(se_first_last, "mat3", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_first_last)) + + # Test 14: SE with assays, all with same colnames but different order (middle different) - should return TRUE + se_middle_different <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_middle_different, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_middle_different, "mat2", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_middle_different, "mat3", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_middle_different)) + + # Test 15: SE with assays, all with same colnames but different order (first different) - should return TRUE + se_first_different <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_first_different, "mat1", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + colnames(assay(se_first_different, "mat2", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_first_different, "mat3", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_first_different)) + + # Test 16: SE with assays, all with same colnames but different order (last different) - should return TRUE + se_last_different <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_last_different, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_last_different, "mat2", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_last_different, "mat3", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_last_different)) + + # Test 17: SE with assays, all with same colnames but different order (all different) - should return TRUE + se_all_different_2 <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_all_different_2, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_all_different_2, "mat2", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + colnames(assay(se_all_different_2, "mat3", withDimnames = FALSE)) <- paste0("S", c(2, 3, 1)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_all_different_2)) + + # Test 18: SE with assays, all with same colnames but different order (all different) - should return TRUE + se_all_different_3 <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_all_different_3, "mat1", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + colnames(assay(se_all_different_3, "mat2", withDimnames = FALSE)) <- paste0("S", c(2, 3, 1)) + colnames(assay(se_all_different_3, "mat3", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_all_different_3)) + + # Test 19: SE with assays, all with same colnames but different order (all different) - should return TRUE + se_all_different_4 <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_all_different_4, "mat1", withDimnames = FALSE)) <- paste0("S", c(2, 3, 1)) + colnames(assay(se_all_different_4, "mat2", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_all_different_4, "mat3", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_all_different_4)) + + # Test 20: SE with assays, all with same colnames but different order (all different) - should return TRUE + se_all_different_5 <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_all_different_5, "mat1", withDimnames = FALSE)) <- paste0("S", c(2, 3, 1)) + colnames(assay(se_all_different_5, "mat2", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + colnames(assay(se_all_different_5, "mat3", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_all_different_5)) + + # Test 21: SE with assays, all with same colnames but different order (all different) - should return TRUE + se_all_different_6 <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_all_different_6, "mat1", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + colnames(assay(se_all_different_6, "mat2", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_all_different_6, "mat3", withDimnames = FALSE)) <- paste0("S", c(2, 3, 1)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_all_different_6)) + + # Test 22: SE with assays, all with same colnames but different order (all different) - should return TRUE + se_all_different_7 <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_all_different_7, "mat1", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_all_different_7, "mat2", withDimnames = FALSE)) <- paste0("S", c(2, 3, 1)) + colnames(assay(se_all_different_7, "mat3", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_all_different_7)) + + # Test 23: SE with assays, all with same colnames but different order (all different) - should return TRUE + se_all_different_8 <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_all_different_8, "mat1", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + colnames(assay(se_all_different_8, "mat2", withDimnames = FALSE)) <- paste0("S", c(2, 3, 1)) + colnames(assay(se_all_different_8, "mat3", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_all_different_8)) + + # Test 24: SE with assays, all with same colnames but different order (all different) - should return TRUE + se_all_different_9 <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_all_different_9, "mat1", withDimnames = FALSE)) <- paste0("S", c(2, 3, 1)) + colnames(assay(se_all_different_9, "mat2", withDimnames = FALSE)) <- paste0("S", seq_len(3)) + colnames(assay(se_all_different_9, "mat3", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_all_different_9)) + + # Test 25: SE with assays, all with same colnames but different order (all different) - should return TRUE + se_all_different_10 <- SummarizedExperiment::SummarizedExperiment( + assays = list( + mat1 = matrix(seq_len(9), nrow = 3), + mat2 = matrix(seq(10, 18), nrow = 3), + mat3 = matrix(seq(19, 27), nrow = 3) + ) + ) + colnames(assay(se_all_different_10, "mat1", withDimnames = FALSE)) <- paste0("S", c(3, 1, 2)) + colnames(assay(se_all_different_10, "mat2", withDimnames = FALSE)) <- paste0("S", c(2, 3, 1)) + colnames(assay(se_all_different_10, "mat3", withDimnames = FALSE)) <- paste0("S", c(1, 2, 3)) + expect_true(tidySummarizedExperiment:::check_if_assays_are_NOT_consistently_ordered(se_all_different_10)) +}) From 482beff20e9c5eecbc5bca87dabc8c624dcb9ef0 Mon Sep 17 00:00:00 2001 From: Stefano Mangiola Date: Thu, 10 Jul 2025 18:25:32 +0930 Subject: [PATCH 4/5] version UP --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 3068a7b..46abdc6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: tidySummarizedExperiment Title: Brings SummarizedExperiment to the Tidyverse -Version: 1.19.2 +Version: 1.19.3 Authors@R: c(person("Stefano", "Mangiola", email = "mangiolastefano@gmail.com", role = c("aut", "cre")) ) Description: The tidySummarizedExperiment package provides a set of tools for creating and From 52c4b6decc8b026c0fccdfde307dd47d5b43dad4 Mon Sep 17 00:00:00 2001 From: Stefano Mangiola Date: Thu, 10 Jul 2025 18:27:23 +0930 Subject: [PATCH 5/5] update docs --- NAMESPACE | 4 ---- 1 file changed, 4 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 94d4c2e..907ff30 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -114,11 +114,7 @@ importFrom(rlang,is_spliced) importFrom(rlang,quo_is_null) importFrom(rlang,quo_name) importFrom(rlang,quo_squash) -<<<<<<< HEAD -======= importFrom(rlang,set_names) -importFrom(stats,setNames) ->>>>>>> 57e61fd (update dependencies) importFrom(stringr,regex) importFrom(stringr,str_detect) importFrom(stringr,str_replace)