-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjson_acqlabel.py
executable file
·144 lines (115 loc) · 4.57 KB
/
json_acqlabel.py
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python3
"""
CLI tool for checking template json file against potential stringified inputs.
Run like::
./flycheck_json_acqlabel.py \
-t pitt-luna-habit-project-template.json \
-r AntiSaccade,Habit \
"13 - AntiSaccade" \
"14 - AntiSaccade_repeat_SBRef::Functional::.json"
Yields rows of matchies.
The first column is input string, second column is BIDS file form::
13 - AntiSaccade sub-{session.info.BIDS.Subject}_task-AntiSaccade_bold.nii.gz
14 - AntiSaccade_repeat_SBRef::Functional::.json sub-{session.info.BIDS.Subject}_task-AntiSaccade_run-2_sbref.json
"""
import logging
import os
from flywheel_bids.supporting_files.bidsify_flywheel import (
create_match_info_update,
process_matching_templates,
)
from flywheel_bids.supporting_files.templates import load_template
#: ``Label`` and ``FileTemplate`` mock template input/output
Label = str
FileTemplate = str
def make_context(label: str, intent="Functional", ext=".nii.gz") -> dict:
"""
Make a phony context using the label and maybe intent and/or ext
:param label: label Flywheel would set likely from SeriesName dicom header
:param intent: e.g. "Functional", "Structural"
:param ext: file extension as would be parsed by flywheel.
:return: very light mock context container
"""
context = {
"container_type": "file",
# "acquisition.label" $regex in new json template
"acquisition": {"label": label},
# criteria from bids-client/flywheel_bids/templates/bids-v1.json:777
"file": {"classification": {"Intent": intent}},
"ext": ext,
}
return context
def simulate_output(
json_fname: os.PathLike, labels: list[Label], rule_ids: list[str]
) -> dict[Label, FileTemplate]:
"""
Run example labels against template for at provided rules.
:param json_fname: input template json file to test
:param labels: list of labels for the template to check
:param rule_ids: list of template rules
:return outputs:
"""
template = load_template(
json_fname, template_name="template_test", save_sidecar_as_metadata=True
)
outputs = {}
for label in labels:
logging.debug("trying against label %s", label)
context = make_context(*label.split("::"))
for rule in template.rules:
if rule_ids and not rule.id in rule_ids:
continue
template_def = template.definitions.get(rule.template)
match_info = create_match_info_update(
rule, context, context["file"], template_def["properties"], "BIDS"
)
rule.initializeProperties(match_info, context)
template.apply_custom_initialization(rule.id, match_info, context)
logging.info("BIDS from apply custom: %s", context["file"]["info"]["BIDS"])
# This only works when create_match_info_update has been run
res = process_matching_templates(context, template, upload=False) # type: ignore
fname_template = res.get("info", {}).get("BIDS", {}).get("Filename")
# store output
outputs[label] = fname_template
return outputs
def template_check():
"""
Command line argument aware entry point for py:func:`simulate_output`.
"""
import argparse
loglevel = os.environ.get("LOGLEVEL", "WARN").upper()
logging.getLogger().setLevel(loglevel)
parser = argparse.ArgumentParser(
description="Check labels against a flywheel template json file.",
usage="""
%(prog)s -t pitt-habit_reproin.json -r AntiSaccade,Habit \\
"13 - AntiSaccade" \\
"14 - AntiSaccade_repeat_SBRef::Functional::.json"
export LOGLEVEL=DEBUG to increase verbosity
""",
)
parser.add_argument(
"--template", "-t", required=True, help="Path to the JSON template file"
)
parser.add_argument(
"--rule_id",
"-r",
required=False,
default=None,
help="Restrict checks to these rule ids. comma separate if more than one.",
)
parser.add_argument(
"labels",
nargs="+",
type=str,
help="One or more labels, optionally like label::intent::extension",
)
args = parser.parse_args()
rule_ids = args.rule_id.split(",") if args.rule_id else []
filenames = simulate_output(args.template, args.labels, rule_ids)
# if verbose logging, hard to see where actual output is
logging.info("#### MATCHES below ####")
# tab separate
print("\n".join([f"{k}\t{v}" for k, v in filenames.items()]))
if __name__ == "__main__":
template_check()