是否可以在 Snakemake 中有一个可选的输出文件?

Is it possible to have an optional output file in Snakemake?

我正在编写一个 snakemake 规则,它将处理对单端或双端测序数据执行 fastq 修剪。如果数据是双端的,应该有两个输出文件,如果是单端的,应该有一个。

我写的规则到目前为止有效,但是,我不知道第二对修剪后的文件是输出文件。这意味着 snakemake 不会检查该文件是否存在。它会输出,但它不检查,是否可以有一个可选输出?

    input:
    #get the value in the fast1 column
        fastq_file = lambda wildcards: return_fastq(wildcards.fastq_name,wildcards.unit,first_pair = True)
    output:
        out_fastqc = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_trimmed.fastq.gz",
        fastpjson = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_fastp.json",
        fastphtml = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_fastp.html"
    params:
        fastp_parameters = return_parsed_extra_params(config['fastp_parameters']),
        fastq_file2 = lambda wildcards: return_fastq(wildcards.fastq_name,wildcards.unit,first_pair = False),
        out_fastqc2 = lambda wildcards: return_fastq2_name(wildcards.fastq_name,wildcards.unit),
        fastpjson = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_fastp.json",
        fastphtml = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_fastp.html"
    run:
        if config["end_type"] == "se":
            shell("{config[fastp_path]} -i {input.fastq_file} -o {output.out_fastqc} --json {output.fastpjson} --html {output.fastphtml} {params.fastp_parameters}")
        if config["end_type"] == "pe":
            shell("{config[fastp_path]} --in1 {input.fastq_file} --in2 {params.fastq_file2} --out1 {output.out_fastqc} --out2  {params.out_fastqc2} --json {output.fastpjson} --html {output.fastphtml} {params.fastp_parameters}")

目标是 out_fastqc2 将作为规则的可选输出包含在内,以便 snakemake 将检查它是否存在,如果不存在,则适当地给我一个错误。

如果 Snakemake 不允许可选输出,我可以分成两条规则,但这不是我想要的。

看看expand函数是如何工作的。它在 Snakemake 构建依赖关系的 DAG 阶段被调用,它使用这个函数的结果来构建 output 部分的文件列表。

我建议您尝试相同的方法:构造一个空或空的列表 - 取决于条件。

只有当您事先知道是否需要 out_fastqc2 时,此解决方案才有效(但是定义 2 个具有优先级的规则也是如此)。如果您仅在 运行 规则时获得有关 out_fastqc2 需求的信息,那么您需要检查点的情况就完全不同了。

下面是说明我的方法的代码:out_fastqc2 变成描述文件的字符串(如果 end_type 配置为 "pe"),否则变成空列表这不会更改输出列表。

output:
    out_fastqc = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_trimmed.fastq.gz",
    out_fastqc2 = lambda wildcards: return_fastq2_name(wildcards.fastq_name,wildcards.unit) if config["end_type"] == "pe" else []

由于 paired-end 和 single-end 之间的选择似乎在配置中是固定的,您可以尝试根据配置以两种方式定义规则:

if config["end_type"] == "se":
    rule do_fastp:
        input:
        #get the value in the fast1 column
            fastq_file = lambda wildcards: return_fastq(wildcards.fastq_name, wildcards.unit, first_pair = True)
        output:
            out_fastqc = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_trimmed.fastq.gz",
            fastpjson = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_fastp.json",
            fastphtml = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_fastp.html"
        params:
            fastp_parameters = return_parsed_extra_params(config['fastp_parameters']),
        shell:
            """
            {config[fastp_path]} -i {input.fastq_file} -o {output.out_fastqc} \
                --json {output.fastpjson} --html {output.fastphtml} \
                {params.fastp_parameters}
            """
if config["end_type"] == "pe":
    rule do_fastp:
        input:
        #get the value in the fast1 column
            fastq_file1 = lambda wildcards: return_fastq(wildcards.fastq_name, wildcards.unit, first_pair = True),
            fastq_file2 = lambda wildcards: return_fastq(wildcards.fastq_name, wildcards.unit, first_pair = False)
        output:
            out_fastqc1 = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_trimmed_1.fastq.gz",
            out_fastqc2 = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_trimmed_2.fastq.gz",
            fastpjson = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_fastp.json",
            fastphtml = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_fastp.html"
        params:
            fastp_parameters = return_parsed_extra_params(config['fastp_parameters']),
        shell:
            """
            {config[fastp_path]} \
                --in1 {input.fastq_file1} --in2 {params.fastq_file2} \
                --out1 {output.out_fastqc1} --out2 {output.out_fastqc2} \
                --json {output.fastpjson} --html {output.fastphtml} \
                {params.fastp_parameters}
            """