@@ -531,6 +531,65 @@ def test_cmap_matches_selected_channels_not_full_image(sdata_blobs: SpatialData)
531531 plt .close (fig )
532532
533533
534+ # Regression for #628: NaN pixels must raise, not silently render
535+ # (na_color in 1ch, black in multi-channel).
536+ def _nan_image (n_channels : int , nan_indices : list [int ]) -> SpatialData :
537+ rng = np .random .default_rng (0 )
538+ data = rng .uniform (0 , 1 , (n_channels , 8 , 8 )).astype (np .float32 )
539+ for ch in nan_indices :
540+ data [ch , 0 :3 , 0 :3 ] = np .nan
541+ img = Image2DModel .parse (data , dims = ("c" , "y" , "x" ), c_coords = list (range (n_channels )))
542+ return SpatialData (images = {"img" : img })
543+
544+
545+ def test_nan_in_single_channel_raises ():
546+ sdata = _nan_image (n_channels = 1 , nan_indices = [0 ])
547+ with pytest .raises (ValueError , match = r"NaN.*channel\(s\) \[0\]" ):
548+ sdata .pl .render_images ("img" ).pl .show ()
549+
550+
551+ def test_nan_in_multi_channel_raises ():
552+ sdata = _nan_image (n_channels = 2 , nan_indices = [0 ])
553+ with pytest .raises (ValueError , match = r"NaN.*channel\(s\) \[0\]" ):
554+ sdata .pl .render_images ("img" ).pl .show ()
555+
556+
557+ def test_finite_multi_channel_unaffected ():
558+ sdata = _nan_image (n_channels = 2 , nan_indices = [])
559+ fig , ax = plt .subplots ()
560+ sdata .pl .render_images ("img" ).pl .show (ax = ax )
561+ plt .close (fig )
562+
563+
564+ def test_integer_dtype_skips_nan_check ():
565+ rng = np .random .default_rng (0 )
566+ data = rng .integers (0 , 255 , (2 , 8 , 8 ), dtype = np .uint16 )
567+ img = Image2DModel .parse (data , dims = ("c" , "y" , "x" ), c_coords = [0 , 1 ])
568+ sdata = SpatialData (images = {"img" : img })
569+ fig , ax = plt .subplots ()
570+ sdata .pl .render_images ("img" ).pl .show (ax = ax )
571+ plt .close (fig )
572+
573+
574+ def test_nan_only_in_unselected_channel_renders ():
575+ sdata = _nan_image (n_channels = 2 , nan_indices = [1 ])
576+ fig , ax = plt .subplots ()
577+ sdata .pl .render_images ("img" , channel = [0 ]).pl .show (ax = ax )
578+ plt .close (fig )
579+
580+
581+ def test_nan_error_lists_all_offending_channels ():
582+ sdata = _nan_image (n_channels = 3 , nan_indices = [0 , 2 ])
583+ with pytest .raises (ValueError , match = r"\[0, 2\]" ):
584+ sdata .pl .render_images ("img" ).pl .show ()
585+
586+
587+ def test_nan_error_message_includes_fillna_hint ():
588+ sdata = _nan_image (n_channels = 1 , nan_indices = [0 ])
589+ with pytest .raises (ValueError , match = "fillna" ):
590+ sdata .pl .render_images ("img" ).pl .show ()
591+
592+
534593# Regression for #612: vmin/vmax kwargs are no longer accepted on any render
535594# function. The check covers all four to prevent the asymmetry from re-emerging.
536595@pytest .mark .parametrize ("kwarg" , ["vmin" , "vmax" ])
0 commit comments