def pdbBox(line): ''' Parses a gro box line and returns a pdb CRYST1 line ''' from math import degrees from chempy.cpv import length, get_angle v = [10*float(i) for i in line.split()] + 6*[0] # Padding for rectangular boxes v1, v2, v3 = (v[0], v[3], v[4]), (v[5], v[1], v[6]), (v[7], v[8], v[2]) a = length(v1) b = length(v2) c = length(v3) alpha = degrees(get_angle(v2, v3)) beta = degrees(get_angle(v1, v3)) gamma = degrees(get_angle(v1, v2)) return _pdbBoxLine % (a, b, c, alpha, beta, gamma)
def angle_between_helices(selection1, selection2, method='helix_orientation', visualize=1, quiet=0): ''' DESCRIPTION Calculates the angle between two helices USAGE angle_between_helices selection1, selection2 [, method [, visualize]] ARGUMENTS selection1 = string: atom selection of first helix selection2 = string: atom selection of second helix method = string: function to calculate orientation {default: helix_orientation} or int: 0: helix_orientation, 1: helix_orientation_hbond, 2: loop_orientation, 3: cafit_orientation visualize = 0 or 1: show fitted vector as arrow {default: 1} SEE ALSO helix_orientation, helix_orientation_hbond, loop_orientation, cafit_orientation ''' visualize, quiet = int(visualize), int(quiet) methods = { '0': helix_orientation, '1': helix_orientation_hbond, '2': loop_orientation, '3': cafit_orientation, } methods.update([(x.__name__, x) for x in methods.values()]) try: orientation = methods[str(method)] except KeyError: print 'no such method:', method raise CmdException if not quiet: print 'Using method:', orientation.__name__ cen1, dir1 = orientation(selection1, visualize, quiet=1) cen2, dir2 = orientation(selection2, visualize, quiet=1) angle = cpv.get_angle(dir1, dir2) angle_deg = math.degrees(angle) if not quiet: print 'Angle: %.2f deg' % (angle_deg) if visualize: cmd.zoom('(%s) or (%s)' % (selection1, selection2), buffer=2) return angle_deg
def helix_orientation(selection, visualize=1, sigma_cutoff=1.5, quiet=0): ''' DESCRIPTION Get the center and direction of a helix as vectors. Will only work for helices and gives slightly different results than loop_orientation. Averages direction of C(i)->O(i) bonds. USAGE helix_orientation selection [, visualize [, sigma_cutoff]] ARGUMENTS selection = string: atom selection of helix visualize = 0 or 1: show fitted vector as arrow {default: 1} sigma_cutoff = float: drop outliers outside (standard_deviation * sigma_cutoff) {default: 1.5} SEE ALSO angle_between_helices, helix_orientation_hbond, loop_orientation, cafit_orientation ''' visualize, quiet, sigma_cutoff = int(visualize), int(quiet), float( sigma_cutoff) stored.x = dict() cmd.iterate_state( STATE, '(%s) and name C+O' % (selection), 'stored.x.setdefault(chain + resi, dict())[name] = x,y,z') vec_list = [] count = 0 for x in stored.x.itervalues(): if 'C' in x and 'O' in x: vec_list.append(cpv.sub(x['O'], x['C'])) count += 1 if count == 0: print 'warning: count == 0' raise CmdException vec = _vec_sum(vec_list) if count > 2 and sigma_cutoff > 0: angle_list = [cpv.get_angle(vec, x) for x in vec_list] angle_mu, angle_sigma = _mean_and_std(angle_list) vec_list = [ vec_list[i] for i in range(len(vec_list)) if abs(angle_list[i] - angle_mu) < angle_sigma * sigma_cutoff ] if not quiet: print 'Dropping %d outlier(s)' % (len(angle_list) - len(vec_list)) vec = _vec_sum(vec_list) vec = cpv.normalize(vec) return _common_orientation(selection, vec, visualize, quiet)
def helix_orientation(selection, visualize=1, sigma_cutoff=1.5, quiet=0): """ DESCRIPTION Get the center and direction of a helix as vectors. Will only work for helices and gives slightly different results than loop_orientation. Averages direction of C(i)->O(i) bonds. USAGE helix_orientation selection [, visualize [, sigma_cutoff]] ARGUMENTS selection = string: atom selection of helix visualize = 0 or 1: show fitted vector as arrow {default: 1} sigma_cutoff = float: drop outliers outside (standard_deviation * sigma_cutoff) {default: 1.5} SEE ALSO angle_between_helices, helix_orientation_hbond, loop_orientation, cafit_orientation """ visualize, quiet, sigma_cutoff = int(visualize), int(quiet), float(sigma_cutoff) stored.x = dict() cmd.iterate_state( STATE, "(%s) and name C+O" % (selection), "stored.x.setdefault(chain + resi, dict())[name] = x,y,z" ) vec_list = [] count = 0 for x in stored.x.values(): if "C" in x and "O" in x: vec_list.append(cpv.sub(x["O"], x["C"])) count += 1 if count == 0: print("warning: count == 0") raise CmdException vec = _vec_sum(vec_list) if count > 2 and sigma_cutoff > 0: angle_list = [cpv.get_angle(vec, x) for x in vec_list] angle_mu, angle_sigma = _mean_and_std(angle_list) vec_list = [ vec_list[i] for i in range(len(vec_list)) if abs(angle_list[i] - angle_mu) < angle_sigma * sigma_cutoff ] if not quiet: print("Dropping %d outlier(s)" % (len(angle_list) - len(vec_list))) vec = _vec_sum(vec_list) vec = cpv.normalize(vec) return _common_orientation(selection, vec, visualize, quiet)
def angle_between_helices(selection1, selection2, method="helix_orientation", visualize=1, quiet=0): """ DESCRIPTION Calculates the angle between two helices USAGE angle_between_helices selection1, selection2 [, method [, visualize]] ARGUMENTS selection1 = string: atom selection of first helix selection2 = string: atom selection of second helix method = string: function to calculate orientation {default: helix_orientation} or int: 0: helix_orientation, 1: helix_orientation_hbond, 2: loop_orientation, 3: cafit_orientation visualize = 0 or 1: show fitted vector as arrow {default: 1} SEE ALSO helix_orientation, helix_orientation_hbond, loop_orientation, cafit_orientation """ visualize, quiet = int(visualize), int(quiet) methods = {"0": helix_orientation, "1": helix_orientation_hbond, "2": loop_orientation, "3": cafit_orientation} methods.update([(x.__name__, x) for x in list(methods.values())]) try: orientation = methods[str(method)] except KeyError: print("no such method: " + str(method)) raise CmdException if not quiet: print("Using method: " + orientation.__name__) cen1, dir1 = orientation(selection1, visualize, quiet=1) cen2, dir2 = orientation(selection2, visualize, quiet=1) angle = cpv.get_angle(dir1, dir2) angle_deg = math.degrees(angle) if not quiet: print("Angle: %.2f deg" % (angle_deg)) if visualize: cmd.zoom("(%s) or (%s)" % (selection1, selection2), buffer=2) return angle_deg
def angle_between_helices(selection1, selection2, method='helix', state1=STATE, state2=STATE, visualize=1, quiet=1): ''' DESCRIPTION Calculates the angle between two helices USAGE angle_between_helices selection1, selection2 [, method [, visualize]] ARGUMENTS selection1 = string: atom selection of first helix selection2 = string: atom selection of second helix method = string: function to calculate orientation {default: helix_orientation} visualize = 0 or 1: show fitted vector as arrow {default: 1} EXAMPLE fetch 2x19, async=0 select hel1, /2x19//B/23-36/ select hel2, /2x19//B/40-54/ angle_between_helices hel1, hel2 angle_between_helices hel1, hel2, cafit SEE ALSO helix_orientation, loop_orientation, cafit_orientation, angle_between_domains ''' import math state1, state2 = int(state1), int(state2) visualize, quiet = int(visualize), int(quiet) try: orientation = globals()[methods_sc[str(method)]] except KeyError: print 'no such method:', method raise CmdException if not int(quiet): print ' Using method:', orientation.__name__ cen1, dir1 = orientation(selection1, state1, visualize, quiet=1) cen2, dir2 = orientation(selection2, state2, visualize, quiet=1) angle = cpv.get_angle(dir1, dir2) angle = math.degrees(angle) if not quiet: print ' Angle: %.2f deg' % (angle) if visualize: # measurement object for angle center = cpv.scale(cpv.add(cen1, cen2), 0.5) tmp = get_unused_name('_') for pos in [center, cpv.add(center, cpv.scale(dir1, 5.0)), cpv.add(center, cpv.scale(dir2, 5.0))]: cmd.pseudoatom(tmp, pos=list(pos), state=1) name = get_unused_name('angle') cmd.angle(name, *[(tmp, i) for i in [2,1,3]]) cmd.delete(tmp) cmd.zoom('(%s) or (%s)' % (selection1, selection2), 2, state1 if state1 == state2 else 0) return angle
def torus(center=(0., 0., 0.), normal=(0., 0., 1.), radius=1., color='', cradius=.25, samples=20, csamples=20): ''' Generate and return a torus CGO with given center, normal and ring radius. ''' from math import cos, sin, pi if color and isinstance(color, str): color = list(cmd.get_color_tuple(color)) obj = [] axis = cpv.cross_product(normal, (0., 0., 1.)) angle = -cpv.get_angle(normal, (0., 0., 1.)) matrix = cpv.rotation_matrix(angle, cpv.normalize(axis)) obj_vertex = lambda x, y, z: obj.extend([VERTEX] + cpv.add(center, cpv.transform(matrix, [x, y, z]))) obj_normal = lambda x, y, z: obj.extend([NORMAL] + cpv.transform(matrix, [x, y, z])) r = radius cr = cradius rr = 1.5 * cr dv = 2 * pi / csamples dw = 2 * pi / samples v = 0.0 w = 0.0 while w < 2 * pi: v = 0.0 c_w = cos(w) s_w = sin(w) c_wdw = cos(w + dw) s_wdw = sin(w + dw) obj.append(BEGIN) obj.append(TRIANGLE_STRIP) if color: obj.append(COLOR) obj.extend(color) while v < 2 * pi + dv: c_v = cos(v) s_v = sin(v) c_vdv = cos(v + dv) s_vdv = sin(v + dv) obj_normal( (r + rr * c_v) * c_w - (r + cr * c_v) * c_w, (r + rr * c_v) * s_w - (r + cr * c_v) * s_w, (rr * s_v - cr * s_v)) obj_vertex( (r + cr * c_v) * c_w, (r + cr * c_v) * s_w, cr * s_v) obj_normal( (r + rr * c_vdv) * c_wdw - (r + cr * c_vdv) * c_wdw, (r + rr * c_vdv) * s_wdw - (r + cr * c_vdv) * s_wdw, rr * s_vdv - cr * s_vdv) obj_vertex( (r + cr * c_vdv) * c_wdw, (r + cr * c_vdv) * s_wdw, cr * s_vdv) v += dv obj.append(END) w += dw return obj
def angle_between_helices(selection1, selection2, method='helix', state1=STATE, state2=STATE, visualize=1, quiet=1): ''' DESCRIPTION Calculates the angle between two helices USAGE angle_between_helices selection1, selection2 [, method [, visualize]] ARGUMENTS selection1 = string: atom selection of first helix selection2 = string: atom selection of second helix method = string: function to calculate orientation {default: helix_orientation} visualize = 0 or 1: show fitted vector as arrow {default: 1} EXAMPLE fetch 2x19, bsync=0 select hel1, /2x19//B/23-36/ select hel2, /2x19//B/40-54/ angle_between_helices hel1, hel2 angle_between_helices hel1, hel2, cafit SEE ALSO helix_orientation, loop_orientation, cafit_orientation, angle_between_domains ''' import math state1, state2 = int(state1), int(state2) visualize, quiet = int(visualize), int(quiet) try: orientation = globals()[methods_sc[str(method)]] except KeyError: print('no such method:', method) raise CmdException if not int(quiet): print(' Using method:', orientation.__name__) cen1, dir1 = orientation(selection1, state1, visualize, quiet=1) cen2, dir2 = orientation(selection2, state2, visualize, quiet=1) angle = cpv.get_angle(dir1, dir2) angle = math.degrees(angle) if not quiet: print(' Angle: %.2f deg' % (angle)) if visualize: # measurement object for angle center = cpv.scale(cpv.add(cen1, cen2), 0.5) tmp = get_unused_name('_') for pos in [ center, cpv.add(center, cpv.scale(dir1, 5.0)), cpv.add(center, cpv.scale(dir2, 5.0)) ]: cmd.pseudoatom(tmp, pos=list(pos), state=1) name = get_unused_name('angle') cmd.angle(name, *[(tmp, i) for i in [2, 1, 3]]) cmd.delete(tmp) cmd.zoom('(%s) or (%s)' % (selection1, selection2), 2, state1 if state1 == state2 else 0) return angle
def torus(center=(0., 0., 0.), normal=(0., 0., 1.), radius=1., color='', cradius=.25, samples=20, csamples=20, _self=cmd): ''' Generate and return a torus CGO with given center, normal and ring radius. ''' from math import cos, sin, pi if color and isinstance(color, str): color = list(_self.get_color_tuple(color)) obj = [] axis = cpv.cross_product(normal, (0., 0., 1.)) angle = -cpv.get_angle(normal, (0., 0., 1.)) matrix = cpv.rotation_matrix(angle, cpv.normalize(axis)) obj_vertex = lambda x, y, z: obj.extend([VERTEX] + cpv.add(center, cpv.transform(matrix, [x, y, z]))) obj_normal = lambda x, y, z: obj.extend([NORMAL] + cpv.transform(matrix, [x, y, z])) r = radius cr = cradius rr = 1.5 * cr dv = 2 * pi / csamples dw = 2 * pi / samples v = 0.0 w = 0.0 while w < 2 * pi: v = 0.0 c_w = cos(w) s_w = sin(w) c_wdw = cos(w + dw) s_wdw = sin(w + dw) obj.append(BEGIN) obj.append(TRIANGLE_STRIP) if color: obj.append(COLOR) obj.extend(color) while v < 2 * pi + dv: c_v = cos(v) s_v = sin(v) c_vdv = cos(v + dv) s_vdv = sin(v + dv) obj_normal( (r + rr * c_v) * c_w - (r + cr * c_v) * c_w, (r + rr * c_v) * s_w - (r + cr * c_v) * s_w, (rr * s_v - cr * s_v)) obj_vertex( (r + cr * c_v) * c_w, (r + cr * c_v) * s_w, cr * s_v) obj_normal( (r + rr * c_vdv) * c_wdw - (r + cr * c_vdv) * c_wdw, (r + rr * c_vdv) * s_wdw - (r + cr * c_vdv) * s_wdw, rr * s_vdv - cr * s_vdv) obj_vertex( (r + cr * c_vdv) * c_wdw, (r + cr * c_vdv) * s_wdw, cr * s_vdv) v += dv obj.append(END) w += dw return obj
def rebuild(self) -> None: """ Rebuilds torus """ obj = [] axis = cpv.cross_product(self.normal.array(), (0., 0., 1.)) angle = -cpv.get_angle(self.normal.array(), (0., 0., 1.)) matrix = cpv.rotation_matrix(angle, cpv.normalize(axis)) def obj_vertex(x, y, z): return [cgo.VERTEX] + cpv.add(self.center.array(), cpv.transform(matrix, [x, y, z])) def obj_normal(x, y, z): return [cgo.NORMAL] + cpv.transform(matrix, [x, y, z]) r = self.radius cr = self.cradius rr = 1.5 * cr dv = 2 * math.pi / self.csamples dw = 2 * math.pi / self.samples v = 0.0 w = 0.0 while w < 2 * math.pi: v = 0.0 c_w = math.cos(w) s_w = math.sin(w) c_wdw = math.cos(w + dw) s_wdw = math.sin(w + dw) obj.append(cgo.BEGIN) obj.append(cgo.TRIANGLE_STRIP) obj.append(cgo.COLOR) obj.extend(self.color.array()) while v < 2 * math.pi + dv: c_v = math.cos(v) s_v = math.sin(v) c_vdv = math.cos(v + dv) s_vdv = math.sin(v + dv) obj.extend( obj_normal((r + rr * c_v) * c_w - (r + cr * c_v) * c_w, (r + rr * c_v) * s_w - (r + cr * c_v) * s_w, (rr * s_v - cr * s_v))) obj.extend( obj_vertex((r + cr * c_v) * c_w, (r + cr * c_v) * s_w, cr * s_v)) obj.extend( obj_normal( (r + rr * c_vdv) * c_wdw - (r + cr * c_vdv) * c_wdw, (r + rr * c_vdv) * s_wdw - (r + cr * c_vdv) * s_wdw, rr * s_vdv - cr * s_vdv)) obj.extend( obj_vertex((r + cr * c_vdv) * c_wdw, (r + cr * c_vdv) * s_wdw, cr * s_vdv)) v += dv obj.append(cgo.END) w += dw self._data = obj