Beispiel #1
0
def zone_mask(grid_data,
              zone_points,
              zone_radius,
              invert_mask=False,
              zone_point_mask_values=None):

    from numpy import single as floatc, array, ndarray, zeros, int8, intc

    if not isinstance(zone_points, ndarray):
        zone_points = array(zone_points, floatc)

    if (not zone_point_mask_values is None
            and not isinstance(zone_point_mask_values, ndarray)):
        zone_point_mask_values = array(zone_point_mask_values, int8)

    shape = tuple(reversed(grid_data.size))
    mask_3d = zeros(shape, int8)
    mask_1d = mask_3d.ravel()

    if zone_point_mask_values is None:
        if invert_mask:
            mask_value = 0
            mask_1d[:] = 1
        else:
            mask_value = 1

    from . import grid_indices
    from chimerax.geometry import find_closest_points

    size_limit = 2**22  # 4 Mvoxels
    if mask_3d.size > size_limit:
        # Calculate plane by plane to save memory with grid point array
        xsize, ysize, zsize = grid_data.size
        grid_points = grid_indices((xsize, ysize, 1), floatc)
        grid_data.ijk_to_xyz_transform.transform_points(grid_points,
                                                        in_place=True)
        zstep = [grid_data.ijk_to_xyz_transform.matrix[a][2] for a in range(3)]
        for z in range(zsize):
            i1, i2, n1 = find_closest_points(grid_points, zone_points,
                                             zone_radius)
            offset = xsize * ysize * z
            if zone_point_mask_values is None:
                mask_1d[i1 + offset] = mask_value
            else:
                mask_1d[i1 + offset] = zone_point_mask_values[n1]
            grid_points[:, :] += zstep
    else:
        grid_points = grid_indices(grid_data.size, floatc)
        grid_data.ijk_to_xyz_transform.transform_points(grid_points,
                                                        in_place=True)
        i1, i2, n1 = find_closest_points(grid_points, zone_points, zone_radius)
        if zone_point_mask_values is None:
            mask_1d[i1] = mask_value
        else:
            mask_1d[i1] = zone_point_mask_values[n1]

    return mask_3d
Beispiel #2
0
 def vertex_to_atom_map(self, vertices=None):
     '''
     Returns a numpy array of integer values with length equal to
     the number of surface vertices and value is the atom index for
     the atom closest to each vertex.  Can return None if atoms are
     not associated with vertices.  Supplying vertices argument computes
     new vertex to atom map.
     '''
     if vertices is not None:
         xyz1 = self.vertices if vertices is None else vertices
         xyz2 = self.atom_coords()
         radii = {
             'scale2': self.atoms.radii
         } if self.resolution is None else {}
         max_dist = self._maximum_atom_to_surface_distance()
         from chimerax import geometry
         i1, i2, nearest1 = geometry.find_closest_points(
             xyz1, xyz2, max_dist, **radii)
         if len(i1) < len(xyz1):
             # TODO: For Gaussian surface should increase max_dist and try again.
             raise RuntimeError(
                 'Surface further from atoms than expected (%g) for %d of %d atoms'
                 % (max_dist, len(xyz1) - len(i1), len(xyz1)))
         from numpy import empty, int32
         v2a = empty((len(xyz1), ), int32)
         v2a[i1] = nearest1
         self._vertex_to_atom = v2a
         self._vertex_to_atom_count = len(self.atoms)
     elif self._vertex_to_atom is not None and len(
             self.atoms) < self._vertex_to_atom_count:
         # Atoms deleted
         self._vertex_to_atom = None
     return self._vertex_to_atom
Beispiel #3
0
def pick_closest_to_point(session,
                          xyz,
                          atoms,
                          cutoff,
                          displayed_only=True,
                          hydrogens=False):
    '''
    Pick the atom closest to an (x,y,z) point in scene coordinates. Optionally the
    selection can be limited to include only displayed atoms and/or
    exclude hydrogens.
    '''
    closest = None
    import numpy
    if displayed_only:
        atoms = atoms.filter(atoms.displays)
    if not hydrogens:
        atoms = atoms.filter(atoms.element_names != 'H')
    atomic_coords = atoms.scene_coords

    from chimerax.geometry import find_closest_points
    ignore1, ignore2, nearest = find_closest_points([xyz], atomic_coords,
                                                    cutoff)
    if nearest is not None:
        if len(nearest):
            return atoms[nearest[0]]
    return
Beispiel #4
0
def color_zone_sharp_edges(surface,
                           points,
                           colors,
                           distance,
                           far_color=None,
                           replace=False):
    # Transform points to surface coordinates
    surface.scene_position.inverse().transform_points(points, in_place=True)

    varray, narray, tarray = surface.vertices, surface.normals, surface.triangles
    if hasattr(surface, '_unsharp_geometry'):
        va_us, na_us, ta_us, va_sh, na_sh, ta_sh = surface._unsharp_geometry
        if varray is va_sh and narray is na_sh and tarray is ta_sh:
            varray, narray, tarray = va_us, na_us, ta_us

    from chimerax.geometry import find_closest_points
    i1, i2, n1 = find_closest_points(varray, points, distance)

    ec = _edge_cuts(varray, tarray, i1, n1, points, colors, distance)

    from numpy import empty, uint8
    carray = empty((len(varray), 4), uint8)
    carray[:, :] = (surface.color if far_color is None else far_color)
    for vi, ai in zip(i1, n1):
        carray[vi, :] = colors[ai]

    va, na, ta, ca = _cut_triangles(ec, varray, narray, tarray, carray)

    if replace:
        surface._unsharp_geometry = (varray, narray, tarray, va, na, ta)
        surface.set_geometry(va, na, ta)
        surface.vertex_colors = ca

    return va, na, ta, ca
Beispiel #5
0
    def _system_from_prmtop(self, prmtop_path, impcrd_path):
        # load in Amber input files
        prmtop = app.AmberPrmtopFile(prmtop_path)
        inpcrd = app.AmberInpcrdFile(incrd_path)
        from numpy import array, float64
        from simtk import unit
        positions = 10 * array(inpcrd.positions.value_in_unit(unit.nanometers),
                               float64)  # Angstroms
        self._particle_positions = positions

        # Ordered atoms to match inpcrd order.
        # PDB can have atoms for a chain not contiguous, e.g. chain A hetatm at end of file.
        # But inpcrd has reordered so all chain atoms are contiguous.
        atom_pos = atoms.scene_coords
        from chimerax.geometry import find_closest_points
        i1, i2, near = find_closest_points(positions, atom_pos, 1.0)
        from numpy import empty, int32
        ai = empty((len(i1), ), int32)
        ai[i1] = near
        self.atoms = oatoms = atoms[ai]
        #        diff = oatoms.scene_coords - positions
        #        print ('diff', diff.max(), diff.min())
        #        p2a = {tuple(int(x) for x in a.scene_coord):a for a in atoms}
        #        oatoms = [p2a[tuple(int(x) for x in p)] for p in positions]
        #        print('\n'.join('%s %s' %(str(a1), str(a2)) for a1,a2 in zip(atoms, oatoms)))
        #        print ('inpcrd', positions[:10])
        #        print ('atoms', atom_pos[:10])

        # prepare system and integrator
        system = prmtop.createSystem(nonbondedMethod=app.CutoffNonPeriodic,
                                     nonbondedCutoff=1.0 * unit.nanometers,
                                     constraints=app.HBonds,
                                     rigidWater=True,
                                     ewaldErrorTolerance=0.0005)
        self._system = system
Beispiel #6
0
def find_coordination_sites(model, residue_name, atom_name, coordinating=_default_coordinating_atoms, cutoff=3):
    from chimerax.geometry import find_closest_points
    import numpy
    residues = model.residues[model.residues.names==residue_name]
    atoms = residues.atoms[residues.atoms.names==atom_name]
    pairs = []
    for resname, atom_names in coordinating.items():
        crs = model.residues[model.residues.names==resname]
        catoms = crs.atoms[numpy.in1d(crs.atoms.names, atom_names)]
        i1, i2, near1 = find_closest_points(catoms.coords, atoms.coords, cutoff)
        for i, ii in zip(i1, near1):
            pairs.append([catoms[i], atoms[ii]])
    return pairs
Beispiel #7
0
def color_surface(surf, points, point_colors, distance, far_color=None):

    varray = surf.vertices
    from chimerax.geometry import find_closest_points
    i1, i2, n1 = find_closest_points(varray, points, distance)

    from numpy import empty, uint8
    rgba = empty((len(varray), 4), uint8)
    rgba[:, :] = (surf.color if far_color is None else far_color)
    for k in range(len(i1)):
        rgba[i1[k], :] = point_colors[n1[k]]

    surf.vertex_colors = rgba
    surf.coloring_zone = True
Beispiel #8
0
def closest(session, atoms, to_atoms, max_dist=10, show=False):
    xyz1, xyz2 = atoms.scene_coords, to_atoms.scene_coords
    from chimerax.geometry import find_closest_points
    i1, i2, nearest1 = find_closest_points(xyz1, xyz2, max_dist)
    if len(nearest1) == 0:
        d = a1 = a2 = None
    else:
        v = xyz2[nearest1] - xyz1[i1]
        d2 = (v * v).sum(axis=1)
        c = d2.argmin()
        c1, c2 = i1[c], nearest1[c]
        a1, a2 = atoms[c1], to_atoms[c2]
        from math import sqrt
        d = sqrt(d2[c])
    report_closest(session, d, a1, a2, show, max_dist)
    return d, a1, a2
Beispiel #9
0
def place_ligand(session,
                 ligand_id,
                 model=None,
                 position=None,
                 bfactor=None,
                 chain=None,
                 distance_cutoff=8.0,
                 sim_settle=False,
                 use_md_template=True,
                 md_template_name=None):
    '''
    Place a ligand at the given position, or the current centre of
    rotation if no :attr:`position` is specified. If the :attr:`bfactor` or
    :attr:`chain` arguments are not specified, the water will be assigned the
    missing properties based on the nearest residue within
    :attr:`distance_cutoff` of :attr:`position`, with the assigned B-factor
    being (average B-factor of nearest residue)+5. If :attr:`sim_settle` is
    True, a small local simulation will automatically start to settle the
    ligand into position.

    For residues of more than three atoms, if you have loaded an MD template for
    the residue (with matching residue name), any mis-matches between atoms in
    the CIF and MD templates will be automatically corrected as long as the
    changes only involve removing atoms from the CIF template and/or adding
    atoms that are directly connected to a single atom in the CIF template. The
    most common scenario where this arises is where the protonation state of the
    CIF template is different from that of the MD template.

    Note that at this stage no attempt is made at a preliminary fit to the
    density, or to avoid clashes: the ligand is simply placed at the given
    position with coordinates defined by the template in the Chemical
    Components Dictionary. Except for small, rigid ligands the use of
    :attr:`sim_settle`=True is inadvisable. If the ligand as placed clashes
    badly with the existing model, the best approach is to run the command
    `isolde ignore ~selAtoms` then start a simulation (which will involve *only*
    the new residue) to pull it into position (you may want to use pins where
    necessary). Once satisfied that there are no severe clashes, stop the
    simulation and run `isolde ~ignore` to reinstate all atoms for simulation
    purposes, and continue with your model building.
    '''
    from chimerax.geometry import find_closest_points
    from chimerax import mmcif
    from chimerax.core.errors import UserError
    if hasattr(session, 'isolde') and session.isolde.simulation_running:
        raise UserError('Cannot add atoms when a simulation is running!')
    if model is None:
        if hasattr(session,
                   'isolde') and session.isolde.selected_model is not None:
            model = session.isolde.selected_model
        else:
            raise UserError(
                'If model is not specified, ISOLDE must be started '
                'with a model loaded')
    if position is None:
        position = session.view.center_of_rotation
    matoms = model.atoms
    if bfactor is None or chain is None:
        _, _, i = find_closest_points([position], matoms.coords,
                                      distance_cutoff)
        if not len(i):
            err_str = (
                'No existing atoms found within the given distance cutoff '
                'of the target position. You may repeat with a larger cutoff or '
                'explicitly specify the B-factor and chain ID')
            if ligand_id == 'HOH':
                err_str += (
                    ', but keep in mind that placing waters outside of '
                    'H-bonding distance to the model is generally inadvisable.'
                )
            else:
                err_str += '.'
            raise UserError(err_str)
        na = matoms[i[0]]
        if chain is None:
            chain = na.residue.chain_id
        if bfactor is None:
            bfactor = na.residue.atoms.bfactors.mean() + 5
    tmpl = mmcif.find_template_residue(session, ligand_id)
    r = new_residue_from_template(model,
                                  tmpl,
                                  chain,
                                  position,
                                  b_factor=bfactor)
    if use_md_template and len(r.atoms) > 3:
        ff = session.isolde.forcefield_mgr[
            session.isolde.sim_params.forcefield]
        if md_template_name is None:
            from chimerax.isolde.openmm.amberff.template_utils import ccd_to_known_template
            md_template_name = ccd_to_known_template.get(ligand_id, None)
        if md_template_name is None:
            ligand_db = session.isolde.forcefield_mgr.ligand_db(
                session.isolde.sim_params.forcefield)
            from chimerax.isolde.openmm.openmm_interface import find_residue_templates
            from chimerax.atomic import Residues
            tdict = find_residue_templates(Residues([r]),
                                           ff,
                                           ligand_db=ligand_db,
                                           logger=session.logger)
            md_template_name = tdict.get(0)
        md_template = None
        if md_template_name is not None:
            md_template = ff._templates.get(md_template_name, None)

        if md_template is None:
            session.logger.warning(
                'place_ligand() was called with use_md_template=True, '
                'but no suitable template was found. This command has been ignored.'
            )
            return
        from ..template_utils import fix_residue_to_match_md_template
        fix_residue_to_match_md_template(session,
                                         r,
                                         md_template,
                                         cif_template=tmpl)

    matoms.selected = False
    r.atoms.selected = True
    if sim_settle:
        if not hasattr(session, 'isolde'):
            session.logger.warning(
                'ISOLDE is not running. sim_settle argument ignored.')
        elif model != session.isolde.selected_model:
            session.logger.warning(
                "New ligand was not added to ISOLDE's "
                "selected model. sim_settle argument ignored.")
        else:
            # defer the simulation starting until after the new atoms have been
            # drawn, to make sure their styling "sticks"
            def do_run(*_, session=session):
                from chimerax.core.commands import run
                run(session, 'isolde sim start sel')
                from chimerax.core.triggerset import DEREGISTER
                return DEREGISTER

            session.triggers.add_handler('frame drawn', do_run)
    return r