Unable to add timeseries of 2D points

Hi there!

I am a new user of Napari and have found it good (awesome!) so far. I am working on a mini-project where I want to segment moving bacteria using 1 channel and visualise the fluorescense of said bacteria in another channel. I got it working so far and I am now trying to visualise and plot my results.

######## To the point ###########
I am trying to plot my cell boundary on top of the segmented image (timeseries). Plotting the timeseries itself works well (all images are padded to have same dimensions).

I am not able to add_points as a timeseries however, but only a 2D array to a single image.

#paddedPoints is a list of 2D arrays with same size (padded with 0’s in case this is what broke Napari)
tmp=np.array(paddedPoints) #convert to array. tmp.shape=(379, 221, 2)
viewer = napari.Viewer()
with napari.gui_qt():
viewer.add_image(np.array(padRotCells)) #works
viewer.add_points(tmp) #doesn’t work, but tmp[0] shows points for first boundary in tmp

#A copy pase of what tmp[0] looks like to give you an idea.
tmp[0]
Out[112]:
array([[53, 28],
[53, 27],
[54, 26],
[54, 25],
[52, 24],
[51, 24],
[50, 24],
[49, 24],
[48, 24],
[46, 23],
[46, 24]…

Is it just me who is not understanding how to properly use add_points / Napari? I found some examples online for the use but it is mostly the example of adding points to a single image (the famous astronaut), hence not helping me.

General comments and suggestions welcome! Keen to learn…

Hi @Andreas-K!

The points should actually be an array of shape (n_points, n_dim). The dimension here is 3, because time is just another dimension in napari-land. =)

So you need to convert the (n_timepoints, n_points_per_timepoint, 2), to (n_total_points, 3). Here’s a script that does this. Might not be the most efficient, but it should work (Edit: it doesn’t, see new code in response below.):

n_pts_per_timepoint = tmp.shape[1]
all_points_list = []
for t, t_points in enumerate(tmp):
    pts_with_time = np.stack(
        (np.full(n_pts_per_timepoint, t), t_points),
        axis=1,
        )
    all_points.append(pts_with_time)
all_points = np.concatenate(all_points_list, axis=0)

Then viewer.add_points(all_points) should work as you expect!

Hi Juan,

Thank you so much for a swift reply. I tried to use the small script you proposed (changed a type on the all_points → all_points_list within the loop).
Unfortunately, since I have X and Y points the shapes from np.full(n_pts_per_timepoint, t) and t_points are not compatible and it throws an error.

The error:
raise ValueError(‘all input arrays must have the same shape’)
ValueError: all input arrays must have the same shape

Soem (maybe?) useful debugging/sanity checking:

np.full(n_pts_per_timepoint, t).shape
Out[1309]: (328,)

t_points.shape
Out[1308]: (328, 2)

t_points
Out[1307]:
array([[86, 69],
[86, 68],
[87, 67],
[88, 67],
[88, 66],
[89, 64],
[88, 63],
[88, 62],

ah, I see my mistake. Try this:

n_pts_per_timepoint = tmp.shape[1]
all_points_list = []
for t, t_points in enumerate(tmp):
    pts_with_time = np.concatenate(
        (
            np.full((n_pts_per_timepoint, 1), fill_value=t),
            t_points,
        ),
        axis=1,
    )
    all_points.append(pts_with_time)
all_points = np.concatenate(all_points_list, axis=0)

Hi Juan,

Apologies for the late reply. Thanks that seem to work!

Best,
Andreas