def attach_image_to_foreground_axes(self, image3d, cmap='gray'): """Attaches a given image to the foreground axes and bring it forth""" image3d = crop_image(image3d, self.padding) image3d = scale_0to1(image3d) slices = pick_slices(image3d, self.views, self.num_slices_per_view) for ax_index, (dim_index, slice_index) in enumerate(slices): slice_data = get_axis(image3d, dim_index, slice_index) self.images_fg[ax_index].set(data=slice_data, cmap=cmap) for ax in self.fg_axes: ax.set(visible=True, zorder=self.layer_order_zoomedin)
def _compute_background(self): """Computes the background image for the current image.""" if not hasattr(self, 'background_img'): # need to scale the mask, as Collage class does NOT automatically rescale self.foreground_mask = mask_image(self.current_img, out_dtype=bool) temp_background_img = np.copy(self.current_img) temp_background_img[self.foreground_mask] = 0.0 self.background_img = scale_0to1(temp_background_img, exclude_outliers_below=1, exclude_outliers_above=1)
def _mix_color(slice1, slice2, alpha_channels, color_space='rgb'): """Mixing them as red and green channels""" if slice1.shape != slice2.shape: raise ValueError( 'size mismatch between cropped slices and checkers!!!') alpha_channels = np.array(alpha_channels) if len(alpha_channels) != 2: raise ValueError('Alphas must be two value tuples.') slice1 = scale_0to1(slice1) slice2 = scale_0to1(slice2) # masking background combined_distr = np.concatenate((slice1.flatten(), slice2.flatten())) image_eps = np.percentile(combined_distr, 5) background = np.logical_or(slice1 <= image_eps, slice2 <= image_eps) if color_space.lower() in ['rgb']: red = alpha_channels[0] * slice1 grn = alpha_channels[1] * slice2 blu = np.zeros_like(slice1) # foreground = np.logical_not(background) # blu[foreground] = 1.0 mixed = np.stack((red, grn, blu), axis=2) elif color_space.lower() in ['hsv']: raise NotImplementedError( 'This method (color_space="hsv") is yet to fully conceptualized and implemented.' ) # ensuring all values are clipped to [0, 1] mixed[mixed <= 0.0] = 0.0 mixed[mixed >= 1.0] = 1.0 return mixed
def show_tails_trimmed(self, no_toggle=False): """Callback for ghosting specific review""" if not self.currently_showing in ['tails_trimmed', ] or no_toggle: if not hasattr(self, 'tails_trimmed_img'): self.tails_trimmed_img = scale_0to1(self.current_img, exclude_outliers_below=1, exclude_outliers_above=0.05) self.collage.attach(self.tails_trimmed_img) self.currently_showing = 'tails_trimmed' else: self.show_original()
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 display_unit(self): """Adds slice collage to the given axes""" # crop and rescale img = crop_image(self.current_img, self.padding) img = scale_0to1(img) # adding slices slices = pick_slices(img, self.views, self.num_slices_per_view) for ax_index, (dim_index, slice_index) in enumerate(slices): slice_data = get_axis(img, dim_index, slice_index) self.images[ax_index].set_data(slice_data) # updating histogram self.update_histogram(img)
def load_unit(self, unit_id): """Loads the image data for display.""" # starting fresh for attr in ('current_img_raw', 'current_img', 'saturated_img', 'tails_trimmed_img', 'background_img'): if hasattr(self, attr): delattr(self, attr) t1_mri_path = self.path_getter_inputs(unit_id) self.current_img_raw = read_image(t1_mri_path, error_msg='T1 mri') # crop and rescale self.current_img = scale_0to1(crop_image(self.current_img_raw, self.padding)) self.currently_showing = None skip_subject = False if np.count_nonzero(self.current_img) == 0: skip_subject = True print('MR image is empty!') # # where to save the visualization to # out_vis_path = pjoin(self.out_dir, 'visual_qc_{}_{}'.format(self.vis_type, unit_id)) return skip_subject