Как передать функцию под директивой запуска snakemake

Я строю рабочий процесс в SnakeMake и хотел бы переработать одно из правил для двух разных источников ввода. Входными источниками могут быть либо source1, либо source1+source2, и в зависимости от входных данных выходной каталог также может отличаться. Поскольку это было довольно сложно сделать в одном и том же правиле, и я не хотел создавать копию полного правила, я хотел бы создать два правила с разным вводом / выводом, но с одной и той же командой.

Можно ли сделать эту работу? Я получаю, что DAG-файл разрешен правильно, но работа в кластере не выполняется (ERROR : bamcov_cmd not defined).. Пример ниже (оба правила используют одну и ту же команду в конце):

это команда

def bamcov_cmd():
return( (deepTools_path+"bamCoverage " +
            "-b {input.bam} " +
            "-o {output} " +
            "--binSize {params.bw_binsize} " +
            "-p {threads} " +
            "--normalizeTo1x {params.genome_size} " +
            "{params.read_extension} " +
            "&> {log}") )

это правило

rule bamCoverage:
input:
    bam = file1+"/{sample}.bam",
    bai = file1+"/{sample}.bam.bai"
output:
    "bamCoverage/{sample}.filter.bw"
params:
    bw_binsize = bw_binsize,
    genome_size = int(genome_size),
    read_extension = "--extendReads"
log:
    "bamCoverage/logs/bamCoverage.{sample}.log"
benchmark:
    "bamCoverage/.benchmark/bamCoverage.{sample}.benchmark"
threads: 16
run:
    bamcov_cmd()

это необязательное правило2

rule bamCoverage2:
input:
    bam = file2+"/{sample}.filter.bam",
    bai = file2+"/{sample}.filter.bam.bai"
output:
    "bamCoverage/{sample}.filter.bw"
params:
    bw_binsize = bw_binsize,
    genome_size = int(genome_size),
    read_extension = "--extendReads"
log:
    "bamCoverage/logs/bamCoverage.{sample}.log"
benchmark:
    "bamCoverage/.benchmark/bamCoverage.{sample}.benchmark"
threads: 16
run:
    bamcov_cmd()

1 ответ

Решение

То, что вы спросили, возможно в Python. Это зависит от того, есть ли в файле код Python JUST или Python и Snakemake. Сначала я отвечу на этот вопрос, а затем у меня будет последующий ответ, потому что я хочу, чтобы вы настроили его по-другому, чтобы вам не пришлось делать это таким образом.

Просто Питон:

 from fileContainingMyBamCovCmdFunction import bamcov_cmd

 rule bamCoverage:
 ...
     run:
         bamcov_cmd()

Визуально посмотрите, как я это делаю в этом файле, чтобы сослаться на доступ к buildHeader и buildSample. Эти файлы вызываются Snakefile. Это должно работать так же для вас. https://github.com/LCR-BCCRC/workflow_exploration/blob/master/Snakemake/modules/py_buildFile/buildFile.py

РЕДАКТИРОВАТЬ 2017-07-23 - Обновление сегмента кода ниже, чтобы отразить комментарий пользователя

Снейкмейк и Питон:

 include: "fileContainingMyBamCovCmdFunction.suffix"

 rule bamCoverage:
 ...
     run:
         shell(bamcov_cmd())

РЕДАКТИРОВАТЬ КОНЕЦ

Если функция действительно специфична для вызова bamCoverage, если вы предпочитаете, вы можете вернуть ее в правило. Это подразумевает, что это не вызывается в другом месте, что может быть правдой. Будьте осторожны, когда комментируете файлы, используя '.' примечание, я использую '_', так как я считаю, что таким образом легче предотвратить создание циклических зависимостей. Кроме того, если вы в конечном итоге оставите два правила по отдельности, вы, скорее всего, получите ошибки двусмысленности. http://snakemake.readthedocs.io/en/latest/snakefiles/rules.html?highlight=ruleorder Когда это возможно, рекомендуется иметь правила, генерирующие уникальные выходные данные.

Что касается альтернатив, подумайте над настройкой кода следующим образом?

from subprocess import call


rule all:
    input:
          "path/to/file/mySample.bw"
          #OR
          #"path/to/file/mySample_filtered.bw"


bamCoverage:
input:
    bam = file1+"/{sample}.bam",
    bai = file1+"/{sample}.bam.bai"
output:
    "bamCoverage/{sample}.bw"
params:
    bw_binsize = bw_binsize,
    genome_size = int(genome_size),
    read_extension = "--extendReads"
log:
    "bamCoverage/logs/bamCoverage.{sample}.log"
benchmark:
    "bamCoverage/.benchmark/bamCoverage.{sample}.benchmark"
threads: 16
run:
    callString= deepTools_path + "bamCoverage " \
            + "-b " + wilcards.input.bam \
            + "-o " + wilcards.output \
            + "--binSize " str(params.bw_binsize) \
            + "-p " + str({threads}) \
            + "--normalizeTo1x " + str(params.genome_size) \
            + " " + str(params.read_extension) \
            + "&> " + str(log)
    call(callString, shell=True)


rule filterBam:
input:
    "{pathFB}/{sample}.bam"
output:
    "{pathFB}/{sample}_filtered.bam"
run:
    callString="samtools view -bh -F 512 " + wildcards.input \
    + ' > ' + wildcards.output

    call(callString, shell=True)

Мысли?

Другие вопросы по тегам