Snakemake: путаница в том, как правильно получить доступ к файлам конфигурации

Этот вопрос следует из вопроса, который я задавал ранее, и касается понимания как правильно получить доступ к файлам конфигурации с помощью Snakemake. У меня есть конкретная проблема, которую я спрошу в первую очередь, и общая проблема с пониманием того, как работает индексация, которую я спрошу во вторую.

Я использую snakemake для запуска и конвейер ATAC-seq от выравнивания / контроля качества до анализа мотивов.

A: конкретный вопрос

Я пытаюсь добавить правило под названием trim_galore_pe для обрезки адаптеров из моих файлов fastq перед выравниванием, и из snakemake выдается сообщение об ошибке, поскольку имена выходных файлов, сгенерированных trim galore, не соответствуют тому, что ожидает snakemake. Это потому, что я не могу понять, как правильно записать оператор выходного файла в моем файле snakemake, чтобы имена совпадали.

Пример имен, сгенерированных TRIM GALORE, содержит номера SRA, например:

trimmed_fastq_files/SRR2920475_1_val_1.fq.gz

В то время как файл, ожидаемый snakemake, содержит образцы ссылок и должен читать:

trimmed_fastq_files/Corces2016_4983.7B_Mono_1_val_1.fq.gz

Это также влияет на последующие правила после правила trim_galore_pe. Мне нужно разработать способ использования информации в моем файле конфигурации для создания требуемых выходных файлов.

Для всех правил после тех, что показаны в Snakefile, мне нужно, чтобы файлы назывались именем образца, то есть Corces2016_4983.7A_Mono. Также было бы полезно, чтобы все правила FAST_QC и MULTIQC, показанные в Snakefile ниже, имели имена образцов в структуре имени выходного файла, что все они уже имеют в текущем Snakefile.

Однако входные данные для Bowtie2, правил FASTQC и входных и выходных данных trim_galore_pe правил должны содержать номера SRA. Проблема начинается на выходе trim_galore и влияет на все последующие правила.

Хотя я извлек номера SRA в предыдущих правилах, я не уверен, как это сделать, если не используется папка fastq_files, которая явно указана в файле конфигурации. Введя правило trim_galore_pe, я фактически переместил новый набор файлов SRA в новую папку trimmed_fastq_files. Как извлечь только номер SRA из списка конфигурационного файла файлов SRA, содержащего старые имена папок, в то время как ссылка на новую папку trimmed_fastq_files в Snakefile является сутью моей проблемы.

Надеюсь, это понятно.

Вот мой файл конфигурации:

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"

Это в настоящее время выполняется и дает полный список заданий с использованием 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 файла конфигурации. Расширение позволяет нам перебирать каждый элемент в файле конфигурации, который соответствует параметрам в команде, то есть всем файлам SRA, и лямбда-символы необходимы для использования вызова wildcards в команде. Я не уверен в следующем:

  1. Что делает f сразу после раскрытия и зачем это нужно?
  2. Почему config['samples'] содержит кавычки в квадратных скобках, а кавычки вокруг [wildcards.sample] не нужны?
  3. Почему используются одинарные и двойные фигурные скобки?
  4. Глядя на Snakefile выше, некоторые из правил содержат части, назначающие последовательность чисел для num, но опять же, эти числа иногда заключаются в кавычки, а иногда нет ... почему?

Будем признательны за любые советы, подсказки, указатели.

C: Пояснения к предложениям, сделанным ниже @bli

Я отредактировал свой файл конфигурации, как вы предложили в своем комментарии, и опустил имена папок, оставив только номера SRA. Для меня это имеет смысл, но у меня есть пара других проблем, которые мешают мне запустить этот Snakefile.

Новый файл конфигурации:

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

Новый файл 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:
      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 была сгенерирована, и в ней находились правильно названные обрезанные файлы fastq. Когда я удалил все ранее созданные файлы, чтобы убедиться, что вся новая версия Snakefile будет работать должным образом, snakemake -np не удалось, заявив, что отсутствуют входные файлы для правил, находящихся ниже по потоку правила trim_galore_pe.

Как видите, я пытаюсь вызвать переменную {wildcard.sample}, установленную в разделе ввода правила trim_galore_pe в разделе вывода, но 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. Я также попытался использовать некоторые из приведенных ниже предложений по индексации, но не смог найти правильную комбинацию.

Вероятно, это вызвано еще одной вещью, в которой я не уверен в отношении Snakefiles, а именно тем, как работает область видимости.

  • Если я определю переменную в rule all, могут ли все другие правила получить к ней доступ?
  • Если я определяю переменную во входном разделе правила, будет ли она доступна для всех других разделов этого правила (то есть для вывода, команды оболочки и т. Д.), Но только для этого правила?
  • Если да, то почему я не могу получить доступ к переменной {wildcard.sample}, если я определил ее в разделе ввода? Это потому, что эта переменная заключена в лямбда-функцию с закрытой областью видимости?

Будем очень признательны за любые (дальнейшие) предложения.


person Darren    schedule 06.05.2018    source источник
comment
Как извлечь только номер SRA из списка конфигурационного файла файлов SRA, содержащего старые имена папок, при этом ссылка на новую папку trimmed_fastq_files в Snakefile является сутью моей проблемы. Может быть, вы могли бы использовать номер SRA в конфигурации и построить список файлов внутри кода snakemake, зная, в каком каталоге вы должны искать в зависимости от правила?   -  person bli    schedule 07.05.2018
comment
Спасибо, Бли, я попытался это сделать, но наткнулся на загвоздку, см. Раздел C, о котором идет речь.   -  person Darren    schedule 08.05.2018
comment
В разделе output вы не используете {wildcards.sample}, вы используете напрямую {sample}. Snakemake уже предполагает, что вы говорите об атрибутах подстановочных знаков. Фактически, атрибуты подстановочных знаков, которые существуют в области действия правила, определяются анализом раздела output. В случае, если это может быть полезно, я попытался написать некоторые пояснения моего текущего понимания этого предмета: bitbucket.org/blaiseli/snakemake/src/   -  person bli    schedule 31.08.2018
comment
Я добавил больше пояснений в конце своего ответа. Надеюсь это поможет. По крайней мере, это помогло мне улучшить мое понимание создания змеи.   -  person bli    schedule 31.08.2018
comment
Большое спасибо Bli - эти ответы очень помогли мне понять Snakemake.   -  person Darren    schedule 31.10.2018


Ответы (2)


Я постараюсь ответить на ваш вопрос Б и дать дополнительные сведения, которые, я надеюсь, могут быть полезны для вас и других.

Изменить: в конце я добавил несколько попыток ответить на вопрос C.

Что касается цитат

Во-первых, что касается того, что вы называете «кавычками», их обычно называют «одинарными кавычками», и они используются в Python для построения строк. С той же целью можно использовать двойные кавычки. Основное отличие заключается в том, что вы пытаетесь создать строки, содержащие кавычки. Использование двойных кавычек позволяет создавать строки, содержащие одинарные кавычки, и наоборот. В противном случае вам нужно "экранировать" цитату, используя обратную косую черту ("\"):

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'}}

Мы получили словарь, в котором ключ «образцы» связан с вложенным словарем.

# 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.

# 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")

Я не знаю, что именно происходит в snakemake, если вы используете {wildcards.sample} вместо {wildcards}, но давайте попробуем с моей структурой моделирования:

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 к f"trimmed_fastq_files/{config['samples'][wildcards.sample]}_{{num}}_val_{{num}}.fq.gz". Для этого он должен иметь возможность оценивать config['samples'][wildcards.sample], но объект wildcards еще не существует. Следовательно, wildcards not defined. wildcards будет сгенерирован только после сопоставления имени файла, необходимого для правила «нисходящего потока», со строкой, содержащей {attribute_name} шаблоны. Но это строка, которую snakemake сейчас пытается построить.

Вот некоторые важные моменты, о которых следует помнить:

  • wildcards фактически существует только локально, в экземпляре правила, после сопоставления его выходных данных с файлом, требуемым другим экземпляром правила «ниже по течению».
  • Вы не определяете переменные во входных секциях. Вы используете переменные для создания конкретных имен файлов, которые потребуются экземпляру правила (или, точнее, вы говорите, что хотите существовать до того, как экземпляр правила может быть запущен: правило не должно фактически использовать эти файлы). Это те переменные, которые определены вне области действия правил, непосредственно на базовом уровне файла snakefile в чистом режиме Python и локальном объекте wildcards. По умолчанию заполнители {attribute_name} будут заменены атрибутами локального объекта wildcards ("{sample}" становится "Corces2016_4983.7A_Mono"), но если вы хотите сделать более сложные вещи для создания имен файлов, вам нужно сделать это с помощью функции, которая должна будет явно обрабатывать этот wildcards объект (lambda wildcards: f"{wildcards.sample}" становится "Corces2016_4983.7A_Mono").
person bli    schedule 07.05.2018

Что касается части A вашего вопроса, я бы предложил использовать файлы с разделителями-табуляторами для хранения информации об образцах, идентификаторов и т. Д., Независимо от количества образцов, которые у вас есть. Затем вы можете сохранить путь к этому файлу в своем файле конфигурации и получить к нему доступ, используя идентификаторы столбцов с библиотекой pandas. См. эту ветку для более подробной информации.

Что касается части B:

  1. Похоже, это новый способ форматирования строки в python, см. эту ссылку для ex .

  2. config['samples'] предназначен для доступа к ключевым «примерам» конфигурационного файла, а [wildcards.sample] предназначен для доступа к подстановочному знаку {sample}, как определено в вашем рабочем процессе (в rule all).

  3. Двойные скобки обычно используются для выхода из простых скобок. Здесь он избегает расширения {{num}} (не могу взять в руки пример из документации snakemake).

  4. num=['1', '2'] назначает список значений подстановочному знаку {num}, поэтому позже к нему можно будет получить доступ с помощью {wildcards.num}. Если все входы и выходы правил связаны, вам не нужно определять эти значения более одного раза.

Надеюсь, это проясняет некоторые из ваших опасений, удачи!

person rioualen    schedule 06.05.2018