#snakemake
#snakemake
Вопрос:
У меня есть рабочий процесс snakemake, содержащий правило, которое запускает другой «внутренний» рабочий процесс snakemake.
Иногда происходит сбой определенного правила внутреннего рабочего процесса, что означает сбой внутреннего рабочего процесса. В результате все файлы, перечисленные в разделе output
внутреннего рабочего процесса, удаляются внешним рабочим процессом, даже если правила внутреннего рабочего процесса, которые их создали, завершились успешно.
Есть ли способ предотвратить удаление snakemake выходных данных сбойных правил? Или, может быть, вы можете предложить другой обходной путь?
Несколько замечаний:
- Выходные данные внутреннего рабочего процесса должны быть перечислены, поскольку они используются в качестве входных данных для других правил во внешнем рабочем процессе.
- Я попытался установить выходные данные внутреннего рабочего процесса как
protected
, но это не помогло. - Я также попытался добавить
exit 0
в конец вызова внутреннего рабочего процесса, чтобы snakemake считал, что он успешно завершен,
вот так:
rule run_inner:
input:
inputs...
output:
outputs...
shell:
"""
snakemake -s inner.snakefile
exit 0
"""
но выходные данные все равно удаляются.
Был бы признателен за любую помощь. Спасибо!
Ответ №1:
Одним из вариантов может быть run_inner
создание фиктивного выходного файла, который помечает завершение правила. Следующие правила run_inner
будут принимать на входе фиктивный файл. Например:
rule run_inner:
...
output:
# or just 'run_inner.done' if wildcards are not involved
touch('{sample}.run_inner.done'),
shell:
'snakemake -s inner.snakefile'
run next:
input:
'{sample}.run_inner.done',
params:
real_input= '{sample}.data.txt', # This is what run_inner actually produces
shell:
'do stuff {params.real_input}'
В случае snakemake -s inner.snakefile
сбоя фиктивный вывод будет удален, но snakemake -s inner.snakefile
будет перезапущен с того места, где он был оставлен.
Другим вариантом может быть интеграция правил inner.snakefile
в ваш внешний конвейер, используя, например, оператор include . Я считаю, что этот вариант предпочтительнее, но, конечно, его было бы сложнее реализовать.
Комментарии:
1. Спасибо!
include
это было именно то, что мне было нужно, и на самом деле довольно просто в использовании.
Ответ №2:
Одним из обходных путей является использование run
вместо shell
:
rule run_inner:
input:
inputs...
output:
outputs...
run:
shell("""snakemake -s inner.snakefile""")
# Add your code here to store the files before removing
Даже если сценарий в shell
вызове функции завершается с ошибкой, файлы все еще существуют, пока сценарий в run
разделе не завершится. Вы можете скопировать файлы в безопасное место.
Обновление: вам необходимо обрабатывать исключения, чтобы продолжить выполнение всякий раз, когда скрипт возвращает ошибку. Приведенный ниже сценарий иллюстрирует идею: print
функция из except:
блока печатает True
, другая из onerror
печатает False
rule run_inner:
output:
"output.txt"
run:
try:
shell("""touch output.txt; exit 1""")
except:
print(os.path.exists("output.txt"))
onerror:
print(os.path.exists("output.txt"))
Комментарии:
1. Спасибо, это интересное направление, но как мне таким образом вернуть выходные файлы к их ожидаемому пути? Они мне понадобятся для возобновления рабочего процесса.
2. Я не думаю, что это сработает. Если
shell
команда не выполняется, snakemake удалит файлы, перечисленные вoutput
, и завершит работу. Он не будет продолжаться и выполнять остальную частьrun
директивы.3. @dariober, не думай, просто проверь. Это не
shell()
функция, которая удаляет выходные данные, а процедура очистки правила. Эта процедура не вызывается до завершенияrun
работы скрипта.4. @DmitryKuzminov Я тестировал это, я все еще не думаю, что сценарий запуска выполняется до конца. В каталоге запуска я помещаю
shell("touch {output}; exit 1"); os.rename(output[0], output[0] '.done')
.shell
создает выходные данные и завершается сбоем, поэтомуos.rename
никогда не выполняется иoutput[0] '.done'
не создается. Можете ли вы опубликовать воспроизводимый пример?5. @dariober, хм, мой первоначальный сценарий был некорректным. После переноса
shell
в try / except это начинает работать.
Ответ №3:
Программа «завершается с ошибкой», когда возвращает ненулевое возвращаемое значение. Поэтому нам нужно только «исправить» эту проблему, чтобы обмануть внутреннюю оболочку, думая, что все программы успешно завершены. Самый простой способ — использовать some error command || true
. Ниже приведен минимальный пример:
rule test:
output:
"test.output",
shell:
"""
touch test.output
# below cat will trigger error
cat file_not_exist || true
"""
Вы обнаружите, что, несмотря на ошибку, выданную cat
, test.output
все еще сохраняется.