Example #1
0
    def _make_histogram(self, bins=50):
        a = self.axes
        a.set_title('Crosslink lengths')
        a.set_xlabel(r'length ($\AA$)')
        a.set_ylabel('model count')

        a1, a2 = self._crosslink_atoms()
        e = self.ensemble_model
        acid = e.active_coordset_id
        cset_ids = e.coordset_ids
        from numpy import empty, float32
        d = empty((len(cset_ids), ), float32)
        from chimerax.geometry import distance
        # TODO: Optimize. Changing coordset scans all coordsets.
        #       Make routine to return coords for all coordsets for an atom?
        for i, id in enumerate(cset_ids):
            e.active_coordset_id = id
            d[i] = distance(a1.scene_coord, a2.scene_coord)
        e.active_coordset_id = acid

        n, be, self._patches = a.hist(d, bins=bins)
        self._bin_edges = be

        if bins > 0:
            # Rightmost bin edge is exactly at max data value.
            # This makes it fall outside bins in numpy.digitize().
            # Remedy this by extending the rightmost bin edge a little.
            be[bins] += 0.01 * (be[bins] - be[bins - 1])

        # Map bin to list of coordset ids.
        from numpy import digitize
        bi = digitize(d, self._bin_edges) - 1
        self._bin_coordset_ids = bcs = {}
        for i, cs in zip(bi, cset_ids):
            bcs.setdefault(i, []).append(cs)
Example #2
0
def first_volume_maxima(xyz_in, xyz_out, vlist):

    line = (xyz_in, xyz_out)  # Scene coords
    hits = []
    from chimerax.geometry import distance
    for v in vlist:
        if not v.shown():
            continue
        v_xyz_in, v_xyz_out = data_slice(v, line)
        if v_xyz_in is None:
            continue
        threshold = v.minimum_surface_level
        if threshold is None:
            if len(v.image_levels) == 0:
                return None, None
            threshold = min(lev for lev, h in v.image_levels)
        f = first_maximum_along_ray(v, v_xyz_in, v_xyz_out, threshold)
        if f is None:
            continue
        vxyz = (1 - f) * v_xyz_in + f * v_xyz_out
        sxyz = v.position * vxyz
        d = distance(sxyz, xyz_in)
        hits.append((d, sxyz, v))

    if len(hits) == 0:
        return None, None

    d, sxyz, v = min(hits, key=lambda h: h[0])
    return sxyz, v
Example #3
0
 def _picked_object(self, pick):
     warning = lambda txt: self.session.logger.status(
         "Distance mouse mode: %s" % txt, color = "red")
     message = self.session.logger.status
     from chimerax.atomic import PickedAtom, PickedPseudobond
     from chimerax.core.commands import run
     if isinstance(pick, PickedAtom):
         if self._first_atom and self._first_atom.deleted:
             self._first_atom = None
         if self._first_atom:
             if pick.atom == self._first_atom:
                 warning("same atom picked twice")
             else:
                 a1, a2 = self._first_atom, pick.atom
                 command = "dist %s %s" % (a1.string(style="command line"),
                     a2.string(style="command line"))
                 from chimerax.geometry import distance
                 message("Distance from %s to %s is %g" % (a1, a2,
                     distance(a1.scene_coord, a2.scene_coord)))
                 self._first_atom = None
                 run(self.session, command)
         else:
             self._first_atom = pick.atom
             message("Distance from %s to..." % pick.atom)
     elif isinstance(pick, PickedPseudobond):
         if pick.pbond.group.name == "distances":
             a1, a2 = pick.pbond.atoms
             command = "~dist %s %s" % (a1.string(style="command line"),
                     a2.string(style="command line"))
             message("Removing distance")
             run(self.session, command)
         else:
             warning("not a distance")
     else:
         warning("no atom/distance picked by mouse click")
Example #4
0
def volume_plane_intercept(xyz_in, xyz_out, vlist):

    line = (xyz_in, xyz_out)  # Scene coords
    hits = []
    from chimerax.geometry import distance
    for v in vlist:
        if not v.shown():
            continue
        plane = (v.single_plane() or v.showing_image('orthoplanes')
                 or v.showing_image('box faces')
                 or v.showing_image('tilted slab'))
        if not plane:
            continue
        v_xyz_in, v_xyz_out = data_slice(v, line)
        if v_xyz_in is None:
            continue
        vxyz = .5 * v_xyz_in + .5 * v_xyz_out
        sxyz = v.position * vxyz
        d = distance(sxyz, xyz_in)
        hits.append((d, sxyz, v))

    if len(hits) == 0:
        return None, None

    d, sxyz, v = min(hits, key=lambda h: h[0])
    return sxyz, v
Example #5
0
 def _label_text_and_height(self):
     from chimerax.geometry import distance
     m1, m2 = self._markers
     d = distance(m1.coord, m2.coord)
     text = '%.4g' % d
     h = max(2 * self._radius, 0.1 * d)
     return text, h
Example #6
0
    def picked_object(self,
                      win_x,
                      win_y,
                      exclude=unpickable,
                      beyond=None,
                      max_transparent_layers=3):
        '''
        Return a Pick object for the frontmost object below the given
        screen window position (specified in pixels).  This Pick object will
        have an attribute position giving the point where the intercept occurs.
        This is used when hovering the mouse over an object (e.g. an atom)
        to get a description of that object.  Beyond is minimum distance
        as fraction from front to rear clip plane.
        '''
        xyz1, xyz2 = self.clip_plane_points(win_x, win_y)
        if xyz1 is None or xyz2 is None:
            p = None
        else:
            p = self.picked_object_on_segment(
                xyz1,
                xyz2,
                exclude=exclude,
                beyond=beyond,
                max_transparent_layers=max_transparent_layers)

        # If scene clipping and some models disable clipping, try picking those.
        if self.clip_planes.have_scene_plane(
        ) and not self.drawing.all_allow_clipping():
            ucxyz1, ucxyz2 = self.clip_plane_points(
                win_x, win_y, include_scene_clipping=False)
            if ucxyz1 is not None and ucxyz2 is not None:

                def exclude_clipped(d, exclude=exclude):
                    return exclude(d) or d.allow_clipping

                ucp = self.picked_object_on_segment(
                    ucxyz1,
                    ucxyz2,
                    max_transparent_layers=max_transparent_layers,
                    exclude=exclude_clipped)
                if ucp:
                    from chimerax.geometry import distance
                    if p is None or ucp.distance * distance(
                            ucxyz1, ucxyz2) < distance(ucxyz1, xyz1):
                        p = ucp

        return p
Example #7
0
    def apply_restraints(trs, rrs, adjust_for_confidence, confidence_type):
        template_as = []
        restrained_as = []
        for tr, rr in zip(trs, rrs):
            ta_names = set(tr.atoms.names).intersection(atom_names)
            ra_names = set(rr.atoms.names).intersection(atom_names)
            common_names = list(ta_names.intersection(ra_names))
            template_as.extend([tr.find_atom(name) for name in common_names])
            restrained_as.extend([rr.find_atom(name) for name in common_names])
            # template_as.append(tr.atoms[numpy.in1d(tr.atoms.names, common_names)])
            # restrained_as.append(rr.atoms[numpy.in1d(rr.atoms.names, common_names)])
        from chimerax.atomic import Atoms
        template_as = Atoms(template_as)
        restrained_as = Atoms(restrained_as)

        template_coords = template_as.coords
        from math import sqrt
        for i, ra1 in enumerate(restrained_as):
            query_coord = numpy.array([template_coords[i]])
            indices = find_close_points(query_coord, template_coords,
                                        distance_cutoff)[1]
            indices = indices[indices != i]
            for ind in indices:
                ra2 = restrained_as[ind]
                if ra1.residue == ra2.residue:
                    continue
                if adjust_for_confidence:
                    if confidence_type == 'plddt':
                        scores = [
                            template_as[i].bfactor * confidence_multiplier,
                            template_as[ind].bfactor * confidence_multiplier
                        ]
                    elif confidence_type == 'pae':
                        scores = [
                            pae_matrix[template_as[i].residue.number - 1,
                                       template_as[ind].residue.number - 1]
                        ]
                    kappa_adj, tol_adj, falloff_adj = adjust_distance_restraint_terms_by_confidence(
                        scores, confidence_type)
                    if kappa_adj == 0:
                        continue
                else:
                    kappa_adj = tol_adj = 1
                    falloff_adj = 0
                try:
                    dr = adrm.add_restraint(ra1, ra2)
                except ValueError:
                    continue
                dist = distance(query_coord[0], template_coords[ind])
                dr.tolerance = tolerance * dist * tol_adj
                dr.target = dist
                dr.c = max(sqrt(dist) * well_half_width, 0.1)
                #dr.effective_spring_constant = spring_constant
                dr.kappa = kappa * kappa_adj
                from math import log
                dr.alpha = -1 - fall_off * log(
                    (max(dist - 1, 1))) - falloff_adj
                dr.enabled = True
Example #8
0
def vseries_measure(session, series, output = None, centroids = True,
                    color = None, radius = None):
    '''Report centroid motion of a map series.'''
    rgba = (170,170,170,255) if color is None else color.uint8x4()
    from chimerax.surface import surface_volume_and_area
    from chimerax.std_commands import measure_inertia
    meas = []
    for s in series:
        n = s.number_of_times()
        start_time = s.last_shown_time
        for t in range(n):
            if t != start_time:
                s.copy_display_parameters(start_time, t)
            s.show_time(t)
            v = s.maps[t]
            v.update_drawings()	# Compute surface.  Normally does not happen until rendered.
            level = v.minimum_surface_level
            if level is None:
                from chimerax.core.errors import UserError
                raise UserError('vseries measure (#%s) requires surface style display' % s.id_string +
                                ' since the surface threshold is used for computing centroid,' +
                                ' enclosed volume, area, and size')
            vol, area, holes = surface_volume_and_area(v)
            axes, d2, c = measure_inertia.map_inertia([v])
            elen = measure_inertia.inertia_ellipsoid_size(d2)
            meas.append((level, c, vol, area, elen))
        s.show_time(start_time)

        if centroids:
            if radius is None:
                radius = min(v.data.step)
            create_centroid_path(session, 'centroid path', tuple(m[1] for m in meas), radius, rgba)

        # Make text output
        lines = ['# Volume series measurements: %s\n' % s.name,
                 '#   n        level         x            y           z           step       distance       volume        area         inertia ellipsoid size  \n']
        d = 0
        cprev = None
        step = 0
        from chimerax.geometry import distance
        for n, (level, c, vol, area, elen) in enumerate(meas):
            if not cprev is None:
                step = distance(cprev, c)
                d += step
            cprev = c
            lines.append('%5d %12.5g %12.5g %12.5g %12.5g %12.5g %12.5g %12.5g %12.5g %12.5g %12.5g %12.5g\n' %
                         (n, level, c[0], c[1], c[2], step, d, vol, area, elen[0], elen[1], elen[2]))
        text = ''.join(lines)
        if output:
            from os import path
            path = path.expanduser(output)
            f = open(path, 'w')
            f.write(text)
            f.close()
        else:
            session.logger.info(text)
Example #9
0
    def vr_press(self, event):
        # Virtual reality hand controller button press.
        pick = event.picked_object(self.view)
        self._bond_rot = br = self._bond_rotation(pick)
        if br:
            br.bond.selected = True

        # Move the side of the bond the VR click is closest to.
        # Would like to have a command to enable this mode for rotating bonds
        # with small ligands
        move_closer_side = False
        if move_closer_side and self._bond_rot is not None:
            br = self._bond_rot
            atom1 = br.moving_side
            atom2 = br.bond.other_atom(atom1)
            p = event.tip_position
            from chimerax.geometry import distance
            if distance(p, atom2.scene_coord) < distance(p, atom1.scene_coord):
                br.moving_side = atom2
Example #10
0
def build_next_atom_from_geometry(residue, residue_anchor, template_anchor,
                                  template_new_atom):
    from chimerax.atomic import struct_edit
    from chimerax.geometry import distance, angle, dihedral
    r = residue
    m = r.structure
    tnext = template_new_atom
    if tnext is None:
        raise TypeError('Template does not contain an atom with that name!')
    tstub = template_anchor
    rstub = residue_anchor
    existing_rstub_neighbors = rstub.neighbors

    n1 = rstub
    n2 = n3 = None
    t_direct_neighbors = []
    r_direct_neighbors = []
    for a2 in tstub.neighbors:
        if a2.element.name != 'H':
            n2 = r.find_atom(a2.name)
            if n2:
                t_direct_neighbors.append(a2)
                r_direct_neighbors.append(n2)
    if len(t_direct_neighbors) > 1:
        a2, a3 = t_direct_neighbors[:2]
        n2, n3 = r_direct_neighbors[:2]
    else:
        a2 = t_direct_neighbors[0]
        n2 = r_direct_neighbors[0]
    if not n2:
        raise TypeError(
            'No n2 found - Not enough connected atoms to form a dihedral!')
    if not n3:
        for a3 in a2.neighbors:
            if a3 not in (a2, tstub) and a3.element.name != 'H':
                n3 = r.find_atom(a3.name)
                if n3:
                    break
        if not n3:
            raise TypeError(
                'No n3 found - Not enough connected atoms to form a dihedral!')

    # print('Building next atom {} from geometry of {}'.format(template_new_atom.name,
    #     ','.join([n.name for n in (n1, n2, n3)])))

    dist = distance(tnext.coord, tstub.coord)
    ang = angle(tnext.coord, tstub.coord, a2.coord)
    dihe = dihedral(tnext.coord, tstub.coord, a2.coord, a3.coord)
    # print('{}: {} {} {}'.format(next_atom_name, dist, ang, dihe))
    a = struct_edit.add_dihedral_atom(tnext.name, tnext.element, n1, n2, n3,
                                      dist, ang, dihe)

    a.occupancy = rstub.occupancy
    a.bfactor = rstub.bfactor
    return a
Example #11
0
def find_nearest(pos, atom, exclude, check_dist, avoid_metal_info=None):
    nearby = search_tree.search(pos, check_dist)
    near_pos = n = near_atom = None
    exclude_pos = set([tuple(ex._addh_coord) for ex in exclude])
    exclude_pos.add(tuple(atom._addh_coord))
    from chimerax.geometry import distance
    for nb in nearby:
        n_pos = nb._addh_coord
        if tuple(n_pos) in exclude_pos:
            # excludes identical models also...
            continue
        if nb.structure != atom.structure and (
                atom.structure.id is None or
            (len(nb.structure.id) > 1 and
             (nb.structure.id[:-1] == atom.structure.id[:-1]))
                or nb.structure in ident_pos_models[atom.structure]):
            # (1) unopen models only "clash" with themselves
            # (2) don't consider atoms in sibling submodels
            continue
        if nb not in atom.neighbors:
            if avoid_metal_info and nb.element.is_metal and nb.structure == atom.structure:
                if metal_clash(nb._addh_coord, pos, atom._addh_coord, atom,
                               avoid_metal_info):
                    return n_pos, 0.0, nb
            d = distance(n_pos, pos) - vdw_radius(nb)
            if near_pos is None or d < n:
                near_pos = n_pos
                n = d
                near_atom = nb
        # only heavy atoms in tree...
        for nbb in nb.neighbors:
            if nbb.element.number != 1:
                continue
            if tuple(nbb._addh_coord) in exclude_pos:
                continue
            n_pos = nbb._addh_coord
            d = distance(n_pos, pos) - h_rad
            if near_pos is None or d < n:
                near_pos = n_pos
                n = d
                near_atom = nbb
    return near_pos, n, near_atom
Example #12
0
def atom_motion(session, atoms, to_atoms):
    amap = {(a.residue.chain_id, a.residue.number, a.name):a for a in atoms}
    count = 0
    from chimerax.geometry import distance
    for a in to_atoms:
        a2 = amap.get((a.residue.chain_id, a.residue.number, a.name))
        if a2:
            d = distance(a.scene_coord, a2.scene_coord)
            a2.motion = a.motion = d
            count += 1
    session.logger.status('%d atom pairs' % count, log = True)
Example #13
0
def closest_slow(session, atoms, to_atoms, max_dist=10, show=False):
    '''Loop through every pair of atoms in Python.  This is slow.'''
    dmin = amin1 = amin2 = None
    from chimerax.geometry import distance
    for a1 in atoms:
        for a2 in to_atoms:
            d = distance(a1.scene_coord, a2.scene_coord)
            if (dmin is None or d < dmin) and d <= max_dist:
                dmin, amin1, amin2 = d, a1, a2
    report_closest(session, dmin, amin1, amin2, show, max_dist)
    return dmin, amin1, amin2
Example #14
0
def unique_symmetry_position(tf, center, ref_point, sym_list):

    if sym_list is None or len(sym_list) == 0:
        return tf

    from chimerax.geometry import distance
    import numpy as n
    i = n.argmin([distance(sym*tf*center, ref_point) for sym in sym_list])
    if sym_list[i].is_identity():
        return tf
    return sym_list[i]*tf
Example #15
0
def sphere_intersection(c0, r0, c1, r1):

    from chimerax.geometry import distance
    d = distance(c0, c1)
    if d > r0 + r1 or r1 + d < r0 or r0 + d < r1:
        return None
    ca = (r0 * r0 + d * d - r1 * r1) / (2 * r0 * d)
    if ca < -1 or ca > 1:
        return None
    c = (c1 - c0) / d
    return Circle(c, ca)
Example #16
0
def restrain_ca_distances_to_template(template_residues,
                                      restrained_residues,
                                      distance_cutoff=8,
                                      spring_constant=500):
    '''
    Creates a "web" of distance restraints between nearby CA atoms, restraining
    one set of residues to the same spatial organisation as another.

    Args:
        * template_residues:
            - a :class:`chimerax.atomic.Residues` instance. All residues must be
              from a single model, but need no be contiguous
        * restrained_residues:
            - a :class:`chimerax.atomic.Residues` instance. All residues must be
              from a single model (which may or may not be the same model as for
              `template_residues`). May be the same array as `template_residues`
              (which will just restrain all distances to their current values).
        * distance_cutoff (default = 8):
            - for each CA atom in `restrained_residues`, a distance restraint
              will be created between it and every other CA atom where the
              equivalent atom in `template_residues` is within `distance_cutoff`
              of its template equivalent.
        * spring_constant (default = 500):
            - the strength of each restraint, in :math:`kJ mol^{-1} nm^{-2}`
    '''
    from chimerax.isolde import session_extensions as sx
    if len(template_residues) != len(restrained_residues):
        raise TypeError(
            'Template and restrained residue arrays must be the same length!')
    template_us = template_residues.unique_structures
    if len(template_us) != 1:
        raise TypeError('Template residues must be from a single model!')
    restrained_us = restrained_residues.unique_structures
    if len(restrained_us) != 1:
        raise TypeError('Restrained residues must be from a single model!')
    restrained_model = restrained_us[0]
    template_cas = template_residues.atoms[template_residues.atoms.names ==
                                           'CA']
    restrained_cas = restrained_residues.atoms[restrained_residues.atoms.names
                                               == 'CA']
    template_coords = template_cas.coords
    drm = sx.get_distance_restraint_mgr(restrained_model)
    from chimerax.geometry import find_close_points, distance
    for i, rca1 in enumerate(restrained_cas):
        query_coord = numpy.array([template_coords[i]])
        indices = find_close_points(query_coord, template_coords,
                                    distance_cutoff)[1]
        indices = indices[indices != i]
        for ind in indices:
            rca2 = restrained_cas[ind]
            dr = drm.add_restraint(rca1, rca2)
            dr.spring_constant = spring_constant
            dr.target = distance(query_coord[0], template_coords[ind])
            dr.enabled = True
Example #17
0
    def _pick_atoms(self, pick):
        if pick is None:
            return None

        a = None
        r = None
        if hasattr(pick, 'atom'):
            a = pick.atom
            r = a.residue
        elif hasattr(pick, 'bond'):
            b = pick.bond
            coords = [a.coord for a in b.atoms]
            from chimerax.geometry import distance
            distances = [distance(c, pick.position) for c in coords]
            a = b.atoms[distances.index(min(distances))]
            r = a.residue
        elif hasattr(pick, 'residue'):
            r = pick.residue

        # Tug heavy atoms instead of hydrogens
        if a:
            if a.element.name == 'H':
                h_mode = self._tug_mgr.allow_hydrogens
                if h_mode == 'no':
                    self.session.logger.warning(
                        'Tugging of hydrogens is not enabled. '
                        'Applying tug to the nearest bonded heavy atom.')
                    a = a.neighbors[0]
                elif h_mode == 'polar':
                    for n in a.neighbors:
                        if n.element.name == 'C':
                            self.session.logger.warning(
                                'Tugging of non-polar hydrogens is not enabled. '
                                'Applying tug to the nearest bonded heavy atom.'
                            )
                            a = n
                            break
            self._focal_atom = a  #a = self._focal_atom = pick

        tm = self.tug_mode
        if tm == "atom" and a:
            from chimerax.atomic import Atoms
            pa = Atoms([a])
        elif tm == "residue" and r:
            pa = r.atoms
            if a is not None:
                self._focal_atom = a
            else:
                self._focal_atom = r.principal_atom
        else:
            pa = None

        return pa
Example #18
0
def pseudobond_connections(structures):
    pcon = {}
    from chimerax.atomic import concatenate, Atoms, interatom_pseudobonds
    from chimerax.geometry import distance
    satoms = concatenate([s.atoms for s in structures], Atoms)
    for pb in interatom_pseudobonds(satoms):
        a1, a2 = pb.atoms
        if pb.shown and pb.group.display:
            d12 = distance(a1.scene_coord, a2.scene_coord)
            pcon.setdefault(a1, []).append((a2,d12))
            pcon.setdefault(a2, []).append((a1,d12))
    return pcon
Example #19
0
def interpolate_dihedral(i0, i1, i2, i3, coords0, coords1, f, coord_set):
    """
        Computer coordinate of atom a0 by interpolating dihedral angle
        defined by atoms (a0, a1, a2, a3).
        """
    t0 = time()
    from chimerax.geometry import distance, angle, dihedral, dihedral_point
    c00 = coords0[i0]
    c01 = coords0[i1]
    c02 = coords0[i2]
    c03 = coords0[i3]
    length0 = distance(c00, c01)
    angle0 = angle(c00, c01, c02)
    dihed0 = dihedral(c00, c01, c02, c03)
    c10 = coords1[i0]
    c11 = coords1[i1]
    c12 = coords1[i2]
    c13 = coords1[i3]
    length1 = distance(c10, c11)
    angle1 = angle(c10, c11, c12)
    dihed1 = dihedral(c10, c11, c12, c13)
    length = length0 + (length1 - length0) * f
    angle = angle0 + (angle1 - angle0) * f
    ddihed = dihed1 - dihed0
    if ddihed > 180:
        ddihed -= 360
    elif ddihed < -180:
        ddihed += 360
    dihed = dihed0 + ddihed * f
    c1 = coord_set[i1, :]
    c2 = coord_set[i2, :]
    c3 = coord_set[i3, :]
    t2 = time()
    c0 = dihedral_point(c1, c2, c3, length, angle, dihed)
    t3 = time()
    coord_set[i0:] = c0
    t1 = time()
    global iit, dpt
    iit += t1 - t0
    dpt += t3 - t2
Example #20
0
def metal_clash(metal_pos, pos, parent_pos, parent_atom, parent_type_info):
    if parent_atom.element.valence < 5 and parent_type_info.geometry != linear:
        # non-sp1 carbons, et al, can't coordinate metals
        return False
    from chimerax.geometry import distance, angle
    if distance(metal_pos, pos) > 2.7:
        # "_metal_dist" is 2.7 + putative S-H bond length of 1.25;
        # see nitrogen stripping in CYS 77 and 120 in 3r24
        return False
    # 135.0 is not strict enough (see :1004.a in 1nyr)
    if angle(parent_pos, pos, metal_pos) > 120.0:
        return True
    return False
Example #21
0
def _stitched_triangles(loop1_vertices, offset1, loop2_vertices, offset2):
    triangles = []
    n1, n2 = len(loop1_vertices), len(loop2_vertices)
    i1 = i2 = 0
    from chimerax.geometry import distance
    while i1 < n1 or i2 < n2:
        v1, v2 = loop1_vertices[i1%n1], loop2_vertices[i2%n2]
        vn1, vn2 = loop1_vertices[(i1+1)%n1], loop2_vertices[(i2+1)%n2]
        if i2 == n2:
            step1 = True
        elif i1 == n1:
            step1 = False
        else:
            step1 = (distance(v2,vn1) < distance(v1,vn2))
        i3 = (offset1 + (i1+1)%n1) if step1 else (offset2 + (i2+1)%n2)
        triangles.append((offset1+i1%n1, offset2+i2%n2, i3))
        if step1:
            i1 += 1
        else:
            i2 += 1

    return triangles
Example #22
0
def get_cylinder(radius, p0, p1, bottom=True, top=True):
    h = distance(p0, p1)
    # TODO: chose number of triangles
    # TODO: separate cap into bottom and top
    vertices, normals, triangles = cylinder_geometry(radius,
                                                     height=h,
                                                     caps=bottom or top,
                                                     nc=30)
    # rotate so z-axis matches p0->p1
    xf = z_align(p0, p1)
    inverse = xf.inverse()
    vertices = inverse * (vertices + [0, 0, h / 2])
    inverse.transform_normals(normals, in_place=True, is_rotation=True)
    return vertices, normals, triangles
Example #23
0
def _file_output(file_name, info, naming_style):
    overlap_cutoff, hbond_allowance, bond_separation, intra_res, intra_mol, \
                        clashes, output_grouping, test_type, res_separation = info
    from chimerax.io import open_output
    out_file = open_output(file_name, 'utf-8')
    if test_type != "distances":
        print("Allowed overlap: %g" % overlap_cutoff, file=out_file)
        print("H-bond overlap reduction: %g" % hbond_allowance, file=out_file)
    print("Ignore %s between atoms separated by %d bonds or less" %
          (test_type, bond_separation),
          file=out_file)
    if res_separation:
        print(
            "Ignore %s between atoms in residues less than %d apart in sequence"
            % (test_type, res_separation),
            file=out_file)
    print("Detect intra-residue %s:" % test_type, intra_res, file=out_file)
    print("Detect intra-molecule %s:" % test_type, intra_mol, file=out_file)
    seen = set()
    data = []
    from chimerax.geometry import distance
    for a, aclashes in clashes.items():
        for c, val in aclashes.items():
            if (c, a) in seen:
                continue
            seen.add((a, c))
            if a in output_grouping:
                out1, out2 = a, c
            else:
                out1, out2 = c, a
            l1, l2 = out1.string(style=naming_style), out2.string(
                style=naming_style)
            data.append(
                (val, l1, l2, distance(out1.scene_coord, out2.scene_coord)))
    data.sort()
    data.reverse()
    print("\n%d %s" % (len(data), test_type), file=out_file)
    field_width1 = max([len(l1) for v, l1, l2, d in data] + [5])
    field_width2 = max([len(l2) for v, l1, l2, d in data] + [5])
    #print("%*s  %*s  overlap  distance" % (0-field_width1, "atom1", 0-field_width2, "atom2"),
    print(
        f"{'atom1':^{field_width1}}  {'atom2':^{field_width2}}  overlap  distance",
        file=out_file)
    for v, l1, l2, d in data:
        print(f"%*s  %*s   %5.3f    %5.3f" %
              (0 - field_width1, l1, 0 - field_width2, l2, v, d),
              file=out_file)
    if file_name != out_file:
        # only close file if we opened it...
        out_file.close()
Example #24
0
def _len_angle(new, n1, n2, template, bond_cache, angle_cache):
    from chimerax.geometry import distance, angle
    bond_key = (n1, new)
    angle_key = (n2, n1, new)
    try:
        bl = bond_cache[bond_key]
        ang = angle_cache[angle_key]
    except KeyError:
        n2pos = template.find_atom(n2).coord
        n1pos = template.find_atom(n1).coord
        newpos = template.find_atom(new).coord
        bond_cache[bond_key] = bl = distance(newpos, n1pos)
        angle_cache[angle_key] = ang = angle(newpos, n1pos, n2pos)
    return bl, ang
Example #25
0
def spline_path(path, grid_spacing):

    oversample = 3
    from chimerax.geometry import distance
    subdiv = max([
        int(oversample * distance(path[i + 1], path[i]) / grid_spacing)
        for i in range(len(path) - 1)
    ])
    from numpy import array
    npath = array(path)
    from chimerax.geometry import natural_cubic_spline
    points, tangents = natural_cubic_spline(npath, subdiv)
    epoints = equispaced_points(points, grid_spacing)
    return epoints
Example #26
0
def get_cone(radius, p0, p1, bottom=False, xform=None, pure=False):
    h = distance(p0, p1)
    vertices, normals, triangles = surface.cone_geometry(radius,
                                                         height=h,
                                                         caps=bottom)
    from chimerax.geometry import z_align
    xf = z_align(p0, p1)
    inverse = xf.inverse()
    vertices = inverse * (vertices + [0, 0, h / 2])
    inverse.transform_normals(normals, in_place=True, is_rotation=True)
    if xform is not None:
        xform.transform_points(vertices, in_place=True)
        xform.transform_normals(normals, in_place=True, is_rotation=pure)
    return vertices, normals, triangles
Example #27
0
def get_cylinder(radius, p0, p1, closed=True, xform=None, pure=False):
    h = distance(p0, p1)
    vertices, normals, triangles = surface.cylinder_geometry(radius,
                                                             height=h,
                                                             caps=closed)
    # rotate so z-axis matches p0->p1
    xf = z_align(p0, p1)
    inverse = xf.inverse()
    vertices = inverse * (vertices + [0, 0, h / 2])
    inverse.transform_normals(normals, in_place=True, is_rotation=True)
    if xform is not None:
        xform.transform_points(vertices, in_place=True)
        xform.transform_normals(normals, in_place=True, is_rotation=pure)
    return vertices, normals, triangles
Example #28
0
def array_slice_values(array, ijk_in, ijk_out, spacing=0.5, method='linear'):

    from chimerax.geometry import distance, place
    d = distance(ijk_in, ijk_out)
    steps = 1 + max(1, int(d / spacing))

    from numpy import empty, single as floatc, arange, outer
    trace = empty((steps, 2), floatc)
    trace[:, 0] = t = arange(steps, dtype=floatc) / steps
    ijk = outer(1 - t, ijk_in) + outer(t, ijk_out)
    from _interpolate import interpolate_volume_data
    trace[:, 1], outside = interpolate_volume_data(ijk, place.identity(),
                                                   array, method)
    return trace
Example #29
0
def donor_hyd(don, cs_id, acc_coord):
    from chimerax.geometry import distance
    dha = hyd = None
    for h in don.neighbors:
        if h.element.number != 1:
            continue
        if cs_id is None:
            h_coord = h.scene_coord
        else:
            h_coord = h.get_coordset_coord(cs_id)
        d = distance(h_coord, acc_coord)
        if dha is None or d < dha:
            dha = d
            hyd = h
    return dha, hyd
Example #30
0
def brace(atoms, max_length, max_loop_length, model, log):

    # Find all atom pairs within distance d of each other.
    apairs = []
    xyz = atoms.scene_coords
    na = len(atoms)
    for i1 in range(na):
        if log and i1 > 0 and i1 % 1000 == 0:
            log.status('Close atom pairs %d of %d atoms' % (i1, na))
        dxyz = xyz[i1+1:] - xyz[i1]
        d2 = (dxyz*dxyz).sum(axis=1)
        close = (d2 <= (max_length*max_length))
        for i2 in close.nonzero()[0]:
            apairs.append((d2[i2],i1,i1+1+i2))
    apairs.sort(key = lambda ap: ap[0])

    # Map atom index to list of connected (atom index, distance)
    sc = {}
    con, ai = connections(atoms, max_loop_length, log)
    for i1,i2,d in con:
        sc.setdefault(i1,[]).append((i2,d))
        
    # Add preexisting pseudobond connections
    for pb in model.pseudobonds:
        a1,a2 = pb.atoms
        i1,i2 = ai[a1], ai[a2]
        d = pb.length
        sc.setdefault(i1,[]).append((i2,d))
        sc.setdefault(i2,[]).append((i1,d))

    # Add connections between close atom pairs which are distantly connected.
    struts = []
    from chimerax.geometry import distance
    for c, (d12, i1, i2) in enumerate(apairs):
        if log and c > 0 and c % 1000 == 0:
            log.status('Evaluating struts %d of %d' % (c, len(apairs)))
        if not short_connection(i1, i2, max_loop_length, sc):
            struts.append((i1,i2))
            d = distance(xyz[i1], xyz[i2])
            sc.setdefault(i1,[]).append((i2,d))
            sc.setdefault(i2,[]).append((i1,d))

    # Create pseudobonds for struts
    for i1,i2 in struts:
        a1, a2 = atoms[i1], atoms[i2]
        b = model.new_pseudobond(a1, a2)
        for a in (a1, a2):
            a.display = True