Skip to content

napari_ndev.image_overview #

Function and class to create and manage image overviews with stackview.

It includes a function image_overview to generate an overview of images and a class ImageOverview to generate and save image overviews.

ImageOverview #

A class for generating and saving image overviews.

Use this class to prevent a memory leak otherwise generated by the image_overview() function when show=True. For some reason, preventing the memory leak requires the use of a class instead of a function, and show=False.

Source code in src/napari_ndev/image_overview.py
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
class ImageOverview:
    """
    A class for generating and saving image overviews.

    Use this class to prevent a memory leak otherwise generated by the
    image_overview() function when show=True. For some reason, preventing
    the memory leak requires the use of a class instead of a function, and
    show=False.
    """

    def __init__(
        self,
        image_sets: ImageSet | list[ImageSet] | dict | list[dict],
        fig_scale: tuple[float, float] = (3, 3),
        fig_title: str = '',
        scalebar: float | dict | None = None,
        show: bool = False,
    ):
        """
        Initialize an ImageOverivew object.

        Parameters
        ----------
        image_sets : ImageSet, list of ImageSet, dict, or list of dict
            A list of dictionaries, each containing an image set. Each image set
            should be a dictionary containing the following keys:
            - image (list): A list of images to display.
            - title (list of str, optional): The title of the image set.
            - colormap (list of str, optional): The colormap to use.
                "labels" will display the image as labels.
            - labels (list of bool, optional): Whether to display labels.
            - **kwargs: Additional keyword arguments to pass to stackview.imshow.
        fig_scale : tuple of float, optional
            The scale of the plot. (Width, Height). Values lower than 2 are likely
            to result in overlapping text. Increased values increase image size.
            Defaults to (3, 3).
        fig_title : str, optional
            The title of the image overview. Default is an empty string.
        scalebar : float or dict, optional
            The scalebar to add to the image overview. If a float, it is used as
            the dx parameter for the scalebar. If a dict, all **kwargs are passed
            to the matplotlib_scalebar.scalebar.ScaleBar class. Defaults to None.
        show : bool, optional
            Whether to display the generated overview. Default is False.
            Prevents memory leak when False.

        """
        plt.ioff()
        self.fig = image_overview(image_sets, fig_scale, fig_title, scalebar)
        if show:
            plt.show()
        plt.close()

    def save(
        self,
        directory: str | None = None,
        filename: str | None = None,
    ):
        """
        Save the generated image overview with matplotlib.savefig.

        Parameters
        ----------
        directory : str, optional
            The directory to save the image overview. If not provided, the
            current directory will be used.
        filename : str, optional
            The filename of the saved image overview. If not provided, a
            default filename will be used.

        """
        import pathlib

        path_dir = pathlib.Path(directory)
        path_dir.mkdir(parents=True, exist_ok=True)
        filepath = path_dir / filename
        self.fig.savefig(filepath)

__init__ #

__init__(image_sets, fig_scale=(3, 3), fig_title='', scalebar=None, show=False)

Initialize an ImageOverivew object.

Parameters:

  • image_sets #

    (ImageSet, list of ImageSet, dict, or list of dict) –

    A list of dictionaries, each containing an image set. Each image set should be a dictionary containing the following keys: - image (list): A list of images to display. - title (list of str, optional): The title of the image set. - colormap (list of str, optional): The colormap to use. "labels" will display the image as labels. - labels (list of bool, optional): Whether to display labels. - **kwargs: Additional keyword arguments to pass to stackview.imshow.

  • fig_scale #

    (tuple of float, default: (3, 3) ) –

    The scale of the plot. (Width, Height). Values lower than 2 are likely to result in overlapping text. Increased values increase image size. Defaults to (3, 3).

  • fig_title #

    (str, default: '' ) –

    The title of the image overview. Default is an empty string.

  • scalebar #

    (float or dict, default: None ) –

    The scalebar to add to the image overview. If a float, it is used as the dx parameter for the scalebar. If a dict, all **kwargs are passed to the matplotlib_scalebar.scalebar.ScaleBar class. Defaults to None.

  • show #

    (bool, default: False ) –

    Whether to display the generated overview. Default is False. Prevents memory leak when False.

Source code in src/napari_ndev/image_overview.py
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
def __init__(
    self,
    image_sets: ImageSet | list[ImageSet] | dict | list[dict],
    fig_scale: tuple[float, float] = (3, 3),
    fig_title: str = '',
    scalebar: float | dict | None = None,
    show: bool = False,
):
    """
    Initialize an ImageOverivew object.

    Parameters
    ----------
    image_sets : ImageSet, list of ImageSet, dict, or list of dict
        A list of dictionaries, each containing an image set. Each image set
        should be a dictionary containing the following keys:
        - image (list): A list of images to display.
        - title (list of str, optional): The title of the image set.
        - colormap (list of str, optional): The colormap to use.
            "labels" will display the image as labels.
        - labels (list of bool, optional): Whether to display labels.
        - **kwargs: Additional keyword arguments to pass to stackview.imshow.
    fig_scale : tuple of float, optional
        The scale of the plot. (Width, Height). Values lower than 2 are likely
        to result in overlapping text. Increased values increase image size.
        Defaults to (3, 3).
    fig_title : str, optional
        The title of the image overview. Default is an empty string.
    scalebar : float or dict, optional
        The scalebar to add to the image overview. If a float, it is used as
        the dx parameter for the scalebar. If a dict, all **kwargs are passed
        to the matplotlib_scalebar.scalebar.ScaleBar class. Defaults to None.
    show : bool, optional
        Whether to display the generated overview. Default is False.
        Prevents memory leak when False.

    """
    plt.ioff()
    self.fig = image_overview(image_sets, fig_scale, fig_title, scalebar)
    if show:
        plt.show()
    plt.close()

save #

save(directory=None, filename=None)

Save the generated image overview with matplotlib.savefig.

Parameters:

  • directory #

    (str, default: None ) –

    The directory to save the image overview. If not provided, the current directory will be used.

  • filename #

    (str, default: None ) –

    The filename of the saved image overview. If not provided, a default filename will be used.

Source code in src/napari_ndev/image_overview.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
def save(
    self,
    directory: str | None = None,
    filename: str | None = None,
):
    """
    Save the generated image overview with matplotlib.savefig.

    Parameters
    ----------
    directory : str, optional
        The directory to save the image overview. If not provided, the
        current directory will be used.
    filename : str, optional
        The filename of the saved image overview. If not provided, a
        default filename will be used.

    """
    import pathlib

    path_dir = pathlib.Path(directory)
    path_dir.mkdir(parents=True, exist_ok=True)
    filepath = path_dir / filename
    self.fig.savefig(filepath)

ImageSet dataclass #

Image information passed to stackview.imshow.

Parameters:

  • image #

    (list) –

    A list of image data to display.

  • title #

    (list of str, default: None ) –

    The title of the image.

  • colormap #

    (list of str, default: None ) –

    The colormap to use. "labels" will display the image as labels.

  • labels #

    (list of bool, default: None ) –

    Whether to display image as a labels.

  • min_display_intensity #

    (list of float, default: None ) –

    The minimum display intensity, in the same units as the image. Use np.percentile(image, 0.1) for 0.1th percentile.

  • max_display_intensity #

    (list of float, default: None ) –

    The maximum display intensity, in the same units as the image. Use np.percentile(image, 99.8) for 99.9th percentile.

Source code in src/napari_ndev/image_overview.py
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@dataclass
class ImageSet:
    """
    Image information passed to `stackview.imshow`.

    Parameters
    ----------
    image : list
        A list of image data to display.
    title : list of str, optional
        The title of the image.
    colormap : list of str, optional
        The colormap to use. "labels" will display the image as labels.
    labels : list of bool, optional
        Whether to display image as a labels.
    min_display_intensity : list of float, optional
        The minimum display intensity, in the same units as the image.
        Use `np.percentile(image, 0.1)` for 0.1th percentile.
    max_display_intensity : list of float, optional
        The maximum display intensity, in the same units as the image.
        Use `np.percentile(image, 99.8)` for 99.9th percentile.

    """

    image: list[ArrayLike]
    title: list[str] | None = None
    colormap: list[str] | None = None
    labels: list[bool] | None = None
    min_display_intensity: list[float] | None = None
    max_display_intensity: list[float] | None = None

    def __post_init__(self):
        """Set default values for colormap and labels if not provided."""
        if self.colormap is None:
            self.colormap = [None] * len(self.image)
        if self.labels is None:
            self.labels = [False] * len(self.image)

__post_init__ #

__post_init__()

Set default values for colormap and labels if not provided.

Source code in src/napari_ndev/image_overview.py
51
52
53
54
55
56
def __post_init__(self):
    """Set default values for colormap and labels if not provided."""
    if self.colormap is None:
        self.colormap = [None] * len(self.image)
    if self.labels is None:
        self.labels = [False] * len(self.image)

image_overview #

image_overview(image_sets, fig_scale=(3, 3), fig_title='', scalebar=None)

Create an overview of images.

Parameters:

  • image_sets #

    (ImageSet, list of ImageSet, dict, or list of dict) –

    A list of napari_ndev.image_overview.ImageSet objects containing image information to display forstackview.imshow`. Using a dict is deprecated and will be removed in the future, but is supported by passing the dictionary keys as arguments to the ImageSet constructor. Will be removed in v1.0.0.

  • fig_scale #

    (tuple of float, default: (3, 3) ) –

    The scale of the plot. (Width, Height). Values lower than 2 are likely to result in overlapping text. Increased values increase image size. Defaults to (3, 3).

  • fig_title #

    (str, default: '' ) –

    The title of the plot. Defaults to an empty string.

  • scalebar #

    (float or dict, default: None ) –

    The scalebar to add to the image overview. If a float, it is used as the dx parameter for the scalebar. If a dict, all **kwargs are passed to the matplotlib_scalebar.scalebar.ScaleBar class. Defaults to None.

Returns:

  • fig ( Figure ) –

    The matplotlib figure object containing the image overview.

Source code in src/napari_ndev/image_overview.py
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
def image_overview(
    image_sets: ImageSet | list[ImageSet] | dict | list[dict],
    fig_scale: tuple[float, float] = (3, 3),
    fig_title: str = '',
    scalebar: float | dict | None = None,
):
    """
    Create an overview of images.

    Parameters
    ----------
    image_sets : ImageSet, list of ImageSet, dict, or list of dict
        A list of `napari_ndev.image_overview.ImageSet objects containing
        image information to display for `stackview.imshow`. Using a dict is
        deprecated and will be removed in the future, but is supported by
        passing the dictionary keys as arguments to the ImageSet constructor.
        Will be removed in v1.0.0.
    fig_scale : tuple of float, optional
        The scale of the plot. (Width, Height). Values lower than 2 are likely
        to result in overlapping text. Increased values increase image size.
        Defaults to (3, 3).
    fig_title : str, optional
        The title of the plot. Defaults to an empty string.
    scalebar : float or dict, optional
        The scalebar to add to the image overview. If a float, it is used as
        the dx parameter for the scalebar. If a dict, all **kwargs are passed
        to the matplotlib_scalebar.scalebar.ScaleBar class. Defaults to None.

    Returns
    -------
    fig : matplotlib.figure.Figure
        The matplotlib figure object containing the image overview.

    """
    # convert single image_set to list of image_set
    image_sets = [image_sets] if isinstance(image_sets, (ImageSet, dict)) else image_sets

    # if list of dicts convert to ImageSet, until deprecated
    image_sets = _convert_dict_to_ImageSet(image_sets) if any(isinstance(image_set, dict) for image_set in image_sets) else image_sets

    # create the subplot grid

    # if only one image set, wrap rows and columns to get a nice aspect ratio
    if len(image_sets) == 1:
        num_images = len(image_sets[0].image)

        if num_images <= 3:
            num_columns = num_images
            num_rows = 1
        # wrap so it is roughly a square aspect ratio
        else:
            num_columns = int(np.ceil(np.sqrt(num_images)))
            num_rows = int(np.ceil(num_images / num_columns))

    if len(image_sets) > 1:
        num_rows = len(image_sets)
        num_columns = max([len(image_set.image) for image_set in image_sets])

    # multiply scale of plot by number of columns and rows
    fig, axs = plt.subplots(
        num_rows,
        num_columns,
        figsize=(num_columns * fig_scale[0], num_rows * fig_scale[1]),
    )

    if num_rows == 1:
        axs = [axs]
    if num_columns == 1:
        axs = [[ax] for ax in axs]

    # iterate through the image sets
    for image_set_idx, image_set in enumerate(image_sets):
        for image_idx, image in enumerate(image_set.image):

            # calculate the correct row and column for the subplot
            if len(image_sets) == 1:
                row =  image_idx // num_columns
                col = image_idx % num_columns
            if len(image_sets) > 1:
                row = image_set_idx
                col = image_idx

            # turn off the subplot and continue if there is no image
            if image is None:
                axs[row][col].axis('off')
                continue

            # set labels value to true, if its in the colormap
            cmap = image_set.colormap[image_idx]
            if cmap is not None and cmap.lower() == 'labels':
                image_set.labels[image_idx] = True

            stackview.imshow(
                image = image,
                title = image_set.title[image_idx] if image_set.title else None,
                colormap = image_set.colormap[image_idx] if image_set.colormap else None,
                labels = image_set.labels[image_idx] if image_set.labels else False,
                min_display_intensity = image_set.min_display_intensity[image_idx] if image_set.min_display_intensity else None,
                max_display_intensity = image_set.max_display_intensity[image_idx] if image_set.max_display_intensity else None,
                plot=axs[row][col]
            )

            # add scalebar, if dict is present
            if scalebar is not None:
                _add_scalebar(axs[row][col], scalebar)

    # remove empty subplots
    for ax in fig.get_axes():
        ax.axis('off') if not ax.get_images() else None

    plt.suptitle(fig_title, fontsize=16)
    plt.tight_layout(pad=0.3)

    return fig