def main():
    # parse cmd arguments
    parser = getParser()
    parser.parse_args()
    args = getArguments(parser)

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)

    # check if output image exists (will also be performed before saving, but as the smoothing might be very time intensity, a initial check can save frustration)
    if not args.force:
        if os.path.exists(args.output):
            raise parser.error('The output image {} already exists.'.format(
                args.output))

    # loading image
    data_input, header_input = load(args.input)

    # apply the watershed
    logger.info(
        'Applying anisotropic diffusion with settings: niter={} / kappa={} / gamma={}...'
        .format(args.iterations, args.kappa, args.gamma))
    data_output = anisotropic_diffusion(data_input, args.iterations,
                                        args.kappa, args.gamma,
                                        get_pixel_spacing(header_input))

    # save file
    save(data_output, args.output, header_input, args.force)

    logger.info('Successfully terminated.')
Example #2
0
def main():
    # parse cmd arguments
    parser = getParser()
    parser.parse_args()
    args = getArguments(parser)
    
    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # check if output image exists (will also be performed before saving, but as the watershed might be very time intensity, a initial check can save frustration)
    if not args.force:
        if os.path.exists(args.output):
            raise ArgumentError('The output image {} already exists.'.format(args.output))
    
    # loading image
    data_input, header_input = load(args.input)
    
    # apply the watershed
    logger.info('Watershedding with settings: thr={} / level={}...'.format(args.threshold, args.level))
    data_output = watershed(data_input, get_pixel_spacing(header_input), args.threshold, args.level)

    # save file
    save(data_output, args.output, header_input, args.force)
    
    logger.info('Successfully terminated.')
def main():
    # parse cmd arguments
    parser = getParser()
    parser.parse_args()
    args = getArguments(parser)

    # prepare logger
    logger = Logger.getInstance()
    if args.debug:
        logger.setLevel(logging.DEBUG)
    elif args.verbose:
        logger.setLevel(logging.INFO)

    # check if output image exists (will also be performed before saving, but as the watershed might be very time intensity, a initial check can save frustration)
    if not args.force:
        if os.path.exists(args.output):
            raise ArgumentError("The output image {} already exists.".format(args.output))

    # loading image
    data_input, header_input = load(args.input)

    # apply the watershed
    logger.info("Watershedding with settings: thr={} / level={}...".format(args.threshold, args.level))
    data_output = watershed(data_input, get_pixel_spacing(header_input), args.threshold, args.level)

    # save file
    save(data_output, args.output, header_input, args.force)

    logger.info("Successfully terminated.")
Example #4
0
def segment_case(sequences, classifier, standardbrain_sequence,
                 standardbrain_path, skullstripped=False):
    """Run pipeline for given sequences."""
    log.debug(str(sequences))
    # -- run preprocessing pipeline
    resampled, transforms = resample(
        sequences, classifier.pixel_spacing, classifier.registration_base)
    log.debug(str(resampled))
    # if not skullstripped:
    skullstripped_sequences, brainmask = skullstrip(
        resampled, classifier.skullstripping_base)
    log.debug(str(skullstripped_sequences))
    # else:
    #    skullstripped_sequences = resampled
    bfced = correct_biasfield(skullstripped_sequences, brainmask)
    log.debug(str(bfced))

    preprocessed = standardize_intensityrange(
            bfced, brainmask, classifier.intensity_models)
    log.debug(str(preprocessed))

    for key in preprocessed:
        output(preprocessed[key])
    output(brainmask, 'brainmask.nii.gz')

    # -- perform image segmentation
    segmentation, probability = segment(
        preprocessed, brainmask, classifier.features,
        classifier.classifier_file)
    output(segmentation, 'segmentation.nii.gz')
    output(probability, 'probability.nii.gz')

    # -- register lesion mask to standardbrain
    tokens = standardbrain_path.split('.')
    tokens[0] += '_mask'
    standardbrain_mask_path = '.'.join(tokens)
    if (not skullstripped) or (not os.path.isfile(standardbrain_mask_path)):
        standardbrain_mask_path = None

    if standardbrain_sequence == classifier.registration_base:
        _, header = mio.load(sequences[standardbrain_sequence])
        original_dims = mio.get_pixel_spacing(header)
        spacing = ','.join(map(str, original_dims))
        standard_mask = register_to_standardbrain(
            segmentation, standardbrain_path,
            sequences[standardbrain_sequence],
            standardbrain_mask=standardbrain_mask_path,
            auxilliary_original_spacing=spacing)
    else:
        standard_mask = register_to_standardbrain(
            segmentation, standardbrain_path,
            sequences[standardbrain_sequence],
            standardbrain_mask=standardbrain_mask_path,
            auxilliary_transform=transforms[standardbrain_sequence])
    output(standard_mask, 'standard_segmentation.nii')
    return standard_mask
Example #5
0
def calculate_atlas_overlaps(mask):
    """Given an image mask, calculate overlap with all available atlases."""
    atlas_files = _get_atlas_files()
    mask, mask_header = mio.load(mask)

    mask_spacing = mio.get_pixel_spacing(mask_header)
    pixel_volume = mask_spacing[0] * mask_spacing[1] * mask_spacing[2]

    for atlas_file in atlas_files:
        atlas, atlas_header = mio.load(atlas_file)
        # if dimensions of mask (standardbrain) and atlas do not match, skip
        # if atlas.shape != mask.shape:
        atlas_spacing = mio.get_pixel_spacing(atlas_header)
        if mask_spacing != atlas_spacing:
            log.warning('Atlas {} will be skipped due to mismatching pixel'
                        ' spacing (atlas: {}, segmentation: {})'
                        .format(os.path.basename(atlas_file), atlas_spacing,
                                mask_spacing))
            continue
        overlap = atlas[mask.astype(numpy.bool)]

        region_sizes = numpy.bincount(atlas.ravel())
        overlap_region_sizes = numpy.bincount(overlap.ravel())

        atlas_name = os.path.basename(atlas_file).split('.')[0]
        region_names = _get_region_name_map(atlas_name)
        out_csv_path = os.path.join(config.get().case_output_dir,
                                    atlas_name + '.csv')
        w = csv.writer(open(out_csv_path, 'w'))
        w.writerow(
            ['value', 'id', 'voxel overlap', 'mL overlap', 'percent overlap'])
        for index, number in enumerate(overlap_region_sizes):
            if number != 0:
                w.writerow([index,
                            region_names[index],
                            number,
                            (number * pixel_volume) / 1000,
                            float(number) / region_sizes[index]])
Example #6
0
def calculate_atlas_overlaps(mask):
    """Given an image mask, calculate overlap with all available atlases."""
    atlas_files = _get_atlas_files()
    mask, mask_header = mio.load(mask)

    mask_spacing = mio.get_pixel_spacing(mask_header)
    pixel_volume = mask_spacing[0] * mask_spacing[1] * mask_spacing[2]

    for atlas_file in atlas_files:
        atlas, atlas_header = mio.load(atlas_file)
        # if dimensions of mask (standardbrain) and atlas do not match, skip
        # if atlas.shape != mask.shape:
        atlas_spacing = mio.get_pixel_spacing(atlas_header)
        if mask_spacing != atlas_spacing:
            log.warning('Atlas {} will be skipped due to mismatching pixel'
                        ' spacing (atlas: {}, segmentation: {})'.format(
                            os.path.basename(atlas_file), atlas_spacing,
                            mask_spacing))
            continue
        overlap = atlas[mask.astype(numpy.bool)]

        region_sizes = numpy.bincount(atlas.ravel())
        overlap_region_sizes = numpy.bincount(overlap.ravel())

        atlas_name = os.path.basename(atlas_file).split('.')[0]
        region_names = _get_region_name_map(atlas_name)
        out_csv_path = os.path.join(config.get().case_output_dir,
                                    atlas_name + '.csv')
        w = csv.writer(open(out_csv_path, 'w'))
        w.writerow(
            ['value', 'id', 'voxel overlap', 'mL overlap', 'percent overlap'])
        for index, number in enumerate(overlap_region_sizes):
            if number != 0:
                w.writerow([
                    index, region_names[index], number,
                    (number * pixel_volume) / 1000,
                    float(number) / region_sizes[index]
                ])
Example #7
0
def printInfo(data, header):
    # print image information
    print '\nInformations obtained from image header:'
    print 'header type={}'.format(type(header))
    try:
        print 'voxel spacing={}'.format(get_pixel_spacing(header))
    except AttributeError:
        print 'Failed to retrieve voxel spacing.'
    try:
        print 'offset={}'.format(get_offset(header))
    except AttributeError:
        print 'Failed to retrieve offset.'    
    
    print '\nInformations obtained from image array:'
    print 'datatype={},dimensions={},shape={}'.format(data.dtype, data.ndim, data.shape)
    print 'first and last element: {} / {}'.format(data.flatten()[0], data.flatten()[-1])
Example #8
0
def printInfo(data, header):
    # print image information
    print '\nInformations obtained from image header:'
    print 'header type={}'.format(type(header))
    try:
        print 'voxel spacing={}'.format(get_pixel_spacing(header))
    except AttributeError:
        print 'Failed to retrieve voxel spacing.'
    try:
        print 'offset={}'.format(get_offset(header))
    except AttributeError:
        print 'Failed to retrieve offset.'

    print '\nInformations obtained from image array:'
    print 'datatype={},dimensions={},shape={}'.format(data.dtype, data.ndim,
                                                      data.shape)
    print 'first and last element: {} / {}'.format(data.flatten()[0],
                                                   data.flatten()[-1])
def main():
    # parse cmd arguments
    parser = getParser()
    parser.parse_args()
    args = getArguments(parser)
    
    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # check if output image exists (will also be performed before saving, but as the smoothing might be very time intensity, a initial check can save frustration)
    if not args.force:
        if os.path.exists(args.output):
            raise parser.error('The output image {} already exists.'.format(args.output))
    
    # loading image
    data_input, header_input = load(args.input)
    
    # apply the watershed
    logger.info('Applying anisotropic diffusion with settings: niter={} / kappa={} / gamma={}...'.format(args.iterations, args.kappa, args.gamma))
    data_output = anisotropic_diffusion(data_input, args.iterations, args.kappa, args.gamma, get_pixel_spacing(header_input))

    # save file
    save(data_output, args.output, header_input, args.force)
    
    logger.info('Successfully terminated.')
Example #10
0
def segment_case(sequences,
                 classifier,
                 standardbrain_sequence,
                 standardbrain_path,
                 skullstripped=False):
    """Run pipeline for given sequences."""
    log.debug(str(sequences))
    # -- run preprocessing pipeline
    resampled, transforms = resample(sequences, classifier.pixel_spacing,
                                     classifier.registration_base)
    log.debug(str(resampled))
    # if not skullstripped:
    skullstripped_sequences, brainmask = skullstrip(
        resampled, classifier.skullstripping_base)
    log.debug(str(skullstripped_sequences))
    # else:
    #    skullstripped_sequences = resampled
    bfced = correct_biasfield(skullstripped_sequences, brainmask)
    log.debug(str(bfced))

    preprocessed = standardize_intensityrange(bfced, brainmask,
                                              classifier.intensity_models)
    log.debug(str(preprocessed))

    for key in preprocessed:
        output(preprocessed[key])
    output(brainmask, 'brainmask.nii.gz')

    # -- perform image segmentation
    segmentation, probability = segment(preprocessed, brainmask,
                                        classifier.features,
                                        classifier.classifier_file)
    output(segmentation, 'segmentation.nii.gz')
    output(probability, 'probability.nii.gz')

    # -- register lesion mask to standardbrain
    tokens = standardbrain_path.split('.')
    tokens[0] += '_mask'
    standardbrain_mask_path = '.'.join(tokens)
    if (not skullstripped) or (not os.path.isfile(standardbrain_mask_path)):
        standardbrain_mask_path = None

    if standardbrain_sequence == classifier.registration_base:
        _, header = mio.load(sequences[standardbrain_sequence])
        original_dims = mio.get_pixel_spacing(header)
        spacing = ','.join(map(str, original_dims))
        standard_mask = register_to_standardbrain(
            segmentation,
            standardbrain_path,
            sequences[standardbrain_sequence],
            standardbrain_mask=standardbrain_mask_path,
            auxilliary_original_spacing=spacing)
    else:
        standard_mask = register_to_standardbrain(
            segmentation,
            standardbrain_path,
            sequences[standardbrain_sequence],
            standardbrain_mask=standardbrain_mask_path,
            auxilliary_transform=transforms[standardbrain_sequence])
    output(standard_mask, 'standard_segmentation.nii')
    return standard_mask
def main():
    # parse cmd arguments
    parser = getParser()
    parser.parse_args()
    args = getArguments(parser)
    
    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # load reference image
    image_reference_data, image_reference_header = load(args.reference)
    
    # prepare reference image data
    image_reference_data = (0 != image_reference_data) # ensures that the reference mask is of type bool
    image_reference_size = len(image_reference_data.nonzero()[0])
    
    # raise exception when the input mask is zero
    if 0 >= image_reference_size:
        raise Exception('The reference mask if of size <= 0.')
    
    # extract pyhsical pixel spacing
    spacing = numpy.array(get_pixel_spacing(image_reference_header))
    
    # print header if requested
    if args.header:
        print '{}/{};'.format(args.reference.split('/')[-1], image_reference_size) ,
        print 'mask-size;VolumetricOverlapError;RelativeVolumeDifference;AverageSymmetricSurfaceDistance;MaximumSymmetricSurfaceDistance;RootMeanSquareSymmetricSurfaceDistance'
    
    # load mask using nibabel
    image_mask_data, image_mask_header = load(args.input)
            
    # check if physical pixel spacing is coherent
    mask_spacing = numpy.array(get_pixel_spacing(image_mask_header))
    if not (spacing == mask_spacing).all():
        if not args.ignore:
            print 'Stopped. Incoherent pixel spacing (reference={}/mask={})\n'.format(spacing, mask_spacing)
            logger.warning('The physical pixel spacings of reference ({}) and mask ({}) do not comply. Breaking evaluation.'.format(spacing, mask_spacing))
            sys.exit(-1)
        else:
            logger.warning('The physical pixel spacings of reference ({}) and mask ({}) do not comply. Evaluation continued nevertheless, as ignore flag is set.'.format(spacing, mask_spacing))
            
    # prepare mask data
    image_mask_data = (0 != image_mask_data) # ensures that the mask is of type bool
    image_mask_size = len(image_mask_data.nonzero()[0])
    
    # write mask name and size into file
    print '{};{}'.format(args.input.split('/')[-1], image_mask_size) ,

    # warn when the mask is of size 0 or less
    if 0 >= image_mask_size:
        print ';Skipped: mask size is 0'
        logger.warning('The mask is of size <= 0. Breaking evaluation.')
        sys.exit(-1)
    
    # skip if reference mask ratio hints to bad results
    if 0.75 > 1. * image_reference_size / image_mask_size or 1.25 < 1. * image_reference_size / image_mask_size:
        print ';Skipped: reference/mask <0.075 or >1.25'
        logger.warning('The reference/mask ration of the mask is <0.075 or >1.25. Breaking evaluation.')
        sys.exit(-1)
    
    # volume metrics
    logger.info('Calculating volume metrics...')
    v = Volume(image_mask_data, image_reference_data)
    print ';{};{}'.format(v.get_volumetric_overlap_error(),
                            v.get_relative_volume_difference()) ,
    
    logger.info('Calculating surface metrics...')
    s = Surface(image_mask_data, image_reference_data, spacing)
    print ';{};{};{}'.format(s.get_average_symmetric_surface_distance(),
                               s.get_maximum_symmetric_surface_distance(),
                               s.get_root_mean_square_symmetric_surface_distance())

    
    logger.info('Successfully terminated.')