def load_unit(self, unit_id): """Loads the image data for display.""" image1_path, image2_path = self.path_getter_inputs(unit_id) self.image_one = read_image(image1_path, error_msg='first image') self.image_two = read_image(image2_path, error_msg='second image') skip_subject = False if np.count_nonzero(self.image_one) == 0: skip_subject = True print('image {} of {} is empty!'.format(self.image1_name, self.current_unit_id)) if np.count_nonzero(self.image_two) == 0: skip_subject = True print('image {} of {} is empty!'.format(self.image2_name, self.current_unit_id)) if not skip_subject: # crop and rescale self.image_one, self.image_two = crop_to_seg_extents( self.image_one, self.image_two, self.padding) self.image_one = scale_0to1(self.image_one) self.image_two = scale_0to1(self.image_two) self.slices = pick_slices(self.image_one, self.views, self.num_slices_per_view) # flag to keep track of whether data has been changed. self._histogram_updated = False # # where to save the visualization to # out_vis_path = pjoin(self.out_dir, 'visual_qc_{}_{}'.format(self.vis_type, unit_id)) return skip_subject
def load_unit(self, unit_id): """Loads the image data for display.""" t1_mri_path = get_freesurfer_mri_path(self.in_dir, unit_id, self.mri_name) fs_seg_path = get_freesurfer_mri_path(self.in_dir, unit_id, self.seg_name) temp_t1_mri = read_image(t1_mri_path, error_msg='T1 mri') temp_fs_seg = read_image(fs_seg_path, error_msg='segmentation') if temp_t1_mri.shape != temp_fs_seg.shape: raise ValueError('size mismatch! MRI: {} Seg: {}\n' 'Size must match in all dimensions.'.format( self.current_t1_mri.shape, temp_fs_seg.shape)) skip_subject = False if self.vis_type in ('cortical_volumetric', 'cortical_contour'): temp_seg_uncropped, roi_set_is_empty = void_subcortical_symmetrize_cortical( temp_fs_seg) elif self.vis_type in ('labels_volumetric', 'labels_contour'): if self.label_set is not None: # TODO same colors for same labels is not guaranteed # if one subject fewer labels than others # due to remapping of labels for each subject temp_seg_uncropped, roi_set_is_empty = get_label_set( temp_fs_seg, self.label_set) else: raise ValueError( '--label_set must be specified for visualization types: ' ' labels_volumetric and labels_contour') else: raise NotImplementedError( 'Invalid visualization type - ' 'choose from: {}'.format( cfg.visualization_combination_choices)) if roi_set_is_empty: skip_subject = True print('segmentation image for {} ' 'does not contain requested label set!'.format(unit_id)) return skip_subject # T1 mri must be rescaled - to avoid strange distributions skewing plots rescaled_t1_mri = scale_0to1(temp_t1_mri, cfg.max_cmap_range_t1_mri) self.current_t1_mri, self.current_seg = crop_to_seg_extents( rescaled_t1_mri, temp_seg_uncropped, self.padding) out_vis_path = pjoin( self.out_dir, 'visual_qc_{}_{}_{}'.format(self.vis_type, self.suffix, unit_id)) return skip_subject
def overlay_images(qcw, mri, seg, subject_id=None, annot=None, figsize=None, padding=default_padding, output_path=None): """Backend engine for overlaying a given seg on MRI with freesurfer label.""" num_rows_per_view, num_slices_per_view, padding = check_params(qcw.num_rows, qcw.num_slices, padding) mri, seg = crop_to_seg_extents(mri, seg, padding) surf_vis = dict() # empty - no vis to include # TODO broaden this to include subcortical structures as well if 'cortical' in qcw.vis_type: if qcw.in_dir is not None and subject_id is not None and qcw.out_dir is not None: surf_vis = make_vis_pial_surface(qcw.in_dir, subject_id, qcw.out_dir) num_surf_vis = len(surf_vis) # TODO calculation below is redundant, if surf vis does not fail # i.e. if num_surf_vis is fixed, no need to recompute for every subject num_views = len(qcw.views) num_rows = num_rows_per_view * num_views slices = pick_slices(seg, qcw.views, num_slices_per_view) num_volumetric_slices = len(slices) total_num_panels = num_volumetric_slices + num_surf_vis num_rows_for_surf_vis = 1 if num_surf_vis > 0 else 0 num_rows = num_rows + num_rows_for_surf_vis num_cols = check_layout(total_num_panels, num_views, num_rows_per_view, num_rows_for_surf_vis) plt.style.use('dark_background') if figsize is None: # figsize = [min(15,4*num_rows), min(12,4*num_cols)] # max (15,12) figsize = [4 * num_rows, 2* num_cols] fig, ax = plt.subplots(num_rows, num_cols, figsize=figsize) display_params_mri = dict(interpolation='none', aspect='equal', origin='lower', alpha=qcw.alpha_mri) display_params_seg = dict(interpolation='none', aspect='equal', origin='lower', alpha=qcw.alpha_seg) normalize_labels = colors.Normalize(vmin=seg.min(), vmax=seg.max(), clip=True) fs_cmap = get_freesurfer_cmap(qcw.vis_type) seg_mapper = cm.ScalarMappable(norm=normalize_labels, cmap=fs_cmap) normalize_mri = colors.Normalize(vmin=mri.min(), vmax=mri.max(), clip=True) mri_mapper = cm.ScalarMappable(norm=normalize_mri, cmap='gray') # deciding colors for the whole image unique_labels = np.unique(seg) # removing background - 0 stays 0 unique_labels = np.delete(unique_labels, 0) if len(unique_labels) == 1: color4label = [qcw.contour_color] else: color4label = seg_mapper.to_rgba(unique_labels) handles_seg = list() handles_mri = list() ax = ax.flatten() # display surfaces for sf_counter, ((hemi, view), spath) in enumerate(surf_vis.items()): plt.sca(ax[sf_counter]) img = mpimg.imread(spath) # img = crop_image(img) plt.imshow(img) ax[sf_counter].text(0, 0, '{} {}'.format(hemi, view)) plt.axis('off') # display slices for ax_counter, (dim_index, slice_num) in enumerate(slices): plt.sca(ax[ax_counter + num_surf_vis]) slice_mri = get_axis(mri, dim_index, slice_num) slice_seg = get_axis(seg, dim_index, slice_num) # display MRI mri_rgb = mri_mapper.to_rgba(slice_mri) h_mri = plt.imshow(mri_rgb, **display_params_mri) if 'volumetric' in qcw.vis_type: seg_rgb = seg_mapper.to_rgba(slice_seg) h_seg = plt.imshow(seg_rgb, **display_params_seg) elif 'contour' in qcw.vis_type: h_seg = plot_contours_in_slice(slice_seg, unique_labels, color4label) plt.axis('off') # # encoding the souce of the object (image/line) being displayed # handle_seg.set_label('seg {} {}'.format(dim_index, slice_num)) # handle_mri.set_label('mri {} {}'.format(dim_index, slice_num)) handles_mri.append(h_mri) if len(h_seg) >= 1: handles_seg.extend(h_seg) else: handles_seg.append(h_seg) # hiding unused axes for ua in range(total_num_panels, len(ax)): ax[ua].set_visible(False) if annot is not None: h_annot = fig.suptitle(annot, **cfg.annot_text_props) h_annot.set_position(cfg.position_annot_text) fig.set_size_inches(figsize) if output_path is not None: # no space left unused plt.subplots_adjust(**cfg.no_blank_area) output_path = output_path.replace(' ', '_') layout_str = 'v{}_ns{}_{}x{}'.format(''.join([ str(v) for v in qcw.views]),num_slices_per_view,num_rows,num_cols) fig.savefig(output_path + '_{}.png'.format(layout_str), bbox_inches='tight') # leaving some space on the right for review elements plt.subplots_adjust(**cfg.review_area) return fig, handles_mri, handles_seg, figsize
def aseg_on_mri(mri_spec, aseg_spec, alpha_mri=1.0, alpha_seg=1.0, num_rows=2, num_cols=6, rescale_method='global', aseg_cmap='freesurfer', sub_cortical=False, annot=None, padding=5, bkground_thresh=0.05, output_path=None, figsize=None, **kwargs): "Produces a collage of various slices from different orientations in the given 3D image" num_rows, num_cols, padding = check_params(num_rows, num_cols, padding) mri = read_image(mri_spec, bkground_thresh=bkground_thresh) seg = read_image(aseg_spec, bkground_thresh=0) mri, seg = crop_to_seg_extents(mri, seg, padding) num_slices_per_view = num_rows * num_cols slices = pick_slices(seg, num_slices_per_view) plt.style.use('dark_background') num_axes = 3 if figsize is None: figsize = [5 * num_axes * num_rows, 5 * num_cols] fig, ax = plt.subplots(num_axes * num_rows, num_cols, figsize=figsize) # displaying some annotation text if provided if annot is not None: fig.suptitle(annot, backgroundcolor='black', color='g') display_params_mri = dict(interpolation='none', aspect='equal', origin='lower', cmap='gray', alpha=alpha_mri, vmin=mri.min(), vmax=mri.max()) display_params_seg = dict(interpolation='none', aspect='equal', origin='lower', alpha=alpha_seg) normalize_labels = colors.Normalize(vmin=seg.min(), vmax=seg.max(), clip=True) fs_cmap = get_freesurfer_cmap(sub_cortical) label_mapper = cm.ScalarMappable(norm=normalize_labels, cmap=fs_cmap) ax = ax.flatten() ax_counter = 0 for dim_index in range(3): for slice_num in slices[dim_index]: plt.sca(ax[ax_counter]) ax_counter = ax_counter + 1 slice_mri = get_axis(mri, dim_index, slice_num) slice_seg = get_axis(seg, dim_index, slice_num) # # masking data to set no-value pixels to transparent # seg_background = np.isclose(slice_seg, 0.0) # slice_seg = np.ma.masked_where(seg_background, slice_seg) # slice_mri = np.ma.masked_where(np.logical_not(seg_background), slice_mri) seg_rgb = label_mapper.to_rgba(slice_seg) plt.imshow(seg_rgb, **display_params_seg) plt.imshow(slice_mri, **display_params_mri) plt.axis('off') # plt.subplots_adjust(wspace=0.0, hspace=0.0) plt.subplots_adjust(left=0.01, right=0.99, bottom=0.01, top=0.99, wspace=0.05, hspace=0.02) # fig.tight_layout() if output_path is not None: output_path = output_path.replace(' ', '_') fig.savefig(output_path + '.png', bbox_inches='tight') # plt.close() return fig