55
66from glob import glob
77from pathlib import Path
8- from typing import Optional , List , Dict
8+ from typing import Optional , List , Dict , Tuple
99
1010import numpy as np
1111import pybdv
12- import tifffile
1312
1413from cluster_tools .utils .volume_utils import write_format_metadata
1514from elf .io import open_file
1615from skimage .transform import rescale
1716
17+ from .file_utils import read_tif , read_raw
18+
1819
1920def _read_resolution_and_unit_flamingo (mdata_path ):
2021 resolution = None
@@ -60,7 +61,27 @@ def _read_start_position_flamingo(path):
6061 return start_position
6162
6263
63- def read_metadata_flamingo (metadata_path , offset = None , parse_affine = False ):
64+ def read_metadata_flamingo (
65+ metadata_path : str ,
66+ offset : Optional [np .ndarray ] = None ,
67+ parse_affine : bool = False
68+ ) -> Tuple [List [float ], str , List [float ]]:
69+ """Read acquisition metadata from a flamingo metadata file.
70+
71+ This will read the resolution, the physical unit, and optionally the
72+ voxel grid transformation from the metadata file. The voxel grid transformation
73+ places tile at their correct tile position.
74+
75+ Args:
76+ metadata_path: The path to the metadata file.
77+ offset: The spatial offset of this data.
78+ parse_affine: Whether to read the affine transformation from the metadata.
79+
80+ Returns:
81+ The resolution / voxel size of the data.
82+ The physical unit of the voxel size.
83+ The affine voxel grid transformation of the data.
84+ """
6485 resolution , unit = None , None
6586
6687 resolution , unit = _read_resolution_and_unit_flamingo (metadata_path )
@@ -109,7 +130,7 @@ def _pos_to_trafo(pos):
109130
110131
111132# TODO derive the scale factors from the shape rather than hard-coding it to 5 levels
112- def derive_scale_factors (shape ):
133+ def _derive_scale_factors (shape ):
113134 scale_factors = [[2 , 2 , 2 ]] * 5
114135 return scale_factors
115136
@@ -147,11 +168,25 @@ def _to_ome_zarr(data, out_path, scale_factors, timepoint, setup_id, attributes,
147168 )
148169
149170
150- def flamingo_filename_parser (file_path , name_mapping ):
171+ def flamingo_filename_parser (file_path : str , name_mapping : Optional [Dict ]) -> Tuple [int , Dict [str , str ], str ]:
172+ """Parse the name of flamingo output files.
173+
174+ This maps the filenames to the corresponding timepoint, the BigStitcher
175+ compatible attributes, and the id (name) of the attributes.
176+
177+ Args:
178+ file_path: The path to the flamingo data.
179+ name_mapping: Optional mapping of parsed attributes to their actual names.
180+
181+ Returns:
182+ The timepoint of this data.
183+ The dictionary mapping attribute names to their values.
184+ The normalized attribute names.
185+ """
151186 filename = os .path .basename (file_path )
152187
153188 # Extract the timepoint.
154- match = re .search (r' _t(\d+)_' , filename )
189+ match = re .search (r" _t(\d+)_" , filename )
155190 if match :
156191 timepoint = int (match .group (1 ))
157192 else :
@@ -163,25 +198,25 @@ def flamingo_filename_parser(file_path, name_mapping):
163198 name_mapping = {}
164199
165200 # Extract the channel.
166- match = re .search (r' _C(\d+)_' , filename )
201+ match = re .search (r" _C(\d+)_" , filename )
167202 channel = int (match .group (1 )) if match else 0
168203 channel_mapping = name_mapping .get ("channel" , {})
169204 attributes ["channel" ] = {"id" : channel , "name" : channel_mapping .get (channel , str (channel ))}
170205
171206 # Extract the tile.
172- match = re .search (r' _R(\d+)_' , filename )
207+ match = re .search (r" _R(\d+)_" , filename )
173208 tile = int (match .group (1 )) if match else 0
174209 tile_mapping = name_mapping .get ("tile" , {})
175210 attributes ["tile" ] = {"id" : tile , "name" : tile_mapping .get (tile , str (tile ))}
176211
177212 # Extract the illumination.
178- match = re .search (r' _I(\d+)_' , filename )
213+ match = re .search (r" _I(\d+)_" , filename )
179214 illumination = int (match .group (1 )) if match else 0
180215 illumination_mapping = name_mapping .get ("illumination" , {})
181216 attributes ["illumination" ] = {"id" : illumination , "name" : illumination_mapping .get (illumination , str (illumination ))}
182217
183218 # Extract D. TODO what is this?
184- match = re .search (r' _D(\d+)_' , filename )
219+ match = re .search (r" _D(\d+)_" , filename )
185220 D = int (match .group (1 )) if match else 0
186221 D_mapping = name_mapping .get ("D" , {})
187222 attributes ["D" ] = {"id" : D , "name" : D_mapping .get (D , str (D ))}
@@ -207,35 +242,11 @@ def _write_missing_views(out_path):
207242 tree .write (xml_path )
208243
209244
210- def _parse_shape (metadata_file ):
211- depth , height , width = None , None , None
212-
213- with open (metadata_file , "r" ) as f :
214- for line in f .readlines ():
215- line = line .strip ().rstrip ("\n " )
216- if line .startswith ("AOI width" ):
217- width = int (line .split (" " )[- 1 ])
218- if line .startswith ("AOI height" ):
219- height = int (line .split (" " )[- 1 ])
220- if line .startswith ("Number of planes saved" ):
221- depth = int (line .split (" " )[- 1 ])
222-
223- assert depth is not None
224- assert height is not None
225- assert width is not None
226- return (depth , height , width )
227-
228-
229245def _load_data (file_path , metadata_file ):
230246 if Path (file_path ).suffix == ".raw" :
231- shape = _parse_shape (metadata_file )
232- data = np .memmap (file_path , mode = "r" , dtype = "uint16" , shape = shape )
247+ data = read_raw (file_path , metadata_file )
233248 else :
234- try :
235- data = tifffile .memmap (file_path , mode = "r" )
236- except ValueError :
237- print (f"Could not memmap the data from { file_path } . Fall back to load it into memory." )
238- data = tifffile .imread (file_path )
249+ data = read_tif (file_path )
239250 return data
240251
241252
@@ -360,7 +371,7 @@ def convert_lightsheet_to_bdv(
360371 print (f"Converting tp={ timepoint } , channel={ attributes ['channel' ]} , tile={ attributes ['tile' ]} " )
361372 data = _load_data (file_path , metadata_file )
362373 if scale_factors is None :
363- scale_factors = derive_scale_factors (data .shape )
374+ scale_factors = _derive_scale_factors (data .shape )
364375
365376 if convert_to_ome_zarr :
366377 _to_ome_zarr (data , out_path , scale_factors , timepoint , setup_id , attributes , unit , resolution )
@@ -387,6 +398,8 @@ def convert_lightsheet_to_bdv(
387398
388399
389400def convert_lightsheet_to_bdv_cli ():
401+ """@private
402+ """
390403 import argparse
391404
392405 parser = argparse .ArgumentParser (
0 commit comments