#nextflow
#nextflow
Вопрос:
У меня есть массив структурных данных, похожих на:
- name: foobar
sex: male
fastqs:
- r1: /path/to/foobar_R1.fastq.gz
r2: /path/to/foobar_R2.fastq.gz
- r1: /path/to/more/foobar_R1.fastq.gz
r2: /path/to/more/foobar_R2.fastq.gz
- name: bazquux
sex: female
fastqs:
- r1: /path/to/bazquux_R1.fastq.gz
r2: /path/to/bazquux_R2.fastq.gz
Обратите внимание, что fastq приходят парами, и количество пар на «образец» может быть переменным.
Я хочу написать process
в nextflow, который обрабатывает один образец за раз.
Для того, чтобы исполнитель nextflow правильно маршалировал файлы, они должны каким-то образом быть напечатаны как path
(или file
). Набрав таким образом, исполнитель скопирует файлы на вычислительный узел для обработки. Просто введя пути к файлам var
как, пути будут обрабатываться как строки, и никакие файлы не будут скопированы.
Тривиальный пример path
ввода из документов:
process foo {
input:
path x from '/some/data/file.txt'
"""
your_command --in $x
"""
}
Как мне объявить process
входные данные, чтобы файлы были правильно маршалированы для вычислительного узла? До сих пор я не нашел в документах никаких примеров того, как обрабатывать структурированные входные данные.
Ответ №1:
Ваши структурированные данные очень похожи на YAML. Если вы можете включить объект верхнего уровня, чтобы ваш файл выглядел примерно так:
samples:
- name: foobar
sex: male
fastqs:
- r1: ./path/to/foobar_R1.fastq.gz
r2: ./path/to/foobar_R2.fastq.gz
- r1: ./path/to/more/foobar_R1.fastq.gz
r2: ./path/to/more/foobar_R2.fastq.gz
- name: bazquux
sex: female
fastqs:
- r1: ./path/to/bazquux_R1.fastq.gz
r2: ./path/to/bazquux_R2.fastq.gz
Затем мы можем использовать -params-file
опцию Nextflow для загрузки параметров при запуске нашего рабочего процесса. Мы можем получить доступ к объекту верхнего уровня из параметров, что дает нам список, который мы можем использовать для создания канала с использованием fromList
фабричного метода. В следующем примере используется новый DSL 2:
process test_proc {
tag { sample_name }
debug true
stageInMode 'rellink'
input:
tuple val(sample_name), val(sex), path(fastqs)
"""
echo "${sample_name},${sex}:"
ls -g *.fastq.gz
"""
}
workflow {
Channel.fromList( params.samples )
| flatMap { rec ->
rec.fastqs.collect { rg ->
readgroup = tuple( file(rg.r1), file(rg.r2) )
tuple( rec.name, rec.sex, readgroup )
}
}
| test_proc
}
Результаты:
$ mkdir -p ./path/to/more
$ touch ./path/to/foobar_R{1,2}.fastq.gz
$ touch ./path/to/more/foobar_R{1,2}.fastq.gz
$ touch ./path/to/bazquux_R{1,2}.fastq.gz
$ nextflow run main.nf -params-file file.yaml
N E X T F L O W ~ version 22.04.0
Launching `main.nf` [desperate_colden] DSL2 - revision: 391a9a3b3a
executor > local (3)
[ed/61c5c3] process > test_proc (foobar) [100%] 3 of 3 ✔
foobar,male:
lrwxrwxrwx 1 users 35 Oct 14 13:56 foobar_R1.fastq.gz -> ../../../path/to/foobar_R1.fastq.gz
lrwxrwxrwx 1 users 35 Oct 14 13:56 foobar_R2.fastq.gz -> ../../../path/to/foobar_R2.fastq.gz
bazquux,female:
lrwxrwxrwx 1 users 36 Oct 14 13:56 bazquux_R1.fastq.gz -> ../../../path/to/bazquux_R1.fastq.gz
lrwxrwxrwx 1 users 36 Oct 14 13:56 bazquux_R2.fastq.gz -> ../../../path/to/bazquux_R2.fastq.gz
foobar,male:
lrwxrwxrwx 1 users 40 Oct 14 13:56 foobar_R1.fastq.gz -> ../../../path/to/more/foobar_R1.fastq.gz
lrwxrwxrwx 1 users 40 Oct 14 13:56 foobar_R2.fastq.gz -> ../../../path/to/more/foobar_R2.fastq.gz
Как и было запрошено, вот решение, которое выполняется для каждого примера. Проблема, с которой мы сталкиваемся, заключается в том, что мы не можем просто ввести список списков, используя path
квалификатор (поскольку ArrayList не является допустимым значением пути). Мы могли бы сгладить () список пар файлов, но это затрудняет доступ к каждой из пар файлов, если они нам понадобятся. Возможно, вам не обязательно нужны отношения пары файлов, но, предполагая, что вы это сделаете, я думаю, что правильным решением будет передать файлы R1 и R2 отдельно (т. Е. Используя спецификатор пути для R1 и другой спецификатор пути для R2). В следующем примере анализируется тип экземпляра для (повторного) создания списка групп чтения. Мы можем использовать stageAs
опцию для локализации файлов в постепенно индексируемые подкаталоги, поскольку некоторые файлы в YAML имеют идентичные имена.
process test_proc {
tag { sample_name }
debug true
stageInMode 'rellink'
input:
tuple val(sample_name), val(sex), path(r1, stageAs:'*/*'), path(r2, stageAs:'*/*')
script:
if( [r1, r2].every { it instanceof List } )
readgroups = [r1, r2].transpose()
else if( [r1, r2].every { it instanceof Path } )
readgroups = [[r1, r2], ]
else
error "Invalid readgroup configuration"
read_pairs = readgroups.collect { r1, r2 -> "${r1},${r2}" }
"""
echo "${sample_name},${sex}:"
echo ${read_pairs.join(' ')}
ls -g */*.fastq.gz
"""
}
workflow {
Channel.fromList( params.samples )
| map { rec ->
def r1 = rec.fastqs.r1.collect { file(it) }
def r2 = rec.fastqs.r2.collect { file(it) }
tuple( rec.name, rec.sex, r1, r2 )
}
| test_proc
}
Результаты:
$ nextflow run main.nf -params-file file.yaml
N E X T F L O W ~ version 22.04.0
Launching `main.nf` [berserk_sanger] DSL2 - revision: 2f317a8cee
executor > local (2)
[93/6345c9] process > test_proc (bazquux) [100%] 2 of 2 ✔
foobar,male:
1/foobar_R1.fastq.gz,1/foobar_R2.fastq.gz 2/foobar_R1.fastq.gz,2/foobar_R2.fastq.gz
lrwxrwxrwx 1 users 38 Oct 19 13:43 1/foobar_R1.fastq.gz -> ../../../../path/to/foobar_R1.fastq.gz
lrwxrwxrwx 1 users 38 Oct 19 13:43 1/foobar_R2.fastq.gz -> ../../../../path/to/foobar_R2.fastq.gz
lrwxrwxrwx 1 users 43 Oct 19 13:43 2/foobar_R1.fastq.gz -> ../../../../path/to/more/foobar_R1.fastq.gz
lrwxrwxrwx 1 users 43 Oct 19 13:43 2/foobar_R2.fastq.gz -> ../../../../path/to/more/foobar_R2.fastq.gz
bazquux,female:
1/bazquux_R1.fastq.gz,1/bazquux_R2.fastq.gz
lrwxrwxrwx 1 users 39 Oct 19 13:43 1/bazquux_R1.fastq.gz -> ../../../../path/to/bazquux_R1.fastq.gz
lrwxrwxrwx 1 users 39 Oct 19 13:43 1/bazquux_R2.fastq.gz -> ../../../../path/to/bazquux_R2.fastq.gz
Комментарии:
1. Здесь вы демонстрируете отдельный процесс для каждой пары fastqs. Не могли бы вы вместо этого продемонстрировать, как запускать один процесс для каждого образца , сохраняя при этом копирование всех файлов, необходимых для каждого образца? По сути, ввод в
test_proc
должен допускать список пар путей (групп чтения) вместо одной группы чтения.2. @GordonBean Пожалуйста, посмотрите мою правку выше. Неясно, как именно вам нужно упорядочить пары файлов для команды, которую вам нужно запустить. Но вы должны быть в состоянии переработать вышесказанное, чтобы получить то, что вы хотите, без особых проблем, я надеюсь. Пожалуйста, дайте мне знать, если вам нужно что-нибудь еще. Приветствия.