Возможно ли иметь дополнительный выходной файл в Snakemake?

Я пишу правило змейки, которое будет выполнять обрезку fastq для данных секвенирования с одним или парным концом. Если данные парные, должно быть два выходных файла, если одиночные, то должен быть один.

Правило, которое я написал, работает до сих пор, однако у меня нет его, чтобы вторая пара обрезанных была выходным файлом. Это означает, что змейка не проверяет, существует ли этот файл. Выводить будет, но не проверяет, можно ли сделать опциональный вывод?

    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 не допускает необязательных выходных данных, я мог бы просто разделить правила на два, но это не совсем то, что мне хотелось бы.

Возможно, можно построить вывод вне правила, основываясь на config["end_type"].

bli 31.05.2019 19:44
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
1
2 201
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Посмотрите, как работает функция 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 []

Можете ли вы объяснить в коде, что вы на самом деле подразумеваете под этим? Язык не ясен.

Al Bro 03.06.2019 11:30

Вы не можете использовать функции в выводе змейки.

Al Bro 04.06.2019 12:02

@ Анна-Ли: я могу ;). В любом случае, похоже, ваш вопрос становится двусмысленным. Вы можете указать переменное количество файлов в выходном разделе на основе критериев, которые существуют до запуска конвейера (например, на основе настройки в конфигурации), но как только файл добавлен в выходной раздел, вы должны создать его в ваше правило. Это логично, поскольку другие правила могут ожидать этот файл и будут очень удивлены, если не найдут его после того, как предварительное правило "успешно" завершится.

Dmitry Kuzminov 04.06.2019 18:03

@Anna-Leigh, чтобы добавить к моему предыдущему комментарию: иногда вы не знаете количество файлов заранее (т. Е. Это зависит от количества кластеров, создаваемых правилом). В этом случае вы можете использовать динамический вывод (устаревший) или контрольные точки. Это потребует от Snakemake перестроить DAG на основе новой информации, которая появляется после завершения вашего правила.

Dmitry Kuzminov 04.06.2019 18:11

@Anna-Leigh, и еще один вариант, который у вас есть, - это создать необязательный файл без вывода сообщений, даже не показывая его в разделе вывода. Это означало бы, что вы можете либо создать файл, либо пропустить его, но никакое другое правило не будет рассчитывать на то, что вы создадите этот файл. Никакой зависимости, просто некоторые файлы будут созданы вместе с другими запрашиваемыми обязательными файлами. Пожалуйста, уточните свой вопрос, чтобы получить более конкретный ответ.

Dmitry Kuzminov 04.06.2019 18:17

На Snakemake версии 5.4.4. использование функций на выходе приводит к синтаксическим ошибкам, однако это решается следующим образом: out_fastqc2 = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_2_trimmed.fastq.gz" if config["end_type"] == "pe" else []

Al Bro 05.06.2019 15:03

Поскольку выбор между парным и односторонним подключением кажется фиксированным в конфигурации, вы можете попытаться определить правило двумя способами в зависимости от конфигурации:

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

Это также решает проблему, но я надеялся получить дополнительный вывод без необходимости иметь два правила или, в данном случае, две версии одного и того же правила.

Al Bro 05.06.2019 15:08

Другие вопросы по теме