2017-08-08 119 views
1

有沒有辦法在.yaml文件中定義snakemake配置字符串,以便它可以包含{通配符}和{param}值,並且在shell命令中使用該字符串時,名稱爲>}替換爲「<名稱>」的實際值?snakemake config參數值可以是要插入/展開的值的字符串嗎?

例如,假設要一個配置字符串定義字符串的格式作爲參數傳遞給一個程序來進行傳遞:

RG:「ID:{ID} REP:{REP}」

其中上述文件位於.yaml文件中,ID和REP是通配符,shell命令將擴展字符串作爲參數傳遞給程序。

回答

1

是,使用PARAMS lambda函數:

MACBOOK> cat paramsArgs.yaml 
A: "Hello world" 
B: "Message: {config[A]} ID: {wildcards.ID} REP: {wildcards.REP}" 

MACBOOK> cat paramsArgs 
configfile: "paramsArgs.yaml" 

rule all: 
    input: "ID2307_REP12.txt" 

def paramFunc(key, wildcards, config): 
    return config[key].format(wildcards=wildcards, config=config) 

rule: 
    output: "ID{ID}_REP{REP}.txt" 
    params: A=config["A"], B=lambda wildcards: paramFunc("B", wildcards, config) 
    shell: 
     """ 
     echo 'A is {params.A}' > {output} 
     echo 'B is {params.B}' >> {output} 
     """ 

MACBOOK> snakemake -s paramsArgs 
Provided cores: 1 
Rules claiming more threads will be scaled down. 
Job counts: 
    count jobs 
    1 2 
    1 all 
    2 

rule 2: 
    output: ID2307_REP12.txt 
    jobid: 1 
    wildcards: REP=12, ID=2307 

Finished job 1. 
1 of 2 steps (50%) done 

localrule all: 
    input: ID2307_REP12.txt 
    jobid: 0 

Finished job 0. 
2 of 2 steps (100%) done 

MACBOOK> cat ID2307_REP12.txt 
A is Hello world 
B is Message: Hello world ID: 2307 REP: 12 
0

這裏設置了一個param功能,它可以讓你展開一個配置字符串,從幾個不同的snakemake來源值:

def paramFunc(wildcards, input, output, threads, resources, config, 
    global_cfg, this_cfg, S): 

    return S.format(wildcards=wildcards, input=input, output=output, 
     threads=threads, resources=resources, config=config, 
     global_cfg=global_cfg, this_cfg=this_cfg) 

這裏有一個如何的例子要從Snakemake params:section中調用paramFunc(),擴展config參數config [「XYZ」]的值並將其分配給名爲「text」的參數,然後在shell命令中展開該「text」參數:

params: 
     text=lambda wildcards, input, output, threads, resources: 
      paramFunc(wildcards, input, output, threads, resources, config, 
       global_cfg, my_local_cfg, config["XYZ"]) 
    shell: "echo 'text is {params.text}'" 

請注意,paramFunc()的最後一個參數是您希望 展開的參數值,在本例中爲config [「XYZ」]。其他參數是包含可能被該參數值引用的值的所有字典。

你可能已經定義配置[「XYZ」與此類似,例如,在.yaml文件:

ABC: "Hello world" 
XYZ: "ABC is {config[ABC]}" 

但是,字符串XYZ不限於擴大在同一個文件中定義的值( ABC在這裏展開),但可以使用其他的「{}」結構來訪問其他地方規定的其他值:

Defined in        Use this construct in param 
----------        --------------------------- 
"config" dictionary      "{config[<name>]}" 
wildcards used in the output filename "{wildcards[<name>]}" 
input filename(s)      "{input}" or "{input[NAME]}" or "{input[#]}" 
output filename(s)      "{output}" or "{output[NAME]}" or "{output[#]}" 
threads         "{threads}" 
resources        "{resources[<name>]}" 
"global_cfg" global config dictionary "{global_cfg[<name>]}" 
"my_local_cfg" module config dictionary "{this_cfg[<name>]}" 

值「global_cfg」和「my_local_cfg」是可被添加到幫助兩個特殊詞典模塊化蛇文件。

對於「global_cfg」,這個想法是,你可能想要一個蛇文件全局定義的字典。在你的主snakefile,這樣做:

include: "global_cfg.py" 

而且在文件global_cfg.py,將全局定義:

global_cfg = { 
    "DATA_DIR" : "ProjData", 
    "PROJ_DESC" : "Mint Sequencing" 
} 

然後你就可以在例如參數字符串中引用這些值:

"{global_cfg[DATADIR]}" 

(字符串必須在PARAMS擴展:通過調用paramFunc()部分)

對於「my_local_cfg」,這個想法是,你可能希望將每個snakefile規則在一個單獨的文件,並且該規則的參數也在單獨的文件中定義,因此每個規則都有一個規則文件和一個參數文件。在主snakefile:

(include paramFunc() definition above) 
include: "myrule.snake" 
rule all: 
    input: "myrule.txt" 

在myrule.snake:

include: "myrule.py" 

在myrule.py地方的MyRule的模塊的配置設置:

myrule_cfg = { 
    "SPD" : 125, 
    "DIST" : 98, 
    "MSG" : "Param settings: Speed={this_cfg[SPD]} Dist={this_cfg[DIST]}" 
} 

,背myrule.snake :

include: "myrule.py" 
rule myrule: 
    params: 
     SPD=myrule_cfg["SPD"], 
     DIST=myrule_cfg["DIST"], 
     # For MSG call paramFunc() to expand {name} constructs. 
     MSG=lambda wildcards, input, output, threads, resources: 
      paramFunc(wildcards, input, output, threads, resources, config, 
       global_cfg, myrule_cfg, myrule_cfg["MSG"]) 
    message: "{params.MSG}" 
    output: "myrule.txt" 
    shell: "echo '-speed {params.SPD} -dist {params.DIST}' >{output}" 

請注意,p aramFunc()函數將名稱「myrule_cfg」(根據規則變化)映射到固定名稱「this_cfg」(不管規則如何)。

請注意,我包含定義global_cfg和this_cfg字典的.py文件。這些可以在.yaml文件中定義,但問題是,它們最終都會以「config」結尾。如果CONFIGFILE命令允許指定的字典這將是很好,例如:

configfile: global_cfg="global_cfg.yaml" 

也許該功能將被添加到某一天snakemake。

+0

這應該真正成爲你原來的一部分問題,因爲它不是一個真正的答案... – tomkinsc

7

讓我試圖提供一個簡短的回答這個問題:

在Snakemake,您可以提供功能參數,可以內搭通配符作爲參數。在這些函數中,您可以執行任何python代碼,包括格式語句來格式化您的配置值,例如

configfile: "config.yaml" 

rule: 
    output: 
     "plots/myplot.{mywildcard}.pdf" 
    params: 
     myparam=lambda wildcards: config["mykey"].format(**wildcards) 
    shell: 
     ... 

正如你所看到的,你可以使用python unpacking operatorstr.format方法,以取代在配置文件中的值。這假設config["mykey"]產生包含與上述相同的通配符的字符串,例如, "foo{mywildcard}bar"

0

我意識到可以使用** config和** globals()在JohannesKöster的答案中format()的附加參數來擴展在蛇文件的python代碼中定義的變量,例如變量「ABC」在下面的例子中,並且允許在不使用擴展中的「config」的情況下擴展配置參數。假設config.yaml包含:

X: "Hello" 
MSG: "config X: {X} variable ABC: {ABC} wildcard WW: {WW}" 

,你有這樣的snakefile:

configfile: "config.yaml" 

rule all: 
    input: "test.Goodbye.txt" 

rule A: 
    output: "test.{WW}.txt" 
    params: MSG=lambda wildcards: config["MSG"].format(wildcards=wildcards, **config, **globals()) 
    message: "{params.MSG}" 
    shell: "echo '{params.MSG}' >{output}" 


ABC = "This is the ABC variable" 

的消息和文件輸出將是這一行:

config X: Hello variable ABC: This is the ABC variable wildcard WW: Goodbye 
相關問題