Восстановление Snakemake/перенос заданий

#python #bioinformatics #jobs #job-scheduling #snakemake

Вопрос:

Я пишу конвейер в Snakemake для людей, которые не обладают большими знаниями в области программирования, поэтому я хочу, чтобы они могли запускать весь конвейер, запрашивая только snakemake all -c в командной строке.

У меня есть 2 файла конфигурации в моем файле Snakefile:

 configfile: "config.yaml"
configfile: "config_samples.yaml"
 

Эти файлы конфигурации будут объединены вместе с помощью Snakemake.

config.yaml это стандартный конфигурационный файл. config_samples.yaml представляет собой конфигурационный файл, содержимое которого изменяется в зависимости от ввода конвейера. Это выглядит следующим образом:

 samples:
  CYP20130000B:
    R1: CYP20130000B_R1.fastq
    R2: CYP20130000B_R2.fastq
  SAT20020000A:
    R1: SAT20020000A_R1.fastq
    R2: SAT20020000A_R2.fastq
  ...
 

Я использую скрипт Python в правиле Snakemake для создания содержимого config_samples.yaml (используя директиву snakemake script). Это прекрасно работает.

Однако, когда я перечисляю все свои желаемые результаты в all правиле, например, так:

 "config_samples.done", # flag file for rule that generates config_samples.yaml
expand(QC_raw_reads/{sample}_{direction}_fastqc.html", sample=config["samples"], direction=["R1", "R2"])
 

Тогда это не сработает, потому expand() что будет расширяться только до образцов, которые находятся в текущем config_samples.yaml состоянии, поэтому до того, как скрипт Python фактически создаст новый config_samples.yaml с новыми образцами.

Этого можно легко избежать, запустив правило, которое генерируется config_samples.yaml отдельно перед запуском конвейера enterire, но, возвращаясь к началу, я хочу, чтобы оно оставалось максимально простым для непрограммистов.

Итак, мне было интересно, есть ли способ позволить Snakemake перестроить/перенести задания, чтобы их можно было обновить для новых образцов.

Комментарии:

1. Вы кладете карту перед лошадью. Зачем вам нужен этот файл yaml? Вы создаете эту конфигурацию, а затем планируете прочитать ее для следующего запуска… Почему бы не работать с содержимым этой конфигурации даже без создания файла yaml?

2. Нет, я хочу сгенерировать конфигурацию для того же запуска. Например, если я выполню первый запуск с 3 образцами, то yaml будет сгенерирован с 3 образцами, и он будет работать нормально. Однако, если я затем хочу запустить снова, но с новыми образцами, допустим 5, то это не будет работать, потому что тогда, когда я прошу all правление в командной строке, выход файлы помещаются в предыдущие 3 образцов, потому что те будут по-прежнему находиться в YAML, а не в 5 новых, потому что эти не были сформированы, по правилу, что делает.

3. Так зачем вам вообще нужен yaml? Конфигурация должна быть источником информации, но в вашем случае источником является что-то другое.

4. Потому что в конфигурации у меня есть информация обо всех инструментах, а что нет, и в этом другом yaml я хочу перечислить образцы, потому что это может привести к очень длинному списку, и я хочу сохранить это отдельно от файла конфигурации (и, кроме того, записывать образцы в yaml проще, потому что я могу просто полностью перезаписать его и не беспокоиться об удалении чего-либо из конфигурации).

5. Вам вообще не нужно хранить список образцов в файле конфигурации.

Ответ №1:

Вся ваша проблема, похоже, возникла из-за этого предложения:

Я использую скрипт Python в правиле Snakemake для создания содержимого примеров конфигурации.yaml (с использованием директивы скрипта snakemake). Это прекрасно работает.

Решение может быть таким же простым, как осознание того, что скрипт Python может выполняться вне правила Snakemake только в начале вашего змеиного файла. Змеиный файл-это в основном скрипт на Python. Таким образом, вы можете просто импортировать свой скрипт в этот змеиный файл и выполнить его там.

Таким образом, ваш змеиный файл может выглядеть следующим образом:

 import config_generator
config = config_generator.add_samples(config)

rule all:
   input: expand(QC_raw_reads/{sample}_{direction}_fastqc.html", sample=config["samples"], direction=["R1", "R2"])

rule A:
...
 

config_generator.py выглядело бы так:

 def add_samples(config):
    # here you can calculate whatever you calculate to get config_samples
    # e.g. config["samples"] = ...
    return config
 

Комментарии:

1.Спасибо, это отлично работает! Сначала я не был уверен, что это сработает , потому что я использую config.yaml для извлечения полного пути к образцам, но пока вы вводите « config = config_generator.add_samples(config) после configfile: config.yaml snakefile «, это работает.

2. Обновление: похоже, это работает не слишком хорошо, если вы используете run директиву для правила. Это правило затем имеет доступ ко всему, что определено в файле Snakefile, также за пределами правила , и кажется, что оно постоянно повторяется config_generator.add_samples(config) , но я не уверен на 100% (ошибки, которые я получаю, очень противоречивы и, вероятно, специфичны для моего случая)

Ответ №2:

Я не полностью переварил вопросы и комментарии ниже, но я чувствую, что согласен с @DmitryKuzminov в том, что текущая настройка немного изменена.

В любом случае, я думаю, что вы можете заставить snakemake регенерироваться config_samples.yaml , добавив в начало файла Snakefile, перед первым правилом, что-то вроде:

 if os.path.exists('config_samples.yaml'):
    os.remove('config_samples.yaml')
 

вы даже можете сделать этот шаг управляемым в командной строке с помощью:

 if config['remake_config'] == 'yes':
    if os.path.exists('config_samples.yaml'):
        os.remove('config_samples.yaml')
 

а затем выполните с:

 snakemake -C remake_config='yes' ...
 

Комментарии:

1. Это хорошее предложение, но не совсем то, что я ищу. К тому времени, когда я запрошу желаемый вывод в командной строке, конфигурационный файл уже был прочитан Snakemake, но затем config_samples.yaml все еще содержит старые образцы вместо новых, которые будут сгенерированы во время выполнения. Я искал способ позволить Snakemake обновлять свою конфигурацию с помощью недавно сгенерированных образцов во время выполнения, чтобы можно было генерировать соответствующие выходные данные для каждого нового образца. Однако сейчас я чувствую, что это просто невозможно, поэтому я просто позволю пользователю выполнить две команды, чтобы исправить это