def rotate(v, angle=None, rm=None, c1=None, c2=None, loc_r=None, siz2=None, default_val=float('NaN')): if (angle is not None): assert (rm is None) angle = N.array(angle, dtype=N.float).flatten() rm = AA.rotation_matrix_zyz(angle) if (rm is None): rm = N.eye(v.ndim) siz1 = N.array(v.shape, dtype=N.float) if (c1 is None): c1 = ((siz1 - 1) / 2.0) else: c1 = c1.flatten() assert (c1.shape == (3,)) if (siz2 is None): siz2 = siz1 siz2 = N.array(siz2, dtype=N.float) if (c2 is None): c2 = ((siz2 - 1) / 2.0) else: c2 = c2.flatten() assert (c2.shape == (3,)) if (loc_r is not None): loc_r = N.array(loc_r, dtype=N.float).flatten() assert (loc_r.shape == (3,)) c2 += loc_r c = ((- rm.dot(c2)) + c1) vr = SNI.affine_transform(input=v, matrix=rm, offset=c, output_shape=siz2.astype(N.int), cval=default_val) return vr
def rotate3d_zyz(data, angle = None, rm = None, center=None, order=2, cval = 0.0): """Rotate a 3D data using ZYZ convention (phi: z1, the: x, psi: z2). """ # Figure out the rotation center if center is None: cx = data.shape[0] / 2 cy = data.shape[1] / 2 cz = data.shape[2] / 2 else: assert len(center) == 3 (cx, cy, cz) = center if rm is None: Inv_R = AA.rotation_matrix_zyz(angle) else: Inv_R = rm from scipy import mgrid grid = mgrid[-cx:data.shape[0]-cx, -cy:data.shape[1]-cy, -cz:data.shape[2]-cz] temp = grid.reshape((3, N.int(grid.size/3))) temp = N.dot(Inv_R, temp) grid = N.reshape(temp, grid.shape) grid[0] += cx grid[1] += cy grid[2] += cz # Interpolation from scipy.ndimage import map_coordinates d = map_coordinates(data, grid, order=order, cval = cval) return d
def distance_6d_sq__frobenius(p1, p2, weight=1.0): loc1 = np.array(p1[:3]) assert len(loc1) == 3 ang1 = p1[3:] assert len(ang1) == 3 rm1 = TGA.rotation_matrix_zyz(ang1) loc2 = np.array(p2[:3]) assert len(loc2) == 3 ang2 = p2[3:] assert len(ang2) == 3 rm2 = TGA.rotation_matrix_zyz(ang2) d_rm = np.square(np.eye(3) - rm1.transpose().dot(rm2)).sum() d_loc = np.square(loc1 - loc2).sum() return d_rm + weight * d_loc
def distance_6d_sq__frobenius(p1, p2, weight=1.0): """ square of the distance defined on the manifold of the 6D rigid transformation parameter space, the distance between rotations are calculated using Frobenius norm """ loc1 = np.array(p1[:3]) assert len(loc1) == 3 ang1 = p1[3:] assert len(ang1) == 3 rm1 = TGA.rotation_matrix_zyz(ang1) loc2 = np.array(p2[:3]) assert len(loc2) == 3 ang2 = p2[3:] assert len(ang2) == 3 rm2 = TGA.rotation_matrix_zyz(ang2) d_rm = np.square(np.eye(3) - rm1.transpose().dot(rm2)).sum() d_loc = np.square(loc1 - loc2).sum() return d_rm + weight * d_loc
def trace(t1, t2, sigma_c, sigma_l, sigma_d, sc_path, out_path, c_path, phi_path, theta_path, psi_path): """ The main function for filament tracing @param: t1: threshold for similarity, defualt=0.000001 t2: threshold for correlation coefficient, default= 0.0007 sigma_c: measure for smootheness, default=1.0 sigma_l: measure for linearity, default=1.0 sigma_d: measure for distance, default=1.0 sc_path: file path of search cone, see search cone linked at the top of the script out_path: output file path for the tracing result (a binary mask) c_path: file path of the correlation coefficients (e.g. c.npy from 007_template_matching.py) phi_path: file path of the first ZYZ rotation angle(e.g. phi.npy from 007_template_matching.py) theta_path: file path of the second ZYZ rotation angle(e.g. theta.npy from 007_template_matching.py) psi_path: file path of the thrid ZYZ rotation angle(e.g. psi.npy from 007_template_matching.py) @return: bm, a binary mask storing the search result Note that if out_path is not None, trace() would store the search result at the given location """ # forward() and backward() might reach recursion limit sys.setrecursionlimit(10000) assert (sc_path is not None) and (c_path is not None), "File path error" assert (phi_path is not None) and (theta_path is not None) and (psi_path is not None), "File path error" if t1 is None: t1 = 0.000001 if t2 is None: t2 = 0.0007 if sigma_c is None: sigma_c = 1.0 if sigma_l is None: sigma_l = 1.0 if sigma_d is None: sigma_d = 1.0 # load template matching results (see 007_template_matching_tutorial.py) print("Loading template matching results...") c = np.load(c_path) # (10, 400, 398) phi = np.load(phi_path) theta = np.load(theta_path) psi = np.load(psi_path) print("Map shape: ", c.shape) # preprocess cross correlation matrix: negative values => 0.0 print("Preproces correlation coefficients...") c[c < 0.0] = 0.0 print("Maximum corr = ", c.max()) print("Preprocessing orientations...") # orientation = np.load('./orietnation.npy', allow_pickle=True)#can store orientation.npy for faster testing # empty np array to store template orientations orientation = np.empty(c.shape, dtype=object) # assume template is parallel to the y axis v = np.array([0, 1, 0]) # for all voxels for idx, x in np.ndenumerate(c): # get ZYZ angle for template orientation angle = (phi[idx], theta[idx], psi[idx]) # convert to rotation matrix rm = AA.rotation_matrix_zyz(angle) # template orientation in [x, y, z] orientation[idx] = rm.dot(v) # binary mask to store tracing results bm = np.full(c.shape, False, dtype=bool) # read in search cone: SC is along the y axis, i.e. [0,1,0] print("Preparing search cone...") mrc = mrcfile.open(sc_path, mode='r+', permissive=True) # rotated already, along the y axis for now #forward search cone sc = mrc.data print('search cone size', sc.shape) # (10, 11, 11) # mark where x0 is with a negative value sc[(5, 0, 5)] = -100.0 # 180 degree rotation of the search cone rm = np.array([[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]]) # about the XYZ axes # rotate to get the backward search cone sc_back = GR.rotate(sc, rm=rm, default_val=0.0) # tracing: go through corr for all c.max()>=t2 print("Start tracing actin filaments...") while c.max() >= t2: # tracing starts with the highest corr corr = c.max() # get the index of c.max #e.g.(array([5]), array([177]), array([182])) x0 = np.where(c == corr) assert (x0[0].size == 1), "multiple maximum" # convert index to a tuple x0 = (x0[0][0], x0[1][0], x0[2][0]) print("Now at ", x0, " with corr=", corr) bm[x0] = True # recursively search forward bm = forward(x0, sc, c, phi, theta, psi, orientation, sigma_c, sigma_l, sigma_d, t1, bm) bm = backward(x0, sc_back, c, phi, theta, psi, orientation, sigma_c, sigma_l, sigma_d, t1, bm) # set c.max() to -1.0 and go to the next c.max() c[x0] = -1.0 # output bm if out_path is not None: print("Generating output to ", out_path) bm = bm.astype(np.int16) mrc = mrcfile.new(out_path, overwrite=True) mrc.set_data(bm) mrc.close() print("TRACING DONE") return bm