﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc	blockedby	blocking	notify_on_close	platform	project
5143	Avoid recalculating idatm_types for entire model after changes?	Tristan Croll	Eric Pettersen	"When working on large models (particularly those with lots of rings on them), any change that triggers recalculation of `idatm_type` information can get unexpectedly slow (up to tens of seconds in the worst cases) because the types are always recalculated for the entire model. Since only bonded interactions are considered in the atom typing algorithm, this could be improved by only recalculating types for the connected fragments affected by the change. The following snippet uses `python-igraph` to partition a model into individual connected components. Running time for typical systems is pretty trivial, but gets a bit more substantial for larger ones (for all cases below, hydrogens have first been added with `addh`):

7lqi (800 residues, 16300 atoms, 99 connected groups): 0.034 seconds
4x2u (2156 residues, 18243 atoms, 1243 connected groups): 0.048 seconds
3mgg (1119 residues, 22111 atoms, 26 connected groups): 0.050 seconds
4wsa (2207 residues, 35755 atoms, 7 connected groups): 0.070 seconds
7cow (2405 residues, 49777 atoms, 34 connected groups): 0.089 seconds
7b9v (12878 residues, 211756 atoms, 136 connected groups): 0.309 seconds
7miz (27288 residues, 423137 atoms, 186 connected groups): 0.630 seconds
3j3q (313236 residues, 4884334 atoms, 1355 connected groups): 6.643 seconds

Seems like it would be fairly straightforward from here to identify the fragments affected by changes (find the group for added/changed atoms, or those that are/were attached to added or deleted atoms or bonds). Or am I missing something critical?


```
def connected_components_igraph(model, include_metal_pseudobonds=True):
    '''
    Returns two arrays:
      - the model atoms
      - a list of integers of the same length as the atom list, where the value at index i
        indicates the connected group to which atom i belongs.
    '''
    import igraph
    import numpy
    g = igraph.Graph()
    atoms = model.atoms
    bonds = model.bonds
    bi = [atoms.indices(ba) for ba in bonds.atoms]
    edges = numpy.array(bi).T
    g.add_vertices(range(len(atoms)))
    g.add_edges(edges)
    if include_metal_pseudobonds:
        pbg = model.pseudobond_group(model.PBG_METAL_COORDINATION, create_type=None)
        if pbg is not None:
            pb = pbg.pseudobonds
            if len(pb):
                pba = pb.atoms
                pi = [atoms.indices(ba) for ba in pba]
                edges = numpy.array(pi).T
                g.add_edges(edges)
    components = g.components()
    membership = numpy.array(components.membership)
    return atoms, membership
```
"	enhancement	closed	major		Structure Editing		wontfix						all	ChimeraX
