This file is indexed.

/usr/share/pyshared/MMTK/NucleicAcids.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
# This module implements classes for nucleotide chains.
#
# Written by Konrad Hinsen
#

"""
Nucleic acid chains
"""

__docformat__ = 'restructuredtext'

from MMTK import Biopolymers, Bonds, ChemicalObjects, Collections, \
                 ConfigIO, Database, Universe, Utility
from Scientific.Geometry import Vector

from MMTK.Biopolymers import defineNucleicAcidResidue

#
# Nucleotides are special groups
#
class Nucleotide(Biopolymers.Residue):

    """
    Nucleic acid residue

    Nucleotides are a special kind of group. Like any other
    group, they are defined in the chemical database. Each residue
    has two or three subgroups ('sugar' and 'base', plus 'phosphate'
    except for 5'-terminal residues) and is usually
    connected to other residues to form a nucleotide chain. The database
    contains three variants of each residue (5'-terminal, 3'-terminal,
    non-terminal).
    """

    def __init__(self, name = None, model = 'all'):
        """
        :param name: the name of the nucleotide in the chemical database. This
                     is the full name of the residue plus the suffix
                     "_5ter" or "_3ter" for the terminal variants.
        :type name: str
        :param model: one of "all" (all-atom), "none" (no hydrogens),
                      "polar" (united-atom with only polar hydrogens),
                      "polar_charmm" (like "polar", but defining
                      polar hydrogens like in the CHARMM force field).
                      Currently the database has definitions only for "all".
        :type model: str
        """
	if name is not None:
	    blueprint = _residueBlueprint(name, model)
	    ChemicalObjects.Group.__init__(self, blueprint)
	    self.model = model
	    self._init()

    def backbone(self):
        """
        :returns: the sugar and phosphate groups
        :rtype: :class:`~MMTK.ChemicalObjects.Group`
        """
        bb = self.sugar
        if hasattr(self, 'phosphate'):
            bb = Collections.Collection([bb, self.phosphate])
        return bb

    def bases(self):
        """
        :returns: the base group
        :rtype: :class:`~MMTK.ChemicalObjects.Group`
        """
        return self.base


def _residueBlueprint(name, model):
    try:
	blueprint = _residue_blueprints[(name, model)]
    except KeyError:
	if model == 'polar':
	    name = name + '_uni'
	elif model == 'polar_charmm':
	    name = name + '_uni2'
	elif model == 'none':
	    name = name + '_noh'
	blueprint = Database.BlueprintGroup(name)
	_residue_blueprints[(name, model)] = blueprint
    return blueprint

_residue_blueprints = {}

#
# Nucleotide chains are molecules with added features.
#
class NucleotideChain(Biopolymers.ResidueChain):

    """
    Nucleotide chain

    Nucleotide chains consist of nucleotides that are linked together.
    They are a special kind of molecule, i.e. all molecule operations
    are available.

    Nucleotide chains act as sequences of residues. If n is a NucleotideChain
    object, then

     * len(n) yields the number of nucleotides

     * n[i] yields nucleotide number i

     * n[i:j] yields the subchain from nucleotide number i up to but
                 excluding nucleotide number j
    """

    def __init__(self, sequence, **properties):
        """
        :param sequence: the nucleotide sequence. This can be a string
                         containing the one-letter codes, or a list
                         of two-letter codes (a "d" or "r" for the type of
                         sugar, and the one-letter base code), or a
                         :class:`~MMTK.PDB.PDBNucleotideChain` object.
                         If a PDBNucleotideChain object is supplied, the
                         atomic positions it contains are assigned to the
                         atoms of the newly generated nucleotide chain,
                         otherwise the positions of all atoms are undefined.
        :keyword model: one of "all" (all-atom), "no_hydrogens" or "none"
                        (no hydrogens), "polar_hydrogens" or "polar"
                        (united-atom with only polar hydrogens),
                        "polar_charmm" (like "polar", but defining
                        polar hydrogens like in the CHARMM force field),
                        "polar_opls" (like "polar", but defining
                        polar hydrogens like in the latest OPLS force field).
                        Default is "all". Currently the database contains
                        definitions only for "all".
        :type model: str
        :keyword terminus_5: if True, the first residue is constructed
                             using the 5'-terminal variant, if False the
                             non-terminal version is used. Default is True.
        :type terminus_5: bool
        :keyword terminus_3: if True, the last residue is constructed
                             using the 3'-terminal variant, if False the
                             non-terminal version is used. Default is True.
        :type terminus_3: bool
        :keyword circular: if True, a bond is constructed
                           between the first and the last residue.
                           Default is False.
        :type circular: bool
        :keyword name: a name for the chain (a string)
        :type name: str
        """
	if sequence is not None:
	    hydrogens = self.binaryProperty(properties, 'hydrogens', 'all')
	    if hydrogens == 1:
		hydrogens = 'all'
	    elif hydrogens == 0:
		hydrogens = 'none'
	    term5 = self.binaryProperty(properties, 'terminus_5', True)
	    term3 = self.binaryProperty(properties, 'terminus_3', True)
	    circular = self.binaryProperty(properties, 'circular', False)
	    try:
		model = properties['model'].lower()
	    except KeyError:
		model = hydrogens
	    self.version_spec = {'hydrogens': hydrogens,
				 'terminus_5': term5,
				 'terminus_3': term3,
				 'model': model,
                                 'circular': circular}
            if isinstance(sequence[0], basestring):
		conf = None
	    else:
		conf = sequence
		sequence = [r.name for r in sequence]
	    sequence = [Biopolymers._fullName(r) for r in sequence]
            if term5:
                if sequence[0].find('5ter') == -1:
                    sequence[0] += '_5ter'
            if term3:
                if sequence[-1].find('3ter') == -1:
                    sequence[-1] += '_3ter'

            self.groups = []
            n = 0
            for residue in sequence:
                n += 1
                r = Nucleotide(residue, model)
                r.name = r.symbol + '_' + `n`
                r.sequence_number = n
                r.parent = self
                self.groups.append(r)

            self._setupChain(circular, properties, conf)

    is_nucleotide_chain = True

    def __getslice__(self, first, last):
	return NucleotideSubChain(self, self.groups[first:last])

    def backbone(self):
        """
        :returns: the sugar and phosphate groups of all nucleotides
        :rtype: :class:`~MMTK.Collections.Collection`
        """
        bb = Collections.Collection([])
        for residue in self.groups:
            try:
                bb.addObject(residue.phosphate)
            except AttributeError:
                pass
            bb.addObject(residue.sugar)
        return bb

    def bases(self):
        """
        :returns: the base groups of all nucleotides
        :rtype: :class:`~MMTK.Collections.Collection`
        """
	return Collections.Collection([r.base for r in self.groups])

    def _descriptionSpec(self):
        kwargs = ','.join([name + '=' + `self.version_spec[name]`
                           for name in sorted(self.version_spec.keys())])
	return "N", kwargs

    def _typeName(self):
        return ''.join([s.ljust(3) for s in self.sequence()])

    def _graphics(self, conf, distance_fn, model, module, options):
	if model != 'backbone':
	    return ChemicalObjects.Molecule._graphics(self, conf,
						      distance_fn, model,
						      module, options)
	color = options.get('color', 'black')
	material = module.EmissiveMaterial(color)
	objects = []
	for i in range(1, len(self.groups)-1):
	    a1 = self.groups[i].phosphate.P
	    a2 = self.groups[i+1].phosphate.P
	    p1 = a1.position(conf)
	    p2 = a2.position(conf)
	    if p1 is not None and p2 is not None:
		bond_vector = 0.5*distance_fn(a1, a2, conf)
		cut = bond_vector != 0.5*(p2-p1)
		if not cut:
		    objects.append(module.Line(p1, p2, material = material))
		else:
		    objects.append(module.Line(p1, p1+bond_vector,
					       material = material))
		    objects.append(module.Line(p2, p2-bond_vector,
					       material = material))
	return objects

#
# Subchains are created by slicing chains or extracting a chain from
# a group of connected chains.
#
class NucleotideSubChain(NucleotideChain):

    """
    A contiguous part of a nucleotide chain

    NucleotideSubChain objects are the result of slicing operations on
    NucleotideChain objects. They cannot be created directly.
    NucleotideSubChain objects permit all operations of NucleotideChain
    objects, but cannot be added to a universe.
    """

    def __init__(self, chain, groups, name = ''):
	self.groups = groups
	self.atoms = []
	self.bonds = []
	for g in self.groups:
	    self.atoms = self.atoms + g.atoms
	    self.bonds = self.bonds + g.bonds
        for i in range(len(self.groups)-1):
            self.bonds.append(Bonds.Bond((self.groups[i].sugar.O_3,
                                          self.groups[i+1].phosphate.P)))
	self.bonds = Bonds.BondList(self.bonds)
	self.name = name
	self.parent = chain.parent
	self.type = None
	self.configurations = {}
	self.part_of = chain

    is_incomplete = True

    def __repr__(self):
	if self.name == '':
	    return 'SubChain of ' + repr(self.part_of)
	else:
	    return ChemicalObjects.Molecule.__repr__(self)
    __str__ = __repr__


#
# Type check functions
#
def isNucleotideChain(x):
    "Returns True if x is a NucleotideChain."
    return hasattr(x, 'is_nucleotide_chain')