Skip to content

Commit

Permalink
Merge pull request #281 from brainglobe/rotation-bug-fix
Browse files Browse the repository at this point in the history
All examples rendering correctly with vedo 2023.5.0
  • Loading branch information
alessandrofelder authored Nov 28, 2023
2 parents e6df766 + b3fa6eb commit 69a2aea
Show file tree
Hide file tree
Showing 24 changed files with 480 additions and 167,181 deletions.
4 changes: 2 additions & 2 deletions brainrender/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def make_actor_label(
color = [0.2, 0.2, 0.2]

# Get mesh's highest point
points = actor.mesh.points().copy()
points = actor.mesh.vertices.copy()
point = points[np.argmin(points[:, 1]), :]
point += np.array(offset) + default_offset
point[2] = -point[2]
Expand All @@ -58,7 +58,7 @@ def make_actor_label(

# Create label
txt = Text3D(
label, point * np.array([1, 1, -1]), s=size, c=color, depth=0.1
label, point * np.array([-1, -1, -1]), s=size, c=color, depth=0.1
)
new_actors.append(txt.rotate_x(180).rotate_y(180))

Expand Down
7 changes: 6 additions & 1 deletion brainrender/actors/neurons.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,12 @@ def __init__(
self.mesh.c(color).alpha(alpha)

def _from_morphapi_neuron(self, neuron: (MorphoNeuron)):
# Temporarily set cache to false as meshes were being corrupted
# on second load
mesh = neuron.create_mesh(
neurite_radius=self.neurite_radius,
soma_radius=self.soma_radius,
use_cache=False,
)[1]
return mesh

Expand All @@ -95,4 +98,6 @@ def _from_file(self, neuron: (str, Path)):

self.name = self.name or path.name

return self._from_morphapi_neuron(MorphoNeuron(data_file=neuron))
return self._from_morphapi_neuron(
MorphoNeuron(data_file=neuron, invert_dims=True)
)
2 changes: 1 addition & 1 deletion brainrender/actors/points.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def __init__(
logger.debug("Creating a PointsDensity actor")

# flip coordinates on XY axis to match brainrender coordinates system
# data[:, 2] = -data[:, 2]
data[:, 2] = -data[:, 2]

# create volume and then actor
volume = (
Expand Down
5 changes: 3 additions & 2 deletions brainrender/actors/ruler.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def ruler(p1, p2, unit_scale=1, units=None, s=50):
dist = mag(p2 - p1) * unit_scale
label = precision(dist, 3) + " " + units
lbl = Text3D(label, pos=midpoint, s=s + 100, justify="center")
# lbl.SetOrientation([0, 0, 180])
lbl.rotate_z(180, around=midpoint)
actors.append(lbl)

# Add spheres add end
Expand All @@ -46,6 +46,7 @@ def ruler(p1, p2, unit_scale=1, units=None, s=50):

act = Actor(merge(*actors), name="Ruler", br_class="Ruler")
act.c((0.3, 0.3, 0.3)).alpha(1).lw(2)

return act


Expand All @@ -66,7 +67,7 @@ def ruler_from_surface(
p2 = p1.copy()
p2[axis] = 0 # zero the chosen coordinate

pts = root.mesh.intersect_with_line(p1, p2)
pts = root._mesh.intersect_with_line(p1, p2)
surface_point = pts[0]

return ruler(p1, surface_point, unit_scale=unit_scale, units=units, s=s)
46 changes: 29 additions & 17 deletions brainrender/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from rich import print
from rich.syntax import Syntax
from vedo import Plotter
from vedo import Volume as VedoVolume
from vedo import settings as vsettings

from brainrender import settings
Expand All @@ -21,6 +22,7 @@

# mtx used to transform meshes to sort axes orientation
mtx = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]]
mtx_swap_x_z = [[0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1]]


class Render:
Expand Down Expand Up @@ -88,24 +90,24 @@ def _make_axes(self):

# make custom axes dict
axes = dict(
axesLineWidth=3,
tipSize=0,
axes_linewidth=3,
tip_size=0,
xtitle="AP (μm)",
ytitle="DV (μm)",
ztitle="LR (μm)",
textScale=0.8,
xTitleRotation=180,
text_scale=0.8,
xtitle_rotation=180,
zrange=z_range,
zValuesAndLabels=z_ticks,
xyGrid=False,
yzGrid=False,
zxGrid=False,
xUseBounds=True,
yUseBounds=True,
zUseBounds=True,
xLabelRotation=180,
yLabelRotation=180,
zLabelRotation=90,
z_values_and_labels=z_ticks,
xygrid=False,
yzgrid=False,
zxgrid=False,
x_use_bounds=True,
y_use_bounds=True,
z_use_bounds=True,
xlabel_rotation=180,
ylabel_rotation=180,
zlabel_rotation=90,
)

return axes
Expand All @@ -118,8 +120,8 @@ def _prepare_actor(self, actor):
Once an actor is 'corrected' it spawns labels and silhouettes as needed
"""
# don't apply transforms to points density actors
if isinstance(actor, PointsDensity):
# don't apply transforms to points density actors or rulers
if isinstance(actor, PointsDensity) or actor.br_class == "Ruler":
logger.debug(
f'Not transforming actor "{actor.name} (type: {actor.br_class})"'
)
Expand All @@ -129,7 +131,16 @@ def _prepare_actor(self, actor):
if not actor._is_transformed:
try:
actor._mesh = actor.mesh.clone()
# actor._mesh.apply_transform(mtx)

if isinstance(actor._mesh, VedoVolume):
actor._mesh.permute_axes(2, 1, 0)
actor._mesh.apply_transform(mtx, True)
elif actor.br_class in ["None", "Gene Data"]:
actor._mesh.apply_transform(mtx_swap_x_z)
actor._mesh.apply_transform(mtx)
else:
actor._mesh.apply_transform(mtx)

except AttributeError: # some types of actors don't transform
logger.debug(
f'Failed to transform actor: "{actor.name} (type: {actor.br_class})"'
Expand Down Expand Up @@ -256,6 +267,7 @@ def render(
bg=settings.BACKGROUND_COLOR,
camera=camera.copy() if update_camera else None,
rate=40,
axes=self.plotter.axes,
)
elif self.backend == "k3d": # pragma: no cover
# Remove silhouettes
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions examples/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
cell_density,
custom_camera,
gene_expression,
# neurons,
# ruler,
neurons,
ruler,
settings,
slice,
# streamlines,
Expand Down
6 changes: 5 additions & 1 deletion examples/add_mesh_from_file.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pathlib import Path
from importlib.resources import files

from myterial import orange
from rich import print
Expand All @@ -14,7 +15,10 @@
scene.add_brain_region("SCm", alpha=0.2)

# Add from file
scene.add("data/CC_134_1_ch1inj.obj", color="tomato")
scene.add(
files("brainrender").joinpath("resources/CC_134_1_ch1inj.obj"),
color="tomato",
)

# Render!
scene.render()
3 changes: 2 additions & 1 deletion examples/neurons.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pathlib import Path
from importlib.resources import files

from morphapi.api.mouselight import MouseLightAPI
from myterial import orange
Expand All @@ -13,7 +14,7 @@
scene = Scene(title="neurons")

# Add a neuron from file
scene.add(Neuron("data/neuron1.swc"))
scene.add(Neuron(files("brainrender").joinpath("resources/neuron1.swc")))

# Download neurons data with morphapi
mlapi = MouseLightAPI()
Expand Down
7 changes: 4 additions & 3 deletions examples/user_volumetric_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
from bg_space import AnatomicalSpace
from myterial import blue_grey, orange
from rich import print
from vedo import Volume
from vedo import Volume as VedoVolume

from brainrender import Scene
from brainrender.actors import Volume

print(f"[{orange}]Running example: {Path(__file__).name}")

Expand Down Expand Up @@ -74,14 +75,14 @@

# 3. create a Volume vedo actor and smooth
print("Creating volume")
vol = Volume(transformed_stack).permute_axes(2, 1, 0)
vol = VedoVolume(transformed_stack)
vol.smooth_median()


# 4. Extract a surface mesh from the volume actor
print("Extracting surface")
mesh = vol.isosurface(value=20).c(blue_grey).decimate().clean()
SHIFT = [-20, 15, 30] # fine tune mesh position
SHIFT = [30, 15, -20] # fine tune mesh position
current_position = mesh.pos()
new_position = [SHIFT[i] + current_position[i] for i in range(3)]
mesh.pos(*new_position)
Expand Down
10 changes: 5 additions & 5 deletions examples/volumetric_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@
from brainrender import Scene, settings
from brainrender.actors import Volume

settings.SHOW_AXES = False


from pathlib import Path
from importlib.resources import files

from myterial import orange
from rich import print

settings.SHOW_AXES = False

print(f"[{orange}]Running example: {Path(__file__).name}")

scene = Scene(inset=False)

data = np.load("data/volume.npy")
data = np.load(files("brainrender").joinpath("resources/volume.npy"))
print(data.shape)

# make a volume actor and add
actor = Volume(
"data/volume.npy",
data,
voxel_size=200, # size of a voxel's edge in microns
as_surface=False, # if true a surface mesh is rendered instead of a volume
c="Reds", # use matplotlib colormaps to color the volume
Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ dependencies = [
"numpy",
"pandas",
"h5py<=3.9", # vedo requires hdf5 <=1.12.x but hdf5 is 1.14+ from h5py 3.10 onwards
"vedo",
"vedo>=2023.5.0",
"k3d",
"imio",
"msgpack",
Expand Down Expand Up @@ -58,7 +58,8 @@ dev = [
"pre-commit",
"ruff",
"setuptools_scm",
"pyside2"
"pyside2",
"imio",
]
nb = ["jupyter", "k3d"]
pyside2= ["PySide2"]
Expand Down
Loading

0 comments on commit 69a2aea

Please sign in to comment.