Skip to content

Commit

Permalink
add automatic scalar range at pointdata.setitem
Browse files Browse the repository at this point in the history
  • Loading branch information
marcomusy committed Dec 5, 2023
1 parent b8c1502 commit ed3388c
Show file tree
Hide file tree
Showing 15 changed files with 148 additions and 35 deletions.
3 changes: 2 additions & 1 deletion docs/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
- add `Axes(title_backface_color=...)` keyword
- improvements on `plotter.__init__()`
- fix `labels()` and `labels2d()`

- add `shapes.plot_scalar()` plot a scalar along a line.


## Breaking changes
Expand Down Expand Up @@ -49,6 +49,7 @@ cut_and_cap.py
volumetric/streamlines1.py
mousehover1.py
mousehover2.py (unstable hovering?)
read_volume3.py interactor lost
```

#### Broken Projects
Expand Down
2 changes: 2 additions & 0 deletions docs/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ for some relevant example.

You can also find online tutorials at:

- [Vedo tutorial for the EMBL Python User Group](https://github.com/marcomusy/vedo-epug-tutorial) with [slides](https://github.com/marcomusy/vedo-epug-tutorial/blob/main/vedo-epug-seminar.pdf) by M. Musy (EMBL).

- [Summer School on Computational Modelling of Multicellular Systems](https://github.com/LauAvinyo/vedo-embo-course) with [slides](https://github.com/LauAvinyo/vedo-embo-course/blob/main/vedo-embo-presentation.pdf) by Laura Avinyo (EMBL).

- Youtube video tutorials by [M. El Amine](https://github.com/amine0110/pycad):
Expand Down
2 changes: 1 addition & 1 deletion docs/examples_db.js
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ vedo_example_db =
imgsrc: 'images/advanced/warp3.png',
},
{
pyname: 'warp4',
pyname: 'warp4a',
kbd : '',
categ : 'advanced',
short : 'interactive morphing',
Expand Down
14 changes: 8 additions & 6 deletions examples/other/madcad2.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
# Example of usage of the madcad library
"""Convert a vedo mesh to a madcad mesh and vice versa"""
# See https://pymadcad.readthedocs.io/en/latest/index.html
import vedo
import numpy as np
import madcad

##########################################################################
mesh = vedo.Mesh(vedo.dataurl+"bunny.obj")
mesh.compute_normals()

############################################################
madcad_mesh = vedo.utils.vedo2madcad(mesh)

madcad.thicken(madcad_mesh, thickness=0.1)
madcad.show([madcad_mesh])


##########################################################################
#############################################################
vedo_mesh = vedo.utils.madcad2vedo(madcad_mesh)

arrs = vedo.Arrows(vedo_mesh.vertices, vedo_mesh.vertices + 0.01 * vedo_mesh.pointdata["Normals"])
vedo.show(mesh, arrs, axes=1).close()
verts = vedo_mesh.vertices
norms = vedo_mesh.pointdata["Normals"]
arrs = vedo.Arrows(verts, verts + 0.005 * norms)
vedo.show(mesh, arrs, __doc__, axes=1).close()
4 changes: 2 additions & 2 deletions examples/pyplot/plot_density3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
vol = pts.density() # density() returns a Volume
vol.cmap('Dark2').alpha([0.1,1])

r = precision(vol.metadata['radius'], 2) # retrieve automatic radius value
vol.add_scalarbar3d(title='Density (counts in r_s ='+r+')', italic=1)
r = precision(vol.metadata['radius'][0], 2) # retrieve automatic radius value
vol.add_scalarbar3d(title=f'Density (counts in r_s ={r})', italic=1)

show(pts, vol, __doc__, axes=True).close()

3 changes: 3 additions & 0 deletions examples/volumetric/tet_threshold.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@
tetm.celldata.select("chem_0").cmap("Accent")
tetm.add_scalarbar3d("chem_0 expression levels", c="k", italic=1)

# Make a 2D clone of the scalarbar and move it to the right:
tetm.scalarbar = tetm.scalarbar.clone2d("center-right", scale=0.2)

show(tetm, __doc__, axes=1).close()
5 changes: 3 additions & 2 deletions examples/volumetric/volume_sharemap.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Share the same color and transparency mapping across different volumes"""
"""Share the same color and transparency
mapping across different volumes"""
from vedo import Volume, show
import numpy as np

Expand All @@ -14,4 +15,4 @@
# or equivalently, to set transparency:
# vol1.alpha([0,1], vmin=0, vmax=70)

show([(vol2, sb, __doc__), vol1], shape=(2,1), axes=1, elevation=-25)
show([(vol2, __doc__), vol1], shape=(2,1), axes=1, elevation=-25)
1 change: 1 addition & 0 deletions tests/pipeline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ cd $VDIR/tests/issues && ./run_all.sh
# TUTORIALS ####################################
cd ~/Projects/server/vedo-embo-course/scripts && ./run_all.sh
cd ~/Projects/server/vedo-bias-course/scripts && ./run_all.sh
cd ~/Projects/server/vedo-epug-course/scripts && ./run_all.sh


# TRIMESH #######################################
Expand Down
2 changes: 1 addition & 1 deletion vedo/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def get_parser():
pr.add_argument("--search-vtk", type=str, help="search examples for the input vtk class", default='', metavar='')
pr.add_argument("--search-code", type=str, help="search keyword in source code", default='', metavar='')
pr.add_argument("--reload", help="reload the file, ignoring any previous download", action="store_true")
pr.add_argument("--info", nargs='*', help="get an info printout of the input file(s)")
pr.add_argument("--info", nargs='*', help="get an info printout of the current installation")
pr.add_argument("--convert", nargs='*', help="input file(s) to be converted")
pr.add_argument("--to", type=str, help="convert to this target format", default='vtk', metavar='')
pr.add_argument("--image", help="image mode for 2d objects", action="store_true")
Expand Down
4 changes: 4 additions & 0 deletions vedo/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ def __setitem__(self, key, input_array):

if len(input_array.shape) == 1: # scalars
data.SetActiveScalars(key)
try: # could be a volume mapper
self.obj.mapper.SetScalarRange(data.GetScalars().GetRange())
except AttributeError:
pass
elif len(input_array.shape) == 2 and input_array.shape[1] == 3: # vectors
if key.lower() == "normals":
data.SetActiveNormals(key)
Expand Down
20 changes: 13 additions & 7 deletions vedo/plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ def __str__(self):
"""Return Plotter info."""
axtype = {
0: "(no axes)",
1: "(customizable grid walls)",
1: "(default customizable grid walls)",
2: "(cartesian axes from origin",
3: "(positive range of cartesian axes from origin",
4: "(axes triad at bottom left)",
Expand Down Expand Up @@ -842,6 +842,8 @@ def __str__(self):

if utils.is_integer(self.axes):
out += "axes style".ljust(14) + f": {self.axes} {axtype[self.axes]}\n"
elif isinstance(self.axes, dict):
out += "axes style".ljust(14) + f": 1 {axtype[1]}\n"
else:
out += "axes style".ljust(14) + f": {[self.axes]}\n"
return out.rstrip() + "\x1b[0m"
Expand Down Expand Up @@ -4050,19 +4052,23 @@ def _keypress(self, iren, event):
self.reset_viewup()

elif key == "w":
if self.clicked_object:
try:
if self.clicked_object.properties.GetRepresentation() == 1: # toggle
self.clicked_object.properties.SetRepresentationToSurface()
else:
self.clicked_object.properties.SetRepresentationToWireframe()
except AttributeError:
pass

elif key == "1":
self._icol += 1
if self.clicked_object:
try:
self._icol += 1
self.clicked_object.mapper.ScalarVisibilityOff()
pal = vedo.colors.palettes[settings.palette % len(vedo.colors.palettes)]
self.clicked_object.c(pal[(self._icol) % 10])
self.remove(self.clicked_object.scalarbar)
except AttributeError:
pass

elif key == "2": # dark colors
bsc = ["k1", "k2", "k3", "k4",
Expand Down Expand Up @@ -4109,7 +4115,7 @@ def _keypress(self, iren, event):
"gist_ncar", "gist_ncar_r",
"viridis", "viridis_r",
"hot", "hot_r",
"terrain","ocean",
"terrain", "ocean",
"coolwarm", "seismic", "PuOr", "RdYlGn",
]
try:
Expand Down Expand Up @@ -4173,7 +4179,7 @@ def _keypress(self, iren, event):
i = 0
if i < 0:
i = len(arrnames) - 1
except ValueError:
except (ValueError, AttributeError):
i = 0

ob.cmap(ob._cmap_name, arrnames[i], on="points")
Expand Down Expand Up @@ -4225,7 +4231,7 @@ def _keypress(self, iren, event):
i = 0
if i < 0:
i = len(arrnames) - 1
except ValueError:
except (ValueError, AttributeError):
i = 0

ob.cmap(ob._cmap_name, arrnames[i], on="cells")
Expand Down
64 changes: 51 additions & 13 deletions vedo/shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,19 +415,10 @@ def __init__(self, p0, p1=None, closed=False, res=2, lw=1, c="k1", alpha=1.0):
p1 = p1.pos()
if isinstance(p0, Points):
p0 = p0.pos()
if isinstance(p0, Points):
p0 = p0.vertices

# try:
# p1 = p1.pos()
# p0 = p0.pos()
# except AttributeError:
# pass

# try:
# p0 = p0.vertices
# except AttributeError:
# pass
try:
p0 = p0.dataset
except AttributeError:
pass

if isinstance(p0, vtk.vtkPolyData):
poly = p0
Expand Down Expand Up @@ -686,6 +677,53 @@ def compute_curvature(self, method=0):
self.cmap("coolwarm", curvs, vmin=vmin, vmax=vmax, name="Curvature")
return self

def plot_scalar(
self,
radius=0,
height=1,
normal=(),
camera=None,
):
"""
Generate a new Line which plots the active scalar along the line.
Arguments:
radius : (float)
distance radius to the line
height: (float)
height of the plot
normal: (list)
normal vector to the plane of the plot
camera: (vtkCamera)
camera object to use for the plot orientation
Example:
```python
from vedo import *
circle = Circle(res=360).rotate_y(20)
pts = circle.vertices
bore = Line(pts).lw(5)
values = np.arctan2(pts[:,1], pts[:,0])
bore.pointdata["scalars"] = values + np.random.randn(360)/5
vap = bore.plot_scalar(radius=0, height=1)
show(bore, vap, axes=1, viewup='z').close()
```
![](https://vedo.embl.es/images/feats/line_plot_scalar.png)
"""
ap = vtk.new("ArcPlotter")
ap.SetInputData(self.dataset)
ap.SetCamera(camera)
ap.SetRadius(radius)
ap.SetHeight(height)
if len(normal)>0:
ap.UseDefaultNormalOn()
ap.SetDefaultNormal(normal)
ap.Update()
vap = Line(ap.GetOutput())
vap.linewidth(3).lighting('off')
vap.name = "ArcPlot"
return vap

def sweep(self, direction=(1, 0, 0), res=1):
"""
Sweep the `Line` along the specified vector direction.
Expand Down
2 changes: 1 addition & 1 deletion vedo/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
_version = '2023.5.0+dev11'
_version = '2023.5.0+dev12'
56 changes: 55 additions & 1 deletion vedo/volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,11 @@ def slab(self, slice_range=(), axis='z', operation="mean"):
operation : (str)
operation to perform on the slab,
allowed values are: "sum", "min", "max", "mean".
Example:
- [slab.py](https://github.com/marcomusy/vedo/blob/master/examples/volumetric/slab_vol.py)
![](https://vedo.embl.es/images/volumetric/slab_vol.jpg)
"""
if len(slice_range) != 2:
vedo.logger.error("in slab(): slice_range is empty or invalid")
Expand Down Expand Up @@ -615,9 +620,13 @@ def apply_transform(self, T, fit=True, interpolation="cubic"):
fit : (bool)
fit/adapt the old bounding box to the modified geometry
interpolation : (str)
one of the following: "linear", "nearest", "cubic"
one of the following: "nearest", "linear", "cubic"
"""
if utils.is_sequence(T):
T = transformations.LinearTransform(T)

TI = T.compute_inverse()

reslice = vtk.new("ImageReslice")
reslice.SetInputData(self.dataset)
reslice.SetResliceTransform(TI.T)
Expand Down Expand Up @@ -725,12 +734,57 @@ def origin(self, s=None):
self.dataset.SetOrigin(s)
return self
return np.array(self.dataset.GetOrigin())

def pos(self, p=None):
"""Set/get the position of the volumetric dataset."""
if p is not None:
self.origin(p)
return self
return self.origin()

def center(self):
"""Get the center of the volumetric dataset."""
# note that this does not have the set method like origin and spacing
return np.array(self.dataset.GetCenter())

def shift(self, s):
"""Shift the volumetric dataset by a vector."""
self.origin(self.origin() + np.array(s))
return self

def rotate_x(self, angle, rad=False, around=None):
"""
Rotate around x-axis. If angle is in radians set `rad=True`.
Use `around` to define a pivoting point.
"""
if angle == 0:
return self
LT = transformations.LinearTransform().rotate_x(angle, rad, around)
return self.apply_transform(LT, fit=True, interpolation="linear")

def rotate_y(self, angle, rad=False, around=None):
"""
Rotate around y-axis. If angle is in radians set `rad=True`.
Use `around` to define a pivoting point.
"""
if angle == 0:
return self
LT = transformations.LinearTransform().rotate_y(angle, rad, around)
return self.apply_transform(LT, fit=True, interpolation="linear")

def rotate_z(self, angle, rad=False, around=None):
"""
Rotate around z-axis. If angle is in radians set `rad=True`.
Use `around` to define a pivoting point.
"""
if angle == 0:
return self
LT = transformations.LinearTransform().rotate_z(angle, rad, around)
return self.apply_transform(LT, fit=True, interpolation="linear")

def get_cell_from_ijk(self, ijk):
"""
Get the voxel id number at the given ijk coordinates.
Expand Down
1 change: 1 addition & 0 deletions vedo/vtkclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@
)
for name in [
"vtkAnnotatedCubeActor",
"vtkArcPlotter",
"vtkAxesActor",
"vtkAxisActor2D",
"vtkCaptionActor2D",
Expand Down

0 comments on commit ed3388c

Please sign in to comment.