samuel-marsh / scCustomize

R package with collection of functions created and/or curated to aid in the visualization and analysis of single-cell data using R.
https://samuel-marsh.github.io/scCustomize/
GNU General Public License v3.0
203 stars 23 forks source link

as.anndata error with which(single_val_columns)) argument to 'which' is not logical #206

Closed brainfo closed 1 week ago

brainfo commented 1 week ago

I have a spatial seurat object like this

An object of class Seurat 
50256 features across 38729 samples within 2 assays 
Active assay: SCT (25128 features, 6000 variable features)
 3 layers present: counts, data, scale.data
 1 other assay present: Spatial
 3 dimensional reductions calculated: pca, umap, tsne

I'd like to export this into anndata:

as.anndata(
  S115_vs_S120,
  '../../spatialdata-workshops/data',
  'S115_vs_S120.h5ad',
  assay = "SCT",
  main_layer = "data",
  other_layers = c("counts", "scale.data"),
  transer_dimreduc = TRUE,
  verbose = TRUE,
)
Error in `select()`:
ℹ In argument: `which(single_val_columns)`.
Caused by error in `which()`:
! argument to 'which' is not logical
Traceback:

1. as.anndata(S115_vs_S120, "../../spatialdata-workshops/data", 
 .     "S115_vs_S120.h5ad", assay = "SCT", main_layer = "data", 
 .     other_layers = c("counts", "scale.data"), transer_dimreduc = TRUE, 
 .     verbose = TRUE, )
2. as.anndata.Seurat(S115_vs_S120, "../../spatialdata-workshops/data", 
 .     "S115_vs_S120.h5ad", assay = "SCT", main_layer = "data", 
 .     other_layers = c("counts", "scale.data"), transer_dimreduc = TRUE, 
 .     verbose = TRUE, )
3. drop_single_value_cols(df = x[[assay]]@meta.features)
4. df %>% select(which(single_val_columns)) %>% colnames()
5. colnames(.)
6. is.data.frame(x)
7. select(., which(single_val_columns))
8. select.data.frame(., which(single_val_columns))
9. tidyselect::eval_select(expr(c(...)), data = .data, error_call = error_call)
10. eval_select_impl(data, names(data), as_quosure(expr, env), include = include, 
  .     exclude = exclude, strict = strict, name_spec = name_spec, 
  .     allow_rename = allow_rename, allow_empty = allow_empty, allow_predicates = allow_predicates, 
  .     error_call = error_call, )
11. with_subscript_errors(out <- vars_select_eval(vars, expr, strict = strict, 
  .     data = x, name_spec = name_spec, uniquely_named = uniquely_named, 
  .     allow_rename = allow_rename, allow_empty = allow_empty, allow_predicates = allow_predicates, 
  .     type = type, error_call = error_call), type = type)
12. withCallingHandlers(expr, vctrs_error_subscript = function(cnd) {
  .     cnd$subscript_action <- subscript_action(type)
  .     cnd$subscript_elt <- "column"
  .     cnd_signal(cnd)
  . })
13. vars_select_eval(vars, expr, strict = strict, data = x, name_spec = name_spec, 
  .     uniquely_named = uniquely_named, allow_rename = allow_rename, 
  .     allow_empty = allow_empty, allow_predicates = allow_predicates, 
  .     type = type, error_call = error_call)
14. walk_data_tree(expr, data_mask, context_mask)
15. eval_c(expr, data_mask, context_mask)
16. reduce_sels(node, data_mask, context_mask, init = init)
17. walk_data_tree(new, data_mask, context_mask)
18. eval_context(expr, context_mask, call = error_call)
19. with_chained_errors(eval_tidy(as_quosure(expr, env), context_mask), 
  .     call = call, eval_expr = expr)
20. withCallingHandlers(expr, error = function(cnd) {
  .     eval_expr <- quo_squash(eval_expr)
  .     if (!is_call(eval_expr) || identical(cnd[["call"]], call2(eval_expr[[1]]))) {
  .         msg <- ""
  .     }
  .     else {
  .         code <- as_label(eval_expr)
  .         msg <- cli::format_inline("In argument: {.code {code}}.")
  .     }
  .     cli::cli_abort(c(i = msg), call = call, parent = cnd)
  . })
21. eval_tidy(as_quosure(expr, env), context_mask)
22. which(single_val_columns)
23. which(single_val_columns)
24. .handleSimpleError(function (cnd) 
  . {
  .     eval_expr <- quo_squash(eval_expr)
  .     if (!is_call(eval_expr) || identical(cnd[["call"]], call2(eval_expr[[1]]))) {
  .         msg <- ""
  .     }
  .     else {
  .         code <- as_label(eval_expr)
  .         msg <- cli::format_inline("In argument: {.code {code}}.")
  .     }
  .     cli::cli_abort(c(i = msg), call = call, parent = cnd)
  . }, "argument to 'which' is not logical", base::quote(which(single_val_columns)))
25. h(simpleError(msg, call))
26. cli::cli_abort(c(i = msg), call = call, parent = cnd)
27. rlang::abort(message, ..., call = call, use_cli_format = TRUE, 
  .     .frame = .frame)
28. signal_abort(cnd, .file)

<details>
  <summary> sessionInfo() output</summary>

How to make the single_val_columns logical? Why this erroe?

R version 4.2.3 (2023-03-15)
Platform: x86_64-conda-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)

Matrix products: default
BLAS/LAPACK: /data/run01/scv6813/miniforge3/envs/r_env/lib/libopenblasp-r0.3.27.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] scCustomize_2.1.2  Seurat_5.1.0       SeuratObject_5.0.2 sp_2.1-4          

loaded via a namespace (and not attached):
  [1] ggbeeswarm_0.7.2       Rtsne_0.17             colorspace_2.1-0      
  [4] deldir_2.0-4           ggridges_0.5.6         snakecase_0.11.1      
  [7] circlize_0.4.16        IRdisplay_1.1          GlobalOptions_0.1.2   
 [10] RcppHNSW_0.6.0         base64enc_0.1-3        spatstat.data_3.1-2   
 [13] leiden_0.4.3.1         listenv_0.9.1          ggrepel_0.9.5         
 [16] lubridate_1.9.3        RSpectra_0.16-1        fansi_1.0.6           
 [19] codetools_0.2-20       splines_4.2.3          polyclip_1.10-6       
 [22] IRkernel_1.3.2         spam_2.10-0            jsonlite_1.8.8        
 [25] ica_1.0-3              cluster_2.1.6          png_0.1-8             
 [28] uwot_0.1.16            ggprism_1.0.5          shiny_1.8.1.1         
 [31] sctransform_0.4.1      spatstat.sparse_3.1-0  compiler_4.2.3        
 [34] httr_1.4.7             Matrix_1.6-5           fastmap_1.2.0         
 [37] lazyeval_0.2.2         cli_3.6.3              later_1.3.2           
 [40] htmltools_0.5.8.1      tools_4.2.3            igraph_1.4.2          
 [43] dotCall64_1.1-1        gtable_0.3.5           glue_1.7.0            
 [46] RANN_2.6.1             reshape2_1.4.4         dplyr_1.1.4           
 [49] Rcpp_1.0.12            scattermore_1.2        vctrs_0.6.5           
 [52] nlme_3.1-165           spatstat.explore_3.2-6 progressr_0.14.0      
 [55] lmtest_0.9-40          spatstat.random_3.2-3  stringr_1.5.1         
 [58] globals_0.16.3         timechange_0.3.0       mime_0.12             
 [61] miniUI_0.1.1.1         lifecycle_1.0.4        irlba_2.3.5.1         
 [64] goftest_1.2-3          future_1.33.2          MASS_7.3-60.0.1       
 [67] zoo_1.8-12             scales_1.3.0           promises_1.3.0        
 [70] spatstat.utils_3.0-5   parallel_4.2.3         rematch2_2.1.2        
 [73] RColorBrewer_1.1-3     reticulate_1.38.0      pbapply_1.7-2         
 [76] gridExtra_2.3          ggrastr_1.0.2          ggplot2_3.5.1         
 [79] stringi_1.7.12         paletteer_1.6.0        fastDummies_1.7.3     
 [82] shape_1.4.6.1          repr_1.1.7             rlang_1.1.4           
 [85] pkgconfig_2.0.3        matrixStats_1.3.0      evaluate_0.24.0       
 [88] lattice_0.22-6         ROCR_1.0-11            purrr_1.0.2           
 [91] tensor_1.5             patchwork_1.2.0        htmlwidgets_1.6.4     
 [94] cowplot_1.1.3          tidyselect_1.2.1       parallelly_1.37.1     
 [97] RcppAnnoy_0.0.22       plyr_1.8.9             magrittr_2.0.3        
[100] R6_2.5.1               generics_0.1.3         pbdZMQ_0.3-11         
[103] withr_3.0.0            pillar_1.9.0           fitdistrplus_1.1-11   
[106] survival_3.7-0         abind_1.4-5            tibble_3.2.1          
[109] future.apply_1.11.2    janitor_2.2.0          crayon_1.5.3          
[112] uuid_1.2-0             KernSmooth_2.23-24     utf8_1.2.4            
[115] spatstat.geom_3.2-9    plotly_4.10.4          grid_4.2.3            
[118] data.table_1.15.2      forcats_1.0.0          digest_0.6.36         
[121] xtable_1.8-4           tidyr_1.3.1            httpuv_1.6.15         
[124] munsell_0.5.1          beeswarm_0.4.0         viridisLite_0.4.2     
[127] vipor_0.4.7   

Thanks for helping me in advance

2015pp commented 1 week ago

As the author said, this issue has now been resolved in the release branch. Please install with:

devtools::install_github("samuel-marsh/scCustomize", ref = "release/3.0.0")

Or, you can download the version 2.9.9.9086 by "https://codeload.github.com/samuel-marsh/scCustomize/legacy.tar.gz/refs/heads/release/3.0.0" and install the scCustomize package by the function devtools::install_local().

samuel-marsh commented 1 week ago

Hi @brainfo,

If the issue persists in the release branch please let me know. I aim to push the release branch to CRAN hopefully in next week or so.

Please also note that as.anndata has not been tested for transfer of spatial assays. There is additional meta data that usually accompanies spatial assays that is not transferred by this function (spot sizes, actual images etc). At this time I do not have bandwidth to add spatial support to function but would be happy to entertain PR or check code if you are interested in such capabilities.

Best, Sam

brainfo commented 6 days ago

Hi @brainfo,

If the issue persists in the release branch please let me know. I aim to push the release branch to CRAN hopefully in next week or so.

Please also note that as.anndata has not been tested for transfer of spatial assays. There is additional meta data that usually accompanies spatial assays that is not transferred by this function (spot sizes, actual images etc). At this time I do not have bandwidth to add spatial support to function but would be happy to entertain PR or check code if you are interested in such capabilities.

Best, Sam

Thanks Sam, Now the as.anndata works to create anndata (with main_layer and layers in other_layers having same shape). I think I would work around by create object in scverse community from the anndata and provide the other information such as spot sizes, images etc. Because I heard that the bioconductor team are working on supporting read/write operations of SpatialData Zarr objects, maybe I won't really PR to solve all the missing functionality here. But a PR to support fillna of the layers with different shapes to the same shape as the main layer (LayerData/slot not support fetching/creating empty/faking non-exist feature or col names?) will be of help to convert to anndata with all available layers, though it's not a very legit need.

Best, Ruby