Exemple #1
0
def main():
    args = getArguments(getParser())

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

    # loading input images
    b0img, b0hdr = load(args.b0image)
    bximg, bxhdr = load(args.bximage)

    # check if image are compatible
    if not b0img.shape == bximg.shape:
        raise ArgumentError(
            'The input images shapes differ i.e. {} != {}.'.format(
                b0img.shape, bximg.shape))
    if not header.get_pixel_spacing(b0hdr) == header.get_pixel_spacing(bxhdr):
        raise ArgumentError(
            'The input images voxel spacing differs i.e. {} != {}.'.format(
                header.get_pixel_spacing(b0hdr),
                header.get_pixel_spacing(bxhdr)))

    # check if supplied threshold value as well as the b value is above 0
    if args.threshold is not None and not args.threshold >= 0:
        raise ArgumentError(
            'The supplied threshold value must be greater than 0, otherwise a division through 0 might occur.'
        )
    if not args.b > 0:
        raise ArgumentError('The supplied b-value must be greater than 0.')

    # compute threshold value if not supplied
    if args.threshold is None:
        b0thr = otsu(b0img, 32) / 2.  # divide by 2 to decrease impact
        bxthr = otsu(bximg, 32) / 2.
        if 0 >= b0thr:
            raise ArgumentError(
                'The supplied b0image seems to contain negative values.')
        if 0 >= bxthr:
            raise ArgumentError(
                'The supplied bximage seems to contain negative values.')
    else:
        b0thr = bxthr = args.threshold

    logger.debug('thresholds={}/{}, b-value={}'.format(b0thr, bxthr, args.b))

    # threshold b0 + bx DW image to obtain a mask
    # b0 mask avoid division through 0, bx mask avoids a zero in the ln(x) computation
    mask = (b0img > b0thr) & (bximg > bxthr)

    logger.debug(
        'excluding {} of {} voxels from the computation and setting them to zero'
        .format(scipy.count_nonzero(mask), scipy.prod(mask.shape)))

    # compute the ADC
    adc = scipy.zeros(b0img.shape, b0img.dtype)
    adc[mask] = -1. * args.b * scipy.log(bximg[mask] / b0img[mask])

    # saving the resulting image
    save(adc, args.output, b0hdr, args.force)
Exemple #2
0
def zoom(image, factor, dimension, hdr = False, order = 3):
    """
    Zooms the provided image by the supplied factor in the supplied dimension.
    The factor is an integer determining how many slices should be put between each
    existing pair.
    If an image header (hdr) is supplied, its voxel spacing gets updated.
    Returns the image and the updated header or false.
    """
    # check if supplied dimension is valid
    if dimension >= image.ndim:
        raise argparse.ArgumentError('The supplied zoom-dimension {} exceeds the image dimensionality of 0 to {}.'.format(dimension, image.ndim - 1))
    
    # get logger
    logger = Logger.getInstance()

    logger.debug('Old shape = {}.'.format(image.shape))

    # perform the zoom
    zoom = [1] * image.ndim
    zoom[dimension] = (image.shape[dimension] + (image.shape[dimension] - 1) * factor) / float(image.shape[dimension])
    logger.debug('Reshaping with = {}.'.format(zoom))
    image = interpolation.zoom(image, zoom, order=order)
        
    logger.debug('New shape = {}.'.format(image.shape))
    
    if hdr:
        new_spacing = list(header.get_pixel_spacing(hdr))
        new_spacing[dimension] = new_spacing[dimension] / float(factor + 1)
        logger.debug('Setting pixel spacing from {} to {}....'.format(header.get_pixel_spacing(hdr), new_spacing))
        header.set_pixel_spacing(hdr, tuple(new_spacing))
    
    return image, hdr
Exemple #3
0
def main():
	onedir = sys.argv[1] # the first folder containing case folders
	twodir = sys.argv[2] # the second folder containing case folders
	nocase = (len(sys.argv) > 3 and sys.argv[3] == '-i')

	if DEBUG: print 'INFO: Comparing all cases in folders {} and {}.'.format(onedir, twodir)

	# iterate over first folder and compare voxel spacings with equivalent image in second folder
	print "Case\tvs same\tshape same"
	for root, dirs, files in os.walk(onedir):
		for case in sorted(dirs):
			for root, dirs, files in os.walk('{}/{}'.format(onedir, case)):
				for file_ in files:
					if file_.endswith(FILE_ENDING):
						i, hi = load('{}/{}/{}'.format(onedir, case, file_))
						if nocase:
							j, hj = load('{}/{}.{}'.format(twodir, case, FILE_ENDING))
						else:
							j, hj = load('{}/{}/{}'.format(twodir, case, file_))
						vs_same = numpy.array_equal(header.get_pixel_spacing(hi), header.get_pixel_spacing(hj))
						shape_same = numpy.array_equal(i.shape, j.shape)
						print '{}\t{}\t{}'.format(case, vs_same, shape_same)
						if not vs_same:
							print "\t{} vs {}".format(header.get_pixel_spacing(hi), header.get_pixel_spacing(hj))
						if not shape_same:
							print "\t{} vs {}".format(i.shape, j.shape)
	print 'Terminated.'
def main():
    args = getArguments(getParser())

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # loading input images
    b0img, b0hdr = load(args.b0image)
    bximg, bxhdr = load(args.bximage)
    
    # convert to float
    b0img = b0img.astype(numpy.float)
    bximg = bximg.astype(numpy.float)

    # check if image are compatible
    if not b0img.shape == bximg.shape:
        raise ArgumentError('The input images shapes differ i.e. {} != {}.'.format(b0img.shape, bximg.shape))
    if not header.get_pixel_spacing(b0hdr) == header.get_pixel_spacing(bxhdr):
        raise ArgumentError('The input images voxel spacing differs i.e. {} != {}.'.format(header.get_pixel_spacing(b0hdr), header.get_pixel_spacing(bxhdr)))
    
    # check if supplied threshold value as well as the b value is above 0
    if args.threshold is not None and not args.threshold >= 0:
        raise ArgumentError('The supplied threshold value must be greater than 0, otherwise a division through 0 might occur.')
    if not args.b > 0:
        raise ArgumentError('The supplied b-value must be greater than 0.')
    
    # compute threshold value if not supplied
    if args.threshold is None:
        b0thr = otsu(b0img, 32) / 4. # divide by 4 to decrease impact
        bxthr = otsu(bximg, 32) / 4.
        if 0 >= b0thr:
            raise ArgumentError('The supplied b0image seems to contain negative values.')
        if 0 >= bxthr:
            raise ArgumentError('The supplied bximage seems to contain negative values.')
    else:
        b0thr = bxthr = args.threshold
    
    logger.debug('thresholds={}/{}, b-value={}'.format(b0thr, bxthr, args.b))
    
    # threshold b0 + bx DW image to obtain a mask
    # b0 mask avoid division through 0, bx mask avoids a zero in the ln(x) computation
    mask = binary_fill_holes(b0img > b0thr) & binary_fill_holes(bximg > bxthr)
    
    # perform a number of binary morphology steps to select the brain only
    mask = binary_erosion(mask, iterations=1)
    mask = largest_connected_component(mask)
    mask = binary_dilation(mask, iterations=1)
    
    logger.debug('excluding {} of {} voxels from the computation and setting them to zero'.format(numpy.count_nonzero(mask), numpy.prod(mask.shape)))
    
    # compute the ADC
    adc = numpy.zeros(b0img.shape, b0img.dtype)
    adc[mask] = -1. * args.b * numpy.log(bximg[mask] / b0img[mask])
    adc[adc < 0] = 0
            
    # saving the resulting image
    save(adc, args.output, b0hdr, args.force)
Exemple #5
0
def test03(img, hdr, idx, delta):
    # TEST 03: DOES ANY META-INFORMATION GET LOST DURING FORMAT CONVERSION? AND IF YES; WHICH?
    for tr in types_int: # reference type
        print ''
        oformat = tr
        
        # create, save and load reference image
        try:
            name_ref = tmp_folder + '.'.join(['tmp_ref', tr])
            save(img, name_ref, hdr, True)
            img_ref, hdr_ref = load(name_ref)
        except Exception as e:
            print '\tERROR: Could not generate reference image for type {}: {}'.format(otype, e)
            continue
        
        # extract meta-data from reference image
        mdata_ref = {'shape': img_ref.shape,
                     'dtype': img_ref.dtype,
                     'point': img_ref[idx],
                     'spacing': header.get_pixel_spacing(hdr_ref),
                     'offset': header.get_offset(hdr_ref),}        
        
        # print meta-data from reference image
        
        # iterate of test images
        for tt in types_int: # test type
            print '{} => {}'.format(oformat, tt),
            
            # create, save and load test images
            try:
                #print type(img_ref), type(hdr_ref)
                #print type(img_test), type(hdr_test)
                name_test = tmp_folder + '.'.join(['tmp_test', tt])
                save(img_ref, name_test, hdr_ref, True)
                img_test, hdr_test = load(name_test)
                
            except Exception as e:
                print '\tERROR: Could not generate test image. {}'.format(e)
                continue
            
            # extract meta-data from test image
            mdata_test = {'shape': img_test.shape,
                          'dtype': img_test.dtype,
                          'spacing': header.get_pixel_spacing(hdr_test),
                          'offset': header.get_offset(hdr_test),
                          'point': img_test[idx]}                    
            
            # compare reference against meta-image
            error = False
            for k in mdata_ref.keys():
                equal = _compare(mdata_ref[k], mdata_test[k], delta)
                #print '\n\t{} ({}) : {} = {}'.format(equal, k, mdata_ref[k], mdata_test[k]),
                if not equal:
                    error = True
                    print '\n\t{} ({}) : {} = {}'.format(equal, k, mdata_ref[k], mdata_test[k]),
            if not error:
                print '\t{}'.format(True)
            else:
                print '\n'
Exemple #6
0
def resample(img, hdr, target_spacing, bspline_order=3, mode='constant'):
        """
        Re-sample an image to a new voxel-spacing. Taken form medpy.io.


        
        Parameters
        ----------
        img : array_like
            The image.
        hdr : object
            The image header.
        target_spacing : number or sequence of numbers
            The target voxel spacing to achieve. If a single number, isotropic spacing is assumed.
        bspline_order : int
            The bspline order used for interpolation.
        mode : str
            Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). Default is 'constant'.
            
        Warning
        -------
        Voxel-spacing of input header will be modified in-place! If the target spacing can't be set exactly, for example in low pixel images, then the closest spacing will be chosen
            
        Returns
        -------
        img : ndarray
            The re-sampled image.
        hdr : object
            The image header with the new voxel spacing.
        """
        if isinstance(target_spacing, numbers.Number):
            target_spacing = [target_spacing] * img.ndim
        
        # compute zoom values
        zoom_factors = [old / float(new) for new, old in zip(target_spacing, header.get_pixel_spacing(hdr))]

        print "Zoom Factors"
        print zoom_factors

        oldImageShape = img.shape
    
        # zoom image
        img = zoom(img, zoom_factors, order=bspline_order, mode=mode)

        newImageShape = img.shape
        old_pixel_spacing = header.get_pixel_spacing(hdr)
        new_pixel_spacing = np.round(np.divide(np.multiply(oldImageShape,old_pixel_spacing),newImageShape),7)
        print "Target Pixel Spacing"
        print target_spacing

        print "Actual Pixel Spacing"
        print new_pixel_spacing
        # set new voxel spacing
        header.set_pixel_spacing(hdr, new_pixel_spacing)
        
        return img, hdr
Exemple #7
0
def main():
    args = getArguments(getParser())

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

    # load input data
    input_data, input_header = load(args.input)

    logger.debug('Old shape = {}.'.format(input_data.shape))

    # compute new shape
    new_shape = list(input_data.shape)
    new_shape[args.dimension] = 1 + (new_shape[args.dimension] -
                                     1) / (args.discard + 1)

    # prepare output image
    output_data = scipy.zeros(new_shape, dtype=input_data.dtype)

    # prepare slicers
    slicer_in = [slice(None)] * input_data.ndim
    slicer_out = [slice(None)] * input_data.ndim

    # prepare skip-counter and output image slice counter
    skipc = 0
    slicec = 0

    logger.debug('Shrinking from {} to {}...'.format(input_data.shape,
                                                     new_shape))
    for idx in range(input_data.shape[args.dimension]):

        if 0 == skipc:
            # transfer slice
            slicer_in[args.dimension] = slice(idx, idx + 1)
            slicer_out[args.dimension] = slice(slicec, slicec + 1)
            output_data[slicer_out] = input_data[slicer_in]

            # resert resp. increase counter
            skipc = args.discard
            slicec += 1

        else:  # skip slice
            # decrease skip counter
            skipc -= 1

    # set new pixel spacing
    new_spacing = list(header.get_pixel_spacing(input_header))
    new_spacing[
        args.dimension] = new_spacing[args.dimension] * float(args.discard + 1)
    logger.debug('Setting pixel spacing from {} to {}....'.format(
        header.get_pixel_spacing(input_header), new_spacing))
    header.set_pixel_spacing(input_header, tuple(new_spacing))

    save(output_data, args.output, input_header, args.force)
Exemple #8
0
 def __diff(self, hdr1, hdr2):
     """
     Returns an error message if the meta-data of the supplied headers differ,
     otherwise False. 
     """
     if not self.__same_seq(header.get_pixel_spacing(hdr1), header.get_pixel_spacing(hdr2)):
         return 'the voxel spacing is not consistent: {} != {}'.format(header.get_pixel_spacing(hdr1), header.get_pixel_spacing(hdr2))
     if not self.__same_seq(header.get_offset(hdr1), header.get_offset(hdr2)):
         return 'the offset is not consistent: {} != {}'.format(header.get_offset(hdr1), header.get_offset(hdr2))
         #return 'the offset is not consistent: {} != {}\n{} / {}\n{} / {}'.format(header.get_offset(hdr1), header.get_offset(hdr2), type(hdr1), type(hdr2), hdr2.NumberOfFrames if "NumberOfFrames" in hdr2 else "NONE", hdr2.ImagePositionPatient if "ImagePositionPatient" in hdr2 else 'NONE')
     else: return False
Exemple #9
0
def main():
    args = getArguments(getParser())

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # load input data
    input_data, input_header = load(args.input)
    
    logger.debug('Old shape = {}.'.format(input_data.shape))
    
    # compute new shape
    new_shape = list(input_data.shape)
    new_shape[args.dimension] = 1 + (new_shape[args.dimension] - 1) / (args.discard + 1)
    
    # prepare output image
    output_data = scipy.zeros(new_shape, dtype=input_data.dtype)
    
    # prepare slicers
    slicer_in = [slice(None)] * input_data.ndim
    slicer_out = [slice(None)] * input_data.ndim
    
    # prepare skip-counter and output image slice counter
    skipc = 0
    slicec = 0
    
    logger.debug('Shrinking from {} to {}...'.format(input_data.shape, new_shape))
    for idx in range(input_data.shape[args.dimension]):
        
        if 0 == skipc:
            # transfer slice
            slicer_in[args.dimension] = slice(idx, idx + 1)
            slicer_out[args.dimension]  = slice(slicec, slicec + 1)
            output_data[slicer_out] = input_data[slicer_in]
            
            # resert resp. increase counter
            skipc = args.discard
            slicec += 1
            
        else: # skip slice
            # decrease skip counter
            skipc -= 1

    
    # set new pixel spacing
    new_spacing = list(header.get_pixel_spacing(input_header))
    new_spacing[args.dimension] = new_spacing[args.dimension] * float(args.discard + 1)
    logger.debug('Setting pixel spacing from {} to {}....'.format(header.get_pixel_spacing(input_header), new_spacing))
    header.set_pixel_spacing(input_header, tuple(new_spacing))
    
    save(output_data, args.output, input_header, args.force)
def main():

	# catch parameters
	segmentation_base_string = sys.argv[1]
	ground_truth_base_string = sys.argv[2]
	mask_file_base_string = sys.argv[3]
	cases = sys.argv[4:]

	# evaluate each case and collect the scores
	hds = []
	assds = []
	precisions = []
	recalls = []
	dcs = []

	# load images and apply mask to segmentation and ground truth (to remove ground truth fg outside of brain mask)
	splush = [load(segmentation_base_string.format(case)) for case in cases]
	tplush = [load(ground_truth_base_string.format(case)) for case in cases]
	masks = [load(mask_file_base_string.format(case))[0].astype(numpy.bool) for case in cases]

	s = [s.astype(numpy.bool) & m for (s, _), m in zip(splush, masks)]
	t = [t.astype(numpy.bool) & m for (t, _), m in zip(tplush, masks)]
	hs = [h for _, h in splush]
	ht = [h for _, h in tplush]

	# compute and append metrics (Pool-processing)
	pool = Pool(n_jobs)
	dcs = pool.map(wdc, zip(t, s))
	precisions = pool.map(wprecision, zip(s, t))
	recalls = pool.map(wrecall, zip(s, t))
	hds = pool.map(whd, zip(t, s, [header.get_pixel_spacing(h) for h in ht]))
	assds = pool.map(wassd, zip(t, s, [header.get_pixel_spacing(h) for h in ht]))

	# print case-wise results
	print 'Metrics:'
	print 'Case\tDC[0,1]\tHD(mm)\tP2C(mm)\tprec.\trecall'
    	for case, _dc, _hd, _assd, _pr, _rc in zip(cases, dcs, hds, assds, precisions, recalls):
        	print '{}\t{:>3,.3f}\t{:>4,.3f}\t{:>4,.3f}\t{:>3,.3f}\t{:>3,.3f}'.format(case, _dc, _hd, _assd, _pr, _rc)
        
	# check for nan/inf values of failed cases and signal warning
	mask = numpy.isfinite(hds)
	if not numpy.all(mask):
		print 'WARNING: Average values only computed on {} of {} cases!'.format(numpy.count_nonzero(mask), mask.size)
		
    	print 'DM  average\t{} +/- {} (Median: {})'.format(numpy.asarray(dcs)[mask].mean(), numpy.asarray(dcs)[mask].std(), numpy.median(numpy.asarray(dcs)[mask]))
    	print 'HD  average\t{} +/- {} (Median: {})'.format(numpy.asarray(hds)[mask].mean(), numpy.asarray(hds)[mask].std(), numpy.median(numpy.asarray(hds)[mask]))
    	print 'ASSD average\t{} +/- {} (Median: {})'.format(numpy.asarray(assds)[mask].mean(), numpy.asarray(assds)[mask].std(), numpy.median(numpy.asarray(assds)[mask]))
    	print 'Prec. average\t{} +/- {} (Median: {})'.format(numpy.asarray(precisions)[mask].mean(), numpy.asarray(precisions)[mask].std(), numpy.median(numpy.asarray(precisions)[mask]))
    	print 'Rec. average\t{} +/- {} (Median: {})'.format(numpy.asarray(recalls)[mask].mean(), numpy.asarray(recalls)[mask].std(), numpy.median(numpy.asarray(recalls)[mask]))
def main():
    args = getArguments(getParser())

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # load input image
    data_input, header_input = load(args.input)
    
    # transform to uin8
    data_input = data_input.astype(scipy.uint8)
                                      
    # reduce to 3D, if larger dimensionality
    if data_input.ndim > 3:
        for _ in range(data_input.ndim - 3): data_input = data_input[...,0]
        
    # iter over slices (2D) until first with content is detected
    for plane in data_input:
        if scipy.any(plane):
            # set pixel spacing
            spacing = list(header.get_pixel_spacing(header_input))
            spacing = spacing[1:3]
            __update_header_from_array_nibabel(header_input, plane)
            header.set_pixel_spacing(header_input, spacing)
            # save image
            save(plane, args.output, header_input, args.force)
            break
    
    logger.info("Successfully terminated.")    
Exemple #12
0
def sresamplebyexample(src, dest, referenceimage, binary = False):
    r"""
    Secure-re-sample an image located at ``src`` by example ``referenceimage`` and
    save it under ``dest``.
    
    Parameters
    ----------
    src : string
        Source image file.
    dest : string
        Destination image file.
    referenceimage : string
        Reference image displaying the target spacing, origin and size.
    binary : bool
        Set to ``True`` for binary images.
    """
    # get target voxel spacing
    refimage, refhdr = load(referenceimage)
    spacing = header.get_pixel_spacing(refhdr)
    
    with tmpdir() as t:
        # create a temporary copy of the reference image with the source image data-type (imiImageResample requires both images to be of the same dtype)
        srcimage, _ = load(src)
        save(refimage.astype(srcimage.dtype), os.path.join(t, 'ref.nii.gz'), refhdr)
    
        # prepare and run registration command
        cmd = ['imiImageResample', '-I', src, '-O', dest, '-R', os.path.join(t, 'ref.nii.gz'), '-s'] + map(str, spacing)
        if binary:
            cmd += ['-b']
        rtcode, stdout, stderr = call(cmd)
    
    # check if successful
    if not os.path.isfile(dest):
        raise CommandExecutionError(cmd, rtcode, stdout, stderr, 'Binary re-sampling result image not created.')
Exemple #13
0
def main():
	i, h = load(sys.argv[1])

	print 'Image:\t{}'.format(sys.argv[1])
	print 'Shape:\t{}'.format(i.shape)
	print 'Spacing:{}'.format(header.get_pixel_spacing(h))
	print 'Offset:\t{}'.format(header.get_offset(h))

	if 0 == h.get_header()['qform_code']:
		method = 'ANALYZE 7.5 (old)'
	if h.get_header()['qform_code'] > 0:
		method = 'Normal (qform)'
	if h.get_header()['sform_code'] > 0:
		method = 'Special space (sform)'

	print
	print 'Orientation and location in space:'
	print 'Type:\t\t{}'.format(method)
	print 'qform_code:\t{}'.format(h.get_header()['qform_code'])
	print 'sform_code:\t{}'.format(h.get_header()['sform_code'])

	print
	print 'qform == sform?\t{} (max diff={})'.format(numpy.all(h.get_qform() == h.get_sform()), numpy.max(numpy.abs(h.get_qform() - h.get_sform())))
	print 'affine = qform?\t{} (max diff={})'.format(numpy.all(h.get_affine() == h.get_qform()), numpy.max(numpy.abs(h.get_affine() - h.get_qform())))
	print 'affine = sform?\t{} (max diff={})'.format(numpy.all(h.get_affine() == h.get_sform()), numpy.max(numpy.abs(h.get_affine() - h.get_sform())))

	print
	print 'qform:'
	print h.get_qform()
	print 'sform:'
	print h.get_sform()
	print 'affine:'
	print h.get_affine()
 def __diff(self, hdr1, hdr2):
     """
     Returns an error message if the meta-data of the supplied headers differ,
     otherwise False. 
     """
     if not self.__same_seq(header.get_pixel_spacing(hdr1),
                            header.get_pixel_spacing(hdr2)):
         return 'the voxel spacing is not consistent: {} != {}'.format(
             header.get_pixel_spacing(hdr1), header.get_pixel_spacing(hdr2))
     if not self.__same_seq(header.get_offset(hdr1),
                            header.get_offset(hdr2)):
         return 'the offset is not consistent: {} != {}'.format(
             header.get_offset(hdr1), header.get_offset(hdr2))
         #return 'the offset is not consistent: {} != {}\n{} / {}\n{} / {}'.format(header.get_offset(hdr1), header.get_offset(hdr2), type(hdr1), type(hdr2), hdr2.NumberOfFrames if "NumberOfFrames" in hdr2 else "NONE", hdr2.ImagePositionPatient if "ImagePositionPatient" in hdr2 else 'NONE')
     else:
         return False
Exemple #15
0
def main():
	i1, h1 = load(sys.argv[1])
	i2, h2 = load(sys.argv[2])

	# shift image to align origins
	origin_h1 = numpy.sign(h1.get_qform()[0:3,0:3]).dot(header.get_offset(h1))
	origin_h2 = numpy.sign(h2.get_qform()[0:3,0:3]).dot(header.get_offset(h2))
	origin_difference_pixel = (origin_h1 - origin_h2) / numpy.asarray(header.get_pixel_spacing(h1))
	# negative values: shift image 1 by this upon inserting (which is the smae as cutting the output image)
	# positive values: cut image 1 by this at inserting and also cut right side by length of output image plus this value
	o = numpy.zeros(i2.shape, i2.dtype)
	o_slicer = []
	i_slicer = []
	for j, p in enumerate(origin_difference_pixel):
		if p >= 0:
			i_slicer.append(slice(0,      min(i1.shape[j], o.shape[j] - abs(p))))
			o_slicer.append(slice(abs(p), min(i1.shape[j] + abs(p), o.shape[j])))
		else:
			i_slicer.append(slice(abs(p), min(i1.shape[j], o.shape[j] + abs(p))))
			o_slicer.append(slice(0,      min(i1.shape[j] - abs(p), o.shape[j])))

	o[o_slicer] = i1[i_slicer]
	header.set_offset(h1, header.get_offset(h2))
	
	save(o, sys.argv[3], h1)
Exemple #16
0
def main():
    parser = getParser()
    args = getArguments(parser)

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

    # loading input images
    img, hdr = load(args.input)
    img = img.astype(numpy.bool)

    # check spacing values
    if not len(args.spacing) == img.ndim:
        parser.error(
            'The image has {} dimensions, but {} spacing parameters have been supplied.'
            .format(img.ndim, len(args.spacing)))

    # check if output image exists
    if not args.force:
        if os.path.exists(args.output):
            parser.error('The output image {} already exists.'.format(
                args.output))

    logger.debug('target voxel spacing: {}'.format(args.spacing))

    # determine number of required complete slices for up-sampling
    vs = header.get_pixel_spacing(hdr)
    rcss = [
        int(y // x - 1) for x, y in zip(args.spacing, vs)
    ]  # TODO: For option b, remove the - 1; better: no option b, since I am rounding later anyway

    # remove negatives and round up to next even number
    rcss = [x if x > 0 else 0 for x in rcss]
    rcss = [x if 0 == x % 2 else x + 1 for x in rcss]
    logger.debug('intermediate slices to add per dimension: {}'.format(rcss))

    # for each dimension requiring up-sampling, from the highest down, perform shape based slice interpolation
    logger.info('Adding required slices using shape based interpolation.')
    for dim, rcs in enumerate(rcss):
        if rcs > 0:
            logger.debug(
                'adding {} intermediate slices to dimension {}'.format(
                    rcs, dim))
            img = shape_based_slice_interpolation(img, dim, rcs)
            logger.debug('resulting new image shape: {}'.format(img.shape))

    # compute and set new voxel spacing
    nvs = [x / (y + 1.) for x, y in zip(vs, rcss)]
    header.set_pixel_spacing(hdr, nvs)
    logger.debug('intermediate voxel spacing: {}'.format(nvs))

    # interpolate with nearest neighbour
    logger.info('Re-sampling the image with a b-spline order of {}.'.format(
        args.order))
    img, hdr = resample(img, hdr, args.spacing, args.order, mode='nearest')

    # saving the resulting image
    save(img, args.output, hdr, args.force)
def main():
    args = getArguments(getParser())

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # load input image
    data_input, header_input = load(args.input)
    
    logger.debug('Original shape = {}.'.format(data_input.shape))
    
    # check if supplied dimension parameters is inside the images dimensions
    if args.dimension1 >= data_input.ndim or args.dimension1 < 0:
        raise ArgumentError('The first swap-dimension {} exceeds the number of input volume dimensions {}.'.format(args.dimension1, data_input.ndim))
    elif args.dimension2 >= data_input.ndim or args.dimension2 < 0:
        raise ArgumentError('The second swap-dimension {} exceeds the number of input volume dimensions {}.'.format(args.dimension2, data_input.ndim))
    
    # swap axes
    data_output = scipy.swapaxes(data_input, args.dimension1, args.dimension2)
    # swap pixel spacing and offset
    ps = list(header.get_pixel_spacing(header_input))
    ps[args.dimension1], ps[args.dimension2] = ps[args.dimension2], ps[args.dimension1]
    header.set_pixel_spacing(header_input, ps)
    os = list(header.get_offset(header_input))
    os[args.dimension1], os[args.dimension2] = os[args.dimension2], os[args.dimension1]
    header.set_offset(header_input, os)
    
    logger.debug('Resulting shape = {}.'.format(data_output.shape))
    
    # save resulting volume
    save(data_output, args.output, header_input, args.force)
    
    logger.info("Successfully terminated.")    
Exemple #18
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 gradient might be 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)

    logger.debug('Input array: dtype={}, shape={}'.format(
        data_input.dtype, data_input.shape))

    # execute the gradient map filter
    logger.info('Applying gradient map filter...')
    data_output = filter.gradient_magnitude(
        data_input, header.get_pixel_spacing(header_input))

    logger.debug('Resulting array: dtype={}, shape={}'.format(
        data_output.dtype, data_output.shape))

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

    logger.info('Successfully terminated.')
Exemple #19
0
def main():
    args = getArguments(getParser())

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # load input image
    data_input, header_input = load(args.input)
    
    # transform to uin8
    data_input = data_input.astype(scipy.uint8)
                                      
    # reduce to 3D, if larger dimensionality
    if data_input.ndim > 3:
        for _ in range(data_input.ndim - 3): data_input = data_input[...,0]
        
    # iter over slices (2D) until first with content is detected
    for plane in data_input:
        if scipy.any(plane):
            # set pixel spacing
            spacing = list(header.get_pixel_spacing(header_input))
            spacing = spacing[1:3]
            __update_header_from_array_nibabel(header_input, plane)
            header.set_pixel_spacing(header_input, spacing)
            # save image
            save(plane, args.output, header_input, args.force)
            break
    
    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 gradient might be 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)
    
    logger.debug('Input array: dtype={}, shape={}'.format(data_input.dtype, data_input.shape))
    
    # execute the gradient map filter
    logger.info('Applying gradient map filter...')
    data_output = filter.gradient_magnitude(data_input, header.get_pixel_spacing(header_input))
        
    logger.debug('Resulting array: dtype={}, shape={}'.format(data_output.dtype, data_output.shape))
    
    # save image
    save(data_output, args.output, header_input, args.force)
    
    logger.info('Successfully terminated.')
def main():
    args = getArguments(getParser())

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

    # load input images and cast to bool
    images = []
    for input_ in args.inputs:
        t = load(input_)
        images.append((t[0], t[1]))

    # check if their shapes and voxel spacings are all equal
    s0 = images[0][0].shape
    if not numpy.all([i[0].shape == s0 for i in images[1:]]):
        raise argparse.ArgumentError(
            args.input,
            'At least one input image is of a different shape than the others.'
        )
    vs0 = header.get_pixel_spacing(images[0][1])
    if not numpy.all(
        [header.get_pixel_spacing(i[1]) == vs0 for i in images[1:]]):
        raise argparse.ArgumentError(
            args.input,
            'At least one input image has a different voxel spacing than the others.'
        )

    # execute operation
    logger.debug('Executing operation {} over {} images.'.format(
        args.operation, len(images)))
    if 'max' == args.operation:
        out = numpy.maximum.reduce([t[0] for t in images])
    elif 'min' == args.operation:
        out = numpy.minimum.reduce([t[0] for t in images])
    elif 'sum' == args.operation:
        out = numpy.sum([t[0] for t in images], 0).astype(numpy.uint8)
    else:  # avg
        out = numpy.average([t[0] for t in images], 0).astype(numpy.float32)

    # save output
    save(out, args.output, images[0][1], args.force)

    logger.info("Successfully terminated.")
Exemple #22
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)

    # load first input image as example
    example_data, example_header = load(args.inputs[0])

    # test if the supplied position is valid
    if args.position > example_data.ndim or args.position < 0:
        raise ArgumentError(
            'The supplied position for the new dimension is invalid. It has to be between 0 and {}.'
            .format(example_data.ndim))

    # prepare empty output volume
    output_data = scipy.zeros([len(args.inputs)] + list(example_data.shape),
                              dtype=example_data.dtype)

    # add first image to output volume
    output_data[0] = example_data

    # load input images and add to output volume
    for idx, image in enumerate(args.inputs[1:]):
        image_data, _ = load(image)
        if not args.ignore and image_data.dtype != example_data.dtype:
            raise ArgumentError(
                'The dtype {} of image {} differs from the one of the first image {}, which is {}.'
                .format(image_data.dtype, image, args.inputs[0],
                        example_data.dtype))
        if image_data.shape != example_data.shape:
            raise ArgumentError(
                'The shape {} of image {} differs from the one of the first image {}, which is {}.'
                .format(image_data.shape, image, args.inputs[0],
                        example_data.shape))
        output_data[idx + 1] = image_data

    # move new dimension to the end or to target position
    for dim in range(output_data.ndim - 1):
        if dim >= args.position: break
        output_data = scipy.swapaxes(output_data, dim, dim + 1)

    # set pixel spacing
    spacing = list(header.get_pixel_spacing(example_header))
    spacing = tuple(spacing[:args.position] + [args.spacing] +
                    spacing[args.position:])
    example_header.set_voxel_spacing(spacing)

    # save created volume
    save(output_data, args.output, example_header, 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)
    
    # load first input image as example 
    example_data, example_header = load(args.inputs[0])
    
    # test if the supplied position is valid
    if args.position > example_data.ndim or args.position < 0:
        raise ArgumentError('The supplied position for the new dimension is invalid. It has to be between 0 and {}.'.format(example_data.ndim))
    
    # prepare empty output volume
    output_data = scipy.zeros([len(args.inputs)] + list(example_data.shape), dtype=example_data.dtype)
    
    # add first image to output volume
    output_data[0] = example_data
    
    # load input images and add to output volume
    for idx, image in enumerate(args.inputs[1:]):
        image_data, _ = load(image)
        if not args.ignore and image_data.dtype != example_data.dtype:
            raise ArgumentError('The dtype {} of image {} differs from the one of the first image {}, which is {}.'.format(image_data.dtype, image, args.inputs[0], example_data.dtype))
        if image_data.shape != example_data.shape:
            raise ArgumentError('The shape {} of image {} differs from the one of the first image {}, which is {}.'.format(image_data.shape, image, args.inputs[0], example_data.shape))
        output_data[idx + 1] = image_data
        
    # move new dimension to the end or to target position
    for dim in range(output_data.ndim - 1):
        if dim >= args.position: break
        output_data = scipy.swapaxes(output_data, dim, dim + 1)
        
    # set pixel spacing
    spacing = list(header.get_pixel_spacing(example_header))
    spacing = tuple(spacing[:args.position] + [args.spacing] + spacing[args.position:])
    
    # !TODO: Find a way to enable this also for PyDicom and ITK images
    if __is_header_nibabel(example_header):
        __update_header_from_array_nibabel(example_header, output_data)
        header.set_pixel_spacing(example_header, spacing)
    else:
        raise ArgumentError("Sorry. Setting the voxel spacing of the new dimension only works with NIfTI images. See the description of this program for more details.")
    
    # save created volume
    save(output_data, args.output, example_header, args.force)
        
    logger.info("Successfully terminated.")
Exemple #24
0
def main():
    args = getArguments(getParser())

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # constants
    contour_dimension = 2
    
    # load input data
    input_data, input_header = load(args.input)
    
    # create output array
    new_shape = list(input_data.shape)
    new_shape[contour_dimension] = input_data.shape[contour_dimension] + (input_data.shape[contour_dimension] - 1) * args.enhancement
    output_data = scipy.zeros(new_shape, scipy.uint8)
    
    # prepare slicers
    slicer_from = [slice(None)] * input_data.ndim
    slicer_to = [slice(None)] * output_data.ndim
    
    logger.debug('Old shape = {}.'.format(input_data.shape))
    
    # copy data    
    for idx in range(input_data.shape[contour_dimension]):
        slicer_from[contour_dimension] = slice(idx, idx + 1)
        slicer_to[contour_dimension] = slice(idx * (args.enhancement + 1), idx * (args.enhancement + 1) + 1)
        
        output_data[slicer_to] = input_data[slicer_from]
        
    logger.debug('New shape = {}.'.format(output_data.shape))
    
    new_spacing = list(header.get_pixel_spacing(input_header))
    new_spacing[contour_dimension] = new_spacing[contour_dimension] / float(args.enhancement + 1)
    logger.debug('Setting pixel spacing from {} to {}....'.format(header.get_pixel_spacing(input_header), new_spacing))
    header.set_pixel_spacing(input_header, tuple(new_spacing))
    
    save(output_data, args.output, input_header, args.force)
def main():
    args = getArguments(getParser())

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

    # copy the example image or generate empty image, depending on the modus
    if args.example:
        grid_image = scipy.zeros(args.example_image.shape, scipy.bool_)
        grid_header = args.example_header
    else:
        grid_image = scipy.zeros(args.shape, scipy.bool_)
        # !TODO: Find another solution for this
        # Saving and loading image once to generate a valid header
        tmp_dir = tempfile.mkdtemp()
        tmp_image = '{}/{}'.format(tmp_dir, args.output.split('/')[-1])
        save(grid_image, tmp_image)
        _, grid_header = load(tmp_image)
        try:
            os.remove(tmp_image)
            os.rmdir(tmp_dir)
        except Exception:
            pass

    # set the image attributes if supplied
    if args.pixelspacing:
        header.set_pixel_spacing(grid_header, args.pixelspacing)
    if args.offset:
        header.set_offset(grid_header, args.offset)

    # compute the right grid spacing for each dimension
    if args.real:
        grid_spacing = [
            int(round(sp / float(ps))) for sp, ps in zip(
                args.spacing, header.get_pixel_spacing(grid_header))
        ]
    else:
        grid_spacing = args.spacing

    # paint the grid into the empty image volume
    for dim in range(grid_image.ndim):
        if 0 == grid_spacing[dim]:
            continue  # skip dimension of 0 grid spacing supplied
        for offset in range(0, grid_image.shape[dim], grid_spacing[dim]):
            slicer = [slice(None)] * grid_image.ndim
            slicer[dim] = slice(offset, offset + 1)
            grid_image[slicer] = True

    # saving resulting grid volume
    save(grid_image, args.output, grid_header, args.force)
Exemple #26
0
def main():
    parser = getParser()
    args = getArguments(parser)

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # loading input images
    img, hdr = load(args.input)
    img = img.astype(numpy.bool)
    
    # check spacing values
    if not len(args.spacing) == img.ndim:
        parser.error('The image has {} dimensions, but {} spacing parameters have been supplied.'.format(img.ndim, len(args.spacing)))
        
    # check if output image exists
    if not args.force:
        if os.path.exists(args.output):
            parser.error('The output image {} already exists.'.format(args.output)) 
        
    logger.debug('target voxel spacing: {}'.format(args.spacing))
    
    # determine number of required complete slices for up-sampling
    vs = header.get_pixel_spacing(hdr)
    rcss = [int(y // x - 1) for x, y in zip(args.spacing, vs)] # TODO: For option b, remove the - 1; better: no option b, since I am rounding later anyway
    
    # remove negatives and round up to next even number
    rcss = [x if x > 0 else 0 for x in rcss]
    rcss = [x if 0 == x % 2 else x + 1 for x in rcss]
    logger.debug('intermediate slices to add per dimension: {}'.format(rcss))
    
    # for each dimension requiring up-sampling, from the highest down, perform shape based slice interpolation
    logger.info('Adding required slices using shape based interpolation.')
    for dim, rcs in enumerate(rcss):
        if rcs > 0:
            logger.debug('adding {} intermediate slices to dimension {}'.format(rcs, dim))
            img = shape_based_slice_interpolation(img, dim, rcs)
            logger.debug('resulting new image shape: {}'.format(img.shape))
            
    # compute and set new voxel spacing
    nvs = [x / (y + 1.) for x, y in zip(vs, rcss)]
    header.set_pixel_spacing(hdr, nvs)
    logger.debug('intermediate voxel spacing: {}'.format(nvs))
    
    # interpolate with nearest neighbour
    logger.info('Re-sampling the image with a b-spline order of {}.'.format(args.order))
    img, hdr = resample(img, hdr, args.spacing, args.order, mode='nearest')
    
    # saving the resulting image
    save(img, args.output, hdr, args.force)
def main():
	thr = float(sys.argv[3])
	i, h = load(sys.argv[1])

	# adapt threshold by voxel spacing
	thr /= numpy.prod(header.get_pixel_spacing(h))
	# threshold binary objects
	j = size_threshold(i, thr, 'lt')
	# reset if last object has been removed
	if 0 == numpy.count_nonzero(j):
		j = i

	save(j, sys.argv[2], h, True)
def main():
    args = getArguments(getParser())

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    
    # load input images and cast to bool
    images = []
    for input_ in args.inputs:
        t = load(input_)
        images.append((t[0], t[1]))
    
    # check if their shapes and voxel spacings are all equal
    s0 = images[0][0].shape
    if not numpy.all(map(lambda i: i[0].shape == s0, images[1:])):
        raise argparse.ArgumentError(args.input, 'At least one input image is of a different shape than the others.')
    vs0 = header.get_pixel_spacing(images[0][1])
    if not numpy.all(map(lambda i: header.get_pixel_spacing(i[1]) == vs0, images[1:])):
        raise argparse.ArgumentError(args.input, 'At least one input image has a different voxel spacing than the others.')
    
    # execute operation
    logger.debug('Executing operation {} over {} images.'.format(args.operation, len(images)))
    if 'max' == args.operation:
        out = numpy.maximum.reduce([t[0] for t in images])
    elif 'min' == args.operation:
        out = numpy.minimum.reduce([t[0] for t in images])
    elif 'sum' == args.operation:
        out = numpy.sum([t[0] for t in images], 0).astype(numpy.uint8)
    else: # avg
        out = numpy.average([t[0] for t in images], 0).astype(numpy.float32)
        
    # save output
    save(out, args.output, images[0][1], args.force)
    
    logger.info("Successfully terminated.")    
Exemple #29
0
def extract_basal_slice(arr, head):
    """
    Takes a 3D array, iterates over the first dimension and returns the first 2D plane
    which contains any non-zero values as we as its voxel spacing.
    """
    for plane in arr:
        if scipy.any(plane):
            # get voxel spacing
            spacing = list(header.get_pixel_spacing(head))
            spacing = spacing[1:3]
            # return plane and spacing
            return (plane, spacing)

    raise ArgumentError('The supplied array does not contain any object.')
def extract_basal_slice(arr, head):
    """
    Takes a 3D array, iterates over the first dimension and returns the first 2D plane
    which contains any non-zero values as we as its voxel spacing.
    """
    for plane in arr:
        if scipy.any(plane):
            # get voxel spacing
            spacing = list(header.get_pixel_spacing(head))
            spacing = spacing[1:3]
            # return plane and spacing
            return (plane, spacing)
        
    raise ArgumentError('The supplied array does not contain any object.')
def main():
	# loading the image mask
	m = load(sys.argv[2])[0].astype(numpy.bool)

	# extracting the required features and saving them
	for sequence, function_call, function_arguments, voxelspacing in features_to_extract:
		if not isfv(sys.argv[3], sequence, function_call, function_arguments):
			#print sequence, function_call.__name__, function_arguments
			i, h = load('{}/{}.nii.gz'.format(sys.argv[1], sequence))
			call_arguments = list(function_arguments)
			if voxelspacing: call_arguments.append(header.get_pixel_spacing(h))
			call_arguments.append(m)
			fv = function_call(i, *call_arguments)
			savefv(fv, sys.argv[3], sequence, function_call, function_arguments)
Exemple #32
0
def zoom(image, factor, dimension, hdr=False, order=3):
    """
    Zooms the provided image by the supplied factor in the supplied dimension.
    The factor is an integer determining how many slices should be put between each
    existing pair.
    If an image header (hdr) is supplied, its voxel spacing gets updated.
    Returns the image and the updated header or false.
    """
    # check if supplied dimension is valid
    if dimension >= image.ndim:
        raise argparse.ArgumentError(
            'The supplied zoom-dimension {} exceeds the image dimensionality of 0 to {}.'
            .format(dimension, image.ndim - 1))

    # get logger
    logger = Logger.getInstance()

    logger.debug('Old shape = {}.'.format(image.shape))

    # perform the zoom
    zoom = [1] * image.ndim
    zoom[dimension] = (image.shape[dimension] +
                       (image.shape[dimension] - 1) * factor) / float(
                           image.shape[dimension])
    logger.debug('Reshaping with = {}.'.format(zoom))
    image = interpolation.zoom(image, zoom, order=order)

    logger.debug('New shape = {}.'.format(image.shape))

    if hdr:
        new_spacing = list(header.get_pixel_spacing(hdr))
        new_spacing[dimension] = new_spacing[dimension] / float(factor + 1)
        logger.debug('Setting pixel spacing from {} to {}....'.format(
            header.get_pixel_spacing(hdr), new_spacing))
        header.set_pixel_spacing(hdr, tuple(new_spacing))

    return image, hdr
def main():
	print 'lesion\tvolume (%)\tvolume (mm)'

	files = [f for f in os.listdir('{}'.format(sys.argv[1])) if os.path.isfile('{}/{}'.format(sys.argv[1], f))]
	for f in files:
		l, h = load('{}/{}'.format(sys.argv[1], f))
		m, _ = load('{}/{}'.format(sys.argv[2], f))

		lesion_voxel = numpy.count_nonzero(l)
		total_voxel = numpy.count_nonzero(m)

		volume_mm = numpy.prod(header.get_pixel_spacing(h)) * lesion_voxel
		volume_percentage = lesion_voxel / float(total_voxel)

		print '{}\t{}\t{}\t'.format(f[:-7], volume_percentage, volume_mm)
Exemple #34
0
def main():
    args = getArguments(getParser())

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # copy the example image or generate empty image, depending on the modus
    if args.example:
        grid_image = scipy.zeros(args.example_image.shape, scipy.bool_)
        grid_header = args.example_header
    else:
        grid_image = scipy.zeros(args.shape, scipy.bool_)
        # !TODO: Find another solution for this
        # Saving and loading image once to generate a valid header
        tmp_dir = tempfile.mkdtemp()
        tmp_image = '{}/{}'.format(tmp_dir, args.output.split('/')[-1])
        save(grid_image, tmp_image)
        _, grid_header = load(tmp_image)
        try:
            os.remove(tmp_image)
            os.rmdir(tmp_dir)
        except Exception:
            pass
        
    # set the image attributes if supplied
    if args.pixelspacing:
        header.set_pixel_spacing(grid_header, args.pixelspacing)
    if args.offset:
        header.set_offset(grid_header, args.offset)
    
    # compute the right grid spacing for each dimension
    if args.real:
        grid_spacing = [int(round(sp / float(ps))) for sp, ps in zip(args.spacing, header.get_pixel_spacing(grid_header))]
    else:
        grid_spacing = args.spacing
        
    # paint the grid into the empty image volume
    for dim in range(grid_image.ndim):
        if 0 == grid_spacing[dim]: continue # skip dimension of 0 grid spacing supplied
        for offset in range(0, grid_image.shape[dim], grid_spacing[dim]):
            slicer = [slice(None)] * grid_image.ndim
            slicer[dim] = slice(offset, offset + 1)
            grid_image[slicer] = True
            
    # saving resulting grid volume
    save(grid_image, args.output, grid_header, args.force)
def main():
    args = getArguments(getParser())

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

    # load input images
    data_fixed, header_fixed = load(args.fixed)
    data_moving, _ = load(args.moving)

    # get points of interest
    fixed_basep, fixed_otherp = get_points_of_interest(data_fixed)
    moving_basep, moving_otherp = get_points_of_interest(data_moving)

    # get voxel spacing
    spacing = header.get_pixel_spacing(header_fixed)

    # determine shift
    shift = (moving_basep[0] - fixed_basep[0],
             moving_basep[1] - fixed_basep[1])
    shift = (shift[0] * spacing[0], shift[1] * spacing[1])

    # determine angle
    angle = angle_between_lines(line_from_points(fixed_basep, fixed_otherp),
                                line_from_points(moving_basep, moving_otherp))

    # determine angle turn point
    turn_point = fixed_basep
    turn_point = (turn_point[0] * spacing[0], turn_point[1] * spacing[1])

    # print results
    print '//angle: {}'.format(math.degrees(angle))
    print transform_string(shift, angle, turn_point)

    # paint in the points and other stuff
    #data_input[tuple(fixed_basep)] = 2
    #data_input[tuple(fixed_otherp)] = 3

    # save image
    #save(data_input, args.output, header_input, args.force)

    logger.info("Successfully terminated.")
Exemple #36
0
def main():
	# loading the features to extract
	d, m = os.path.split(os.path.splitext(sys.argv[4])[0])
	f, filename, desc = imp.find_module(m, [d])
	features_to_extract = imp.load_module(m, f, filename, desc).features_to_extract

	# loading the image mask
	m = load(sys.argv[2])[0].astype(numpy.bool)

	# extracting the required features and saving them
	for sequence, function_call, function_arguments, voxelspacing in features_to_extract:
		if not isfv(sys.argv[3], sequence, function_call, function_arguments):
			#print sequence, function_call.__name__, function_arguments
			i, h = load('{}/{}.nii.gz'.format(sys.argv[1], sequence))
			call_arguments = list(function_arguments)
			if voxelspacing: call_arguments.append(header.get_pixel_spacing(h))
			call_arguments.append(m)
			fv = function_call(i, *call_arguments)
			savefv(fv, sys.argv[3], sequence, function_call, function_arguments)
def main():
    args = getArguments(getParser())

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # load input images
    data_fixed, header_fixed = load(args.fixed)
    data_moving, _ = load(args.moving)
    
    # get points of interest
    fixed_basep, fixed_otherp = get_points_of_interest(data_fixed)
    moving_basep, moving_otherp = get_points_of_interest(data_moving)
    
    # get voxel spacing
    spacing = header.get_pixel_spacing(header_fixed)
    
    # determine shift
    shift = (moving_basep[0] - fixed_basep[0], moving_basep[1] - fixed_basep[1])
    shift = (shift[0] * spacing[0], shift[1] * spacing[1])
    
    # determine angle
    angle = angle_between_lines(line_from_points(fixed_basep, fixed_otherp),
                                line_from_points(moving_basep, moving_otherp))
    
    # determine angle turn point
    turn_point = fixed_basep
    turn_point = (turn_point[0] * spacing[0], turn_point[1] * spacing[1])
    
    # print results
    print '//angle: {}'.format(math.degrees(angle))
    print transform_string(shift, angle, turn_point)
    
    # paint in the points and other stuff
    #data_input[tuple(fixed_basep)] = 2
    #data_input[tuple(fixed_otherp)] = 3
    
    # save image
    #save(data_input, args.output, header_input, args.force)
    
    logger.info("Successfully terminated.")
Exemple #38
0
def main():
    parser = getParser()
    args = getArguments(parser)

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

    # loading input images
    img, hdr = load(args.input)

    # check spacing values
    if not len(args.spacing) == img.ndim:
        parser.error(
            'The image has {} dimensions, but {} spacing parameters have been supplied.'
            .format(img.ndim, len(args.spacing)))

    # check if output image exists
    if not args.force:
        if os.path.exists(args.output):
            parser.error('The output image {} already exists.'.format(
                args.output))

    logger.debug('target voxel spacing: {}'.format(args.spacing))

    # compute zoom values
    zoom_factors = [
        old / float(new)
        for new, old in zip(args.spacing, header.get_pixel_spacing(hdr))
    ]
    logger.debug('zoom-factors: {}'.format(zoom_factors))

    # zoom image
    img = scipy.ndimage.interpolation.zoom(img, zoom_factors, order=args.order)
    logger.debug('new image shape: {}'.format(img.shape))

    # set new voxel spacing
    header.set_pixel_spacing(hdr, args.spacing)

    # saving the resulting image
    save(img, args.output, hdr, args.force)
def main():
    args = getArguments(getParser())

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

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

    logger.debug('Original shape = {}.'.format(data_input.shape))

    # check if supplied dimension parameters is inside the images dimensions
    if args.dimension1 >= data_input.ndim or args.dimension1 < 0:
        raise ArgumentError(
            'The first swap-dimension {} exceeds the number of input volume dimensions {}.'
            .format(args.dimension1, data_input.ndim))
    elif args.dimension2 >= data_input.ndim or args.dimension2 < 0:
        raise ArgumentError(
            'The second swap-dimension {} exceeds the number of input volume dimensions {}.'
            .format(args.dimension2, data_input.ndim))

    # swap axes
    data_output = scipy.swapaxes(data_input, args.dimension1, args.dimension2)
    # swap pixel spacing and offset
    ps = list(header.get_pixel_spacing(header_input))
    ps[args.dimension1], ps[args.dimension2] = ps[args.dimension2], ps[
        args.dimension1]
    header.set_pixel_spacing(header_input, ps)
    os = list(header.get_offset(header_input))
    os[args.dimension1], os[args.dimension2] = os[args.dimension2], os[
        args.dimension1]
    header.set_offset(header_input, os)

    logger.debug('Resulting shape = {}.'.format(data_output.shape))

    # save resulting volume
    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)

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

    # check if the supplied dimension is valid
    if args.dimension >= data_input.ndim or args.dimension < 0:
        raise ArgumentError(
            'The supplied cut-dimension {} exceeds the image dimensionality of 0 to {}.'
            .format(args.dimension, data_input.ndim - 1))

    # prepare output file string
    name_output = args.output.replace('{}', '{:03d}')

    # compute the new the voxel spacing
    spacing = list(header.get_pixel_spacing(header_input))
    del spacing[args.dimension]

    # iterate over the cut dimension
    slices = data_input.ndim * [slice(None)]
    for idx in range(data_input.shape[args.dimension]):
        # cut the current slice from the original image
        slices[args.dimension] = slice(idx, idx + 1)
        data_output = scipy.squeeze(data_input[slices])
        # update the header and set the voxel spacing
        __update_header_from_array_nibabel(header_input, data_output)
        header.set_pixel_spacing(header_input, spacing)
        # save current slice
        save(data_output, name_output.format(idx), header_input, args.force)

    logger.info("Successfully terminated.")
Exemple #41
0
def _postprocess(src, dest, threshold):
    r"""
    Execute post-processing on a segmentation.
    """
    # load source image
    img, hdr = load(src)
    img = img.astype(numpy.bool)
    
    # fill holes in 3D
    img = binary_fill_holes(img)
    # adapt threshold by voxel spacing
    threshold /= numpy.prod(header.get_pixel_spacing(hdr))
    # threshold binary objects
    out = size_threshold(img, threshold, 'lt')
    # reset if last object has been removed
    if 0 == numpy.count_nonzero(out):
        out = img
    # fill holes in 2d
    out = _fill2d(out)
    
    # save
    save(out, dest, hdr, True)
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 input image
    data_input, header_input = load(args.input)
    
    # check if the supplied dimension is valid
    if args.dimension >= data_input.ndim or args.dimension < 0:
        raise ArgumentError('The supplied cut-dimension {} exceeds the image dimensionality of 0 to {}.'.format(args.dimension, data_input.ndim - 1))
    
    # prepare output file string
    name_output = args.output.replace('{}', '{:03d}')
    
    # compute the new the voxel spacing
    spacing = list(header.get_pixel_spacing(header_input))
    del spacing[args.dimension]
    
    # iterate over the cut dimension
    slices = data_input.ndim * [slice(None)]
    for idx in range(data_input.shape[args.dimension]):
        # cut the current slice from the original image 
        slices[args.dimension] = slice(idx, idx + 1)
        data_output = scipy.squeeze(data_input[slices])
        # update the header and set the voxel spacing
        __update_header_from_array_nibabel(header_input, data_output)
        header.set_pixel_spacing(header_input, spacing)
        # save current slice
        save(data_output, name_output.format(idx), header_input, args.force)
        
    logger.info("Successfully terminated.")
Exemple #43
0
def main():
    parser = getParser()
    args = getArguments(parser)

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # loading input images
    img, hdr = load(args.input)

    # check spacing values
    if not len(args.spacing) == img.ndim:
        parser.error('The image has {} dimensions, but {} spacing parameters have been supplied.'.format(img.ndim, len(args.spacing)))
        
    # check if output image exists
    if not args.force:
        if os.path.exists(args.output):
            parser.error('The output image {} already exists.'.format(args.output)) 
        
    logger.debug('target voxel spacing: {}'.format(args.spacing))

    # compute zoom values
    zoom_factors = [old / float(new) for new, old in zip(args.spacing, header.get_pixel_spacing(hdr))]
    logger.debug('zoom-factors: {}'.format(zoom_factors))

    # zoom image
    img = scipy.ndimage.interpolation.zoom(img, zoom_factors, order=args.order)
    logger.debug('new image shape: {}'.format(img.shape))

    # set new voxel spacing
    header.set_pixel_spacing(hdr, args.spacing)

    # saving the resulting image
    save(img, args.output, hdr, args.force)
Exemple #44
0
def main(interest_list, train_only, proportion, save_name):
    if train_only == False:
        train_indicator = [False, True]
    else:
        train_indicator = [True]

    for indicator in train_indicator:
        isTrain = indicator

        if isTrain == True:
            datadir_to_load = '../input/submission/pred_result/train/'
            data_name = 'train'
            datadir_to_save = '../input/submission/pred_result_ensemble/train/'
        else:
            datadir_to_load = '../input/submission/pred_result/test/'
            data_name = 'test'
            datadir_to_save = '../input/submission/pred_result_ensemble/test/'

        if os.path.isdir(datadir_to_load) is not True:
            raise
        if os.path.isdir(datadir_to_save) is not True:
            os.makedirs(datadir_to_save)

        file_list = []
        interest_model_list = list(interest_list)
        for model_num in interest_model_list:
            file_list = file_list + glob(
                os.path.join(datadir_to_load,
                             '*model_{}*.nii'.format(model_num)))
        file_dict = dict()
        for file in file_list:
            name = str.split(file, '.')[-2]
            if name in file_dict.keys():
                file_dict[name].append(file)
            else:
                file_dict[name] = []
                file_dict[name].append(file)

        record = []
        for name in file_dict.keys():
            N = len(file_dict[name])
            img_list = []
            #NEED CHANGE !!!
            if isTrain == True:
                file_path = glob(
                    '../input/train_data/*/*/*{}*'.format(name))[0]
            else:
                file_path = glob('../input/test_data/*/*/*{}*'.format(name))[0]
            mtt, mtt_header = load(file_path)
            adc_path = glob('/'.join(str.split(file_path, '/')[:4]) +
                            '/*/*ADC*.nii')[0]
            _, adc_header = load(adc_path)
            # print('name: {}, number of images: {}'.format(name, N))

            for j in xrange(N):
                img, img_header = load(file_dict[name][j])
                if header.get_pixel_spacing(
                        adc_header) != header.get_pixel_spacing(img_header):
                    print("ERROR!!!!")
                if header.get_offset(adc_header) != header.get_offset(
                        img_header):
                    print("ERROR!!!!")
                if mtt.shape != img.shape:
                    print("ERROR!!!!")
                img_list.append(img)

            arr = np.sum(np.array(img_list), axis=0)
            arr = np.array(arr > N * proportion, dtype=np.uint16)
            arr_name = datadir_to_save + 'VSD.yong_{}_{}.'.format(
                save_name, data_name) + name + '.nii'
            # print('proportion of GT: {}, dimension: {}'.format(np.mean(arr), arr.shape))
            save(arr, arr_name, adc_header)

            if isTrain == True:
                gt_path = glob('../input/train_data/{}/*/*OT*'.format(
                    str.split(file_path, '/')[-3]))[0]
                gt, gt_header = load(gt_path)
                f1 = 2.0 * np.sum(gt * arr) / (np.sum(gt) + np.sum(arr))
                record.append(f1)

        if isTrain == True:
            record = np.array(record)
            print(record)
            print(np.mean(record))
            print(np.std(record))
def __get_diagonal(h):
	return numpy.diag(list(header.get_pixel_spacing(h)) + [1])
Exemple #46
0
# Manually segmented fake lesion for use with this example

image_file = 'data/manualTest.nii.gz'
image_data, image_header = load(image_file)

# Provide the coordenates or calculate the bounding box of the segmentation
coords2crop = [0,10,0,10,0,10] # You can do manual coordenates
coords2crop = recrop.bbox_3D(image_data) # Or calculated by a boundary box
print coords2crop

# Crop the image using the provided coordinates
croppedImage = recrop.crop_3D(image_data, coords2crop)

# Print the pixel spacing
print header.get_pixel_spacing(image_header)

targetSpacing = 2.0
targetSpacing = [2,1,1]

# Resample from 
croppedResampledImage, croppedResampledImage_header = recrop.resample(croppedImage, image_header,targetSpacing)




save(croppedImage, image_file[0:-7]+'.bbox.nii.gz', image_header)
save(croppedResampledImage, image_file[0:-7]+'.bboxResample.nii.gz', croppedResampledImage_header)
print 'Original:'
print croppedImage.shape
print 'Resampled:'
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
    if not args.force:
        if os.path.exists(args.output):
            logger.warning('The output image {} already exists. Exiting.'.format(args.output))
            exit(-1)
            
    # select boundary term
    ['diff_linear', 'diff_exp', 'diff_div', 'diff_pow', 'max_linear', 'max_exp', 'max_div', 'max_pow']
    if 'diff_linear' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_difference_linear
        logger.info('Selected boundary term: linear difference of intensities')
    elif 'diff_exp' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_difference_exponential
        logger.info('Selected boundary term: exponential difference of intensities')
    elif 'diff_div' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_difference_division
        logger.info('Selected boundary term: divided difference of intensities')
    elif 'diff_pow' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_difference_power
        logger.info('Selected boundary term: power based / raised difference of intensities')
    elif 'max_linear' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_maximum_linear
        logger.info('Selected boundary term: linear maximum of intensities')
    elif 'max_exp' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_maximum_exponential
        logger.info('Selected boundary term: exponential maximum of intensities')
    elif 'max_div' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_maximum_division
        logger.info('Selected boundary term: divided maximum of intensities')
    elif 'max_pow' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_maximum_power
        logger.info('Selected boundary term: power based / raised maximum of intensities')

    # load input images
    badditional_image_data, reference_header = load(args.badditional)
    markers_image_data, _ = load(args.markers)
    
    # split marker image into fg and bg images
    fgmarkers_image_data, bgmarkers_image_data = split_marker(markers_image_data)
       
    # check if all images dimensions are the same
    if not (badditional_image_data.shape == fgmarkers_image_data.shape == bgmarkers_image_data.shape):
        logger.critical('Not all of the supplied images are of the same shape.')
        raise ArgumentError('Not all of the supplied images are of the same shape.')

    # extract spacing if required
    if args.spacing:
        spacing = header.get_pixel_spacing(reference_header)
        logger.info('Taking spacing of {} into account.'.format(spacing))
    else:
        spacing = False

    # generate graph
    logger.info('Preparing BK_MFMC C++ graph...')
    gcgraph = graphcut.graph_from_voxels(fgmarkers_image_data,
                                         bgmarkers_image_data,
                                         boundary_term = boundary_term,
                                         boundary_term_args = (badditional_image_data, args.sigma, spacing))
    
    # execute min-cut
    logger.info('Executing min-cut...')
    maxflow = gcgraph.maxflow()
    logger.debug('Maxflow is {}'.format(maxflow))
    
    # reshape results to form a valid mask
    logger.info('Applying results...')
    result_image_data = scipy.zeros(bgmarkers_image_data.size, dtype=scipy.bool_)
    for idx in range(len(result_image_data)):
        result_image_data[idx] = 0 if gcgraph.termtype.SINK == gcgraph.what_segment(idx) else 1    
    result_image_data = result_image_data.reshape(bgmarkers_image_data.shape)
    
    # save resulting mask    
    save(result_image_data.astype(scipy.bool_), args.output, reference_header, args.force)

    logger.info('Successfully terminated.')
Exemple #48
0
def main():
    args = getArguments(getParser())

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

    # load input images
    data_fixed, header_fixed = load(args.fixed)
    data_moving, header_moving = load(args.moving)

    # convert to binary arrays
    data_fixed = data_fixed.astype(scipy.bool_)
    data_moving = data_moving.astype(scipy.bool_)

    # check that they are 3D volumes and contain an object
    if not 3 == data_fixed.ndim:
        raise ArgumentError(
            'The fixed image has {} instead of the expected 3 dimensions.'.
            format(data_fixed.ndim))
    if not 3 == data_moving.ndim:
        raise ArgumentError(
            'The moving image has {} instead of the expected 3 dimensions.'.
            format(data_moving.ndim))
    if not scipy.any(data_fixed):
        raise ArgumentError('The fixed image contains no binary object.')
    if not scipy.any(data_moving):
        raise ArgumentError('The moving image contains no binary object.')

    # get voxel spacing of fixed image
    fixed_spacing = header.get_pixel_spacing(header_fixed)

    # extract the first basal slices form both RV objects
    basal_fixed, basal_fixed_spacing = extract_basal_slice(
        data_fixed, header_fixed)
    basal_moving, basal_moving_spacing = extract_basal_slice(
        data_moving, header_moving)
    logger.debug(
        'Extracted basal slices fixed: {} and moving: {} with voxel spacing {} resp. {}.'
        .format(basal_fixed.shape, basal_moving.shape, basal_fixed_spacing,
                basal_moving_spacing))

    # get points of interest
    fixed_basep, fixed_otherp = get_points_of_interest(basal_fixed)
    moving_basep, moving_otherp = get_points_of_interest(basal_moving)
    logger.debug(
        'Points of interest found are fixed: {} / {} and moving: {} / {}.'.
        format(fixed_basep, fixed_otherp, moving_basep, moving_otherp))

    # translate all points of interest to physical coordinate system
    fixed_basep = [x * y for x, y in zip(fixed_basep, basal_fixed_spacing)]
    fixed_otherp = [x * y for x, y in zip(fixed_otherp, basal_fixed_spacing)]
    moving_basep = [x * y for x, y in zip(moving_basep, basal_moving_spacing)]
    moving_otherp = [
        x * y for x, y in zip(moving_otherp, basal_moving_spacing)
    ]
    logger.debug(
        'Points of interest translated to real-world coordinates are fixed: {} / {} and moving: {} / {}.'
        .format(fixed_basep, fixed_otherp, moving_basep, moving_otherp))

    # determine shift to unite the two base-points
    shift = (fixed_basep[0] - moving_basep[0],
             fixed_basep[1] - moving_basep[1])
    logger.debug('Shift to unite base-point is {}.'.format(shift))

    # shift the vector end-point of the moving object's vector so that it shares the
    # same base as the fixed vector
    moving_otherp = shiftp(moving_otherp, shift)
    logger.debug('Shifted vector end-point of moving image is {}.'.format(
        moving_otherp))

    # assure correctness of shift
    if not scipy.all(
        [x == y for x, y in zip(fixed_basep, shiftp(moving_basep, shift))]):
        raise ArgumentError(
            'Aligning base-point through shifting failed due to unknown reason: {} does not equal {}.'
            .format(shiftp(moving_basep, shift), fixed_basep))

    # shift both vector end-points to origin base
    fixed_otherp = shiftp(fixed_otherp, map(lambda x: -1. * x, fixed_basep))
    moving_otherp = shiftp(moving_otherp, map(lambda x: -1. * x, fixed_basep))

    # determine angle
    angle = angle_between_vectors(fixed_otherp, moving_otherp)
    logger.debug('Angle set to {} degree in radians.'.format(
        math.degrees(angle)))

    # determine angle turn point
    turn_point = fixed_basep
    logger.debug(
        'Turn point set to {} in real-world coordinates.'.format(turn_point))

    # reverse shift to fit into the 'elastix' view
    shift = [-1. * x for x in shift]

    # print results
    print '// {}'.format(math.degrees(angle))
    print """
//# SOME NOTES ON 'ELASTIX'
//# 1. 'elastix' performs shifting before rotation!
//# 2. 'elastix' works on the real world coordinates (i.e. with voxel spacing of 0)
"""
    print transform_string(data_fixed.shape, fixed_spacing, [0] + list(shift),
                           [angle, 0, 0], [0] + list(turn_point))

    logger.info("Successfully terminated.")
def main():
    args = getArguments(getParser())
    
    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # load input images
    data_fixed, header_fixed = load(args.fixed)
    data_moving, header_moving = load(args.moving)
    
    # convert to binary arrays
    data_fixed = data_fixed.astype(scipy.bool_)
    data_moving = data_moving.astype(scipy.bool_)
    
    # check that they are 3D volumes and contain an object
    if not 3 == data_fixed.ndim: raise ArgumentError('The fixed image has {} instead of the expected 3 dimensions.'.format(data_fixed.ndim))
    if not 3 == data_moving.ndim: raise ArgumentError('The moving image has {} instead of the expected 3 dimensions.'.format(data_moving.ndim))
    if not scipy.any(data_fixed): raise ArgumentError('The fixed image contains no binary object.')
    if not scipy.any(data_moving): raise ArgumentError('The moving image contains no binary object.')
    
    # get voxel spacing of fixed image
    fixed_spacing = header.get_pixel_spacing(header_fixed)
    
    # extract the first basal slices form both RV objects
    basal_fixed, basal_fixed_spacing = extract_basal_slice(data_fixed, header_fixed)
    basal_moving, basal_moving_spacing = extract_basal_slice(data_moving, header_moving)
    logger.debug('Extracted basal slices fixed: {} and moving: {} with voxel spacing {} resp. {}.'.format(basal_fixed.shape, basal_moving.shape, basal_fixed_spacing, basal_moving_spacing))
    
    # get points of interest
    fixed_basep, fixed_otherp = get_points_of_interest(basal_fixed)
    moving_basep, moving_otherp = get_points_of_interest(basal_moving)
    logger.debug('Points of interest found are fixed: {} / {} and moving: {} / {}.'.format(fixed_basep, fixed_otherp, moving_basep, moving_otherp))
    
    # translate all points of interest to physical coordinate system
    fixed_basep = [x * y for x, y in zip(fixed_basep, basal_fixed_spacing)]
    fixed_otherp = [x * y for x, y in zip(fixed_otherp, basal_fixed_spacing)]
    moving_basep = [x * y for x, y in zip(moving_basep, basal_moving_spacing)]
    moving_otherp = [x * y for x, y in zip(moving_otherp, basal_moving_spacing)]
    logger.debug('Points of interest translated to real-world coordinates are fixed: {} / {} and moving: {} / {}.'.format(fixed_basep, fixed_otherp, moving_basep, moving_otherp))
    
    # determine shift to unite the two base-points
    shift = (fixed_basep[0] - moving_basep[0], fixed_basep[1] - moving_basep[1])
    logger.debug('Shift to unite base-point is {}.'.format(shift))
    
    # shift the vector end-point of the moving object's vector so that it shares the
    # same base as the fixed vector
    moving_otherp = shiftp(moving_otherp, shift)
    logger.debug('Shifted vector end-point of moving image is {}.'.format(moving_otherp))
    
    # assure correctness of shift
    if not scipy.all([x == y for x, y in zip(fixed_basep, shiftp(moving_basep, shift))]):
        raise ArgumentError('Aligning base-point through shifting failed due to unknown reason: {} does not equal {}.'.format(shiftp(moving_basep, shift), fixed_basep))
    
    # shift both vector end-points to origin base
    fixed_otherp = shiftp(fixed_otherp, map(lambda x: -1. * x, fixed_basep))
    moving_otherp = shiftp(moving_otherp, map(lambda x: -1. * x, fixed_basep))
    
    # determine angle
    angle = angle_between_vectors(fixed_otherp, moving_otherp)
    logger.debug('Angle set to {} degree in radians.'.format(math.degrees(angle)))
    
    # determine angle turn point
    turn_point = fixed_basep
    logger.debug('Turn point set to {} in real-world coordinates.'.format(turn_point))
    
    # reverse shift to fit into the 'elastix' view
    shift = [-1. * x for x in shift]
    
    # print results
    print '// {}'.format(math.degrees(angle))
    print """
//# SOME NOTES ON 'ELASTIX'
//# 1. 'elastix' performs shifting before rotation!
//# 2. 'elastix' works on the real world coordinates (i.e. with voxel spacing of 0)
"""
    print transform_string(data_fixed.shape,
                           fixed_spacing,
                           [0] + list(shift),
                           [angle, 0, 0],
                           [0] + list(turn_point))
    
    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
    if not args.force:
        if os.path.exists(args.output):
            logger.warning('The output image {} already exists. Exiting.'.format(args.output))
            exit(-1)
            
    # select boundary term
    ['diff_linear', 'diff_exp', 'diff_div', 'diff_pow', 'max_linear', 'max_exp', 'max_div', 'max_pow']
    if 'diff_linear' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_difference_linear
        logger.info('Selected boundary term: linear difference of intensities')
    elif 'diff_exp' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_difference_exponential
        logger.info('Selected boundary term: exponential difference of intensities')
    elif 'diff_div' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_difference_division
        logger.info('Selected boundary term: divided difference of intensities')
    elif 'diff_pow' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_difference_power
        logger.info('Selected boundary term: power based / raised difference of intensities')
    elif 'max_linear' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_maximum_linear
        logger.info('Selected boundary term: linear maximum of intensities')
    elif 'max_exp' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_maximum_exponential
        logger.info('Selected boundary term: exponential maximum of intensities')
    elif 'max_div' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_maximum_division
        logger.info('Selected boundary term: divided maximum of intensities')
    elif 'max_pow' == args.boundary:
        boundary_term = graphcut.energy_voxel.boundary_maximum_power
        logger.info('Selected boundary term: power based / raised maximum of intensities')

    # load input images
    badditional_image_data, reference_header = load(args.badditional)
    markers_image_data, _ = load(args.markers)
    
    # split marker image into fg and bg images
    fgmarkers_image_data, bgmarkers_image_data = split_marker(markers_image_data)
       
    # check if all images dimensions are the same
    if not (badditional_image_data.shape == fgmarkers_image_data.shape == bgmarkers_image_data.shape):
        logger.critical('Not all of the supplied images are of the same shape.')
        raise ArgumentError('Not all of the supplied images are of the same shape.')

    # extract spacing if required
    if args.spacing:
        spacing = header.get_pixel_spacing(reference_header)
        logger.info('Taking spacing of {} into account.'.format(spacing))
    else:
        spacing = False

    # generate graph
    logger.info('Preparing BK_MFMC C++ graph...')
    gcgraph = graphcut.graph_from_voxels(fgmarkers_image_data,
                                         bgmarkers_image_data,
                                         boundary_term = boundary_term,
                                         boundary_term_args = (badditional_image_data, args.sigma, spacing))
    
    # execute min-cut
    logger.info('Executing min-cut...')
    maxflow = gcgraph.maxflow()
    logger.debug('Maxflow is {}'.format(maxflow))
    
    # reshape results to form a valid mask
    logger.info('Applying results...')
    result_image_data = scipy.zeros(bgmarkers_image_data.size, dtype=scipy.bool_)
    for idx in range(len(result_image_data)):
        result_image_data[idx] = 0 if gcgraph.termtype.SINK == gcgraph.what_segment(idx) else 1    
    result_image_data = result_image_data.reshape(bgmarkers_image_data.shape)
    
    # save resulting mask    
    save(result_image_data.astype(scipy.bool_), args.output, reference_header, args.force)

    logger.info('Successfully terminated.')
def main():
    args = getArguments(getParser())

    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # constants
    dimension_spatial = 0
    dimension_temporal = 3
    name_output_data = '{}/{}_d{:01d}_s{:04d}.nii' # basename / slice-dimension / slice-number
    name_output_marker = '{}/m{}_d{:01d}_s{:04d}.nii' # basename / slice-dimension / slice-number
    
    # load input image
    input_data, input_header = load(args.input)
    
    # determine type of extraction and eventuelly load contour file
    if args.paintc or args.type in ['es']:
        contour_data, _ = load(args.contour)
    
    # select dimension and set variable parameter
    if args.type in ['ed', 'es', 'spatial']: cut_dimension = dimension_temporal
    else: cut_dimension = dimension_spatial
    basename = '.'.join(os.path.basename(args.input).split('.')[:-1])
    
    # adjust voxel spacing
    voxel_spacing = list(header.get_pixel_spacing(input_header))
    del voxel_spacing[cut_dimension]
    voxel_spacing += [0]
    header.set_pixel_spacing(input_header, voxel_spacing)
    
    # split and save images
    first = True
    slices = input_data.ndim * [slice(None)]
    for idx in range(input_data.shape[cut_dimension]):
        slices[cut_dimension] = slice(idx, idx + 1)
        
        # skip if output image already exists
        if not args.force and os.path.exists(name_output_data.format(args.output, basename, cut_dimension, idx)):
            logger.warning('The output image {} already exists, skipping this step.'.format(name_output_data.format(args.output, basename, cut_dimension, idx)))
            continue
        elif not args.force and os.path.exists(name_output_marker.format(args.output, basename, cut_dimension, idx)):
            logger.warning('The output marker image {} already exists, skipping this step.'.format(name_output_marker.format(args.output, basename, cut_dimension, idx)))
            continue
        
        # extract original sub-volume
        data_output = scipy.squeeze(input_data[slices])
        
        # create same-sized empty volume as marker base
        data_marker = scipy.zeros(data_output.shape, scipy.uint8)
        
        # extract also contour sub-volume if required
        if args.paintc:
            data_marker += scipy.squeeze(contour_data[slices])
            
        # check if contour data is empty in ed and es case; if yes, skip this volume
        if args.type in ['es'] and 0 == len(scipy.squeeze(contour_data[slices]).nonzero()[0]):
            continue
        
        # check if first volume in case of type = es, then skip
        if 'es' == args.type and first:
            first = False
            continue
        
        # save data and marker sub-volumes
        save(data_output, name_output_data.format(args.output, basename, cut_dimension, idx), input_header, args.force)
        save(data_marker, name_output_marker.format(args.output, basename, cut_dimension, idx), input_header, args.force)
        
        # in case of type = ed, break after first
        if 'ed' == args.type: break
        
    logger.info("Successfully terminated.")