def _run_single_scan(self, idx): in_img = ScanWrapper(self._in_data_folder.get_file_path(idx)) in_mask = ScanWrapper(self._in_mask_folder_obj.get_file_path(idx)) in_img_data = in_img.get_data() in_mask_data = in_mask.get_data() mask_data = np.zeros(in_mask_data.shape, dtype=int) for lung_label in self._lung_label_list: mask_match_map = (in_mask_data == lung_label).astype(int) print(f'lung label: {lung_label}') print(f'match_map shape: {mask_match_map.shape}') print(f'num posi voxels: {np.sum(mask_match_map)}') mask_data += mask_match_map mask_data = ~mask_data.astype('bool') print(f'Final mask: {np.sum(mask_data)}') in_img_data_with_mask = np.ma.array(in_img_data, mask=mask_data.astype('bool')) mean_in_mask = in_img_data_with_mask.mean() file_name = self._in_data_folder.get_file_name(idx) result_dict = { 'file_name': file_name, 'mean': mean_in_mask } print(result_dict) return result_dict
def clip_plot_3_view(self, out_png_folder): in_img_obj = ScanWrapper(self._in_img_path) in_mask_obj = ScanWrapper(self._in_mask_path) in_img_data = in_img_obj.get_data() in_mask_data = in_mask_obj.get_data() masked_img_data = np.zeros(in_img_data.shape, dtype=float) masked_img_data.fill(np.nan) masked_img_data[in_mask_data == 1] = in_img_data[in_mask_data == 1]
def clip_plot(self, out_png_folder): in_img_obj = ScanWrapper(self._in_img_path) in_back_obj = ScanWrapper(self._in_back_img_path) in_img_data = in_img_obj.get_data() in_back_data = in_back_obj.get_data() masked_img_data = None masked_back_data = None if self._in_mask_path is not None: in_mask_obj = ScanWrapper(self._in_mask_path) in_mask_data = in_mask_obj.get_data() masked_img_data = np.zeros(in_img_data.shape, dtype=float) masked_img_data.fill(np.nan) masked_img_data[in_mask_data == 1] = in_img_data[in_mask_data == 1] masked_back_data = np.zeros(in_back_data.shape, dtype=float) masked_back_data.fill(np.nan) masked_back_data[in_mask_data == 1] = in_back_data[in_mask_data == 1] else: masked_img_data = in_img_data masked_back_data = in_back_data self._plot_stacked_view( self._num_clip, self._step_axial, masked_img_data, masked_back_data, 'axial', out_png_folder, 1 ) self._plot_stacked_view( self._num_clip, self._step_sagittal, masked_img_data, masked_back_data, 'sagittal', out_png_folder, 5.23438 / 2.28335 ) self._plot_stacked_view( self._num_clip, self._step_coronal, masked_img_data, masked_back_data, 'coronal', out_png_folder, 5.23438 / 2.17388 )
def _run_single_scan(self, idx): in_file_path = self._in_data_folder.get_file_path(idx) in_data = ScanWrapper(in_file_path) in_img = in_data.get_data() # self._data_matrix[idx, :] = in_img.reshape(in_data.get_number_voxel()) self._data_matrix[idx, :] = convert_3d_2_flat(in_img)
def plot_pc(self, out_png): fig = plt.figure(figsize=(self._num_show_pc * 20, self._num_clip * self._num_view * 15)) gs = gridspec.GridSpec(1, self._num_show_pc) sub_gs_list = [] for idx_pc in range(self._num_show_pc): sub_gs = gs[idx_pc].subgridspec(self._num_clip * self._num_view, 1) sub_gs_list.append(sub_gs) for idx_pc in range(self._num_show_pc): img_data_obj = ScanWrapper( self._pc_folder_obj.get_file_path(idx_pc)) img_data = img_data_obj.get_data() img_name = os.path.basename( self._pc_folder_obj.get_file_path(idx_pc)).replace( '.nii.gz', '') logger.info( f'Reading image {self._pc_folder_obj.get_file_path(idx_pc)}') self._plot_one_pc(img_data, sub_gs_list[idx_pc], f'{img_name}') # out_eps = out_png.replace('.png', '.eps') logger.info(f'Save fig to {out_png}') # plt.savefig(out_eps, bbox_inches='tight', pad_inches=0, dpi=self._out_dpi, format='pdf') plt.savefig(out_png, bbox_inches='tight', pad_inches=0, dpi=self._out_dpi) plt.close(fig=fig)
def _run_single_scan(self, idx): in_img = ScanWrapper(self._in_data_folder.get_file_path(idx)) out_mask_path = self._out_folder.get_file_path(idx) in_img_data = in_img.get_data() non_nan_mask = in_img_data == in_img_data logger.info(f'Save non-nan mask to {out_mask_path}') in_img.save_scan_same_space(out_mask_path, non_nan_mask.astype(int))
def clip_plot(self, out_png_folder): in_int_obj = ScanWrapper(self._in_int_path) in_jac_obj = ScanWrapper(self._in_jac_path) in_att_obj = ScanWrapper(self._in_att_path) in_int_data = in_int_obj.get_data() in_jac_data = in_jac_obj.get_data() in_att_data = in_att_obj.get_data() fig, axs = plt.subplots(1, 3, constrained_layout=True, figsize=(30, 30)) # plt.axis('off') for ax in axs: ax.axis('off') self._plot_view( self._num_clip, self._step_axial, in_int_data, in_jac_data, in_att_data, 'axial', 1, axs[0] ) self._plot_view( self._num_clip, self._step_coronal, in_int_data, in_jac_data, in_att_data, 'coronal', 5.23438 / 2.17388, axs[1] ) self._plot_view( self._num_clip, self._step_sagittal, in_int_data, in_jac_data, in_att_data, 'sagittal', 5.23438 / 2.28335, axs[2] ) out_root_folder = os.path.join(out_png_folder, 'stacked') mkdir_p(out_root_folder) out_png_path = os.path.join(out_root_folder, f'{self._in_img_file_name}.png') print(f'Save overlay png to {out_png_path}') plt.savefig(out_png_path, bbox_inches='tight', pad_inches=0) plt.close()
def _run_chunk(self, chunk_list): result_list = [] im_shape = self._ref_img.get_shape() sum_image_union = np.zeros(im_shape) region_mask_count_image = np.zeros(im_shape) for idx in chunk_list: self._in_data_folder.print_idx(idx) img_obj = ScanWrapper(self._in_data_folder.get_file_path(idx)) mask_obj = ScanWrapper( self._in_region_mask_folder.get_file_path(idx)) sum_image_union += img_obj.get_data() region_mask_count_image += mask_obj.get_data() result = { 'sum_image': sum_image_union, 'region_count': region_mask_count_image } result_list.append(result) return result_list
def _plot_pc_one_view(self, idx_view, out_png_path): view_config_list = self._get_view_config() clip_plane = view_config_list[idx_view]['clip plane'] num_files = self._pc_folder_obj.num_files() num_lines = int(num_files / self._num_show_pc) fig = plt.figure(figsize=(self._num_show_pc * 15, num_lines * 12)) gs = gridspec.GridSpec(num_lines, self._num_show_pc) gs.update(wspace=0.025, hspace=0.025) for idx_row in range(num_lines): # if idx_row != 0: # continue for idx_column in range(self._num_show_pc): # if idx_column != 0: # continue idx_file = idx_column + self._num_show_pc * idx_row logger.info( f'Plot scan {self._pc_folder_obj.get_file_path(idx_file)}') img_data_obj = ScanWrapper( self._pc_folder_obj.get_file_path(idx_file)) img_data = img_data_obj.get_data() range_norm = np.max([np.min(img_data), np.max(img_data)]) # vmin = - 0.5 * range_norm # vmax = 0.5 * range_norm vmin = -0.0015 vmax = 0.0015 clip = self._clip_image(img_data, clip_plane, 0) ax = plt.subplot(gs[idx_row, idx_column]) plt.axis('off') im = plt.imshow(clip, interpolation='none', cmap=self._cm, norm=colors.Normalize(vmin=vmin, vmax=vmax)) # divider = make_axes_locatable(ax) # cax = divider.append_axes("right", size="5%", pad=0.05) # # cb = plt.colorbar(im, cax=cax) # # cb.set_label('Intensity of eigen image') # cb.ax.tick_params(labelsize=self._sub_title_font_size / 2) logger.info(f'Save plot to {out_png_path}') plt.savefig(out_png_path, bbox_inches='tight', pad_inches=0.1, dpi=self._out_dpi) plt.close(fig=fig)
def _run_single_scan(self, idx): in_data_path = self._in_data_folder.get_file_path(idx) in_affine_mat_path = self._in_affine_mat_folder.get_file_path( idx).replace('.nii.gz', '.txt') out_file_path = self._out_data_folder.get_file_path(idx) in_image = ScanWrapper(in_data_path) affine_mat = self._get_affine_matrix(in_affine_mat_path) new_log_jacobian_det = in_image.get_data() + np.log( np.linalg.det(affine_mat)) self._ref_img.save_scan_same_space(out_file_path, new_log_jacobian_det)
def get_average_map(file_list, save_path): first_img = ScanWrapper(file_list[0]) im_shape = first_img.get_shape() sum_map = np.zeros(im_shape, dtype=float) for idx_image in range(len(file_list)): img = ScanWrapper(file_list[idx_image]) img_data = img.get_data() print(f'Adding {file_list[idx_image]} ({idx_image} / {len(file_list)})') print(f'Max intensity {np.max(img_data)}') sum_map += img_data average_map = sum_map / float(len(file_list)) print(f'Average map max int {np.max(average_map)}') first_img.save_scan_same_space(save_path, average_map)
class OverlayMaskPNG(AbstractParallelRoutine): def __init__(self, config, in_folder, mask_img, out_png_folder, file_list_txt): super().__init__(config, in_folder, file_list_txt) self._mask_img = ScanWrapper(mask_img) self._out_png_folder = DataFolder.get_data_folder_obj(config, out_png_folder, data_list_txt=file_list_txt) self._out_png_folder.change_suffix('.png') self._vmax = 500 self._vmin = -1000 def _run_single_scan(self, idx): in_img_path = self._in_data_folder.get_file_path(idx) in_img = ScanWrapper(in_img_path) slice_in_img = self._clip_nifti(in_img.get_data()) slice_mask_img = self._clip_nifti(self._mask_img.get_data()) plt.figure(figsize=(15, 15)) plt.axis('off') clip_x_nii_rescale = exposure.rescale_intensity(slice_in_img, in_range=(self._vmin, self._vmax), out_range=(0, 1)) clip_x_nii_rgb = color.gray2rgb(clip_x_nii_rescale) plt.imshow(clip_x_nii_rgb, alpha=0.8) plt.imshow(slice_mask_img, interpolation='none', cmap='jet', norm=colors.Normalize(vmin=0, vmax=1), alpha=0.3) out_png_path = self._out_png_folder.get_file_path(idx) print(f'Saving image to {out_png_path}') plt.savefig(out_png_path, bbox_inches='tight', pad_inches=0) @staticmethod def _clip_nifti(im_data, offset=0): im_shape = im_data.shape clip_x = im_data[int(im_shape[0] / 2) - 1 + offset, :, :] clip_x = np.flip(clip_x, 0) clip_x = np.rot90(clip_x) return clip_x
def _run_single_scan(self, idx): in_img_path = self._in_data_folder.get_file_path(idx) in_img = ScanWrapper(in_img_path) slice_in_img = self._clip_nifti(in_img.get_data()) slice_mask_img = self._clip_nifti(self._mask_img.get_data()) plt.figure(figsize=(15, 15)) plt.axis('off') clip_x_nii_rescale = exposure.rescale_intensity(slice_in_img, in_range=(self._vmin, self._vmax), out_range=(0, 1)) clip_x_nii_rgb = color.gray2rgb(clip_x_nii_rescale) plt.imshow(clip_x_nii_rgb, alpha=0.8) plt.imshow(slice_mask_img, interpolation='none', cmap='jet', norm=colors.Normalize(vmin=0, vmax=1), alpha=0.3) out_png_path = self._out_png_folder.get_file_path(idx) print(f'Saving image to {out_png_path}') plt.savefig(out_png_path, bbox_inches='tight', pad_inches=0)
class PreprocessAverageImputation(AbstractParallelRoutine): def __init__(self, config, in_folder, out_folder, average_img, file_list_txt=None): super().__init__(config, in_folder, file_list_txt=file_list_txt) self._out_data_folder = DataFolder.get_data_folder_obj( config, out_folder, data_list_txt=file_list_txt) mkdir_p(out_folder) self._average_img = ScanWrapper(average_img) def _run_single_scan(self, idx): in_file_path = self._in_data_folder.get_file_path(idx) out_file_path = self._out_data_folder.get_file_path(idx) in_img = ScanWrapper(in_file_path).get_data() average_img = self._average_img.get_data() np.copyto(in_img, average_img, where=(in_img != in_img)) np.copyto(in_img, 0, where=(in_img != in_img)) self._average_img.save_scan_same_space(out_file_path, in_img)
class AverageScans: def __init__(self, config, in_folder=None, data_file_txt=None, in_data_folder_obj=None): self._data_folder = None if in_data_folder_obj is None: self._data_folder = DataFolder(in_folder, data_file_txt) else: self._data_folder = in_data_folder_obj self._standard_ref = ScanWrapper(self._data_folder.get_first_path()) self._num_processes = config['num_processes'] def get_average_image_union(self, save_path): im_shape = self._get_std_shape() average_union = np.zeros(im_shape) average_union.fill(np.nan) non_null_mask_count_image = np.zeros(im_shape) chunk_list = self._data_folder.get_chunks_list(self._num_processes) pool = Pool(processes=self._num_processes) print('Average in union') print('Step.1 Summation') image_average_union_result_list = [ pool.apply_async(self._sum_images_union, (file_idx_chunk, )) for file_idx_chunk in chunk_list ] for thread_idx in range(len(image_average_union_result_list)): result = image_average_union_result_list[thread_idx] result.wait() print( f'Thread with idx {thread_idx} / {len(image_average_union_result_list)} is completed' ) print('Adding to averaged_image...') averaged_image_chunk = result.get() average_union = self._add_image_union(average_union, averaged_image_chunk) print('Done.') print('Step.2 Non-nan counter') non_null_mask_count_result = [ pool.apply_async(self._sum_non_null_count, (file_idx_chunk, )) for file_idx_chunk in chunk_list ] for thread_idx in range(len(non_null_mask_count_result)): result = non_null_mask_count_result[thread_idx] result.wait() print( f'Thread with idx {thread_idx} / {len(non_null_mask_count_result)} is completed' ) print('Adding to averaged_image...') averaged_image_chunk = result.get() non_null_mask_count_image = np.add(non_null_mask_count_image, averaged_image_chunk) print('Done.') average_union = np.divide(average_union, non_null_mask_count_image, out=average_union, where=non_null_mask_count_image > 0) self._standard_ref.save_scan_same_space(save_path, average_union) print('Done.') def _sum_images_union(self, chunk_list): print('Sum images, union non-null region. Loading images...') im_shape = self._get_std_shape() sum_image = np.zeros(im_shape) sum_image.fill(np.nan) for id_file in chunk_list: file_path = self._data_folder.get_file_path(id_file) self._data_folder.print_idx(id_file) im = nib.load(file_path) im_data = im.get_data() sum_image = self._add_image_union(sum_image, im_data) return sum_image def _sum_non_null_count(self, chunk_list): print('Count non-null per voxel. Loading images...') im_shape = self._get_std_shape() sum_image = np.zeros(im_shape) for id_file in chunk_list: file_path = self._data_folder.get_file_path(id_file) self._data_folder.print_idx(id_file) im = nib.load(file_path) im_data = im.get_data() sum_image = np.add(sum_image, 1, out=sum_image, where=np.logical_not(np.isnan(im_data))) return sum_image def _get_std_shape(self): return self._standard_ref.get_data().shape @staticmethod def _add_image_inter(image1, image2): return np.add(image1, image2, out=np.full_like(image1, np.nan), where=np.logical_not( np.logical_or(np.isnan(image1), np.isnan(image2)))) @staticmethod def _add_image_union(image1, image2): add_image = np.full_like(image1, np.nan) add_image[np.logical_not( np.logical_and(np.isnan(image1), np.isnan(image2)))] = 0 add_image = np.add(add_image, image1, out=add_image, where=np.logical_not(np.isnan(image1))) add_image = np.add(add_image, image2, out=add_image, where=np.logical_not(np.isnan(image2))) return add_image @staticmethod def sum_non_null_count(file_list, in_folder): print('Count non-null per voxel. Loading images...') im_temp = nib.load(os.path.join(in_folder, file_list[0])) im_temp_data = im_temp.get_data() sum_image = np.zeros_like(im_temp_data) for id_file in range(len(file_list)): file_name = file_list[id_file] print('%s (%d/%d)' % (file_name, id_file, len(file_list))) file_path = os.path.join(in_folder, file_name) im = nib.load(file_path) im_data = im.get_data() sum_image = np.add(sum_image, 1, out=sum_image, where=np.logical_not(np.isnan(im_data))) return sum_image
def _calc_nmse(ref_img: ScanWrapper, in_img: ScanWrapper): mse_val = metrics.normalized_root_mse(image_true=ref_img.get_data(), image_test=in_img.get_data()) return mse_val
def _run_single_scan(self, idx): in_img = ScanWrapper(self._in_data_folder.get_file_path(idx)) return in_img.get_data()