Я пишу правило змейки, которое будет выполнять обрезку 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 не допускает необязательных выходных данных, я мог бы просто разделить правила на два, но это не совсем то, что мне хотелось бы.
Посмотрите, как работает функция 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 []
Можете ли вы объяснить в коде, что вы на самом деле подразумеваете под этим? Язык не ясен.
Вы не можете использовать функции в выводе змейки.
@ Анна-Ли: я могу ;). В любом случае, похоже, ваш вопрос становится двусмысленным. Вы можете указать переменное количество файлов в выходном разделе на основе критериев, которые существуют до запуска конвейера (например, на основе настройки в конфигурации), но как только файл добавлен в выходной раздел, вы должны создать его в ваше правило. Это логично, поскольку другие правила могут ожидать этот файл и будут очень удивлены, если не найдут его после того, как предварительное правило "успешно" завершится.
@Anna-Leigh, чтобы добавить к моему предыдущему комментарию: иногда вы не знаете количество файлов заранее (т. Е. Это зависит от количества кластеров, создаваемых правилом). В этом случае вы можете использовать динамический вывод (устаревший) или контрольные точки. Это потребует от Snakemake перестроить DAG на основе новой информации, которая появляется после завершения вашего правила.
@Anna-Leigh, и еще один вариант, который у вас есть, - это создать необязательный файл без вывода сообщений, даже не показывая его в разделе вывода. Это означало бы, что вы можете либо создать файл, либо пропустить его, но никакое другое правило не будет рассчитывать на то, что вы создадите этот файл. Никакой зависимости, просто некоторые файлы будут созданы вместе с другими запрашиваемыми обязательными файлами. Пожалуйста, уточните свой вопрос, чтобы получить более конкретный ответ.
На Snakemake версии 5.4.4. использование функций на выходе приводит к синтаксическим ошибкам, однако это решается следующим образом: out_fastqc2 = config["fastp_trimmed_output_folder"] + "{unit}/{fastq_name}_2_trimmed.fastq.gz" if config["end_type"] == "pe" else []
Поскольку выбор между парным и односторонним подключением кажется фиксированным в конфигурации, вы можете попытаться определить правило двумя способами в зависимости от конфигурации:
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}
"""
Это также решает проблему, но я надеялся получить дополнительный вывод без необходимости иметь два правила или, в данном случае, две версии одного и того же правила.
Возможно, можно построить вывод вне правила, основываясь на
config["end_type"]
.