|
@@ -1,9 +1,5 @@
|
|
from pathlib import Path
|
|
from pathlib import Path
|
|
-import xmltodict
|
|
|
|
import argparse
|
|
import argparse
|
|
-
|
|
|
|
-import javabridge
|
|
|
|
-import bioformats
|
|
|
|
import numpy as np
|
|
import numpy as np
|
|
import nibabel as nib
|
|
import nibabel as nib
|
|
from PIL import Image, ImageSequence
|
|
from PIL import Image, ImageSequence
|
|
@@ -11,6 +7,9 @@ from scipy import ndimage
|
|
from skimage import morphology, filters
|
|
from skimage import morphology, filters
|
|
from nipype.interfaces.ants.segmentation import N4BiasFieldCorrection
|
|
from nipype.interfaces.ants.segmentation import N4BiasFieldCorrection
|
|
|
|
|
|
|
|
+import warnings
|
|
|
|
+warnings.simplefilter(action='ignore', category=FutureWarning)
|
|
|
|
+
|
|
|
|
|
|
def get_out_paths(out_dir, stem):
|
|
def get_out_paths(out_dir, stem):
|
|
out_path_scaled = Path(out_dir, f'{stem}.nii')
|
|
out_path_scaled = Path(out_dir, f'{stem}.nii')
|
|
@@ -27,12 +26,6 @@ def bias_field_correction(image, output, dim=2):
|
|
|
|
|
|
|
|
|
|
def image_data_to_nii(pixdim, image_data, shrink, out_dir, file_path, save_unscaled=False):
|
|
def image_data_to_nii(pixdim, image_data, shrink, out_dir, file_path, save_unscaled=False):
|
|
- """
|
|
|
|
- Saves an array of image data as a nifti file, with correct pixel dimensions in
|
|
|
|
- :param save_unscaled: boolean whether to save unscaled, as well as scaled nifti file
|
|
|
|
- :param shrink: factor by which to shrink image dimensions by
|
|
|
|
- :return: location of scaled and possibly unscaled nifti files
|
|
|
|
- """
|
|
|
|
image_dim = (image_data.shape[0], image_data.shape[1])
|
|
image_dim = (image_data.shape[0], image_data.shape[1])
|
|
scale = 1/shrink
|
|
scale = 1/shrink
|
|
new_dim = (round(image_dim[1] * scale), round(image_dim[0] * scale))
|
|
new_dim = (round(image_dim[1] * scale), round(image_dim[0] * scale))
|
|
@@ -57,22 +50,8 @@ def image_data_to_nii(pixdim, image_data, shrink, out_dir, file_path, save_unsca
|
|
return path_scaled, path_unscaled
|
|
return path_scaled, path_unscaled
|
|
|
|
|
|
|
|
|
|
-def nd2_to_nii(nd2_path, out_dir, series, shrink=10):
|
|
|
|
- """
|
|
|
|
- Wrapper function for image_data_to_nii, for converting nd2 files to nifti
|
|
|
|
- """
|
|
|
|
- javabridge.start_vm(bioformats.JARS)
|
|
|
|
- image = np.array(bioformats.load_image(str(nd2_path), series=series-1, rescale=False))
|
|
|
|
- meta_dict = xmltodict.parse(bioformats.get_omexml_metadata(str(nd2_path)))
|
|
|
|
- vox_size_x = float(meta_dict['OME']['Image'][series-1]['Pixels']['@PhysicalSizeX'])
|
|
|
|
- javabridge.kill_vm()
|
|
|
|
- return image_data_to_nii(vox_size_x, image, shrink, out_dir, nd2_path)
|
|
|
|
-
|
|
|
|
-
|
|
|
|
def tiff_to_nii(tif_path, out_dir, pixdim=None, shrink=10):
|
|
def tiff_to_nii(tif_path, out_dir, pixdim=None, shrink=10):
|
|
- """
|
|
|
|
- Wrapper function for image_data_to_nii, for converting tiff files to nifti
|
|
|
|
- """
|
|
|
|
|
|
+ Image.MAX_IMAGE_PIXELS = None
|
|
tif_image = Image.open(tif_path)
|
|
tif_image = Image.open(tif_path)
|
|
tif_header = dict(tif_image.tag)
|
|
tif_header = dict(tif_image.tag)
|
|
output = np.empty(np.array(tif_image).shape + (0,))
|
|
output = np.empty(np.array(tif_image).shape + (0,))
|
|
@@ -85,13 +64,6 @@ def tiff_to_nii(tif_path, out_dir, pixdim=None, shrink=10):
|
|
|
|
|
|
|
|
|
|
def split_nii_channels(nii_path, out_dir=None, flip=False, mask_index=-1, bias=False):
|
|
def split_nii_channels(nii_path, out_dir=None, flip=False, mask_index=-1, bias=False):
|
|
- """
|
|
|
|
- Converts a single multi-channel nifti file to multiple single-channel nifti files, and masks foreground
|
|
|
|
- :param flip: Whether to vertically flip the image, in order to properly align nifti file with template
|
|
|
|
- :param mask_index: index of DAPI stained channel, on which to mask other channels on
|
|
|
|
- :param bias: whether to bias-field correct the image
|
|
|
|
- :return: Location of multiple single-channel nifti files
|
|
|
|
- """
|
|
|
|
if out_dir is None:
|
|
if out_dir is None:
|
|
out_dir = nii_path.parent
|
|
out_dir = nii_path.parent
|
|
nii = nib.load(str(nii_path))
|
|
nii = nib.load(str(nii_path))
|
|
@@ -108,10 +80,8 @@ def split_nii_channels(nii_path, out_dir=None, flip=False, mask_index=-1, bias=F
|
|
|
|
|
|
if flip:
|
|
if flip:
|
|
channel_data = np.flip(channel_data, 1)
|
|
channel_data = np.flip(channel_data, 1)
|
|
-
|
|
|
|
if i == mask_index:
|
|
if i == mask_index:
|
|
channel_data = mask_foreground(channel_data)
|
|
channel_data = mask_foreground(channel_data)
|
|
- channel_data = channel_data/np.mean(channel_data)
|
|
|
|
|
|
|
|
new_header = nii_header
|
|
new_header = nii_header
|
|
new_header['dim'][0] = 2
|
|
new_header['dim'][0] = 2
|
|
@@ -130,9 +100,6 @@ def split_nii_channels(nii_path, out_dir=None, flip=False, mask_index=-1, bias=F
|
|
|
|
|
|
|
|
|
|
def mask_foreground(raw_data):
|
|
def mask_foreground(raw_data):
|
|
- """
|
|
|
|
- Mask the foreground of an image, using otsu threshold and connected components to remove background noise
|
|
|
|
- """
|
|
|
|
raw_max = raw_data.max()
|
|
raw_max = raw_data.max()
|
|
raw_data = raw_data / raw_max
|
|
raw_data = raw_data / raw_max
|
|
blurred_data = ndimage.gaussian_filter(raw_data, 4)
|
|
blurred_data = ndimage.gaussian_filter(raw_data, 4)
|
|
@@ -152,13 +119,13 @@ def mask_foreground(raw_data):
|
|
closed = morphology.binary_closing(foreground_mask, selem=morphology.square(30))
|
|
closed = morphology.binary_closing(foreground_mask, selem=morphology.square(30))
|
|
raw_data = np.where(closed, raw_data, 0)
|
|
raw_data = np.where(closed, raw_data, 0)
|
|
return raw_data * raw_max
|
|
return raw_data * raw_max
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+
|
|
if __name__ == '__main__':
|
|
if __name__ == '__main__':
|
|
parser = argparse.ArgumentParser()
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("file", help="Location of file to process")
|
|
parser.add_argument("file", help="Location of file to process")
|
|
parser.add_argument("dir", help="Directory for preprocessed Files")
|
|
parser.add_argument("dir", help="Directory for preprocessed Files")
|
|
- parser.add_argument("-s", type=int, help="Series to extract")
|
|
|
|
|
|
+ parser.add_argument("-s", "--series", type=int, help="Series to extract")
|
|
|
|
+ parser.add_argument('-b', type=bool, default= True, help='Bias field correct image')
|
|
parser.add_argument('--pdim', type=float, help='Pixel dimensions (Retrieved from Tiff file if not set)')
|
|
parser.add_argument('--pdim', type=float, help='Pixel dimensions (Retrieved from Tiff file if not set)')
|
|
args = parser.parse_args()
|
|
args = parser.parse_args()
|
|
|
|
|
|
@@ -167,3 +134,5 @@ if __name__ == '__main__':
|
|
n_path = tiff_to_nii(Path(args.file), Path(args.dir))
|
|
n_path = tiff_to_nii(Path(args.file), Path(args.dir))
|
|
elif filetype == '.nd2':
|
|
elif filetype == '.nd2':
|
|
n_path = nd2_to_nii(Path(args.file), Path(args.dir), args.series)
|
|
n_path = nd2_to_nii(Path(args.file), Path(args.dir), args.series)
|
|
|
|
+ elif filetype == '.nii':
|
|
|
|
+ n_path = Path(args.file)
|