@@ -697,6 +697,61 @@ def __init__(self, napari_viewer):
697697 # (Of course this will be a problem if we start using it everywhere so do not reuse lightly)
698698 QTimer .singleShot (10 , self .silently_dock_matplotlib_canvas )
699699
700+ # Retroactively initialize KeypointStores for Points layers that were
701+ # added before this widget was fully initialized (timing issue where
702+ # on_insert never fires for pre-existing layers).
703+ self ._init_retry_count = 0
704+ QTimer .singleShot (1000 , self ._retroactive_store_init )
705+
706+ def _retroactive_store_init (self ):
707+ self ._init_retry_count += 1
708+ if self ._stores :
709+ return
710+ has_points = any (
711+ isinstance (l , Points ) and l .metadata .get ("header" )
712+ for l in self .viewer .layers
713+ )
714+ if not has_points :
715+ if self ._init_retry_count < 10 :
716+ QTimer .singleShot (1000 , self ._retroactive_store_init )
717+ return
718+ # Populate _images_meta from Image layers (normally done by on_insert)
719+ for layer in self .viewer .layers :
720+ if isinstance (layer , Image ) and layer .metadata .get ("root" ):
721+ self ._images_meta .update (
722+ {
723+ "paths" : layer .metadata .get ("paths" ),
724+ "shape" : layer .level_shapes [0 ],
725+ "root" : layer .metadata ["root" ],
726+ "name" : layer .name ,
727+ }
728+ )
729+ for layer in self .viewer .layers :
730+ if isinstance (layer , Points ) and layer .metadata .get ("header" ):
731+ store = keypoints .KeypointStore (self .viewer , layer )
732+ self ._stores [layer ] = store
733+ if root := layer .metadata .get ("root" ):
734+ update_save_history (root )
735+ layer .metadata ["controls" ] = self
736+ layer .text .visible = False
737+ layer .bind_key ("M" , self .cycle_through_label_modes )
738+ layer .bind_key ("F" , self .cycle_through_color_modes )
739+ func = partial (_paste_data , store = store )
740+ layer ._paste_data = MethodType (func , layer )
741+ layer .add = MethodType (keypoints ._add , store )
742+ layer .events .add (query_next_frame = Event )
743+ layer .events .query_next_frame .connect (store ._advance_step )
744+ layer .bind_key ("Shift-Right" , store ._find_first_unlabeled_frame )
745+ layer .bind_key ("Shift-Left" , store ._find_first_unlabeled_frame )
746+ layer .bind_key ("Down" , store .next_keypoint , overwrite = True )
747+ layer .bind_key ("Up" , store .prev_keypoint , overwrite = True )
748+ layer .face_color_mode = "cycle"
749+ self ._form_dropdown_menus (store )
750+ self ._radio_box .setEnabled (True )
751+ self ._color_grp .setEnabled (True )
752+ self ._trail_cb .setEnabled (True )
753+ self ._show_traj_plot_cb .setEnabled (True )
754+
700755 def _ensure_mpl_canvas_docked (self ) -> None :
701756 """
702757 Dock the Matplotlib canvas as a napari dock widget, exactly once,
@@ -1225,6 +1280,9 @@ def on_insert(self, event):
12251280
12261281 return
12271282
1283+ if not layer .metadata .get ("header" ):
1284+ return
1285+
12281286 if layer .metadata .get ("tables" , "" ):
12291287 self ._keypoint_mapping_button .show ()
12301288
0 commit comments