def circlearound_n2d(self, src, radius, metric="euclidean"): shortmetric = metric[0].lower() if shortmetric == "e": v = self.vertices # make sure src is a 1x3 array if type(src) is tuple and len(src) == 3: src = np.asarray(src) if isinstance(src, np.ndarray): if src.shape not in ((1, 3), (3,), (3, 1)): raise ValueError("Illegal shape: should have 3 elements") src_coord = src if src.shape == (1, 3) else np.reshape(src, (1, 3)) else: src_coord = np.reshape(v[src, :], (1, 3)) # ensure it is a float src_coord = np.asanyarray(src_coord, dtype=np.float) # make a mask around center voxel2world = self._vg.affine world2voxel = np.linalg.inv(voxel2world) nrm = np.linalg.norm(voxel2world, 2) max_extent = np.ceil(radius / nrm + 1) src_ijk = self._vg.xyz2ijk(src_coord) # min and max ijk coordinates mn = (src_ijk.ravel() - max_extent).astype(np.int_) mx = (src_ijk.ravel() + max_extent).astype(np.int_) # set boundaries properly mn[mn < 0] = 0 sh = np.asarray(self._vg.shape[:3]) mx[mx > sh] = sh[mx > sh] msk_ijk = np.zeros(self._vg.shape[:3], np.int) msk_ijk[mn[0] : mx[0], mn[1] : mx[1], mn[2] : mx[2]] = 1 msk_lin = msk_ijk.ravel() # indices of voxels around the mask idxs = np.nonzero(msk_lin)[0] d = volgeom.distance(src_coord, v[idxs])[0, :] n = d.size node2dist = dict((idxs[i], d[i]) for i in np.arange(n) if d[i] <= radius) return node2dist elif shortmetric == "d": return {src: 0.0} else: raise ValueError("Illegal metric: %s" % metric)
def target2nearest_source(self, target, fallback_euclidean_distance=False): """Find the voxel nearest to a mask center Parameters ========== target: int linear index of a voxel fallback_euclidean_distance: bool (default: False) Whether to use a euclidean distance metric if target is not in any of the masks in this instance Returns ======= src: int key index for the mask that contains target and is nearest to target. If target is not contained in any mask, then None is returned if fallback_euclidean_distance is False, and the index of the source nearest to target using a Euclidean distance metric is returned if fallback_euclidean_distance is True """ targets = [] if type(target) in (list, tuple): for t in target: targets.append(t) else: targets = [target] xyz_trg = self.xyz_target(np.asarray(targets)) src = self.target2sources(targets) flat_srcs = [] for s in src: if s: for j in s: flat_srcs.append(j) if not flat_srcs: if fallback_euclidean_distance: flat_srcs = self.keys() else: return None xyz_srcs = self.xyz_source(flat_srcs) d = volgeom.distance(xyz_srcs, xyz_trg) i = np.argmin(d) # d is a 2D array, get the row number with the lowest d source = flat_srcs[i // xyz_trg.shape[0]] return source
def source2nearest_target(self, source): """Find the voxel nearest to a mask center Parameters ========== src: int mask index Returns ======= target: int linear index of the voxel that is contained in the mask associated with src and nearest (Euclidean distance) to src. """ trgs = self.__getitem__(source) trg_xyz = self.xyz_target(trgs) src_xyz = self.xyz_source(source) d = volgeom.distance(trg_xyz, src_xyz) i = np.argmin(d) return trgs[i / src_xyz.shape[0]]
def source2nearest_target(self, source): """Finds the voxel nearest to a mask center Parameters ========== src: int mask index Returns ======= target: int linear index of the voxel that is contained in the mask associated with src and nearest (Euclidian distance) to src. """ trgs = self.__getitem__(source) trg_xyz = self.xyz_target(trgs) src_xyz = self.xyz_source(source) d = volgeom.distance(trg_xyz, src_xyz) i = np.argmin(d) return trgs[i / src_xyz.shape[0]]
def test_volume_mask_dict(self): # also tests the outside_node_margin feature sh = (10, 10, 10) msk = np.zeros(sh) for i in xrange(0, sh[0], 2): msk[i, :, :] = 1 vol_affine = np.identity(4) vol_affine[0, 0] = vol_affine[1, 1] = vol_affine[2, 2] = 2 vg = volgeom.VolGeom(sh, vol_affine, mask=msk) density = 10 outer = surf.generate_sphere(density) * 10. + 5 inner = surf.generate_sphere(density) * 5. + 5 intermediate = outer * .5 + inner * .5 xyz = intermediate.vertices radius = 50 outside_node_margins = [None, 0, 100., np.inf, True] expected_center_count = [87] * 2 + [intermediate.nvertices] * 3 for k, outside_node_margin in enumerate(outside_node_margins): sel = surf_voxel_selection.run_voxel_selection( radius, vg, inner, outer, outside_node_margin=outside_node_margin) assert_equal(intermediate, sel.source) assert_equal(len(sel.keys()), expected_center_count[k]) assert_true( set(sel.aux_keys()).issubset( set(['center_distances', 'grey_matter_position']))) msk_lin = msk.ravel() sel_msk_lin = sel.get_mask().ravel() for i in xrange(vg.nvoxels): if msk_lin[i]: src = sel.target2nearest_source(i) assert_false((src is None) ^ (sel_msk_lin[i] == 0)) if src is None: continue # index of node nearest to voxel i src_anywhere = sel.target2nearest_source( i, fallback_euclidean_distance=True) # coordinates of node nearest to voxel i xyz_src = xyz[src_anywhere] # coordinates of voxel i xyz_trg = vg.lin2xyz(np.asarray([i])) # distance between node nearest to voxel i, and voxel i # this should be the smallest distancer d = volgeom.distance(np.reshape(xyz_src, (1, 3)), xyz_trg) # distances between all nodes and voxel i ds = volgeom.distance(xyz, xyz_trg) # order of the distances is_ds = np.argsort(ds.ravel()) # go over all the nodes # require that the node is in the volume # mask # index of node nearest to voxel i ii = np.argmin(ds) xyz_min = xyz[ii] lin_min = vg.xyz2lin([xyz_min]) # linear index of voxel that contains xyz_src lin_src = vg.xyz2lin(np.reshape(xyz_src, (1, 3))) # when using multi-core support, # pickling and unpickling can reduce the precision # a little bit, causing rounding errors eps = 1e-14 delta = np.abs(ds[ii] - d) assert_false(delta > eps and ii in sel and i in sel[ii] and vg.contains_lin(lin_min))
def test_volume_mask_dict(self): # also tests the outside_node_margin feature sh = (10, 10, 10) msk = np.zeros(sh) for i in xrange(0, sh[0], 2): msk[i, :, :] = 1 vol_affine = np.identity(4) vol_affine[0, 0] = vol_affine[1, 1] = vol_affine[2, 2] = 2 vg = volgeom.VolGeom(sh, vol_affine, mask=msk) density = 10 outer = surf.generate_sphere(density) * 10. + 5 inner = surf.generate_sphere(density) * 5. + 5 intermediate = outer * .5 + inner * .5 xyz = intermediate.vertices radius = 50 outside_node_margins = [None, 0, 100., np.inf, True] expected_center_count = [87] * 2 + [intermediate.nvertices] * 3 for k, outside_node_margin in enumerate(outside_node_margins): sel = surf_voxel_selection.run_voxel_selection(radius, vg, inner, outer, outside_node_margin=outside_node_margin) assert_equal(intermediate, sel.source) assert_equal(len(sel.keys()), expected_center_count[k]) assert_true(set(sel.aux_keys()).issubset(set(['center_distances', 'grey_matter_position']))) msk_lin = msk.ravel() sel_msk_lin = sel.get_mask().ravel() for i in xrange(vg.nvoxels): if msk_lin[i]: src = sel.target2nearest_source(i) assert_false((src is None) ^ (sel_msk_lin[i] == 0)) if src is None: continue # index of node nearest to voxel i src_anywhere = sel.target2nearest_source(i, fallback_euclidean_distance=True) # coordinates of node nearest to voxel i xyz_src = xyz[src_anywhere] # coordinates of voxel i xyz_trg = vg.lin2xyz(np.asarray([i])) # distance between node nearest to voxel i, and voxel i # this should be the smallest distancer d = volgeom.distance(np.reshape(xyz_src, (1, 3)), xyz_trg) # distances between all nodes and voxel i ds = volgeom.distance(xyz, xyz_trg) # order of the distances is_ds = np.argsort(ds.ravel()) # go over all the nodes # require that the node is in the volume # mask # index of node nearest to voxel i ii = np.argmin(ds) xyz_min = xyz[ii] lin_min = vg.xyz2lin([xyz_min]) # linear index of voxel that contains xyz_src lin_src = vg.xyz2lin(np.reshape(xyz_src, (1, 3))) # when using multi-core support, # pickling and unpickling can reduce the precision # a little bit, causing rounding errors eps = 1e-14 delta = np.abs(ds[ii] - d) assert_false(delta > eps and ii in sel and i in sel[ii] and vg.contains_lin(lin_min))
def circlearound_n2d(self, src, radius, metric='euclidean'): shortmetric = metric[0].lower() if shortmetric == 'e': v = self.vertices # make sure src is a 1x3 array if type(src) is tuple and len(src) == 3: src = np.asarray(src) if isinstance(src, np.ndarray): if src.shape not in ((1, 3), (3, ), (3, 1)): raise ValueError("Illegal shape: should have 3 elements") src_coord = src if src.shape == (1, 3) else np.reshape( src, (1, 3)) else: src_coord = np.reshape(v[src, :], (1, 3)) # ensure it is a float src_coord = np.asanyarray(src_coord, dtype=np.float) # make a mask around center voxel2world = self._vg.affine world2voxel = np.linalg.inv(voxel2world) nrm = np.linalg.norm(voxel2world, 2) max_extent = np.ceil(radius / nrm + 1) src_ijk = self._vg.xyz2ijk(src_coord) # min and max ijk coordinates mn = (src_ijk.ravel() - max_extent).astype(np.int_) mx = (src_ijk.ravel() + max_extent).astype(np.int_) # set boundaries properly mn[mn < 0] = 0 sh = np.asarray(self._vg.shape[:3]) mx[mx > sh] = sh[mx > sh] msk_ijk = np.zeros(self._vg.shape[:3], np.int) msk_ijk[mn[0]:mx[0], mn[1]:mx[1], mn[2]:mx[2]] = 1 msk_lin = msk_ijk.ravel() # indices of voxels around the mask idxs = np.nonzero(msk_lin)[0] d = volgeom.distance(src_coord, v[idxs])[0, :] n = d.size node2dist = dict( (idxs[i], d[i]) for i in np.arange(n) if d[i] <= radius) return node2dist elif shortmetric == 'd': return {src: 0.} else: raise ValueError("Illegal metric: %s" % metric)