def transformation_and_inverse(origin, step, axes): ox, oy, oz = origin d0, d1, d2 = step ax, ay, az = axes from chimerax.geometry import Place tf = Place(((d0 * ax[0], d1 * ay[0], d2 * az[0], ox), (d0 * ax[1], d1 * ay[1], d2 * az[1], oy), (d0 * ax[2], d1 * ay[2], d2 * az[2], oz))) tf_inv = tf.inverse() return tf, tf_inv
def ses_surface_geometry(xyz, radii, probe_radius=1.4, grid_spacing=0.5, sas=False): ''' Calculate a solvent excluded molecular surface using a distance grid contouring method. Vertex, normal and triangle arrays are returned. If sas is true then the solvent accessible surface is returned instead. ''' # Compute bounding box for atoms xyz_min, xyz_max = xyz.min(axis=0), xyz.max(axis=0) pad = 2 * probe_radius + radii.max() + grid_spacing origin = [x - pad for x in xyz_min] # Create 3d grid for computing distance map from math import ceil s = grid_spacing shape = [ int(ceil((xyz_max[a] - xyz_min[a] + 2 * pad) / s)) for a in (2, 1, 0) ] # print('ses surface grid size', shape, 'spheres', len(xyz)) from numpy import empty, float32, sqrt try: matrix = empty(shape, float32) except (MemoryError, ValueError): raise MemoryError( 'Surface calculation out of memory trying to allocate a grid %d x %d x %d ' % (shape[2], shape[1], shape[0]) + 'to cover xyz bounds %.3g,%.3g,%.3g ' % tuple(xyz_min) + 'to %.3g,%.3g,%.3g ' % tuple(xyz_max) + 'with grid size %.3g' % grid_spacing) max_index_range = 2 matrix[:, :, :] = max_index_range # Transform centers and radii to grid index coordinates from chimerax.geometry import Place xyz_to_ijk_tf = Place( ((1.0 / s, 0, 0, -origin[0] / s), (0, 1.0 / s, 0, -origin[1] / s), (0, 0, 1.0 / s, -origin[2] / s))) from numpy import float32 ijk = xyz.astype(float32) xyz_to_ijk_tf.transform_points(ijk, in_place=True) ri = radii.astype(float32) ri += probe_radius ri /= s # Compute distance map from surface of spheres, positive outside. from chimerax.map import sphere_surface_distance sphere_surface_distance(ijk, ri, max_index_range, matrix) # Get the SAS surface as a contour surface of the distance map from chimerax.map import contour_surface level = 0 sas_va, sas_ta, sas_na = contour_surface(matrix, level, cap_faces=False, calculate_normals=True) if sas: xyz_to_ijk_tf.inverse().transform_points(sas_va, in_place=True) return sas_va, sas_na, sas_ta # Compute SES surface distance map using SAS surface vertex # points as probe sphere centers. matrix[:, :, :] = max_index_range rp = empty((len(sas_va), ), float32) rp[:] = float(probe_radius) / s sphere_surface_distance(sas_va, rp, max_index_range, matrix) ses_va, ses_ta, ses_na = contour_surface(matrix, level, cap_faces=False, calculate_normals=True) # Transform surface from grid index coordinates to atom coordinates xyz_to_ijk_tf.inverse().transform_points(ses_va, in_place=True) # Delete connected components more than 1.5 probe radius from atom spheres. kvi = [] kti = [] from ._surface import connected_pieces vtilist = connected_pieces(ses_ta) for vi, ti in vtilist: v0 = ses_va[vi[0], :] d = xyz - v0 d2 = (d * d).sum(axis=1) adist = (sqrt(d2) - radii).min() if adist < 1.5 * probe_radius: kvi.append(vi) kti.append(ti) from .split import reduce_geometry from numpy import concatenate keepv = concatenate(kvi) if kvi else [] keept = concatenate(kti) if kti else [] va, na, ta = reduce_geometry(ses_va, ses_na, ses_ta, keepv, keept) return va, na, ta
for b in standard_bases.values(): pts = [b["atoms"][n] for n in b["ring atom names"][0:2]] y_axis = pts[0] - pts[1] # insure that y_axis is perpendicular to z_axis # (should be zero already) y_axis[2] = 0.0 normalize_vector(y_axis) x_axis = numpy.cross(y_axis, z_axis) xf = Place(matrix=((x_axis[0], y_axis[0], z_axis[0], 0.0), (x_axis[1], y_axis[1], z_axis[1], 0.0), (x_axis[2], y_axis[2], z_axis[2], 0.0)) # TODO: orthogonalize=True ) # axis, angle = xf.getRotation() # print("axis = %s, angle = %s" % (axis, angle)) b["correction factor"] = xf.inverse() del b, pts, x_axis, y_axis, z_axis, xf system_dimensions = { # predefined dimensions in local coordinate frame # note: (0, 0) corresponds to position of C1' 'small': { ANCHOR: BASE, PURINE: ((0.0, -4.0), (2.1, 0.0)), PYRIMIDINE: ((0.0, -2.1), (2.1, 0.0)), PSEUDO_PYRIMIDINE: ((0.0, -2.1), (2.1, 0.0)), }, 'long': { ANCHOR: BASE, PURINE: ((0.0, -5.0), (2.1, 0.0)), PYRIMIDINE: ((0.0, -3.5), (2.1, 0.0)),