bsplot 0.0.2__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.
- bsplot/__init__.py +23 -0
- bsplot/anat.py +55 -0
- bsplot/animate.py +194 -0
- bsplot/bioicons.py +777 -0
- bsplot/brain.py +188 -0
- bsplot/colors.py +1935 -0
- bsplot/data/HCP_avg-SC.txt +379 -0
- bsplot/data/MNI152.rh.pial +0 -0
- bsplot/data/STN_lh.nii.gz +0 -0
- bsplot/data/STN_rh.nii.gz +0 -0
- bsplot/data/__init__.py +22 -0
- bsplot/data/left_electrode.ply +257270 -0
- bsplot/data/parcellations/HCP-MMP1.L.label.gii +442 -0
- bsplot/data/parcellations/HCP-MMP1.R.label.gii +442 -0
- bsplot/data/parcellations/code/split_hcpmmp1.sh +4 -0
- bsplot/data/right_electrode.ply +257270 -0
- bsplot/data/surface.py +112 -0
- bsplot/data/tpl-MNI152NLin2009b_atlas-hcpmmp1_desc-ordered_dseg.nii.gz +0 -0
- bsplot/figure.py +177 -0
- bsplot/graph/__init__.py +31 -0
- bsplot/graph/edges.py +312 -0
- bsplot/graph/flowchart.py +762 -0
- bsplot/graph/layout.py +201 -0
- bsplot/graph/network.py +974 -0
- bsplot/graph/nodes.py +452 -0
- bsplot/panels.py +110 -0
- bsplot/scientific_color_maps/__init__.py +0 -0
- bsplot/scientific_color_maps/_sync_from_zenodo_download.sh +1 -0
- bsplot/scientific_color_maps/batlowK.txt +256 -0
- bsplot/scientific_color_maps/batlowW.txt +256 -0
- bsplot/scientific_color_maps/cyclic/bamO.txt +256 -0
- bsplot/scientific_color_maps/cyclic/brocO.txt +256 -0
- bsplot/scientific_color_maps/cyclic/corkO.txt +256 -0
- bsplot/scientific_color_maps/cyclic/romaO.txt +256 -0
- bsplot/scientific_color_maps/cyclic/vikO.txt +256 -0
- bsplot/scientific_color_maps/diverging/bam.txt +256 -0
- bsplot/scientific_color_maps/diverging/berlin.txt +256 -0
- bsplot/scientific_color_maps/diverging/broc.txt +256 -0
- bsplot/scientific_color_maps/diverging/cork.txt +256 -0
- bsplot/scientific_color_maps/diverging/lisbon.txt +256 -0
- bsplot/scientific_color_maps/diverging/managua.txt +256 -0
- bsplot/scientific_color_maps/diverging/roma.txt +256 -0
- bsplot/scientific_color_maps/diverging/tofino.txt +256 -0
- bsplot/scientific_color_maps/diverging/vanimo.txt +256 -0
- bsplot/scientific_color_maps/diverging/vik.txt +256 -0
- bsplot/scientific_color_maps/multisequential/bukavu.txt +256 -0
- bsplot/scientific_color_maps/multisequential/fes.txt +256 -0
- bsplot/scientific_color_maps/multisequential/oleron.txt +256 -0
- bsplot/scientific_color_maps/naviaW.txt +256 -0
- bsplot/scientific_color_maps/sequential/acton.txt +256 -0
- bsplot/scientific_color_maps/sequential/bamako.txt +256 -0
- bsplot/scientific_color_maps/sequential/batlow.txt +256 -0
- bsplot/scientific_color_maps/sequential/bilbao.txt +256 -0
- bsplot/scientific_color_maps/sequential/buda.txt +256 -0
- bsplot/scientific_color_maps/sequential/davos.txt +256 -0
- bsplot/scientific_color_maps/sequential/devon.txt +256 -0
- bsplot/scientific_color_maps/sequential/glasgow.txt +256 -0
- bsplot/scientific_color_maps/sequential/grayC.txt +256 -0
- bsplot/scientific_color_maps/sequential/hawaii.txt +256 -0
- bsplot/scientific_color_maps/sequential/imola.txt +256 -0
- bsplot/scientific_color_maps/sequential/lajolla.txt +256 -0
- bsplot/scientific_color_maps/sequential/lapaz.txt +256 -0
- bsplot/scientific_color_maps/sequential/lipari.txt +256 -0
- bsplot/scientific_color_maps/sequential/navia.txt +256 -0
- bsplot/scientific_color_maps/sequential/nuuk.txt +256 -0
- bsplot/scientific_color_maps/sequential/oslo.txt +256 -0
- bsplot/scientific_color_maps/sequential/tokyo.txt +256 -0
- bsplot/scientific_color_maps/sequential/turku.txt +256 -0
- bsplot/streamlines.py +314 -0
- bsplot/style.py +791 -0
- bsplot/styles/black.mplstyle +78 -0
- bsplot/styles/bss.mplstyle +50 -0
- bsplot/styles/bwcomp.mplstyle +30 -0
- bsplot/styles/nature.mplstyle +57 -0
- bsplot/styles/transparent.mplstyle +16 -0
- bsplot/styles/tvbo.mplstyle +57 -0
- bsplot/surface.py +2370 -0
- bsplot/templates.py +270 -0
- bsplot/text.py +199 -0
- bsplot/text2obj.py +59 -0
- bsplot/timeseries.py +10 -0
- bsplot/utils.py +13 -0
- bsplot/volume.py +958 -0
- bsplot-0.0.2.dist-info/METADATA +60 -0
- bsplot-0.0.2.dist-info/RECORD +89 -0
- bsplot-0.0.2.dist-info/WHEEL +5 -0
- bsplot-0.0.2.dist-info/entry_points.txt +2 -0
- bsplot-0.0.2.dist-info/licenses/LICENSE +193 -0
- bsplot-0.0.2.dist-info/top_level.txt +1 -0
bsplot/brain.py
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
from os.path import join
|
|
2
|
+
import inspect
|
|
3
|
+
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
import numpy as np
|
|
6
|
+
from nilearn import surface
|
|
7
|
+
|
|
8
|
+
from bsplot import anat, data
|
|
9
|
+
|
|
10
|
+
# imshow kwargs that are not in plot_slice's signature but should still be
|
|
11
|
+
# routed to plot_slice / imshow rather than to Patch schematics
|
|
12
|
+
_IMSHOW_PARAMS = frozenset({
|
|
13
|
+
"norm", "vmin", "vmax", "interpolation", "interpolation_stage",
|
|
14
|
+
"filternorm", "filterrad", "resample", "url", "origin", "extent",
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _split_glass_brain_kwargs(kwargs):
|
|
19
|
+
"""Split **kwargs into (slice_kwargs, patch_kwargs).
|
|
20
|
+
|
|
21
|
+
Kwargs whose names match a ``plot_slice`` parameter or a known
|
|
22
|
+
``imshow`` parameter are routed to *slice_kwargs* (for the image).
|
|
23
|
+
Everything else is routed to *patch_kwargs* (for the brain outline
|
|
24
|
+
Patch objects drawn by ``plot_brain_schematics``).
|
|
25
|
+
"""
|
|
26
|
+
from bsplot.volume import plot_slice
|
|
27
|
+
|
|
28
|
+
sig = inspect.signature(plot_slice)
|
|
29
|
+
slice_param_names = {
|
|
30
|
+
name
|
|
31
|
+
for name, p in sig.parameters.items()
|
|
32
|
+
if p.kind != inspect.Parameter.VAR_KEYWORD
|
|
33
|
+
}
|
|
34
|
+
slice_param_names |= _IMSHOW_PARAMS
|
|
35
|
+
|
|
36
|
+
slice_kw = {}
|
|
37
|
+
patch_kw = {}
|
|
38
|
+
for key, value in kwargs.items():
|
|
39
|
+
if key in slice_param_names:
|
|
40
|
+
slice_kw[key] = value
|
|
41
|
+
else:
|
|
42
|
+
patch_kw[key] = value
|
|
43
|
+
return slice_kw, patch_kw
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def glass_brain(
|
|
47
|
+
img,
|
|
48
|
+
ax=None,
|
|
49
|
+
view="sagittal",
|
|
50
|
+
cmap="viridis",
|
|
51
|
+
colorbar=False,
|
|
52
|
+
intensity_projection="absmax",
|
|
53
|
+
linewidth=None,
|
|
54
|
+
abs_linewidth=None,
|
|
55
|
+
**kwargs,
|
|
56
|
+
):
|
|
57
|
+
# Split kwargs: plot_slice / imshow kwargs vs Patch / schematics kwargs
|
|
58
|
+
slice_kwargs, patch_kwargs = _split_glass_brain_kwargs(kwargs)
|
|
59
|
+
|
|
60
|
+
if linewidth is not None:
|
|
61
|
+
patch_kwargs["linewidth"] = linewidth
|
|
62
|
+
if abs_linewidth is not None:
|
|
63
|
+
patch_kwargs["abs_linewidth"] = abs_linewidth
|
|
64
|
+
|
|
65
|
+
if view in ["lateral", "sagittal"]:
|
|
66
|
+
view = "sagittal"
|
|
67
|
+
|
|
68
|
+
if ax is None and view.lower() == "all":
|
|
69
|
+
fig, axs = plt.subplots(ncols=3, layout="compressed", figsize=(9, 4))
|
|
70
|
+
views = ["coronal", "sagittal", "horizontal"]
|
|
71
|
+
for i, view in enumerate(views):
|
|
72
|
+
ax = axs[i]
|
|
73
|
+
mappable = anat.plot_img(
|
|
74
|
+
img,
|
|
75
|
+
intensity_projection=intensity_projection,
|
|
76
|
+
view=view,
|
|
77
|
+
cmap=cmap,
|
|
78
|
+
ax=ax,
|
|
79
|
+
**slice_kwargs,
|
|
80
|
+
)
|
|
81
|
+
anat.plot_brain_schematics(ax, view=view, **patch_kwargs)
|
|
82
|
+
ax.axis("off")
|
|
83
|
+
return_fig = True
|
|
84
|
+
else:
|
|
85
|
+
if ax is None:
|
|
86
|
+
fig, ax = plt.subplots()
|
|
87
|
+
return_fig = True
|
|
88
|
+
else:
|
|
89
|
+
return_fig = False
|
|
90
|
+
|
|
91
|
+
mappable = anat.plot_img(
|
|
92
|
+
img, intensity_projection=intensity_projection, view=view, cmap=cmap, ax=ax, **slice_kwargs
|
|
93
|
+
)
|
|
94
|
+
# Get image extent before schematics overwrite it
|
|
95
|
+
img_xlim = ax.get_xlim()
|
|
96
|
+
img_ylim = ax.get_ylim()
|
|
97
|
+
|
|
98
|
+
schematic_bounds = anat.plot_brain_schematics(ax=ax, view=view, **patch_kwargs)
|
|
99
|
+
|
|
100
|
+
# Use union of image and schematic bounds
|
|
101
|
+
xlim = (min(img_xlim[0], schematic_bounds[0]), max(img_xlim[1], schematic_bounds[1]))
|
|
102
|
+
ylim = (min(img_ylim[0], schematic_bounds[2]), max(img_ylim[1], schematic_bounds[3]))
|
|
103
|
+
ax.set_xlim(xlim)
|
|
104
|
+
ax.set_ylim(ylim)
|
|
105
|
+
|
|
106
|
+
ax.set_aspect("equal")
|
|
107
|
+
if return_fig:
|
|
108
|
+
if colorbar:
|
|
109
|
+
fig.colorbar(mappable, ax=ax, shrink=0.8)
|
|
110
|
+
plt.close()
|
|
111
|
+
return fig
|
|
112
|
+
else:
|
|
113
|
+
return mappable
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def glass_brain_3d(img, ax=None, surf="fsaverage", cmap="viridis", brain_color="k"):
|
|
117
|
+
if ax is None:
|
|
118
|
+
fig, ax = plt.subplots(1, 1)
|
|
119
|
+
return_fig = True
|
|
120
|
+
else:
|
|
121
|
+
return_fig = False
|
|
122
|
+
|
|
123
|
+
img_data = img.get_fdata()
|
|
124
|
+
|
|
125
|
+
if surf == "fsaverage":
|
|
126
|
+
# fsaverage = datasets.fetch_surf_fsaverage()
|
|
127
|
+
# mesh = surface.load_surf_mesh(fsaverage.pial_right)
|
|
128
|
+
mesh = surface.load_surf_mesh(
|
|
129
|
+
data.surface.get_surface_geometry(
|
|
130
|
+
template="fsaverage", hemi="rh", suffix="pial", density="10k"
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
linewidth = 0.1
|
|
134
|
+
elif surf == "mni09c":
|
|
135
|
+
mesh = surface.load_surf_mesh(join(data.surface.root, "MNI152.rh.pial"))
|
|
136
|
+
linewidth = 0.05
|
|
137
|
+
|
|
138
|
+
coords, faces = mesh[0], mesh[1]
|
|
139
|
+
x, y, z = coords.T
|
|
140
|
+
|
|
141
|
+
if surf != "nilearn":
|
|
142
|
+
ax.triplot(
|
|
143
|
+
y, z, faces, color=brain_color, alpha=0.8, linewidth=linewidth, zorder=100
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
xlim = ax.get_xlim()
|
|
147
|
+
ylim = ax.get_ylim()
|
|
148
|
+
|
|
149
|
+
affine = img.affine
|
|
150
|
+
|
|
151
|
+
voxel_sizes = np.linalg.norm(affine[:3, :3], axis=0) # Get voxel sizes
|
|
152
|
+
origin = affine[:3, 3] # Get translation offset
|
|
153
|
+
x_coords = np.arange(img_data.shape[1]) * voxel_sizes[1] + origin[1]
|
|
154
|
+
y_coords = np.arange(img_data.shape[2]) * voxel_sizes[2] + origin[2]
|
|
155
|
+
|
|
156
|
+
mip_sagittal = np.max(img_data, axis=0) # Maximum Intensity Projection
|
|
157
|
+
mip_sagittal[mip_sagittal == 0] = np.nan
|
|
158
|
+
mip_sagittal = mip_sagittal.T
|
|
159
|
+
valid_x = np.any(~np.isnan(mip_sagittal), axis=0) # Check columns
|
|
160
|
+
valid_y = np.any(~np.isnan(mip_sagittal), axis=1) # Check rows
|
|
161
|
+
|
|
162
|
+
first_valid_x_index, last_valid_x_index = np.flatnonzero(valid_x)[[0, -1]]
|
|
163
|
+
first_valid_y_index, last_valid_y_index = np.flatnonzero(valid_y)[[0, -1]]
|
|
164
|
+
|
|
165
|
+
ax.imshow(
|
|
166
|
+
mip_sagittal,
|
|
167
|
+
cmap=cmap,
|
|
168
|
+
origin="lower",
|
|
169
|
+
interpolation="none",
|
|
170
|
+
alpha=1,
|
|
171
|
+
extent=[
|
|
172
|
+
x_coords[0],
|
|
173
|
+
x_coords[-1],
|
|
174
|
+
y_coords[0],
|
|
175
|
+
y_coords[-1],
|
|
176
|
+
],
|
|
177
|
+
zorder=0,
|
|
178
|
+
)
|
|
179
|
+
ax.set_xlim(x_coords[first_valid_x_index], x_coords[last_valid_x_index])
|
|
180
|
+
ax.set_ylim(y_coords[first_valid_y_index], y_coords[last_valid_y_index])
|
|
181
|
+
ax.set_ylim(ylim)
|
|
182
|
+
ax.set_xlim(xlim)
|
|
183
|
+
ax.set_aspect("equal")
|
|
184
|
+
|
|
185
|
+
if return_fig:
|
|
186
|
+
ax.axis("off")
|
|
187
|
+
plt.close()
|
|
188
|
+
return fig
|