~ubuntu-branches/ubuntu/natty/python-cogent/natty

« back to all changes in this revision

Viewing changes to doc/cookbook/useful_utilities.rst

  • Committer: Bazaar Package Importer
  • Author(s): Steffen Moeller
  • Date: 2010-12-04 22:30:35 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20101204223035-j11kinhcrrdgg2p2
Tags: 1.5-1
* Bumped standard to 3.9.1, no changes required.
* New upstream version.
  - major additions to Cookbook
  - added AlleleFreqs attribute to ensembl Variation objects.
  - added getGeneByStableId method to genome objects.
  - added Introns attribute to Transcript objects and an Intron class.
  - added Mann-Whitney test and a Monte-Carlo version
  - exploratory and confirmatory period estimation techniques (suitable for
    symbolic and continuous data)
  - Information theoretic measures (AIC and BIC) added
  - drawing of trees with collapsed nodes
  - progress display indicator support for terminal and GUI apps
  - added parser for illumina HiSeq2000 and GAiix sequence files as 
    cogent.parse.illumina_sequence.MinimalIlluminaSequenceParser.
  - added parser to FASTQ files, one of the output options for illumina's
    workflow, also added cookbook demo.
  - added functionality for parsing of SFF files without the Roche tools in
    cogent.parse.binary_sff
  - thousand fold performance improvement to nmds
  - >10-fold performance improvements to some Table operations

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
Useful Utilities
3
3
****************
4
4
 
 
5
.. authors, Daniel McDonald
 
6
 
5
7
Using PyCogent's optimisers for your own functions
6
8
==================================================
7
9
 
33
35
 
34
36
.. doctest::
35
37
    
36
 
    >>> fit, vec = opt.run(show_progress=False)
 
38
    >>> fit, vec = opt.run()
37
39
    >>> assert 0.0 <= fit < 1e-6
38
40
    >>> print 'S=%.4f' % vec[0]
39
41
    S=-3.6150
45
47
 
46
48
.. cogent.util.transform
47
49
 
 
50
Miscellaneous functions
 
51
=======================
 
52
 
 
53
.. index:: cogent.util.misc
 
54
 
 
55
Identity testing
 
56
^^^^^^^^^^^^^^^^
 
57
 
 
58
Basic ``identity`` function to avoid having to test explicitly for None
 
59
 
 
60
.. doctest::
 
61
 
 
62
    >>> from cogent.util.misc import identity
 
63
    >>> my_var = None
 
64
    >>> if identity(my_var):
 
65
    ...   print "foo"
 
66
    ... else:
 
67
    ...   print "bar"
 
68
    ... 
 
69
    bar
 
70
 
 
71
One-line if/else statement
 
72
^^^^^^^^^^^^^^^^^^^^^^^^^^
 
73
 
 
74
Convenience function for performing one-line if/else statements. This is similar to the C-style tertiary operator:
 
75
 
 
76
.. doctest::
 
77
 
 
78
    >>> from cogent.util.misc import if_
 
79
    >>> result = if_(4 > 5, "Expression is True", "Expression is False")
 
80
    >>> result
 
81
    'Expression is False'
 
82
 
 
83
However, the value returned is evaluated, but not called. For instance:
 
84
 
 
85
.. doctest::
 
86
 
 
87
    >>> from cogent.util.misc import if_
 
88
    >>> def foo():
 
89
    ...   print "in foo"
 
90
    ... 
 
91
    >>> def bar():
 
92
    ...   print "in bar"
 
93
    ...
 
94
    >>> if_(4 > 5, foo, bar)
 
95
    <function bar at...
 
96
 
 
97
Force a variable to be iterable
 
98
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
99
 
 
100
This support method will force a variable to be an iterable, allowing you to guarantee that the variable will be safe for use in, say, a ``for`` loop.
 
101
 
 
102
.. doctest::
 
103
 
 
104
    >>> from cogent.util.misc import iterable
 
105
    >>> my_var = 10
 
106
    >>> for i in my_var:
 
107
    ...   print "will not work"
 
108
    ... 
 
109
    Traceback (most recent call last):
 
110
    TypeError: 'int' object is not iterable
 
111
    >>> for i in iterable(my_var):
 
112
    ...   print i
 
113
    ... 
 
114
    10
 
115
 
 
116
Obtain the index of the largest item
 
117
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
118
 
 
119
To determine the index of the largest item in any iterable container, use ``max_index``:
 
120
 
 
121
.. doctest::
 
122
 
 
123
    >>> from cogent.util.misc import max_index
 
124
    >>> l = [5,4,2,2,6,8,0,10,0,5]
 
125
    >>> max_index(l)
 
126
    7
 
127
 
 
128
.. note:: Will return the lowest index of duplicate max values
 
129
 
 
130
Obtain the index of the smallest item
 
131
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
132
 
 
133
To determine the index of the smallest item in any iterable container, use ``min_index``:
 
134
 
 
135
.. doctest::
 
136
 
 
137
    >>> from cogent.util.misc import min_index
 
138
    >>> l = [5,4,2,2,6,8,0,10,0,5]
 
139
    >>> min_index(l)
 
140
    6
 
141
 
 
142
.. note:: Will return the lowest index of duplicate min values
 
143
 
 
144
Remove a nesting level
 
145
^^^^^^^^^^^^^^^^^^^^^^
 
146
 
 
147
To flatten a 2-dimensional list, you can use ``flatten``:
 
148
 
 
149
.. doctest::
 
150
 
 
151
    >>> from cogent.util.misc import flatten
 
152
    >>> l = ['abcd','efgh','ijkl']
 
153
    >>> flatten(l)
 
154
    ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']
 
155
 
 
156
Convert a nested tuple into a list
 
157
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
158
 
 
159
Conversion of a nested ``tuple`` into a ``list`` can be performed using ``deep_list``:
 
160
 
 
161
.. doctest::
 
162
 
 
163
    >>> from cogent.util.misc import deep_list
 
164
    >>> t = ((1,2),(3,4),(5,6))
 
165
    >>> deep_list(t)
 
166
    [[1, 2], [3, 4], [5, 6]]
 
167
 
 
168
Simply calling ``list`` will not convert the nested items:
 
169
 
 
170
.. doctest::
 
171
 
 
172
    >>> list(t)
 
173
    [(1, 2), (3, 4), (5, 6)]
 
174
 
 
175
Convert a nested list into a tuple
 
176
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
177
 
 
178
Conversion of a nested ``list`` into a ``tuple`` can be performed using ``deep_list``:
 
179
 
 
180
.. doctest::
 
181
 
 
182
    >>> from cogent.util.misc import deep_tuple
 
183
    >>> l = [[1,2],[3,4],[5,6]]
 
184
    >>> deep_tuple(l)
 
185
    ((1, 2), (3, 4), (5, 6))
 
186
 
 
187
Simply calling ``tuple`` will not convert the nested items:
 
188
 
 
189
.. doctest::
 
190
 
 
191
    >>> tuple(l)
 
192
    ([1, 2], [3, 4], [5, 6])
 
193
 
 
194
Testing if an item is between two values
 
195
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
196
 
 
197
Same as: min <= number <= max, although it is quickly readable within code
 
198
 
 
199
.. doctest::
 
200
 
 
201
    >>> from cogent.util.misc import between
 
202
    >>> between((3,5),4)
 
203
    True
 
204
    >>> between((3,5),6)
 
205
    False
 
206
 
 
207
Return combinations of items
 
208
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
209
 
 
210
``Combinate`` returns all k-combinations of items. For instance:
 
211
 
 
212
.. doctest::
 
213
 
 
214
    >>> from cogent.util.misc import combinate
 
215
    >>> list(combinate([1,2,3],0))
 
216
    [[]]
 
217
    >>> list(combinate([1,2,3],1))
 
218
    [[1], [2], [3]]
 
219
    >>> list(combinate([1,2,3],2))
 
220
    [[1, 2], [1, 3], [2, 3]]
 
221
    >>> list(combinate([1,2,3],3))
 
222
    [[1, 2, 3]]
 
223
 
 
224
Save and load gzip'd files
 
225
^^^^^^^^^^^^^^^^^^^^^^^^^^
 
226
 
 
227
These handy methods will ``cPickle`` an object and automagically gzip the file. You can also then reload the object at a later date.
 
228
 
 
229
.. doctest::
 
230
 
 
231
    >>> from cogent.util.misc import gzip_dump, gzip_load
 
232
    >>> class foo(object):
 
233
    ...   some_var = 5
 
234
    ... 
 
235
    >>> bar = foo()
 
236
    >>> bar.some_var = 10
 
237
    >>> # gzip_dump(bar, 'test_file')
 
238
    >>> # new_bar = gzip_load('test_file')
 
239
    >>> # isinstance(new_bar, foo)
 
240
 
 
241
.. note:: The above code does work, but cPickle won't write out within doctest
 
242
 
 
243
Curry a function
 
244
^^^^^^^^^^^^^^^^
 
245
 
 
246
curry(f,x)(y) = f(x,y) or = lambda y: f(x,y). This was modified from the Python Cookbook. Docstrings are also carried over.
 
247
 
 
248
.. doctest::
 
249
 
 
250
    >>> from cogent.util.misc import curry
 
251
    >>> def foo(x,y):
 
252
    ...   """Some function"""
 
253
    ...   return x + y
 
254
    ... 
 
255
    >>> bar = curry(foo, 5)
 
256
    >>> print bar.__doc__
 
257
     curry(foo,5)
 
258
    == curried from foo ==
 
259
     Some function
 
260
    >>> bar(10)
 
261
    15
 
262
 
 
263
Test to see if an object is iterable
 
264
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
265
 
 
266
Perform a simple test to see if an object supports iteration
 
267
 
 
268
.. doctest::
 
269
 
 
270
    >>> from cogent.util.misc import is_iterable
 
271
    >>> can_iter = [1,2,3,4]
 
272
    >>> cannot_iter = 1.234
 
273
    >>> is_iterable(can_iter)
 
274
    True
 
275
    >>> is_iterable(cannot_iter)
 
276
    False
 
277
 
 
278
Test to see if an object is a single char
 
279
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
280
 
 
281
Perform a simple test to see if an object is a single character
 
282
 
 
283
.. doctest::
 
284
 
 
285
    >>> from cogent.util.misc import is_char
 
286
    >>> class foo: 
 
287
    ...   pass
 
288
    ... 
 
289
    >>> is_char('a')
 
290
    True
 
291
    >>> is_char('ab')
 
292
    False
 
293
    >>> is_char(foo())
 
294
    False
 
295
 
 
296
Flatten a deeply nested iterable
 
297
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
298
 
 
299
To flatten a deeply nested iterable, use ``recursive_flatten``. This method supports multiple levels of nesting, and multiple iterable types
 
300
 
 
301
.. doctest::
 
302
 
 
303
    >>> from cogent.util.misc import recursive_flatten
 
304
    >>> l = [[[[1,2], 'abcde'], [5,6]], [7,8], [9,10]]
 
305
    >>> recursive_flatten(l)
 
306
    [1, 2, 'a', 'b', 'c', 'd', 'e', 5, 6, 7, 8, 9, 10]
 
307
 
 
308
Test to determine if ``list`` of ``tuple``
 
309
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
310
 
 
311
Perform a simple check to see if an object is not a list or a tuple
 
312
 
 
313
.. doctest::
 
314
 
 
315
    >>> from cogent.util.misc import not_list_tuple
 
316
    >>> not_list_tuple(1)
 
317
    True
 
318
    >>> not_list_tuple([1])
 
319
    False
 
320
    >>> not_list_tuple('ab')
 
321
    True
 
322
 
 
323
Unflatten items to row-width
 
324
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
325
 
 
326
Unflatten an iterable of items to a specified row-width. This does reverse the effect of ``zip`` as the lists produced are not interleaved.
 
327
 
 
328
.. doctest::
 
329
 
 
330
    >>> from cogent.util.misc import unflatten
 
331
    >>> l = [1,2,3,4,5,6,7,8]
 
332
    >>> unflatten(l,1)
 
333
    [[1], [2], [3], [4], [5], [6], [7], [8]]
 
334
    >>> unflatten(l,2)
 
335
    [[1, 2], [3, 4], [5, 6], [7, 8]]
 
336
    >>> unflatten(l,3)
 
337
    [[1, 2, 3], [4, 5, 6]]
 
338
    >>> unflatten(l,4)
 
339
    [[1, 2, 3, 4], [5, 6, 7, 8]]
 
340
 
 
341
Unzip items
 
342
^^^^^^^^^^^
 
343
 
 
344
Reverse the effects of a ``zip`` method, i.e. produces separate lists from tuples
 
345
 
 
346
.. doctest::
 
347
 
 
348
    >>> from cogent.util.misc import unzip
 
349
    >>> l = ((1,2),(3,4),(5,6))
 
350
    >>> unzip(l)
 
351
    [[1, 3, 5], [2, 4, 6]]
 
352
 
 
353
Select items in order
 
354
^^^^^^^^^^^^^^^^^^^^^
 
355
 
 
356
Select items in a specified order
 
357
 
 
358
.. doctest::
 
359
 
 
360
    >>> from cogent.util.misc import select
 
361
    >>> select('ea', {'a':1,'b':5,'c':2,'d':4,'e':6})
 
362
    [6, 1]
 
363
    >>> select([0,4,8], 'abcdefghijklm')
 
364
    ['a', 'e', 'i']
 
365
 
 
366
Obtain the index sort order
 
367
^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
368
 
 
369
Obtain the indices for items in sort order. This is similar to numpy.argsort, but will work on any iterable that implements the necessary ``cmp`` methods
 
370
 
 
371
.. doctest::
 
372
 
 
373
    >>> from cogent.util.misc import sort_order
 
374
    >>> sort_order([4,2,3,5,7,8])
 
375
    [1, 2, 0, 3, 4, 5]
 
376
    >>> sort_order('dcba')
 
377
    [3, 2, 1, 0]
 
378
 
 
379
Find overlapping pattern occurrences
 
380
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
381
 
 
382
Find all of the overlapping occurrences of a pattern within a text
 
383
 
 
384
.. doctest::
 
385
 
 
386
    >>> from cogent.util.misc import find_all
 
387
    >>> text = 'aaaaaaa'
 
388
    >>> pattern = 'aa'
 
389
    >>> find_all(text, pattern)
 
390
    [0, 1, 2, 3, 4, 5]
 
391
    >>> text = 'abababab'
 
392
    >>> pattern = 'aba'
 
393
    >>> find_all(text, pattern)
 
394
    [0, 2, 4]
 
395
 
 
396
Find multiple pattern occurrences
 
397
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
398
 
 
399
Find all of the overlapping occurrences of multiple patterns within a text. Returned indices are sorted, each index is the start position of one of the patterns
 
400
 
 
401
.. doctest::
 
402
 
 
403
    >>> from cogent.util.misc import find_many
 
404
    >>> text = 'abababcabab'
 
405
    >>> patterns = ['ab','abc']
 
406
    >>> find_many(text, patterns)
 
407
    [0, 2, 4, 4, 7, 9]
 
408
 
 
409
Safely remove a trailing underscore
 
410
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
411
 
 
412
'Unreserve' a mutation of Python reserved words
 
413
 
 
414
.. doctest::
 
415
 
 
416
    >>> from cogent.util.misc import unreserve
 
417
    >>> unreserve('class_')
 
418
    'class'
 
419
    >>> unreserve('class')
 
420
    'class'
 
421
 
 
422
Create a case-insensitive iterable
 
423
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
424
 
 
425
Create a case-insensitive object, for instance, if you want the key 'a' and 'A' to point to the same item in a dict
 
426
 
 
427
.. doctest::
 
428
 
 
429
    >>> from cogent.util.misc import add_lowercase
 
430
    >>> d = {'A':5,'B':6,'C':7,'foo':8,42:'life'}
 
431
    >>> add_lowercase(d)
 
432
    {'A': 5, 'a': 5, 'C': 7, 'B': 6, 42: 'life', 'c': 7, 'b': 6, 'foo': 8}
 
433
 
 
434
Extract data delimited by differing left and right delimiters
 
435
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
436
 
 
437
Extract data from a line that is surrounded by different right/left delimiters
 
438
 
 
439
.. doctest::
 
440
 
 
441
    >>> from cogent.util.misc import extract_delimited
 
442
    >>> line = "abc[def]ghi"
 
443
    >>> extract_delimited(line,'[',']')
 
444
    'def'
 
445
 
 
446
Invert a dictionary
 
447
^^^^^^^^^^^^^^^^^^^
 
448
 
 
449
Get a dictionary with the values set as keys and the keys set as values
 
450
 
 
451
.. doctest::
 
452
 
 
453
    >>> from cogent.util.misc import InverseDict
 
454
    >>> d = {'some_key':1,'some_key_2':2}
 
455
    >>> InverseDict(d)
 
456
    {1: 'some_key', 2: 'some_key_2'}
 
457
 
 
458
.. note:: An arbitrary key will be set if there are multiple keys with the same value
 
459
 
 
460
Invert a dictionary with multiple keys having the same value
 
461
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
462
 
 
463
Get a dictionary with the values set as keys and the keys set as values. Can handle the case where multiple keys point to the same values
 
464
 
 
465
.. doctest::
 
466
 
 
467
    >>> from cogent.util.misc import InverseDictMulti
 
468
    >>> d = {'some_key':1,'some_key_2':1}
 
469
    >>> InverseDictMulti(d)
 
470
    {1: ['some_key_2', 'some_key']}
 
471
    >>> 
 
472
 
 
473
Get mapping from sequence item to all positions
 
474
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
475
 
 
476
``DictFromPos`` returns the positions of all items seen within a sequence. This is useful for obtaining, for instance, nucleotide counts and positions
 
477
 
 
478
.. doctest::
 
479
 
 
480
    >>> from cogent.util.misc import DictFromPos
 
481
    >>> seq = 'aattggttggaaggccgccgttagacg'
 
482
    >>> DictFromPos(seq)
 
483
    {'a': [0, 1, 10, 11, 22, 24], 'c': [14, 15, 17, 18, 25], 't': [2, 3, 6, 7, 20, 21], 'g': [4, 5, 8, 9, 12, 13, 16, 19, 23, 26]}
 
484
 
 
485
Get the first index of occurrence for each item in a sequence
 
486
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
487
 
 
488
``DictFromFirst`` will return the first location of each item in a sequence
 
489
 
 
490
.. doctest::
 
491
    
 
492
    >>> from cogent.util.misc import DictFromFirst
 
493
    >>> seq = 'aattggttggaaggccgccgttagacg'
 
494
    >>> DictFromFirst(seq)
 
495
    {'a': 0, 'c': 14, 't': 2, 'g': 4}
 
496
 
 
497
Get the last index of occurrence for each item in a sequence
 
498
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
499
 
 
500
``DictFromLast`` will return the last location of each item in a sequence
 
501
 
 
502
.. doctest::
 
503
 
 
504
    >>> from cogent.util.misc import DictFromLast
 
505
    >>> seq = 'aattggttggaaggccgccgttagacg'
 
506
    >>> DictFromLast(seq)
 
507
    {'a': 24, 'c': 25, 't': 21, 'g': 26}
 
508
 
 
509
Construct a distance matrix lookup function
 
510
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
511
 
 
512
Automatically construct a distance matrix lookup function. This is useful for maintaining flexibility about whether a function is being computed or if a lookup is being used
 
513
 
 
514
.. doctest::
 
515
 
 
516
    >>> from cogent.util.misc import DistanceFromMatrix
 
517
    >>> from numpy import array
 
518
    >>> m = array([[1,2,3],[4,5,6],[7,8,9]])
 
519
    >>> f = DistanceFromMatrix(m)
 
520
    >>> f(0,0)
 
521
    1
 
522
    >>> f(1,2)
 
523
    6
 
524
 
 
525
Get all pairs from groups
 
526
^^^^^^^^^^^^^^^^^^^^^^^^^
 
527
 
 
528
Get all of the pairs of items present in a list of groups. A key will be created (i,j) iff i and j share a group
 
529
 
 
530
.. doctest::
 
531
 
 
532
    >>> from cogent.util.misc import PairsFromGroups
 
533
    >>> groups = ['ab','xyz']
 
534
    >>> PairsFromGroups(groups)
 
535
    {('a', 'a'): None, ('b', 'b'): None, ('b', 'a'): None, ('x', 'y'): None, ('z', 'x'): None, ('y', 'y'): None, ('x', 'x'): None, ('y', 'x'): None, ('z', 'y'): None, ('x', 'z'): None, ('a', 'b'): None, ('y', 'z'): None, ('z', 'z'): None}
 
536
 
 
537
Check class types
 
538
^^^^^^^^^^^^^^^^^
 
539
 
 
540
Check an object against base classes or derived classes to see if it is acceptable
 
541
 
 
542
.. doctest::
 
543
 
 
544
    >>> from cogent.util.misc import ClassChecker
 
545
    >>> class not_okay(object):
 
546
    ...   pass
 
547
    ... 
 
548
    >>> no = not_okay()
 
549
    >>> class okay(object):
 
550
    ...   pass
 
551
    ... 
 
552
    >>> o = okay()
 
553
    >>> class my_dict(dict):
 
554
    ...   pass
 
555
    ... 
 
556
    >>> md = my_dict()
 
557
    >>> cc = ClassChecker(str, okay, dict)
 
558
    >>> o in cc
 
559
    True
 
560
    >>> no in cc
 
561
    False
 
562
    >>> 5 in cc
 
563
    False
 
564
    >>> {'a':5} in cc
 
565
    True
 
566
    >>> 'asasas' in cc
 
567
    True
 
568
    >>> md in cc
 
569
    True
 
570
 
 
571
Delegate to a separate object
 
572
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
573
 
 
574
Delegate object method calls, properties and variables to the appropriate object. Useful to combine multiple objects together while assuring that the calls will go to the correct object.
 
575
 
 
576
.. doctest::
 
577
 
 
578
    >>> from cogent.util.misc import Delegator
 
579
    >>> class ListAndString(list, Delegator):
 
580
    ...   def __init__(self, items, string):
 
581
    ...     Delegator.__init__(self, string)
 
582
    ...     for i in items:
 
583
    ...       self.append(i)
 
584
    ... 
 
585
    >>> ls = ListAndString([1,2,3], 'ab_cd')
 
586
    >>> len(ls)
 
587
    3
 
588
    >>> ls[0]
 
589
    1
 
590
    >>> ls.upper()
 
591
    'AB_CD'
 
592
    >>> ls.split('_')
 
593
    ['ab', 'cd']
 
594
 
 
595
Wrap a function to hide from a class
 
596
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
597
 
 
598
Wrap a function to hide it from a class so that it isn't a method. 
 
599
 
 
600
.. doctest::
 
601
 
 
602
    >>> from cogent.util.misc import FunctionWrapper
 
603
    >>> f = FunctionWrapper(str)
 
604
    >>> f
 
605
    <cogent.util.misc.FunctionWrapper object at ...
 
606
    >>> f(123)
 
607
    '123'
 
608
 
 
609
Construct a constrained container
 
610
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
611
 
 
612
Wrap a container with a constraint. This is useful for enforcing that the data contained is valid within a defined context. PyCogent provides a base ``ConstrainedContainer`` which can be used to construct user-defined constrained objects. PyCogent also provides ``ConstrainedString``, ``ConstrainedList``, and ``ConstrainedDict``. These provided types fully cover the builtin types while staying integrated with the ``ConstrainedContainer``.
 
613
 
 
614
Here is a light example of the ``ConstrainedDict``
 
615
 
 
616
.. doctest::
 
617
 
 
618
    >>> from cogent.util.misc import ConstrainedDict
 
619
    >>> d = ConstrainedDict({'a':1,'b':2,'c':3}, Constraint='abc')
 
620
    >>> d
 
621
    {'a': 1, 'c': 3, 'b': 2}
 
622
    >>> d['d'] = 5
 
623
    Traceback (most recent call last):
 
624
    ConstraintError: Item 'd' not in constraint 'abc'
 
625
 
 
626
PyCogent also provides mapped constrained containers for each of the default types provided, ``MappedString``, ``MappedList``, and ``MappedDict``. These behave the same, except that they map a mask onto ``__contains__`` and ``__getitem__``
 
627
 
 
628
.. doctest::
 
629
 
 
630
    >>> def mask(x):
 
631
    ...   return str(int(x) + 3)
 
632
    ... 
 
633
    >>> from cogent.util.misc import MappedString
 
634
    >>> s = MappedString('12345', Constraint='45678', Mask=mask)
 
635
    >>> s
 
636
    '45678'
 
637
    >>> s + '123'
 
638
    '45678456'
 
639
    >>> s + '9'
 
640
    Traceback (most recent call last):
 
641
    ConstraintError: Sequence '9' doesn't meet constraint
 
642
 
 
643
Check the location of an application
 
644
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
645
 
 
646
Determine if an application is available on a system
 
647
 
 
648
.. doctest::
 
649
 
 
650
    >>> from cogent.util.misc import app_path
 
651
    >>> app_path('ls')
 
652
    '/bin/ls'
 
653
    >>> app_path('does_not_exist')
 
654
    False