diff options
author | Bruce Smith <bruce@nanorex.com> | 2008-04-11 18:06:16 +0000 |
---|---|---|
committer | Bruce Smith <bruce@nanorex.com> | 2008-04-11 18:06:16 +0000 |
commit | 3f76ff1c7c6778d0f8f6faa67492ea31d2a3fd3b (patch) | |
tree | fefcde711c3bada4a45d98d6c690242036954193 | |
parent | 0f66720dc7592e697b0246deb3b5551a198d4c93 (diff) | |
download | nanoengineer-3f76ff1c7c6778d0f8f6faa67492ea31d2a3fd3b.tar.gz nanoengineer-3f76ff1c7c6778d0f8f6faa67492ea31d2a3fd3b.zip |
move NeighborhoodGenerator from bonds.py into its own module
-rwxr-xr-x | cad/src/commands/InsertNanotube/NanotubeGenerator.py | 2 | ||||
-rwxr-xr-x | cad/src/commands/InsertPeptide/PeptideGenerator.py | 2 | ||||
-rw-r--r-- | cad/src/geometry/NeighborhoodGenerator.py | 115 | ||||
-rwxr-xr-x | cad/src/model/bonds.py | 93 | ||||
-rwxr-xr-x | cad/src/operations/bonds_from_atoms.py | 3 | ||||
-rwxr-xr-x | cad/src/scratch/buckyball.py | 3 |
6 files changed, 121 insertions, 97 deletions
diff --git a/cad/src/commands/InsertNanotube/NanotubeGenerator.py b/cad/src/commands/InsertNanotube/NanotubeGenerator.py index 3a1ae1400..75aa1ea6c 100755 --- a/cad/src/commands/InsertNanotube/NanotubeGenerator.py +++ b/cad/src/commands/InsertNanotube/NanotubeGenerator.py @@ -25,7 +25,7 @@ from model.chunk import Chunk from model.elements import PeriodicTable from model.bonds import bond_atoms -from model.bonds import NeighborhoodGenerator +from geometry.NeighborhoodGenerator import NeighborhoodGenerator from model.bond_constants import V_GRAPHITE, V_SINGLE ##from bonds_from_atoms import make_bonds diff --git a/cad/src/commands/InsertPeptide/PeptideGenerator.py b/cad/src/commands/InsertPeptide/PeptideGenerator.py index 22a8b705f..72c0b35d4 100755 --- a/cad/src/commands/InsertPeptide/PeptideGenerator.py +++ b/cad/src/commands/InsertPeptide/PeptideGenerator.py @@ -25,7 +25,7 @@ from model.chem import Atom from model.chunk import Chunk from model.bonds import bond_atoms -from model.bonds import NeighborhoodGenerator +from geometry.NeighborhoodGenerator import NeighborhoodGenerator from model.bond_constants import atoms_are_bonded from model.bond_constants import V_SINGLE, V_DOUBLE, V_AROMATIC from operations.bonds_from_atoms import inferBonds diff --git a/cad/src/geometry/NeighborhoodGenerator.py b/cad/src/geometry/NeighborhoodGenerator.py new file mode 100644 index 000000000..6af7526c4 --- /dev/null +++ b/cad/src/geometry/NeighborhoodGenerator.py @@ -0,0 +1,115 @@ +# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details. +""" +NeighborhoodGenerator.py -- linear time way to find overlapping or nearby atoms. + +@author: Will +@version: $Id$ +@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details. + +History: + +Will wrote this in bonds.py for use in bond inference. + +Bruce 080411 moved it into its own module, classifying it +as geometry (i.e. moving it into that source package) +since it's essentially purely geometric (and could easily +be generalized to be entirely so) -- all it assumes about +"atoms" is that they have a few methods like .posn() +and .is_singlet(), and it needs no imports from model. +""" + +import struct + +from Numeric import floor + +from geometry.VQT import vlen + +# == + + +# This is an order(N) operation that produces a function which gets a +# list of potential neighbors in order(1) time. This is handy for +# inferring bonds for PDB files that lack any bonding information. +class NeighborhoodGenerator: + """ + Given a list of atoms and a radius, be able to quickly take a + point and generate a neighborhood, which is a list of the atoms + within that radius of the point. + + Reading in the list of atoms is done in O(n) time, where n is the + number of atoms in the list. Generating a neighborhood around a + point is done in O(1) time. So this is a pretty efficient method + for finding neighborhoods, especially if the same generator can + be used many times. + """ + def __init__(self, atomlist, maxradius, include_singlets = False): + self._buckets = { } + self._oldkeys = { } + self._maxradius = 1.0 * maxradius + self.include_singlets = include_singlets + for atom in atomlist: + self.add(atom) + + def _quantize(self, vec): + """ + Given a point in space, partition space into little cubes + so that when the time comes, it will be quick to locate and + search the cubes right around a point. + """ + maxradius = self._maxradius + return (int(floor(vec[0] / maxradius)), + int(floor(vec[1] / maxradius)), + int(floor(vec[2] / maxradius))) + + def add(self, atom, _pack = struct.pack): + buckets = self._buckets + if self.include_singlets or not atom.is_singlet(): + # The keys of the _buckets dictionary are 12-byte strings. + # Comparing them when doing lookups should be quicker than + # comparisons between tuples of integers, so dictionary + # lookups will go faster. + i, j, k = self._quantize(atom.posn()) + key = _pack('lll', i, j, k) + buckets.setdefault(key, []).append(atom) + self._oldkeys[atom.key] = key + + def atom_moved(self, atom): + """ + If an atom has been added to a neighborhood generator and + is later moved, this method must be called to refresh the + generator's position information. This only needs to be done + during the useful lifecycle of the generator. + """ + oldkey = self._oldkeys[atom.key] + self._buckets[oldkey].remove(atom) + self.add(atom) + + def region(self, center, _pack = struct.pack): + """ + Given a position in space, return the list of atoms that + are within the neighborhood radius of that position. + """ + buckets = self._buckets + def closeEnough(atm, radius = self._maxradius): + return vlen(atm.posn() - center) < radius + lst = [ ] + x0, y0, z0 = self._quantize(center) + for x in range(x0 - 1, x0 + 2): + for y in range(y0 - 1, y0 + 2): + for z in range(z0 - 1, z0 + 2): + # keys are 12-byte strings, see rationale above + key = _pack('lll', x, y, z) + if buckets.has_key(key): + lst += filter(closeEnough, buckets[key]) + return lst + + def remove(self, atom): + key = self._quantize(atom.posn()) + try: + self._buckets[key].remove(atom) + except: + pass + + pass # end of class NeighborhoodGenerator + +# end diff --git a/cad/src/model/bonds.py b/cad/src/model/bonds.py index 3f6238fde..3ca4800f0 100755 --- a/cad/src/model/bonds.py +++ b/cad/src/model/bonds.py @@ -30,9 +30,6 @@ History: debug_1951 = False # DO NOT COMMIT with True -import struct -from Numeric import floor - from geometry.VQT import Q, vlen, norm from utilities.debug import print_compact_stack, compact_stack, print_compact_traceback @@ -471,96 +468,6 @@ def bond_direction(atom1, atom2): #bruce 070601 assert bond, "the atoms %s and %s must be bonded" % (atom1, atom2) return bond.bond_direction_from(atom1) -# This is an order(N) operation that produces a function which gets a -# list of potential neighbors in order(1) time. This is handy for -# inferring bonds for PDB files that lack any bonding information. -class NeighborhoodGenerator: - """ - Given a list of atoms and a radius, be able to quickly take a - point and generate a neighborhood, which is a list of the atoms - within that radius of the point. - - Reading in the list of atoms is done in O(n) time, where n is the - number of atoms in the list. Generating a neighborhood around a - point is done in O(1) time. So this is a pretty efficient method - for finding neighborhoods, especially if the same generator can - be used many times. - """ - # REVIEW: should this class be moved into its own module? - # (Note, it's *almost* purely geometry... it might make sense - # to file it there even though it assumes added objects - # act like class Atom instances.) - # [bruce 071030/080122 comment] - def __init__(self, atomlist, maxradius, include_singlets = False): - self._buckets = { } - self._oldkeys = { } - self._maxradius = 1.0 * maxradius - self.include_singlets = include_singlets - for atom in atomlist: - self.add(atom) - - def _quantize(self, vec): - """ - Given a point in space, partition space into little cubes - so that when the time comes, it will be quick to locate and - search the cubes right around a point. - """ - maxradius = self._maxradius - return (int(floor(vec[0] / maxradius)), - int(floor(vec[1] / maxradius)), - int(floor(vec[2] / maxradius))) - - def add(self, atom, _pack=struct.pack): - buckets = self._buckets - if self.include_singlets or not atom.is_singlet(): - # The keys of the _buckets dictionary are 12-byte strings. - # Comparing them when doing lookups should be quicker than - # comparisons between tuples of integers, so dictionary - # lookups will go faster. - i, j, k = self._quantize(atom.posn()) - key = _pack('lll', i, j, k) - buckets.setdefault(key, []).append(atom) - self._oldkeys[atom.key] = key - - def atom_moved(self, atom): - """ - If an atom has been added to a neighborhood generator and - is later moved, this method must be called to refresh the - generator's position information. This only needs to be done - during the useful lifecycle of the generator. - """ - oldkey = self._oldkeys[atom.key] - self._buckets[oldkey].remove(atom) - self.add(atom) - - def region(self, center, _pack=struct.pack): - """ - Given a position in space, return the list of atoms that - are within the neighborhood radius of that position. - """ - buckets = self._buckets - def closeEnough(atm, radius=self._maxradius): - return vlen(atm.posn() - center) < radius - lst = [ ] - x0, y0, z0 = self._quantize(center) - for x in range(x0 - 1, x0 + 2): - for y in range(y0 - 1, y0 + 2): - for z in range(z0 - 1, z0 + 2): - # keys are 12-byte strings, see rationale above - key = _pack('lll', x, y, z) - if buckets.has_key(key): - lst += filter(closeEnough, buckets[key]) - return lst - - def remove(self, atom): - key = self._quantize(atom.posn()) - try: - self._buckets[key].remove(atom) - except: - pass - - pass # end of class NeighborhoodGenerator - # == _changed_Bonds = {} # tracks all changes to Bonds: existence/liveness (maybe not needed), which atoms, bond order diff --git a/cad/src/operations/bonds_from_atoms.py b/cad/src/operations/bonds_from_atoms.py index 1808efb13..f5595d8d3 100755 --- a/cad/src/operations/bonds_from_atoms.py +++ b/cad/src/operations/bonds_from_atoms.py @@ -38,7 +38,8 @@ from geometry.VQT import atom_angle_radians import foundation.env as env -from model.bonds import bond_atoms_faster, NeighborhoodGenerator +from model.bonds import bond_atoms_faster +from geometry.NeighborhoodGenerator import NeighborhoodGenerator from model.bond_constants import atoms_are_bonded # was: from bonds import bonded from model.bond_constants import V_SINGLE diff --git a/cad/src/scratch/buckyball.py b/cad/src/scratch/buckyball.py index b10aee46d..e99118ab4 100755 --- a/cad/src/scratch/buckyball.py +++ b/cad/src/scratch/buckyball.py @@ -38,7 +38,8 @@ __author__ = "Will" from math import sin, cos, pi, floor from geometry.VQT import V, vlen -from model.bonds import NeighborhoodGenerator, bond_atoms, CC_GRAPHITIC_BONDLENGTH +from geometry.NeighborhoodGenerator import NeighborhoodGenerator +from model.bonds import bond_atoms, CC_GRAPHITIC_BONDLENGTH from model.bond_constants import V_GRAPHITE from model.chem import Atom |