def tile_planes(v, axis = 'z', pstep = 1, trim = 0, rows = None, columns = None, fill_order = 'ulh', step = None, subregion = None, model_id = None): vreg = v.subregion(step = step, subregion = subregion) reg = [list(ijk) for ijk in vreg] ac,ar,a = {'x':(1,2,0), 'y':(2,0,1), 'z':(0,1,2)}[axis] reg[0][a] += trim reg[1][a] -= trim reg[2][a] = pstep dorigin, dstep = v.region_origin_and_step(reg) m = v.region_matrix(reg) tcount = m.shape[2-a] if tcount == 0: return if rows is None and columns is None: # Choose columns to make square aspect ratio. w,h = m.shape[2-ac]*dstep[ac], m.shape[2-ar]*dstep[ar] from math import sqrt, ceil columns = min(tcount, int(ceil(sqrt(tcount*float(h)/w)))) rows = (tcount - 1 + columns) // columns elif rows is None: rows = (tcount - 1 + columns) // columns elif columns is None: columns = (tcount - 1 + rows) // rows s0, s1, s2 = m.shape if axis == 'z': tshape = (1,rows*s1,columns*s2) elif axis == 'y': tshape = (columns*s0,1,rows*s2) elif axis == 'x': tshape = (rows*s0,columns*s1,1) from numpy import zeros ta = zeros(tshape, m.dtype) for i in range(tcount): # Start with top image in upper left corner. p,r,c = tile_position(i, rows, columns, tcount, fill_order) if axis == 'z': ta[0,r*s1:(r+1)*s1,c*s2:(c+1)*s2] = m[p,:,:] elif axis == 'y': ta[c*s0:(c+1)*s0,0,r*s2:(r+1)*s2] = m[:,p,:] elif axis == 'x': ta[r*s0:(r+1)*s0,c*s1:(c+1)*s1,0] = m[:,:,p] from chimerax.map_data import ArrayGridData td = ArrayGridData(ta, dorigin, dstep) td.name = v.name + ' tiled %s' % axis from chimerax.map import volume_from_grid_data tv = volume_from_grid_data(td, v.session, model_id = model_id) tv.copy_settings_from(v, copy_region = False, copy_active = False, copy_xform = open) v.display = False # Hide original map return tv
def fourier_transform(v, step=None, subregion=None, model_id=None, phase=False): m = v.matrix(step=step, subregion=subregion) from numpy.fft import fftn cftm = fftn(m) # Complex128 result, same array size as input from numpy import absolute, angle, float32 if phase: aftm = angle(cftm).astype(float32) # Radians else: aftm = absolute(cftm).astype(float32) aftm *= 1.0 / aftm.size # Normalization aftm[0, 0, 0] = 0 # Constant term often huge making histogram hard to use cftm = None # Release memory ftm = fftshift(aftm) aftm = None # Release memory # Place FT centered on data, scaled to keep same volume xyz_min, xyz_max = v.xyz_bounds() xyz_center = map(lambda a, b: 0.5 * (a + b), xyz_min, xyz_max) ijk_size = list(ftm.shape) ijk_size.reverse() if step is None: ijk_step = v.region[2] elif isinstance(step, int): ijk_step = (step, step, step) else: ijk_step = step xyz_size = [a - b for a, b in zip(xyz_max, xyz_min)] vol = xyz_size[0] * xyz_size[1] * xyz_size[2] cell_size = [a * b for a, b in zip(v.data.step, ijk_step)] cell_vol = cell_size[0] * cell_size[1] * cell_size[2] scale = pow(vol * cell_vol, 1.0 / 3) step = [scale / a for a in xyz_size] origin = [c - 0.5 * s * z for c, s, z in zip(xyz_center, step, ijk_size)] from chimerax.map_data import ArrayGridData ftd = ArrayGridData(ftm, origin, step) ftd.name = v.name + (' FT phase' if phase else ' FT') from chimerax.map import volume_from_grid_data ftr = volume_from_grid_data(ftd, v.session, model_id=model_id) ftr.copy_settings_from(v, copy_thresholds=False, copy_colors=False, copy_region=False) ftr.set_parameters(show_outline_box=True) v.display = False # Hide original map return ftr