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.')
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.")
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 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]])
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] ])
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.')
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.')