def are_blended_voxels_aligned(blended, main_dr, main_r0, over_arr, over_dr, over_r0): """Tests that the over_arr was mixed into blended in the correct voxels, given the spacing and offset parameters. NOTE: It is assumed that the blended array was zero everywhere before blending, making any nonzero elements the contribution of over_arr """ main_map = ni_api.AffineTransform.from_start_step('ijk', 'xyz', main_r0, main_dr) over_map = ni_api.AffineTransform.from_start_step('ijk', 'xyz', over_r0, over_dr) over_vox_from_main_vox = ni_api.compose(over_map.inverse(), main_map) #checking the red component main_nz_vox = np.array( blended[...,0].nonzero() ).T over_nz_vox = over_vox_from_main_vox(main_nz_vox) over_nz_vox = over_nz_vox[(over_nz_vox >= 0).all(axis=-1)] max_idx = np.array(over_arr.shape[:3]) over_nz_vox = over_nz_vox[(over_nz_vox < max_idx).all(axis=-1)].astype('i') # check that in fact the nonzero components from the main blended # image are the nonzero components from the overlay image.. # this mask is False at all over_nz_vox mask = np.ma.getmask(vu.signal_array_to_masked_vol( np.empty(len(over_nz_vox)), over_nz_vox )) # where the mask is True should be 0 -- well, not so if part of the # over array lies outside of the under array. Then there are regions # where the over array does not blend! ## none_outside = not over_arr[...,0][mask].any() # where the mask is False should be != 0 all_inside = over_arr[...,0][np.logical_not(mask)].all() return all_inside
def resample_to_world_grid(img, bbox=None, grid_spacing=None, order=3, axis_permutation=None, **interp_kws): cmap_ijk_xyz = img.coordmap.reordered_range( xipy_ras ).reordered_domain('ijk') T = cmap_ijk_xyz.affine if grid_spacing is None: # find the (i,j,k) voxel sizes, which should be the norm of the columns grid_spacing = voxel_size(T) if bbox is None: # the extent of the rotated image may cover a larger box bbox = world_limits(img) box_limits = np.diff(bbox).reshape(3) diag_affine = np.diag(list(grid_spacing) + [1]) diag_affine[:3,3] = np.asarray(bbox)[:,0] if not axis_permutation: target_domain = 'ijk' else: target_domain = [ 'ijk'[ax] for ax in axis_permutation ] resamp_affine = ni_api.AffineTransform.from_params( target_domain, xipy_ras, diag_affine ) resamp_affine = resamp_affine.reordered_domain( img.coordmap.function_domain.coord_names ) # Doing the mapping this way, we don't have to assume what # the input space of the Image is like cmap_xyz = img.coordmap.reordered_range(xipy_ras) mapping = ni_api.compose(cmap_xyz, img.coordmap.inverse()) # this is the ijk dim ordering.. how do we permute it to match # the input coordinates of the original image? new_dims = np.ceil(box_limits/grid_spacing).astype('i') dim_ordering = map(lambda x: target_domain.index(x), img.coordmap.function_domain.coord_names) new_dims = np.take(new_dims, dim_ordering) new_img = resample.resample(img, resamp_affine, mapping.affine, tuple(new_dims), order=order, **interp_kws) return new_img
def _resample_over_into_main(self): i_bad = self.over_cmap.i_bad vox_to_vox = ni_api.compose( self.over.coordmap.inverse(), self.main.coordmap ) print vox_to_vox.affine print self._main_idx.shape print self._over_idx.shape # this is supposed to be diagonal!! mat = vox_to_vox.affine.diagonal()[:3] offset = vox_to_vox.affine[:3,-1] ## self._over_idx = ndimage.affine_transform( ## self._over_idx, mat, offset, ## output_shape=self._main_idx.shape, ## output=self._over_idx.dtype, ## order=0, cval=i_bad) self._over_idx = resize_lookup_array( self._main_idx.shape, i_bad, self._over_idx, mat, offset )
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 resample(image, target, mapping, shape, order=3, **interp_kws): """ Resample an image to a target CoordinateMap with a "world-to-world" mapping and spline interpolation of a given order. Here, "world-to-world" refers to the fact that mapping should be a callable that takes a physical coordinate in "target" and gives a physical coordinate in "image". Parameters ---------- image : Image instance that is to be resampled target :target CoordinateMap for output image mapping : transformation from target.function_range to image.coordmap.function_range, i.e. 'world-to-world mapping' Can be specified in three ways: a callable, a tuple (A, b) representing the mapping y=dot(A,x)+b or a representation of this in homogeneous coordinates. shape : shape of output array, in target.function_domain order : what order of interpolation to use in `scipy.ndimage` interp_kws : keyword arguments for ndimage interpolator routine Returns ------- output : Image instance with interpolated data and output.coordmap == target """ if not callable(mapping): if type(mapping) is type(()): A, b = mapping ndimout = b.shape[0] ndimin = A.shape[1] mapping = np.zeros((ndimout+1, ndimin+1)) mapping[:ndimout,:ndimin] = A mapping[:ndimout,-1] = b mapping[-1,-1] = 1. # image world to target world mapping TW2IW = AffineTransform(target.function_range, image.coordmap.function_range, mapping) else: TW2IW = CoordinateMap(mapping, target.function_range, image.coordmap.function_range) function_domain = target.function_domain function_range = image.coordmap.function_range # target voxel to image world mapping TV2IW = compose(TW2IW, target) # CoordinateMap describing mapping from target voxel to # image world coordinates if not isinstance(TV2IW, AffineTransform): # interpolator evaluates image at values image.coordmap.function_range, # i.e. physical coordinates rather than voxel coordinates grid = ArrayCoordMap.from_shape(TV2IW, shape) interp = ImageInterpolator(image, order=order) idata = interp.evaluate(grid.transposed_values, **interp_kws) del(interp) else: TV2IV = compose(image.coordmap.inverse(), TV2IW) if isinstance(TV2IV, AffineTransform): A, b = affines.to_matrix_vector(TV2IV.affine) data = np.asarray(image) idata = affine_transform(data, A, offset=b, output_shape=shape, output=data.dtype, order=order, **interp_kws) else: interp = ImageInterpolator(image, order=order) grid = ArrayCoordMap.from_shape(TV2IV, shape) idata = interp.evaluate(grid.values, **interp_kws) del(interp) return Image(idata, target)