Skip to content

Commit

Permalink
Optimized and refactored common compound code. (#3005)
Browse files Browse the repository at this point in the history
* Optimized and refactored common compound code.

Performance increased and code duplication reduced.

* Added compound-splitting performance benchmarks
  • Loading branch information
mnmelo authored Feb 13, 2021
1 parent 258a73e commit 42c5417
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 183 deletions.
56 changes: 56 additions & 0 deletions benchmarks/benchmarks/ag_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,62 @@ def time_bond(self, num_atoms):
self.ag[:2].bond


class CompoundSplitting(object):
"""Test how fast can we split compounds into masks and apply them
The benchmark used in Issue #3000. Parameterizes multiple compound number
and size combinations.
"""

params = [(100, 10000, 1000000), # n_atoms
(1, 10, 100), # n_compounds
(True, False), # homogeneous
(True, False)] # contiguous

def setup(self, n_atoms, n_compounds, homogeneous, contiguous):
rg = np.random.Generator(np.random.MT19937(3000))

# some parameter screening for nonsensical combinations.
if n_compounds > n_atoms:
raise NotImplementedError

if n_compounds == 1 and not (homogeneous and contiguous):
raise NotImplementedError

if n_compounds == n_atoms:
if not (homogeneous and contiguous):
raise NotImplementedError
compound_indices = np.arange(n_compounds)
elif homogeneous:
ats_per_compound, remainder = divmod(n_atoms, n_compounds)
if remainder:
raise NotImplementedError
compound_indices = np.tile(np.arange(n_compounds),
(ats_per_compound, 1)).T.ravel()
else:
compound_indices = np.sort(np.floor(rg.random(n_atoms)
* n_compounds).astype(np.int))

unique_indices = np.unique(compound_indices)
if len(unique_indices) != n_compounds:
raise RuntimeError

if not contiguous:
rg.shuffle(compound_indices)

self.u = MDAnalysis.Universe.empty(n_atoms,
n_residues=n_compounds,
n_segments=1,
atom_resindex=compound_indices,
trajectory=True)
self.u.atoms.positions = rg.random((n_atoms, 3),
dtype=np.float32) * 100
self.u.dimensions = [50, 50, 50, 90, 90, 90]

def time_center_compounds(self, *args):
self.u.atoms.center(None, compound='residues')


class FragmentFinding(object):
"""Test how quickly we find fragments (distinct molecules from bonds)"""
# if we try to parametrize over topology &
Expand Down
2 changes: 2 additions & 0 deletions package/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ Fixes
* Fix syntax warning over comparison of literals using is (Issue #3066)

Enhancements
* Code for operations on compounds refactored, centralized and optimized for
performance (Issue #3000)
* Added automatic selection class generation for TopologyAttrs,
FloatRangeSelection, and BoolSelection (Issues #2925, #2875; PR #2927)
* Added 'to' operator, negatives, scientific notation, and arbitrary
Expand Down
Loading

0 comments on commit 42c5417

Please sign in to comment.