def match_histograms(reference_path, apply_to_path):

    print('Start')

    for name in ['InPhase', 'OutPhase']:

        print(f'Working on: {name}')
        ref_files = list()
        for folder in os.listdir(reference_path):
            ref_files.append(f'{reference_path}/{folder}/{name}.nii')

        print('Training')
        mask_files = [None] * len(ref_files)
        standard_scale, percs = nyul.train(ref_files, mask_files)

        input_files, output_files = list(), list()
        for folder in os.listdir(apply_to_path):
            input_files.append(f'{apply_to_path}/{folder}/{name}.nii')
            output_files.append(f'{apply_to_path}/{folder}/{name}_HM.nii')

        print('Normalizing')
        for img_fn, out_fn in zip(input_files, output_files):
            print(img_fn, '->', out_fn)
            _, base, _ = io.split_filename(img_fn)
            img = io.open_nii(img_fn)
            normalized = nyul.do_hist_norm(img,
                                           percs,
                                           standard_scale,
                                           mask=None)
            io.save_nii(normalized, out_fn, is_nii=True)

    print('Done')
def process(image, brain_mask, args, logger):
    img = io.open_nii(image)
    mask = io.open_nii(brain_mask)
    dirname, base, ext = io.split_filename(image)
    if args.output_dir is not None:
        dirname = args.output_dir
        if not os.path.exists(dirname):
            logger.info('Making output directory: {}'.format(dirname))
            os.mkdir(dirname)
    if args.find_background_mask:
        bg_mask = background_mask(img)
        bgfile = os.path.join(dirname, base + '_bgmask' + ext)
        io.save_nii(bg_mask, bgfile, is_nii=True)
    if args.wm_peak is not None:
        logger.info('Loading WM peak: ', args.wm_peak)
        peak = float(np.load(args.wm_peak))
    else:
        peak = gmm_class_mask(img, brain_mask=mask, contrast=args.contrast)
        if args.save_wm_peak:
            np.save(os.path.join(dirname, base + '_wmpeak.npy'), peak)
    normalized = gmm.gmm_normalize(img, mask, args.norm_value, args.contrast,
                                   args.background_mask, peak)
    outfile = os.path.join(dirname, base + '_gmm' + ext)
    logger.info('Normalized image saved: {}'.format(outfile))
    io.save_nii(normalized, outfile, is_nii=True)
def run_intensity_fcm(infile, outfolder):

    from intensity_normalization.normalize import fcm
    from intensity_normalization.utilities import io

    try:
        if not exists(join(outfolder, "Robex")):
            makedirs(join(outfolder, "Robex"))

        if not exists(join(outfolder, "wm_masks")):
            makedirs(join(outfolder, "wm_masks"))

        filename = infile.split(sep)[-1].split(".")[0]
        i = io.open_nii(infile)
        b_mask = io.open_nii(
            join(outfolder, "robex_masks", filename + "_mask.nii.gz"))
        wm_mask = fcm.find_tissue_mask(i, b_mask)
        normalized = fcm.fcm_normalize(i, wm_mask)
        io.save_nii(wm_mask,
                    join(outfolder, "wm_masks", filename + "_wmmask.nii.gz"))
        io.save_nii(normalized, join(outfolder, filename + "_fcm.nii.gz"))
        shutil.move(join(infile), join(outfolder, "Robex"))
    except:
        e = sys.exc_info()
        print("Error: ", str(e[0]))
        print("Error: ", str(e[1]))
        print("Error: executing fcm method")
        sys.exit(2)
예제 #4
0
def nyul_normalize(img_dir, mask_dir=None, output_dir=None, standard_hist=None, write_to_disk=True):
    """
    Use Nyul and Udupa method ([1,2]) to normalize the intensities of a set of MR images

    Args:
        img_dir (str): directory containing MR images
        img_dir (str): directory containing masks for MR images
        output_dir (str): directory to save images if you do not want them saved in
            same directory as data_dir
        standard_hist (str): path to output or use standard histogram landmarks
        write_to_disk (bool): write the normalized data to disk or nah

    Returns:
        normalized (np.ndarray): last normalized image from img_dir

    References:
        [1] N. Laszlo G and J. K. Udupa, “On Standardizing the MR Image
            Intensity Scale,” Magn. Reson. Med., vol. 42, pp. 1072–1081,
            1999.
        [2] M. Shah, Y. Xiao, N. Subbanna, S. Francis, D. L. Arnold,
            D. L. Collins, and T. Arbel, “Evaluating intensity
            normalization on MRIs of human brain with multiple sclerosis,”
            Med. Image Anal., vol. 15, no. 2, pp. 267–282, 2011.
    """
    input_files = io.glob_nii(img_dir)
    if output_dir is None:
        out_fns = [None] * len(input_files)
    else:
        out_fns = []
        for fn in input_files:
            _, base, ext = io.split_filename(fn)
            out_fns.append(os.path.join(output_dir, base + '_hm' + ext))
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

    mask_files = [None] * len(input_files) if mask_dir is None else io.glob_nii(mask_dir)

    if standard_hist is None:
        logger.info('Learning standard scale for the set of images')
        standard_scale, percs = train(input_files, mask_files)
    elif not os.path.isfile(standard_hist):
        logger.info('Learning standard scale for the set of images')
        standard_scale, percs = train(input_files, mask_files)
        np.save(standard_hist, np.vstack((standard_scale, percs)))
    else:
        logger.info('Loading standard scale ({}) for the set of images'.format(standard_hist))
        standard_scale, percs = np.load(standard_hist)

    for i, (img_fn, mask_fn, out_fn) in enumerate(zip(input_files, mask_files, out_fns)):
        _, base, _ = io.split_filename(img_fn)
        logger.info('Transforming image {} to standard scale ({:d}/{:d})'.format(base, i+1, len(input_files)))
        img = io.open_nii(img_fn)
        mask = io.open_nii(mask_fn) if mask_fn is not None else None
        normalized = do_hist_norm(img, percs, standard_scale, mask)
        if write_to_disk:
            io.save_nii(normalized, out_fn, is_nii=True)

    return normalized
예제 #5
0
def lsq_normalize(img_dir, mask_dir=None, output_dir=None, write_to_disk=True):
    """
    normalize intensities of a set of MR images by minimizing the squared distance
    between CSF, GM, and WM means within the set

    Args:
        img_dir (str): directory containing MR images
        mask_dir (str): directory containing masks for MR images
        output_dir (str): directory to save images if you do not want them saved in
            same directory as data_dir
        write_to_disk (bool): write the normalized data to disk or nah

    Returns:
        normalized (np.ndarray): last normalized image from img_dir
    """
    input_files = io.glob_nii(img_dir)
    if output_dir is None:
        out_fns = [None] * len(input_files)
    else:
        out_fns = []
        for fn in input_files:
            _, base, ext = io.split_filename(fn)
            out_fns.append(os.path.join(output_dir, base + '_lsq' + ext))
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

    mask_files = [None] * len(
        input_files) if mask_dir is None else io.glob_nii(mask_dir)

    standard_tissue_means = None
    normalized = None
    for i, (img_fn, mask_fn,
            out_fn) in enumerate(zip(input_files, mask_files, out_fns)):
        _, base, _ = io.split_filename(img_fn)
        logger.info(
            'Transforming image {} to standard scale ({:d}/{:d})'.format(
                base, i + 1, len(input_files)))
        img = io.open_nii(img_fn)
        mask = io.open_nii(mask_fn) if mask_fn is not None else None
        tissue_mem = mask_util.fcm_class_mask(img, mask)
        if standard_tissue_means is None:
            csf_tissue_mask = find_tissue_mask(img, mask, tissue_type='csf')
            csf_normed_data = fcm_normalize(img, csf_tissue_mask).get_fdata()
            standard_tissue_means = calc_tissue_means(csf_normed_data,
                                                      tissue_mem)
            del csf_tissue_mask, csf_normed_data
        img_data = img.get_fdata()
        tissue_means = calc_tissue_means(img_data, tissue_mem)
        sf = find_scaling_factor(tissue_means, standard_tissue_means)
        logger.debug('Scaling factor for {}: {:0.3e}'.format(base, sf))
        normalized = nib.Nifti1Image(sf * img_data, img.affine, img.header)
        if write_to_disk:
            io.save_nii(normalized, out_fn, is_nii=True)

    return normalized
def main(args=None):
    args = arg_parser().parse_args(args)
    if args.verbosity == 1:
        level = logging.getLevelName('INFO')
    elif args.verbosity >= 2:
        level = logging.getLevelName('DEBUG')
    else:
        level = logging.getLevelName('WARNING')
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        level=level)
    logger = logging.getLogger(__name__)
    try:
        if not os.path.isdir(args.img_dir):
            raise ValueError(
                '(-i / --img-dir) argument needs to be a directory of NIfTI images.'
            )
        if args.mask_dir is not None:
            if not os.path.isdir(args.mask_dir):
                raise ValueError(
                    '(-m / --mask-dir) argument needs to be a directory of NIfTI images.'
                )

        img_fns = io.glob_nii(args.img_dir)
        if args.mask_dir is not None:
            mask_fns = io.glob_nii(args.mask_dir)
        else:
            mask_fns = [None] * len(img_fns)
        if not os.path.exists(args.output_dir):
            logger.info('Making Output Directory: {}'.format(args.output_dir))
            os.mkdir(args.output_dir)
        hard_seg = not args.memberships
        for i, (img_fn, mask_fn) in enumerate(zip(img_fns, mask_fns), 1):
            _, base, _ = io.split_filename(img_fn)
            logger.info('Creating Mask for Image: {}, ({:d}/{:d})'.format(
                base, i, len(img_fns)))
            img = io.open_nii(img_fn)
            mask = io.open_nii(mask_fn)
            tm = fcm_class_mask(img, mask,
                                hard_seg) if not args.gmm else gmm_class_mask(
                                    img, mask, 't1', False, hard_seg)
            tissue_mask = os.path.join(args.output_dir, base + '_tm')
            if args.memberships:
                classes = ('csf', 'gm', 'wm')
                for j, c in enumerate(classes):
                    io.save_nii(img, tissue_mask + '_' + c + '.nii.gz', tm[...,
                                                                           j])
            else:
                io.save_nii(img, tissue_mask + '.nii.gz', tm)
        return 0
    except Exception as e:
        logger.exception(e)
        return 1
예제 #7
0
def process(image_fn, brain_mask_fn, args, logger):
    img = io.open_nii(image_fn)
    if args.brain_mask is not None:
        mask = io.open_nii(brain_mask_fn)
    else:
        mask = None
    dirname, base, _ = io.split_filename(image_fn)
    if args.output_dir is not None:
        dirname = args.output_dir
        if not os.path.exists(dirname):
            logger.info('Making output directory: {}'.format(dirname))
            os.mkdir(dirname)
    normalized = kde.kde_normalize(img, mask, args.contrast, args.norm_value)
    outfile = os.path.join(dirname, base + '_kde.nii.gz')
    logger.info('Normalized image saved: {}'.format(outfile))
    io.save_nii(normalized, outfile, is_nii=True)
예제 #8
0
def process(image_fn, brain_mask_fn, output_dir, logger):
    img = io.open_nii(image_fn)
    dirname, base, _ = io.split_filename(image_fn)
    if output_dir is not None:
        dirname = output_dir
        if not os.path.exists(dirname):
            logger.info('Making output directory: {}'.format(dirname))
            os.mkdir(dirname)
    if brain_mask_fn is None:
        mask = None
    else:
        if brain_mask_fn == 'nomask':
            mask = 'nomask'
        else:
            mask = io.open_nii(brain_mask_fn)
    normalized = zscore.zscore_normalize(img, mask)
    outfile = os.path.join(dirname, base + '_zscore.nii.gz')
    logger.info('Normalized image saved: {}'.format(outfile))
    io.save_nii(normalized, outfile, is_nii=True)
예제 #9
0
def process(image_fn, brain_mask_fn, wm_mask_fn, output_dir, args, logger):
    img = io.open_nii(image_fn)
    dirname, base, _ = io.split_filename(image_fn)
    if output_dir is not None:
        dirname = output_dir
        if not os.path.exists(dirname):
            logger.info('Making output directory: {}'.format(dirname))
            os.mkdir(dirname)
    if brain_mask_fn is not None:
        mask = io.open_nii(brain_mask_fn)
        wm_mask = fcm.find_wm_mask(img, mask)
        outfile = os.path.join(dirname, base + '_wmmask.nii.gz')
        io.save_nii(wm_mask, outfile, is_nii=True)
    if wm_mask_fn is not None:
        wm_mask = io.open_nii(wm_mask_fn)
        normalized = fcm.fcm_normalize(img, wm_mask, args.norm_value)
        outfile = os.path.join(dirname, base + '_fcm.nii.gz')
        logger.info('Normalized image saved: {}'.format(outfile))
        io.save_nii(normalized, outfile, is_nii=True)
def run_intensity_gmm(infile, outfolder):
    from intensity_normalization.normalize import gmm
    from intensity_normalization.utilities import io
    try:
        if not exists(join(outfolder, "Robex")):
            makedirs(join(outfolder, "Robex"))

        filename = infile.split(sep)[-1].split(".")[0]
        i = io.open_nii(join(outfolder, infile))
        b_mask = io.open_nii(
            join(outfolder, "robex_masks", filename + "_mask.nii.gz"))
        normalized = gmm.gmm_normalize(i, b_mask)
        io.save_nii(normalized, join(outfolder, filename + "_gmm.nii.gz"))
        shutil.move(join(outfolder, infile), join(outfolder, "Robex"))
    except:
        e = sys.exc_info()
        print("Error: ", str(e[0]))
        print("Error: ", str(e[1]))
        print("Error: executing gmm method")
        sys.exit(2)
def run_intensity_ws(infile, outfolder):

    from intensity_normalization.normalize import whitestripe
    from intensity_normalization.utilities import io

    try:
        filename = infile.split(sep)[-1].split(".")[0]

        if not exists(join(outfolder, "Robex")):
            makedirs(join(outfolder, "Robex"))

        print('running intensity white stripe...')
        mask = whitestripe.whitestripe(io.open_nii(infile), "T1")
        normalized = whitestripe.whitestripe_norm(io.open_nii(infile), mask)
        io.save_nii(normalized, join(outfolder, filename + "_ws.nii.gz"))
        shutil.move(infile, join(outfolder, "Robex"))
    except:
        e = sys.exc_info()
        print("Error: ", str(e[0]))
        print("Error: ", str(e[1]))
        print("Error: executing white stripe method")
        sys.exit(2)
def run_intensity_zscore(infile, outfolder):

    from intensity_normalization.normalize import zscore
    from intensity_normalization.utilities import io
    try:
        filename = infile.split(sep)[-1].split(".")[0]
        i = io.open_nii(infile)
        b_mask = io.open_nii(
            join(outfolder, "robex_masks", filename + "_mask.nii.gz"))

        if not exists(join(outfolder, "Robex")):
            makedirs(join(outfolder, "Robex"))

        print('running intensity zscore...')
        normalized = zscore.zscore_normalize(i, b_mask)
        io.save_nii(normalized, join(outfolder, filename + "_zscore.nii.gz"))
        shutil.move(join(infile), join(outfolder, "Robex"))
    except:
        e = sys.exc_info()
        print("Error: ", str(e[0]))
        print("Error: ", str(e[1]))
        print("Error: executing z-score method")
        sys.exit(2)
def ws_normalize(img_dir,
                 contrast,
                 mask_dir=None,
                 output_dir=None,
                 write_to_disk=True):
    """
    Use WhiteStripe normalization method ([1]) to normalize the intensities of
    a set of MR images by normalizing an area around the white matter peak of the histogram

    Args:
        img_dir (str): directory containing MR images to be normalized
        contrast (str): contrast of MR images to be normalized (T1, T2, or FLAIR)
        mask_dir (str): if images are not skull-stripped, then provide brain mask
        output_dir (str): directory to save images if you do not want them saved in
            same directory as img_dir
        write_to_disk (bool): write the normalized data to disk or nah

    Returns:
        normalized (np.ndarray): last normalized image data from img_dir
            I know this is an odd behavior, but yolo

    References:
        [1] R. T. Shinohara, E. M. Sweeney, J. Goldsmith, N. Shiee,
            F. J. Mateen, P. A. Calabresi, S. Jarso, D. L. Pham,
            D. S. Reich, and C. M. Crainiceanu, “Statistical normalization
            techniques for magnetic resonance imaging,” NeuroImage Clin.,
            vol. 6, pp. 9–19, 2014.
    """

    # grab the file names for the images of interest
    data = io.glob_nii(img_dir)

    # define and get the brain masks for the images, if defined
    if mask_dir is None:
        masks = [None] * len(data)
    else:
        masks = io.glob_nii(mask_dir)
        if len(data) != len(masks):
            raise NormalizationError(
                'Number of images and masks must be equal, Images: {}, Masks: {}'
                .format(len(data), len(masks)))

    # define the output directory and corresponding output file names
    if output_dir is None:
        output_files = [None] * len(data)
    else:
        output_files = []
        for fn in data:
            _, base, ext = io.split_filename(fn)
            output_files.append(os.path.join(output_dir, base + '_ws' + ext))
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

    # do whitestripe normalization and save the results
    for i, (img_fn, mask_fn,
            output_fn) in enumerate(zip(data, masks, output_files), 1):
        logger.info('Normalizing image: {} ({:d}/{:d})'.format(
            img_fn, i, len(data)))
        img = io.open_nii(img_fn)
        mask = io.open_nii(mask_fn) if mask_fn is not None else None
        indices = whitestripe(img, contrast, mask=mask)
        normalized = whitestripe_norm(img, indices)
        if write_to_disk:
            logger.info('Saving normalized image: {} ({:d}/{:d})'.format(
                output_fn, i, len(data)))
            io.save_nii(normalized, output_fn)

    # output the last normalized image (mostly for testing purposes)
    return normalized
예제 #14
0
def ravel_normalize(img_dir,
                    mask_dir,
                    contrast,
                    output_dir=None,
                    write_to_disk=False,
                    do_whitestripe=True,
                    b=1,
                    membership_thresh=0.99,
                    segmentation_smoothness=0.25,
                    do_registration=False,
                    use_fcm=True):
    """
    Use RAVEL [1] to normalize the intensities of a set of MR images to eliminate
    unwanted technical variation in images (but, hopefully, preserve biological variation)

    this function has an option that is modified from [1] in where no registration is done,
    the control mask is defined dynamically by finding a tissue segmentation of the brain and
    thresholding the membership at a very high level (this seems to work well and is *much* faster)
    but there seems to be some more inconsistency in the results

    Args:
        img_dir (str): directory containing MR images to be normalized
        mask_dir (str): brain masks for imgs
        contrast (str): contrast of MR images to be normalized (T1, T2, or FLAIR)
        output_dir (str): directory to save images if you do not want them saved in
            same directory as data_dir
        write_to_disk (bool): write the normalized data to disk or nah
        do_whitestripe (bool): whitestripe normalize the images before applying RAVEL correction
        b (int): number of unwanted factors to estimate
        membership_thresh (float): threshold of membership for control voxels
        segmentation_smoothness (float): segmentation smoothness parameter for atropos ANTsPy
            segmentation scheme (i.e., mrf parameter)
        do_registration (bool): deformably register images to find control mask
        use_fcm (bool): use FCM for segmentation instead of atropos (may be less accurate)

    Returns:
        Z (np.ndarray): unwanted factors (used in ravel correction)
        normalized (np.ndarray): set of normalized images from data_dir

    References:
        [1] J. P. Fortin, E. M. Sweeney, J. Muschelli, C. M. Crainiceanu,
            and R. T. Shinohara, “Removing inter-subject technical variability
            in magnetic resonance imaging studies,” Neuroimage, vol. 132,
            pp. 198–212, 2016.
    """
    img_fns = io.glob_nii(img_dir)
    mask_fns = io.glob_nii(mask_dir)

    if output_dir is None or not write_to_disk:
        out_fns = None
    else:
        out_fns = []
        for fn in img_fns:
            _, base, ext = io.split_filename(fn)
            out_fns.append(os.path.join(output_dir, base + ext))
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)

    # get parameters necessary and setup the V array
    V, Vc = image_matrix(img_fns,
                         contrast,
                         masks=mask_fns,
                         do_whitestripe=do_whitestripe,
                         return_ctrl_matrix=True,
                         membership_thresh=membership_thresh,
                         do_registration=do_registration,
                         smoothness=segmentation_smoothness,
                         use_fcm=use_fcm)

    # estimate the unwanted factors Z
    _, _, vh = np.linalg.svd(Vc)
    Z = vh.T[:, 0:b]

    # perform the ravel correction
    V_norm = ravel_correction(V, Z)

    # save the results to disk if desired
    if write_to_disk:
        for i, (img_fn, out_fn) in enumerate(zip(img_fns, out_fns)):
            img = io.open_nii(img_fn)
            norm = V_norm[:, i].reshape(img.get_data().shape)
            io.save_nii(img, out_fn, data=norm)

    return Z, V_norm
def run_intensity_ravel(outfolder):
    from intensity_normalization.normalize import ravel
    from intensity_normalization.utilities import io, csf

    try:
        images = []
        brainMasks = []
        csfMasks = []
        _, _, filenames = next(walk(outfolder))
        for f in filenames:
            filename = f.split(sep)[-1].split(".")[0]
            images.append(io.open_nii(join(outfolder, f.split(sep)[-1])))
            brainMasks.append(
                io.open_nii(
                    join(outfolder, 'robex_masks', filename + "_mask.nii.gz")))

        if not exists(join(outfolder, "Robex")):
            makedirs(join(outfolder, "Robex"))

        if not exists(join(outfolder, "csf_masks")):
            makedirs(join(outfolder, "csf_masks"))

        print("creating csf masks...")
        for image, brainMask, f in zip(images, brainMasks, filenames):
            filename = f.split(sep)[-1].split(".")[0]
            csfMask = csf.csf_mask(image,
                                   brainMask,
                                   contrast='T1',
                                   csf_thresh=0.9,
                                   return_prob=False,
                                   mrf=0.25,
                                   use_fcm=False)
            output = nib.Nifti1Image(csfMask, None)
            io.save_nii(
                output,
                join(outfolder, 'csf_masks', filename + "_csfmask.nii.gz"))
            shutil.move(join(outfolder,
                             f.split(sep)[-1]), join(outfolder, "Robex"))

        print('running intensity ravel...')
        ravel.ravel_normalize(join(outfolder, 'Robex'),
                              join(outfolder, 'csf_masks'),
                              'T1',
                              output_dir=outfolder,
                              write_to_disk=True,
                              do_whitestripe=True,
                              b=1,
                              membership_thresh=0.99,
                              segmentation_smoothness=0.25,
                              do_registration=False,
                              use_fcm=True,
                              sparse_svd=False,
                              csf_masks=True)

        for i in filenames:
            rename(
                join(outfolder,
                     i.split(sep)[-1]),
                join(outfolder,
                     i.split(sep)[-1].split(".")[0] + "_RAVEL.nii.gz"))
    except:
        e = sys.exc_info()
        print("Error: ", str(e[0]))
        print("Error: ", str(e[1]))
        print("Error: executing ravel method")
        sys.exit(2)