如何在Snakemake中为R脚本设置非硬编码的工作目录?
问题描述
按照Snakemake官方部署规范构建目录结构后,R脚本位于My_project/workflow/scripts/seurat.R。从My_project目录运行snakemake --profile slurm时,希望R脚本将My_project作为工作目录,且不硬编码路径。目前单独运行R脚本正常,但在Snakemake中存在工作目录问题,且无法通过save.image()保存工作区用于调试。
现有规则代码
rule seurat: input: tsv="results/souporcell_{sample}/clusters.tsv", mtx="results/cr_{sample}/outs/filtered_feature_bc_matrix" output: rds_export = "results/seurat_{sample}.rds" log: "results/seurat_{sample}.log" params: k_indiv=config["INDIVIDUALS"], sample = "{sample}" #conda: #"envs/r_software.yaml" script: "workflow/scripts/seurat.R"
现有R脚本代码
sample <- snakemake@params[['sample']] input <- read_delim(here::here(paste0("My_project/results/souporcell_", sample,"/clusters.tsv")), delim = "\t", escape_double = FALSE, trim_ws = TRUE) k_indiv <- snakemake@params[['k_indiv']] no_clusters <- (1:k_indiv) # Read MTX/TSV files (results in an S4 object) counts.data <- Read10X( data.dir = here::here(paste0("My_project/results/cr_", sample, "/outs/filtered_feature_bc_matrix")), gene.column = 2, cell.column = 1, unique.features = TRUE, strip.suffix = FALSE ) seurat_object <- CreateSeuratObject(counts.data, project = sample) seurat_object <- AddMetaData(object = seurat_object, metadata = input$assignment, col.name = "assignment") # Remove "NA" (doublets cells / two or more cells in one GEM) seurat_filtered <- subset(seurat_object, subset = assignment != "NA") # Split S4 object by condition seurat_split.list <- SplitObject(seurat_filtered, split.by = "assignment") # Export the S4 object saveRDS(seurat_split.list, file = here::here(paste0( "My_project/results/seurat_", sample,".rds"))) # Save image for debugging save.image("snake_debug.RData")
解决方案
1. 利用Snakemake对象传递路径(推荐)
Snakemake运行脚本时默认以调用命令的My_project为工作目录,问题根源是你硬编码了My_project前缀,且here包会根据脚本位置推断根目录导致路径错误。最规范的做法是直接从snakemake对象获取输入输出路径,完全避免硬编码:
修改后的R脚本:
sample <- snakemake@params[['sample']] k_indiv <- snakemake@params[['k_indiv']] no_clusters <- (1:k_indiv) # 直接读取snakemake输入文件 input <- read_delim(snakemake@input[['tsv']], delim = "\t", escape_double = FALSE, trim_ws = TRUE) # 直接使用snakemake输入的mtx路径读取矩阵 counts.data <- Read10X( data.dir = snakemake@input[['mtx']], gene.column = 2, cell.column = 1, unique.features = TRUE, strip.suffix = FALSE ) seurat_object <- CreateSeuratObject(counts.data, project = sample) seurat_object <- AddMetaData(object = seurat_object, metadata = input$assignment, col.name = "assignment") seurat_filtered <- subset(seurat_object, subset = assignment != "NA") seurat_split.list <- SplitObject(seurat_filtered, split.by = "assignment") # 直接用snakemake输出路径保存结果 saveRDS(seurat_split.list, file = snakemake@output[['rds_export']]) # 将调试工作区保存到log目录,避免分散在各处 save.image(file = file.path(dirname(snakemake@log[[1]]), paste0("snake_debug_", sample, ".RData")))
2. 让here包正确识别根目录(可选)
如果一定要用here包,在My_project目录下创建标记文件.here,here::here()会自动将包含该文件的目录作为根目录:
touch My_project/.here
之后R脚本中可直接写相对路径:
input <- read_delim(here::here("results", paste0("souporcell_", sample), "clusters.tsv"))
3. 规则中无需额外配置工作目录
Snakemake默认以调用命令的目录为工作目录,不需要在rule或config.yaml中额外指定。若强制指定可添加workdir参数,但会降低项目可移植性,不推荐:
rule seurat: # 其他参数不变 workdir: "/path/to/My_project"
内容的提问来源于stack exchange,提问作者Robin Garcia Victoria
相关产品推荐
相关产品推荐

