1
+ import json
1
2
import math
2
- from typing import Dict
3
3
from typing import List
4
+ from typing import Tuple
4
5
from typing import Union
5
6
6
7
import anndata as ad
10
11
11
12
def prepare_FOV_ROI_table (
12
13
df : pd .DataFrame ,
13
- image_size : Union [Dict , None ] = None ,
14
- well_size_z : int = None ,
15
14
) -> ad .AnnData :
16
15
17
- if image_size is None :
18
- raise Exception ("Missing image_size arg in prepare_ROIs_table" )
19
- if well_size_z is None :
20
- raise Exception ("Missing well_size_z arg in prepare_ROIs_table" )
16
+ for mu in ["x" , "y" , "z" ]:
21
17
22
- # Reset reference values for coordinates
23
- df ["x_micrometer" ] -= df ["x_micrometer" ].min ()
24
- df ["y_micrometer" ] -= df ["y_micrometer" ].min ()
25
- df ["z_micrometer" ] -= df ["z_micrometer" ].min ()
18
+ # Reset reference values for coordinates
19
+ df [f"{ mu } _micrometer" ] -= df [f"{ mu } _micrometer" ].min ()
26
20
27
- # Obtain box size in physical units
28
- df ["len_x_micrometer" ] = image_size ["x" ] * df ["pixel_size_x" ]
29
- df ["len_y_micrometer" ] = image_size ["y" ] * df ["pixel_size_y" ]
30
- df ["len_z_micrometer" ] = well_size_z * df ["pixel_size_z" ]
21
+ # Obtain box size in physical units
22
+ df [f"len_{ mu } _micrometer" ] = df [f"{ mu } _pixel" ] * df [f"pixel_size_{ mu } " ]
23
+
24
+ # Remove information about pixel sizes in physical units
25
+ df .drop (f"pixel_size_{ mu } " , inplace = True , axis = 1 )
26
+
27
+ # Remove information about array size in pixels
28
+ df .drop (f"{ mu } _pixel" , inplace = True , axis = 1 )
31
29
32
30
# Remove unused column
33
31
df .drop ("bit_depth" , inplace = True , axis = 1 )
@@ -52,22 +50,17 @@ def prepare_FOV_ROI_table(
52
50
return adata
53
51
54
52
55
- def convert_FOV_ROIs_3D_to_2D (adata : ad .AnnData = None ) -> ad .AnnData :
53
+ def convert_FOV_ROIs_3D_to_2D (
54
+ adata : ad .AnnData = None , pixel_size_z : float = None
55
+ ) -> ad .AnnData :
56
56
57
- # FIXME: use this piece of code (or similar) in tests
58
- """
59
- adata = ad.AnnData(X=np.zeros((2, 3)), dtype=int)
60
- adata.obs_names = ["FOV1", "FOV2"]
61
- adata.var_names = ["z", "len_z", "pixel_size_z"]
62
- adata[:, "z"].X = [[2], [4]]
63
- adata[:, "len_z"].X = [[5], [7]]
64
- adata[:, "pixel_size_z"].X = [[2], [2]]
65
- """
57
+ if pixel_size_z is None :
58
+ raise Exception ("Missing pixel_size_z in convert_FOV_ROIs_3D_to_2D" )
66
59
67
60
# Compress a 3D stack of images to a single Z plane,
68
61
# with thickness equal to pixel_size_z
69
62
df = adata .to_df ()
70
- df ["len_z_micrometer" ] = df [ " pixel_size_z" ]
63
+ df ["len_z_micrometer" ] = pixel_size_z
71
64
72
65
# Assign dtype explicitly, to avoid
73
66
# >> UserWarning: X converted to numpy array with dtype float64
@@ -88,10 +81,13 @@ def convert_ROI_table_to_indices(
88
81
ROI : ad .AnnData ,
89
82
level : int = 0 ,
90
83
coarsening_xy : int = 2 ,
91
- ) -> List [List ]:
84
+ pixel_sizes_zyx : Union [List [float ], Tuple [float ]] = None ,
85
+ ) -> List [List [int ]]:
92
86
93
87
list_indices = []
94
88
89
+ pixel_size_z , pixel_size_y , pixel_size_x = pixel_sizes_zyx
90
+
95
91
for FOV in sorted (ROI .obs_names ):
96
92
97
93
# Extract data from anndata table
@@ -101,9 +97,6 @@ def convert_ROI_table_to_indices(
101
97
len_x_micrometer = ROI [FOV , "len_x_micrometer" ].X [0 , 0 ]
102
98
len_y_micrometer = ROI [FOV , "len_y_micrometer" ].X [0 , 0 ]
103
99
len_z_micrometer = ROI [FOV , "len_z_micrometer" ].X [0 , 0 ]
104
- pixel_size_x = ROI [FOV , "pixel_size_x" ].X [0 , 0 ]
105
- pixel_size_y = ROI [FOV , "pixel_size_y" ].X [0 , 0 ]
106
- pixel_size_z = ROI [FOV , "pixel_size_z" ].X [0 , 0 ]
107
100
108
101
# Set pyramid-level pixel sizes
109
102
prefactor = coarsening_xy ** level
@@ -151,7 +144,10 @@ def split_3D_indices_into_z_layers(
151
144
152
145
153
146
def _inspect_ROI_table (
154
- path : str = None , level : int = 0 , coarsening_xy : int = 2
147
+ path : str = None ,
148
+ level : int = 0 ,
149
+ coarsening_xy : int = 2 ,
150
+ pixel_sizes_zyx = [1.0 , 0.1625 , 0.1625 ],
155
151
) -> None :
156
152
157
153
adata = ad .read_zarr (path )
@@ -161,7 +157,10 @@ def _inspect_ROI_table(
161
157
print ()
162
158
163
159
list_indices = convert_ROI_table_to_indices (
164
- adata , level = level , coarsening_xy = coarsening_xy
160
+ adata ,
161
+ level = level ,
162
+ coarsening_xy = coarsening_xy ,
163
+ pixel_sizes_zyx = pixel_sizes_zyx ,
165
164
)
166
165
167
166
list_indices = split_3D_indices_into_z_layers (list_indices )
@@ -174,10 +173,120 @@ def _inspect_ROI_table(
174
173
print ()
175
174
176
175
176
+ def temporary_test ():
177
+
178
+ pixel_size_z = 1.0
179
+ pixel_size_y = 0.1625
180
+ pixel_size_x = 0.1625
181
+
182
+ df = pd .DataFrame (np .zeros ((2 , 10 )), dtype = int )
183
+ df .index = ["FOV1" , "FOV2" ]
184
+ df .columns = [
185
+ "x_micrometer" ,
186
+ "y_micrometer" ,
187
+ "z_micrometer" ,
188
+ "x_pixel" ,
189
+ "y_pixel" ,
190
+ "z_pixel" ,
191
+ "pixel_size_x" ,
192
+ "pixel_size_y" ,
193
+ "pixel_size_z" ,
194
+ "bit_depth" ,
195
+ ]
196
+ df ["x_micrometer" ] = [0.0 , 416.0 ]
197
+ df ["y_micrometer" ] = [0.0 , 0.0 ]
198
+ df ["z_micrometer" ] = [0.0 , 0.0 ]
199
+ df ["x_pixel" ] = [2560 , 2560 ]
200
+ df ["y_pixel" ] = [2160 , 2160 ]
201
+ df ["z_pixel" ] = [5 , 5 ]
202
+ df ["pixel_size_x" ] = [pixel_size_x ] * 2
203
+ df ["pixel_size_y" ] = [pixel_size_y ] * 2
204
+ df ["pixel_size_z" ] = [pixel_size_z ] * 2
205
+ df ["bit_depth" ] = [16.0 , 16.0 ]
206
+
207
+ print ("DataFrame" )
208
+ print (df )
209
+ print ()
210
+
211
+ adata = prepare_FOV_ROI_table (df )
212
+
213
+ print ("AnnData table" )
214
+ print (adata .var_names )
215
+ print (adata .obs_names )
216
+ print (adata .X )
217
+ print ()
218
+
219
+ print ("Indices 3D" )
220
+ pixel_sizes_zyx = [pixel_size_z , pixel_size_y , pixel_size_x ]
221
+ list_indices = convert_ROI_table_to_indices (
222
+ adata , level = 0 , coarsening_xy = 2 , pixel_sizes_zyx = pixel_sizes_zyx
223
+ )
224
+ for indices in list_indices :
225
+ print (indices )
226
+ print ()
227
+
228
+ print ("Indices 3D / split" )
229
+ list_indices = split_3D_indices_into_z_layers (list_indices )
230
+ for indices in list_indices :
231
+ print (indices )
232
+ print ()
233
+
234
+ print ("Indices 2D" )
235
+ adata = convert_FOV_ROIs_3D_to_2D (adata , pixel_size_z )
236
+ list_indices = convert_ROI_table_to_indices (
237
+ adata , level = 0 , coarsening_xy = 2 , pixel_sizes_zyx = pixel_sizes_zyx
238
+ )
239
+ for indices in list_indices :
240
+ print (indices )
241
+ print ()
242
+
243
+
244
+ def extract_zyx_pixel_sizes_from_zattrs (zattrs_path : str , level : int = 0 ):
245
+ with open (zattrs_path , "r" ) as jsonfile :
246
+ zattrs = json .load (jsonfile )
247
+
248
+ try :
249
+
250
+ # Identify multiscales
251
+ multiscales = zattrs ["multiscales" ]
252
+
253
+ # Check that there is a single multiscale
254
+ if len (multiscales ) > 1 :
255
+ raise Exception (f"ERROR: There are { len (multiscales )} multiscales" )
256
+
257
+ # Check that there are no datasets-global transformations
258
+ if "coordinateTransformations" in multiscales [0 ].keys ():
259
+ raise Exception (
260
+ "ERROR: coordinateTransformations at the multiscales "
261
+ "level are not currently supported"
262
+ )
263
+
264
+ # Identify all datasets (AKA pyramid levels)
265
+ datasets = multiscales [0 ]["datasets" ]
266
+
267
+ # Select highest-resolution dataset
268
+ transformations = datasets [level ]["coordinateTransformations" ]
269
+ for t in transformations :
270
+ if t ["type" ] == "scale" :
271
+ return t ["scale" ]
272
+ raise Exception (
273
+ "ERROR:"
274
+ f" no scale transformation found for level { level } "
275
+ f" in { zattrs_path } "
276
+ )
277
+
278
+ except KeyError as e :
279
+ raise KeyError (
280
+ "extract_zyx_pixel_sizes_from_zattrs failed, for {zattrs_path}\n " ,
281
+ e ,
282
+ )
283
+
284
+
177
285
if __name__ == "__main__" :
178
- import sys
286
+ # import sys
287
+ # args = sys.argv[1:]
288
+ # types = [str, int, int]
289
+ # args = [types[ix](x) for ix, x in enumerate(args)]
290
+ # _inspect_ROI_table(*args)
179
291
180
- args = sys .argv [1 :]
181
- types = [str , int , int ]
182
- args = [types [ix ](x ) for ix , x in enumerate (args )]
183
- _inspect_ROI_table (* args )
292
+ temporary_test ()
0 commit comments