from coseda.logging_utils import log_print
import os
import gc
import h5py
import numpy as np
import ncempy.io as nio
import datetime
from coseda.io import handle_input, parse_config
from coseda.logging_utils import log_start, log_result, shoutout
[docs]
def bin_chunk(chunk, bin_factor):
""" Bins the chunk of images by the specified bin factor. """
if chunk.ndim == 3:
n_frames, height, width = chunk.shape
new_height = height // bin_factor
new_width = width // bin_factor
chunk_binned = chunk.reshape(n_frames, new_height, bin_factor, new_width, bin_factor).mean(axis=(2, 4))
elif chunk.ndim == 2:
height, width = chunk.shape
new_height = height // bin_factor
new_width = width // bin_factor
chunk_binned = chunk.reshape(new_height, bin_factor, new_width, bin_factor).mean(axis=(1, 3))
return chunk_binned
[docs]
def get_stage_position(dm4file):
""" Extract the stage position from the DM4 file's metadata. """
# Example key, adjust based on your file's metadata structure
stage_position_key = '.ImageList.1.ImageTags.Microscope Info.Stage Position'
stage_position = dm4file.allTags.get(stage_position_key, None)
if stage_position is None:
log_print("Warning: Stage position not found in metadata.")
return stage_position
[docs]
def process_and_save_h5(dm4_file_path, output_h5_file, bin_factor):
""" Process DM4 file and save it as an HDF5 file. """
# Log start
log_print(f'Starting HDF5 conversion of {dm4_file_path}')
starttime = datetime.datetime.now()
# Load DM4 file
with nio.dm.fileDM(dm4_file_path) as dm4file:
# Extract stage position from metadata
stage_position = get_stage_position(dm4file)
# Assuming the image data is in the first dataset
dm4_data = dm4file.getDataset(0)['data']
if dm4_data.ndim == 3:
n_frames, height, width = dm4_data.shape
elif dm4_data.ndim == 2:
height, width = dm4_data.shape
n_frames = 1
dm4_data = dm4_data[None, :, :] # Add a new axis for consistency
if bin_factor > 1:
new_height = height // bin_factor
new_width = width // bin_factor
else:
new_height, new_width = height, width
chunk_size = 20 # Adjust as needed
with h5py.File(output_h5_file, 'w') as h5f:
dset = h5f.create_dataset('entry/data/images', shape=(n_frames, new_height, new_width), dtype=np.float32)
for i in range(0, n_frames, chunk_size):
end = min(i + chunk_size, n_frames)
chunk_data = dm4_data[i:end, :, :].astype(np.float32)
if bin_factor > 1:
chunk_data = bin_chunk(chunk_data, bin_factor)
dset[i:end, :, :] = chunk_data
# Cleanup
del dm4_data
gc.collect()
runtime = datetime.datetime.now() - starttime
# Log end
log_print(f'HDF5 conversion successful, written to {output_h5_file}, {n_frames} frames, {height} by {width}px, finished in {runtime}')
[docs]
def dm4_to_h5(dm4_file_path, output_folder, bin_factor=1):
""" Converts a DM4 file to an HDF5 file. """
if not os.path.exists(output_folder):
os.makedirs(output_folder)
outputfile = os.path.splitext(os.path.basename(dm4_file_path))[0] + '.h5'
output_h5_file = os.path.join(output_folder, outputfile)
process_and_save_h5(dm4_file_path, output_h5_file, bin_factor)