Skip to content

Commit e2db096

Browse files
authored
Merge pull request #4 from rkka02/main
Implemented 3DFL reader for LDM file format
2 parents b6444a4 + 1440000 commit e2db096

File tree

1 file changed

+45
-6
lines changed

1 file changed

+45
-6
lines changed

TCFile/TCFile_class.py

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,16 +263,55 @@ def __init__(self, tcfname: str, channel: int = 0):
263263
with h5py.File(self.tcfname) as f:
264264
self.max_channels = self.get_attr(f, f'/Data/{self.imgtype}', 'Channels')
265265

266-
def __getitem__(self, key: int, array_type = 'numpy') -> np.ndarray:
266+
def get_data_location(self, key: int) -> str:
267+
length = len(self)
268+
if not isinstance(key, int):
269+
raise TypeError(f'{self.__class__} indices must be integer, not {type(key)}')
270+
if key < -length or key >= length:
271+
raise IndexError(f'{self.__class__} index out of range')
272+
key = (key + length) % length
273+
# Build the path with the correct channel:
274+
return f'/Data/{self.imgtype}/CH{self.channel}/{key:06d}'
275+
276+
def __getitem__(self, key: int, array_type='numpy') -> np.ndarray:
267277
if array_type == 'numpy':
268278
into_array = np.asarray
279+
zeros = np.zeros
269280
elif array_type == 'dask':
270281
into_array = da.from_array
282+
zeros = da.zeros
271283
else:
272284
raise TypeError('array_type must be either "numpy" or "dask"')
273-
self.imgtype = f'3DFL/CH{self.channel}'
274-
data_path = self.get_data_location(key)
275-
self.imgtype = '3DFL'
276-
data = into_array(h5py.File(self.tcfname)[data_path])
277-
return data
278285

286+
data_path = self.get_data_location(key)
287+
with h5py.File(self.tcfname, 'r') as f:
288+
obj = f[data_path]
289+
# If it's a dataset, do a direct read:
290+
if isinstance(obj, h5py.Dataset):
291+
data = into_array(obj)
292+
return data
293+
# Otherwise, if it's a group, do tile stitching:
294+
elif isinstance(obj, h5py.Group):
295+
# Prepare for stitching:
296+
get_data_attr = lambda attr_name: self.get_attr(f, data_path, attr_name)
297+
is_uint8 = get_data_attr('ScalarType')
298+
# Use proper numpy dtypes:
299+
data_type = np.uint8 if is_uint8 else np.uint16
300+
data = zeros(self.data_shape, dtype=data_type)
301+
tile_path_list = [p for p in obj.keys() if re.match(r'^TILE_\d+$', p)]
302+
tile_path_list.sort()
303+
for tile in tile_path_list:
304+
tile_path = f'{data_path}/{tile}'
305+
get_tile_attr = lambda attr_name: self.get_attr(f, tile_path, attr_name)
306+
if get_tile_attr('SamplingStep') != 1:
307+
continue # skip unsupported tiles
308+
# For each axis, get the tile’s placement info:
309+
offset = [get_tile_attr(f'DataIndexOffsetPoint{axis}') for axis in ('Z', 'Y', 'X')[3-self.data_ndim:]]
310+
last_idx = [get_tile_attr(f'DataIndexLastPoint{axis}') for axis in ('Z', 'Y', 'X')[3-self.data_ndim:]]
311+
mapping_range = tuple(slice(o, l + 1) for o, l in zip(offset, last_idx))
312+
valid_range = tuple(slice(0, l - o + 1) for o, l in zip(offset, last_idx))
313+
tile_data = into_array(f[tile_path])[valid_range]
314+
data[mapping_range] += tile_data
315+
return data
316+
else:
317+
raise TypeError("Unexpected HDF5 object type at data_path")

0 commit comments

Comments
 (0)