nipost 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nipost/__init__.py +19 -0
- nipost/_async.py +8 -0
- nipost/_version.pyi +1 -0
- nipost/bids/__init__.py +17 -0
- nipost/bids/_layout.py +17 -0
- nipost/bids/collect.py +292 -0
- nipost/bids/data/anat.yml +57 -0
- nipost/bids/data/fmap.yml +25 -0
- nipost/bids/data/func.yml +125 -0
- nipost/bids/spec.py +191 -0
- nipost/epi.py +198 -0
- nipost/fieldmap.py +219 -0
- nipost/py.typed +0 -0
- nipost/resampling.py +412 -0
- nipost/transforms.py +34 -0
- nipost-0.1.0.dist-info/METADATA +254 -0
- nipost-0.1.0.dist-info/RECORD +19 -0
- nipost-0.1.0.dist-info/WHEEL +4 -0
- nipost-0.1.0.dist-info/licenses/LICENSE +202 -0
nipost/__init__.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
try:
|
|
2
|
+
from ._version import __version__
|
|
3
|
+
except ImportError: # pragma: no cover
|
|
4
|
+
__version__ = '0+unknown'
|
|
5
|
+
|
|
6
|
+
from nipost.epi import ensure_positive_cosines, get_trt, prepare_epi
|
|
7
|
+
from nipost.fieldmap import reconstruct_fieldmap
|
|
8
|
+
from nipost.resampling import resample_image
|
|
9
|
+
from nipost.transforms import load_transforms
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
'__version__',
|
|
13
|
+
'ensure_positive_cosines',
|
|
14
|
+
'get_trt',
|
|
15
|
+
'load_transforms',
|
|
16
|
+
'prepare_epi',
|
|
17
|
+
'reconstruct_fieldmap',
|
|
18
|
+
'resample_image',
|
|
19
|
+
]
|
nipost/_async.py
ADDED
nipost/_version.pyi
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__: str
|
nipost/bids/__init__.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""BIDS derivatives discovery (requires the ``nipost[bids]`` extra)."""
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
from nipost.bids.collect import collect_derivatives, collect_fieldmaps
|
|
5
|
+
from nipost.bids.spec import load_spec, sanitize_fieldmap_id, sanitize_space
|
|
6
|
+
except ImportError as exc: # pragma: no cover
|
|
7
|
+
raise ImportError(
|
|
8
|
+
"nipost.bids requires the 'bids' extra. Install with: pip install 'nipost[bids]'"
|
|
9
|
+
) from exc
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
'collect_derivatives',
|
|
13
|
+
'collect_fieldmaps',
|
|
14
|
+
'load_spec',
|
|
15
|
+
'sanitize_fieldmap_id',
|
|
16
|
+
'sanitize_space',
|
|
17
|
+
]
|
nipost/bids/_layout.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Cached BIDSLayout factory for derivative discovery."""
|
|
2
|
+
|
|
3
|
+
from functools import cache
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from bids.layout import BIDSLayout
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@cache
|
|
10
|
+
def get_layout(derivatives_dir: Path) -> BIDSLayout:
|
|
11
|
+
import niworkflows.data
|
|
12
|
+
|
|
13
|
+
return BIDSLayout(
|
|
14
|
+
derivatives_dir,
|
|
15
|
+
config=[niworkflows.data.load('nipreps.json')],
|
|
16
|
+
validate=False,
|
|
17
|
+
)
|
nipost/bids/collect.py
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# src/nipost/bids/collect.py
|
|
2
|
+
"""Generic, spec-driven derivative discovery."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import re
|
|
7
|
+
from collections.abc import Iterable
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from bids.layout import Query as BIDSQuery
|
|
11
|
+
|
|
12
|
+
from nipost.bids._layout import get_layout
|
|
13
|
+
from nipost.bids.spec import _PLACEHOLDER_RE, Group, Query, Spec, load_spec
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _resolve(alt: dict, base: dict, scope: list[str] | None, params: dict) -> dict:
|
|
17
|
+
"""Build a PyBIDS filter dict from an entities spec and caller-supplied entities.
|
|
18
|
+
|
|
19
|
+
Spec-declared entities override caller-supplied ones.
|
|
20
|
+
``scope`` restricts the caller-supplied entities to the ones this query
|
|
21
|
+
accepts; ``None`` accepts all of them and ``[]`` accepts none.
|
|
22
|
+
Values of the form ``{name}`` are replaced with ``params[name]`` verbatim,
|
|
23
|
+
so ``None`` requires the entity to be absent.
|
|
24
|
+
"""
|
|
25
|
+
merged = {
|
|
26
|
+
# Filter supplied entities by scope, if provided
|
|
27
|
+
**{key: val for key, val in base.items() if scope is None or key in scope},
|
|
28
|
+
# Override with spec-declared entities, which may contain placeholders
|
|
29
|
+
**alt,
|
|
30
|
+
}
|
|
31
|
+
out: dict = {}
|
|
32
|
+
for key, value in merged.items():
|
|
33
|
+
resolved = []
|
|
34
|
+
for declared in value if isinstance(value, list) else [value]:
|
|
35
|
+
match = _PLACEHOLDER_RE.match(declared) if isinstance(declared, str) else None
|
|
36
|
+
if match is None:
|
|
37
|
+
resolved.append(declared)
|
|
38
|
+
continue
|
|
39
|
+
resolved.append(params[match.group(1)])
|
|
40
|
+
out[key] = resolved
|
|
41
|
+
return out
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _lookup(
|
|
45
|
+
layout, location: str, query: Query, base: dict, params: dict
|
|
46
|
+
) -> str | list[str] | None:
|
|
47
|
+
"""Return the reduced result for the first alternative that matches anything.
|
|
48
|
+
|
|
49
|
+
If a single file is expected, the result is a string or ``None``.
|
|
50
|
+
If an unordered list of files is expected, the result is a non-empty list or ``None``.
|
|
51
|
+
If an ordered list of files is expected, the result is a complete list or ``None``.
|
|
52
|
+
|
|
53
|
+
Ambiguous results (multiple matches for either a single file
|
|
54
|
+
or a single value in an ordered list) produce ValueErrors.
|
|
55
|
+
|
|
56
|
+
Ordered lists are sorted by matching entity values.
|
|
57
|
+
Unordered lists are natural-sorted by path to ensure deterministic results,
|
|
58
|
+
and to support use-cases such as :func:`nipost.reconstruct_fieldmap` that depend
|
|
59
|
+
on position (``coefficients[-1]`` is the finest B-spline level).
|
|
60
|
+
"""
|
|
61
|
+
found = []
|
|
62
|
+
entities: dict = {}
|
|
63
|
+
filters: dict = {}
|
|
64
|
+
index = 0
|
|
65
|
+
for index, entities in enumerate(query.entities):
|
|
66
|
+
filters = _resolve(entities, base, query.scope, params)
|
|
67
|
+
found = layout.get(**filters)
|
|
68
|
+
if found:
|
|
69
|
+
break
|
|
70
|
+
where = f'{location} in {layout.root} (alternative {index})'
|
|
71
|
+
|
|
72
|
+
# Unordered, single or multi
|
|
73
|
+
if query.order is None:
|
|
74
|
+
if not (paths := [f.path for f in found]):
|
|
75
|
+
return None
|
|
76
|
+
if query.is_multi:
|
|
77
|
+
return sorted(paths, key=_natural_key)
|
|
78
|
+
if len(paths) > 1:
|
|
79
|
+
raise ValueError(
|
|
80
|
+
f'{where}: expected at most one match for {filters}, got {len(paths)}: {paths}'
|
|
81
|
+
)
|
|
82
|
+
return paths[0]
|
|
83
|
+
|
|
84
|
+
# Ordered result
|
|
85
|
+
by_value: dict[str | None, list[str]] = {}
|
|
86
|
+
for f in found:
|
|
87
|
+
by_value.setdefault(f.entities.get(query.order), []).append(f.path)
|
|
88
|
+
|
|
89
|
+
for value, group in by_value.items():
|
|
90
|
+
if len(group) > 1:
|
|
91
|
+
raise ValueError(
|
|
92
|
+
f'{where}: expected at most one match for {filters} with '
|
|
93
|
+
f'{query.order}={value!r}, got {len(group)}: {group}'
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
order_values = _coerce_axis(entities.get(query.order, []), by_value)
|
|
97
|
+
|
|
98
|
+
if not order_values or any(value not in by_value for value in order_values):
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
return [by_value[value][0] for value in order_values]
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _natural_key(path: str) -> list[int | str]:
|
|
105
|
+
"""Sort key ordering embedded integers numerically, so coeff2 precedes coeff10.
|
|
106
|
+
|
|
107
|
+
``re.split`` with a capture group always yields non-digit segments at
|
|
108
|
+
even indices and digit runs at odd ones, so within a single key an
|
|
109
|
+
``int`` is never compared against a ``str`` at the same position.
|
|
110
|
+
"""
|
|
111
|
+
return [int(part) if part.isdigit() else part for part in re.split(r'(\d+)', path)]
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _coerce_axis(order_values: list[str | None], parsed: Iterable[str | None]) -> list[str | None]:
|
|
115
|
+
"""Coerce declared axis values to the type PyBIDS parsed the entity as.
|
|
116
|
+
|
|
117
|
+
PyBIDS will coerce '01' to an int if the entity is int-typed,
|
|
118
|
+
so the axis must do the same in order to match values
|
|
119
|
+
(``'01' != PaddedInt('01')``).
|
|
120
|
+
|
|
121
|
+
Coerce rather than error, because the values have already been accepted
|
|
122
|
+
by PyBIDS.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
if (sample := next((val for val in parsed if val is not None), None)) is None:
|
|
126
|
+
return order_values
|
|
127
|
+
cls = type(sample)
|
|
128
|
+
coerced: list[str | None] = []
|
|
129
|
+
for value in order_values:
|
|
130
|
+
if value is None or isinstance(value, cls):
|
|
131
|
+
coerced.append(value)
|
|
132
|
+
continue
|
|
133
|
+
try:
|
|
134
|
+
coerced.append(cls(value))
|
|
135
|
+
except (TypeError, ValueError):
|
|
136
|
+
coerced.append(value)
|
|
137
|
+
return coerced
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def collect_derivatives(
|
|
141
|
+
derivatives_dir: Path,
|
|
142
|
+
*,
|
|
143
|
+
spec: Spec,
|
|
144
|
+
entities: dict | None = None,
|
|
145
|
+
params: dict | None = None,
|
|
146
|
+
) -> dict:
|
|
147
|
+
"""Collect precomputed derivatives described by ``spec``.
|
|
148
|
+
|
|
149
|
+
Parameters
|
|
150
|
+
----------
|
|
151
|
+
derivatives_dir
|
|
152
|
+
Root of the derivatives dataset to search.
|
|
153
|
+
spec
|
|
154
|
+
Author-named groups of queries, from :func:`nipost.bids.spec.load_spec`.
|
|
155
|
+
entities
|
|
156
|
+
BIDS entities to match, e.g. ``{'subject': '01', 'task': 'rest'}``.
|
|
157
|
+
A query's ``scope`` may narrow which of these it accepts.
|
|
158
|
+
params
|
|
159
|
+
Values for the placeholders the spec references. A group declaring
|
|
160
|
+
``per: <name>`` iterates ``params[<name>]``: ``None`` for no iterations,
|
|
161
|
+
a single value, or a sequence of values. Any other placeholder takes
|
|
162
|
+
``params[<name>]`` as a scalar, used verbatim: ``None`` requires the
|
|
163
|
+
entity to be absent, and a ``bids.layout.Query`` member has its
|
|
164
|
+
PyBIDS meaning. Values are used verbatim, so apply
|
|
165
|
+
:func:`nipost.bids.spec.sanitize_space` or
|
|
166
|
+
:func:`nipost.bids.spec.sanitize_fieldmap_id` first if needed.
|
|
167
|
+
|
|
168
|
+
Returns
|
|
169
|
+
-------
|
|
170
|
+
dict
|
|
171
|
+
One key per group declared by ``spec``, always present even when the
|
|
172
|
+
group collected nothing. A plain group maps to ``{query: result}``; a
|
|
173
|
+
group with ``per`` maps to ``{param value: {query: result}}``.
|
|
174
|
+
|
|
175
|
+
Raises
|
|
176
|
+
------
|
|
177
|
+
TypeError
|
|
178
|
+
If a group's ``per`` parameter is missing or contains a
|
|
179
|
+
``bids.layout.Query`` member, a placeholder has no value in
|
|
180
|
+
``params``, or a list or tuple is bound to a scalar placeholder.
|
|
181
|
+
ValueError
|
|
182
|
+
If a query matches more than one file in one alternative, or two
|
|
183
|
+
files share an ordering value.
|
|
184
|
+
"""
|
|
185
|
+
base: dict = dict(entities or {})
|
|
186
|
+
supplied: dict = dict(params or {})
|
|
187
|
+
|
|
188
|
+
# Check every group before querying, so a malformed call fails on any dataset
|
|
189
|
+
iterations: dict[str, list | None] = {}
|
|
190
|
+
for group_name, group in spec.items():
|
|
191
|
+
if group.per is not None:
|
|
192
|
+
if group.per not in supplied:
|
|
193
|
+
raise TypeError(
|
|
194
|
+
f'Group {group_name!r} iterates over {group.per!r}; '
|
|
195
|
+
f'pass params[{group.per!r}], or None for no iterations'
|
|
196
|
+
)
|
|
197
|
+
values = supplied[group.per]
|
|
198
|
+
if values is None:
|
|
199
|
+
values = []
|
|
200
|
+
elif isinstance(values, str) or not isinstance(values, Iterable):
|
|
201
|
+
values = [values]
|
|
202
|
+
else:
|
|
203
|
+
values = list(values)
|
|
204
|
+
if any(isinstance(value, (list, tuple)) for value in values):
|
|
205
|
+
raise TypeError(
|
|
206
|
+
f'Group {group_name!r}: params[{group.per!r}] cannot bind a list '
|
|
207
|
+
f'or tuple to a scalar placeholder'
|
|
208
|
+
)
|
|
209
|
+
if any(isinstance(value, BIDSQuery) for value in values):
|
|
210
|
+
raise TypeError(
|
|
211
|
+
f'Group {group_name!r}: params[{group.per!r}] cannot contain '
|
|
212
|
+
f'bids.layout.Query members'
|
|
213
|
+
)
|
|
214
|
+
iterations[group_name] = values
|
|
215
|
+
else:
|
|
216
|
+
iterations[group_name] = None
|
|
217
|
+
for query_name, query in group.queries.items():
|
|
218
|
+
for i, names in enumerate(query.placeholders):
|
|
219
|
+
if missing := sorted(names - supplied.keys()):
|
|
220
|
+
raise TypeError(
|
|
221
|
+
f'{group_name}/{query_name} (alternative {i}) has no value for '
|
|
222
|
+
f'params {missing}'
|
|
223
|
+
)
|
|
224
|
+
for name in names:
|
|
225
|
+
if name != group.per and isinstance(supplied.get(name), (list, tuple)):
|
|
226
|
+
raise TypeError(
|
|
227
|
+
f'{group_name}/{query_name} (alternative {i}): '
|
|
228
|
+
f'params[{name!r}] must be a scalar, not a list or tuple'
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
layout = get_layout(Path(derivatives_dir))
|
|
232
|
+
|
|
233
|
+
def _run_queries(prefix: str, group: Group, params: dict) -> dict:
|
|
234
|
+
"""Run every query in a group once, dropping the keys that found nothing."""
|
|
235
|
+
return {
|
|
236
|
+
key: result
|
|
237
|
+
for key, query in group.queries.items()
|
|
238
|
+
if (result := _lookup(layout, f'{prefix}/{key}', query, base, params)) is not None
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
out: dict = {}
|
|
242
|
+
for group_name, group in spec.items():
|
|
243
|
+
values = iterations[group_name]
|
|
244
|
+
if values is None:
|
|
245
|
+
out[group_name] = _run_queries(group_name, group, supplied)
|
|
246
|
+
continue
|
|
247
|
+
out[group_name] = {
|
|
248
|
+
value: _run_queries(f'{group_name}[{value}]', group, {**supplied, group.per: value})
|
|
249
|
+
for value in values
|
|
250
|
+
}
|
|
251
|
+
return out
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def collect_fieldmaps(
|
|
255
|
+
derivatives_dir: Path,
|
|
256
|
+
*,
|
|
257
|
+
entities: dict,
|
|
258
|
+
spec: Spec | None = None,
|
|
259
|
+
) -> dict[str, dict[str, dict[str, str | list[str]]]]:
|
|
260
|
+
"""Collect fieldmap derivatives, grouped by fieldmap id.
|
|
261
|
+
|
|
262
|
+
Parameters
|
|
263
|
+
----------
|
|
264
|
+
derivatives_dir
|
|
265
|
+
Root of the derivatives dataset to search.
|
|
266
|
+
entities
|
|
267
|
+
BIDS entities to match, e.g. ``{'subject': '01'}``. Also scopes the
|
|
268
|
+
fieldmap-id enumeration, so only ids reachable under these entities
|
|
269
|
+
are collected.
|
|
270
|
+
spec
|
|
271
|
+
Groups of queries to run against each id. Defaults to the bundled
|
|
272
|
+
``fmap`` spec.
|
|
273
|
+
|
|
274
|
+
Returns
|
|
275
|
+
-------
|
|
276
|
+
dict
|
|
277
|
+
The grouped output of :func:`collect_derivatives`. With the bundled
|
|
278
|
+
spec that is ``{'fieldmaps': {fmapid: {'fieldmap': ..., 'coeffs': [...],
|
|
279
|
+
'magnitude': ...}}}``, where ``coeffs`` has one entry per B-spline
|
|
280
|
+
level and is present only when coefficient files are found, which is
|
|
281
|
+
what :func:`nipost.reconstruct_fieldmap` expects.
|
|
282
|
+
"""
|
|
283
|
+
if spec is None:
|
|
284
|
+
spec = load_spec('fmap')
|
|
285
|
+
|
|
286
|
+
layout = get_layout(Path(derivatives_dir))
|
|
287
|
+
|
|
288
|
+
fmapids: list[str] = layout.get_fmapids(**entities)
|
|
289
|
+
|
|
290
|
+
return collect_derivatives(
|
|
291
|
+
derivatives_dir, spec=spec, entities=entities, params={'fmapid': fmapids}
|
|
292
|
+
)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
images:
|
|
2
|
+
queries:
|
|
3
|
+
t1w_preproc:
|
|
4
|
+
entities:
|
|
5
|
+
- datatype: anat
|
|
6
|
+
suffix: T1w
|
|
7
|
+
desc: preproc
|
|
8
|
+
space: null
|
|
9
|
+
extension: [.nii.gz, .nii]
|
|
10
|
+
t2w_preproc:
|
|
11
|
+
entities:
|
|
12
|
+
- datatype: anat
|
|
13
|
+
suffix: T2w
|
|
14
|
+
desc: preproc
|
|
15
|
+
space: null
|
|
16
|
+
extension: [.nii.gz, .nii]
|
|
17
|
+
mask:
|
|
18
|
+
entities:
|
|
19
|
+
- datatype: anat
|
|
20
|
+
suffix: mask
|
|
21
|
+
desc: brain
|
|
22
|
+
space: null
|
|
23
|
+
extension: [.nii.gz, .nii]
|
|
24
|
+
dseg:
|
|
25
|
+
entities:
|
|
26
|
+
- datatype: anat
|
|
27
|
+
suffix: dseg
|
|
28
|
+
desc: null
|
|
29
|
+
space: null
|
|
30
|
+
extension: [.nii.gz, .nii]
|
|
31
|
+
tpms:
|
|
32
|
+
entities:
|
|
33
|
+
- datatype: anat
|
|
34
|
+
suffix: probseg
|
|
35
|
+
space: null
|
|
36
|
+
label: [GM, WM, CSF]
|
|
37
|
+
extension: [.nii.gz, .nii]
|
|
38
|
+
multi: { order: label }
|
|
39
|
+
anat_ribbon:
|
|
40
|
+
entities:
|
|
41
|
+
- datatype: anat
|
|
42
|
+
desc: ribbon
|
|
43
|
+
suffix: mask
|
|
44
|
+
extension: [.nii.gz, .nii]
|
|
45
|
+
transforms:
|
|
46
|
+
per: space
|
|
47
|
+
queries:
|
|
48
|
+
forward:
|
|
49
|
+
entities:
|
|
50
|
+
- from: T1w
|
|
51
|
+
to: "{space}"
|
|
52
|
+
suffix: xfm
|
|
53
|
+
reverse:
|
|
54
|
+
entities:
|
|
55
|
+
- from: "{space}"
|
|
56
|
+
to: T1w
|
|
57
|
+
suffix: xfm
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
fieldmaps:
|
|
2
|
+
per: fmapid
|
|
3
|
+
queries:
|
|
4
|
+
fieldmap:
|
|
5
|
+
entities:
|
|
6
|
+
- datatype: fmap
|
|
7
|
+
fmapid: "{fmapid}"
|
|
8
|
+
desc: preproc
|
|
9
|
+
suffix: fieldmap
|
|
10
|
+
extension: [.nii.gz, .nii]
|
|
11
|
+
coeffs:
|
|
12
|
+
entities:
|
|
13
|
+
- datatype: fmap
|
|
14
|
+
fmapid: "{fmapid}"
|
|
15
|
+
desc: [coeff, coeff0, coeff1]
|
|
16
|
+
suffix: fieldmap
|
|
17
|
+
extension: [.nii.gz, .nii]
|
|
18
|
+
multi: true
|
|
19
|
+
magnitude:
|
|
20
|
+
entities:
|
|
21
|
+
- datatype: fmap
|
|
22
|
+
fmapid: "{fmapid}"
|
|
23
|
+
desc: epi
|
|
24
|
+
suffix: fieldmap
|
|
25
|
+
extension: [.nii.gz, .nii]
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
boldrefs:
|
|
2
|
+
queries:
|
|
3
|
+
hmc:
|
|
4
|
+
entities:
|
|
5
|
+
- datatype: func
|
|
6
|
+
space: orig
|
|
7
|
+
desc: hmc
|
|
8
|
+
suffix: boldref
|
|
9
|
+
extension: [.nii.gz, .nii]
|
|
10
|
+
- datatype: func
|
|
11
|
+
space: null
|
|
12
|
+
desc: hmc
|
|
13
|
+
suffix: boldref
|
|
14
|
+
extension: [.nii.gz, .nii]
|
|
15
|
+
run:
|
|
16
|
+
entities:
|
|
17
|
+
- datatype: func
|
|
18
|
+
space: run
|
|
19
|
+
desc: null
|
|
20
|
+
suffix: boldref
|
|
21
|
+
extension: [.nii.gz, .nii]
|
|
22
|
+
- datatype: func
|
|
23
|
+
space: null
|
|
24
|
+
desc: coreg
|
|
25
|
+
suffix: boldref
|
|
26
|
+
extension: [.nii.gz, .nii]
|
|
27
|
+
session:
|
|
28
|
+
entities:
|
|
29
|
+
- datatype: func
|
|
30
|
+
space: session
|
|
31
|
+
suffix: boldref
|
|
32
|
+
extension: [.nii.gz, .nii]
|
|
33
|
+
scope: [subject, session]
|
|
34
|
+
subject:
|
|
35
|
+
entities:
|
|
36
|
+
- datatype: func
|
|
37
|
+
space: subject
|
|
38
|
+
suffix: boldref
|
|
39
|
+
extension: [.nii.gz, .nii]
|
|
40
|
+
scope: [subject]
|
|
41
|
+
transforms:
|
|
42
|
+
queries:
|
|
43
|
+
hmc:
|
|
44
|
+
entities:
|
|
45
|
+
- datatype: func
|
|
46
|
+
from: orig
|
|
47
|
+
to: run
|
|
48
|
+
mode: image
|
|
49
|
+
suffix: xfm
|
|
50
|
+
extension: .txt
|
|
51
|
+
- datatype: func
|
|
52
|
+
from: orig
|
|
53
|
+
to: boldref
|
|
54
|
+
mode: image
|
|
55
|
+
suffix: xfm
|
|
56
|
+
extension: .txt
|
|
57
|
+
run2anat:
|
|
58
|
+
entities:
|
|
59
|
+
- datatype: func
|
|
60
|
+
from: run
|
|
61
|
+
to: [anat, T1w, T2w]
|
|
62
|
+
mode: image
|
|
63
|
+
suffix: xfm
|
|
64
|
+
extension: .txt
|
|
65
|
+
- datatype: func
|
|
66
|
+
from: boldref
|
|
67
|
+
to: [anat, T1w, T2w]
|
|
68
|
+
mode: image
|
|
69
|
+
suffix: xfm
|
|
70
|
+
extension: .txt
|
|
71
|
+
run2session:
|
|
72
|
+
entities:
|
|
73
|
+
- datatype: func
|
|
74
|
+
from: run
|
|
75
|
+
to: session
|
|
76
|
+
desc: coreg
|
|
77
|
+
mode: image
|
|
78
|
+
suffix: xfm
|
|
79
|
+
extension: .txt
|
|
80
|
+
run2subject:
|
|
81
|
+
entities:
|
|
82
|
+
- datatype: func
|
|
83
|
+
from: run
|
|
84
|
+
to: subject
|
|
85
|
+
desc: coreg
|
|
86
|
+
mode: image
|
|
87
|
+
suffix: xfm
|
|
88
|
+
extension: .txt
|
|
89
|
+
session2anat:
|
|
90
|
+
entities:
|
|
91
|
+
- datatype: func
|
|
92
|
+
from: session
|
|
93
|
+
to: [anat, T1w, T2w]
|
|
94
|
+
mode: image
|
|
95
|
+
suffix: xfm
|
|
96
|
+
extension: .txt
|
|
97
|
+
scope: [subject, session]
|
|
98
|
+
subject2anat:
|
|
99
|
+
entities:
|
|
100
|
+
- datatype: func
|
|
101
|
+
from: subject
|
|
102
|
+
to: [anat, T1w, T2w]
|
|
103
|
+
mode: image
|
|
104
|
+
suffix: xfm
|
|
105
|
+
extension: .txt
|
|
106
|
+
scope: [subject]
|
|
107
|
+
fmap_transforms:
|
|
108
|
+
per: fmapid
|
|
109
|
+
queries:
|
|
110
|
+
run2fmap:
|
|
111
|
+
entities:
|
|
112
|
+
- datatype: func
|
|
113
|
+
from: run
|
|
114
|
+
to: "{fmapid}"
|
|
115
|
+
desc: fmap
|
|
116
|
+
mode: image
|
|
117
|
+
suffix: xfm
|
|
118
|
+
extension: .txt
|
|
119
|
+
- datatype: func
|
|
120
|
+
from: boldref
|
|
121
|
+
to: "{fmapid}"
|
|
122
|
+
desc: null
|
|
123
|
+
mode: image
|
|
124
|
+
suffix: xfm
|
|
125
|
+
extension: .txt
|