nltools 0.6.0.dev0__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.
- nltools/__init__.py +55 -0
- nltools/algorithms/__init__.py +90 -0
- nltools/algorithms/alignment/__init__.py +21 -0
- nltools/algorithms/alignment/procrustes.py +565 -0
- nltools/algorithms/alignment/srm.py +758 -0
- nltools/algorithms/backends.py +1059 -0
- nltools/algorithms/corrections.py +177 -0
- nltools/algorithms/decoding.py +327 -0
- nltools/algorithms/inference/__init__.py +50 -0
- nltools/algorithms/inference/bootstrap.py +1386 -0
- nltools/algorithms/inference/correlation.py +373 -0
- nltools/algorithms/inference/intersubject.py +422 -0
- nltools/algorithms/inference/isc.py +1554 -0
- nltools/algorithms/inference/matrix.py +602 -0
- nltools/algorithms/inference/one_sample.py +288 -0
- nltools/algorithms/inference/random.py +122 -0
- nltools/algorithms/inference/timeseries.py +347 -0
- nltools/algorithms/inference/two_sample.py +212 -0
- nltools/algorithms/inference/utils.py +58 -0
- nltools/algorithms/inference/validation.py +282 -0
- nltools/algorithms/neighborhoods.py +207 -0
- nltools/algorithms/outliers.py +308 -0
- nltools/algorithms/regression.py +83 -0
- nltools/algorithms/signal.py +303 -0
- nltools/algorithms/similarity.py +234 -0
- nltools/algorithms/validation.py +151 -0
- nltools/cross_validation.py +72 -0
- nltools/data/__init__.py +30 -0
- nltools/data/adjacency/__init__.py +875 -0
- nltools/data/adjacency/io.py +111 -0
- nltools/data/adjacency/modeling.py +569 -0
- nltools/data/adjacency/plotting.py +174 -0
- nltools/data/adjacency/state.py +349 -0
- nltools/data/adjacency/stats.py +596 -0
- nltools/data/adjacency/utils.py +79 -0
- nltools/data/atlases/__init__.py +23 -0
- nltools/data/atlases/labeling.py +158 -0
- nltools/data/atlases/loading.py +76 -0
- nltools/data/atlases/registry.py +96 -0
- nltools/data/atlases/reporting.py +456 -0
- nltools/data/braindata/__init__.py +2170 -0
- nltools/data/braindata/analysis.py +1381 -0
- nltools/data/braindata/bootstrap.py +398 -0
- nltools/data/braindata/io.py +896 -0
- nltools/data/braindata/modeling.py +594 -0
- nltools/data/braindata/plotting.py +501 -0
- nltools/data/braindata/prediction.py +1250 -0
- nltools/data/braindata/utils.py +348 -0
- nltools/data/braindata/validation.py +197 -0
- nltools/data/braindata/viewer.js +266 -0
- nltools/data/braindata/viewer.py +770 -0
- nltools/data/combine.py +27 -0
- nltools/data/designmatrix/__init__.py +1032 -0
- nltools/data/designmatrix/append.py +518 -0
- nltools/data/designmatrix/diagnostics.py +248 -0
- nltools/data/designmatrix/io.py +356 -0
- nltools/data/designmatrix/plotting.py +291 -0
- nltools/data/designmatrix/regressors.py +463 -0
- nltools/data/designmatrix/transforms.py +200 -0
- nltools/data/designmatrix/utils.py +350 -0
- nltools/data/ownership.py +129 -0
- nltools/data/results.py +291 -0
- nltools/data/roc/__init__.py +398 -0
- nltools/data/simulator/__init__.py +927 -0
- nltools/data/simulator/haxby.py +124 -0
- nltools/data/validation.py +83 -0
- nltools/datasets.py +218 -0
- nltools/io/__init__.py +10 -0
- nltools/io/events.py +67 -0
- nltools/io/h5.py +246 -0
- nltools/mask.py +403 -0
- nltools/models/__init__.py +11 -0
- nltools/models/glm.py +543 -0
- nltools/models/results.py +49 -0
- nltools/models/ridge.py +1303 -0
- nltools/models/validation.py +26 -0
- nltools/plotting/__init__.py +32 -0
- nltools/plotting/adjacency.py +421 -0
- nltools/plotting/brain.py +669 -0
- nltools/plotting/decomposition.py +111 -0
- nltools/plotting/prediction.py +110 -0
- nltools/resources/covariates_example.csv +161 -0
- nltools/resources/onsets_example.csv +40 -0
- nltools/templates/__init__.py +51 -0
- nltools/templates/config.py +144 -0
- nltools/templates/fetch.py +260 -0
- nltools/templates/matching.py +183 -0
- nltools/templates/paths.py +106 -0
- nltools/templates/registry.py +25 -0
- nltools/utils.py +230 -0
- nltools/version.py +13 -0
- nltools-0.6.0.dev0.dist-info/METADATA +95 -0
- nltools-0.6.0.dev0.dist-info/RECORD +95 -0
- nltools-0.6.0.dev0.dist-info/WHEEL +4 -0
- nltools-0.6.0.dev0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"""Visualize a DesignMatrix as a heatmap, overlaid time courses, or a correlation matrix.
|
|
2
|
+
|
|
3
|
+
`DesignMatrix.plot` dispatches over `method` to `_plot_matrix`,
|
|
4
|
+
`_plot_timeseries`, and `_plot_corr`, mirroring `BrainData.plot`.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
import matplotlib.pyplot as plt
|
|
15
|
+
|
|
16
|
+
from nltools.data.designmatrix import DesignMatrix
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
VALID_PLOT_METHODS = ("matrix", "timeseries", "corr")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _plot_designmatrix(
|
|
23
|
+
dm: DesignMatrix,
|
|
24
|
+
method: str = "matrix",
|
|
25
|
+
*,
|
|
26
|
+
columns: list[str] | None = None,
|
|
27
|
+
rescale: bool = True,
|
|
28
|
+
metric: str = "pearson",
|
|
29
|
+
ax: plt.Axes | None = None,
|
|
30
|
+
figsize: tuple | None = None,
|
|
31
|
+
title: str | None = None,
|
|
32
|
+
cmap: str | None = None,
|
|
33
|
+
save: str | None = None,
|
|
34
|
+
**kwargs,
|
|
35
|
+
):
|
|
36
|
+
"""Visualize a DesignMatrix, dispatching over `method`.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
dm (DesignMatrix): DesignMatrix instance.
|
|
40
|
+
method (str): ``'matrix'`` (SPM-style heatmap), ``'timeseries'``
|
|
41
|
+
(overlaid line plot), or ``'corr'`` (correlation heatmap).
|
|
42
|
+
Default: ``'matrix'``.
|
|
43
|
+
columns (list[str] | None): Subset of columns to plot. Defaults to all.
|
|
44
|
+
rescale (bool): ``'matrix'`` only; rescale each column by its L2 norm.
|
|
45
|
+
Default: True.
|
|
46
|
+
metric (str): ``'corr'`` only; ``'pearson'`` (default) or ``'spearman'``.
|
|
47
|
+
ax (matplotlib.axes.Axes | None): Existing axis to draw on; a new
|
|
48
|
+
figure is created if omitted.
|
|
49
|
+
figsize (tuple | None): Figure size; per-method default when omitted.
|
|
50
|
+
title (str | None): Axis title.
|
|
51
|
+
cmap (str | None): Colormap (``'matrix'`` / ``'corr'``).
|
|
52
|
+
save (str | None): Path to save the figure.
|
|
53
|
+
**kwargs (dict): Forwarded to the underlying plotter
|
|
54
|
+
(``seaborn.heatmap`` for ``'matrix'`` / ``'corr'``;
|
|
55
|
+
``matplotlib.axes.Axes.plot`` for ``'timeseries'``).
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
matplotlib.figure.Figure: The figure containing the plot.
|
|
59
|
+
|
|
60
|
+
Raises:
|
|
61
|
+
ValueError: If `method` is not one of the three supported values.
|
|
62
|
+
"""
|
|
63
|
+
if method == "matrix":
|
|
64
|
+
return _plot_matrix(
|
|
65
|
+
dm,
|
|
66
|
+
columns=columns,
|
|
67
|
+
rescale=rescale,
|
|
68
|
+
figsize=figsize,
|
|
69
|
+
title=title,
|
|
70
|
+
cmap=cmap,
|
|
71
|
+
ax=ax,
|
|
72
|
+
save=save,
|
|
73
|
+
**kwargs,
|
|
74
|
+
)
|
|
75
|
+
if method == "timeseries":
|
|
76
|
+
return _plot_timeseries(
|
|
77
|
+
dm,
|
|
78
|
+
columns=columns,
|
|
79
|
+
figsize=figsize,
|
|
80
|
+
title=title,
|
|
81
|
+
ax=ax,
|
|
82
|
+
save=save,
|
|
83
|
+
**kwargs,
|
|
84
|
+
)
|
|
85
|
+
if method == "corr":
|
|
86
|
+
return _plot_corr(
|
|
87
|
+
dm,
|
|
88
|
+
columns=columns,
|
|
89
|
+
metric=metric,
|
|
90
|
+
figsize=figsize,
|
|
91
|
+
title=title,
|
|
92
|
+
cmap=cmap,
|
|
93
|
+
ax=ax,
|
|
94
|
+
save=save,
|
|
95
|
+
**kwargs,
|
|
96
|
+
)
|
|
97
|
+
raise ValueError(f"Invalid method {method!r}. Must be one of {VALID_PLOT_METHODS}.")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _plot_matrix(
|
|
101
|
+
dm: DesignMatrix,
|
|
102
|
+
*,
|
|
103
|
+
columns: list[str] | None = None,
|
|
104
|
+
rescale: bool = True,
|
|
105
|
+
figsize: tuple | None = None,
|
|
106
|
+
title: str | None = None,
|
|
107
|
+
cmap: str | None = None,
|
|
108
|
+
ax: plt.Axes | None = None,
|
|
109
|
+
save: str | None = None,
|
|
110
|
+
**kwargs,
|
|
111
|
+
):
|
|
112
|
+
"""Render the design matrix as an SPM-style heatmap (rows=TRs, cols=regressors).
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
dm (DesignMatrix): DesignMatrix instance.
|
|
116
|
+
columns (list[str] | None): Subset of columns to plot. Defaults to all columns.
|
|
117
|
+
rescale (bool): If True, rescale each column by its L2 norm so columns
|
|
118
|
+
with different native magnitudes are visually comparable
|
|
119
|
+
(SPM/nilearn convention). Default: True.
|
|
120
|
+
figsize (tuple | None): Figure size; defaults to ``(4, 6)`` when a new
|
|
121
|
+
figure is made.
|
|
122
|
+
title (str | None): Axis title.
|
|
123
|
+
cmap (str | None): Colormap name. Default: ``'gray'``.
|
|
124
|
+
ax (matplotlib.axes.Axes | None): Existing axis to draw on; a new
|
|
125
|
+
figure is created if omitted.
|
|
126
|
+
save (str | None): Path to save the figure.
|
|
127
|
+
**kwargs (dict): Forwarded to ``seaborn.heatmap``.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
matplotlib.figure.Figure: The rendered figure.
|
|
131
|
+
"""
|
|
132
|
+
import seaborn as sns
|
|
133
|
+
|
|
134
|
+
labels = dm.columns if columns is None else list(columns)
|
|
135
|
+
values = dm.data.select(labels).to_numpy()
|
|
136
|
+
if rescale:
|
|
137
|
+
values = values.astype(float)
|
|
138
|
+
values = values / np.maximum(1.0e-12, np.sqrt(np.sum(values**2, 0)))
|
|
139
|
+
|
|
140
|
+
fig, ax, owns_fig = _new_axis(ax, figsize or (4, 6))
|
|
141
|
+
heatmap_kwargs = {
|
|
142
|
+
"cmap": cmap or "gray",
|
|
143
|
+
"cbar": False,
|
|
144
|
+
"xticklabels": labels,
|
|
145
|
+
"yticklabels": False, # Too many rows for labels typically
|
|
146
|
+
}
|
|
147
|
+
heatmap_kwargs.update(kwargs)
|
|
148
|
+
sns.heatmap(values, ax=ax, **heatmap_kwargs)
|
|
149
|
+
|
|
150
|
+
ax.set_xlabel("Regressors")
|
|
151
|
+
ax.set_ylabel("Time (TRs)")
|
|
152
|
+
if title:
|
|
153
|
+
ax.set_title(title)
|
|
154
|
+
return _finalize(fig, owns_fig, save)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _plot_timeseries(
|
|
158
|
+
dm: DesignMatrix,
|
|
159
|
+
*,
|
|
160
|
+
columns: list[str] | None = None,
|
|
161
|
+
figsize: tuple | None = None,
|
|
162
|
+
title: str | None = None,
|
|
163
|
+
ax: plt.Axes | None = None,
|
|
164
|
+
save: str | None = None,
|
|
165
|
+
**kwargs,
|
|
166
|
+
):
|
|
167
|
+
"""Plot regressor time courses as overlaid lines.
|
|
168
|
+
|
|
169
|
+
One line is drawn per column. Pass the same ``ax`` across calls to overlay
|
|
170
|
+
multiple DesignMatrices (e.g. original vs. convolved).
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
dm (DesignMatrix): DesignMatrix instance.
|
|
174
|
+
columns (list[str] | None): Subset of columns to plot. Defaults to all columns.
|
|
175
|
+
figsize (tuple | None): Figure size; defaults to ``(8, 4)`` when a new
|
|
176
|
+
figure is made.
|
|
177
|
+
title (str | None): Axis title.
|
|
178
|
+
ax (matplotlib.axes.Axes | None): Existing axis to draw on; a new
|
|
179
|
+
figure is created if omitted.
|
|
180
|
+
save (str | None): Path to save the figure.
|
|
181
|
+
**kwargs (dict): Forwarded to ``matplotlib.axes.Axes.plot`` for each line.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
matplotlib.figure.Figure: The rendered figure.
|
|
185
|
+
"""
|
|
186
|
+
cols = list(columns) if columns is not None else list(dm.columns)
|
|
187
|
+
|
|
188
|
+
fig, ax, owns_fig = _new_axis(ax, figsize or (8, 4))
|
|
189
|
+
x = np.arange(dm.shape[0])
|
|
190
|
+
for col in cols:
|
|
191
|
+
ax.plot(x, dm.data[col].to_numpy(), label=col, **kwargs)
|
|
192
|
+
|
|
193
|
+
ax.set_xlabel("Time (TRs)")
|
|
194
|
+
ax.set_ylabel("Value")
|
|
195
|
+
if title:
|
|
196
|
+
ax.set_title(title)
|
|
197
|
+
ax.legend(loc="best", fontsize="small")
|
|
198
|
+
return _finalize(fig, owns_fig, save)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _plot_corr(
|
|
202
|
+
dm: DesignMatrix,
|
|
203
|
+
*,
|
|
204
|
+
columns: list[str] | None = None,
|
|
205
|
+
metric: str = "pearson",
|
|
206
|
+
figsize: tuple | None = None,
|
|
207
|
+
title: str | None = None,
|
|
208
|
+
cmap: str | None = None,
|
|
209
|
+
ax: plt.Axes | None = None,
|
|
210
|
+
save: str | None = None,
|
|
211
|
+
**kwargs,
|
|
212
|
+
):
|
|
213
|
+
"""Render a labeled correlation heatmap of the columns.
|
|
214
|
+
|
|
215
|
+
Reuses `DesignMatrix.corr`, which returns a similarity ``Adjacency``
|
|
216
|
+
with the unit diagonal dropped; the diagonal is restored to ``1.0`` here so
|
|
217
|
+
the heatmap reads as a standard correlation matrix.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
dm (DesignMatrix): DesignMatrix instance.
|
|
221
|
+
columns (list[str] | None): Subset of columns to correlate. Defaults to
|
|
222
|
+
all columns.
|
|
223
|
+
metric (str): ``'pearson'`` (default) or ``'spearman'``.
|
|
224
|
+
figsize (tuple | None): Figure size; scales with the number of columns
|
|
225
|
+
when omitted.
|
|
226
|
+
title (str | None): Axis title.
|
|
227
|
+
cmap (str | None): Colormap name. Default: ``'RdBu_r'``.
|
|
228
|
+
ax (matplotlib.axes.Axes | None): Existing axis to draw on; a new
|
|
229
|
+
figure is created if omitted.
|
|
230
|
+
save (str | None): Path to save the figure.
|
|
231
|
+
**kwargs (dict): Forwarded to ``seaborn.heatmap`` (e.g. ``annot=False``).
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
matplotlib.figure.Figure: The rendered figure.
|
|
235
|
+
"""
|
|
236
|
+
import seaborn as sns
|
|
237
|
+
|
|
238
|
+
from .diagnostics import _corr as _corr
|
|
239
|
+
|
|
240
|
+
adj = _corr(dm, metric=metric, columns=columns)
|
|
241
|
+
mat = adj.squareform()
|
|
242
|
+
np.fill_diagonal(mat, 1.0) # restore unit diagonal dropped by Adjacency
|
|
243
|
+
labels = list(adj.labels) if adj.labels else "auto"
|
|
244
|
+
|
|
245
|
+
n = mat.shape[0]
|
|
246
|
+
side = max(4.0, 0.6 * n + 2.0)
|
|
247
|
+
fig, ax, owns_fig = _new_axis(ax, figsize or (side, side))
|
|
248
|
+
heatmap_kwargs = {
|
|
249
|
+
"cmap": cmap or "RdBu_r",
|
|
250
|
+
"vmin": -1.0,
|
|
251
|
+
"vmax": 1.0,
|
|
252
|
+
"square": True,
|
|
253
|
+
"annot": True,
|
|
254
|
+
"fmt": ".2f",
|
|
255
|
+
"xticklabels": labels,
|
|
256
|
+
"yticklabels": labels,
|
|
257
|
+
}
|
|
258
|
+
heatmap_kwargs.update(kwargs)
|
|
259
|
+
sns.heatmap(mat, ax=ax, **heatmap_kwargs)
|
|
260
|
+
if title:
|
|
261
|
+
ax.set_title(title)
|
|
262
|
+
return _finalize(fig, owns_fig, save)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _new_axis(ax, figsize):
|
|
266
|
+
"""Resolve a drawing axis, tracking whether we created its figure.
|
|
267
|
+
|
|
268
|
+
Caller-supplied axes belong to the caller's figure lifecycle, so we don't
|
|
269
|
+
detach/close them in ``_finalize``.
|
|
270
|
+
"""
|
|
271
|
+
import matplotlib.pyplot as plt
|
|
272
|
+
|
|
273
|
+
if ax is None:
|
|
274
|
+
fig, ax = plt.subplots(figsize=figsize)
|
|
275
|
+
return fig, ax, True
|
|
276
|
+
return ax.figure, ax, False
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def _finalize(fig, owns_fig, save):
|
|
280
|
+
"""Save if requested and detach owned figures from pyplot.
|
|
281
|
+
|
|
282
|
+
Detaching keeps the notebook ``flush_figures`` post-hook from rendering the
|
|
283
|
+
returned figure a second time alongside its ``_repr_*_`` display.
|
|
284
|
+
"""
|
|
285
|
+
import matplotlib.pyplot as plt
|
|
286
|
+
|
|
287
|
+
if save:
|
|
288
|
+
fig.savefig(save, bbox_inches="tight")
|
|
289
|
+
if owns_fig:
|
|
290
|
+
plt.close(fig)
|
|
291
|
+
return fig
|