Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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)