This file is indexed.

/usr/lib/python2.7/dist-packages/cogent/core/usage.py is in python-cogent 1.9-9.

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
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
#!/usr/bin/env python
"""Classes for dealing with base, codon, and amino acid usage.
"""
from __future__ import division
from cogent.maths.stats.util import Freqs, Numbers, UnsafeFreqs
from cogent.maths.stats.special import fix_rounding_error
from cogent.util.array import euclidean_distance
from cogent.util.misc import Delegator, FunctionWrapper, InverseDict
from cogent.core.genetic_code import GeneticCodes, GeneticCode as GenCodeClass
from cogent.core.info import Info as InfoClass
from cogent.core.alphabet import CharAlphabet
from string import upper

from numpy import array, concatenate, sum, mean, isfinite, sqrt

__author__ = "Rob Knight"
__copyright__ = "Copyright 2007-2016, The Cogent Project"
__credits__ = ["Rob Knight", "Sandra Smit", "Daniel McDonald"]
__license__ = "GPL"
__version__ = "1.9"
__maintainer__ = "Rob Knight"
__email__ = "rob@spot.colorado.edu"
__status__ = "Production"

RnaBases = CharAlphabet('UCAG')
DnaBases = CharAlphabet('TCAG')
AminoAcids = CharAlphabet('ACDEFGHIKLMNPQRSTVWY*') # * denotes termination
AB = CharAlphabet('ab') #used for testing
Chars = CharAlphabet(''.join(map(chr, range(256))), '-')  #used for raw chars
RnaBasesGap = CharAlphabet('UCAG-', '-')
DnaBasesGap = CharAlphabet('TCAG-', '-')
AminoAcidsGap = CharAlphabet('ACDEFGHIKLMNPQRSTVWY*-', '-')
DnaIupac = CharAlphabet('TCAGNVBHDKSWMYR')
RnaIupac = CharAlphabet('UCAGNVBHDKSWMYR')
AminoAcidsIupac = CharAlphabet('ACDEFGHIKLMNPQRSTVWY*XBZ')
DnaIupacGap = CharAlphabet('TCAG-NVBHDKSWMYR', '-')
RnaIupacGap = CharAlphabet('UCAG-NVBHDKSWMYR', '-')
AminoAcidsIupacGap = CharAlphabet('ACDEFGHIKLMNPQRSTVWY*-XBZ', '-')

RnaPairs = RnaBases**2
DnaPairs = DnaBases**2
RnaGapPairs = RnaBasesGap**2
DnaGapPairs = DnaBasesGap**2
AminoAcidPairs = AminoAcids**2
ABPairs = AB**2

#RnaBases = 'UCAG'
#DnaBases = 'TCAG'
RnaCodons = [i+j+k for i in RnaBases for j in RnaBases for k in RnaBases]
DnaCodons = [i+j+k for i in DnaBases for j in DnaBases for k in DnaBases]
#AminoAcids = 'ACDEFGHIKLMNPQRSTVWY*'
SGC = GeneticCodes[1]

RnaDinucs = [i+j for i in RnaBases for j in RnaBases]

RnaToDna = dict(zip(RnaBases, DnaBases))
DnaToRna = dict(zip(DnaBases, RnaBases))

Bases = RnaBases        #by default
Codons = RnaCodons      #by default

_equal_bases = Freqs(Bases)
_equal_codons = Freqs(Codons)
_equal_amino_acids = Freqs(AminoAcids[:-1])     #exclude Stop
for i in (_equal_bases, _equal_codons, _equal_amino_acids):
    i.normalize()

empty_rna_codons = dict.fromkeys(RnaCodons, 0.0)
empty_dna_codons = dict.fromkeys(DnaCodons, 0.0)

def seq_to_codon_dict(seq, empty_codons=empty_dna_codons):
    """Converts sequence into codon dict."""
    leftover = len(seq) % 3
    if leftover:
        seq += 'A' * (3-leftover)
    result = empty_codons.copy()
    for i in range(0, len(seq), 3):
        curr = seq[i:i+3]
        if curr in result:  #ignore others
            result[curr] += 1
    return result

def UnsafeCodonsFromString(seq, rna=False, formatted=False, **kwargs):
    if rna:
        d = empty_rna_codons
        if not formatted:
            seq = seq.upper().replace('T','U')
    else:
        d = empty_dna_codons
        if not formatted:
            seq = seq.upper().replace('U','T')
    return UnsafeCodonUsage(seq_to_codon_dict(seq,d), **kwargs)

def key_to_rna(key):
    """Sets key to uppercase RNA."""
    return key.upper().replace('T', 'U')

def key_to_dna(key):
    """Sets key to uppercase DNA."""
    return key.upper().replace('U', 'T')

class InfoFreqs(Freqs, Delegator):
    """Like Freqs, but has an Info object storing additional data.
    
    Intended for holding base or codon frequencies that come from a 
    particular sequence, so that the Info of the sequence can be preserved
    even if the sequence is deleted to free up memory.
    """
    def __init__(self, data=None, Info=None, **kwargs):
        """Intializes BaseUsage with data, either sequence or dict of freqs.
        
        Ignores additional kwargs (e.g. to support copy).

        Makes the _handler for delegator accessible with the name Info.
        """
        if Info is None:
            if hasattr(data, 'Info'):
                Info = data.Info
            else:
                Info = InfoClass()
        Delegator.__init__(self, Info)
        Freqs.__init__(self, data or [], **kwargs)

    def _get_info(self):
        """Accessor for Info."""
        return self._handler
    def _set_info(self, obj):
        """Mutator for Info."""
        self._handler = obj
    Info = property(_get_info, _set_info)


class BaseUsageI(object):
    """Provides shared interface for BaseUsage classes.

    BaseUsage stores counts of the four DNA or RNA bases.
    """
    def bases(self):
        """Supports bases/codons/positionalBases/aminoAcids interface."""
        return self

    def codons(self):
        """Predicts codon frequencies from the base frequencies."""
        result = {}
        base_copy = self.__class__(self)
        base_copy.normalize()
        for c in Codons:
            curr = 1
            for i in c:
                curr *= base_copy[i]
            result[c] = curr
        return CodonUsage(result, self.Info)

    def positionalBases(self):
        """Returns PositionalBaseUsage with copy of self at each position."""
        return PositionalBaseUsage(self.__class__(self), self.__class__(self),
            self.__class__(self), self.Info)

    def aminoAcids(self, genetic_code=SGC):
        """Predicts amino acid frequencies from the base frequencies."""
        return self.codons().aminoAcids(genetic_code)
    
    def distance(self,other):
        """Calculates the distance between two BaseUsages.

        Distance is measured in three directions, CG-content, CU-content, and
        GU-content.
        """
        return euclidean_distance(array(self.toCartesian()),\
            array(other.toCartesian()))

    def content(self, string):
        """Gets the sum of bases specified in string.
        
        For example, self.content('GC') gets the GC content.
        """
        return sum([self.get(i, 0) for i in string], 0)

    def toCartesian(self):
        """Returns tuple of x, y, z coordinates from BaseUsage.

        x=u+c, y=u+g, z=u+a

        Doesn't alter original object.
        """
        return self['UC'], self['UG'], self['UA']

    def fromCartesian(cls, *coords):
        """Returns new BaseUsage with A,C,G,U coordinates from UC,UG,UA.

        From UC,UG,UA to A,C,G(,U).

        This will only work when the original coordinates come from a simplex,
        where U+C+A+G=1
        """
        result = cls()
        x,y,z = coords
        u = fix_rounding_error((1-x-y-z)/-2)
        a, c, g = z-u, x-u, y-u
        result['A'] = a
        result['C'] = c
        result['G'] = g
        result['U'] = u
        return result
    fromCartesian = classmethod(fromCartesian)

class BaseUsage(BaseUsageI, InfoFreqs):
    """Stores frequencies of the four bases, mapped to RNA.

    This class is convenient but inefficient, since it automatically maps any
    lookups to the uppercase RNA alphabet internally. Use UnsafeBaseUsage for 
    speed when necessary.
    """
    
    Mask = FunctionWrapper(key_to_rna)
    RequiredKeys = dict.fromkeys(Bases)
    
    def __getitem__(self, key):
        """Normalizes key and treats T=U."""
        key = self.Mask(key)
        if len(key) == 2:  #pair of bases, e.g. GC for GC content
            dup = BaseUsage(self)
            dup.normalize()
            return sum([dup.get(i,0) for i in key], 0)
        else:
            return super(BaseUsage, self).__getitem__(key)

class UnsafeBaseUsage(BaseUsageI, UnsafeFreqs):
    """Stores frequencies of the four bases. Does not do any validation.

    This class avoids overriding most built-ins, so is much faster than
    BaseFreqs (although it is often less convenient).
    """
    RequiredKeys = dict.fromkeys(Bases)
    Info = {}   # for interface compatibility with InfoFreqs-based class

class CodonUsageI(object):
    """Stores codon usage for a gene or species.
    
    Note that CodonUsage objects get their own reference to _default_code
    during creation, so changing CodonUsage._default_code will not change the
    GeneticCode of any CodonUsage object that has already been created.
    """
    _default_code = SGC

    BlockAbbreviations = \
        {'UU':'F/L', 'CU':'Leu', 'AU':'I/M', 'GU':'Val', \
        'UC':'Ser', 'CC':'Pro', 'AC':'Thr', 'GC':'Ala',\
        'UA':'Y/*','CA':'H/Q','AA':'N/K','GA':'D/E',\
        'UG':'C*W', 'CG':'Arg', 'AG':'S/R', 'GG':'Gly'}
    
    BlockNames = \
        {'UU':'Phe/Leu', 'CU':'Leucine', 'AU':'Ile/Met', 'GU':'Valine', \
        'UC':'Serine', 'CC':'Proline', 'AC':'Threonine', 'GC':'Alanine',\
        'UA':'Tyr/Ter','CA':'His/Gln','AA':'Asn/Lys','GA':'Asp/Glu',\
        'UG':'Cys/Ter/Trp', 'CG':'Arginine', 'AG':'Ser/Arg', 'GG':'Glycine'}

    Blocks = [i+j for i in 'UCAG' for j in 'UCAG'] #UCAG order
    SingleAABlocks = ['GC','CG','GG','CU','CC','UC','AC','GU'] #alpha by aa
    SplitBlocks = ['UU', 'CA','AU','AA','AG','GA'] #UCAG order]

    AbbreviationsToBlocks = InverseDict(BlockAbbreviations)
    NamesToBlocks = InverseDict(BlockNames)

    BaseUsageClass = None   #Must overrride in subclasses

    def bases(self, purge_unwanted=False):
        """Returns overall base counts."""
        result = {}
        if purge_unwanted:
            data = self._purged_data()
        else:
            data = self
        for codon, freq in data.items():
            for base in codon:
                if base in result:
                    result[base] += freq
                else:
                    result[base] = freq
        return self.BaseUsageClass(result, self.Info)

    def codons(self):
        """Supports codons/aminoAcids/bases/positionalBases interface."""
        return self

    def rscu(self):
        """Normalizes self in-place to RSCU, relative synonymous codon usage.

        RSCU divides the frequency of each codon to the sum of the freqs for
        that codon's amino acid.
        """
        gc = self.GeneticCode
        syn = gc.Synonyms
        aa_sums = {}
        for key, codons in syn.items():
            aa_sums[key] = sum([self[c] for c in codons], 0)
        for codon in self:
            try:
                curr = self[codon]
                res = curr/aa_sums[gc[codon]]
            except (KeyError, ZeroDivisionError, FloatingPointError):
                pass
            else:
                if isfinite(res):
                    self[codon] = res
        return self
        

    def _purged_data(self):
        """Copy of self's freqs after removing bad/stop codons and singlets."""
        good_codons = self.RequiredKeys
        code = self.GeneticCode
        data = dict(self)   #need copy, since we're deleting required keys
        #delete any bad codons
        for codon in self:
            if codon not in good_codons:
                del data[codon]
        #delete any stop codons in the current code
        for codon in code['*']:
            try:
                c = codon.upper().replace('T','U')
                del data[c]
            except KeyError:
                pass    #don't care if it's not there
        #delete any single-item blocks in the current code (i.e. leaving
        #only doublets and quartets).
        for group in code.Blocks:
            if len(group) == 1:
                try:
                    c = group[0].upper().replace('T','U')
                    del data[c]
                except KeyError:
                    pass    #don't care if already deleted
        return data

    def positionalBases(self, purge_unwanted=False):
        """Calculates positional base usage.
        
        purge_unwanted controls whether or not to purge 1-codon groups, stop
        codons, and any codons containing degnerate bases before calculating 
        the base usage (e.g. to get Noboru Sueoka's P3 measurement): default 
        is False. Deletion of unwanted codons happens on a copy, not the 
        original data.
        """
        first = {}
        second = {}
        third = {}

        if purge_unwanted:  #make a copy of the data and delete things from it
            data = self._purged_data()
        else:
            data = self

        for codon, freq in data.items():
            try:
                p1, p2, p3 = codon
            except ValueError:
                continue #skip any incomplete codons
            
            if p1 in first:
                first[p1] += freq
            else:
                first[p1] = freq
            if p2 in second:
                second[p2] += freq
            else:
                second[p2] = freq
            if p3 in third:
                third[p3] += freq
            else:
                third[p3] = freq
        return PositionalBaseUsage(self.BaseUsageClass(first), \
            self.BaseUsageClass(second), self.BaseUsageClass(third), self.Info)

    def positionalGC(self, purge_unwanted=True):
        """Returns GC, P1, P2 P3. Use purge_unwanted=False to get raw counts."""
        p = self.positionalBases(purge_unwanted)
        p.normalize()
        result = [i['G'] + i['C'] for i in p]
        average = sum(result, 0)/3
        return [average] + result
        
    def fingerprint(self, which_blocks='quartets', include_mean=True,\
        normalize=True):
        """Returns fingerprint data for fingerprint plots.
        
        which_blocks: whether to include only the usual 4-codon quartets (the
                      default), the split blocks only, or all blocks.
        include_mean: whether to include the mean (True).
        normalize:    whether to normalize so that the quartets sum to 1 (True)
        """ 
        if which_blocks == 'split':
            blocks = self.SplitBlocks
        elif which_blocks == 'quartets':
            blocks = self.SingleAABlocks
        elif which_blocks == 'all':
            blocks = self.Blocks
        else:
            raise "Got invalid option %s for which_blocks:\n" % which_blocks+\
                    "  (valid options: 'split', 'quartets', 'all')."
        result = []
        for b in blocks:    #iterates over doublet string
            U, C, A, G = [self[b+i] for i in 'UCAG']
            all = U+C+A+G
            if G+C:
                g_ratio = G/(G+C)
            else:
                g_ratio = 0.5

            if A+U:
                a_ratio = A/(A+U)
            else:
                a_ratio=0.5
                
            result.append([g_ratio, a_ratio, all])
        result = array(result)
        
        if normalize:   #make the shown bubbles sum to 1
            sum_ = sum(result[:,-1])
            if sum_:
                result[:,-1] /= sum_
        
        if include_mean: #calculate mean from all codons
            third = self.positionalBases().Third
            U, C, A, G = [third[i] for i in 'UCAG']
            if G+C:
                g_ratio = G/(G+C)
            else:
                g_ratio = 0.5
            if A+U:
                a_ratio = A/(A+U)
            else:
                a_ratio=0.5
            result = concatenate((result, array([[g_ratio,a_ratio,1]])))
        
        return result

    def pr2bias(self, block):
        """Calculates PR2 bias for a specified block, e.g. 'AC' or 'UU'.

        Returns tuple of:
        (G/G+C, A/A+T, G/G+A, C/C+T, G/G+T, C/C+A)

        If any pair sums to zero, will raise ZeroDivisionError.

        block: codon block, e.g. 'AC', 'UU', etc. Any of the 16 doublets.
        """
        U, C, A, G = [self[block+i] for i in 'UCAG']
        return G/(G+C), A/(A+U), G/(G+A), C/(C+U), G/(G+U), C/(C+A)
            
    def aminoAcids(self, genetic_code=None):
        """Calculates amino acid usage, optionally using a specified code."""
        if genetic_code is None:
            curr_code = self.GeneticCode
        elif isinstance(genetic_code, GenCodeClass):
            curr_code = genetic_code
        else:
            curr_code = GeneticCodes[genetic_code]
        aa = {}
        for codon, freq in self.items():
            curr_aa = curr_code[codon]
            if curr_aa in aa:
                aa[curr_aa] += freq
            else:
                aa[curr_aa] = freq
        return AminoAcidUsage(aa, self.Info)
    
class CodonUsage(CodonUsageI, InfoFreqs):
    """Stores frequencies of the 64 codons, mapped to RNA.

    This class is convenient but inefficient, since it automatically maps any
    lookups to the uppercase RNA alphabet internally. Use UnsafeBaseUsage for 
    speed when necessary.
    """
    
    Mask = FunctionWrapper(key_to_rna)
    RequiredKeys = RnaCodons
    BaseUsageClass = BaseUsage
   
    def __init__(self, data=None, Info=None, GeneticCode=None, \
        Mask=None, ValueMask=None, Constraint=None):
        """Initializes new CodonUsage with Info and frequency data.
        
        Note: Mask, ValueMask and Constraint are ignored, but must be present
        to support copy() because of the ConstrainedContainer interface.
        """
        #check if we have a sequence: if so, take it 3 bases at a time
        #this will (properly) fail on lists of tuples or anything else where 
        #the items don't behave like strings.
        try:
            codons = [''.join(data[i:i+3]) for i in xrange(0, len(data), 3)]
        except:
            codons = data
        super(CodonUsage, self).__init__(codons, Info)
        
        if GeneticCode:
            if isinstance(GeneticCode, GenCodeClass):
                curr_code = GeneticCode
            else:
                curr_code = GeneticCodes[GeneticCode]
        else:
            curr_code = self._default_code
        self.__dict__['GeneticCode'] = curr_code
 
    def __getitem__(self, key):
        """Normalizes key and treats T=U."""
        key = self.Mask(key)
        if len(key) == 2:  #pair of bases, e.g. GC for GC content
            dup = BaseUsage(self)
            dup.normalize()
            return sum([dup.get(i,0) for i in key], 0)
        else:
            return super(CodonUsage, self).__getitem__(key)

class UnsafeCodonUsage(CodonUsageI, UnsafeFreqs):
    """Stores frequencies of the four bases. Must access as RNA.

    This class avoids overriding most built-ins, so is much faster than
    CodonFreqs (although it is often less convenient).
    """
    RequiredKeys = RnaCodons
    Info = {}   # for interface compatibility with InfoFreqs-based class
    Gene=None       #for CUTG compatibility
    Species=None    # for CUTG compaitibility
    BaseUsageClass = UnsafeBaseUsage

    def __init__(self, data=None, Info=None, GeneticCode=None, \
        Mask=None, ValueMask=None, Constraint=None):
        """Initializes new CodonUsage with Info and frequency data.
        
        Note: Mask, ValueMask and Constraint are ignored, but must be present
        to support copy() because of the ConstrainedContainer interface.
        """
        #check if we have a sequence: if so, take it 3 bases at a time
        #this will (properly) fail on lists of tuples or anything else where 
        #the items don't behave like strings.
        try:
            codons = [''.join(data[i:i+3]) for i in xrange(0, len(data), 3)]
        except:
            codons = data or {}
        UnsafeFreqs.__init__(self, codons)
        #set required keys
        for k in self.RequiredKeys:
            if k not in self:
                self[k] = 0.0
        #flatten Info onto self directly for lookups
        if Info:
            self.__dict__.update(Info)
        self.Info = Info or {}
        
        if GeneticCode:
            if isinstance(GeneticCode, GenCodeClass):
                curr_code = GeneticCode
            else:
                curr_code = GeneticCodes[GeneticCode]
        else:
            curr_code = self._default_code
        self.GeneticCode = curr_code

    
class PositionalBaseUsage(Delegator):
    """Stores a BaseUsage for each of the three codon positions."""
    
    def __init__(self, First=None, Second=None, Third=None, Info=None):
        """Returns new PositionalBaseUsage with values for the 3 positions."""
        Delegator.__init__(self, Info)
        self.__dict__['First'] = First or BaseUsage()
        self.__dict__['Second'] = Second or BaseUsage()
        self.__dict__['Third'] = Third or BaseUsage()

    def _get_info(self):
        """Accessor for Info."""
        return self._handler
    def _set_info(self, obj):
        """Mutator for Info."""
        self._handler = obj
    Info = property(_get_info, _set_info)

    def __getitem__(self, index):
        """Supports lookups by index."""
        if index == 0 or index == -3:
            return self.First
        elif index == 1 or index == -2:
            return self.Second
        elif index == 2 or index == -1:
            return self.Third
        else:
            raise IndexError, "PositionalBaseUsage only has 3 positions."

    def normalize(self):
        """Normalizes each of the component base usages."""
        self.First.normalize()
        self.Second.normalize()
        self.Third.normalize()

    def bases(self):
        """Returns distribution of the four bases, summed over positions."""
        sum = BaseUsage(Info=self.Info)
        for i in self:
            sum +=i
        return sum

    def codons(self):
        """Returns codon distribution, calculated from positional freqs."""
        result = {}
        first_copy, second_copy, third_copy = map(Freqs, self)
        first_copy.normalize()
        second_copy.normalize()
        third_copy.normalize()
        for c in Codons:
            result[c] = first_copy[c[0]] * second_copy[c[1]] * third_copy[c[2]]
        return CodonUsage(result, self.Info)

    def positionalBases(self):
        """Supports bases/codons/positionalBases/aminoAcids interface."""
        return self

    def aminoAcids(self, genetic_code=None):
        """Returns amino acid distribution."""
        return self.codons().aminoAcids(genetic_code)
        
class AminoAcidUsage(InfoFreqs):
    """Stores counts ofthe 20 canonical amino acids."""
    Mask = FunctionWrapper(upper)
    RequiredKeys = dict.fromkeys(AminoAcids)

    def bases(self, genetic_code=SGC, codon_usage=_equal_codons):
        """Predicts most likely set of base frequencies.
        
        Optionally uses a genetic code (default: standard genetic code) and 
        codon usage (default: unbiased codon usage).
        """
        result = self.codons(genetic_code, codon_usage).bases()
        result.normalize()
        return result


    def codons(self, genetic_code=SGC, codon_usage=_equal_codons):
        """Predicts most likely set of codon frequencies.

        Optionally uses genetic_code (to figure out which codons belong
        with each amino acid), and codon_usage (to get most likely codons for 
        each amino acid). Defaults are the standard genetic code and unbiased 
        codon frequencies.
        """
        result = {}
        normalized = Freqs(self)
        normalized.normalize()
        for aa, aa_freq in normalized.items():
            curr_codons = [c.upper().replace('T','U') for c in genetic_code[aa]]
            if not curr_codons:
                continue    #code might be missing some amino acids?
            curr_codon_freqs = Numbers([codon_usage[c] for c in curr_codons])
            curr_codon_freqs.normalize()
            for codon, c_freq in zip(curr_codons, curr_codon_freqs):
                result[codon] = c_freq * aa_freq
        return CodonUsage(result, self.info, genetic_code)

    def positionalBases(self, genetic_code=SGC, codon_usage=_equal_codons):
        """Predicts most likely set of positional base frequencies.

        Optionally uses a genetic code (default: standard genetic code) and
        codon usage (default: unbiased codon usage).
        """
        return self.codons(genetic_code, codon_usage).positionalBases()

    def aminoAcids(self):
        """Supports bases/positionalBases/aminoAcids/codons interface."""
        return self

class DinucI(object):
    """Provides shared interface for DinucUsage classes.

    DinucUsage stores counts of the 16 doublets.
    """

    def distance(self, other):
        """Calculates distance between two DinucUsage objects."""
        result = 0
        for k in self.RequiredKeys:
            result += (self[k]-other[k])**2
        return sqrt(result)

class DinucUsage(DinucI, InfoFreqs):
    """Stores frequencies of the 16 dinucleotides, mapped to RNA.

    This class is convenient but inefficient, since it automatically maps any
    lookups to the uppercase RNA alphabet internally. Use UnsafeBaseUsage for 
    speed when necessary.
    """
    Mask = FunctionWrapper(key_to_rna)
    RequiredKeys = RnaDinucs

    def __init__(self, data=None, Info=None, Overlapping=True, \
        GeneticCode=None, Mask=None, ValueMask=None, Constraint=None):
        """Initializes new CodonUsage with Info and frequency data.
        
        Note: Mask, ValueMask and Constraint are ignored, but must be present
        to support copy() because of the ConstrainedContainer interface.
        """
        #check if we have a sequence: if so, take it 3 bases at a time
        #this will (properly) fail on lists of tuples or anything else where 
        #the items don't behave like strings.
        if Mask is not None:
            self.Mask = Mask
        if ValueMask is not None:
            self.ValueMask = ValueMask
        try:
            data = self.Mask(data)
            if Overlapping == '3-1':
                range_ = range(2, len(data)-1, 3)
            elif Overlapping:
                range_ = range(0, len(data)-1)
            else:
                range_ = range(0, len(data)-1, 2)
            dinucs = [''.join(data[i:i+2]) for i in range_]
        except:
            dinucs = data
        super(DinucUsage, self).__init__(dinucs, Info)
        
    def __getitem__(self, key):
        """Normalizes key and treats T=U."""
        key = self.Mask(key)
        return super(DinucUsage, self).__getitem__(key)


#some useful constants...

EqualBases = BaseUsage()
EqualBases = BaseUsage(_equal_bases)
EqualPositionalBases = PositionalBaseUsage(BaseUsage(_equal_bases),
    BaseUsage(_equal_bases), BaseUsage(_equal_bases))
EqualAminoAcids = AminoAcidUsage(_equal_amino_acids)   #excl. Stop
EqualCodons = CodonUsage(_equal_codons)