This file is indexed.

/usr/share/pyshared/MMTK/InternalCoordinates.py is in python-mmtk 2.7.9-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# Manipulation of internal coordinates
#
# Written by Konrad Hinsen
#

"""
Manipulation of molecular configurations in terms of internal coordinates
"""

__docformat__ = 'restructuredtext'

import MMTK
from Scientific import N

#
# The abstract base class
#
class InternalCoordinate:

    def __init__(self, atoms):
        self.atoms = atoms
        self.molecule = None
        for m in atoms[0].topLevelChemicalObject().bondedUnits():
            if atoms[0] in m.atomList():
                self.molecule = m
                break
        if self.molecule is None:
            raise ValueError("inconsistent data structure")
        for a in atoms[1:]:
            if a not in self.molecule.atomList():
                raise ValueError("atoms not in the same molecule")
        self.universe = self.molecule.universe()
        if self.universe is None:
            self.universe = MMTK.InfiniteUniverse()

    def bondTest(self):
        for i in range(len(self.atoms)-1):
            if not self.atoms[i] in self.atoms[i+1].bondedTo():
                raise ValueError("no bond between %s and %s"
                                  % (self.atoms[i], self.atoms[i+1]))

    def findFragments(self, spec1, spec2, excluded_first_only=False):
        self.fragment1 = MMTK.Collection()
        self.fragment2 = MMTK.Collection()
        self.molecule.setBondAttributes()
        try:
            self.bondTest()
            for fragment, (start, excluded, error_check) \
                    in [(self.fragment1, spec1), (self.fragment2, spec2)]:
                atoms = set([start])
                first = True
                new_atoms = set([start])
                while new_atoms:
                    check = new_atoms
                    new_atoms = set()
                    for a in check:
                        for na in a.bondedTo():
                            if excluded_first_only:
                                if first:
                                    add = na not in excluded
                                else:
                                    add = True
                            else:
                                add = na not in excluded
                            if add and na not in atoms:
                                atoms.add(na)
                                new_atoms.add(na)
                    first = False
                if error_check in atoms:
                    raise ValueError("cyclic bond structure")
                for a in atoms:
                    fragment.addObject(a)
        finally:
            self.molecule.clearBondAttributes()

#
# Bond length
#
class BondLength(InternalCoordinate):

    """
    Bond length coordinate

    A BondLength object permits calculating and modifying the
    length of a bond in a molecule, under the condition that
    the bond is not part of a circular bond structure (but it
    is not a problem to have a circular bond structure elsewhere
    in the molecule). Modifying the bond length moves the parts
    of the molecule on both sides of the bond along the bond direction
    in such a way that the center of mass of the molecule does not
    change.

    The initial construction of the BondLength object can be
    expensive (the bond structure of the molecule must be
    analyzed). It is therefore advisable to keep the object
    rather than recreate it frequently. Note that if you only
    want to calculate bond lengths (no modification), the
    method Universe.distance is simpler and faster.
    """

    def __init__(self, atom1, atom2):
        """
        :param atom1: the first atom that defines the bond
        :type atom1: :class:`~MMTK.ChemicalObjects.Atom`
        :param atom2: the second atom that defines the bond
        :type atom2: :class:`~MMTK.ChemicalObjects.Atom`
        """
        InternalCoordinate.__init__(self, [atom1, atom2])
        self.findFragments((atom1, set([atom2]), atom2),
                           (atom2, set([atom1]), atom1),
                            True)

    def getValue(self, conf = None):
        """
        :param conf: a configuration (defaults to the current configuration)
        :type conf: :class:`~MMTK.ParticleProperties.Configuration`
        :returns: the length of the bond in the configuration conf
        :rtype: float
        """
        return self.universe.distance(self.atoms[0], self.atoms[1], conf)

    def setValue(self, value):
        """
        Sets the length of the bond
        :param value: the desired length of the bond
        :type value: float
        """
        v = self.universe.distanceVector(self.atoms[0], self.atoms[1])
        axis = v.normal()
        distance = value - v.length()
        m1 = self.fragment1.mass()
        m2 = self.fragment2.mass()
        d1 = -m2*distance/(m1+m2)
        d2 = m1*distance/(m1+m2)
        self.fragment1.translateBy(d1*axis)
        self.fragment2.translateBy(d2*axis)

#
# Bond angles
#
class BondAngle(InternalCoordinate):

    """
    Bond angle

    A BondAngle object permits calculating and modifying the
    angle between two bonds in a molecule, under the condition that
    the bonds are not part of a circular bond structure (but it
    is not a problem to have a circular bond structure elsewhere
    in the molecule). Modifying the bond angle rotates the parts
    of the molecule on both sides of the central atom around
    an axis passing through the central atom and perpendicular
    to the plane defined by the two bonds in such a way that
    there is no overall rotation of the molecule. The central
    atom and any other atoms bonded to it do not move.

    The initial construction of the BondAngle object can be
    expensive (the bond structure of the molecule must be
    analyzed). It is therefore advisable to keep the object
    rather than recreate it frequently. Note that if you only
    want to calculate bond angles (no modification), the
    method Universe.angle is simpler and faster.
    """

    def __init__(self, atom1, atom2, atom3):
        """
        :param atom1: the first atom that defines the angle
        :type atom1: :class:`~MMTK.ChemicalObjects.Atom`
        :param atom2: the second and central atom that defines the bond
        :type atom2: :class:`~MMTK.ChemicalObjects.Atom`
        :param atom3: the third atom that defines the bond
        :type atom3: :class:`~MMTK.ChemicalObjects.Atom`
        """
        InternalCoordinate.__init__(self, [atom1, atom2, atom3])
        excluded = set([atom2])
        self.findFragments((atom1, excluded, atom3), (atom3, excluded, atom1))

    def getValue(self, conf = None):
        """
        :param conf: a configuration (defaults to the current configuration)
        :type conf: :class:`~MMTK.ParticleProperties.Configuration`
        :returns: the size of the angle in the configuration conf
        :rtype: float
        """
        return self.universe.angle(self.atoms[0], self.atoms[1],
                                   self.atoms[2], conf)

    def setValue(self, value):
        """
        Sets the size of the angle
        :param value: the desired angle
        :type value: float
        """
        from Scientific.Geometry import delta
        v1 = self.universe.distanceVector(self.atoms[1], self.atoms[0])
        v2 = self.universe.distanceVector(self.atoms[1], self.atoms[2])
        angle = v1.angle(v2)
        if N.fabs(angle - N.pi) < 1.e-4:
            raise ValueError("angle too close to pi")
        axis = v1.cross(v2).normal()
        d = angle-value
        cm1, th1 = self.fragment1.centerAndMomentOfInertia()
        r1 = self.universe.distanceVector(self.atoms[1], cm1)
        th1 -= self.fragment1.mass()*((r1*r1)*delta-r1.dyadicProduct(r1))
        i1 = axis*(th1*axis)
        cm2, th2 = self.fragment2.centerAndMomentOfInertia()
        r2 = self.universe.distanceVector(self.atoms[1], cm2)
        th2 -= self.fragment2.mass()*((r2*r2)*delta-r2.dyadicProduct(r2))
        i2 = axis*(th2*axis)
        d1 = i2*d/(i1+i2)
        d2 = d1-d
        self.fragment1.rotateAroundAxis(self.atoms[1].position(),
                                        self.atoms[1].position()+axis,
                                        d1)
        self.fragment2.rotateAroundAxis(self.atoms[1].position(),
                                        self.atoms[1].position()+axis,
                                        d2)

#
# Dihedral angles
#
class DihedralAngle(InternalCoordinate):

    """
    Dihedral angle

    A DihedralAngle object permits calculating and modifying the
    dihedral angle defined by three consecutive bonds in a molecule,
    under the condition that the central bond is not part of a
    circular bond structure (but it is not a problem to have a
    circular bond structure elsewhere in the molecule). Modifying the
    dihedral angle rotates the parts of the molecule on both sides of
    the central bond around this central bond in such a way that there
    is no overall rotation of the molecule.

    The initial construction of the DihedralAngle object can be
    expensive (the bond structure of the molecule must be
    analyzed). It is therefore advisable to keep the object
    rather than recreate it frequently. Note that if you only
    want to calculate bond angles (no modification), the
    method Universe.dihedral is simpler and faster.
    """

    def __init__(self, atom1, atom2, atom3, atom4):
        """
        :param atom1: the first atom that defines the dihedral
        :type atom1: :class:`~MMTK.ChemicalObjects.Atom`
        :param atom2: the second atom that defines the dihedral,
                      must be on the central bond
        :type atom2: :class:`~MMTK.ChemicalObjects.Atom`
        :param atom3: the third atom that defines the dihedral,
                      must be on the central bond
        :type atom3: :class:`~MMTK.ChemicalObjects.Atom`
        :param atom4: the fourth atom that defines the dihedral
        :type atom4: :class:`~MMTK.ChemicalObjects.Atom`
        """
        InternalCoordinate.__init__(self, [atom1, atom2, atom3, atom4])
        excluded = set([atom2, atom3])
        self.findFragments((atom1, excluded, atom4), (atom4, excluded, atom1))

    def getValue(self, conf = None):
        """
        :param conf: a configuration (defaults to the current configuration)
        :type conf: :class:`~MMTK.ParticleProperties.Configuration`
        :returns: the size of the dihedral angle in the configuration conf
        :rtype: float
        """
        return self.universe.dihedral(self.atoms[0], self.atoms[1],
                                      self.atoms[2], self.atoms[3], conf)

    def setValue(self, value):
        """
        Sets the size of the dihedral
        :param value: the desired dihedral angle
        :type value: float
        """
        from Scientific.Geometry import delta
        angle  = self.universe.dihedral(self.atoms[0], self.atoms[1],
                                        self.atoms[2], self.atoms[3])
        v = self.universe.distanceVector(self.atoms[1], self.atoms[2])
        axis = v.normal()
        d = N.fmod(angle-value, 2.*N.pi)
        cm1, th1 = self.fragment1.centerAndMomentOfInertia()
        r1 = self.universe.distanceVector(self.atoms[1], cm1)
        th1 -= self.fragment1.mass()*((r1*r1)*delta-r1.dyadicProduct(r1))
        i1 = axis*(th1*axis)
        cm2, th2 = self.fragment2.centerAndMomentOfInertia()
        r2 = self.universe.distanceVector(self.atoms[2], cm2)
        th2 -= self.fragment2.mass()*((r2*r2)*delta-r2.dyadicProduct(r2))
        i2 = axis*(th2*axis)
        d1 = i2*d/(i1+i2)
        d2 = d1-d
        self.fragment1.rotateAroundAxis(self.atoms[1].position(),
                                        self.atoms[1].position()+axis,
                                        d1)
        self.fragment2.rotateAroundAxis(self.atoms[2].position(),
                                        self.atoms[2].position()+axis,
                                        d2)