Loading...

Napari

Multi-dimensional image viewer for Python with interactive visualization and annotation capabilities

Neuroscience-Specific Analysis Tools Intermediate Recommended Tool
Quick Info
  • Category: Neuroscience-Specific Analysis Tools
  • Level: Intermediate
  • Type: Recommended Tool
  • Requires:

Why We Recommend Napari

Napari provides an intuitive, fast viewer for multi-dimensional scientific images. It's perfect for exploring calcium imaging data, manually selecting ROIs, and visualizing complex image stacks. Its plugin ecosystem and Python API make it both user-friendly and extensible.

Common Use Cases

  • Interactive exploration of image stacks
  • Manual ROI selection and annotation
  • Visualizing segmentation results
  • Multi-channel image overlay

Getting Started

Napari is a fast, interactive, multi-dimensional image viewer for Python. It’s designed for browsing, annotating, and analyzing large multi-dimensional images including calcium imaging data, microscopy stacks, and other scientific imaging data.

Why Napari?

  • Fast Rendering: Handles large image stacks smoothly
  • N-Dimensional: Works with 2D, 3D, 4D+ data
  • Interactive: Real-time manipulation and annotation
  • Layer-Based: Overlay multiple data types
  • Plugin Ecosystem: Extensible functionality
  • Python Integration: Seamless workflow with NumPy/scikit-image

Basic Usage

Opening Images

import napari
import numpy as np
from skimage import data

# Start viewer
viewer = napari.Viewer()

# Add 2D image
image = data.camera()
viewer.add_image(image, name='camera')

# Add image stack (time series)
stack = np.random.rand(10, 512, 512)  # (time, height, width)
viewer.add_image(stack, name='time series')

# Run viewer
napari.run()

Quick View

import napari

# Quick view (single line)
napari.view_image(image, name='My Image')

# Or with stack
napari.view_image(stack, name='Time Series')

Working with Calcium Imaging

Load and View Recording

import napari
import tifffile

# Load calcium imaging stack
stack = tifffile.imread('calcium_recording.tif')
# Shape: (frames, height, width)

# View with Napari
viewer = napari.view_image(
    stack,
    name='Ca²⁺ Recording',
    colormap='green',
    contrast_limits=[100, 400]
)

napari.run()

View with ROIs

import napari
import numpy as np
import tifffile

# Load data
stack = tifffile.imread('recording.tif')

# Load ROI masks
roi_masks = np.load('rois.npy')  # Binary masks

# Create viewer
viewer = napari.Viewer()

# Add image
viewer.add_image(
    stack,
    name='Recording',
    colormap='gray',
    blending='additive'
)

# Add ROIs as labels
viewer.add_labels(
    roi_masks,
    name='ROIs',
    opacity=0.5
)

napari.run()

Layer Types

Image Layer

# Grayscale
viewer.add_image(data, colormap='gray')

# With properties
viewer.add_image(
    data,
    name='My Image',
    colormap='viridis',
    contrast_limits=[0, 100],
    blending='additive',
    opacity=0.7
)

Labels Layer (Segmentation)

# Integer labels
labels = np.zeros((512, 512), dtype=int)
labels[100:150, 100:150] = 1  # ROI 1
labels[200:250, 200:250] = 2  # ROI 2

viewer.add_labels(labels, name='ROIs')

Points Layer

# Mark specific locations
points = np.array([
    [100, 120],
    [200, 85],
    [150, 200]
])

viewer.add_points(
    points,
    name='Cell Centers',
    size=10,
    face_color='red'
)

Shapes Layer

# Draw regions
shapes_data = [
    np.array([[100, 100], [100, 200], [200, 200], [200, 100]]),  # Rectangle
]

viewer.add_shapes(
    shapes_data,
    shape_type='polygon',
    edge_color='red',
    face_color='transparent',
    edge_width=2,
    name='Annotations'
)

Interactive ROI Selection

Manual ROI Drawing

import napari
import tifffile
import numpy as np

# Load image
mean_img = tifffile.imread('mean_projection.tif')

# Create viewer
viewer = napari.Viewer()
viewer.add_image(mean_img, name='Mean Image', colormap='gray')

# Add shapes layer for drawing
shapes_layer = viewer.add_shapes(
    name='ROIs',
    shape_type='polygon',
    edge_color='red',
    face_color=[1, 0, 0, 0.3]  # Semi-transparent red
)

print("Draw ROIs using the polygon tool")
print("Press 'P' to activate polygon tool")
print("Click to add points, double-click to close polygon")

napari.run()

# After closing, get drawn ROIs
roi_shapes = shapes_layer.data
print(f"Drew {len(roi_shapes)} ROIs")

Convert Shapes to Masks

from skimage import draw

# Get image dimensions
height, width = mean_img.shape

# Create mask for each ROI
masks = []
for roi in shapes_layer.data:
    mask = np.zeros((height, width), dtype=bool)

    # Get polygon coordinates
    rr, cc = draw.polygon(roi[:, 0], roi[:, 1], shape=(height, width))
    mask[rr, cc] = True

    masks.append(mask)

# Stack masks
roi_masks = np.array(masks)
print(f"Created {len(masks)} masks")

# Save
np.save('manual_rois.npy', roi_masks)

Multi-Channel Imaging

View Multiple Channels

import napari

# Load channels
green_channel = tifffile.imread('green_channel.tif')  # GCaMP
red_channel = tifffile.imread('red_channel.tif')      # Anatomical

# Create viewer
viewer = napari.Viewer()

# Add channels with different colors
viewer.add_image(
    green_channel,
    name='GCaMP',
    colormap='green',
    blending='additive'
)

viewer.add_image(
    red_channel,
    name='Anatomical',
    colormap='red',
    blending='additive',
    opacity=0.5
)

napari.run()

Time Series Navigation

# Load time series
stack = tifffile.imread('timeseries.tif')  # (time, height, width)

viewer = napari.view_image(
    stack,
    name='Time Series',
    colormap='viridis'
)

# Use slider to navigate time
# Keyboard shortcuts:
# - Left/Right arrows: previous/next frame
# - Alt+Left/Right: jump 10 frames

napari.run()

Visualization Techniques

Side-by-Side Comparison

import napari

viewer = napari.Viewer()

# Add grid arrangement
viewer.add_image(raw_data, name='Raw')
viewer.add_image(processed_data, name='Processed')

# Set grid mode
viewer.grid.enabled = True
viewer.grid.shape = (1, 2)  # 1 row, 2 columns

napari.run()

Overlay Segmentation

import napari
from skimage import segmentation

# Segment image
labels = segmentation.watershed(...)

viewer = napari.Viewer()

# Original image
viewer.add_image(image, name='Original', colormap='gray')

# Overlay labels
viewer.add_labels(
    labels,
    name='Segmentation',
    opacity=0.5
)

napari.run()

Programmatic Interaction

Update Layers

import napari
import numpy as np

viewer = napari.Viewer()

# Add initial image
image_layer = viewer.add_image(np.random.rand(512, 512))

# Update data
new_data = np.random.rand(512, 512)
image_layer.data = new_data

# Update properties
image_layer.colormap = 'viridis'
image_layer.contrast_limits = [0, 0.5]

Add Callbacks

@viewer.bind_key('s')
def save_screenshot(viewer):
    """Press 's' to save screenshot."""
    screenshot = viewer.screenshot()
    import matplotlib.pyplot as plt
    plt.imsave('screenshot.png', screenshot)
    print("Screenshot saved!")

Practical Workflows

Quality Check Pipeline

import napari
import tifffile
from pathlib import Path

def inspect_recordings(data_dir):
    """Visually inspect all recordings in directory."""
    data_path = Path(data_dir)

    viewer = napari.Viewer()

    # Load all TIFF files
    for tiff_file in sorted(data_path.glob('*.tif')):
        stack = tifffile.imread(tiff_file)
        viewer.add_image(stack, name=tiff_file.stem)

    napari.run()

# Usage
inspect_recordings('data/recordings')

ROI Refinement

import napari
import numpy as np

# Load automated ROI detection results
auto_rois = np.load('auto_rois.npy')
mean_image = np.load('mean_image.npy')

viewer = napari.Viewer()

# Show mean image
viewer.add_image(mean_image, name='Mean', colormap='gray')

# Show automated ROIs
viewer.add_labels(auto_rois, name='Auto ROIs')

# Add layer for manual corrections
manual_layer = viewer.add_labels(
    np.zeros_like(auto_rois),
    name='Manual Corrections'
)

print("Edit ROIs:")
print("- Brush tool (1): paint new regions")
print("- Eraser tool (2): remove regions")
print("- Fill tool (3): fill regions")

napari.run()

# Save refined ROIs
refined_rois = manual_layer.data
np.save('refined_rois.npy', refined_rois)

Plugins

Install Plugins

# Install plugin manager
pip install napari[all]

# Install specific plugins
pip install napari-animation  # Create animations
pip install napari-segment-blobs-and-things-with-membranes

Use Plugins

import napari

viewer = napari.Viewer()
viewer.add_image(data)

# Access plugins through menu
# Plugins → napari-animation → Wizard

Advanced Features

3D Rendering

# View 3D data
stack_3d = np.random.rand(50, 512, 512)  # (z, y, x)

viewer = napari.view_image(
    stack_3d,
    name='3D Stack',
    rendering='mip'  # Maximum intensity projection
)

# Switch to 3D mode
viewer.dims.ndisplay = 3

napari.run()

Headless Mode (No GUI)

import napari

# Create viewer without showing
viewer = napari.Viewer(show=False)

# Add layers
viewer.add_image(data)

# Take screenshot
screenshot = viewer.screenshot()

# Close
viewer.close()

Keyboard Shortcuts

  • Navigation: Arrow keys move through dimensions
  • Zoom: Ctrl/Cmd + scroll
  • Pan: Click and drag (or middle mouse)
  • Toggle Layer: Click eye icon
  • Full Screen: F
  • Screenshot: Alt + S
  • Grid View: Ctrl/Cmd + G

Installation

# Basic installation
pip install "napari[all]"

# Or with pixi
pixi add "napari[all]"

# Minimal (no Qt)
pip install napari

# With PyQt5
pip install "napari[pyqt5]"

Best Practices

  • Start with default contrast limits, adjust as needed
  • Use blending=‘additive’ for multi-channel images
  • Save screenshots for figures and presentations
  • Use labels layers for segmentation masks
  • Leverage keyboard shortcuts for efficiency
  • Use grid view for comparisons
  • Install relevant plugins for specific tasks

Performance Tips

  • Use appropriate data types (uint8, uint16 instead of float64)
  • Downsample very large images
  • Use multiscale for pyramidal viewing
  • Close unused layers
  • Limit number of visible layers

Resources

Summary

Napari is essential for:

  • Interactive exploration of multi-dimensional images
  • Manual ROI selection and refinement
  • Quality control of imaging data
  • Visualization of analysis results

It bridges the gap between automated analysis and manual verification, making it invaluable for calcium imaging workflows.

Top