def test_project_fsaverage_voxel_index_to_RAS_coord(): #Cortex structure 'paracentral lobule, anterior part, left' with id 4072: found MIN152 coordinates (-5, -20, 72) coords_mni152 = np.array([[-5, -20, 72]]) coords_mni305 = st.apply_affine_3D(coords_mni152, st.get_affine_matrix_MNI152_to_MNI305()) coords_mni305_surface = st.apply_affine_3D( coords_mni305, st.get_freesurfer_matrix_vox2ras()) assert coords_mni305_surface.shape == (1, 3) assert_allclose(coords_mni305_surface, np.array([[134.37332, -57.259495, 149.267631]]))
def test_get_freesurfer_matrix_vox2ras_for_vertex_0(): # Tests that the vertex at index (128, 128, 128) has a RAS coordinate close to the origin (0., 0., 0.). m = st.get_freesurfer_matrix_vox2ras() voxel_origin = np.array([[128, 128, 128]]) ras_coords_near_origin = st.apply_affine_3D(voxel_origin, m) assert ras_coords_near_origin.shape == (1, 3) assert_allclose(ras_coords_near_origin, np.array([[0., 0., 0.]]))
def test_apply_affine_3D_from_MNI305_to_MIN152_array(): coords_305 = np.array([[10, -20, 35], [-5, -20, 72]]) affine_matrix = st.get_affine_matrix_MNI305_to_MNI152() coords_152 = st.apply_affine_3D(coords_305, affine_matrix) assert coords_152.shape == (2, 3) expected = np.array([[10.6941, -18.4064, 36.1385], [-3.6172, -18.7142, 73.2262]]) assert_allclose(coords_152, expected)
def test_get_freesurfer_matrix_ras2vox(): expected = np.array([[-1.00000, 0.00000, 0.00000, 128.00000], [0.00000, 0.00000, -1.00000, 128.00000], [0.00000, 1.00000, 0.00000, 128.00000], [0.00000, 0.00000, 0.00000, 1.00000]]) m = st.get_freesurfer_matrix_ras2vox() assert_allclose(expected, m) # now apply it: the coordinate (0.0, 0.0, 0.0) should give us voxel index (128, 128, 128) query_coord = np.array([[0., 0., 0.]]) vox_idx = np.rint(st.apply_affine_3D(query_coord, m)).astype(int) expected = np.array([[128, 128, 128]]) assert_array_equal(vox_idx, expected)
def get_ras_coords_at_voxel_crs(self, query_crs_coords): """ Find the RAS coord of each voxel. Find the RAS coord of each voxel. A voxel is identified by its indices along the 3 axes, also knows as CRS (column, row, slice). The computation is based on the ras2vox matrix in the file header. Parameters ---------- query_crs_coords: numpy 2D int array The 3D row, column, slice indices for each voxel, given as a numeric array with shape (n, 3) for n voxels. Returns ------- numpy 2D float array Array with shape (n, 3) representing the RAS coordinates in the volume file (x,y,z). """ return blsp.apply_affine_3D(query_crs_coords, self.vox2ras)
def get_voxel_crs_at_ras_coords(self, query_coords): """ Find the voxel closest to each of the given coordinates. Find the voxel closest to each of the given coordinates. A voxel is identified by its indices along the 3 axes, also knows as CRS (column, row, slice). The computation is based on the ras2vox matrix in the file header. Parameters ---------- query_coords: numpy 2D float array The 3D coordinates, given as a numeric array with shape (n, 3) for n coords. Returns ------- numpy 2D int array Array with shape (n, 3) representing the voxel indices in the volume file. """ voxel_index = blsp.apply_affine_3D(query_coords, self.ras2vox) voxel_index = np.rint(voxel_index).astype(int) return voxel_index
def brain_fs_space_info(): """ Brain FreeSurfer volume file space information. Simple script to query data from a FreeSurfer format brain volume file with transform information in the header. """ # Parse command line arguments parser = argparse.ArgumentParser( description= "Query brain space information from a FreeSurfer volume data file.") input_group = parser.add_mutually_exclusive_group(required=True) input_group.add_argument( "-l", "--location", nargs=3, help= "The location to which the matrix should be applied. Must be a RAS coord or a voxel CRS in the 3D volume (three digits)." ) input_group.add_argument( "-f", "--location-file", help= "A file that contains multiple locations (one per line, the three digits separated by spaces within the line)." ) matrix_to_apply_group = parser.add_mutually_exclusive_group(required=True) matrix_to_apply_group.add_argument( '-r', '--ras2vox-from-vol', help= "Use ras2vox matrix from the header of the given mgh or mgz format file." ) matrix_to_apply_group.add_argument( '-o', '--vox2ras-from-vol', help= "Use vox2ras matrix from the header of the given mgh or mgz format file." ) matrix_to_apply_group.add_argument( '-t', '--vox2ras-tkr-from-vol', help= "Use ras2vox-tkr matrix from the header of the given mgh or mgz format file." ) parser.add_argument( "-s", "--separator", help="Output separator (between vertex coords / indices).", default=" ") parser.add_argument("-i", "--inverse-matrix", help="Inverse the matrix before applying it.", action="store_true") parser.add_argument( "-c", "--round-output", help= "Round output to closest integer. (Useful when result is a voxel CRS.)", action="store_true") parser.add_argument("-v", "--verbose", help="Increase output verbosity.", action="store_true") args = parser.parse_args() if args.location: location = tuple([float(x) for x in args.location]) locations = np.array([location]) else: pass volume_file = args.volume verbose = args.verbose sep = args.separator vol_data, mgh_meta_data = fsd.read_mgh_file(volume_file) m_ras2vox = mgh_meta_data['ras2vox'] m_vox2ras = mgh_meta_data['vox2ras'] m_vox2ras_tkr = mgh_meta_data['vox2ras_tkr'] if verbose: print("Volume has %d dimensions, shape %s and data type %s." % (len(vol_data.shape), vol_data.shape, vol_data.dtype)) if args.apply_ras2vox: location = tuple([float(x) for x in args.apply_ras2vox]) if verbose: print("Applying ras2vox to %s." % str(location)) res_matrix = np.rint( sp.apply_affine_3D(np.array([location]), m_ras2vox)).astype(int) for row in res_matrix: res = sep.join(str(x) for x in row) print(res) if args.apply_vox2ras: location = tuple([int(x) for x in args.apply_vox2ras]) if verbose: print("Applying vox2ras to %s." % str(location)) res_matrix = sp.apply_affine_3D(np.array([location]), m_vox2ras) for row in res_matrix: res = sep.join(str(x) for x in row) print(res) if args.apply_vox2ras_tkr: location = tuple([int(x) for x in args.apply_vox2ras_tkr]) if verbose: print("Applying vox2ras_tkr to %s." % str(location)) res_matrix = sp.apply_affine_3D(np.array([location]), m_vox2ras_tkr) for row in res_matrix: res = sep.join(str(x) for x in row) print(res) sys.exit(0)