def test_slice_from_3d(): # Resample a 3d image, returning a zslice, yslice and xslice # # This example creates a coordmap that coincides with # a given z, y, or x slice of an image, and checks that # resampling agrees with the data in the given slice. shape = (100,90,80) g = AffineTransform.from_params('ijk', 'xyz', np.diag([0.5,0.5,0.5,1])) img = Image(np.ones(shape), g) img.get_data()[50:55,40:55,30:33] = 3 I = np.identity(4) zsl = slices.zslice(26, ((0,49.5), 100), ((0,44.5), 90), img.reference) ir = resample(img, zsl, I, (100, 90)) assert_array_almost_equal(ir.get_data(), img[:,:,53].get_data()) ysl = slices.yslice(22, ((0,49.5), 100), ((0,39.5), 80), img.reference) ir = resample(img, ysl, I, (100, 80)) assert_array_almost_equal(ir.get_data(), img[:,45,:].get_data()) xsl = slices.xslice(15.5, ((0,44.5), 90), ((0,39.5), 80), img.reference) ir = resample(img, xsl, I, (90, 80)) assert_array_almost_equal(ir.get_data(), img[32,:,:].get_data())
def test_resample_outvalue(): # Test resampling with different modes, constant values, datatypes, orders def func(xyz): return xyz + np.asarray([1, 0, 0]) coordmap = vox2mni(np.eye(4)) arr = np.arange(3 * 3 * 3).reshape(3, 3, 3) aff = np.eye(4) aff[0, 3] = 1. # x translation for mapping, dt, order in product( [aff, func], [np.int8, np.intp, np.int32, np.int64, np.float32, np.float64], [0, 1, 3]): img = Image(arr.astype(dt), coordmap) # Test constant value of 0 img2 = resample(img, coordmap, mapping, img.shape, order=order, mode='constant', cval=0.) exp_arr = np.zeros(arr.shape) exp_arr[:-1, :, :] = arr[1:, :, :] assert_array_almost_equal(img2.get_data(), exp_arr) # Test constant value of 1 img2 = resample(img, coordmap, mapping, img.shape, order=order, mode='constant', cval=1.) exp_arr[-1, :, :] = 1 assert_array_almost_equal(img2.get_data(), exp_arr) # Test nearest neighbor img2 = resample(img, coordmap, mapping, img.shape, order=order, mode='nearest') exp_arr[-1, :, :] = arr[-1, :, :] assert_array_almost_equal(img2.get_data(), exp_arr) # Test img2img target_coordmap = vox2mni(aff) target = Image(arr, target_coordmap) img2 = resample_img2img(img, target, 3, 'nearest') assert_array_almost_equal(img2.get_data(), exp_arr) img2 = resample_img2img(img, target, 3, 'constant', cval=1.) exp_arr[-1, :, :] = 1 assert_array_almost_equal(img2.get_data(), exp_arr)
def test_nonaffine(): # resamples an image along a curve through the image. # # FIXME: use the reference.evaluate.Grid to perform this nicer # FIXME: Remove pylab references def curve(x): # function accept N by 1, returns N by 2 return np.vstack([5 * np.sin(x.T), 5 * np.cos(x.T)]).T + [52, 47] for names in (("xy", "ij", "t", "u"), ("ij", "xy", "t", "s")): in_names, out_names, tin_names, tout_names = names g = AffineTransform.from_params(in_names, out_names, np.identity(3)) img = Image(np.ones((100, 90)), g) img[50:55, 40:55] = 3.0 tcoordmap = AffineTransform.from_start_step(tin_names, tout_names, [0], [np.pi * 1.8 / 100]) ir = resample(img, tcoordmap, curve, (100,)) if gui_review: import pylab pylab.figure(num=3) pylab.imshow(img, interpolation="nearest") d = curve(np.linspace(0, 1.8 * np.pi, 100)) pylab.plot(d[0], d[1]) pylab.gca().set_ylim([0, 99]) pylab.gca().set_xlim([0, 89]) pylab.figure(num=4) pylab.plot(np.asarray(ir))
def resamp(nipy_img, onto_aff, onto_shape, order=3, cval=-1, w2wmap=None, debug=0): """ utility function to resample an image input: nipy image onto affine onto shape order : scipy resample interpolation order cval: value outside when resampling to bigger box """ arraycoo = 'ijklmnopq'[:len(onto_shape)] spacecoo = 'xyztrsuvw'[:len(onto_shape)] if debug: print('\narraycoo: ', arraycoo, '\nspacecoo: ', spacecoo, '\nonto_aff\n', onto_aff) dmaker = CoordSysMaker(arraycoo, 'generic-array') rmaker = CoordSysMaker(spacecoo, 'generic-scanner') cm_maker = cmap.CoordMapMaker(dmaker, rmaker) cmap_out = cm_maker.make_affine(onto_aff) if debug: print('cmap_out:\n',cmap_out) if w2wmap == None: w2wmap = np.eye(onto_aff.shape[0]) if debug: print('w2wmap:\n',w2wmap) return resample(nipy_img, cmap_out, w2wmap, onto_shape, order=order, cval=cval)
def test_nonaffine(): # resamples an image along a curve through the image. # # FIXME: use the reference.evaluate.Grid to perform this nicer # FIXME: Remove pylab references def curve(x): # function accept N by 1, returns N by 2 return (np.vstack([5 * np.sin(x.T), 5 * np.cos(x.T)]).T + [52, 47]) for names in (('xy', 'ij', 't', 'u'), ('ij', 'xy', 't', 's')): in_names, out_names, tin_names, tout_names = names g = AffineTransform.from_params(in_names, out_names, np.identity(3)) img = Image(np.ones((100, 90)), g) img.get_data()[50:55, 40:55] = 3. tcoordmap = AffineTransform.from_start_step(tin_names, tout_names, [0], [np.pi * 1.8 / 100]) ir = resample(img, tcoordmap, curve, (100, )) if gui_review: import pylab pylab.figure(num=3) pylab.imshow(img, interpolation='nearest') d = curve(np.linspace(0, 1.8 * np.pi, 100)) pylab.plot(d[0], d[1]) pylab.gca().set_ylim([0, 99]) pylab.gca().set_xlim([0, 89]) pylab.figure(num=4) pylab.plot(ir.get_data())
def resample_image(source_file, target_file, outdir, w2wmap=None, order=3, cval=0, verbose=0): """ Resample the source image to match the target image using Nipy. Parameters ---------- source_file: str (mandatory) the image to resample. target_file: str (mandatory) the reference image. outdir: str (mandatory) the folder where the resampled image will be saved. w2wmap: array (4, 4) or callable physical to physical transformation. verbose: int (optional, default 0) the verbosity level. Returns ------- resampled_file: str the resampled image. """ # Get target image information target_image = nipy.load_image(target_file) onto_shape = target_image.shape[:3] onto_aff = xyz_affine(target_image.affine, xyz=[0, 1, 2], verbose=verbose) # Define index and physical coordinate systems arraycoo = "ijklmnopq"[:len(onto_shape)] spacecoo = "xyztrsuvw"[:len(onto_shape)] if verbose > 0: print("\narraycoo: ", arraycoo, "\nspacecoo: ", spacecoo, "\nonto_aff\n", onto_aff) dmaker = CoordSysMaker(arraycoo, 'generic-array') rmaker = CoordSysMaker(spacecoo, 'generic-scanner') cm_maker = cmap.CoordMapMaker(dmaker, rmaker) cmap_out = cm_maker.make_affine(onto_aff) if verbose > 0: print("cmap_out:\n", cmap_out) # Define the default physical to physical transformation if w2wmap is None: w2wmap = np.eye(onto_aff.shape[0]) if verbose > 0: print("w2wmap:\n", w2wmap) # Resample source_image = nipy.load_image(source_file) resampled_image = resample( source_image, cmap_out, w2wmap, onto_shape, order=order, cval=cval) # Save the resampled image resampled_file = os.path.join( outdir, "resampled_{0}".format(os.path.basename(source_file))) nipy.save_image(resampled_image, resampled_file) return resampled_file
def test_resample2d3(): # Same as test_resample2d, only a different way of specifying # the transform: here it is an (A,b) pair g = AffineTransform.from_params('ij', 'xy', np.diag([0.5,0.5,1])) i = Image(np.ones((100,90)), g) i.get_data()[50:55,40:55] = 3. a = np.identity(3) a[:2,-1] = 4. ir = resample(i, i.coordmap, a, (100,90)) assert_array_almost_equal(ir.get_data()[42:47,32:47], 3.)
def test_resample2d2(): g = AffineTransform.from_params('ij', 'xy', np.diag([0.5,0.5,1])) i = Image(np.ones((100,90)), g) i.get_data()[50:55,40:55] = 3. a = np.identity(3) a[:2,-1] = 4. A = np.identity(2) b = np.ones(2)*4 ir = resample(i, i.coordmap, (A, b), (100,90)) assert_array_almost_equal(ir.get_data()[42:47,32:47], 3.)
def test_resample2d2(): g = AffineTransform.from_params('ij', 'xy', np.diag([0.5, 0.5, 1])) i = Image(np.ones((100, 90)), g) i.get_data()[50:55, 40:55] = 3. a = np.identity(3) a[:2, -1] = 4. A = np.identity(2) b = np.ones(2) * 4 ir = resample(i, i.coordmap, (A, b), (100, 90)) assert_array_almost_equal(ir.get_data()[42:47, 32:47], 3.)
def test_resample2d3(): # Same as test_resample2d, only a different way of specifying # the transform: here it is an (A,b) pair g = AffineTransform.from_params('ij', 'xy', np.diag([0.5, 0.5, 1])) i = Image(np.ones((100, 90)), g) i.get_data()[50:55, 40:55] = 3. a = np.identity(3) a[:2, -1] = 4. ir = resample(i, i.coordmap, a, (100, 90)) assert_array_almost_equal(ir.get_data()[42:47, 32:47], 3.)
def test_resample2d3(): # Same as test_resample2d, only a different way of specifying # the transform: here it is an (A,b) pair g = AffineTransform.from_params("ij", "xy", np.diag([0.5, 0.5, 1])) i = Image(np.ones((100, 90)), g) i[50:55, 40:55] = 3.0 a = np.identity(3) a[:2, -1] = 4.0 ir = resample(i, i.coordmap, a, (100, 90)) yield assert_array_almost_equal, ir[42:47, 32:47], 3.0
def test_resample2d2(): g = AffineTransform.from_params("ij", "xy", np.diag([0.5, 0.5, 1])) i = Image(np.ones((100, 90)), g) i[50:55, 40:55] = 3.0 a = np.identity(3) a[:2, -1] = 4.0 A = np.identity(2) b = np.ones(2) * 4 ir = resample(i, i.coordmap, (A, b), (100, 90)) yield assert_array_almost_equal, ir[42:47, 32:47], 3.0
def test_rotate2d(): # Rotate an image in 2d on a square grid, should result in transposed image g = AffineTransform.from_params('ij', 'xy', np.diag([0.7, 0.5, 1])) g2 = AffineTransform.from_params('ij', 'xy', np.diag([0.5, 0.7, 1])) i = Image(np.ones((100, 100)), g) # This sets the image data by writing into the array i.get_data()[50:55, 40:55] = 3. a = np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]], np.float) ir = resample(i, g2, a, (100, 100)) assert_array_almost_equal(ir.get_data().T, i.get_data())
def test_slice_from_3d(): # Resample a 3d image, returning a zslice, yslice and xslice # # This example creates a coordmap that coincides with # a given z, y, or x slice of an image, and checks that # resampling agrees with the data in the given slice. shape = (100, 90, 80) g = AffineTransform.from_params('ijk', 'xyz', np.diag([0.5, 0.5, 0.5, 1])) img = Image(np.ones(shape), g) img.get_data()[50:55, 40:55, 30:33] = 3 I = np.identity(4) zsl = slices.zslice(26, ((0, 49.5), 100), ((0, 44.5), 90), img.reference) ir = resample(img, zsl, I, (100, 90)) assert_array_almost_equal(ir.get_data(), img[:, :, 53].get_data()) ysl = slices.yslice(22, ((0, 49.5), 100), ((0, 39.5), 80), img.reference) ir = resample(img, ysl, I, (100, 80)) assert_array_almost_equal(ir.get_data(), img[:, 45, :].get_data()) xsl = slices.xslice(15.5, ((0, 44.5), 90), ((0, 39.5), 80), img.reference) ir = resample(img, xsl, I, (90, 80)) assert_array_almost_equal(ir.get_data(), img[32, :, :].get_data())
def test_slice_from_3d(): # Resample a 3d image, returning a zslice, yslice and xslice # # This example creates a coordmap that coincides with # the 10th slice of an image, and checks that # resampling agrees with the data in the 10th slice. shape = (100, 90, 80) g = AffineTransform.from_params("ijk", "xyz", np.diag([0.5, 0.5, 0.5, 1])) i = Image(np.ones(shape), g) i[50:55, 40:55, 30:33] = 3 a = np.identity(4) zsl = slices.zslice(26, ((0, 44.5), 90), ((0, 39.5), 80), i.reference) ir = resample(i, zsl, a, (90, 80)) yield assert_true(np.allclose(np.asarray(ir), np.asarray(i[53]))) ysl = slices.yslice(22, (0, 49.5), (0, 39.5), i.reference, (100, 80)) ir = resample(i, ysl.coordmap, a, ysl.shape) yield assert_true(np.allclose(np.asarray(ir), np.asarray(i[:, 45]))) xsl = slices.xslice(15.5, (0, 49.5), (0, 44.5), i.reference, (100, 90)) ir = resample(i, xsl.coordmap, a, xsl.shape) yield assert_true(np.allclose(np.asarray(ir), np.asarray(i[:, :, 32])))
def test_rotate3d(): # Rotate / transpose a 3d image on a non-square grid g = AffineTransform.from_params('ijk', 'xyz', np.diag([0.5, 0.6, 0.7, 1])) g2 = AffineTransform.from_params('ijk', 'xyz', np.diag([0.5, 0.7, 0.6, 1])) shape = (100, 90, 80) i = Image(np.ones(shape), g) i.get_data()[50:55, 40:55, 30:33] = 3. a = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1.]]) ir = resample(i, g2, a, (100, 80, 90)) assert_array_almost_equal(np.transpose(ir.get_data(), (0, 2, 1)), i.get_data())
def test_rotate2d(): # Rotate an image in 2d on a square grid, should result in transposed image g = AffineTransform.from_params('ij', 'xy', np.diag([0.7,0.5,1])) g2 = AffineTransform.from_params('ij', 'xy', np.diag([0.5,0.7,1])) i = Image(np.ones((100,100)), g) # This sets the image data by writing into the array i.get_data()[50:55,40:55] = 3. a = np.array([[0,1,0], [1,0,0], [0,0,1]], np.float) ir = resample(i, g2, a, (100, 100)) assert_array_almost_equal(ir.get_data().T, i.get_data())
def test_resample_outvalue(): # Test resampling with different modes, constant values, datatypes, orders def func(xyz): return xyz + np.asarray([1,0,0]) coordmap = vox2mni(np.eye(4)) arr = np.arange(3 * 3 * 3).reshape(3, 3, 3) aff = np.eye(4) aff[0, 3] = 1. # x translation for mapping, dt, order in product( [aff, func], [np.int8, np.intp, np.int32, np.int64, np.float32, np.float64], [0, 1, 3]): img = Image(arr.astype(dt), coordmap) # Test constant value of 0 img2 = resample(img, coordmap, mapping, img.shape, order=order, mode='constant', cval=0.) exp_arr = np.zeros(arr.shape) exp_arr[:-1, :, :] = arr[1:, :, :] assert_array_almost_equal(img2.get_data(), exp_arr) # Test constant value of 1 img2 = resample(img, coordmap, mapping, img.shape, order=order, mode='constant', cval=1.) exp_arr[-1, :, :] = 1 assert_array_almost_equal(img2.get_data(), exp_arr) # Test nearest neighbor img2 = resample(img, coordmap, mapping, img.shape, order=order, mode='nearest') exp_arr[-1, :, :] = arr[-1, :, :] assert_array_almost_equal(img2.get_data(), exp_arr) # Test img2img target_coordmap = vox2mni(aff) target = Image(arr, target_coordmap) img2 = resample_img2img(img, target, 3, 'nearest') assert_array_almost_equal(img2.get_data(), exp_arr) img2 = resample_img2img(img, target, 3, 'constant', cval=1.) exp_arr[-1, :, :] = 1 assert_array_almost_equal(img2.get_data(), exp_arr)
def test_2d_from_3d(): # Resample a 3d image on a 2d affine grid # This example creates a coordmap that coincides with # the 10th slice of an image, and checks that # resampling agrees with the data in the 10th slice. shape = (100, 90, 80) g = AffineTransform.from_params('ijk', 'xyz', np.diag([0.5, 0.5, 0.5, 1])) i = Image(np.ones(shape), g) i.get_data()[50:55, 40:55, 30:33] = 3. a = np.identity(4) g2 = ArrayCoordMap.from_shape(g, shape)[10] ir = resample(i, g2.coordmap, a, g2.shape) assert_array_almost_equal(ir.get_data(), i[10].get_data())
def test_2d_from_3d(): # Resample a 3d image on a 2d affine grid # This example creates a coordmap that coincides with # the 10th slice of an image, and checks that # resampling agrees with the data in the 10th slice. shape = (100, 90, 80) g = AffineTransform.from_params("ijk", "xyz", np.diag([0.5, 0.5, 0.5, 1])) i = Image(np.ones(shape), g) i[50:55, 40:55, 30:33] = 3.0 a = np.identity(4) g2 = ArrayCoordMap.from_shape(g, shape)[10] ir = resample(i, g2.coordmap, a, g2.shape) yield assert_array_almost_equal, np.asarray(ir), np.asarray(i[10])
def test_rotate3d(): # Rotate / transpose a 3d image on a non-square grid g = AffineTransform.from_params('ijk', 'xyz', np.diag([0.5,0.6,0.7,1])) g2 = AffineTransform.from_params('ijk', 'xyz', np.diag([0.5,0.7,0.6,1])) shape = (100,90,80) i = Image(np.ones(shape), g) i.get_data()[50:55,40:55,30:33] = 3. a = np.array([[1,0,0,0], [0,0,1,0], [0,1,0,0], [0,0,0,1.]]) ir = resample(i, g2, a, (100,80,90)) assert_array_almost_equal(np.transpose(ir.get_data(), (0,2,1)), i.get_data())
def test_resample2d1(): # Tests the same as test_resample2d, only using a callable instead of # an AffineTransform instance g = AffineTransform.from_params('ij', 'xy', np.diag([0.5,0.5,1])) i = Image(np.ones((100,90)), g) i.get_data()[50:55,40:55] = 3. a = np.identity(3) a[:2,-1] = 4. A = np.identity(2) b = np.ones(2)*4 def mapper(x): return np.dot(x, A.T) + b ir = resample(i, i.coordmap, mapper, (100,90)) assert_array_almost_equal(ir.get_data()[42:47,32:47], 3.)
def test_rotate3d(): # Rotate / transpose a 3d image on a non-square grid g = AffineTransform.from_params("ijk", "xyz", np.diag([0.5, 0.6, 0.7, 1])) g2 = AffineTransform.from_params("ijk", "xyz", np.diag([0.5, 0.7, 0.6, 1])) shape = (100, 90, 80) i = Image(np.ones(shape), g) i[50:55, 40:55, 30:33] = 3.0 a = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1.0]]) ir = resample(i, g2, a, (100, 80, 90)) yield assert_array_almost_equal, np.transpose(np.asarray(ir), (0, 2, 1)), i
def test_rotate2d2(): # Rotate an image in 2d on a non-square grid, # should result in transposed image g = AffineTransform.from_params("ij", "xy", np.diag([0.7, 0.5, 1])) g2 = AffineTransform.from_params("ij", "xy", np.diag([0.5, 0.7, 1])) i = Image(np.ones((100, 80)), g) i[50:55, 40:55] = 3.0 a = np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]], np.float) ir = resample(i, g2, a, (80, 100)) yield assert_array_almost_equal, np.asarray(ir).T, i
def test_resample2d(): g = AffineTransform.from_params('ij', 'xy', np.diag([0.5, 0.5, 1])) i = Image(np.ones((100, 90)), g) i.get_data()[50:55, 40:55] = 3. # This mapping describes a mapping from the "target" physical # coordinates to the "image" physical coordinates. The 3x3 matrix # below indicates that the "target" physical coordinates are related # to the "image" physical coordinates by a shift of -4 in each # coordinate. Or, to find the "image" physical coordinates, given # the "target" physical coordinates, we add 4 to each "target # coordinate". The resulting resampled image should show the # overall image shifted -8,-8 voxels towards the origin a = np.identity(3) a[:2, -1] = 4. ir = resample(i, i.coordmap, a, (100, 90)) assert_array_almost_equal(ir.get_data()[42:47, 32:47], 3.)
def test_resample2d1(): # Tests the same as test_resample2d, only using a callable instead of # an AffineTransform instance g = AffineTransform.from_params('ij', 'xy', np.diag([0.5, 0.5, 1])) i = Image(np.ones((100, 90)), g) i.get_data()[50:55, 40:55] = 3. a = np.identity(3) a[:2, -1] = 4. A = np.identity(2) b = np.ones(2) * 4 def mapper(x): return np.dot(x, A.T) + b ir = resample(i, i.coordmap, mapper, (100, 90)) assert_array_almost_equal(ir.get_data()[42:47, 32:47], 3.)
def test_resample2d(): g = AffineTransform.from_params('ij', 'xy', np.diag([0.5,0.5,1])) i = Image(np.ones((100,90)), g) i.get_data()[50:55,40:55] = 3. # This mapping describes a mapping from the "target" physical # coordinates to the "image" physical coordinates. The 3x3 matrix # below indicates that the "target" physical coordinates are related # to the "image" physical coordinates by a shift of -4 in each # coordinate. Or, to find the "image" physical coordinates, given # the "target" physical coordinates, we add 4 to each "target # coordinate". The resulting resampled image should show the # overall image shifted -8,-8 voxels towards the origin a = np.identity(3) a[:2,-1] = 4. ir = resample(i, i.coordmap, a, (100,90)) assert_array_almost_equal(ir.get_data()[42:47,32:47], 3.)
def test_resample3d(): g = AffineTransform.from_params('ijk', 'xyz', np.diag([0.5, 0.5, 0.5, 1])) shape = (100, 90, 80) i = Image(np.ones(shape), g) i.get_data()[50:55, 40:55, 30:33] = 3. # This mapping describes a mapping from the "target" physical # coordinates to the "image" physical coordinates. The 4x4 matrix # below indicates that the "target" physical coordinates are related # to the "image" physical coordinates by a shift of -4 in each # coordinate. Or, to find the "image" physical coordinates, given # the "target" physical coordinates, we add 4 to each "target # coordinate". The resulting resampled image should show the # overall image shifted [-6,-8,-10] voxels towards the origin a = np.identity(4) a[:3, -1] = [3, 4, 5] ir = resample(i, i.coordmap, a, (100, 90, 80)) assert_array_almost_equal(ir.get_data()[44:49, 32:47, 20:23], 3.)
def test_resample3d(): g = AffineTransform.from_params("ijk", "xyz", np.diag([0.5, 0.5, 0.5, 1])) shape = (100, 90, 80) i = Image(np.ones(shape), g) i[50:55, 40:55, 30:33] = 3.0 # This mapping describes a mapping from the "target" physical # coordinates to the "image" physical coordinates. The 4x4 matrix # below indicates that the "target" physical coordinates are related # to the "image" physical coordinates by a shift of -4 in each # coordinate. Or, to find the "image" physical coordinates, given # the "target" physical coordinates, we add 4 to each "target # coordinate". The resulting resampled image should show the # overall image shifted [-6,-8,-10] voxels towards the origin a = np.identity(4) a[:3, -1] = [3, 4, 5] ir = resample(i, i.coordmap, a, (100, 90, 80)) yield assert_array_almost_equal, ir[44:49, 32:47, 20:23], 3.0
def test_rotate2d3(): # Another way to rotate/transpose the image, similar to # test_rotate2d2 and test_rotate2d, except the world of the # output coordmap is the same as the world of the # original image. That is, the data is transposed on disk, but the # output coordinates are still 'x,'y' order, not 'y', 'x' order as # above # this functionality may or may not be used a lot. if data is to # be transposed but one wanted to keep the NIFTI order of output # coords this would do the trick g = AffineTransform.from_params('xy', 'ij', np.diag([0.5, 0.7, 1])) i = Image(np.ones((100, 80)), g) # This sets the image data by writing into the array i.get_data()[50:55, 40:55] = 3. a = np.identity(3) g2 = AffineTransform.from_params( 'xy', 'ij', np.array([[0, 0.5, 0], [0.7, 0, 0], [0, 0, 1]])) ir = resample(i, g2, a, (80, 100)) assert_array_almost_equal(ir.get_data().T, i.get_data())
def test_rotate2d3(): # Another way to rotate/transpose the image, similar to # test_rotate2d2 and test_rotate2d, except the world of the # output coordmap is the same as the world of the # original image. That is, the data is transposed on disk, but the # output coordinates are still 'x,'y' order, not 'y', 'x' order as # above # this functionality may or may not be used a lot. if data is to # be transposed but one wanted to keep the NIFTI order of output # coords this would do the trick g = AffineTransform.from_params('xy', 'ij', np.diag([0.5,0.7,1])) i = Image(np.ones((100,80)), g) # This sets the image data by writing into the array i.get_data()[50:55,40:55] = 3. a = np.identity(3) g2 = AffineTransform.from_params('xy', 'ij', np.array([[0,0.5,0], [0.7,0,0], [0,0,1]])) ir = resample(i, g2, a, (80,100)) assert_array_almost_equal(ir.get_data().T, i.get_data())
def test_rotate2d3(): # Another way to rotate/transpose the image, similar to # test_rotate2d2 and test_rotate2d except the world of the # output coordmap are the same as the world of the # original image. That is, the data is transposed on disk, but the # output coordinates are still 'x,'y' order, not 'y', 'x' order as # above # this functionality may or may not be used a lot. if data is to # be transposed but one wanted to keep the NIFTI order of output # coords this would do the trick g = AffineTransform.from_params("xy", "ij", np.diag([0.5, 0.7, 1])) i = Image(np.ones((100, 80)), g) i[50:55, 40:55] = 3.0 a = np.identity(3) g2 = AffineTransform.from_params("xy", "ij", np.array([[0, 0.5, 0], [0.7, 0, 0], [0, 0, 1]])) ir = resample(i, g2, a, (80, 100)) v2v = compose(g.inverse(), g2) yield assert_array_almost_equal, np.asarray(ir).T, i
def test_subsample(): # This is how you would subsample with nipy.algorithms.resample # On the first axis, we'll take every 2nd, # on the second axis every 3rd, and on the 3rd every 4th im, xyz_im, ras = generate_im() subsample_matrix = np.array([[2,0,0,0], [0,3,0,0], [0,0,4,0], [0,0,0,1]]) subsampled_shape = np.array(xyz_im)[::2,::3,::4].shape subsample_coordmap = AffineTransform(xyz_im.xyz_transform.function_domain, xyz_im.xyz_transform.function_domain, subsample_matrix) target_coordmap = compose(xyz_im.xyz_transform, subsample_coordmap) # The images have the same output coordinates world_to_world_coordmap = AffineTransform(xyz_im.xyz_transform.function_range, xyz_im.xyz_transform.function_range, np.identity(4)) im_subsampled = resample(xyz_im, target_coordmap, world_to_world_coordmap, shape=subsampled_shape) xyz_im_subsampled = xyz_image.XYZImage(np.array(im_subsampled), im_subsampled.affine, im_subsampled.coordmap.function_domain.coord_names) yield assert_almost_equal, np.array(xyz_im_subsampled), np.array(xyz_im)[::2,::3,::4] # We can now do subsampling with these methods. xyz_im_subsampled2 = xyz_im.resampled_to_affine(target_coordmap, shape=subsampled_shape) yield assert_almost_equal, np.array(xyz_im_subsampled2), np.array(xyz_im_subsampled) yield assert_true, xyz_im_subsampled2 == xyz_im_subsampled
def _set_coef_block( self, coords = None, mask = MASK_FULL, upsample = True ): """ Gets a coefficient block corresponding to a set of model parameters. """ if coords is None: coords = [self.x_coord, self.y_coord, self.z_coord, self.t_coord] coefs = self._get_coefs( self.params ) ims = unmask( coefs, mask ) im = ims[ coords[3] ] / np.fabs( ims[ coords[3] ] ).max() im = Image( im, self.anatim.coordmap ) if upsample == True: print 'resampling' if self.affine_resample is None: h = R.HistogramRegistration( im, self.anathi ) self.affine_resample = h.optimize( 'affine' ).as_affine() resampled_im = resample( im, self.anathi.coordmap, self.affine_resample, self.anathi.shape, order = 1 ) # reim = resample( im, self.anathi.coordmap, np.identity(4), self.anathi.shape, order=1 ) print 'done' # im = np.ma.masked_array( np.asarray(reim), np.less( np.fabs(reim), 0.05 ) ) im = np.asarray( resampled_im ) self.im = im
def resampled_to_affine(self, affine_transform, world_to_world=None, interpolation_order=3, shape=None): """ Resample the image to be an affine image. Parameters ---------- affine_transform : XYZTransform Affine of the new grid. world_to_world: 4x4 ndarray, optional A matrix representing a mapping from the target's "world" to self's "world". Defaults to np.identity(4) interpolation_order : int, optional Order of the spline interplation. If 0, nearest-neighbour interpolation is performed. shape: tuple Shape of the resulting image. Defaults to self.shape. Returns ------- resampled_image : XYZImage New nipy image with the data resampled in the given affine. Notes ----- The coordinate system of the output image is the world of affine_transform. Therefore, if world_to_world=np.identity(4), the coordinate system is not changed: the returned image points to the same world space. """ shape = shape or self.shape shape = shape[:3] if world_to_world is None: world_to_world = np.identity(4) world_to_world_transform = AffineTransform(affine_transform.function_range, self.reference, world_to_world) if self.ndim == 3: # we import ``resample`` here because an earlier import causes # an import error, during build, because of the statistics # import of compile modules. This is not a good fix, but it # will do for now. from nipy.algorithms.resample import resample im = resample(self, affine_transform, world_to_world_transform, shape, order=interpolation_order) return XYZImage(np.array(im), affine_transform.affine, affine_transform.function_domain.coord_names, metadata=self.metadata) # XXX this below wasn't included in the original XYZImage # proposal and it would fail for an XYZImage with ndim == 4. I # don't know if it should be included as a special case in the # XYZImage, but then we should at least raise an exception # saying that these resample_* methods only work for XYZImage's # with ndim==3. # # This is part of the reason nipy.core.image.Image does not have # resample_* methods... elif self.ndim == 4: result = np.empty(shape + (self.shape[3],)) data = self.get_data() for i in range(self.shape[3]): tmp_affine_im = XYZImage(data[...,i], self.affine, self.axes.coord_names[:-1], metadata=self.metadata) tmp_im = tmp_affine_im.resampled_to_affine(affine_transform, world_to_world, interpolation_order, shape) result[...,i] = np.array(tmp_im) return XYZImage(result, affine_transform.affine, self.axes.coord_names, metadata=self.metadata) else: raise ValueError('resampling only defined for 3d and 4d XYZImage')
# downsample to make smaller output image downsamp = 1/3 epi_scale = np.diag([downsamp, downsamp, downsamp, 1]) # template voxels to epi box image voxels vox2epi_vox = epi_scale.dot(rot.dot(epi_trans)) # epi image voxels to mm epi_vox2mm = t2_img.affine.dot(npl.inv(vox2epi_vox)) # downsampled image shape epi_vox_shape = np.array([data.shape[0], epi_x_len, epi_y_len]) * downsamp # Make sure dimensions are odd by rounding up or down # This makes the voxel center an integer index, which is convenient epi_vox_shape = [np.floor(d) if np.floor(d) % 2 else np.ceil(d) for d in epi_vox_shape] # resample, preserving affine epi_cmap = nca.vox2mni(epi_vox2mm) epi = rsm.resample(t2_img, epi_cmap, np.eye(4), epi_vox_shape) epi_data = epi.get_data() # Do the same kind of thing for the anatomical scan anat_vox_sizes = [2.75, 2.75, 2.75] anat_scale = npl.inv(np.diag(anat_vox_sizes + [1])) anat_trans = np.eye(4) anat_trans[:3, 3] = -np.array([0, anat_box[0, 0], anat_box[0, 1]]) vox2anat_vox = anat_scale.dot(anat_trans) anat_vox2mm = t1_img.affine.dot(npl.inv(vox2anat_vox)) anat_vox_shape = np.round(np.divide( [data.shape[0], anat_x_len, anat_y_len], anat_vox_sizes)) anat_cmap = nca.vox2mni(anat_vox2mm) anat = rsm.resample(t1_img, anat_cmap, np.eye(4), anat_vox_shape) anat_data = anat.get_data() save_plot()
def resampled_to_affine(self, affine_transform, world_to_world=None, interpolation_order=3, shape=None): """ Resample the image to be an affine image. Parameters ---------- affine_transform : AffineTransform Affine of the new grid. XXX In the original proposal, it said something about "if only 3x3 it is assumed to be a rotation", but this wouldn't work the way the code was written becuase it was written as if affine was the affine of an AffineImage. So, if you input a "rotation matrix" that is assuming you have voxels of size 1.... This rotation can now be expressed with the world_to_world argument. world_to_world: 4x4 ndarray, optional A matrix representing a mapping from the target's (affine_transform) "world" to self's "world". Defaults to np.identity(4) interpolation_order : int, optional Order of the spline interplation. If 0, nearest-neighbour interpolation is performed. shape: tuple Shape of the resulting image. Defaults to self.shape. Returns ------- resampled_image : nipy AffineImage New nipy image with the data resampled in the given affine. Notes ----- The coordinate system of the resampled_image is the world of affine_transform. Therefore, if world_to_world=np.identity(4), the coordinate system is not changed: the returned image points to the same world space. """ shape = shape or self.shape shape = shape[:3] if world_to_world is None: world_to_world = np.identity(4) world_to_world_transform = AffineTransform(affine_transform.function_range, self.spatial_coordmap.function_range, world_to_world) if self.ndim == 3: im = resample(self, affine_transform, world_to_world_transform, shape, order=interpolation_order) return AffineImage(np.array(im), affine_transform.affine, affine_transform.function_domain.name) # XXX this below wasn't included in the original AffineImage proposal # and it would fail for an AffineImage with ndim == 4. # I don't know if it should be included as a special case in the AffineImage, # but then we should at least raise an exception saying that these resample_* methods # only work for AffineImage's with ndim==3. # # This is part of the reason nipy.core.image.Image does not have # resample_* methods... elif self.ndim == 4: result = np.empty(shape + (self.shape[3],)) data = self.get_data() for i in range(self.shape[3]): tmp_affine_im = AffineImage(data[...,i], self.affine, self.axis_names[:-1]) tmp_im = tmp_affine_im.resampled_to_affine(affine_transform, world_to_world, interpolation_order, shape) result[...,i] = np.array(tmp_im) return AffineImage(result, affine_transform.affine, affine_transform.function_domain.name) else: raise ValueError('resampling only defined for 3d and 4d AffineImage')
def resample_image(source_file, target_file, output_directory, w2wmap_file=None, erode_path_nb=0, order=3, cval=0.0): """ Resample the source image to match the target image using Nipy. Parameters ---------- source_file: str (mandatory) the image to resample. target_file: str (mandatory) the reference image. outdir: str (mandatory) the folder where the resampled image will be saved. w2wmap: array (4, 4) or callable physical to physical transformation. erode_path_nb: Int (optional, default 1) the number of path of the erosion. Performed before resampling. verbose: int (optional, default 0) the verbosity level. Returns ------- resampled_file: str the resampled image. CAPSUL header ------------- <process capsul_xml="2.0"> <input name="source_file" type="file" doc="the image to resample."/> <input name="target_file" type="file" doc="the reference image."/> <input name="output_directory" type="directory" doc="the folder where the resampled image will be saved."/> <input name="w2wmap_file" type="file" doc="physical to physical transformation file."/> <input name="erode_path_nb" type="int" doc="the number of path in erosion of the mask"/> <input name="order" type="int" doc="interpolation mode, 0 = nearest neighbour"/> <input name="cval" type="float" doc=""/> <return name="resampled_file" type="file" doc="the resampled image."/> </process> """ verbose = 0 # get world to world transformation # SPM version w2wmap = scipy.io.loadmat(w2wmap_file)["Affine"] # fsl version # w2wmap = np.fromfile(w2wmap_file, sep=" ") # w2wmap = w2wmap.reshape(4, 4) w2wmap = np.linalg.inv(w2wmap) # Get target image information target_image = nipy.load_image(target_file) onto_shape = target_image.shape[:3] onto_aff = xyz_affine(target_image.affine, xyz=[0, 1, 2], verbose=verbose) # Define index and physical coordinate systems arraycoo = "ijklmnopq"[:len(onto_shape)] spacecoo = "xyztrsuvw"[:len(onto_shape)] if verbose > 0: print("\narraycoo: ", arraycoo, "\nspacecoo: ", spacecoo, "\nonto_aff\n", onto_aff) dmaker = CoordSysMaker(arraycoo, 'generic-array') rmaker = CoordSysMaker(spacecoo, 'generic-scanner') cm_maker = cmap.CoordMapMaker(dmaker, rmaker) cmap_out = cm_maker.make_affine(onto_aff) if verbose > 0: print("cmap_out:\n", cmap_out) # Define the default physical to physical transformation if w2wmap is None: w2wmap = np.eye(onto_aff.shape[0]) if verbose > 0: print("w2wmap:\n", w2wmap) # erode anatomic mask if requestd if erode_path_nb > 0: structuring_element = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]], [[0, 1, 0], [1, 1, 1], [0, 1, 0]], [[0, 0, 0], [0, 1, 0], [0, 0, 0]]]) # get anatomic mask source_image = nibabel.load(source_file) source_data = source_image.get_data() eroded_image = binary_erosion( source_data, iterations=erode_path_nb, structure=structuring_element).astype(source_data.dtype) # save _temp = nibabel.Nifti1Image(eroded_image, source_image.get_affine()) source_file = os.path.join(output_directory, 'eroded_anat_mask.nii.gz') nibabel.save(_temp, source_file) # Get eroded anatomic mask source_image = nipy.load_image(source_file) # resample resampled_image = resample( source_image, cmap_out, w2wmap, onto_shape, order=order, cval=cval) # save resampled_file = os.path.join( output_directory, "resampled_{0}".format(os.path.basename(source_file))) nipy.save_image(resampled_image, resampled_file) # if not os.path.isfile(resampled_file): # raise ValueError("NO RESAMPLED FILE") return resampled_file