You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:52:55