class MeshKLazy(SymMatrixApprox): def __init__(self, func=None, m=1.0): """ m : float, default 1.0 Time step for the geodesic heat approximation. Should be 1.0 normally, but if there's numerical instability, set it higher (e.g. 100.0) """ if func is not None: self._func = func else: self._func = lambda x: x self._m = m def fit(self, pts, polys): self._n = len(pts) self._surface = Surface(pts, polys) def get_row(self, i): return self._func(self._surface.geodesic_distance([i], m=self._m)) def get_rows(self, rows): return np.vstack([ self._func(self._surface.geodesic_distance([i], m=self._m)) for i in rows ]) def get_size(self): return self._n def get_memory(self): return ( self._surface.pts.shape[0] * self._surface.pts.shape[1] + self._surface.polys.shape[0] * self._surface.polys.shape[1]) * 8 def get_name(self): return 'MeshKLazy' @property def shape(self): return self._n, self._n
def perpendicular_scalar_func(sfunc, surf, origin, antipode, mask): sfunc_grad = surf.surface_gradient(sfunc, at_verts=False) normals = surf.face_normals grad_perps = np.cross(sfunc_grad, normals) #norm_grad_perps = grad_perps / np.sqrt((grad_perps ** 2).sum(1)) norm_grad_perps = np.nan_to_num(grad_perps.T / np.sqrt( (grad_perps**2).sum(1))).T # compute integrated divergence X = norm_grad_perps c32, c13, c21 = surf._cot_edge x1 = 0.5 * (c32 * X).sum(1) x2 = 0.5 * (c13 * X).sum(1) x3 = 0.5 * (c21 * X).sum(1) conn1, conn2, conn3 = surf._polyconn divx = conn1.dot(x1) + conn2.dot(x2) + conn3.dot(x3) # create a surface with a cut print("about to cut path") cut_path = np.array(surf.geodesic_path(origin, antipode, m=5)) cut_path = np.union1d(cut_path, mask) #noncut_polys = np.array([p for p in surf.polys if ]) good_polys = ~np.any( np.in1d(surf.polys, cut_path).reshape(surf.polys.shape), 1) cut_surf = Surface(surf.pts, surf.polys[good_polys]) # run the geodesic distance code to generate laplace solver (lol) cut_surf.geodesic_distance([0]) print('2') cconn1, cconn2, cconn3 = cut_surf._polyconn divx_cut = cconn1.dot(x1[good_polys]) + cconn2.dot( x2[good_polys]) + cconn3.dot(x3[good_polys]) # integrate to find fxn whose gradient is norm_grad_perps print('3') part_perp_func = cut_surf._nLC_solvers[1.0](divx_cut[cut_surf._goodrows]) perp_func = np.zeros_like(sfunc) perp_func[cut_surf._goodrows] = part_perp_func return perp_func
class MeshK(SymMatrixApprox): CACHE_DIR = "/tmp" def __init__(self, func=None, m=1.0): self._m = m if func is not None: self._func = func else: self._func = lambda x: x def fit(self, pts, polys, recache=False): self._n = len(pts) self._surface = Surface(pts, polys) # check to see if the full K is cached dataset_hash = str(hash(pts.tostring())) + str(hash( polys.tostring())) + str(hash(self._m)) cache_path = os.path.join(self.CACHE_DIR, dataset_hash + '_geodesic_K_cache.npz') if not os.path.exists(cache_path) or recache: print('Cache not found, computing K..') K = np.vstack([ self._surface.geodesic_distance([i], m=self._m) for i in counter(range(self._n)) ]) self._K = (K + K.T) / 2.0 np.savez(cache_path, geodesic_K=self._K) else: print('Loading K from cache..') self._K = np.load(cache_path)['geodesic_K'] def get_row(self, i): return self._K[i, :] def get_rows(self, rows): return self._K[rows, :] def get_size(self): return self._n def get_memory(self): return self._K.shape[0] * self._K.shape[1] * 8 def get_name(self): return 'MeshK' @property def shape(self): return self._n, self._n
import numpy as np import os from cortex.polyutils import Surface from perpendicular_path import perpendicular_scalar_func import io_mesh as io from neighbours import get_neighbours surf_io = io.load_mesh_geometry('icbm_avg_mid_sym_mc_left_hires.obj') surf = Surface(surf_io['coords'], surf_io['faces']) atlas = np.loadtxt('icbm_avg_mid_sym_mc_atlas_left.txt') lobule = np.loadtxt('lobule.txt') medial = (atlas == 0).astype(int) medial[lobule == 1] = 1 mask = np.where(medial == 1)[0] dists = surf.geodesic_distance(mask, m=5) max_start = np.argmax(dists) #np.savetxt('dists.txt',dists) inv_dists = surf.geodesic_distance(max_start, m=5) filtered = inv_dists.copy() filtered[medial == 0] = 500 #np.savetxt('invdists.txt',inv_dists) #filtered=filtered*0 #filtered[max_start]=1 #np.savetxt('start.txt',filtered) start_vert = np.argmax(dists) end_vert = np.argmin(filtered) #print end_vert