def boundaries( atlas, boundaries_out_path, atlas_labels=False, atlas_scale=None, transformation_matrix=None, ): """ Generate the boundary image, which is the border between each segmentation region. Useful for overlaying on the raw image to assess the registration and segmentation :param atlas: The registered atlas :param boundaries_out_path: Path to save the boundary image :param atlas_labels: If True, keep the numerical values of the atlas for the labels :param atlas_scale: Image scaling so that the resulting nifti can be processed using other tools. :param transformation_matrix: Transformation matrix so that the resulting nifti can be processed using other tools. """ boundaries_image = find_boundaries(atlas, mode="inner") if atlas_labels: boundaries_image = boundaries_image * atlas boundaries_image = scale_and_convert_to_16_bits(boundaries_image) logging.debug("Saving segmentation boundary image") brainio.to_nii( boundaries_image, boundaries_out_path, scale=atlas_scale, affine_transform=transformation_matrix, )
def filter_image(brain): """ Filter a 3D image to allow registration :return: The filtered brain :rtype: np.array """ brain = brain.astype(np.float64, copy=False) for i in trange(brain.shape[-1], desc="filtering", unit="plane"): brain[..., i] = filter_plane(brain[..., i]) brain = scale_and_convert_to_16_bits(brain) return brain
def filter_for_registration(brain): """ A static method to filter a 3D image to allow registration (avoids overfitting details in the image) (algorithm from Alex Brown). The filter is composed of a despeckle filter using opening and a pseudo flatfield filter :return: The filtered brain :rtype: np.array """ brain = brain.astype(np.float64, copy=False) # OPTIMISE: could multiprocess but not slow for i in trange(brain.shape[-1], desc="filtering", unit="plane"): # OPTIMISE: see if in place better brain[..., i] = filter_plane_for_registration(brain[..., i]) brain = scale_and_convert_to_16_bits(brain) return brain
def run( downsampled_points, atlas, downsampled_shape, registered_atlas_path, output_filename, smoothing=None, mask=True, ): points = pd.read_hdf(downsampled_points).values bins = get_bins(downsampled_shape, (1, 1, 1)) heatmap_array, _ = np.histogramdd(points, bins=bins) heatmap_array = heatmap_array.astype(np.uint16) if smoothing is not None: logging.debug("Smoothing heatmap") # assume isotropic atlas smoothing = int(round(smoothing / atlas.resolution[0])) heatmap_array = gaussian(heatmap_array, sigma=smoothing) if mask: logging.debug("Masking image based on registered atlas") atlas = tifffile.imread(registered_atlas_path) heatmap_array = mask_image_threshold(heatmap_array, atlas) del atlas logging.debug("Saving heatmap") heatmap_array = scale_and_convert_to_16_bits(heatmap_array) logging.debug("Ensuring output directory exists") ensure_directory_exists(Path(output_filename).parent) logging.debug("Saving heatmap image") imio.to_tiff(heatmap_array, output_filename)
def generate_region_volume( structure_names, atlas_path, output_path, atlas_config, glass=False ): structure_csv_file = get_structures_path() reference_structures_table = pd.read_csv(structure_csv_file) # ensure all names are valid for indv_structure_name in structure_names: try: get_substructures(indv_structure_name, reference_structures_table) except IndexError: raise ValueError( f"Brain region: '{indv_structure_name}' cannot be found " f"in file: {structure_csv_file}. Please choose " f"another structure." ) print(f"Loading atlas from: {atlas_path}") atlas = brainio.load_nii(atlas_path, as_array=False) atlas_scale = atlas.header.get_zooms() atlas = atlas.get_data() transformation_matrix = nii.get_transformation_matrix(atlas_config) if len(structure_names) > 1: # Initialise an image to add each subimage to. final_image = np.zeros_like(atlas) for indv_structure_name in structure_names: print(f"Analysing brain region: {indv_structure_name}") substructures = get_substructures( indv_structure_name, reference_structures_table ) print("This includes structures:") indv_substructure_names = substructures["name"].values for indv_substructure_name in indv_substructure_names: print(indv_substructure_name) list_vals = substructures["id"].values print("Generating image with specified regions \n") sub_image = np.isin(atlas, list_vals) if glass: print("Generating glass brain") sub_image = sk_segmentation.find_boundaries(sub_image) # If multiple structures, add them together if len(structure_names) > 1: final_image = np.logical_or(final_image, sub_image) else: final_image = sub_image print("Converting image to 16 bit") final_image = scale_and_convert_to_16_bits(final_image) print("Saving image") brainio.to_nii( final_image, output_path, scale=atlas_scale, affine_transform=transformation_matrix, ) print(f"Saved image at: {output_path}")
def test_scale_to_16_bits(): validate_2d_img_uint16 = validate_2d_img.astype(np.uint16, copy=False) assert (validate_2d_img_uint16 == scale.scale_and_convert_to_16_bits( test_2d_img)).all()
def run( cells_file, output_filename, target_size, raw_image_shape, raw_image_bin_sizes, transformation_matrix, atlas_scale, smoothing=10, mask=True, atlas=None, cells_only=True, convert_16bit=True, ): """ :param cells_file: Cellfinder output cells file. :param output_filename: File to save heatmap into :param target_size: Size of the final heatmap :param raw_image_shape: Size of the raw data (coordinate space of the cells) :param raw_image_bin_sizes: List/tuple of the sizes of the bins in the raw data space :param transformation_matrix: Transformation matrix so that the resulting nifti can be processed using other tools. :param atlas_scale: Image scaling so that the resulting nifti can be processed using other tools. :param smoothing: Smoothing kernel size, in the target image space :param mask: Whether or not to mask the heatmap based on an atlas file :param atlas: Atlas file to mask the heatmap :param cells_only: Only use "cells", not artefacts :param convert_16bit: Convert final image to 16 bit """ # TODO: compare the smoothing effects of gaussian filtering, and upsampling target_size = convert_shape_dict_to_array_shape(target_size, type="fiji") raw_image_shape = convert_shape_dict_to_array_shape(raw_image_shape, type="fiji") cells_array = get_cell_location_array(cells_file, cells_only=cells_only) bins = get_bins(raw_image_shape, raw_image_bin_sizes) logging.debug("Generating heatmap (3D histogram)") heatmap_array, _ = np.histogramdd(cells_array, bins=bins) logging.debug("Resizing heatmap to the size of the target image") heatmap_array = resize(heatmap_array, target_size, order=0) if smoothing is not None: logging.debug("Applying Gaussian smoothing with a kernel sigma of: " "{}".format(smoothing)) heatmap_array = gaussian(heatmap_array, sigma=smoothing) if mask: logging.debug("Masking image based on registered atlas") # copy, otherwise it's modified, which affects later figure generation atlas_for_mask = np.copy(atlas) heatmap_array = mask_image_threshold(heatmap_array, atlas_for_mask) if convert_16bit: logging.debug("Converting to 16 bit") heatmap_array = scale_and_convert_to_16_bits(heatmap_array) logging.debug("Saving heatmap image") brainio.to_nii( heatmap_array, output_filename, scale=atlas_scale, affine_transform=transformation_matrix, )