def change_bond_length(self, *args): dist = self.bond_distance.value() atom_pairs = [] sel = selected_atoms(self.session) if len(sel) == 2 and sel[0].structure is sel[1].structure: atom_pairs.append(sel) for bond in selected_bonds(self.session): if not all(atom in sel for atom in bond.atoms): atom_pairs.append(bond.atoms) for bond in selected_pseudobonds(self.session): if not all(atom in sel for atom in bond.atoms): atom_pairs.append(bond.atoms) for pair in atom_pairs: atom1, atom2 = pair frag1 = get_fragment(atom1, stop=atom2, max_len=atom1.structure.num_atoms) frag2 = get_fragment(atom2, stop=atom1, max_len=atom1.structure.num_atoms) v = atom2.coord - atom1.coord cur_dist = np.linalg.norm(v) change = dist - cur_dist if self.move_fragment.currentText() == "both": change = 0.5 * change frag1.coords -= change * v / cur_dist frag2.coords += change * v / cur_dist elif self.move_fragment.currentText() == "smaller": if len(frag1) < len(frag2) or (len(frag1) == len(frag2) and sum(frag1.elements.masses) < sum(frag2.elements.masses)): frag1.coords -= change * v / cur_dist else: frag2.coords += change * v / cur_dist elif self.move_fragment.currentText() == "larger": if len(frag1) > len(frag2) or (len(frag1) == len(frag2) and sum(frag1.elements.masses) > sum(frag2.elements.masses)): frag1.coords -= change * v / cur_dist else: frag2.coords += change * v / cur_dist
def substitute(self, sub, target, *args, attached_to=None, **kwargs): if attached_to is None: from SEQCROW.selectors import get_fragment frags = [] target = self.find(target)[0] target_chix = target.chix_atom for bonded_atom in target_chix.neighbors: frags.append(get_fragment(bonded_atom, target_chix, 1000)) attached_to = None longest_frag = None for test_end, (i, frag1) in zip(target_chix.neighbors, enumerate(frags)): cyclic = False for frag2 in frags[i + 1:]: if frag1.intersects(frag2): cyclic = True break if cyclic: continue if attached_to is None or len(longest_frag) < len(frag1): longest_frag = frag1 attached_to = test_end if attached_to is not None: attached_to = self.find(AtomSpec(attached_to.atomspec))[0] return super().substitute(sub, target, *args, attached_to=attached_to, **kwargs)
def seqcrow_s(session, models=None, atoms=None): """atoms are represented with sticks atoms colored by Jmol colors""" from AaronTools.const import RADII from chimerax.atomic import AtomicStructure, Atom from chimerax.atomic.colors import element_color from SEQCROW.selectors import get_fragment if models is None or atoms is None: apply_seqcrow_s_lighting(session) if models is None: if atoms is None: models = session.models.list(type=AtomicStructure) else: models = list(set([atom.structure for atom in atoms])) elif isinstance(models, AtomicStructure): models = [models] for m in models: if atoms is None: m.ball_scale = 0.625 if atoms is None: atom_list = m.atoms else: atom_list = [atom for atom in atoms if atom.structure is m] for bond in m.bonds: if any(a in atom_list for a in bond.atoms): bond.halfbond = True bond.radius = 0.25 bond.hide = False tm_bonds = m.pseudobond_group(m.PBG_METAL_COORDINATION, create_type=None) ts_bonds = m.pseudobond_group("TS bonds", create_type=None) h_bonds = m.pseudobond_group("hydrogen bonds", create_type=None) for atom in atom_list: ele = atom.element.name color = element_color(atom.element.number) atom.color = color if not atom.neighbors: atom.draw_mode = Atom.BALL_STYLE if ele in RADII: atom.radius = RADII[ele] else: atom.draw_mode = Atom.STICK_STYLE if atom.element.name == "H": display = len(atom.neighbors) != 1 if tm_bonds: if any(atom in bond.atoms for bond in tm_bonds.pseudobonds): display = True if h_bonds: if any(atom in bond.atoms for bond in h_bonds.pseudobonds): display = True if ts_bonds: if any(atom in bond.atoms for bond in ts_bonds.pseudobonds): display = True if not display: for bonded_atom in atom.neighbors: if "C" != bonded_atom.element.name or (( bonded_atom.element.name == "C" and ( # show H's on terminal carbons that aren't RCH3's sum( len(a.neighbors) == 1 for a in bonded_atom.neighbors ) >= bonded_atom.num_bonds - 1 and not (sum( int(a.element.name == "H") for a in bonded_atom.neighbors) == 3 and len(bonded_atom.neighbors) == 4) # show H's in TS bonds or on atoms that are coordinated to a metal or (ts_bonds and any(bonded_atom in bond.atoms for bond in ts_bonds.pseudobonds)) or (tm_bonds and any(bonded_atom in bond.atoms for bond in tm_bonds.pseudobonds)))) # show H's that are on chiral carbons # this is a really lazy check and doesn't get everything or (sum( a.element. name == "H" for a in bonded_atom. neighbors ) == 1 and (len( set( sum( get_fragment( a, bonded_atom ). elements .masses ) for a in bonded_atom .neighbors ) ) == 4 # or any(a.element.name not in "CH" for a in bonded_atom.neighbors) ) and bonded_atom. num_bonds == 4)): display = True break # show H's on trigonal carbons adjacent to terminal trigonal carbons if "C" == bonded_atom.element.name and bonded_atom.num_bonds < 4: for bonded_atom2 in bonded_atom.neighbors: if bonded_atom2.element.name == "C" and (sum( len(a.neighbors) == 1 for a in bonded_atom2.neighbors ) >= bonded_atom2.num_bonds - 1 and not (sum( int(a.element.name == "H") for a in bonded_atom2.neighbors ) == 3 and len(bonded_atom2.neighbors) == 4)): display = True break atom.display = display
def mouse_up(self, event): if event.shift_down(): _ElementPicker(self.session, "pick element") return if not self.element: self.session.logger.warning( "no element selected; shift-click to set element") self.session.logger.status( "no element selected; shift-click to set element") _ElementPicker(self.session, "pick element") return x, y = event.position() pick = self.view.picked_object(x, y) if not pick: x1, x2 = self.session.main_view.clip_plane_points(x, y) coords = (x1 + x2) / 2 new_fragment = _ModelSelector(self.session, "place atom in model", coords) if new_fragment.model_selector.count() == 1: new_fragment.new_atom() return # import cProfile # # profile = cProfile.Profile() # profile.enable() vsepr = self.vsepr if vsepr == "do not change": vsepr = False elif vsepr == "linear (1 bond)": vsepr = "linear 1" goal = 1 elif vsepr == "linear (2 bonds)": vsepr = "linear 2" goal = 2 elif vsepr == "trigonal planar (2 bonds)": vsepr = "bent 2 planar" goal = 2 elif vsepr == "tetrahedral (2 bonds)": vsepr = "bent 2 tetrahedral" goal = 2 elif vsepr == "trigonal planar": goal = 3 elif vsepr == "tetrahedral (3 bonds)": vsepr = "bent 3 tetrahedral" goal = 3 elif vsepr == "tetrahedral": goal = 4 else: goal = len(Atom.get_shape(vsepr)) - 1 if not isinstance(pick, PickedAtom): return atom = pick.atom # # use built-in ChimeraX command for some of the more common things # # because it's faster for proteins # if False: # run( # self.session, # "build modify %s %s %i geometry %s" % ( # atom.atomspec, # self.element, # goal, # vsepr, # ) # ) # frags = [] for neighbor in atom.neighbors: frags.append( get_fragment(neighbor, stop=atom, max_len=atom.structure.num_atoms)) residues = [atom.residue] hold_steady = None for i, frag in enumerate(sorted(frags, key=len)): if i == len(frags) - 1: hold_steady = AtomSpec(frag[0].atomspec) residues.append(frag[0].residue) continue residues.extend(frag.residues) rescol = ResidueCollection(atom.structure, convert_residues=set(residues), refresh_ranks=False) res = [ residue for residue in rescol.residues if residue.chix_residue is atom.residue ][0] target = res.find_exact(AtomSpec(atom.atomspec))[0] adjust_hydrogens = vsepr if vsepr is not False: cur_bonds = len(target.connected) change_Hs = goal - cur_bonds adjust_hydrogens = (change_Hs, vsepr) rescol.change_element( target, self.element, adjust_bonds=True, adjust_hydrogens=adjust_hydrogens, hold_steady=hold_steady, ) res.update_chix(res.chix_residue, apply_preset=True, refresh_connected=True) rescol.update_chix(atom.structure, apply_preset=False, refresh_connected=False)
def select_pick(self, pick, set_sel): if set_sel: self.session.selection.clear() if pick: atoms = Atoms() bonds = Bonds() if not hasattr(pick, "__iter__"): pick = [pick] first_selected = None for p in pick: if isinstance(p, PickedAtoms): for atom in p.atoms: if atom in atoms: continue connected_atoms = get_fragment( atom, max_len=atom.structure.num_atoms) atoms = atoms.merge(connected_atoms) if first_selected is None: first_selected = atoms[0].selected elif isinstance(p, PickedAtom): if p.atom in atoms: continue connected_atoms = get_fragment( p.atom, max_len=p.atom.structure.num_atoms) atoms = atoms.merge(connected_atoms) if first_selected is None: first_selected = atoms[0].selected elif isinstance(p, PickedBonds): for bond in p.bonds: if bond.atoms[0] in atoms: continue connected_atoms = get_fragment( bond.atoms[0], max_len=bond.structure.num_atoms) atoms = atoms.merge(connected_atoms) if first_selected is None: first_selected = atoms[0].selected elif isinstance(p, PickedBond): if p.bond.atoms[0] in atoms: continue connected_atoms = get_fragment( p.bond.atoms[0], max_len=p.bond.structure.num_atoms) atoms = atoms.merge(connected_atoms) if first_selected is None: first_selected = atoms[0].selected elif isinstance(p, PickedResidues): for res in p.residues: for atom in res: if atom in atoms: continue connected_atoms = get_fragment( atom, max_len=res.structure.num_atoms) atoms = atoms.merge(connected_atoms) if first_selected is None: first_selected = atoms[0].selected elif isinstance(p, PickedResidue): for atom in p.residue.atoms: if atoms in atoms: continue connected_atoms = get_fragment( atom, max_len=p.residue.structure.num_atoms) atoms = atoms.merge(connected_atoms) if first_selected is None: first_selected = atoms[0].selected for atom in atoms: for neighbor, bond in zip(atom.neighbors, atom.bonds): bonds = bonds.merge(Bonds([bond])) if first_selected is not None: atoms.selected = not first_selected bonds.selected = not first_selected else: run(self.session, "select clear")