Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 13 additions & 42 deletions examples/head_models/41_photogrammetric_optode_coregistration.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -345,11 +345,11 @@
"\n",
"### 5.1. Pick positions in interactive plot\n",
"\n",
"When using the `plot_surface` function with parameter `pick_landmarks` set to *True*, the plot becomes interactive and allows to pick the positions of 5 landmarks. These are \"Nz\", \"Iz\", \"Cz\", \"Lpa\", \"RpA\".\n",
"When using the `plot_surface` function with parameter `pick_landmarks` set to *True*, the plot becomes interactive and allows picking the positions of 5 landmarks. These are \"Nz\", \"Iz\", \"Cz\", \"Lpa\", \"RpA\". If other landmarks need to be picked, pass their labels as a list to `pick_landmarks` (instead of passing *True*).\n",
"\n",
"After clicking on the mesh, a green sphere marks the picked location. The sphere has a label attached. If this label is not visible, try to zoom further into the plot (mouse wheel). By clicking again with right mouse button on the sphere one can cycle through the different labels or remove a misplaced landmark.\n",
"\n",
"It halps to add colored markers at the landmark positions when preparing the subject. Here green stickers where used."
"It helps to add colored markers at the landmark positions when preparing the subject. Here, green stickers were used."
]
},
{
Expand Down Expand Up @@ -385,7 +385,7 @@
"outputs": [],
"source": [
"if INTERACTIVE:\n",
" landmark_coordinates, landmark_labels = get_landmarks()\n",
" landmarks = get_landmarks()\n",
"else:\n",
" # For documentation purposes and to enable automatically rendered example notebooks\n",
" # we provide the hand-picked coordinates here, too.\n",
Expand All @@ -400,45 +400,16 @@
" ]\n",
" )\n",
"\n",
"display(landmark_labels)\n",
"display(landmark_coordinates)\n",
"\n",
"assert len(set(landmark_labels)) == 5, \"please select 5 landmarks\"\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "27",
"metadata": {},
"source": [
"### 5.3 Wrap landmark positions and labels in a xarray.DataArray structure\n",
"\n",
"* insert *landmark_coordinates* and *landmark_labels*"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "28",
"metadata": {},
"outputs": [],
"source": [
"coordinates = landmark_coordinates\n",
"labels = landmark_labels\n",
"\n",
"types = [cdc.PointType.LANDMARK] * 5\n",
"groups = [\"L\"] * 5\n",
"\n",
"landmarks = xr.DataArray(\n",
" np.vstack(coordinates),\n",
" dims=[\"label\", \"digitized\"],\n",
" coords={\n",
" \"label\": (\"label\", labels),\n",
" \"type\": (\"label\", types),\n",
" \"group\": (\"label\", groups),\n",
" },\n",
").pint.quantify(\"mm\")\n",
" # Wrap landmark positions and labels in a xarray.DataArray structure\n",
" landmarks = xr.DataArray(\n",
" np.vstack(landmark_coordinates),\n",
" dims=[\"label\", \"digitized\"],\n",
" coords={\n",
" \"label\": (\"label\", landmark_labels),\n",
" \"type\": (\"label\", [cdc.PointType.LANDMARK] * 5),\n",
" \"group\": (\"label\", [\"L\"] * 5),\n",
" },\n",
" ).pint.quantify(\"mm\")\n",
"\n",
"display(landmarks)"
]
Expand Down
17 changes: 2 additions & 15 deletions examples/misc/finger_tapping_full_pipeline.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -299,20 +299,7 @@
"import tkinter as tk\n",
"from tkinter import messagebox\n",
"\n",
"landmark_coordinates, landmark_labels = get_landmarks()\n",
"\n",
"# write into Xarray\n",
"landmarks = xr.DataArray(\n",
" np.vstack(landmark_coordinates),\n",
" dims=[\"label\", \"digitized\"],\n",
" coords={\n",
" \"label\": (\"label\", landmark_labels),\n",
" \"type\": (\"label\", [cdc.PointType.LANDMARK]*5),\n",
" \"group\": (\"label\", [\"L\"]*5),\n",
" },\n",
").pint.quantify(\"mm\")\n",
"\n",
"\n",
"landmarks = get_landmarks()\n",
"display(landmarks)"
]
},
Expand Down Expand Up @@ -1022,5 +1009,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}
14 changes: 8 additions & 6 deletions examples/plots_visualization/12_plots_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@
"metadata": {},
"source": [
"## Interactive 3D Plot to select Landmarks\n",
"using **plot_surface** with \"pick_landmarks = True\". Here we use a photogrammetric scan, and the landmarks are indicated by green dots. Right-clicking again on an existing landmark changes the label."
"using **plot_surface** with `pick_landmarks = ['Nz', 'Iz', 'Cz', 'Lpa', 'Rpa']`. Here we use a photogrammetric scan, and the landmarks are indicated by green dots. Right-clicking again on an existing landmark changes the label."
]
},
{
Expand All @@ -359,7 +359,7 @@
"import cedalion.plots\n",
"\n",
"plt = pv.Plotter()\n",
"get_landmarks = cedalion.plots.plot_surface(plt, pscan, opacity=1.0, pick_landmarks = True)\n",
"get_landmarks = cedalion.plots.plot_surface(plt, pscan, opacity=1.0, pick_landmarks = ['Nz', 'Iz', 'Cz', 'Lpa', 'Rpa'])\n",
"plt.show(interactive = True)"
]
},
Expand All @@ -377,9 +377,11 @@
" np.array([82.8771277, 79.79500128, 498.3338802]),\n",
" np.array([15.17214095, -60.56186128, 563.29621021])]\n",
"\n",
"# uncommentif you want to see your own picked results: when you are done run get_landmarks() to get the landmarks. \n",
"# landmark_coordinates, landmark_labels = get_landmarks()\n",
"display (landmark_labels)"
"# Uncomment the following lines if you want to see your own picked results. When you are done, run' get_landmarks() ' to retrieve the landmarks. \n",
"#landmarks = get_landmarks()\n",
"#landmark_labels = landmarks.label.values\n",
"#landmark_coordinates = landmarks.values\n",
"display(landmark_labels)"
]
},
{
Expand Down Expand Up @@ -663,5 +665,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}
44 changes: 29 additions & 15 deletions src/cedalion/plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def plot_surface(
surface: cdc.Surface,
color: pv.ColorLike | None = None,
opacity : float =1.0,
pick_landmarks : bool = False,
pick_landmarks : list[str] | bool = False,
**kwargs,
):
#used for picking landmarks in photogrammetry example
Expand All @@ -168,8 +168,9 @@ def plot_surface(
color: Color of the mesh.
opacity: Opacity of the mesh, ranging from 0 (transparent) to 1
(opaque). Default is 1.0.
pick_landmarks: If True, enables interactive picking of landmarks on the
surface. Default is False.
pick_landmarks: If True, enables interactive picking of landmarks
('Nz', 'Iz', 'Cz', 'Lpa', 'Rpa') on the surface. If a list of strings is
provided, these are used as the landmark labels instead. Default is False.
**kwargs: Additional keyword arguments are passed to pv.add_mesh.

Returns:
Expand All @@ -181,7 +182,6 @@ def plot_surface(
- Eike Middell | [email protected] | 2024
- Masha Iudina | [email protected] | 2024
"""

if isinstance(surface, cdc.VTKSurface):
mesh = surface.mesh
elif isinstance(surface, cdc.TrimeshSurface):
Expand All @@ -208,7 +208,11 @@ def plot_surface(


# Define landmark labels
landmark_labels = ['Nz', 'Iz', 'Cz', 'Lpa', 'Rpa']
if isinstance(pick_landmarks, bool):
landmark_labels = ['Nz', 'Iz', 'Cz', 'Lpa', 'Rpa']
else:
landmark_labels = pick_landmarks
pick_landmarks = True
picked_points = []
labels = []
point_actors = []
Expand Down Expand Up @@ -247,10 +251,10 @@ def place_landmark(point):

# If no point is close enough, create a new point and assign a label
# Check if there are already 5 points placed
if len(picked_points) >= 5:
if len(picked_points) >= len(landmark_labels):
return

landmark_label = landmark_labels[0]
landmark_label = landmark_labels[(len(picked_points) % len(landmark_labels))]
# Add new point and label actors
point_actor = plotter.add_mesh(pv.Sphere(radius=3, center=new_point),
color='green', smooth_shading=True)
Expand All @@ -262,25 +266,35 @@ def place_landmark(point):
picked_points.append(new_point)
labels.append(landmark_label)

# Initialize the labels list
# labels = [None] * 5 # Initialize with None for unassigned labels

if pick_landmarks is True:
def get_points_and_labels():

if len(labels) < 5:
if len(labels) < len(landmark_labels):
print("Warning: Some labels are missing")
elif len(set(labels)) != 5:
elif len(set(labels)) != len(landmark_labels):
print("Warning: Some labels are repeated!")
return picked_points, labels

landmarks = xr.DataArray(
np.vstack(picked_points),
dims=["label", "digitized"],
coords={
"label": ("label", labels),
"type": ("label", [cdc.PointType.LANDMARK]*len(labels)),
"group": ("label", ["L"]*len(labels)),
},
).pint.quantify("mm")
return landmarks


plotter.enable_surface_point_picking(
callback=place_landmark,
show_message="Right click to place or change the landmark label",
show_message="Right click to place or change the landmark label.\n"\
"Expected labels: "+str(landmark_labels)+"\n"\
"Close window when done.",
show_point=False,
tolerance=0.005,
)

return get_points_and_labels

def plot_labeled_points(
Expand Down
Loading