#snakemake
#snakemake
Вопрос:
Я хотел бы использовать snakemake для первого объединения некоторых файлов, а затем обработать другие файлы на основе этого слияния. (Менее абстрактно: я хочу объединить управляющие файлы IGG bam из двух разных наборов, а затем использовать их для выполнения пикового вызова для других файлов.
В минимальном примере структура папок будет выглядеть следующим образом.
├── data
│ ├── toBeMerged
│ │ ├── singleA
│ │ ├── singleB
│ │ ├── singleC
│ │ └── singleD
│ └── toBeProcessed
│ ├── NotProcess1
│ ├── NotProcess2
│ ├── NotProcess3
│ ├── NotProcess4
│ └── NotProcess5
├── merge.cfg
├── output
│ ├── mergeAB_merge
│ ├── mergeCD_merge
│ ├── NotProcess1_processed
│ ├── NotProcess2_processed
│ ├── NotProcess3_processed
│ ├── NotProcess4_processed
│ └── NotProcess5_processed
├── process.cfg
└── Snakefile
Какие файлы объединяются, а какие обрабатываются, определено в двух файлах конфигурации.
merge.cfg
singlePath controlName
data/toBeMerged/singleA output/controlAB
data/toBeMerged/singleB output/controlAB
data/toBeMerged/singleC output/controlCD
data/toBeMerged/singleD output/controlCD
и обработать.cfg
controlName inName
output/controlAB data/toBeProcessed/NotProcess1
output/controlAB data/toBeProcessed/NotProcess2
output/controlCD data/toBeProcessed/NotProcess3
output/controlCD data/toBeProcessed/NotProcess4
output/controlAB data/toBeProcessed/NotProcess5
В настоящее время я застрял с подобным snakefile, который сам по себе не работает и выдает ошибку о том, что оба правила неоднозначны. И даже если бы я заставил это работать, я подозреваю, что это не «правильный» способ, поскольку правило процесса должно иметь {mergeName} в качестве входных данных для построения своей базы данных. Но это не работает, поскольку тогда мне понадобились бы две подстановочные карточки в одном правиле.
import pandas as pd
cfgMerge = pd.read_table("merge.cfg").set_index("controlName", drop=False)
cfgProc= pd.read_table("process.cfg").set_index("inName", drop=False)
rule all:
input:
expand('{mergeName}', mergeName= cfgMerge.controlName),
expand('{rawName}_processed', rawName= cfgProc.inName)
rule merge:
input:
lambda wc: cfgMerge[cfgMerge.controlName == wc.mergeName].singlePath
output:
"{mergeName}"
shell:
"cat {input} > {output}"
rule process:
input:
inMerge=lambda wc: cfgProc[cfgProc.inName == wc.rawName].controlName.iloc[0],
Name=lambda wc: cfgProc[cfgProc.inName == wc.rawName].inName.iloc[0]
output:
'{rawName}_processed'
shell:
"cat {input.inMerge} {input.Name} > {output}"
Я предполагаю, что ключевая проблема заключается в том, как использовать вывод правила в качестве входных данных для другого, когда оно не зависит от того же подстановочного знака или включает другой другой подстановочный знак.
Комментарии:
1. «как использовать вывод правила в качестве входных данных для другого, когда оно не зависит от того же подстановочного знака» -> Это наводит меня на мысль, что сложная функция ввода могла бы помочь. Под «сложным» я подразумеваю: «С некоторой логикой, реализованной на Python», а также могло бы помочь что-то более читаемое, чем лямбда-функция. «оба правила неоднозначны» -> Такого рода вещи иногда можно разрешить, используя ограничения с подстановочными знаками.
Ответ №1:
Для справки на будущее: проблема, похоже, заключалась не в «использовании вывода правила в качестве входных данных для другого, когда оно не зависит от того же подстановочного знака или включает другой другой подстановочный знак». Кажется, что входные данные для правила all и выходные данные для двух других правил неоднозначны. Простое решение — поместить каждый вывод в другой каталог, и это сработало (см. Ниже).
import pandas as pd
cfgMerge = pd.read_table("merge.cfg").set_index("controlName", drop=False)
cfgProc= pd.read_table("process.cfg").set_index("inName", drop=False)
#ruleorder: merge > process
rule all:
input:
expand('output/bam/{rawName}_processed', rawName= cfgProc.inName),
expand('output/control/{controlNameSnake}', controlNameSnake= cfgMerge.controlName.unique())
rule merge:
input:
lambda wc: cfgMerge[cfgMerge.controlName == wc.controlNameSnake].singlePath.unique()
output:
'output/control/{controlNameSnake}'
shell:
'echo {input} > {output}'
rule process:
input:
in1="data/toBeProcessed/{rawName}",
in2=lambda wc: "output/control/" "".join(cfgProc[cfgProc.inName == wc.rawName].controlName.unique())
output:
'output/bam/{rawName}_processed'
shell:
'echo {input} > {output}'