Exemplo n.º 1
0
def next_direction(direction, e, vertices, normal1, normal2):
    ev = edge_vector(e, vertices)
    from chimerax.geometry import cross_product, inner_product, normalize_vector
    en1, en2 = cross_product(ev, normal1), cross_product(ev, normal2)
    d = inner_product(direction, ev) * ev + inner_product(direction, en1) * en2
    d = normalize_vector(d)
    return d
Exemplo n.º 2
0
def extrusion_transforms(path, tangents, yaxis=None):

    from chimerax.geometry import identity, vector_rotation, translation
    tflist = []
    if yaxis is None:
        # Make xy planes for coordinate frames at each path point not rotate
        # from one point to next.
        tf = identity()
        n0 = (0, 0, 1)
        for p1, n1 in zip(path, tangents):
            tf = vector_rotation(n0, n1) * tf
            tflist.append(translation(p1) * tf)
            n0 = n1
    else:
        # Make y-axis of coordinate frames at each point align with yaxis.
        from chimerax.geometry import normalize_vector, cross_product, Place
        for p, t in zip(path, tangents):
            za = t
            xa = normalize_vector(cross_product(yaxis, za))
            ya = cross_product(za, xa)
            tf = Place(
                ((xa[0], ya[0], za[0], p[0]), (xa[1], ya[1], za[1], p[1]),
                 (xa[2], ya[2], za[2], p[2])))
            tflist.append(tf)
    return tflist
Exemplo n.º 3
0
def polygon_coordinate_frame(polygon):

    p = polygon
    c = p.center()
    za = p.normal()
    xa = p.vertices[0].coord - c
    from chimerax.geometry import normalize_vector, cross_product, Place
    ya = normalize_vector(cross_product(za, xa))
    xa = normalize_vector(cross_product(ya, za))
    tf = [(xa[a], ya[a], za[a], c[a]) for a in (0, 1, 2)]
    return Place(tf)
Exemplo n.º 4
0
def next_edge(p, direction, edges, vertices):
    from chimerax.geometry import cross_product, inner_product
    for e in edges:
        ev1, ev2 = vertices[e[0]] - p, vertices[e[1]] - p
        n = cross_product(ev1, ev2)
        tn = cross_product(direction, n)
        i1, i2 = inner_product(tn, ev1), inner_product(tn, ev2)
        if (i1 < 0 and i2 > 0) or (i1 > 0 and i2 < 0):
            # Edge is split by geodesic direction
            f = i1 / (i1 - i2)
            p2 = (1 - f) * vertices[e[0]] + f * vertices[e[1]]
            return e, f
    return None, None
Exemplo n.º 5
0
def edge_coordinate_frame(edge):

    x0, x1 = edge_alignment_points(edge)
    p = edge.polygon
    c = p.center()
    c01 = 0.5 * (x0 + x1)
    from chimerax.geometry import cross_product, normalize_vector, Place
    xa = normalize_vector(x1 - x0)
    za = normalize_vector(cross_product(xa, c01 - c))
    ya = cross_product(za, xa)
    tf = Place(((xa[0], ya[0], za[0], c01[0]), (xa[1], ya[1], za[1], c01[1]),
                (xa[2], ya[2], za[2], c01[2])))
    return tf
Exemplo n.º 6
0
 def stem_residue_orientation(self, p, next_p, pair_p):
     from chimerax.geometry import cross_product, orthonormal_frame
     from numpy import array
     x, y = next_p - p, array(pair_p) - p
     z = cross_product(x, y)
     tf = orthonormal_frame(z, xdir=x, origin=p)
     return tf
Exemplo n.º 7
0
    def scene_position_2d(self, hand_pose, view):
        # Adjust origin
        cpos = hand_pose.origin() - self._center

        # Scale millimeters to scene units
        cpos /= self._width  # millimeters to unit width

        # Rotate to screen orientation
        from chimerax.geometry import cross_product, orthonormal_frame
        yaxis = self._facing
        zaxis = cross_product(yaxis, self._cord)
        cpos = orthonormal_frame(zaxis, ydir=yaxis) * cpos

        # Convert to window pixels
        w, h = view.window_size
        win_xy = (w / 2 + w * cpos[0], h / 2 - h * cpos[1])

        # Map to scene near front clip plane.
        xyz_min, xyz_max = view.clip_plane_points(win_xy[0], win_xy[1])
        scene_point = (0, 0,
                       0) if xyz_min is None else (.9 * xyz_min + .1 * xyz_max)

        # Convert camera coordinates to scene coordinates
        rot = view.camera.position.zero_translation()
        from chimerax.geometry import translation
        scene_pos = translation(scene_point) * rot

        return scene_pos, win_xy
Exemplo n.º 8
0
    def scene_position_6d(self, hand_pose, view):
        from chimerax.geometry import translation, cross_product
        from chimerax.geometry import orthonormal_frame, inner_product

        # Adjust origin
        cpos = translation(-self._center) * hand_pose

        # Scale millimeters to scene units
        scene_center = view.center_of_rotation
        cam = view.camera
        factor = cam.view_width(scene_center) / self._width
        cpos = cpos.scale_translation(factor)  # millimeters to scene units

        # Rotate to screen orientation
        yaxis = self._facing
        zaxis = cross_product(yaxis, self._cord)
        cpos = orthonormal_frame(zaxis, ydir=yaxis) * cpos

        # Adjust depth origin to center of rotation.
        cam_pos = cam.position
        depth = inner_product(scene_center - cam_pos.origin(),
                              -cam_pos.z_axis())
        cpos = translation(
            (0, 0, -depth)) * cpos  # Center in front of camera (-z axis).

        # Convert camera coordinates to scene coordinates
        scene_pos = cam_pos * cpos  # Map from camera to scene coordinates

        return scene_pos
Exemplo n.º 9
0
def interpolate_corkscrew(xf, c0, c1, minimum_rotation = 0.1):
        '''
        Rotate and move along a circular arc perpendicular to the rotation axis and
        translate parallel the rotation axis.  This makes the initial geometric center c0
        traverse a helical path to the final center c1.  The circular arc spans an angle
        equal to the rotation angle so it is nearly a straight segment for small angles,
        and for the largest possible rotation angle of 180 degrees it is a half circle
        centered half-way between c0 and c1 in the plane perpendicular to the rotation axis.
        Rotations less than the minimum (degrees) are treated as no rotation.
        '''
        from chimerax.geometry import normalize_vector
        dc = c1 - c0
        axis, angle = xf.rotation_axis_and_angle()      # a is in degrees.
        if abs(angle) < minimum_rotation:
                # Use linear instead of corkscrew interpolation to
                # avoid numerical precision problems at small rotation angles.
                # ChimeraX bug #2928.
                center = c0
                shift = dc
        else:
                from chimerax.geometry import inner_product, cross_product, norm
                tra = inner_product(dc, axis)           # Magnitude of translation along rotation axis.
                shift = tra*axis
                vt = dc - tra * axis                    # Translation perpendicular to rotation axis.
                v0 = cross_product(axis, vt)
                if norm(v0) == 0 or angle == 0:
                        center = c0
                else:
                        import math
                        l = 0.5*norm(vt) / math.tan(math.radians(angle / 2))
                        center = c0 + 0.5*vt + l*normalize_vector(v0)

        return axis, angle, center, shift
Exemplo n.º 10
0
 def __init__(self,
              axis=(0, 1, 0),
              center=(0, 0, 0),
              angle=90,
              rock=None,
              wobble=None,
              wobble_aspect=0.3,
              wobble_axis=None,
              camera=None,
              models=None,
              atoms=None):
     self._axis = axis
     self._center = center
     self._full_angle = angle
     self._rock = rock
     self._wobble = wobble
     if wobble is not None and wobble_axis is None:
         from chimerax.geometry import cross_product, normalize_vector
         wobble_axis = normalize_vector(
             cross_product(camera.view_direction(), axis))
     self._wobble_axis = wobble_axis
     self._wobble_aspect = wobble_aspect
     self._wobble_axis = wobble_axis
     self._camera = camera
     self._models = models
     self._atoms = atoms
Exemplo n.º 11
0
def surface_path(session,
                 surface,
                 length=100,
                 rgba=(255, 255, 0, 255),
                 radius=1,
                 geodesic=True):
    ep = edge_pairs(surface.triangles)
    from random import choice
    e = choice(tuple(ep.keys()))
    #    e = first_element(ep.keys())
    vertices = surface.vertices
    if geodesic:
        tnormals = edge_triangle_normals(surface.vertices, surface.triangles)
        # Start in direction perpendicular to starting edge.
        eo = (e[1], e[0])
        ev = edge_vector(eo, vertices)
        from chimerax.geometry import cross_product, normalize_vector
        direction = normalize_vector(cross_product(tnormals[eo], ev))
    else:
        direction, tnormals = None
    points = make_surface_path(e, ep, length, vertices, direction, tnormals)
    from chimerax.markers import MarkerSet, create_link
    ms = MarkerSet(session, 'surface path')
    mprev = None
    for id, xyz in enumerate(points):
        m = ms.create_marker(xyz, rgba, radius, id)
        if mprev is not None:
            create_link(mprev, m, rgba=rgba, radius=radius)
        mprev = m
    session.models.add([ms])
Exemplo n.º 12
0
def edge_triangle_normals(vertices, triangles):
    tn = {}
    from chimerax.geometry import cross_product, normalize_vector
    for v1, v2, v3 in triangles:
        x1, x2, x3 = vertices[v1], vertices[v2], vertices[v3]
        n = normalize_vector(cross_product(x2 - x1, x3 - x1))
        tn[(v1, v2)] = tn[(v2, v3)] = tn[(v3, v1)] = n
    return tn
Exemplo n.º 13
0
def curve_segment_placement(curve, t0, t1):
    '''
    Create a Place instance mapping segment (0,0,0), (0,0,length) to
    curve points at parameter value t0 and t1.
    '''
    from chimerax.geometry import normalize_vector, cross_product, Place
    if t1 > t0:
        xyz0, xyz1 = curve.position(t0), curve.position(t1)
        x_axis = normalize_vector(xyz1 - xyz0)
        center = xyz0
    else:
        x_axis = normalize_vector(curve.velocity(t0))
        center = curve.position(t0)
    y_axis = normalize_vector(curve.normal(
        0.5 * (t0 + t1)))  # May not be normal to x_axis
    z_axis = normalize_vector(cross_product(x_axis, y_axis))
    y_axis = normalize_vector(cross_product(z_axis, x_axis))
    p = Place(axes=(x_axis, y_axis, z_axis), origin=center)
    return p
Exemplo n.º 14
0
 def _patient_axes(self):
   files = self._file_info
   if files:
     # TODO: Different files can have different orientations.
     #   For example, study 02ef8f31ea86a45cfce6eb297c274598/series-000004.
     #   These should probably be separated into different series.
     orient = files[0]._orientation
     if orient is not None:
       x_axis, y_axis = orient[0:3], orient[3:6]
       from chimerax.geometry import cross_product
       z_axis = cross_product(x_axis, y_axis)
       return (x_axis, y_axis, z_axis)
   return ((1,0,0),(0,1,0),(0,0,1))
Exemplo n.º 15
0
def rna_nucleotide_templates(session,
                             file='rna_templates_6pj6.cif',
                             chain_id='I',
                             residue_numbers={
                                 'A': 2097,
                                 'C': 2096,
                                 'G': 2193,
                                 'U': 2192
                             }):
    '''
    Return residues A,G,C,U with P at (0,0,0) and next residue P at (x,0,0) with x>0
    and rotated so that a basepaired residue P is in the xy-plane with y > 0.
    These are used for building an atomic model from a P-atom backbone trace.
    '''

    # Read template residues from mmCIF file
    from os.path import join, dirname
    path = join(dirname(__file__), file)
    from chimerax.mmcif import open_mmcif
    mols, msg = open_mmcif(session, path)
    m = mols[0]

    # Calculate transforms to standard coordinates.
    res_tf = []
    pair_name = {'A': 'U', 'U': 'A', 'G': 'C', 'C': 'G'}
    from chimerax.geometry import cross_product, orthonormal_frame
    for resname in ('A', 'C', 'G', 'U'):
        r = m.find_residue(chain_id, residue_numbers[resname])
        rnext = m.find_residue(chain_id, residue_numbers[resname] + 1)
        rpair = m.find_residue(chain_id, residue_numbers[pair_name[resname]])
        a0, a1, a2 = r.find_atom('P'), rnext.find_atom('P'), rpair.find_atom(
            'P')
        o, x, y = a0.coord, a1.coord, a2.coord
        z = cross_product(x - o, y - o)
        tf = orthonormal_frame(z, xdir=x - o, origin=o).inverse()
        res_tf.append((resname, r, tf))

    # Transform template residues to standard coordinate frame.
    res = {}
    for name, r, tf in res_tf:
        ratoms = r.atoms
        ratoms.coords = tf * ratoms.coords
        res[name] = r

    res['T'] = res['U']

    return res
Exemplo n.º 16
0
def circle_intercepts(c0, c1):

    from chimerax.geometry import inner_product, cross_product
    ca01 = inner_product(c0.center, c1.center)
    x01 = cross_product(c0.center, c1.center)
    s2 = inner_product(x01, x01)
    if s2 == 0:
        return None, None

    ca0 = c0.cos_angle
    ca1 = c1.cos_angle
    a = (ca0 - ca01 * ca1) / s2
    b = (ca1 - ca01 * ca0) / s2
    d2 = (s2 - ca0 * ca0 - ca1 * ca1 + 2 * ca01 * ca0 * ca1)
    if d2 < 0:
        return None, None
    d = sqrt(d2) / s2

    return (a * c0.center + b * c1.center - d * x01,
            a * c0.center + b * c1.center + d * x01)
Exemplo n.º 17
0
def test_phi(dp, ap, bp, phi_plane, phi):
    if phi_plane:
        normal = normalize_vector(
            cross_product(phi_plane[1] - phi_plane[0],
                          phi_plane[2] - phi_plane[1]))
        D = dot(normal, phi_plane[1])
        bproj = project(bp, normal, D)
        aproj = project(ap, normal, D)
        dproj = project(dp, normal, D)

        ang = angle(bproj, aproj, dproj)
        if ang < phi:
            if hbond.verbose:
                print("phi criteria failed (%g < %g)" % (ang, phi))
            return False
        if hbond.verbose:
            print("phi criteria OK (%g >= %g)" % (ang, phi))
    else:
        if hbond.verbose:
            print("phi criteria irrelevant")
    return True
Exemplo n.º 18
0
def moments_of_inertia(vw):

  from numpy import zeros, float, array, dot, outer, argsort, linalg, identity
  i = zeros((3,3), float)
  c = zeros((3,), float)
  w = 0
  for xyz, weights in vw:
    xyz, weights = array(xyz), array(weights)
    n = len(xyz)
    if n > 0 :
      wxyz = weights.reshape((n,1)) * xyz
      w += weights.sum()
      i += (xyz*wxyz).sum()*identity(3) - dot(xyz.transpose(),wxyz)
      c += wxyz.sum(axis = 0)

  if w == 0:
    return None, None, None      # All weights are zero.

  i /= w
  c /= w                         # Center of vertices
  i -= dot(c,c)*identity(3) - outer(c,c)

  eval, evect = linalg.eigh(i)

  # Sort by eigenvalue size.
  order = argsort(eval)
  seval = eval[order]
  sevect = evect[:,order]

  axes = sevect.transpose()
  from chimerax.geometry import inner_product, cross_product
  if inner_product(cross_product(axes[0],axes[1]),axes[2]) < 0:
    axes[2,:] = -axes[2,:]  # Make axes a right handed coordinate system

  # Make rows of 3 by 3 matrix the principle axes.
  return axes, seval, c
Exemplo n.º 19
0
def tetra_pos(bondee,
              bonded,
              bond_len,
              toward=None,
              away=None,
              toward2=None,
              away2=None):
    new_bonded = []
    cur_bonded = bonded[:]
    if len(cur_bonded) == 0:
        pos = single_pos(bondee, bond_len, toward, away)
        toward = toward2
        away = away2
        new_bonded.append(pos)
        cur_bonded.append(pos)

    if len(cur_bonded) == 1:
        # add at 109.5 degree angle
        coplanar = toward or away
        if coplanar:
            coplanar = [coplanar]
        else:
            coplanar = None
        pos = angle_pos(bondee,
                        cur_bonded[0],
                        bond_len,
                        109.5,
                        coplanar=coplanar)
        if toward or away:
            # find the other 109.5 position in the toward/away
            # plane and the closer/farther position as appropriate
            old = normalize(bondee - cur_bonded[0])
            new = pos - bondee
            midpoint = tinyarray.array(bondee + old * norm(new) * cos705)
            other_pos = pos + (midpoint - pos) * 2
            d1 = sqlength(pos - (toward or away))
            d2 = sqlength(other_pos - (toward or away))
            if toward is not None:
                if d2 < d1:
                    pos = other_pos
            elif away is not None and d2 > d1:
                pos = other_pos

        new_bonded.append(pos)
        cur_bonded.append(pos)

    if len(cur_bonded) == 2:
        # add along anti-bisector of current bonds and raised up
        # 54.75 degrees from plane of those bonds (half of 109.5)
        v1 = normalize(cur_bonded[0] - bondee)
        v2 = normalize(cur_bonded[1] - bondee)
        anti_bi = normalize(tinyarray.negative(v1 + v2))
        # in order to stabilize the third and fourth tetrahedral
        # positions, cross the longer vector by the shorter
        if sqlength(v1) > sqlength(v2):
            cross_v = normalize(cross_product(v1, v2))
        else:
            cross_v = normalize(cross_product(v2, v1))

        anti_bi = anti_bi * cos5475 * bond_len
        cross_v = cross_v * sin5475 * bond_len

        pos = bondee + anti_bi + cross_v
        if toward or away:
            other_pos = bondee + anti_bi - cross_v
            d1 = sqlength(pos - (toward or away))
            d2 = sqlength(other_pos - (toward or away))
            if toward is not None:
                if d2 < d1:
                    pos = other_pos
            elif away is not None and d2 > d1:
                pos = other_pos
        new_bonded.append(pos)
        cur_bonded.append(pos)

    if len(cur_bonded) == 3:
        unitized = []
        for cb in cur_bonded:
            v = normalize(cb - bondee)
            unitized.append(bondee + v)
        pl = Plane(unitized)
        normal = pl.normal
        # if normal on other side of plane from bondee, we need to
        # invert the normal;  the (signed) distance from bondee
        # to the plane indicates if it is on the same side
        # (positive == same side)
        d = pl.distance(bondee)
        if d < 0.0:
            normal = tinyarray.negative(normal)
        new_bonded.append(bondee + normal * bond_len)
    return new_bonded
Exemplo n.º 20
0
def triangle_normal(v0,v1,v2):

    e10, e20 = v1 - v0, v2 - v0
    from chimerax.geometry import normalize_vector, cross_product
    n = normalize_vector(cross_product(e10, e20))
    return n
Exemplo n.º 21
0
    def normal(self):

        x0, x1, x2 = [m.coord for m in self.vertices[:3]]
        from chimerax.geometry import normalize_vector, cross_product
        n = normalize_vector(cross_product(x1 - x0, x2 - x1))
        return n