2

我的最终目标是在 GitHub 存储库上托管一个 snakemake 工作流程,可以作为一个 snakemake 模块访问。我在托管它之前在本地进行测试,但我遇到了一个问题。我无法访问snakemake 模块目录中的脚本。它在当前的 snakemake 目录中本地查找脚本,如果我的最终目标是远程托管模块,我显然无法在本地移动。

在远程目录中访问 Conda 环境时,我没有看到这个问题。有没有办法模仿脚本目录的这种行为?如果可以将其应用于访问远程脚本目录,我将对绝对路径引用开放。这是一个重现错误的虚拟示例:

Snakemake 版本:6.0.5

树结构:

.
├── external_module
│   ├── scripts
│   │   ├── argparse
│   │   └── print.py
│   └── Snakefile
└── Snakefile

本地蛇文件:

module remote_module:
    snakefile: "external_module/Snakefile"

use rule * from remote_module

use rule foo from remote_module with:
    input:
        "complete.txt"

外部蛇文件:

rule foo:
    input:
        "complete.txt"

rule bar:
    output:
        touch(temp("complete.txt"))
    shell:
        "scripts/print.py -i foo"

打印.py

import argparse

def get_parser():
    parser = argparse.ArgumentParser(
        description='dummy snakemake function',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument("-i", default=None,
                        help="item to be printed")
    
    return parser

def main():
    args = get_parser().parse_args()
    print(args.i)

if __name__ == '__main__':
    main()

Snakemake管道执行

(base) bobby@SongBird:~/remote_snakemake_test$ snakemake --cores 4
Building DAG of jobs...
Using shell: /usr/bin/bash
Provided cores: 4
Rules claiming more threads will be scaled down.
Job counts:
        count   jobs
        1       bar
        1       foo
        2

[Fri Mar 26 10:12:50 2021]
rule bar:
    output: complete.txt
    jobid: 1

/usr/bin/bash: scripts/print.py: No such file or directory
[Fri Mar 26 10:12:50 2021]
Error in rule bar:
    jobid: 1
    output: complete.txt
    shell:
        scripts/print.py -i foo
        (one of the commands exited with non-zero exit code; note that snakemake uses bash strict mode!)

Shutting down, this might take some time.
Exiting because a job execution failed. Look above for error message
Complete log: /home/bobby/remote_snakemake_test/.snakemake/log/2021-03-26T101250.118440.snakemake.log

任何见解将不胜感激。谢谢!

4

2 回答 2

0

模块对我来说是新的,所以这可能不是最好的方法。该行为似乎有点错误,但这目前有效......

看起来您可以访问工作流的基本目录., withworkflow.basedir和外部目录external_module, with workflow.current_basedirinside external_module/Snakefile。但是,在模块中执行规则时,您似乎无法在规则中使用这些功能。如果将其保存为变量,则以后可以使用它,但前提是该变量也在主 Snakefile 中定义。

这有效:

# Snakefile
module remote_module:
    snakefile: "external_module/Snakefile"

use rule * from remote_module

my_basedir = "DOESN'T MATTER"
use rule foo from remote_module with:
    input:
        "complete.txt"

# external_module/Snakefile
my_basedir = workflow.current_basedir

rule foo:
    input:
        "complete.txt"

rule bar:
    output:
        touch(temp("complete.txt"))
    shell:
        "{my_basedir}/scripts/print.py -i foo"

my_basedir将具有正确目录的值。但是,如果您删除my_basedir顶层 Snakefile 中的赋值,则该变量将不可用,但显然该值本身并未被使用。看起来像一个最终会被修补的错误,所以将它设置为workflow.basedir + '/external_module'.

我还要注意,如果您在不同的工作目录中运行工作流,则 print.py 的相对路径将在原始示例中中断。将该路径设置为配置变量并在主 Snakefile 中正确设置它可能更安全、更理智,如下所示:

# Snakefile
config['my_basedir'] = workflow.current_basedir + '/external_module'
module remote_module:
    snakefile: "external_module/Snakefile"

use rule * from remote_module

use rule foo from remote_module with:
    input:
        "complete.txt"

# external_module/Snakefile
rule foo:
    input:
        "complete.txt"

rule bar:
    output:
        touch(temp("complete.txt"))
    shell:
        "{config[my_basedir]}/scripts/print.py -i foo"

感谢您提供的好玩具示例!

于 2021-03-31T15:05:38.670 回答
0

我也在努力使用模块和相关的脚本。AFAIK 'shell' 条目不会跟踪外部路径,而 'script' 条目会。所以考虑一个具有以下规则的外部模块:

rule foo_shell:
  ...
  shell:
    "script/somescript -a somearg ..."

rule foo_script:
  ...
  script:
    "scripts/somescript_without_arguments.py"

规则 foo_shell 将somescript在相对于主(本地)Snakefile 的子目录脚本中查找脚本,在您的示例中显然不存在。规则 foo_script 将somescript_without_arguments.py在包含远程 Snakefile 的目录中的 scripts 目录中查找脚本,即在您的 external_module/scripts 目录中。通过脚本条目调用的脚本不能使用参数调用,但它们可以访问变量“snakemake”,请参阅文档。此外,只有少数几种语言是可能的,例如 python、R、...

我对您的示例进行了一些更改,这些更改对我有用:

本地/主蛇文件:

module remote_module:
    snakefile: "external_module/Snakefile"
    config: config

use rule * from remote_module

use rule foo from remote_module with:
    input:
        "complete.txt"

外部模块/蛇文件:

rule foo:
    input:
        "complete.txt"

rule bar:
    output:
        touch(temp("complete.txt"))
    params:
      i="foo2"
    script:
        "scripts/print2.py"

external_module/scripts/print2.py (丑陋,但信息丰富:-))

print(snakemake.params["i"])

让我感到困惑的是,似乎在外部模块中使用的脚本中,可以通过在调用的脚本中导入(python)或采购(R)它们来使用额外的、外部的、python 或 R 脚本。以下外部 python 脚本工作得很好,假设 script1.py 和 script2.py 都在外部模块的脚本目录中:

# script1.py
import script2

...

但到目前为止,我还无法从例如正在运行的 python 脚本执行 bash 脚本。类似的东西subprocess.run("remote_module_script.sh","arg")再次查找相对于包含主要本地蛇文件的目录的 bash 脚本。似乎没有办法在远程模块中运行 bash 脚本,除非使用特洛伊的回答中解释的方法。因为我希望能够完全使用当前文件系统外部的模块(例如直接来自 github),所以这个选项对我不起作用。

我希望我对 bash 脚本的理解是错误的,有人会更好地解释外部模块和外部(bash)脚本实际上是如何工作的。

于 2022-01-14T08:59:28.967 回答