在 Snakemake 中不能正常使用星号作为球形图案

Cannot use asterisk as glob pattern normally in Snakemake

提问人:Xiaokang 提问时间:11/9/2023 更新时间:11/10/2023 访问量:25

问:

我想使用星号作为 glob 模式来代表 Snakemake 规则文件中的“除 / 之外的任何字符串”(如 glob Wikipedia 中所述)。但是注意到我不能像在壳牌终端中那样正常使用它。我是在我的规则文件中犯了什么错误,还是因为 Snakemake 在最新版本中禁止了它?shell

我的规则文件如下所示:

barcodes = ["AAA", "GGG", "TTT"]

rule end:
    input: "output/merged.txt"

rule test_glob:
    input: "per_barcode/sample_*_rep_{barcode}.txt"
    output: "output/{barcode}.txt"
    shell:
        "head {input} > {output}"

rule merge:
    input: expand("output/{barcode}.txt", barcode = barcodes)
    output: "output/merged.txt"
    shell: 
        "cat {input} > {output}"

文件是:

ls per_barcode/
sample_10_rep_GGG.txt  sample_2_rep_AAA.txt  sample_5_rep_TTT.txt

错误消息是:

MissingInputException in line 7 of test.smk:
Missing input files for rule test_regex:
per_barcode/sample_*_rep_GGG.txt

但是,如果我将规则更改为以下内容以在命令中使用 glob 模式而不是 ,它会起作用:test_globshellinput

rule test_glob:
    output: "output/{barcode}.txt"
    shell:
        "head per_barcode/sample_*_rep_{wildcards.barcode}.txt > {output}"
蛇制作

评论


答:

0赞 Troy Comi 11/10/2023 #1

由于执行范式,snakemake 中的通用星号球存在一些问题。星号表示“给我此处存在的所有文件”,但 snakemake 需要知道这些文件是什么,以便它可以生成它们(如果需要)。在第二个示例中,当它运行时,它无法通知 snakemake 输入文件的实际内容。如果修改示例文件,snakemake 将无法检测并重新运行该规则。更好的编写方法是使用输入函数:

barcodes = ["AAA", "GGG", "TTT"]

rule end:
    input: "output/merged.txt"

def test_glob_input(wildcards):
    # get list of samples, format name with barcode from wildcards
    samples = glob_wildcards(
                 f"per_barcode/sample_{{sample}}_rep_{wildcards.barcode}.txt"
              ).sample
    return expand(
           "per_barcode/sample_{sample}_rep_{barcode}.txt",
           sample=samples,
           barcode=wildcards.barcode)


rule test_glob:
    input: test_glob_input
    output: "output/{barcode}.txt"
    shell:
        "head {input} > {output}"

rule merge:
    input: expand("output/{barcode}.txt", barcode = barcodes)
    output: "output/merged.txt"
    shell: 
        "cat {input} > {output}"

现在,如果文件发生更改,snakemake 将重新运行相关输出。但是,如果必须首先生成这些示例文件,这将失败,因为它只查看文件系统上的当前内容。这可能不是问题,但最好的方法是使用一个 config、json 或 csv 文件,该文件可以将每个样本映射到条形码。然后,您的输入函数可以从中提取以确定它需要哪些样本。

barcodes = ["AAA", "GGG", "TTT"]
# need a dictionary or dataframe with barcode to sample mapping
barcodes_to_sample = {"AAA": ['a1', 'a2', a3'], "GGG": ['g1', 'g2'], ...}

rule end:
    input: "output/merged.txt"

def test_glob_input(wildcards):
    # get list of samples from wildcard information
    samples = barcodes_to_sample[wildcards.barcode]
    return expand(
           "per_barcode/sample_{sample}_rep_{barcode}.txt",
           sample=samples,
           barcode=wildcards.barcode)


rule test_glob:
    input: test_glob_input
    output: "output/{barcode}.txt"
    shell:
        "head {input} > {output}"

rule merge:
    input: expand("output/{barcode}.txt", barcode = barcodes)
    output: "output/merged.txt"
    shell: 
        "cat {input} > {output}"

虽然这会微妙地改变文件,但对执行的影响意味着您可以添加上游规则,例如下载或过滤文件,并且仍然可以正常工作。

我不确定 snakemake 是否允许在输入规则 ASAIK 中使用 glob 星号。