def main(): parser = build_args_parser() args = parser.parse_args() if args.verbose: logging.basicConfig(level=logging.INFO) assert_inputs_exist(parser, [args.dwi, args.bvals, args.bvecs]) assert_outputs_exist( parser, args, [args.output_dwi, args.output_bvals, args.output_bvecs]) bvals, bvecs = read_bvals_bvecs(args.bvals, args.bvecs) # Find the volume indices that correspond to the shells to extract. tol = args.tolerance indices = [ get_shell_indices(bvals, shell, tol=tol) for shell in args.bvals_to_extract ] indices = np.unique(np.sort(np.hstack(indices))) if len(indices) == 0: parser.error('There are no volumes that have the supplied b-values.') logging.info( 'Extracting shells [{}], with number of images per shell [{}], ' 'from {} images from {}.'.format( ' '.join([str(b) for b in args.bvals_to_extract]), ' '.join([ str(len(get_shell_indices(bvals, shell))) for shell in args.bvals_to_extract ]), len(bvals), args.dwi)) img = nib.load(args.dwi) if args.block_size is None: args.block_size = img.shape[-1] # Load the shells by iterating through blocks of volumes. This approach # is slower for small files, but allows very big files to be split # with less memory usage. shell_data = np.zeros((img.shape[:-1] + (len(indices), ))) for vi, data in volumes(img, args.block_size): in_volume = np.array([i in vi for i in indices]) in_data = np.array([i in indices for i in vi]) shell_data[..., in_volume] = data[..., in_data] bvals = bvals[indices].astype(int) bvals.shape = (1, len(bvals)) np.savetxt(args.output_bvals, bvals, '%d') np.savetxt(args.output_bvecs, bvecs[indices, :].T, '%0.15f') nib.save(nib.Nifti1Image(shell_data, img.affine, img.header), args.output_dwi)
def prepare_data_for_actors(dwi_filename, bvals_filename, bvecs_filename, target_template_filename, slices_choice, shells=None): # Load and prepare the data dwi_img = nib.load(dwi_filename) dwi_data = dwi_img.get_data() dwi_affine = dwi_img.get_affine() bvals, bvecs = read_bvals_bvecs(bvals_filename, bvecs_filename) target_template_img = nib.load(target_template_filename) target_template_data = target_template_img.get_data() target_template_affine = target_template_img.affine mask_data = np.zeros(target_template_data.shape) mask_data[target_template_data > 0] = 1 # Prepare mask for tensors fit x_slice, y_slice, z_slice = slices_choice mask_data = prepare_slices_mask(mask_data, x_slice, y_slice, z_slice) # Extract B0 gtab = gradient_table(bvals, normalize_bvecs(bvecs), b0_threshold=10) b0_idx = np.where(gtab.b0s_mask)[0] mean_b0 = np.mean(dwi_data[..., b0_idx], axis=3, dtype=dwi_data.dtype) if shells: indices = [get_shell_indices(bvals, shell) for shell in shells] indices = np.sort(np.hstack(indices)) if len(indices) < 1: raise ValueError( 'There are no volumes that have the supplied b-values.') shell_data = np.zeros((dwi_data.shape[:-1] + (len(indices),)), dtype=dwi_data.dtype) shell_bvecs = np.zeros((len(indices), 3)) shell_bvals = np.zeros((len(indices),)) for i, indice in enumerate(indices): shell_data[..., i] = dwi_data[..., indice] shell_bvals[i] = bvals[indice] shell_bvecs[i, :] = bvecs[indice, :] else: shell_data = dwi_data shell_bvals = bvals shell_bvecs = bvecs # Register the DWI data to the template transformed_dwi, transformation = register_image(target_template_data, target_template_affine, mean_b0, dwi_affine, transformation_type='rigid', dwi=shell_data) # Rotate gradients rotated_bvecs = np.dot(shell_bvecs, transformation[0:3, 0:3]) rotated_bvecs = normalize_bvecs(rotated_bvecs) rotated_gtab = gradient_table(shell_bvals, rotated_bvecs, b0_threshold=10) # Get tensors tensor_model = TensorModel(rotated_gtab, fit_method='LS') tensor_fit = tensor_model.fit(transformed_dwi, mask_data) # Get FA fa_map = np.clip(fractional_anisotropy(tensor_fit.evals), 0, 1) # Get eigen vals/vecs evals = np.zeros(target_template_data.shape + (1,)) evals[..., 0] = tensor_fit.evals[..., 0] / np.max(tensor_fit.evals[..., 0]) evecs = np.zeros(target_template_data.shape + (1, 3)) evecs[:, :, :, 0, :] = tensor_fit.evecs[..., 0] return fa_map, evals, evecs
def main(): parser = _build_arg_parser() args = parser.parse_args() inputs = [args.in_dwi, args.in_bval] if args.mask: inputs.append(args.mask) assert_inputs_exist(parser, inputs) assert_outputs_exist(parser, args, args.out_avg) if args.verbose: logging.basicConfig(level=logging.DEBUG) img = nib.load(args.in_dwi) data = img.get_fdata(dtype=np.float32) affine = img.affine if args.mask is None: mask = None else: mask_img = nib.load(args.mask) assert_same_resolution((img, mask_img)) mask = get_data_as_mask(mask_img, dtype='uint8') # Read bvals (bvecs not needed at this point) logging.info('Performing powder average') bvals, _ = read_bvals_bvecs(args.in_bval, None) # Select diffusion volumes to average if not (args.shells): # If no shell given, average all diffusion weighted images pwd_avg_idx = np.squeeze(np.where(bvals > 0 + args.b0_thr)) logging.debug('Calculating powder average from all diffusion' '-weighted volumes, {} volumes ' 'included.'.format(len(pwd_avg_idx))) else: pwd_avg_idx = [] logging.debug('Calculating powder average from {} ' 'shells {}'.format(len(args.shells), args.shells)) for shell in args.shells: pwd_avg_idx = np.int64( np.concatenate((pwd_avg_idx, get_shell_indices(bvals, shell, tol=args.shell_thr)))) logging.debug('{} b{} volumes detected and included'.format( len(pwd_avg_idx), shell)) # remove b0 indices b0_idx = get_shell_indices(bvals, 0, args.b0_thr) logging.debug('{} b0 volumes detected and not included'.format( len(b0_idx))) for val in b0_idx: pwd_avg_idx = pwd_avg_idx[pwd_avg_idx != val] if len(pwd_avg_idx) == 0: raise ValueError('No shells selected for powder average, ensure ' 'shell, shell_thr and b0_thr are set ' 'appropriately') powder_avg = np.squeeze(np.mean(data[:, :, :, pwd_avg_idx], axis=3)) if args.mask: powder_avg = powder_avg * mask powder_avg_img = nib.Nifti1Image(powder_avg.astype(np.float32), affine) nib.save(powder_avg_img, args.out_avg)