def populate_clash_table_from_geometry(self, model): ''' If no simulation is running, use ChimeraX's built-in clash toolset to find and list geometric clashes in decreasing order of overlap severity. ''' atoms = model.atoms from chimerax.clashes import clashes clash_dict = clashes.find_clashes(self.session, atoms, inter_model=False) t = self._geom_clash_table t.setRowCount(0) if not clash_dict: return from functools import reduce # Clash dict is bi-directional, so number of clashes is half the total count clash_count = 1 / 2 * reduce(lambda x, y: x + y, (len(d.keys()) for d in clash_dict.values())) t.setRowCount(clash_count) seen = set() from chimerax.atomic import Atoms # Make list of unique clashing atom pairs and their distances clash_list = [] for a1, clashes in clash_dict.items(): seen.add(a1) for a2, dist in clashes.items(): if a2 in seen: continue clash_list.append((Atoms([a1, a2]), dist)) # Sort clashes in decreasing order of overlap clash_list = sorted(clash_list, key=lambda x: x[1], reverse=True) from Qt.QtWidgets import QTableWidgetItem for i, (catoms, overlap) in enumerate(clash_list): a1, a2 = catoms r1, r2 = catoms.residues data = ("{} {}{}: {}".format(r1.name, r1.chain_id, r1.number, a1.name), "{} {}{}: {}".format(r2.name, r2.chain_id, r2.number, a2.name), "{:0.2f}".format(overlap)) for j, d in enumerate(data): item = QTableWidgetItem(d) item.data = catoms t.setItem(i, j, item) t.resizeColumnsToContents()
def populate_clash_table_from_energies(self, atoms, clashing_indices, forces): ''' When running a simulation, list atoms that are experiencing extreme forces. This is preferable, since clashes in a static molecule can lead to extremely stretched bonds on energy minimization, with no van der Waals overlap to detect. Args: * atoms: - All currently-simulated atoms, in the order they were added to the simulation * clashing_indices: - Indices of atoms experiencing excessive forces, sorted in decreasing order of force magnitude * forces: - The forces on the clashing atoms, in decreasing order * clash_table: - The table to populate with details of the clashing atoms ''' catoms = atoms[clashing_indices] t = self._energy_clash_table t.setRowCount(0) if not len(catoms): return forces /= 10 # kJ mol-1 nm-1 to kJ mol-1 A-1 residues = catoms.residues chain_ids = residues.chain_ids resnames = residues.names resnums = residues.numbers anames = catoms.names from Qt.QtWidgets import QTableWidgetItem from chimerax.atomic import Atoms t.setRowCount(len(catoms)) for i, (a, cid, rname, rnum, aname, force) in enumerate( zip(catoms, chain_ids, resnames, resnums, anames, forces)): data = (cid, "{}-{}".format(rname, rnum), aname, "{:0.3g}".format(force)) aa = Atoms([a]) for j, d in enumerate(data): item = QTableWidgetItem(d) item.data = aa t.setItem(i, j, item) t.resizeColumnsToContents()