From 2cfae017f93820cee43c5848e4ca3e59bd49612c Mon Sep 17 00:00:00 2001 From: mirjagranfors Date: Wed, 30 Jul 2025 09:25:06 +0200 Subject: [PATCH 1/8] formatting --- deeptrack/features.py | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/deeptrack/features.py b/deeptrack/features.py index a4bf2c709..b4513f3ef 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -387,7 +387,18 @@ 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: ( + np.ndarray + | list[np.ndarray] + | Image + | list[Image] + | None + ) = None, + resolve_kwargs: dict | None = None, + interval: float | None = None, + **kwargs: Any, + ) -> Any` It visualizes the output of the feature. **Private and internal methods.** @@ -1754,37 +1765,39 @@ def bind_arguments( return self - #TODO ***MG*** def plot( self: Feature, - input_image: np.ndarray | list[np.ndarray] | Image | list[Image] = None, + input_image: ( + np.ndarray | list[np.ndarray] | Image | list[Image] + ) = None, resolve_kwargs: dict = None, interval: float = None, **kwargs: Any, ) -> Any: """Visualizes 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 - matplotlib backend. + 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 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. + 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 @@ -1814,7 +1827,9 @@ def plot( 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 From 719eb37a54cb73ab6eb8e26c0dfa4f3b9b1f4c3d Mon Sep 17 00:00:00 2001 From: mirjagranfors Date: Wed, 30 Jul 2025 10:00:56 +0200 Subject: [PATCH 2/8] added examples --- deeptrack/features.py | 54 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/deeptrack/features.py b/deeptrack/features.py index b4513f3ef..029562051 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -389,11 +389,12 @@ class Feature(DeepTrackNode): It binds another feature’s properties as arguments to this feature. `plot( input_image: ( - np.ndarray - | list[np.ndarray] + NDArray + | list[NDArray] + | torch.Tensor + | list[torch.Tensor] | Image | list[Image] - | None ) = None, resolve_kwargs: dict | None = None, interval: float | None = None, @@ -1768,25 +1769,32 @@ def bind_arguments( def plot( self: Feature, input_image: ( - np.ndarray | list[np.ndarray] | Image | list[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 matplotlib backend. + 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 + 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. @@ -1802,6 +1810,32 @@ def plot( ------- Any The output of the feature or pipeline after execution. + + Examples + -------- + >>> import deeptrack as dt + >>> import numpy as np + + Create a dummy feature that returns the image: + >>> class DummyFeature(dt.Feature): + ... def resolve(self, input_image): + ... return input_image + + Create an instance of the dummy feature: + >>> feature = DummyFeature() + + Generate and plot a dummy grayscale image: + >>> img = np.random.randint(0, 256, (64, 64)) + >>> feature.plot(img, cmap='gray'); + + Generate and plot a dummy grayscale video: + >>> video = [np.random.randint(0, 256, (64, 64)) for _ in range(10)] + >>> feature.plot(video, interval=100, cmap='gray'); + + Generate a dummy grayscale image using torch and plot it: + >>> import torch + >>> img = torch.randint(0, 256, size=(64, 64)) + >>> feature.plot(img, cmap='gray'); """ From 45f3ec8d64e53488831d4afa0dd0180991c67b71 Mon Sep 17 00:00:00 2001 From: mirjagranfors Date: Wed, 30 Jul 2025 10:26:20 +0200 Subject: [PATCH 3/8] minor changes --- deeptrack/features.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/deeptrack/features.py b/deeptrack/features.py index 029562051..34dff3a4b 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -1816,23 +1816,18 @@ def plot( >>> import deeptrack as dt >>> import numpy as np - Create a dummy feature that returns the image: - >>> class DummyFeature(dt.Feature): - ... def resolve(self, input_image): - ... return input_image + Create an instance of a dummy feature that returns the image: + >>> feature = dt.DummyFeature() - Create an instance of the dummy feature: - >>> feature = DummyFeature() - - Generate and plot a dummy grayscale image: + Generate and plot a grayscale image: >>> img = np.random.randint(0, 256, (64, 64)) >>> feature.plot(img, cmap='gray'); - Generate and plot a dummy grayscale video: + 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 dummy grayscale image using torch and plot it: + Generate a grayscale image using torch and plot it: >>> import torch >>> img = torch.randint(0, 256, size=(64, 64)) >>> feature.plot(img, cmap='gray'); From b4a6818e6ccac68a1e86a1808213a791edd15147 Mon Sep 17 00:00:00 2001 From: mirjagranfors Date: Wed, 30 Jul 2025 10:29:43 +0200 Subject: [PATCH 4/8] update of example --- deeptrack/features.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deeptrack/features.py b/deeptrack/features.py index 34dff3a4b..882d0ca64 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -1816,7 +1816,7 @@ def plot( >>> import deeptrack as dt >>> import numpy as np - Create an instance of a dummy feature that returns the image: + Create an instance of a dummy feature that returns the input: >>> feature = dt.DummyFeature() Generate and plot a grayscale image: From 9cc08214753dd8c31830034919e25693980a7581 Mon Sep 17 00:00:00 2001 From: mirjagranfors Date: Wed, 30 Jul 2025 14:53:00 +0200 Subject: [PATCH 5/8] Added one more example --- deeptrack/features.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/deeptrack/features.py b/deeptrack/features.py index 882d0ca64..1db0699a3 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -1832,6 +1832,13 @@ def plot( >>> 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'); + """ from IPython.display import HTML, display From 1dcf316dbae37ab6b0f31a21587b5bf565203e62 Mon Sep 17 00:00:00 2001 From: mirjagranfors Date: Thu, 7 Aug 2025 17:49:38 +0200 Subject: [PATCH 6/8] update features_plot --- deeptrack/features.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deeptrack/features.py b/deeptrack/features.py index 1db0699a3..697902e0f 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -1851,6 +1851,7 @@ def plot( # 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() @@ -1859,6 +1860,7 @@ def plot( images = [] plt.axis("off") for image in output_image: + image = xp.squeeze(image) images.append([plt.imshow(image, **kwargs)]) if not interval: From 7677ea678c26c1eb07250f4c25af98a60af95251 Mon Sep 17 00:00:00 2001 From: mirjagranfors Date: Mon, 11 Aug 2025 18:23:27 +0200 Subject: [PATCH 7/8] update plot() --- deeptrack/features.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/deeptrack/features.py b/deeptrack/features.py index 697902e0f..f0bd23408 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -1814,38 +1814,37 @@ def plot( Examples -------- >>> import deeptrack as dt - >>> import numpy as np 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'); + >>> 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'); + >>> 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'); + >>> 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'); + >>> imaged_particle.plot(cmap="gray"); """ 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 From ded72bd0300e84911198e60f875a5be890715d25 Mon Sep 17 00:00:00 2001 From: mirjagranfors Date: Mon, 8 Sep 2025 09:41:09 +0200 Subject: [PATCH 8/8] update plot --- deeptrack/features.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/deeptrack/features.py b/deeptrack/features.py index f0bd23408..360bfa82c 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -1782,12 +1782,12 @@ def plot( ) -> Any: """Visualize the output of the feature. - This method 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. + `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`.