# Using the surface layer¶

In this document, you will learn about the napari Surface layer, including how to display surface data and edit the properties of surfaces like the contrast, opacity, colormaps and blending mode. You will also understand how to add and manipulate surfaces both from the GUI and from the console.

## When to use the surface layer¶

The surface layer allows you to display a precomputed surface mesh that is defined by an NxD array of N vertices in D coordinates, an Mx3 integer array of the indices of the triangles making up the faces of the surface, and a length N list of values to associate with each vertex to use alongside a colormap.

## A simple example¶

You can create a new viewer and add a surface in one go using the napari.view_surface method, or if you already have an existing viewer, you can add an image to it using viewer.add_surface. The api of both methods is the same. In these examples we’ll mainly use view_surface.

A simple example of viewing a surface is as follows:

import napari
import numpy as np

vertices = np.array([[0, 0], [0, 20], [10, 0], [10, 10]])
faces = np.array([[0, 1, 2], [1, 2, 3]])
values = np.linspace(0, 1, len(vertices))
surface = (vertices, faces, values)

viewer = napari.view_surface(surface)  # add the surface

from napari.utils import nbscreenshot

nbscreenshot(viewer, alt_text="A viewer with a surface")


## Arguments of view_surface and add_surface¶

view_surface() and add_surface() accept the same layer-creation parameters.

help(napari.view_surface)

Help on function view_surface in module napari.view_layers:

view_surface(data, *, colormap='gray', contrast_limits=None, gamma=1, name=None, metadata=None, scale=None, translate=None, rotate=None, shear=None, affine=None, opacity=1, blending='translucent', shading='flat', visible=True, cache=True, experimental_clipping_planes=None, wireframe=None, normals=None, title='napari', ndisplay=2, order=(), axis_labels=(), show=True) -> napari.viewer.Viewer
Create a viewer and add a surface layer.

Parameters
----------
data : 2-tuple or 3-tuple of array
The first element of the tuple is an (N, D) array of vertices of
mesh triangles. The second is an (M, 3) array of int of indices
of the mesh triangles. The optional third element is the
(K0, ..., KL, N) array of values used to color vertices where the
additional L dimensions are used to color the same mesh with
different values. If not provided, it defaults to ones.
colormap : str, napari.utils.Colormap, tuple, dict
Colormap to use for luminance images. If a string must be the name
of a supported colormap from vispy or matplotlib. If a tuple the
first value must be a string to assign as a name to a colormap and
the second item must be a Colormap. If a dict the key must be a
string to assign as a name to a colormap and the value must be a
Colormap.
contrast_limits : list (2,)
Color limits to be used for determining the colormap bounds for
luminance images. If not passed is calculated as the min and max of
the image.
gamma : float
Gamma correction for determining colormap linearity. Defaults to 1.
name : str
Name of the layer.
scale : tuple of float
Scale factors for the layer.
translate : tuple of float
Translation values for the layer.
rotate : float, 3-tuple of float, or n-D array.
If a float convert into a 2D rotation matrix using that value as an
angle. If 3-tuple convert into a 3D rotation matrix, using a yaw,
pitch, roll convention. Otherwise assume an nD rotation. Angles are
assumed to be in degrees. They can be converted from radians with
np.degrees if needed.
shear : 1-D array or n-D array
Either a vector of upper triangular values, or an nD shear matrix with
ones along the main diagonal.
affine : n-D array or napari.utils.transforms.Affine
(N+1, N+1) affine transformation matrix in homogeneous coordinates.
The first (N, N) entries correspond to a linear transform and
the final column is a length N translation vector and a 1 or a napari
Affine transform object. Applied as an extra transform on top of the
provided scale, rotate, and shear values.
opacity : float
Opacity of the layer visual, between 0.0 and 1.0.
blending : str
One of a list of preset blending modes that determines how RGB and
alpha values of the layer visual get mixed. Allowed values are
One of a list of preset shading modes that determine the lighting model
using when rendering the surface in 3D.

* Shading.NONE
Corresponds to shading='none'.
* Shading.FLAT
Corresponds to shading='flat'.
* Shading.SMOOTH
Corresponds to shading='smooth'.
visible : bool
Whether the layer visual is currently being displayed.
cache : bool
Whether slices of out-of-core datasets should be cached upon retrieval.
Currently, this only applies to dask arrays.
wireframe : dict or SurfaceWireframe
Whether and how to display the edges of the surface mesh with a wireframe.
normals : dict or SurfaceNormals
Whether and how to display the face and vertex normals of the surface mesh.
title : string, optional
The title of the viewer window. by default 'napari'.
ndisplay : {2, 3}, optional
Number of displayed dimensions. by default 2.
order : tuple of int, optional
Order in which dimensions are displayed where the last two or last
three dimensions correspond to row x column or plane x row x column if
ndisplay is 2 or 3. by default None
axis_labels : list of str, optional
Dimension names. by default they are labeled with sequential numbers
show : bool, optional
Whether to show the viewer after instantiation. by default True.

Returns
-------
viewer : :class:napari.Viewer
The newly-created viewer.


## Surface data¶

The data for a surface layer is defined by a 3-tuple of its vertices, faces, and vertex values. The vertices are an NxD array of N vertices in D coordinates. The faces are an Mx3 integer array of the indices of the triangles making up the faces of the surface. The vertex values are a length N list of values to associate with each vertex to use alongside a colormap. This 3-tuple is accessible through the layer.data property.

## 3D rendering of images¶

All our layers can be rendered in both 2D and 3D mode, and one of our viewer buttons can toggle between each mode. The number of dimensions sliders will be 2 or 3 less than the total number of dimensions of the layer. See for example these brain surfaces rendered in 3D:

## Working with colormaps¶

The same colormaps available for the Image layer are also available for the Surface layer. napari supports any colormap that is created with vispy.color.Colormap. We provide access to some standard colormaps that you can set using a string of their name.

list(napari.utils.colormaps.AVAILABLE_COLORMAPS)

['PiYG',
'blue',
'bop blue',
'bop orange',
'bop purple',
'cyan',
'gist_earth',
'gray',
'gray_r',
'green',
'hsv',
'inferno',
'magenta',
'magma',
'plasma',
'red',
'turbo',
'twilight',
'twilight_shifted',
'viridis',
'yellow']


Passing any of these as follows as keyword arguments will set the colormap of that surface. You can also access the current colormap through the layer.colormap property which returns a tuple of the colormap name followed by the vispy colormap object. You can list all the available colormaps using layer.colormaps.

It is also possible to create your own colormaps using vispy’s vispy.color.Colormap object, see it’s full documentation here. For more detail see the image layer guide.

The vertex values of the surface layer get mapped through its colormap according to values called contrast limits. These are a 2-tuple of values defining how what values get applied the minimum and maximum of the colormap and follow the same principles as the contrast_limits described in the image layer guide. They are also accessible through the same keyword arguments, properties, and range slider as in the image layer.