-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsnakefile_utils.smk
94 lines (74 loc) · 2.62 KB
/
snakefile_utils.smk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import os
import sys
import glob
import yaml
import json
import pathlib
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
# from snakemk_util import recursive_format
def recursive_format(data, params, fail_on_unknown=False):
if isinstance(data, str):
return data.format(**params)
elif isinstance(data, dict):
return {k: recursive_format(v, params) for k, v in data.items()}
elif isinstance(data, list):
return [recursive_format(v, params) for v in data]
else:
if fail_on_unknown:
raise ValueError("Handling of data type not implemented: %s" % type(data))
else:
return data
checkpoint file_depends:
output:
file=touch("{file}.depends"),
input:
file="{file}",
shell:
"echo '{wildcards.file}'"
def require(file):
"""
Makes sure that a certain input file exists before the rest of the rule is being executed.
Technically, returns a function that takes wildcards as arguments.
The resulting dependency adds ".depends" to the file path.
Usage example:
```
def read_config():
[...]
rule test:
input:
config_depends = require("config.yaml") # will effectively require the file "config.yaml.depends"
config = lambda wildcards: read_config("config.yaml")
```
This script does not fail, as `config_depends` has to exist before `config` is being executed.
"""
return lambda wildcards: checkpoints.file_depends.get(file=file).output.file
def read_yaml_input(file, wildcards):
"""
Reads the "input" section from a config yaml
"""
import yaml
with open(file, "r") as fd:
config = yaml.safe_load(fd)
retval = dict()
if "snakemake" in config:
if "input" in config["snakemake"]:
retval = config["snakemake"]["input"]
retval = recursive_format(retval, wildcards)
# make sure that the output is a dictionary
if isinstance(retval, list):
retval = dict(yaml_input=retval)
return retval
def require_yaml_input(file):
"""
Reads the "input" section from a config yaml and adds it as additional input rules.
Also, makes sure that the config file exists beforehand.
See also `require`
"""
def retval(wildcards):
file_fmt = file.format(**wildcards)
# make sure that yaml file exists:
config_depends = checkpoints.file_depends.get(file=file_fmt).output
return read_yaml_input(file_fmt, wildcards)
return retval
localrules: file_depends