Пример #1
0
def run_script(session):
    from chimerax.atomic import selected_atoms
    from chimerax.build_structure import modify_atom
    from chimerax.build_structure.mod import ParamError
    from chimerax.core.errors import UserError

    sel = selected_atoms(session)
    if len(sel) != 1:
        raise UserError('Please select a single atom!')
    sel = sel[0]
    current_num_bonds = len(sel.neighbors)
    current_color = sel.color
    try:
        modify_atom(sel,
                    sel.element,
                    current_num_bonds + 1,
                    connect_back=False,
                    res_name=sel.residue.name)
        sel.color = current_color
    except ParamError as e:
        # If modify_atom throws an error at the previous step, it will have deleted
        # any attached hydrogens and not put them back. We need to put them back here.
        modify_atom(sel,
                    sel.element,
                    current_num_bonds,
                    connect_back=False,
                    res_name=sel.residue.name)
        sel.color = current_color
        raise UserError(str(e))
Пример #2
0
def add_oxt(session, residue):
    catom = residue.find_atom('C')
    resname = residue.name
    if catom is None:
        session.logger.warning('Residue {} {}{} has no C atom!'.format(
            residue.name, residue.chain_id, residue.number))
        return
    color = catom.color
    for n in catom.neighbors:
        if n.name == 'OXT':
            session.logger.warning(
                'Chain {} already has a C-terminal OXT. Skipping.')
            return
        if n.residue != residue:
            raise UserError(
                'Residue {} {}{} is not a C-terminal residue!'.format(
                    residue.name, residue.chain_id, residue.number))
    from chimerax.build_structure import modify_atom
    from chimerax.atomic import Element
    atoms = modify_atom(catom, catom.element, 3, res_name=residue.name)
    for a in atoms:
        if a.element.name == 'H':
            break
    modify_atom(a,
                Element.get_element('O'),
                1,
                name='OXT',
                res_name=residue.name)
    catom.color = color
    session.logger.info('Added a C-terminal OXT to chain {}'.format(
        residue.chain_id))
Пример #3
0
def run_script(session):
    from chimerax.atomic import selected_residues
    from chimerax.build_structure import modify_atom
    from chimerax.build_structure.mod import ParamError
    from chimerax.core.errors import UserError

    sel = selected_residues(session)
    if len(sel) != 1 or sel[0].name not in ('ASP', 'GLU'):
        raise UserError('Please select a single ASP or GLU residue!')
    sel = sel[0]
    if sel.name == 'ASP':
        pos = 'D'
    else:
        pos = 'E'
    o_atom = sel.find_atom(f'O{pos}2')
    other_o = sel.find_atom(f'O{pos}1')
    if o_atom is None or other_o is None:
        raise UserError(
            'Selected acid sidechain is missing one or both of its oxygen atoms!'
        )
    if len(o_atom.neighbors) != 1 or len(other_o.neighbors) != 1:
        raise UserError(
            'Selected acid sidechain already has a substituent on its carboxyl group!'
        )

    new_h = modify_atom(o_atom,
                        o_atom.element,
                        2,
                        connect_back=False,
                        res_name=sel.name)[1]
    new_h.color = [255, 255, 255, 255]
Пример #4
0
def break_disulfide(cys1, cys2):
    from chimerax.core.errors import UserError
    from chimerax.atomic import Atoms
    s1 = cys1.find_atom('SG')
    s2 = cys2.find_atom('SG')
    if s1 is None or s2 is None:
        raise UserError(
            'Missing SG atom! Are both residues complete cysteines?')
    if s2 not in s1.neighbors:
        raise UserError('These residues are not disulfide bonded!')
    has_hydrogens = ('H' in cys1.atoms.element_names)
    b = Atoms((s1, s2)).intra_bonds[0]
    b.delete()
    if has_hydrogens:
        from chimerax.build_structure import modify_atom
        modify_atom(s1, s1.element, 2, res_name='CYS', connect_back=False)
        modify_atom(s2, s2.element, 2, res_name='CYS', connect_back=False)
Пример #5
0
def add_missing_md_template_atoms(session, residue, md_template,
                                  residue_indices, template_indices):
    import numpy
    template_extra_indices = [
        i for i in range(len(md_template.atoms)) if i not in template_indices
    ]
    if not len(template_extra_indices):
        return
    template_extra_bonds = set([
        b for b in md_template.bonds
        if any([i in template_extra_indices for i in b])
    ])
    from collections import defaultdict
    stub_map = defaultdict(list)
    # stub_map maps an existing atom in the residue to any atoms in the MD
    # template that should be connected to it, but aren't yet modelled.
    found_bonds = set()
    for b in template_extra_bonds:
        i1, i2 = b
        i1_index = numpy.where(template_indices == i1)[0]
        i2_index = numpy.where(template_indices == i2)[0]
        if not len(i1_index) and not len(i2_index):
            continue
        if len(i2_index):
            i1, i2 = i2, i1
            i1_index = i2_index
        i1_index = i1_index[0]
        res_atom = residue.atoms[residue_indices[i1_index]]
        # if not res_atom:
        #     raise RuntimeError("Atom {} should be in residue, but isn't".format(ccd_atom.name))
        stub_map[res_atom].append(i2)
        found_bonds.add(b)
    template_extra_bonds = template_extra_bonds.difference(found_bonds)
    if len(template_extra_bonds):
        err_str = (
            'MD template {} for residue {} {}{}{} contains extra atoms that are not in '
            'a coordinate template, and are not directly connected to existing '
            'atoms. Since MD templates do not explicitly provide geometry,'
            'these atoms will not be built.').format(md_template.name,
                                                     residue.name,
                                                     residue.chain_id,
                                                     residue.number,
                                                     residue.insertion_code)
        session.logger.warning(err_str)
    seen = set()
    for new_atom_list in stub_map.values():
        for i in new_atom_list:
            if i in seen:
                err_str = (
                    'The atom {} in MD template {} bonds to more than '
                    'one existing atom in residue {}. Since MD templates do '
                    'not explicitly specify geometry, this type of atom addition '
                    'is not currently supported. The resulting residue will '
                    'contain only those atoms which the MD and coordinate templates '
                    'have in common').format(md_template.atoms[i].name,
                                             md_template.name, residue.name)
                raise UserError(err_str)
            seen.add(i)
    from chimerax.atomic import Element
    from chimerax.build_structure import modify_atom
    for existing_atom, new_indices in stub_map.items():
        num_new_atoms = len(new_indices)
        num_existing_neighbors = len(existing_atom.neighbors)
        num_bonds = len(existing_atom.neighbors) + num_new_atoms
        new_tatoms = [md_template.atoms[i] for i in new_indices]
        from chimerax.build_structure.mod import ParamError
        try:
            modified_atoms = modify_atom(existing_atom,
                                         existing_atom.element,
                                         num_bonds,
                                         res_name=residue.name)
        except ParamError:
            err_str = (
                'Failed to add atoms {} to atom {} because this will '
                'lead to having {} atoms attached, which is more than its '
                'assigned geometry can support. This is probably due to an '
                'error in the MD template ({}). If this template is built '
                'into ISOLDE, please report this using Help/Report a bug'
            ).format([a.name for a in new_tatoms], existing_atom.name,
                     num_existing_neighbors + len(new_tatoms),
                     md_template.name)
            raise UserError(err_str)
        new_atoms = modified_atoms[1:]
        for na, ta in zip(new_atoms, new_tatoms):
            modify_atom(na,
                        Element.get_element(ta.element.atomic_number),
                        1,
                        name=ta.name,
                        res_name=residue.name)