def annotate3d(centroids, image, **kwargs): """ An extension of annotate that annotates a 3D image and returns a scrollable stack for display in IPython. Parameters: see annotate. """ if plots_to_frame is None: raise ImportError('annotate3d requires pims 0.3 or later, please ' 'update pims') import matplotlib as mpl import matplotlib.pyplot as plt if image.ndim != 3 and not (image.ndim == 4 and image.shape[-1] in (3, 4)): raise ValueError("image has incorrect dimensions. Please input a 3D " "grayscale or RGB(A) image. For 2D image annotation, " "use annotate. Multichannel images can be " "converted to RGB using pims.display.to_rgb.") # We want to normalize on the full image and stop imshow from normalizing. normalized = (normalize(image) * 255).astype(np.uint8) imshow_style = dict(vmin=0, vmax=255) if '_imshow_style' in kwargs: kwargs['imshow_style'].update(imshow_style) else: kwargs['imshow_style'] = imshow_style # Suppress warning when >20 figures are opened max_open_warning = mpl.rcParams['figure.max_open_warning'] mpl.rc('figure', max_open_warning=0) figures = [] for i, imageZ in enumerate(normalized): fig = plt.figure() kwargs['ax'] = fig.gca() centroidsZ = centroids[(centroids['z'] > i - 0.5) & (centroids['z'] < i + 0.5)] annotate(centroidsZ, imageZ, **kwargs) figures.append(fig) result = plots_to_frame(figures, width=512, bbox_inches='tight') for fig in figures: plt.close(fig) mpl.rc('figure', max_open_warning=max_open_warning) return result
def annotate3d(centroids, image, **kwargs): """Annotates a 3D image and returns a scrollable stack for display in IPython. Parameters ---------- centroids : DataFrame including columns x and y image : image array (or string path to image file) circle_size : Deprecated. This will be removed in a future version of trackpy. Use `plot_style={'markersize': ...}` instead. color : single matplotlib color or a list of multiple colors default None invert : If you give a filepath as the image, specify whether to invert black and white. Default True. ax : matplotlib axes object, defaults to current axes split_category : string, parameter to use to split the data into sections default None split_thresh : single value or list of ints or floats to split particles into sections for plotting in multiple colors. List items should be ordered by increasing value. default None imshow_style : dictionary of keyword arguments passed through to the `Axes.imshow(...)` command the displays the image plot_style : dictionary of keyword arguments passed through to the `Axes.plot(...)` command that marks the features Returns ------- pims.Frame object containing a three-dimensional RGBA image See Also -------- annotate : annotation of 2D images """ if plots_to_frame is None: raise ImportError('annotate3d requires pims 0.3 or later. Please ' 'install/update pims') import matplotlib as mpl import matplotlib.pyplot as plt if image.ndim != 3 and not (image.ndim == 4 and image.shape[-1] in (3, 4)): raise ValueError("image has incorrect dimensions. Please input a 3D " "grayscale or RGB(A) image. For 2D image annotation, " "use annotate. Multichannel images can be " "converted to RGB using pims.display.to_rgb.") # We want to normalize on the full image and stop imshow from normalizing. normalized = (normalize(image) * 255).astype(np.uint8) imshow_style = dict(vmin=0, vmax=255) if '_imshow_style' in kwargs: kwargs['imshow_style'].update(imshow_style) else: kwargs['imshow_style'] = imshow_style max_open_warning = mpl.rcParams['figure.max_open_warning'] was_interactive = plt.isinteractive() try: # Suppress warning when many figures are opened mpl.rc('figure', max_open_warning=0) # Turn off interactive mode (else the closed plots leave emtpy space) plt.ioff() figures = [None] * len(normalized) for i, imageZ in enumerate(normalized): fig = plt.figure() kwargs['ax'] = fig.gca() centroidsZ = centroids[(centroids['z'] > i - 0.5) & (centroids['z'] < i + 0.5)] annotate(centroidsZ, imageZ, **kwargs) figures[i] = fig result = plots_to_frame(figures, width=512, close_fig=True, bbox_inches='tight') finally: # put matplotlib back in original state if was_interactive: plt.ion() mpl.rc('figure', max_open_warning=max_open_warning) return result
def annotate3d(centroids, image, **kwargs): """Annotates a 3D image and returns a scrollable stack for display in IPython. Parameters ---------- centroids : DataFrame including columns x and y image : image array (or string path to image file) circle_size : Deprecated. This will be removed in a future version of trackpy. Use `plot_style={'markersize': ...}` instead. color : single matplotlib color or a list of multiple colors default None invert : If you give a filepath as the image, specify whether to invert black and white. Default True. ax : matplotlib axes object, defaults to current axes split_category : string, parameter to use to split the data into sections default None split_thresh : single value or list of ints or floats to split particles into sections for plotting in multiple colors. List items should be ordered by increasing value. default None imshow_style : dictionary of keyword arguments passed through to the `Axes.imshow(...)` command the displays the image plot_style : dictionary of keyword arguments passed through to the `Axes.plot(...)` command that marks the features Returns ------- pims.Frame object containing a three-dimensional RGBA image See Also -------- annotate : annotation of 2D images """ if plots_to_frame is None: raise ImportError('annotate3d requires pims 0.3 or later, please ' 'update pims') import matplotlib as mpl import matplotlib.pyplot as plt if image.ndim != 3 and not (image.ndim == 4 and image.shape[-1] in (3, 4)): raise ValueError("image has incorrect dimensions. Please input a 3D " "grayscale or RGB(A) image. For 2D image annotation, " "use annotate. Multichannel images can be " "converted to RGB using pims.display.to_rgb.") # We want to normalize on the full image and stop imshow from normalizing. normalized = (normalize(image) * 255).astype(np.uint8) imshow_style = dict(vmin=0, vmax=255) if '_imshow_style' in kwargs: kwargs['imshow_style'].update(imshow_style) else: kwargs['imshow_style'] = imshow_style max_open_warning = mpl.rcParams['figure.max_open_warning'] was_interactive = plt.isinteractive() try: # Suppress warning when many figures are opened mpl.rc('figure', max_open_warning=0) # Turn off interactive mode (else the closed plots leave emtpy space) plt.ioff() figures = [None] * len(normalized) for i, imageZ in enumerate(normalized): fig = plt.figure() kwargs['ax'] = fig.gca() centroidsZ = centroids[(centroids['z'] > i - 0.5) & (centroids['z'] < i + 0.5)] annotate(centroidsZ, imageZ, **kwargs) figures[i] = fig result = plots_to_frame(figures, width=512, close_fig=True, bbox_inches='tight') finally: # put matplotlib back in original state if was_interactive: plt.ion() mpl.rc('figure', max_open_warning=max_open_warning) return result
def test_plots_from_generator(self): frame = plots_to_frame(iter(self.figures)) assert_equal(frame.shape, (10, 384, 512, 4))
def test_plots_width(self): width = np.random.randint(100, 1000) frame = plots_to_frame(self.figures, width) assert_equal(frame.shape[2], width)
def test_plots_resize(self): frame = plots_to_frame(self.figures, fig_size_inches=(4, 4)) assert_equal(frame.shape, (10, 512, 512, 4))
def test_plots_tight(self): frame = plots_to_frame(self.figures, bbox_inches='tight') assert_equal(frame.shape, (10, 384, 512, 4))
def test_plots_to_frame(self): frame = plots_to_frame(self.figures) assert_equal(frame.shape, (10, 384, 512, 4))
def test_plots_tight(self): frame = plots_to_frame(self.figures, bbox_inches='tight') assert_less(frame.shape[1:3], (384, 512))
def test_axes_to_frame(self): frame = plots_to_frame(self.axes) self.assertEqual(frame.shape, (10, 384, 512, 4))