Event emitter for deleting data within a layer (points, shapes, etc.)


Sorry in advanced that is post is long. I am working on creating an annotation program similar to Bounding box annotations with text and annotating videos with napari - napari and would like to be able to display the annotations (rectangles in a Shapes layer) as they are added and/or removed in a table format. Thanks to the recent addition of the table widget to magicgui and the changes here https://github.com/napari/napari/pull/2441, I have been able to update the table by just resetting the dictionary defining the table every time I change layers or add rectangles via mouse drag call backs.

The one thing I have not been able to figure out is what callback to use when I delete a shape so I can update the table in real time. My callbacks catch it as soon as you change layers or click anywhere else but not until then. I have tried using viewer.active_layer.events.data.connect(my_callback) (similar to what is mentioned here An Introduction to the Event Loop in napari - napari) but this does not seem to work. It is likely I am either misuing/don’t understand this callback or my rudimentary Python skills are failing me haha. Now I know you all have plans to work on events for shapes layer and add more functionality to the table but is there a way to capture the deletion of data in the current iteration of napari?

My thought would be to either write my own dataclass or bind a key to do it because then my callbacks are easy. I would like to avoid both of these as I prefer not to duplicate data if possible and do not want the users of the script not have to remember what specific key I binded.

I realize this is a nit picky thing, so any insight you can provide would be great. Thanks!

Yeah so the issue is that events.data is triggered when you do something like layer.data = blah. But if you are modifying data in-place, we have no way of knowing when you are doing that. However if you look at your first linked example — bounding box annotations — you see that the event triggered by adding shapes using the UI is shapes.events.set_data! Note the set_. I do wonder if we shouldn’t just trigger a .data@sofroniewn?

Note that if you are adding shapes by some other means you can trigger events manually with shapes.events.data() — and then hook up whatever listeners you want to that.

Does that resolve your issue? If not then it might be good to have a tiny example with dummy data so that we can play with it…

Yeah, we need to improve this - we actually have this open issue here which I think if addressed would meet your needs. Maybe we can continue discussion there Receive events on shape create and delete · Issue #720 · napari/napari · GitHub

Sure, lets continue the conversation there.