@@ -925,6 +925,22 @@ def single_image_analysis(
925925
926926 def process_image (img , img_cell , img_bulk , k1 , k2 ):
927927 z_planes , img2 , Gx , Gy = self .get_infocus_planes (img , k1 , sigma = gsigma )
928+ # Restrict to the in-focus z range before spot/mask detection --
929+ # otherwise compute_spot_and_cell_props processes every plane of
930+ # the full stack but make_datarray_spot only labels the first
931+ # len(z_planes) of them with the (unrelated) in-focus z numbers,
932+ # silently misaligning planes and, for any array derived from the
933+ # full per-plane results (e.g. the bulk overlap column), producing
934+ # a length mismatch against to_save. Mirrors the slicing already
935+ # done in analyse_images._analysis_loop.
936+ img = img [z_planes [0 ] : z_planes [1 ], :, :]
937+ img2 = img2 [z_planes [0 ] : z_planes [1 ], :, :]
938+ Gx = Gx [z_planes [0 ] : z_planes [1 ], :, :]
939+ Gy = Gy [z_planes [0 ] : z_planes [1 ], :, :]
940+ if img_cell is not None :
941+ img_cell = img_cell [z_planes [0 ] : z_planes [1 ], :, :]
942+ if img_bulk is not None :
943+ img_bulk = img_bulk [z_planes [0 ] : z_planes [1 ], :, :]
928944 to_save , to_save_largeobjects , lo_mask , cell_mask , bulk_mask = (
929945 IA_F .compute_spot_and_cell_props (
930946 img ,
@@ -950,7 +966,16 @@ def process_image(img, img_cell, img_bulk, k1, k2):
950966 bulk_sigma2 = self .bulk_sigma2 ,
951967 )
952968 )
953- return z_planes , to_save , to_save_largeobjects , cell_mask , bulk_mask
969+ return (
970+ z_planes ,
971+ img ,
972+ img_cell ,
973+ img_bulk ,
974+ to_save ,
975+ to_save_largeobjects ,
976+ cell_mask ,
977+ bulk_mask ,
978+ )
954979
955980 def filter_z_planes (to_save , z_planes ):
956981 z_to_plot = np .full_like (np .arange (z_planes [0 ] + 1 , z_planes [- 1 ] + 1 ), - 1 )
@@ -968,6 +993,7 @@ def filter_z_planes(to_save, z_planes):
968993
969994 def plot_images (
970995 z_to_plot ,
996+ z_planes ,
971997 img ,
972998 to_save ,
973999 to_save_largeobjects = None ,
@@ -1002,13 +1028,18 @@ def plot_images(
10021028 fig , axs = plots .two_column_plot (
10031029 nrows = 1 , ncolumns = ncolumns , widthratio = [1 ] * ncolumns
10041030 )
1031+ # to_save's "z" column holds the original (absolute) z-plane
1032+ # number, but img/img_cell/img_bulk/cell_mask/bulk_mask were
1033+ # sliced down to just the in-focus range in process_image --
1034+ # zi converts the absolute plane number back to that local index.
1035+ zi = i [1 ] - 1 - z_planes [0 ]
10051036 col = 0
10061037 puncta_label = (
10071038 "puncta, z plane = " if ncolumns > 1 else "z plane = "
10081039 ) + str (int (i [1 ]))
10091040 axs [col ] = plots .image_scatter_plot (
10101041 axs [col ],
1011- img [i [ 1 ] - 1 , :image_size , :image_size ],
1042+ img [zi , :image_size , :image_size ],
10121043 xdata = xpositions ,
10131044 ydata = ypositions ,
10141045 label = puncta_label ,
@@ -1017,7 +1048,7 @@ def plot_images(
10171048 if to_save_largeobjects is not None :
10181049 axs [col ] = plots .image_scatter_plot (
10191050 axs [col ],
1020- img [i [ 1 ] - 1 , :, :],
1051+ img [zi , :, :],
10211052 xdata = xpositions_large ,
10221053 ydata = ypositions_large ,
10231054 label = "z plane = " + str (int (i [1 ])),
@@ -1026,19 +1057,19 @@ def plot_images(
10261057 if cell_file is not None :
10271058 axs [col ] = plots .image_plot (
10281059 axs [col ],
1029- img_cell [i [ 1 ] - 1 , :, :],
1060+ img_cell [zi , :, :],
10301061 label = "cell, z plane = " + str (int (i [1 ])),
10311062 plotmask = True ,
1032- mask = cell_mask [i [ 1 ] - 1 , :, :],
1063+ mask = cell_mask [zi , :, :],
10331064 )
10341065 col += 1
10351066 if bulk_file is not None :
10361067 axs [col ] = plots .image_plot (
10371068 axs [col ],
1038- img_bulk [i [ 1 ] - 1 , :, :],
1069+ img_bulk [zi , :, :],
10391070 label = "bulk stain, z plane = " + str (int (i [1 ])),
10401071 plotmask = True ,
1041- mask = bulk_mask [i [ 1 ] - 1 , :, :],
1072+ mask = bulk_mask [zi , :, :],
10421073 mask_fill = True ,
10431074 )
10441075 col += 1
@@ -1056,16 +1087,23 @@ def plot_images(
10561087 plt .show ()
10571088
10581089 if len (img .shape ) > 2 :
1059- z_planes , to_save , to_save_largeobjects , cell_mask , bulk_mask = (
1060- process_image (img , img_cell , img_bulk , k1 , k2 )
1061- )
1090+ (
1091+ z_planes ,
1092+ img ,
1093+ img_cell ,
1094+ img_bulk ,
1095+ to_save ,
1096+ to_save_largeobjects ,
1097+ cell_mask ,
1098+ bulk_mask ,
1099+ ) = process_image (img , img_cell , img_bulk , k1 , k2 )
10621100 if lower_lo_size_threshold is not None :
10631101 to_save_largeobjects = to_save_largeobjects .filter (
10641102 (pl .col ("area" ) > lower_lo_size_threshold )
10651103 & (pl .col ("area" ) <= upper_lo_size_threshold )
10661104 )
10671105 if lower_cell_size_threshold is not None :
1068- for i in np .arange (cell_mask .shape [- 1 ]):
1106+ for i in np .arange (cell_mask .shape [0 ]):
10691107 cell_mask [i , :, :], _ , _ , _ = A_F .threshold_cell_areas_2d (
10701108 cell_mask [i , :, :],
10711109 lower_cell_size_threshold = lower_cell_size_threshold ,
@@ -1075,6 +1113,7 @@ def plot_images(
10751113 z_to_plot = filter_z_planes (to_save , z_planes )
10761114 plot_images (
10771115 z_to_plot ,
1116+ z_planes ,
10781117 img ,
10791118 to_save ,
10801119 to_save_largeobjects ,
0 commit comments