Skip to content
Merged
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
88 changes: 70 additions & 18 deletions deeptrack/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,19 @@ class Feature(DeepTrackNode):
behavior.
`bind_arguments(arguments: Feature) -> Feature`
It binds another feature’s properties as arguments to this feature.
`plot(input_image: np.ndarray | list[np.ndarray] | Image | list[Image] | None = None, resolve_kwargs: dict | None = None, interval: float | None = None, **kwargs: Any) -> Any`
`plot(
input_image: (
NDArray
| list[NDArray]
| torch.Tensor
| list[torch.Tensor]
| Image
| list[Image]
) = None,
resolve_kwargs: dict | None = None,
interval: float | None = None,
**kwargs: Any,
) -> Any`
It visualizes the output of the feature.

**Private and internal methods.**
Expand Down Expand Up @@ -1754,54 +1766,91 @@ def bind_arguments(

return self

#TODO ***MG***
def plot(
self: Feature,
input_image: np.ndarray | list[np.ndarray] | Image | list[Image] = None,
input_image: (
NDArray
| list[NDArray]
| torch.Tensor
| list[torch.Tensor]
| Image
| list[Image]
) = None,
resolve_kwargs: dict = None,
interval: float = None,
**kwargs: Any,
) -> Any:
"""Visualizes the output of the feature.
"""Visualize the output of the feature.

This method resolves the feature and visualizes the result. If the output is
an `Image`, it displays it using `pyplot.imshow`. If the output is a list, it
creates an animation. In Jupyter notebooks, the animation is played inline
using `to_jshtml()`. In scripts, the animation is displayed using the
`plot()` resolves the feature and visualizes the result. If the output
is a single image (NumPy array, PyTorch tensor, or Image), it is
displayed using `pyplot.imshow`. If the output is a list, an animation
is created. In Jupyter notebooks, the animation is played inline using
`to_jshtml()`. In scripts, the animation is displayed using the
matplotlib backend.

Any parameters in `kwargs` are passed to `pyplot.imshow`.

Parameters
----------
input_image: np.ndarray or Image or list[np.ndarray or Image], optional
The input image or list of images passed as an argument to the `resolve`
call. If `None`, uses previously set input values or propagates properties.
input_image: np.ndarray, torch.tensor, or Image or list[np.ndarray,
torch.tensor, or Image], optional
The input image or list of images passed as an argument to the
`resolve` call. If `None`, uses previously set input values or
propagates properties.
resolve_kwargs: dict, optional
Additional keyword arguments passed to the `resolve` call.
interval: float, optional
The time between frames in the animation, in milliseconds. The default
value is 33 ms.
The time between frames in the animation, in milliseconds. The
default value is 33 ms.
**kwargs: dict, optional
Additional keyword arguments passed to `pyplot.imshow`.

Returns
-------
Any
The output of the feature or pipeline after execution.

Examples
--------
>>> import deeptrack as dt

Create an instance of a dummy feature that returns the input:
>>> feature = dt.DummyFeature()

Generate and plot a grayscale image:
>>> import numpy as np
>>>
>>> img = np.random.randint(0, 256, (64, 64))
>>> feature.plot(img, cmap="gray");

Generate and plot a grayscale video:
>>> video = [np.random.randint(0, 256, (64, 64)) for _ in range(10)]
>>> feature.plot(video, interval=100, cmap="gray");

Generate a grayscale image using torch and plot it:
>>> import torch
>>>
>>> img = torch.randint(0, 256, size=(64, 64))
>>> feature.plot(img, cmap="gray");

Generate a simulated image of a point particle visualized using
brightfield microscopy and plot it:
>>> particle = dt.PointParticle()
>>> optics = dt.Brightfield()
>>> imaged_particle = optics(particle)
>>> imaged_particle.plot(cmap="gray");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A more advanced example of the usage that I think should be included would be to plot a sphere resolved in brightfield, something like:

>>> particle = dt.Sphere()
>>> optics = dt.Brightfield()
>>> imaged_particle = optics(particle)
>>> imaged_particle.plot()

"""

from IPython.display import HTML, display

# if input_image is not None:
# input_image = [Image(input_image)]

output_image = self.resolve(input_image, **(resolve_kwargs or {}))

# If a list, assume video
if not isinstance(output_image, list):
# Single image
output_image = xp.squeeze(output_image)
plt.imshow(output_image, **kwargs)
return plt.gca()

Expand All @@ -1810,11 +1859,14 @@ def plot(
images = []
plt.axis("off")
for image in output_image:
image = xp.squeeze(image)
images.append([plt.imshow(image, **kwargs)])

if not interval:
if isinstance(output_image[0], Image):
interval = output_image[0].get_property("interval") or (1 / 30 * 1000)
interval = (
output_image[0].get_property("interval") or (1 / 30 * 1000)
)
else:
interval = 1 / 30 * 1000

Expand Down
Loading