120 lines
5.3 KiB
Python
120 lines
5.3 KiB
Python
|
"""
|
||
|
Convert to VTK. Use pvti files for final assembly.
|
||
|
"""
|
||
|
|
||
|
import os
|
||
|
import logging
|
||
|
import math
|
||
|
from argparse import ArgumentParser
|
||
|
from functools import partial
|
||
|
import multiprocessing as mp
|
||
|
import vtk
|
||
|
import utility
|
||
|
import extract_zeiss_metadata
|
||
|
|
||
|
|
||
|
def do_conversion(file_attributes, working_directory):
|
||
|
|
||
|
reader = vtk.vtkTIFFReader()
|
||
|
reader.SetFileName(file_attributes["FileName"])
|
||
|
reader.Update()
|
||
|
|
||
|
image_data = reader.GetOutput()
|
||
|
image_data.SetExtent(file_attributes["Extents"])
|
||
|
image_data.SetSpacing(file_attributes["PhysicalSize"])
|
||
|
|
||
|
out_path = working_directory + "/" + os.path.splitext(os.path.basename(file_attributes["FileName"]))[0] + ".vti"
|
||
|
writer = vtk.vtkXMLImageDataWriter()
|
||
|
writer.SetInputData(image_data)
|
||
|
writer.SetFileName(out_path)
|
||
|
writer.Write()
|
||
|
|
||
|
def convert_to_vti(input_folder, metadata_file, tile_dimensions, downsample_dimensions):
|
||
|
|
||
|
extract_zeiss_metadata.extract_metadata(metadata_file, os.getcwd() + "temp_metadata.xml")
|
||
|
image_metadata = extract_zeiss_metadata.get_metadata_as_class(os.getcwd() + "temp_metadata.xml")
|
||
|
|
||
|
num_x = int(math.floor(image_metadata.Image[0].Pixels.SizeX/tile_dimensions[0]))+1
|
||
|
num_y = int(math.floor(image_metadata.Image[0].Pixels.SizeY/tile_dimensions[1]))+1
|
||
|
size_x = int(math.floor(tile_dimensions[0]/downsample_dimensions[0]))+1
|
||
|
size_y = int(math.floor(tile_dimensions[1]/downsample_dimensions[1]))+1
|
||
|
size_z = int(math.floor(image_metadata.Image[0].Pixels.SizeZ/downsample_dimensions[2]))
|
||
|
physical_x = float(image_metadata.Image[0].Pixels.PhysicalSizeX)*float(downsample_dimensions[0])
|
||
|
physical_y = float(image_metadata.Image[0].Pixels.PhysicalSizeY)*float(downsample_dimensions[1])
|
||
|
physical_z = float(image_metadata.Image[0].Pixels.PhysicalSizeZ)*float(downsample_dimensions[2])
|
||
|
|
||
|
# Grab the file base name. Assume the input folder only has the tiff files we want to convert
|
||
|
path_base_name = ""
|
||
|
for eachFile in os.listdir(input_folder):
|
||
|
if eachFile.endswith(".tiff"):
|
||
|
loc_start_index = eachFile.find("_tile")
|
||
|
if loc_start_index>-1:
|
||
|
path_base_name = input_folder + "/" + eachFile[:loc_start_index]
|
||
|
break
|
||
|
|
||
|
file_attribute_collection = []
|
||
|
for jdx in range(num_y):
|
||
|
for idx in range(num_x):
|
||
|
global_index = idx + jdx*num_x
|
||
|
file_name = path_base_name + "_tile_X" + str(idx) + "_Y" + str(jdx) + "_ID_" + str(global_index)+"_pixels_only_downsampled.tiff"
|
||
|
min_ext_x = idx*size_x
|
||
|
min_ext_y = jdx*size_y
|
||
|
max_ext_x = (idx+1)*size_x-1
|
||
|
max_ext_y = (jdx+1)*size_y-1
|
||
|
min_ext_z = 0
|
||
|
max_ext_z = size_z-1
|
||
|
if idx == num_x - 1:
|
||
|
max_ext_x = int(math.floor(image_metadata.Image[0].Pixels.SizeX/downsample_dimensions[0]))+2
|
||
|
if jdx == num_y - 1:
|
||
|
max_ext_y = int(math.floor(image_metadata.Image[0].Pixels.SizeY/downsample_dimensions[1]))+2
|
||
|
extents = [min_ext_x, max_ext_x, min_ext_y, max_ext_y, min_ext_z, max_ext_z]
|
||
|
file_attributes = {}
|
||
|
file_attributes["PhysicalSize"]= (physical_x, physical_y, physical_z)
|
||
|
file_attributes["Extents"]= extents
|
||
|
file_attributes["FileName"]= file_name
|
||
|
file_attribute_collection.append(file_attributes)
|
||
|
|
||
|
# Make a partial function for multiple arg mapping
|
||
|
working_directory = os.getcwd() + "/VTK_Files/"
|
||
|
if not os.path.exists(working_directory):
|
||
|
os.makedirs(working_directory)
|
||
|
partial_extract_pixel_values_only = partial(do_conversion, working_directory=working_directory)
|
||
|
|
||
|
# Limit to max 6 cpus
|
||
|
num_available_cpus = mp.cpu_count()
|
||
|
if num_available_cpus > 6:
|
||
|
num_available_cpus = 6
|
||
|
|
||
|
# Distribute across processes - Be conservative with available CPUs
|
||
|
run_cpus = int(math.floor(num_available_cpus/2))
|
||
|
if run_cpus == 0:
|
||
|
run_cpus = 1
|
||
|
#pool = mp.Pool(processes = run_cpus)
|
||
|
pool = mp.Pool(processes = 1)
|
||
|
pool.map(partial_extract_pixel_values_only, file_attribute_collection)
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
|
||
|
# Do setup
|
||
|
tool_name = "zeiss_to_tiff"
|
||
|
utility.do_setup(tool_name)
|
||
|
logger1 = logging.getLogger('tiff_to_vtk.'+tool_name)
|
||
|
|
||
|
# Suppress XML Parse warnings
|
||
|
pyxb_logger = logging.getLogger('pyxb')
|
||
|
pyxb_logger.setLevel(logging.CRITICAL)
|
||
|
|
||
|
parser = ArgumentParser()
|
||
|
parser.add_argument("-i", "--input_folder", type=str, help='Folder with tiffs to be converted.')
|
||
|
parser.add_argument("-m", "--metadatafile", type=str, help='File with image metadata.')
|
||
|
parser.add_argument("-tx", "--tile_x", type=int, help='X Tile size.')
|
||
|
parser.add_argument("-ty", "--tile_y", type=int, help='Y Tile Size.')
|
||
|
parser.add_argument("-dx", "--downsample_x", type=int, help='X Downsample Factor.', default=1)
|
||
|
parser.add_argument("-dy", "--downsample_y", type=int, help='Y Downsample Factor.', default=1)
|
||
|
parser.add_argument("-dz", "--downsample_z", type=int, help='Y Downsample Factor.', default=1)
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
logger1.info('Start Converting Images to VTI at: ' + args.input_folder)
|
||
|
convert_to_vti(args.input_folder, args.metadatafile, (args.tile_x, args.tile_y),
|
||
|
(args.downsample_x, args.downsample_y, args.downsample_z))
|
||
|
logger1.info('Completed Converting')
|