Один из вариантов - использовать checkpoint
при разбиении fastq, чтобы вы могли динамически пересмотреть DAG на более позднем этапе, чтобы получить результирующие дорожки.
Вот пошаговое руководство MWE:
- Настройте и создайте пример файла fastq.
# Requires Python 3.6+ for f-strings, Snakemake 5.4+ for checkpoints
import pathlib
import random
random.seed(1)
rule make_fastq:
output:
fastq = touch("input/{sample}.fastq")
- Создайте случайное число дорожек от 1 до 9 со случайным идентификатором от 1 до 9. Обратите внимание, что мы объявляем это как
checkpoint
, а не как правило, чтобы впоследствии мы могли получить доступ к результату. Кроме того, мы объявляем выходные данные здесь как каталог, указывающий c для образца, чтобы мы могли позже использовать его, чтобы получить созданные дорожки.
checkpoint split_fastq:
input:
fastq = rules.make_fastq.output.fastq
output:
lane_dir = directory("temp/split_fastq/{sample}")
run:
pathlib.Path(output.lane_dir).mkdir(exist_ok=True)
n_lanes = random.randrange(1, 10)-
lane_numbers = random.sample(range(1, 10), k = n_lanes)
for lane_number in lane_numbers:
path = pathlib.Path(output.lane_dir) / f"L00{lane_number}.fastq"
path.touch()
- Выполнить некоторую промежуточную обработку.
rule map_fastq:
input:
fastq = "temp/split_fastq/{sample}/L00{lane_number}.fastq"
output:
bam = "temp/map_fastq/{sample}/L00{lane_number}.bam"
run:
bam = pathlib.Path(output.bam)
bam.parent.mkdir(exist_ok=True)
bam.touch()
- Чтобы объединить все обработанные файлы, мы используем функцию ввода для доступа к дорожки, которые были созданы в
split_fastq
, так что мы можем сделать динамические c expand
на них. Мы делаем expand
на последнем правиле в цепочке промежуточных этапов обработки, в данном случае map_fastq
, поэтому мы запрашиваем правильные входные данные.
def get_bams(wildcards):
lane_dir = checkpoints.split_fastq.get(**wildcards).output[0]
lane_numbers = glob_wildcards(f"{lane_dir}/L00{{lane_number}}.fastq").lane_number
bams = expand(rules.map_fastq.output.bam, **wildcards, lane_number=lane_numbers)
return bams
- Это теперь функция ввода дает нам легкий доступ к файлам bam, которые мы будем sh объединять, сколько бы их ни было, и как бы их ни называли.
rule merge_bam:
input:
get_bams
output:
bam = "temp/merge_bam/{sample}.bam"
shell:
"cat {input} > {output.bam}"
Этот пример выполняется и с random.seed(1)
создает три полосы (l001
, l002
и l005
).
Если вы не хотите использовать checkpoint
, я думаю, вы могли бы добиться чего-то подобного, создав Функция ввода для merge_bam
, которая открывает исходный ввод fastq, сканирует прочитанные имена для информации о дорожке и прогнозирует, какими должны быть входные файлы. Однако это кажется менее надежным.