Using Napari-SpatialData#

This tutorial shows how to load SpatialData objects into the Napari-Spatialdata plugin, and use it with the “View” and “Scatter” widgets for visualising coordinates.

Import packages and data#

There are two options to install napari-spatialdata:

(1) Install napari

(2a) Run pip install napari-spatialdata

or,

(2b) Clone this repo and run pip install -e .

%matplotlib inline
import matplotlib.pyplot as plt
from napari_spatialdata import Interactive
from spatialdata import SpatialData

plt.rcParams['figure.figsize'] = (20, 20)

Next, we will download the Nanostring dataset (cosmx_io) for analysis.

If on Windows, download the dataset from https://s3.embl.de/spatialdata/spatialdata-sandbox/cosmx_io.zip.

In on Linux, uncomment the lines below to download the dataset.

# !mkdir tutorial_data
# !mkdir tutorial_data/nanostring_data
# !wget -P tutorial_data/nanostring_data https://s3.embl.de/spatialdata/spatialdata-sandbox/cosmx_io.zip
# !unzip tutorial_data/nanostring_data/cosmx_io.zip -d tutorial_data/nanostring_data

We will load the dataset from the filepath and create a spatialdata.SpatialData object. We’ll use this object with the class Interactive to visualise this dataset in Napari.

FILE_PATH = "tutorial_data/nanostring_data/data.zarr" # Path to the data file. Change if your data is stored in a different location.
sdata = SpatialData.read(FILE_PATH)

Visualise in napari#

We can instantiate the Interactive class with our spatialdata.SpatialData object, and view it in Napari.

interactive = Interactive(sdata)
interactive.run()

This executes an empty Napari viewer. The SpatialData widget is in the bottom left hand corner and consists of two boxes, “Coordinate System” and “Elements”.

A spatialdata.SpatialData object groups together five spatialdata.models.SpatialElement: Images (raster images), Labels (e.g. segmentation masks), Points (e.g. transcripts locations, molecular probes), Shapes (regions of interests, array capture locations etc.), and Table (where the molecular profiles and annotations are stored). Each SpatialElement can be associated with a coordinate system and the transformation required to align that element to it.

plt.imshow(interactive.screenshot())
plt.axis('off')
(-0.5, 1496.5, 953.5, -0.5)
../_images/ebb9d33d63fe63783a732cd968a4edb8c25433e4d39d08127377acc95cded7e3.png

We can pick a coordinate system in the first box. This automatically updates the next box, which shows the elements associated with that coordinate system. Clicking on an element loads it as a layer into Napari.

In the example below, we selected the coordinate system “point23” and loaded “point23_image” and “point23_labels” to the Napari viewer.

plt.imshow(interactive.screenshot())
plt.axis('off')
(-0.5, 1496.5, 953.5, -0.5)
../_images/da1802d53a1bdbbbb7fc495ac59cad441a832dfaee8b6d885b02354d5f01b7b7.png

Load axis with the view widget#

Napari-SpatialData also comes with a “View” widget that opens automatically on the right side of Napari window.

You can also find it in the menu bar by going to Plugins > napari-spatialdata > View. The obs, var and obsm values are associated with the anndata of the selected layer.

To further examine a specific value, we can double click on any element on the View Widget to load it to the viewer. In the example below, we selected the layer “point23_labels” and double clicked on the gene expression, “CD14” in the view widget.

plt.imshow(interactive.screenshot())
plt.axis('off')
(-0.5, 1496.5, 953.5, -0.5)
../_images/7541826cd8eb91ca7ccd5fbdf7e58c3f2a408b7a4961a029509850109d7f69dc.png

Load axis into scatter widget#

Napari-SpatialData also comes with a Scatter widget to visualise points in 2D coordinates.

In the example below, we started again with a setup where we’ve loaded point23_labels and point23_image to the viewer. We select the layer, “point23_labels”. Then, we open the Scatter widget by going to Plugins > napari-spatialdata > Scatter. This loads the AnnData object associated with that layer into the “Scatter” Widget.

Note that widgets are moveable within a napari window. You can drag the Scatter widget to take the entire right side of the viewer. In this configuration View and Scatter widget are in separate tabs.

plt.imshow(interactive.screenshot())
plt.axis('off')
(-0.5, 1496.5, 1088.5, -0.5)
../_images/6ca822f49afd3a0dbdef4db4586f8d401c4ac7398e070f1c78223c4d78300adc.png

We can now pick AnnData values to visualise in the scatterplot.

In the example below, we’ve selected obsm[“spatial”] , with axis 0 in the x-axis and axis 1 in the y-axis. We’re coloring each coordinate by obs[“cell_size”] . Once we’ve selected the relevant data points, clicking on “Plot” generates a scatterplot.

Note that the Scatter widget y axis is inverted in comparison with the image in the Napari window.

plt.imshow(interactive.screenshot())
plt.axis('off')
(-0.5, 1496.5, 1088.5, -0.5)
../_images/9049c05ece9431e2702d7f76efb71671e69eb8daa33a3cecb8733dd5dcb17d60.png

The “Scatter” widget also offers an interactive feature to manually select clusters of interest.

In the example below, we used the lasso tool to select a triangular region on the top left area of the scatterplot. (See scatterwidget.ipynb and scatterwidget_annotion.ipynb for details of the ROI selection).

plt.imshow(interactive.screenshot())
plt.axis('off')
(-0.5, 1496.5, 1088.5, -0.5)
../_images/a0f418f70d2d82938436ab709aca0fb8a34151bb9d13ce006c5eadada3016ea6.png

After a ROI has been created, it can be exported into AnnData by clicking on the “Annotate” button. This creates a new obs value, with the name that you can specify in the dialog.

We will use the new annotation as the color type for our scatterplot. After selection of the new color click “Plot” to generate the scatterplot.

plt.imshow(interactive.screenshot())
plt.axis('off')
(-0.5, 1496.5, 1088.5, -0.5)
../_images/34ae5e9fd42af7753f1ab78c4e8721a46d8d4b0c23888ebf35241b42a5855ac8.png

We can also view this in the “View” widget and use to color existing labels.

You can find the new annotation at the bottom of “Observations”. Double click it to re-color the labels.

plt.imshow(interactive.screenshot())
plt.axis('off')
(-0.5, 1496.5, 1088.5, -0.5)
../_images/ba940c5a3aa2571168cdc15bdc0e8951e62982ee1d1a22e86a58644ed071b98c.png