Napari timepoints not detected

Hello everyone,

I wrote a script which in my environment seems to work. One crucial part of the script is to add points to certain images and get TYX coordinates from

viewer.layers['Points'].__dict__['_data']

and everything goes right.

The problem is that when I tried to make a new environment with all dependencies needed to run napari I don’t get any problem in the installation but when running exactly the same script, this Timepoint dimensions extracted from the coordinates doesn’t appear (just YX). Does anybody know what could be the cause? I have been suspecting about qt but not sure. For now, my only solution has been to clone the environment and cut/paste the whole folder (not nice workaround).

My environment has pip installations and for some reason, I can’t export a working yml file to install the same environment somewhere else.

Thank you in advance

The dimensionality of a points layer depends a bit on exactly how the points are added to the viewer. By default, it has 2 dimensions:

import napari
viewer = napari.Viewer()
points = viewer.add_points()
print(points.data.shape)  # (0,2)
points.add((0,0,0))  # ERROR: array has size 2 and the points have size 3

If you are programmatically creating the points layer, you can dictate the desired shape of your points data, using the ndim argument, or by instantiating with a numpy array of the desired shape:

import napari
viewer = napari.Viewer()
points = viewer.add_points(ndim=3)
print(points.data.shape)  # (0,3)
points.add((0,0,0))  # no problem

One slightly hidden thing here is that, if you’re adding the points layer using the “add points” button in the GUI, just above the layer list… then it performs the following logic when adding the new points layer.

# i.e. create points with at least 2 dimensions, or as many
# dimensions as the highest dimension existing layer in the viewer
viewer.add_points(ndim=max(viewer.dims.ndim, 2))

(so, if you click that button, or simply use add_points() prior to adding some higher dimensional image, then your points will only have 2 dims)

The problem is that when I tried to make a new environment …

I can’t remember whether this behavior has changed in a while (@sofroniewn?) … but I’d check what version of napari you have in your “working” environment.


side note: it’s never “future safe” to use private attributes as shown in your example: .__dict__['_data'] , prefer accessing layer data using viewer.layers['Points'].data

1 Like

Thanks a lot!

side note: it’s never “future safe” to use private attributes as shown in your example: .__dict__['_data'] , prefer accessing layer data using viewer.layers['Points'].data

I did not know how to access it because for some reason I don’t get suggestions of what can be accessed from that object, I was always wrong trying viewer.layers[‘Points’]._data. So good to know. Thanks.

I can’t remember whether this behavior has changed in a while (@sofroniewn?) … but I’d check what version of napari you have in your “working” environment.

I think it has changed. I just realized that I didn’t have the last version of napari in my “working” environment (0.3.4) while in the new environment I created from scratch is 0.4.4. So I think there is the issue I’m facing.

What I do is to open an Image with dimensions (507, 3312, 3312) and add by default the Points layer so the user just have to click and close the window after finished.

with napari.gui_qt():
    viewer = napari.Viewer()
    viewer.add_image(image)
    viewer.add_points(name='points', face_color='red', opacity=0.9, symbol='disc', size=50, n_dimensional=False)
    viewer.layers['points'].mode = 'add'

From this command

viewer.layers['points'].data

the output in napari 0.3.4 would look like:

array([[   0.        , 2400.55072594,  743.0588457 ],
       [  25.        , 1750.68264203,  874.34532729],
       [  49.        , 1527.49562332, 1694.88583727]])

while in napari 0.4.4:

array([[   2400.55072594,  743.0588457 ],
       [  1750.68264203,  874.34532729],
       [  1527.49562332, 1694.88583727]])

For now, I solved it installing that specific version with:

pip install napari[all]==0.3.4

Fascinating! I can confirm that the add_points call now creates a 2D points layer instead of a 3D points layer! That’s certainly a bug. add_points() with no data should do the same thing as the button, or at least that’s my understanding/preference, and it seems, also the historical behaviour. Here’s a complete minimal example:

import numpy as np
import napari

image = np.random.random((10, 1024, 1024))

with napari.gui_qt():
    viewer = napari.Viewer()
    _ = viewer.add_image(image)
    pts_layer = viewer.add_points()
    print(pts_layer.ndim)

This prints 2 on current napari and 3 on 0.3.4. (note: on current napari you no longer need the with napari.gui_qt context. You can leave it blank if you don’t need to see the UI, or you can add napari.run() at the end.)

As @talley showed, the workaround for current napari is to use add_points(..., ndim=image.ndim). That should work regardless of your napari version. In a future version, there’s a chance we’ll return the default based on current ndims, but specifying ndim should always work.

1 Like

I’ve created an issue on the repo to track this:

There’s a change we’ll decide not to fix because it adds code complexity, but in that case, we’ll try to do a better job of documenting add_points(..., ndim=3).

1 Like