Snakemake:关于如何正确访问配置文件的困惑

Snakemake: confusion on how to access config files properly

这个问题来自 我之前问过的问题,它与理解如何使用 Snakemake 正确访问配置文件有关。我有一个需要解决的特定问题,我会先问,然后再问一个理解索引如何工作的一般问题。

我正在使用 snakemake 到 运行 和从 Alignment/QC 到主题分析的 ATAC-seq 管道。

答:具体问题

我正在尝试在对齐之前从我的 fastq 文件中向 trim 适配器添加一个名为 trim_galore_pe 的规则,并且从 snakemake 中抛出一条错误语句作为 [ 生成的输出文件的名称=17=] 与 snakemake 所期望的不匹配。这是因为我不知道如何在我的 snakemake 文件中正确编写输出文件语句以使名称匹配。

TRIM GALORE 生成的名称示例包含 SRA 编号,例如:

trimmed_fastq_files/SRR2920475_1_val_1.fq.gz

而 snakemake 期望的文件包含 sample 引用并且应该是:

trimmed_fastq_files/Corces2016_4983.7B_Mono_1_val_1.fq.gz

这也会影响trim_galore_pe规则之后的后续规则。我需要想出一种方法来使用我的配置文件中的信息来生成所需的输出文件。

对于 Snakefile 中显示的规则之后的所有规则,我需要文件以 样本名称 命名,即 Corces2016_4983.7A_Mono。对于下面的 Snakefile 中显示的所有 FAST_QCMULTIQC 规则,在输出文件名结构中包含 样本名称 也是有用的,它们都是已经在当前的 Snakefile 中做了。

但是,Bowtie2 的输入、FASTQC 规则以及 trim_galore_pe 规则的输入和输出需要包含 SRA 编号。问题从 trim_galore 的输出开始并影响所有下游规则。

虽然我已经在之前的规则中提取了 SRA 编号,但我不确定在不使用配置文件中明确说明的 fastq_files 文件夹时如何执行此操作。通过引入 trim_galore_pe 规则,我有效地将一组新的 SRA 文件移到了新的 trimmed_fastq_files 文件夹中。如何从包含旧文件夹名称的 SRA 文件配置文件列表中提取 SRA 编号,同时引用 Snakefile 中的新 trimmed_fastq_files 文件夹是我问题的症结所在。

我希望这是清楚的。

这是我的配置文件:

samples:
    Corces2016_4983.7A_Mono: fastq_files/SRR2920475
    Corces2016_4983.7B_Mono: fastq_files/SRR2920476
cell_types:
    Mono:
    - Corces2016_4983.7A
index: /home/genomes_and_index_files/hg19

这是我的 Snakefile:

# read config info into this namespace
configfile: "config.yaml"
print (config['samples'])

rule all:
    input:
        expand("FastQC/PRETRIM/{sample}_{num}_fastqc.zip", sample=config["samples"], num=['1', '2']),
        expand("bam_files/{sample}.bam", sample=config["samples"]),
        "FastQC/PRETRIM/fastq_multiqc.html",
        "FastQC/POSTTRIM/fastq_multiqc.html"

rule fastqc_pretrim:
    input:
        sample=lambda wildcards: f"{config['samples'][wildcards.sample]}_{wildcards.num}.fastq.gz"
    output:
        # Output needs to end in '_fastqc.html' for multiqc to work
        html="FastQC/PRETRIM/{sample}_{num}_fastqc.html",
        zip="FastQC/PRETRIM/{sample}_{num}_fastqc.zip"
    wrapper:
        "0.23.1/bio/fastqc"

rule multiqc_fastq_pretrim:
    input:
        expand("FastQC/PRETRIM/{sample}_{num}_fastqc.html", sample=config["samples"], num=['1', '2'])
    output:
        "FastQC/PRETRIM/fastq_multiqc.html"
    wrapper:
        "0.23.1/bio/multiqc"

rule trim_galore_pe:
    input:
        sample=lambda wildcards: expand(f"{config['samples'][wildcards.sample]}_{{num}}.fastq.gz", num=[1,2])
    output:
        "trimmed_fastq_files/{sample}_1_val_1.fq.gz",
        "trimmed_fastq_files/{sample}_1.fastq.gz_trimming_report.txt",
        "trimmed_fastq_files/{sample}_2_val_2.fq.gz",
        "trimmed_fastq_files/{sample}_2.fastq.gz_trimming_report.txt"
    params:
        extra="--illumina -q 20"
    log:
        "logs/trim_galore/{sample}.log"
    wrapper:
        "0.23.1/bio/trim_galore/pe"

rule fastqc_posttrim:
    input:
        "trimmed_fastq_files/{sample}_1_val_1.fq.gz", "trimmed_fastq_files/{sample}_2_val_2.fq.gz"
    output:
        # Output needs to end in '_fastqc.html' for multiqc to work
        html="FastQC/POSTTRIM/{sample}_{num}_fastqc.html",
        zip="FastQC/POSTTRIM/{sample}_{num}_fastqc.zip"
    wrapper:
        "0.23.1/bio/fastqc"

rule multiqc_fastq_posttrim:
    input:
        expand("FastQC/POSTTRIM/{sample}_{num}.trim_fastqc.html", sample=config["samples"], num=['1', '2'])
    output:
        "FastQC/POSTTRIM/fastq_multiqc.html"
    wrapper:
        "0.23.1/bio/multiqc"

rule bowtie2:
    input:
        "trimmed_fastq_files/{sample}_1_val_1.fq.gz", "trimmed_fastq_files/{sample}_2_val_2.fq.gz"
    output:
        "bam_files/{sample}.bam"
    log:
        "logs/bowtie2/{sample}.txt"
    params:
       index=config["index"],  # prefix of reference genome index (built with bowtie2-build),
       extra=""
    threads: 8
    wrapper:
        "0.23.1/bio/bowtie2/align"

当前 运行s,并使用 snakemake -np 给出完整的工作列表,但抛出上述错误。

B: 一般问题

是否有在线资源简要说明如何使用 python 引用配置文件,尤其是关于 snakemake 的引用?在线文档非常不足,并且假定先验知识 python。

我的编程经验主要是 bash 和 R,但我喜欢 Snakemake,并且大体上了解字典和列表在 python 中的工作原理以及如何引用存储在其中的项目。然而,我发现在上面的一些 Snakemake 规则中,括号、通配符和引号的复杂使用令人困惑,因此在尝试引用配置文件中文件名的不同部分时往往会遇到困难。我想充分了解如何利用这些元素。

例如,在上面发布的 Snakefile 中的这样一条规则中:

sample=lambda wildcards: expand(f"{config['samples'][wildcards.sample]}_{{num}}.fastq.gz", num=[1,2]) 

这个命令实际上发生了什么?我的理解是我们正在使用 config['samples'] 访问配置文件,我们正在使用 [wildcards.sample] 部分来显式访问配置文件的 fastq_files/SRR2920475 部分。 expand 允许我们遍历配置文件中符合命令参数的每个项目,即所有 SRA 文件,并且需要 lambda 通配符才能在命令中使用 wildcards 调用。我不确定的是:

  1. 展开后 f 的作用是什么?为什么需要它?
  2. 为什么 config['samples'] 在方括号内包含引号,但 [wildcards.sample] 周围不需要引号?
  3. 为什么要使用单大括号和双大括号?
  4. 查看上面的 Snakefile,一些规则包含将数字序列分配给 num 的部分,但同样这些数字有时用引号括起来,有时不...为什么?

如有任何建议、提示和指点,我们将不胜感激。

C:对@bli

的以下建议进行澄清

我已经按照您在评论中的建议编辑了我的配置文件,并省略了文件夹名称,只留下 SRA 编号。这对我来说很有意义,但我还有一些其他问题阻止我获得这个 Snakefile 运行ning。

新配置文件:

samples:
    Corces2016_4983.7A_Mono: SRR2920475
    Corces2016_4983.7B_Mono: SRR2920476
cell_types:
    Mono:
    - Corces2016_4983.7A
index: /home/c1477909/genomes_and_index_files/hg19

新蛇文件:

# read config info into this namespace
configfile: "config.yaml"
print (config['samples'])

rule all:
    input:
        expand("FastQC/PRETRIM/{sample}_{num}_fastqc.zip", sample=config["samples"], num=['1', '2']),
        expand("bam_files/{sample}.bam", sample=config["samples"]),
        "FastQC/PRETRIM/fastq_multiqc.html",
        "FastQC/POSTTRIM/fastq_multiqc.html",

rule fastqc_pretrim:
    input:
      lambda wildcards: f"fastq_files/{config['samples'][wildcards.sample]}_{wildcards.num}.fastq.gz"
    output:
        # Output needs to end in '_fastqc.html' for multiqc to work
        html="FastQC/PRETRIM/{sample}_{num}_fastqc.html",
        zip="FastQC/PRETRIM/{sample}_{num}_fastqc.zip"
    wrapper:
        "0.23.1/bio/fastqc"

rule multiqc_fastq_pretrim:
    input:
        expand("FastQC/PRETRIM/{sample}_{num}_fastqc.html", sample=config["samples"], num=['1', '2'])
    output:
        "FastQC/PRETRIM/fastq_multiqc.html"
    wrapper:
        "0.23.1/bio/multiqc"

rule trim_galore_pe:
    input:
        lambda wildcards: expand(f"fastq_files/{config['samples'][wildcards.sample]}_{{num}}.fastq.gz", num=[1,2])
    output:
        "trimmed_fastq_files/{wildcards.sample}_1_val_1.fq.gz",
        "trimmed_fastq_files/{wildcards.sample}_1.fastq.gz_trimming_report.txt",
        "trimmed_fastq_files/{wildcards.sample}_2_val_2.fq.gz",
        "trimmed_fastq_files/{wildcards.sample}_2.fastq.gz_trimming_report.txt"
    params:
        extra="--illumina -q 20"
    log:
        "logs/trim_galore/{sample}.log"
    wrapper:
        "0.23.1/bio/trim_galore/pe"

rule fastqc_posttrim:
    input:
        lambda wildcards: expand(f"trimmed_fastq_files/{config['samples'][wildcards.sample]}_{{num}}_val_{{num}}.fq.gz", num=[1,2])
    output:
        # Output needs to end in '_fastqc.html' for multiqc to work
        html="FastQC/POSTTRIM/{sample}_{num}_fastqc.html",
        zip="FastQC/POSTTRIM/{sample}_{num}_fastqc.zip"
    wrapper:
        "0.23.1/bio/fastqc"

rule multiqc_fastq_posttrim:
    input:
        expand("FastQC/POSTTRIM/{sample}_{num}.trim_fastqc.html", sample=config["samples"], num=['1', '2'])
    output:
        "FastQC/POSTTRIM/fastq_multiqc.html"
    wrapper:
        "0.23.1/bio/multiqc"

rule bowtie2:
    input:
        lambda wildcards: expand(f"trimmed_fastq_files/{config['samples'][wildcards.sample]}_{{num}}_val_{{num}}.fq.gz", num=[1,2])
    output:
        "bam_files/{sample}.bam"
    log:
        "logs/bowtie2/{sample}.txt"
    params:
        index=config["index"],  # prefix of reference genome index (built with bowtie2-build),
        extra=""
    threads: 8
    wrapper:
        "0.23.1/bio/bowtie2/align"

使用这些新文件最初一切正常,snakemake -np 创建了部分工作列表。但是,这是因为完整的工作列表已经有一半了运行;那就是生成了 trimmed_fastq_files 文件夹,并且在其中放置了正确命名的 trimmed fastq 文件。当我删除所有以前创建的文件以查看整个新版本的 Snakefile 是否可以正常工作时,snakemake -np 失败,指出 trim_galore_pe 规则下游的规则缺少输入文件。

如您所见,我试图在输出部分调用 trim_galore_pe 规则的输入部分中设置的 {wildcard.sample} 变量,但 snakemake 不喜欢这样。可以这样做吗?

我也使用以下答案中的提示进行了尝试,但这也不起作用:

rule trim_galore_pe:
    input:
        sample=lambda wildcards: expand(f"fastq_files/{config['samples'][wildcards.sample]}_{{num}}.fastq.gz", num=[1,2])
    output:
        expand(f"trimmed_fastq_files/{config['samples'][wildcards.sample]}_{{num}}_val_{{num}}.fq.gz", num=[1,2]),
        expand(f"trimmed_fastq_files/{config['samples'][wildcards.sample]}_{{num}}.fastq.gz_trimming_report.txt", num=[1,2])
    params:
        extra="--illumina -q 20"
    log:
        "logs/trim_galore/{sample}.log"
    wrapper:
        "0.23.1/bio/trim_galore/pe"

然后错误指出 wildcards not defined。因此,从逻辑上讲,我尝试将 lambda wildcards: 放在输出部分的两个扩展语句前面以尝试定义通配符,但这引发了语法错误 Only input files can be specified as functions。我也尝试使用下面的一些索引建议,但无法获得正确的组合。

这可能是由于我不确定关于 Snakefile 的另一件事造成的,这就是范围界定的工作原理。

任何(进一步的)建议将不胜感激。

对于你问题的 A 部分,我建议使用制表符分隔的文件来存储样本信息、ID 等,无论你有多少样本。然后,您可以将此文件的路径存储在您的配置文件中,并通过使用带有 pandas 库的列标识符来访问它。有关详细信息,请参阅

关于 B 部分:

  1. 看起来这是一种在 python 中格式化字符串的新方法,例如请参见 this link

  2. config['samples'] 用于访问配置文件的密钥 "samples",而 [wildcards.sample] 用于访问通配符 {sample}工作流程(在 rule all 中)。

  3. 双括号一般用于转义单括号。在这里它避免了扩展 {{num}} (我无法将手放在 snakemake 文档中的示例上)。

  4. num=['1', '2'] 正在将值列表分配给通配符 {num},因此稍后可以使用 {wildcards.num} 访问它。如果所有规则的输入和输出都链接在一起,则您不必多次定义这些值。

希望这能澄清您的一些疑虑,祝您好运!

我会尽量回答你的问题 B,并提供额外的细节,希望对你和其他人有用。

编辑:我在最后添加了一些尝试回答问题 C。

关于报价

首先,关于你所说的"inverted"逗号,通常叫"single quotes",在python中用来构成字符串。双引号也可以用于相同的目的。主要区别在于当您尝试创建包含引号的字符串时。使用双引号可以创建包含单引号的字符串,反之亦然。否则,您需要 "escape" 引号使用反斜杠 ("\"):

s1 = 'Contains "double quotes"'
s1_bis = "Contains \"double quotes\""
s2 = "Contains 'single quotes'"
s2_bis = 'Contains \'single quotes\''

(我倾向于使用双引号,这只是个人喜好。)

分解示例

rule trim_galore_pe:
    input:
        sample=lambda wildcards: expand(f"{config['samples'][wildcards.sample]}_{{num}}.fastq.gz", num=[1,2])

您正在将一个函数 (lambda wildcards: ...) 分配给一个变量 (sample),该变量恰好属于规则的输入部分。

这将导致 snakemake 在根据通配符的当前值(根据它要生成的输出的当前值推断)来确定规则的特定实例的输入时使用此函数).

为了清楚起见,很可能通过将函数定义与规则声明分开来重写它,而不使用 lambda 结构,并且它的工作方式相同:

def determine_sample(wildcards):
    return expand(
        f"{config['samples'][wildcards.sample]}_{{num}}.fastq.gz",
        num=[1,2])

rule trim_galore_pe:
    input:
        sample = determine_sample

expand 是一个特定于 snakemake 的函数(但你可以在任何 python 程序或带有 from snakemake.io import expand 的交互式解释器中导入它),这使得生成字符串列表变得更容易.在下面的交互式 python3.6 会话中,我们将尝试使用不同的本机 python 构造来重现您使用它时发生的情况。

正在访问配置

# We'll try to see how `expand` works, we can import it from snakemake
from snakemake.io import expand
    ​
# We want to see how it works using the following example
# expand(f"{config['samples'][wildcards.sample]}_{{num}}.fastq.gz", num=[1,2])

# To make the example work, we will first simulate the reading
# of a configuration file
import yaml

config_text = """
samples:
    Corces2016_4983.7A_Mono: fastq_files/SRR2920475
    Corces2016_4983.7B_Mono: fastq_files/SRR2920476
cell_types:
    Mono:
    - Corces2016_4983.7A
index: /home/genomes_and_index_files/hg19
"""
# Here we used triple quotes, to have a readable multi-line string.
​
# The following is equivalent to what snakemake does with the configuration file:
config = yaml.load(config_text)
config

输出:

{'cell_types': {'Mono': ['Corces2016_4983.7A']},
 'index': '/home/genomes_and_index_files/hg19',
 'samples': {'Corces2016_4983.7A_Mono': 'fastq_files/SRR2920475',
  'Corces2016_4983.7B_Mono': 'fastq_files/SRR2920476'}}

我们获得了一个字典,其中键 "samples" 与嵌套字典相关联。

# We can access the nested dictionary as follows
config["samples"]
# Note that single quotes could be used instead of double quotes
# Python interactive interpreter uses single quotes when it displays strings

输出:

{'Corces2016_4983.7A_Mono': 'fastq_files/SRR2920475',
 'Corces2016_4983.7B_Mono': 'fastq_files/SRR2920476'}
# We can access the value corresponding to one of the keys
# again using square brackets
config["samples"]["Corces2016_4983.7A_Mono"]

输出:

'fastq_files/SRR2920475'
# Now, we will simulate a `wildcards` object that has a `sample` attribute
# We'll use a namedtuple for that
# https://docs.python.org/3/library/collections.html#collections.namedtuple
from collections import namedtuple
Wildcards = namedtuple("Wildcards", ["sample"])
wildcards = Wildcards(sample="Corces2016_4983.7A_Mono")
wildcards.sample

输出:

'Corces2016_4983.7A_Mono'

编辑 (15/11/2018):我发现了一种更好的创建通配符的方法:

from snakemake.io import Wildcards
wildcards = Wildcards(fromdict={"sample": "Corces2016_4983.7A_Mono"})

# We can use this attribute as a key in the nested dictionary
# instead of using directly the string
config["samples"][wildcards.sample]
# No quotes here: `wildcards.sample` is a string variable

输出:

'fastq_files/SRR2920475'

解构 expand

# Now, the expand of the example works, and it results in a list with two strings
expand(f"{config['samples'][wildcards.sample]}_{{num}}.fastq.gz", num=[1,2])    
# Note: here, single quotes are used for the string "sample",
# in order not to close the opening double quote of the whole string

输出:

['fastq_files/SRR2920475_1.fastq.gz', 'fastq_files/SRR2920475_2.fastq.gz']
# Internally, I think what happens is something similar to the following:
filename_template = f"{config['samples'][wildcards.sample]}_{{num}}.fastq.gz"

# This template is then used for each element of this "list comprehension"    
[filename_template.format(num=num) for num in [1, 2]]

输出:

['fastq_files/SRR2920475_1.fastq.gz', 'fastq_files/SRR2920475_2.fastq.gz']
# This is equivalent to building the list using a for loop:
filenames = []
for num in [1, 2]:
    filename = filename_template.format(num=num)
    filenames.append(filename)
filenames

输出:

['fastq_files/SRR2920475_1.fastq.gz', 'fastq_files/SRR2920475_2.fastq.gz']

字符串模板和格式

# It is interesting to have a look at `filename_template`    
filename_template

输出:

'fastq_files/SRR2920475_{num}.fastq.gz'
# The part between curly braces can be substituted
# during a string formatting operation:
"fastq_files/SRR2920475_{num}.fastq.gz".format(num=1)

输出:

'fastq_files/SRR2920475_1.fastq.gz'

现在让我们进一步展示如何使用字符串格式。

# In python 3.6 and above, one can create formatted strings    
# in which the values of variables are interpreted inside the string    
# if the string is prefixed with `f`.
# That's what happens when we create `filename_template`:
filename_template = f"{config['samples'][wildcards.sample]}_{{num}}.fastq.gz"    
filename_template    

输出:

'fastq_files/SRR2920475_{num}.fastq.gz'

在格式化字符串的过程中发生了两次替换:

  1. config['samples'][wildcards.sample] 的值用于制作字符串的第一部分。 (在 sample 周围使用了单引号,因为这个 python 表达式在用双引号构建的字符串中。)

  2. 作为格式化操作的一部分,num 周围的双括号被简化为单括号。这就是为什么我们可以在涉及 num.

  3. 的进一步格式化操作中再次使用它
# Equivalently, without using 3.6 syntax:    
filename_template = "{filename_prefix}_{{num}}.fastq.gz".format(
    filename_prefix = config["samples"][wildcards.sample])
filename_template

输出:

'fastq_files/SRR2920475_{num}.fastq.gz'
# We could achieve the same by first extracting the value
# from the `config` dictionary    
filename_prefix = config["samples"][wildcards.sample]
filename_template = f"{filename_prefix}_{{num}}.fastq.gz"
filename_template

输出:

'fastq_files/SRR2920475_{num}.fastq.gz'
# Or, equivalently:
filename_prefix = config["samples"][wildcards.sample]
filename_template = "{filename_prefix}_{{num}}.fastq.gz".format(
    filename_prefix=filename_prefix)
filename_template

输出:

'fastq_files/SRR2920475_{num}.fastq.gz'
# We can actually perform string formatting on several variables
# at the same time:
filename_prefix = config["samples"][wildcards.sample]
num = 1
"{filename_prefix}_{num}.fastq.gz".format(
    filename_prefix=filename_prefix, num=num)

输出:

'fastq_files/SRR2920475_1.fastq.gz'
# Or, using 3.6 formatted strings
filename_prefix = config["samples"][wildcards.sample]
num = 1
f"{filename_prefix}_{num}.fastq.gz"

输出:

'fastq_files/SRR2920475_1.fastq.gz'
# We could therefore build the result of the expand in a single step:
[f"{config['samples'][wildcards.sample]}_{num}.fastq.gz" for num in [1, 2]]

输出:

['fastq_files/SRR2920475_1.fastq.gz', 'fastq_files/SRR2920475_2.fastq.gz']

关于问题 C 的评论

以下内容有点复杂,就 Python 将如何构建字符串而言:

input:
    lambda wildcards: expand(f"fastq_files/{config['samples'][wildcards.sample]}_{{num}}.fastq.gz", num=[1,2])

但它应该有效,正如我们在以下模拟中看到的那样:

from collections import namedtuple
from snakemake.io import expand

Wildcards = namedtuple("Wildcards", ["sample"])
wildcards = Wildcards(sample="Corces2016_4983.7A_Mono")
config = {"samples": {
    "Corces2016_4983.7A_Mono": "SRR2920475",
    "Corces2016_4983.7B_Mono": "SRR2920476"}}
expand(
    f"fastq_files/{config['samples'][wildcards.sample]}_{{num}}.fastq.gz",
    num=[1,2])

输出:

['fastq_files/SRR2920475_1.fastq.gz', 'fastq_files/SRR2920475_2.fastq.gz']

trim_galore_pe 规则中的问题实际上在其 output 部分:您不应该在那里使用 {wildcards.sample},而应该使用 {sample}

规则的 output 部分是您通知 snakemake 给定规则实例的通配符属性的地方,方法是将它想要获取的文件与给定的模式进行匹配。大括号匹配的部分将用于设置相应属性名称的值。

例如,如果 snakemake 想要一个名为 "trimmed_fastq_files/Corces2016_4983.7A_Mono_1_val_1.fq.gz" 的文件,它将尝试将此文件与所有规则输出部分中存在的所有模式进行匹配,并最终找到这个文件:"trimmed_fastq_files/{sample}_1_val_1.fq.gz"

幸运的是,通过在 Corces2016_4983.7A_Mono{sample} 部分之间建立对应关系,它将能够将文件名与模式匹配。然后它会在本地通配符实例中放置一个 sample 属性,有点像我手动执行以下操作:

Wildcards = namedtuple("Wildcards", ["sample"])
wildcards = Wildcards(sample="Corces2016_4983.7A_Mono")

如果你使用 {wildcards.sample} 而不是 {wildcards},我不知道在 snakemake 中究竟会发生什么,但让我们试试我的模拟框架:

Wildcards = namedtuple("Wildcards", ["sample"])
wildcards = Wildcards(wildcards.sample="Corces2016_4983.7A_Mono")
  File "<ipython-input-12-c02ce12bff85>", line 1
    wildcards = Wildcards(wildcards.sample="Corces2016_4983.7A_Mono")
                         ^
SyntaxError: keyword can't be an expression

你接下来的尝试怎么样?

output:
    expand(f"trimmed_fastq_files/{config['samples'][wildcards.sample]}_{{num}}_val_{{num}}.fq.gz", num=[1,2]),

在这里,我的理解是 Python 首先尝试在 f"trimmed_fastq_files/{config['samples'][wildcards.sample]}_{{num}}_val_{{num}}.fq.gz" 上应用 f 字符串格式。 为此,它需要能够计算 config['samples'][wildcards.sample],但 wildcards 对象尚不存在。因此 wildcards not definedwildcards 仅在将 "downstream" 规则所需的文件名与包含 {attribute_name} 模式的字符串匹配后生成。但这是 snakemake 当前正在尝试构建的字符串。

这里有一些要点要记住:

  • wildcards 实际上只存在于本地,在一个规则的实例中,在将其输出与另一个 "downstream" 规则实例所需的文件匹配之后。
  • 您没有在输入部分定义变量。您使用变量来构建规则实例将需要的文件的具体名称(或者更准确地说,您说您希望在规则实例之前存在 运行:规则不需要实际使用那些文件)。这些变量是在规则范围之外定义的,直接在 snakefile 的底层,在纯 Python 模式下,以及本地 wildcards 对象。默认情况下,{attribute_name} 占位符将被本地 wildcards 对象的属性替换("{sample}" 变为 "Corces2016_4983.7A_Mono"),但是如果你想做更复杂的东西来构建文件名,您需要通过一个必须显式处理此 wildcards 对象(lambda wildcards: f"{wildcards.sample}" 变为 "Corces2016_4983.7A_Mono")的函数来执行此操作。