brainrender 2.1.19__tar.gz → 2.2.0__tar.gz
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.
- {brainrender-2.1.19 → brainrender-2.2.0}/PKG-INFO +18 -12
- {brainrender-2.1.19 → brainrender-2.2.0}/README.md +13 -9
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/_io.py +24 -1
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/_jupyter.py +8 -4
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/_video.py +1 -1
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/actor.py +154 -79
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/atlas.py +95 -37
- brainrender-2.2.0/brainrender/atlas_specific/allen_brain_atlas/streamlines.py +232 -0
- brainrender-2.2.0/brainrender/camera.py +169 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/cameras.py +6 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/render.py +120 -55
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/scene.py +180 -100
- brainrender-2.2.0/brainrender/video.py +628 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender.egg-info/PKG-INFO +18 -12
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender.egg-info/SOURCES.txt +2 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender.egg-info/requires.txt +4 -2
- brainrender-2.2.0/brainrender.egg-info/scm_file_list.json +112 -0
- brainrender-2.2.0/brainrender.egg-info/scm_version.json +8 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/pyproject.toml +4 -2
- brainrender-2.1.19/brainrender/atlas_specific/allen_brain_atlas/streamlines.py +0 -111
- brainrender-2.1.19/brainrender/camera.py +0 -110
- brainrender-2.1.19/brainrender/video.py +0 -437
- {brainrender-2.1.19 → brainrender-2.2.0}/.github/workflows/test_and_deploy.yml +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/.gitignore +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/CITATION.cff +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/LICENSE +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/MANIFEST.in +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/__init__.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/_colors.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/_utils.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/actors/__init__.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/actors/cylinder.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/actors/line.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/actors/neurons.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/actors/points.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/actors/ruler.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/actors/streamlines.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/actors/volume.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/atlas_specific/__init__.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/atlas_specific/allen_brain_atlas/gene_expression/__init__.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/atlas_specific/allen_brain_atlas/gene_expression/api.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/atlas_specific/allen_brain_atlas/gene_expression/ge_utils.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender/settings.py +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender.egg-info/dependency_links.txt +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/brainrender.egg-info/top_level.txt +0 -0
- {brainrender-2.1.19 → brainrender-2.2.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: brainrender
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Visualisation and exploration of brain atlases and other anatomical data
|
|
5
5
|
Author-email: "Federico Claudi, Adam Tyson, Luigi Petrucco" <hello@brainglobe.info>
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -23,12 +23,14 @@ Requires-Python: >=3.11
|
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Requires-Dist: brainglobe-atlasapi>=2.0.1
|
|
26
|
+
Requires-Dist: cloud-volume>=3.11.0
|
|
26
27
|
Requires-Dist: brainglobe-space>=1.0.0
|
|
27
28
|
Requires-Dist: brainglobe-utils>=0.5.0
|
|
28
|
-
Requires-Dist: h5py
|
|
29
|
+
Requires-Dist: h5py
|
|
29
30
|
Requires-Dist: k3d
|
|
30
31
|
Requires-Dist: loguru
|
|
31
|
-
Requires-Dist:
|
|
32
|
+
Requires-Dist: meshio
|
|
33
|
+
Requires-Dist: morphapi>=0.3.3
|
|
32
34
|
Requires-Dist: msgpack
|
|
33
35
|
Requires-Dist: myterial
|
|
34
36
|
Requires-Dist: numpy
|
|
@@ -55,18 +57,22 @@ Requires-Dist: jupyter; extra == "nb"
|
|
|
55
57
|
Requires-Dist: k3d; extra == "nb"
|
|
56
58
|
Dynamic: license-file
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
[](https://pypi.org/project/brainrender)
|
|
63
|
-
[](https://pypi.org/project/brainrender)
|
|
60
|
+
[](https://brainglobe.info/documentation/brainrender/index.html)
|
|
61
|
+
[](https://brainglobe.info/contact.html)
|
|
62
|
+
[](https://doi.org/10.7554/eLife.65751)
|
|
63
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
64
64
|
[](https://github.com/brainglobe/brainrender/actions)
|
|
65
65
|
[](https://codecov.io/gh/brainglobe/brainrender)
|
|
66
|
+
[](https://pypi.org/project/brainrender)
|
|
67
|
+
[](https://pypi.org/project/brainrender)
|
|
66
68
|
[](https://pepy.tech/project/brainrender)
|
|
67
|
-
[](https://github.com/astral-sh/ruff)
|
|
70
|
+
[](https://github.com/pre-commit/pre-commit)
|
|
71
|
+
[](https://brainglobe.info/community/developers/index.html)
|
|
72
|
+
|
|
73
|
+
# brainrender
|
|
74
|
+
|
|
75
|
+
*A user-friendly python library to create high-quality, 3D neuro-anatomical renderings combining data from publicly available brain atlases with user-generated experimental data.*
|
|
70
76
|
|
|
71
77
|
|
|
72
78
|
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
[](https://pypi.org/project/brainrender)
|
|
6
|
-
[](https://pypi.org/project/brainrender)
|
|
1
|
+
[](https://brainglobe.info/documentation/brainrender/index.html)
|
|
2
|
+
[](https://brainglobe.info/contact.html)
|
|
3
|
+
[](https://doi.org/10.7554/eLife.65751)
|
|
4
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
7
5
|
[](https://github.com/brainglobe/brainrender/actions)
|
|
8
6
|
[](https://codecov.io/gh/brainglobe/brainrender)
|
|
7
|
+
[](https://pypi.org/project/brainrender)
|
|
8
|
+
[](https://pypi.org/project/brainrender)
|
|
9
9
|
[](https://pepy.tech/project/brainrender)
|
|
10
|
-
[](https://github.com/astral-sh/ruff)
|
|
11
|
+
[](https://github.com/pre-commit/pre-commit)
|
|
12
|
+
[](https://brainglobe.info/community/developers/index.html)
|
|
13
|
+
|
|
14
|
+
# brainrender
|
|
15
|
+
|
|
16
|
+
*A user-friendly python library to create high-quality, 3D neuro-anatomical renderings combining data from publicly available brain atlases with user-generated experimental data.*
|
|
13
17
|
|
|
14
18
|
|
|
15
19
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
3
|
import requests
|
|
4
|
-
from vedo import load
|
|
4
|
+
from vedo import Mesh, load
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def connected_to_internet(url="http://www.google.com/", timeout=5):
|
|
@@ -85,3 +85,26 @@ def load_mesh_from_file(filepath, color=None, alpha=None):
|
|
|
85
85
|
actor = load(str(filepath))
|
|
86
86
|
actor.c(color).alpha(alpha)
|
|
87
87
|
return actor
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def convert_meshio_to_vedo(meshio_mesh, color=None, alpha=None):
|
|
91
|
+
"""
|
|
92
|
+
Convert a meshio mesh to a vedo mesh.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
meshio_mesh : meshio.Mesh
|
|
97
|
+
The meshio mesh to convert.
|
|
98
|
+
color : str, optional
|
|
99
|
+
The color to apply to the mesh. Default is None.
|
|
100
|
+
alpha : float, optional
|
|
101
|
+
The transparency to apply to the mesh. Default is None.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
vedo.Mesh
|
|
106
|
+
The converted vedo mesh.
|
|
107
|
+
"""
|
|
108
|
+
actor = Mesh([meshio_mesh.points, meshio_mesh.cells_dict["triangle"]])
|
|
109
|
+
actor.c(color).alpha(alpha)
|
|
110
|
+
return actor
|
|
@@ -43,9 +43,13 @@ class not_on_jupyter: # pragma: no cover
|
|
|
43
43
|
return self.func(obj, *args, **kwargs)
|
|
44
44
|
else:
|
|
45
45
|
print(
|
|
46
|
-
f"[{orange_dark}]Cannot run function [bold {salmon}]{self.func.__name__}[/
|
|
47
|
-
f"[{orange_dark}]
|
|
48
|
-
Syntax("
|
|
49
|
-
Syntax(
|
|
46
|
+
f"[{orange_dark}]Cannot run function [bold {salmon}]{self.func.__name__}[/bold {salmon}] in a jupyter notebook.",
|
|
47
|
+
f"[{orange_dark}]To use brainrender in a Jupyter notebook, set the vedo backend to 'k3d' before creating your scene:\n",
|
|
48
|
+
Syntax("import vedo", lexer="python"),
|
|
49
|
+
Syntax(
|
|
50
|
+
"vedo.settings.default_backend = 'k3d'", lexer="python"
|
|
51
|
+
),
|
|
52
|
+
f"\n[{orange_dark}]Note: some features are not available in the k3d backend.",
|
|
53
|
+
f"[{orange_dark}]To use all features, run brainrender in a standard Python script or interactive terminal instead.",
|
|
50
54
|
)
|
|
51
55
|
return None
|
|
@@ -30,7 +30,7 @@ class Video(VtkVideo):
|
|
|
30
30
|
if self.size:
|
|
31
31
|
fmt += f" -s {self.size}"
|
|
32
32
|
|
|
33
|
-
command = f
|
|
33
|
+
command = f'ffmpeg -hide_banner -loglevel panic -y -r {fps} -start_number 0 -i "{fld}" {fmt} "{name}"'
|
|
34
34
|
out = os.system(command)
|
|
35
35
|
self.tmp_dir.cleanup()
|
|
36
36
|
return out, command
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
"""Actor class and label utilities for brainrender scenes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
1
5
|
from io import StringIO
|
|
2
|
-
from typing import
|
|
6
|
+
from typing import Any, Self
|
|
3
7
|
|
|
4
8
|
import numpy as np
|
|
5
9
|
import numpy.typing as npt
|
|
@@ -7,8 +11,8 @@ import pyinspect as pi
|
|
|
7
11
|
from brainglobe_atlasapi import BrainGlobeAtlas
|
|
8
12
|
from brainglobe_space import AnatomicalSpace
|
|
9
13
|
from myterial import amber, orange, salmon
|
|
10
|
-
from rich.console import Console
|
|
11
|
-
from vedo import Sphere, Text3D
|
|
14
|
+
from rich.console import Console, ConsoleOptions, RenderResult
|
|
15
|
+
from vedo import Mesh, Sphere, Text3D
|
|
12
16
|
|
|
13
17
|
from brainrender._utils import listify
|
|
14
18
|
|
|
@@ -17,27 +21,44 @@ label_mtx = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
|
|
|
17
21
|
|
|
18
22
|
|
|
19
23
|
def make_actor_label(
|
|
20
|
-
atlas,
|
|
21
|
-
actors,
|
|
22
|
-
labels,
|
|
23
|
-
size=300,
|
|
24
|
-
color=None,
|
|
25
|
-
radius=100,
|
|
26
|
-
xoffset=0,
|
|
27
|
-
yoffset
|
|
28
|
-
zoffset=0,
|
|
29
|
-
):
|
|
24
|
+
atlas: BrainGlobeAtlas,
|
|
25
|
+
actors: Actor | list[Actor],
|
|
26
|
+
labels: str | list[str],
|
|
27
|
+
size: int = 300,
|
|
28
|
+
color: str | list[float] | None = None,
|
|
29
|
+
radius: int | None = 100,
|
|
30
|
+
xoffset: int = 0,
|
|
31
|
+
yoffset: int = -500,
|
|
32
|
+
zoffset: int = 0,
|
|
33
|
+
) -> list[Text3D | Sphere]:
|
|
30
34
|
"""
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
Create 3D text labels anchored to actor meshes.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
atlas
|
|
40
|
+
Atlas used for hemisphere queries and point mirroring.
|
|
41
|
+
actors
|
|
42
|
+
Actors to label.
|
|
43
|
+
labels
|
|
44
|
+
Label string(s) for each actor.
|
|
45
|
+
size
|
|
46
|
+
Text size. Default 300.
|
|
47
|
+
color
|
|
48
|
+
Label colour. Defaults to dark grey if None.
|
|
49
|
+
radius
|
|
50
|
+
Radius of the anchor sphere. Set to None to hide. Default 100.
|
|
51
|
+
xoffset
|
|
52
|
+
Positional offset along x. Default 0.
|
|
53
|
+
yoffset
|
|
54
|
+
Positional offset along y. Default -500.
|
|
55
|
+
zoffset
|
|
56
|
+
Positional offset along z. Default 0.
|
|
57
|
+
|
|
58
|
+
Returns
|
|
59
|
+
-------
|
|
60
|
+
list
|
|
61
|
+
Flat list of vedo Text3D and Sphere objects.
|
|
41
62
|
"""
|
|
42
63
|
offset = [-yoffset, -zoffset, xoffset]
|
|
43
64
|
default_offset = np.array([0, -200, 100])
|
|
@@ -79,40 +100,50 @@ def make_actor_label(
|
|
|
79
100
|
|
|
80
101
|
|
|
81
102
|
class Actor:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
103
|
+
"""
|
|
104
|
+
Represents any object displayed in a brainrender scene.
|
|
105
|
+
|
|
106
|
+
Wraps a vedo Mesh with a name and class type, and provides helpers
|
|
107
|
+
for creating silhouettes and 3D labels. Unknown attribute lookups
|
|
108
|
+
are delegated to the underlying mesh.
|
|
109
|
+
|
|
110
|
+
Parameters
|
|
111
|
+
----------
|
|
112
|
+
mesh
|
|
113
|
+
The 3D mesh for this actor.
|
|
114
|
+
name
|
|
115
|
+
Actor name. Default ``"Actor"``.
|
|
116
|
+
br_class
|
|
117
|
+
Brainrender class type. Default ``"None"``.
|
|
118
|
+
is_text
|
|
119
|
+
Whether this actor is a 2D text annotation. Default False.
|
|
120
|
+
color
|
|
121
|
+
Colour to apply to the mesh on construction.
|
|
122
|
+
alpha
|
|
123
|
+
Transparency to apply to the mesh on construction.
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
_needs_label: bool = False # needs to make a label
|
|
127
|
+
_needs_silhouette: bool = False # needs to make a silhouette
|
|
128
|
+
_is_transformed: bool = (
|
|
129
|
+
False # has been transformed to correct axes orientation
|
|
130
|
+
)
|
|
131
|
+
_is_added: bool = False # has the actor been added to the scene already
|
|
86
132
|
|
|
87
|
-
labels = []
|
|
88
|
-
silhouette = None
|
|
133
|
+
labels: list[Actor] = []
|
|
134
|
+
silhouette: Actor | None = None
|
|
89
135
|
|
|
90
136
|
def __init__(
|
|
91
137
|
self,
|
|
92
|
-
mesh,
|
|
93
|
-
name=None,
|
|
94
|
-
br_class=None,
|
|
95
|
-
is_text=False,
|
|
96
|
-
color=None,
|
|
97
|
-
alpha=None,
|
|
98
|
-
):
|
|
99
|
-
"""
|
|
100
|
-
Actor class representing anything shown in a brainrender scene.
|
|
101
|
-
Methods in brainrender.actors are used to creates actors specific
|
|
102
|
-
for different data types.
|
|
103
|
-
|
|
104
|
-
An actor has a mesh, a name and a brainrender class type.
|
|
105
|
-
It also has methods to create a silhouette or a label.
|
|
106
|
-
|
|
107
|
-
:param mesh: instance of vedo.Mesh
|
|
108
|
-
:param name: str, actor name
|
|
109
|
-
:param br_class: str, name of brainrender actors class
|
|
110
|
-
:param is_text: bool, is it a 2d text or annotation?
|
|
111
|
-
:param color: str, name or hex code of color to assign to actor's mesh
|
|
112
|
-
:param alpha: float, transparency to assign to actor's mesh
|
|
113
|
-
"""
|
|
138
|
+
mesh: Mesh,
|
|
139
|
+
name: str | None = None,
|
|
140
|
+
br_class: str | None = None,
|
|
141
|
+
is_text: bool = False,
|
|
142
|
+
color: str | None = None,
|
|
143
|
+
alpha: float | None = None,
|
|
144
|
+
) -> None:
|
|
114
145
|
self.mesh = mesh
|
|
115
|
-
self.name = name or
|
|
146
|
+
self.name = name or Actor
|
|
116
147
|
self.br_class = br_class or "None"
|
|
117
148
|
self.is_text = is_text
|
|
118
149
|
|
|
@@ -121,10 +152,14 @@ class Actor:
|
|
|
121
152
|
if alpha:
|
|
122
153
|
self.mesh.alpha(alpha)
|
|
123
154
|
|
|
124
|
-
def __getattr__(self, attr):
|
|
155
|
+
def __getattr__(self, attr: str) -> Any:
|
|
125
156
|
"""
|
|
126
|
-
|
|
127
|
-
|
|
157
|
+
Delegate unknown attribute lookups to the underlying mesh.
|
|
158
|
+
|
|
159
|
+
Raises
|
|
160
|
+
------
|
|
161
|
+
AttributeError
|
|
162
|
+
If the attribute is not found on any mesh object.
|
|
128
163
|
"""
|
|
129
164
|
if "mesh" not in self.__dict__.keys():
|
|
130
165
|
raise AttributeError(
|
|
@@ -148,10 +183,10 @@ class Actor:
|
|
|
148
183
|
f"Actor does not have attribute {attr}"
|
|
149
184
|
) # pragma: no cover
|
|
150
185
|
|
|
151
|
-
def __repr__(self): # pragma: no cover
|
|
186
|
+
def __repr__(self) -> str: # pragma: no cover
|
|
152
187
|
return f"brainrender.Actor: {self.name}-{self.br_class}"
|
|
153
188
|
|
|
154
|
-
def __str__(self):
|
|
189
|
+
def __str__(self) -> str:
|
|
155
190
|
buf = StringIO()
|
|
156
191
|
_console = Console(file=buf, force_jupyter=False)
|
|
157
192
|
_console.print(self)
|
|
@@ -159,23 +194,50 @@ class Actor:
|
|
|
159
194
|
return buf.getvalue()
|
|
160
195
|
|
|
161
196
|
@property
|
|
162
|
-
def center(self):
|
|
197
|
+
def center(self) -> npt.NDArray[np.float64]:
|
|
163
198
|
"""
|
|
164
|
-
|
|
199
|
+
Return the mesh's centre of mass coordinates.
|
|
200
|
+
|
|
201
|
+
Returns
|
|
202
|
+
-------
|
|
203
|
+
numpy.ndarray
|
|
204
|
+
Array of shape (3,) with (x, y, z) coordinates.
|
|
165
205
|
"""
|
|
166
206
|
return self.mesh.center_of_mass()
|
|
167
207
|
|
|
168
208
|
@classmethod
|
|
169
|
-
def make_actor(cls, mesh, name, br_class):
|
|
209
|
+
def make_actor(cls, mesh: Mesh, name: str, br_class: str) -> Self:
|
|
170
210
|
"""
|
|
171
|
-
|
|
211
|
+
Construct an Actor from an existing mesh.
|
|
212
|
+
|
|
213
|
+
Parameters
|
|
214
|
+
----------
|
|
215
|
+
mesh
|
|
216
|
+
Mesh to wrap.
|
|
217
|
+
name
|
|
218
|
+
Actor name.
|
|
219
|
+
br_class
|
|
220
|
+
Brainrender class type.
|
|
221
|
+
|
|
222
|
+
Returns
|
|
223
|
+
-------
|
|
224
|
+
Actor
|
|
172
225
|
"""
|
|
173
226
|
return cls(mesh, name=name, br_class=br_class)
|
|
174
227
|
|
|
175
|
-
def make_label(self, atlas):
|
|
228
|
+
def make_label(self, atlas: BrainGlobeAtlas) -> list[Actor]:
|
|
176
229
|
"""
|
|
177
|
-
Create
|
|
178
|
-
|
|
230
|
+
Create 3D label actors anchored to this actor's mesh.
|
|
231
|
+
|
|
232
|
+
Parameters
|
|
233
|
+
----------
|
|
234
|
+
atlas
|
|
235
|
+
Atlas used for hemisphere queries and mirroring.
|
|
236
|
+
|
|
237
|
+
Returns
|
|
238
|
+
-------
|
|
239
|
+
list of Actor
|
|
240
|
+
Label actors (text and optional sphere markers).
|
|
179
241
|
"""
|
|
180
242
|
labels = make_actor_label(
|
|
181
243
|
atlas, self, self._label_str, **self._label_kwargs
|
|
@@ -188,9 +250,14 @@ class Actor:
|
|
|
188
250
|
self.labels = lbls
|
|
189
251
|
return lbls
|
|
190
252
|
|
|
191
|
-
def make_silhouette(self):
|
|
253
|
+
def make_silhouette(self) -> Actor:
|
|
192
254
|
"""
|
|
193
|
-
Create a
|
|
255
|
+
Create a silhouette actor outlining this actor's mesh.
|
|
256
|
+
|
|
257
|
+
Returns
|
|
258
|
+
-------
|
|
259
|
+
Actor
|
|
260
|
+
Silhouette actor with brainrender class ``"silhouette"``.
|
|
194
261
|
"""
|
|
195
262
|
lw = self._silhouette_kwargs["lw"]
|
|
196
263
|
color = self._silhouette_kwargs["color"]
|
|
@@ -208,19 +275,25 @@ class Actor:
|
|
|
208
275
|
def mirror(
|
|
209
276
|
self,
|
|
210
277
|
axis: str,
|
|
211
|
-
origin:
|
|
212
|
-
atlas:
|
|
213
|
-
):
|
|
278
|
+
origin: npt.NDArray | None = None,
|
|
279
|
+
atlas: BrainGlobeAtlas | None = None,
|
|
280
|
+
) -> None:
|
|
214
281
|
"""
|
|
215
|
-
Mirror the actor's mesh
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
282
|
+
Mirror the actor's mesh across the given axis.
|
|
283
|
+
|
|
284
|
+
Accepts Cartesian axes (``'x'``, ``'y'``, ``'z'``) or anatomical
|
|
285
|
+
plane names (``'sagittal'``, ``'vertical'``, ``'frontal'``).
|
|
286
|
+
If an anatomical name is used without an atlas, ``'asr'`` space
|
|
287
|
+
is assumed. The mesh is updated in place.
|
|
288
|
+
|
|
289
|
+
Parameters
|
|
290
|
+
----------
|
|
291
|
+
axis
|
|
292
|
+
Axis or anatomical plane to mirror across.
|
|
293
|
+
origin
|
|
294
|
+
Centre of the mirroring operation. Default None.
|
|
295
|
+
atlas
|
|
296
|
+
Atlas used to resolve anatomical axis names. Default None.
|
|
224
297
|
"""
|
|
225
298
|
if axis in ["sagittal", "vertical", "frontal"]:
|
|
226
299
|
anatomical_space = atlas.space if atlas else AnatomicalSpace("asr")
|
|
@@ -230,7 +303,9 @@ class Actor:
|
|
|
230
303
|
|
|
231
304
|
self.mesh = self.mesh.mirror(axis, origin)
|
|
232
305
|
|
|
233
|
-
def __rich_console__(
|
|
306
|
+
def __rich_console__(
|
|
307
|
+
self, console: Console, options: ConsoleOptions
|
|
308
|
+
) -> RenderResult:
|
|
234
309
|
"""
|
|
235
310
|
Print some useful characteristics to console.
|
|
236
311
|
"""
|
|
@@ -1,24 +1,36 @@
|
|
|
1
|
+
"""Atlas subclass adding region and plane Actor support for scenes."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
1
5
|
import numpy as np
|
|
6
|
+
import numpy.typing as npt
|
|
2
7
|
from brainglobe_atlasapi.bg_atlas import BrainGlobeAtlas
|
|
3
8
|
from loguru import logger
|
|
4
9
|
from vedo import Plane
|
|
5
10
|
|
|
6
11
|
from brainrender import settings
|
|
7
|
-
from brainrender._io import
|
|
12
|
+
from brainrender._io import convert_meshio_to_vedo
|
|
8
13
|
from brainrender._utils import return_list_smart
|
|
9
14
|
from brainrender.actor import Actor
|
|
10
15
|
|
|
11
16
|
|
|
12
17
|
class Atlas(BrainGlobeAtlas):
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
"""
|
|
19
|
+
Subclass of BrainGlobeAtlas with helpers for rendering.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
atlas_name
|
|
24
|
+
Falls back to ``settings.DEFAULT_ATLAS`` if None.
|
|
25
|
+
check_latest
|
|
26
|
+
Check for the latest atlas version. Default True.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
atlas_name: str | None = None,
|
|
32
|
+
check_latest: bool = True,
|
|
33
|
+
) -> None:
|
|
22
34
|
atlas_name = atlas_name or settings.DEFAULT_ATLAS
|
|
23
35
|
self.atlas_name = atlas_name
|
|
24
36
|
logger.debug(f"Generating ATLAS: {atlas_name}")
|
|
@@ -30,9 +42,9 @@ class Atlas(BrainGlobeAtlas):
|
|
|
30
42
|
super().__init__(atlas_name=atlas_name, check_latest=check_latest)
|
|
31
43
|
|
|
32
44
|
@property
|
|
33
|
-
def zoom(self):
|
|
45
|
+
def zoom(self) -> float:
|
|
34
46
|
"""
|
|
35
|
-
|
|
47
|
+
Return a reasonable camera zoom given the atlas resolution.
|
|
36
48
|
"""
|
|
37
49
|
res = np.max(self.metadata["resolution"])
|
|
38
50
|
|
|
@@ -44,20 +56,44 @@ class Atlas(BrainGlobeAtlas):
|
|
|
44
56
|
else:
|
|
45
57
|
return 40 / res
|
|
46
58
|
|
|
47
|
-
def _get_region_color(self, region):
|
|
59
|
+
def _get_region_color(self, region: str | int) -> list[float]:
|
|
48
60
|
"""
|
|
49
|
-
|
|
61
|
+
Get the rgb color of a region in the atlas.
|
|
62
|
+
|
|
63
|
+
Parameters
|
|
64
|
+
----------
|
|
65
|
+
region
|
|
66
|
+
Region acronym or ID.
|
|
67
|
+
|
|
68
|
+
Returns
|
|
69
|
+
-------
|
|
70
|
+
list of float
|
|
50
71
|
"""
|
|
51
72
|
return [
|
|
52
73
|
x / 255 for x in self._get_from_structure(region, "rgb_triplet")
|
|
53
74
|
]
|
|
54
75
|
|
|
55
|
-
def get_region(
|
|
76
|
+
def get_region(
|
|
77
|
+
self,
|
|
78
|
+
*regions: str | int,
|
|
79
|
+
alpha: float = 1,
|
|
80
|
+
color: str | list[float] | None = None,
|
|
81
|
+
) -> Actor | list[Actor] | None:
|
|
56
82
|
"""
|
|
57
|
-
Get brain regions meshes as Actors
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
83
|
+
Get brain regions meshes as Actors.
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
*regions
|
|
88
|
+
Region acronyms or IDs.
|
|
89
|
+
alpha
|
|
90
|
+
Mesh transparency. Default 1.
|
|
91
|
+
color
|
|
92
|
+
Uses atlas RGB colour if None.
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
Actor or list of Actor or None
|
|
61
97
|
"""
|
|
62
98
|
if not regions:
|
|
63
99
|
return None
|
|
@@ -75,12 +111,14 @@ class Atlas(BrainGlobeAtlas):
|
|
|
75
111
|
continue
|
|
76
112
|
|
|
77
113
|
# Get mesh
|
|
78
|
-
obj_file = str(self.meshfile_from_structure(region))
|
|
79
114
|
try:
|
|
80
|
-
|
|
115
|
+
meshio_mesh = self.mesh_from_structure(region)
|
|
116
|
+
mesh = convert_meshio_to_vedo(
|
|
117
|
+
meshio_mesh, color=color, alpha=alpha
|
|
118
|
+
)
|
|
81
119
|
except FileNotFoundError:
|
|
82
120
|
print(
|
|
83
|
-
f"The region {region} is in the
|
|
121
|
+
f"The region {region} is in the ontology but does not have a corresponding volume in the atlas being used: {self.atlas_name}. Skipping"
|
|
84
122
|
)
|
|
85
123
|
continue
|
|
86
124
|
|
|
@@ -99,25 +137,45 @@ class Atlas(BrainGlobeAtlas):
|
|
|
99
137
|
|
|
100
138
|
def get_plane(
|
|
101
139
|
self,
|
|
102
|
-
pos=None,
|
|
103
|
-
norm=None,
|
|
104
|
-
plane=None,
|
|
105
|
-
sx=None,
|
|
106
|
-
sy=None,
|
|
107
|
-
color="lightgray",
|
|
108
|
-
alpha=0.25,
|
|
109
|
-
**kwargs,
|
|
110
|
-
):
|
|
140
|
+
pos: npt.ArrayLike | None = None,
|
|
141
|
+
norm: npt.ArrayLike | None = None,
|
|
142
|
+
plane: str | None = None,
|
|
143
|
+
sx: float | None = None,
|
|
144
|
+
sy: float | None = None,
|
|
145
|
+
color: str = "lightgray",
|
|
146
|
+
alpha: float = 0.25,
|
|
147
|
+
**kwargs: Any,
|
|
148
|
+
) -> Actor:
|
|
111
149
|
"""
|
|
112
150
|
Returns a plane going through a point at pos, oriented
|
|
113
|
-
orthogonally to the vector
|
|
151
|
+
orthogonally to the ``norm`` vector and of width and height
|
|
114
152
|
sx, sy.
|
|
115
153
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
154
|
+
Parameters
|
|
155
|
+
----------
|
|
156
|
+
pos
|
|
157
|
+
(x, y, z) the plane passes through. Defaults to root centre of mass.
|
|
158
|
+
norm
|
|
159
|
+
Normal vector. Derived from *plane* if not given.
|
|
160
|
+
plane
|
|
161
|
+
``"sagittal"``, ``"horizontal"``, or ``"frontal"``.
|
|
162
|
+
sx
|
|
163
|
+
Width. Inferred from root bounds if None.
|
|
164
|
+
sy
|
|
165
|
+
Height. Inferred from root bounds if None.
|
|
166
|
+
color
|
|
167
|
+
Default ``"lightgray"``.
|
|
168
|
+
alpha
|
|
169
|
+
Default 0.25.
|
|
170
|
+
|
|
171
|
+
Returns
|
|
172
|
+
-------
|
|
173
|
+
Actor
|
|
174
|
+
|
|
175
|
+
Raises
|
|
176
|
+
------
|
|
177
|
+
ValueError
|
|
178
|
+
If *plane* has no matching normal in the atlas space.
|
|
121
179
|
"""
|
|
122
180
|
axes_pairs = dict(sagittal=(0, 1), horizontal=(2, 0), frontal=(2, 1))
|
|
123
181
|
|