-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchapter9.txt
More file actions
2089 lines (1680 loc) · 96.9 KB
/
chapter9.txt
File metadata and controls
2089 lines (1680 loc) · 96.9 KB
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
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{:: encoding="UTF-8" /}
# Introducción a Biopython
## ¿QUÉ ES BIOPYTHON?
**Biopython**[^nota9-1] es un paquete de módulos muy útil para desarrollar aplicaciones bioinformáticas. Si bien cada análisis bioinformática es único, hay algunas tareas que son repetitivas, constantes que son utilizadas por diferentes programas y formatos de archivo estándares. Está situación sugiere que necesitamos un paquete para lidiar con problemas biológicos.
Biopython comenzó como una idea en Agosto de 1999, por iniciativa de Jeff Chang and Andrew Dalke. Ni bien avanzaron con la idea rápidamente muchos colaboradores se unieron al proyecto. Entre los desarrolladores más activos se encuentran Brad Chapman, Peter Cock, Michie de Hoon e Iddo Friedberg entre otros. El proyecto comienza a tomar forma en febrero de 2000 y en julio de ese mismo año se hace el primer lanzamiento. La idea original fue construir un paquete equivalente a BioPerl, que en ese momento era el paquete principal para bioinformática. A pesar de que BioPerl fue la inspiración para el Biopython, las diferencias conceptuales entre Perl y Python hacen que Biopython tenga una forma particular de hacer las cosas. Biopython es parte de la familia de proyectos open-bio (también conocido como Bio*), por lo cual institucionalmente es un miembro de la Open Bioinformatics Foundation[^nota9-2].
[^nota9-1]: Disponible en <http://biopython.org>
[^nota9-2]: <http://www.open-bio.org>
### Organización del proyecto
Si bien Biopython es un proyecto de software libre, la Open Bioinformatics Foundation se ocupa de cuestiones administrativas, económicas y de aspectos generales, mientras que los contenidos son manejados por los desarrolladores y usuarios.
El código es de dominio público y está disponible en el repositorio <http://github.com/biopython/biopython> y cualquiera puede participar en el proyecto. El procedimiento que deben seguir para colaborar con Biopython es similar al de otros proyectos de software libre. Si utilizando el software determinan que es necesario incorporar nuevas características o modificar alguna de las existentes. Antes de escribir algo de código, mi recomendación es discutir primero tus ideas con el equipo de desarrollo en el mailing list[^nota9_3]. Allí encontrarás si la característica ha sido previamente discutida y fue rechazada, o sino fue incluido porque nadie la había necesitado antes. En el caso de una corrección de un error, no necesitas preguntar, solo reportarlo en el issue tracker[^nota9_4] y si es posible agregar una propuesta de solución.
Por la naturaleza de los proyectos muchas personas de campos muy diversos de la bioinformática han contribuido, desde la teoría de la información a la genética de poblaciones.
Yo estoy involucrado en Biopython como usuario desde 2002 y submiti mi primera contribución en 2003 con lcc.py, una función para calcular la complejidad local de la composición de una secuencia. En 2004 sume el código para calcular el punto de fusión de los oligonucleótidos. En 2007 contribui con algunas funciones para el módulo CheckSum[^nota9_5]. Mi última contribución fue un parche a el módulo Bio.Restriction (2017). En todos los casos encontre un gran soporte de la comunidad, en especial en la primera contribución cuando mis habilidades de programación eran de un nivel de principiante.
Para más información de como participar en el proyecto Biopython, ver las instrucciones en <http://biopython.org/wiki/Contributing>.
El código de Biopython está desarrollado bajo la Licencia de Biopython (Biopython License)[^nota9_6]. Es muy libre y virtualmente no hay ninguna restricción para su uso[^nota9_7].
[^nota9_3]: http://biopython.org/wiki/Mailing_lists
[^nota9_4]: https://github.com/biopython/biopython/issues
[^nota9_5]: Bassi, Sebastian, and Gonzalez, Virginia. New checksum functions for Biopython. Available from Nature Precedings <http://dx.doi.org/10.1038/npre.2007.278.1> (2007).
[^nota9_6]: La licencia está incluida en el paquete de Biopython y disponible en <http://www.biopython.org/DIST/LICENSE>.
[^nota9_7]: La única condición impuesta para usar Biopython es citar correctamente el proyecto y no utilizar el nombre de los colaboradores en publicidades.
## INSTALANDO BIOPYTHON
**En macOS/Linux**
Los siguientes comandos muestran como instalar Biopython bajo una **virtualenv**. Primero instalar **virtualenv** (si no esta instalada):
{line-numbers=off}
```
$ pip install virtualenv
Collecting virtualenv
Using cached virtualenv-15.1.0-py2.py3-none-any.whl
Installing collected packages: virtualenv
Successfully installed virtualenv-15.1.0
You are using pip version 8.1.1, however version 9.0.1 is available. <=
You should consider upgrading via the 'pip install --upgrade pip' command.
$ pip install --upgrade pip Collecting pip
(...)
```
Crear una virtualenv para Biopython (en este caso la virtualenv es llamada `py4biovirtualenv`)
{line-numbers=off}
```
$ virtualenv py4biovirtualenv
Using base prefix '/usr'
New python executable in /home/sb/py4biovirtualenv/bin/python3 Also <=
creating executable in /home/sb/py4biovirtualenv/bin/python Installing<=
setuptools, pip, wheel...done.
```
Activa la virtualenv
{line-numbers=off}
```
$ . py4biovirtualenv/bin/activate
(py4biovirtualenv) $
```
Dentro de la virtualenv instalar *numpy* y luego *biopython*
{line-numbers=off}
```
(py4biovirtualenv) $ pip install numpy
Collecting numpy
(...)
Installing collected packages: numpy
Successfully installed numpy-1.11.2
(py4biovirtualenv) $ pip install biopython
Collecting biopython
(...)
Successfully installed biopython-1.68
(py4biovirtualenv) $ python
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import Bio
>>> Bio.__version__
'1.68'
```
Si estas usando Anaconda, en lugar de correr una **virtualenv**, usar **conda create**. Necesitas hacerlo solo una vez.
{line-numbers=off}
```
$ conda create -n biopy python
Fetching package metadata: ....
Solving package specifications: ........
Package plan for installation in environment /sb/anaconda3/envs/biopy:
The following packages will be downloaded:
|package |buid |
|--------|-----|
|pip-9.0.1 |py35_1 1.7 MB|
(...)
#
# To activate this environment, use:
# $ source activate biopy
#
# To deactivate this environment, use: # $ source deactivate
#
```
Una vez que el ambiente conda (equivalente a una virtualenv) está creado, necesitas activarlo. Esto lo debes hacer cada vez que necesites usar el ambiente:
{line-numbers=off}
```
$ source activate biopy
discarding /sb/anaconda3/bin from PATH
prepending /sb/anaconda3/envs/biopy/bin to PATH
(biopy)$
```
En el ambiente conda, instalar Biopython usando **conda** en lugar de **pip**:
{line-numbers=off}
```
(biopy)$ conda install biopython
Fetching package metadata: ....
Solving package specifications: ...............
Package plan for installation in environment /sb/anaconda3/envs/biopy:
The following packages will be downloaded:
(...)
The following NEW packages will be INSTALLED:
biopython: 1.68-np111py35_0
mkl: 11.3.3-0
numpy: 1.11.2-py35_0
Proceed ([y]/n)?
(...)
```
Testear que el paquete de Biopython esta instalado:
{line-numbers=off}
```
(biopy)$ python
Python 3.5.2 |Continuum Analytics, Inc.| (default, Jul 2 2016) [GCC 4.<=
4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import Bio
>>> Bio.__version__
'1.68'
```
**En Windows**
No hay un paquete oficial de Biopython para Windows de 64-bit (la arquitectura más común de Windows), por lo tanto la instalación no es tan simple. El primer paso es bajar un paquete no oficial en <http://lfd.uci.edu/~gohlke/pythonlibs>, hay que elegir cuidadosamente ya que hay muchos archivos en esta página. Este debe coincidir con la versión de Python y la arquitectura del microprocesador que estemos usando. Para Python 3.6 en una máquina de 64-bit, baja `biopython-1.68-cp36m-win_amd64.whl`. Una vez bajado el archivo tomar nota de donde es bajado ya que necesitarás está información en el siguiente paso. Dado que Python tiene el **pip** preinstalado desde la versión 2.7.9, puedes usarlo desde la terminal:
{line-numbers=off}
```
c:\Users\sb\AppData\Local\Programs\Python36\Scripts> pip install c:<=
\Users\sb\Downloads\biopython-1.68-cp36-cp36m-win_amd64.whl
```
Esto instalará **Biopython**.
## COMPONENTES DE BIOPYTHON
Biopython tiene varios módulos, algunos de los cuales facilitan las tareas que se realizan que diariamente en los laboratorios de biología molecular. Otros módulos tienen objetivos mucho más específicos. Qué es lo "comúnmente usado" dependerá del ambiente de trabajo del lector, lo que muestro a continuación es una compilación basada en mi perspectiva personal sobre lo que es más usado.
Todas las enumeraciones son arbitrarias y es posible que no reflejen los intereses de todos los lectores. Las enumeraciones están ordenadas de un modo didáctico con el objetivo que los primeros temas ayuden a entender al resto.
### Alfabeto
En bioinformática trabajamos con alfabetos. DNA tiene un alfabeto de cuatro letras (A, C, T, G) mientras las proteínas tienen sus 20 aminoácidos, cada uno representado por una letra del alfabeto (cuando se usa la representación de una letra). También hay "alfabetos" especiales como los que contemplan posiciones ambiguas. Se trata de posiciones donde más de un nucleótido puede estar presente. Por ejemplo, la letra S puede representar los ácidos nucleicos C o G y la letra H representa a A, C o T. En Biopython este alfabeto ambiguo es llamado **ambigous_dna**. En el caso de la proteínas hay un diccionario extendido que contiene aminoácidos que normalmente no se encuentran en las proteínas[^nota9-8] (**ExtendedIUPACProtein**). También hay un alfabeto extendido para nucleótidos (**ExtendedIUPACDNA**) que permite letras con bases modificadas. En proteínas hay también un alfabeto reducido que agrupa aquellos aminoácidos con propiedades fisicoquímicas en común representados por una letra.
Incluso hay un alfabeto que no está basado ni ADN ni aminoácidos: **SecondaryStructure**. Este alfabeto representa los dominios como **H**elix (hélice), **T**urn (giros), **S**trand (hebra) y **C**oil (espiral). Los alfabetos definidos por IUPAC se almacenan en Biopython como clases del módulo **IUPAC**. El módulo principal (**Bio.Alphabet**) incluye casos más generales. Aquí vemos algunos atributos de los alfabetos:
[^nota9-8]: Selenocisteína y pirrolisina son ejemplos típicos de aminoácidos atípicos.
{line-numbers=off}
```
>>> import Bio.Alphabet
>>> Bio.Alphabet.ThreeLetterProtein.letters
['Ala', 'Asx', 'Cys', 'Asp', 'Glu', 'Phe', 'Gly', 'His', <=
'Ile', 'Lys', 'Leu', 'Met', 'Asn', 'Pro', 'Gln', 'Arg', <=
'Ser', 'Thr', 'Sec', 'Val', 'Trp', 'Xaa', 'Tyr', 'Glx']
>>> from Bio.Alphabet import IUPAC
>>> IUPAC.IUPACProtein.letters
'ACDEFGHIKLMNPQRSTVWY'
>>> IUPAC.unambiguous_dna.letters
'GATC'
>>> IUPAC.ambiguous_dna.letters
'GATCRYWSMKHBVDN'
>>> IUPAC.ExtendedIUPACProtein.letters
'ACDEFGHIKLMNPQRSTVWYBXZJUO'
>>> IUPAC.ExtendedIUPACDNA.letters
'GATCBDSW'
```
Los alfabetos son usados para definir el contenido de una secuencia. ¿Cómo sabes que la secuencia "CCGGGTT" es un péptido pequeño con cisteína, glicina y treonina o es un fragmento de ADN de citocinas, guaninas y timinas? Si las secuencias se almacenarán como cadenas, no habría manera de saber qué tipo de secuencia es. Por esta razón Biopython introduce los objetos **Seq**.
### Seq
Este objeto está compuesto por la secuencia y un **alfabeto** que define la naturaleza de la secuencia.
Vamos a crear un objeto secuencia como un fragmento de ADN:
{line-numbers=off}
```
>>> from Bio.Seq import Seq
>>> import Bio.Alphabet
>>> seq = Seq('CCGGGTT', Bio.Alphabet.IUPAC.unambiguous_dna)
```
Dado que esta secuencia (`seq`) está definida como DNA podes aplicarle todas las operaciones que están permitidas en una secuencia de ADN. Los objetos **seq** tienen los métodos **transcribe** (transcribir) and **translate** (traducir):
{line-numbers=off}
```
>>> seq.transcribe()
Seq('CCGGGUU', IUPACUnambiguousRNA())
>>> seq.translate()
BiopythonWarning: Partial codon, len(sequence) not a multiple of three.
Explicitly trim the sequence or add trailing N before translation.<=
This may become an error in future.
Seq('PG', IUPACProtein())
```
Una secuencia de ARN no puede ser transcripta pero si puede ser traducida:
{line-numbers=off}
```
>>> rna_seq = Seq('CCGGGUU',Bio.Alphabet.IUPAC.unambiguous_rna)
>>> rna_seq.transcribe()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/sb/Seq.py", line 520, in transcribe
raise ValueError("RNA cannot be transcribed!")
ValueError: RNA cannot be transcribed!
>>> rna_seq.translate()
Seq('PG', IUPACProtein())
```
Podemos volver desde el ARN al ADN usando el método **back_transcribe**:
{line-numbers=off}
```
>>> rna_seq.back_transcribe()
Seq('CCGGGTT', IUPACUnambiguousDNA())
```
T> ### La función de transcripción (transcribe) en Biopython
T> Hay que tener en cuenta que la función **transcribe** puede no funcionar como espera la mayoría de los biólogos. Esta función reemplaza cada aparición de "T" en la secuencia con una "U". En biología, una transcripción significa reemplazar cada nucleótido de ADN con su nucleótido complementario y la reversa de la cadena resultante. La función **transcribe** funciona de esta manera porque todas las publicaciones biológicas muestran la cadena complementaria. Biopython asume que le estás dando la cadena complementaria a la función. El módulo **Bio.Seq** también tiene las funciones de transcripción, transcripción inversa y traducción, que se pueden usar en los objetos o cadenas de Seq:
{line-numbers=off}
```
>>> from Bio.Seq import translate, transcribe, back_transcribe
>>> dnaseq = 'ATGGTATAA'
>>> translate(dnaseq)
'MV*'
>>> transcribe(dnaseq)
'AUGGUAUAA'
>>> rnaseq = transcribe(dnaseq)
>>> translate(rnaseq)
'MV*'
>>> back_transcribe(rnaseq)
'ATGGTATAA'
```
**Los objetos Seq como una cadena**
Los objetos Seq se comportan casi como una cadena por lo tanto las operaciones aplicadas a cadenas son permitidas:
{line-numbers=off}
```
>>> seq = Seq('CCGGGTTAACGTA',Bio.Alphabet.IUPAC.unambiguous_dna)
>>> seq[:5]
Seq('CCGGG', IUPACUnambiguousDNA())
>>> len(seq)
13
>>> print(seq)
CCGGGTTAACGTA
```
Este comportamiento está constantemente evolucionando por lo que esperamos más características similares a una cadena en los próximos lanzamientos de Biopython.
Si se necesita una representación de la cadena de un objeto Seq, se puede usar la función incorporada de Python **str()**. También está el método **tostring()** que también funciona, pero se recomienda solo si desea que el código sea compatible con versiones anteriores de Biopython.
### MutableSeq
Los objetos **Seq** no son mutables. Esto está destinado a que se puedan mantener los datos sin cambios. De esta manera, seq inmutable coincide con el comportamiento de la cadena en Python. Intentar modificarlo genera una excepción:
{line-numbers=off}
```
>>> seq[0] = 'T'
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: 'Seq' object does not support item assignment
```
Este problema puede ser resuelto generando un **MutableSeq** con el método **tomutable()**:
{line-numbers=off}
```
>>> mut_seq = seq.tomutable()
>>> mut_seq
MutableSeq('CCGGGTTAACGTA', IUPACUnambiguousDNA())
```
Introducir un cambio para testear si es mutable:
{line-numbers=off}
```
>>> mut_seq[0] = 'T'
>>> mut_seq
MutableSeq('TCGGGTTAACGTA', IUPACUnambiguousDNA())
```
Podemos cambiar la secuencia como si fuera una lista con **append()**, **insert()**, **pop()** y **remove()**. Existen algunos métodos específicos para manipular una secuencia de ADN:
{line-numbers=off}
```
>>> mut_seq.reverse()
>>> mut_seq
MutableSeq('ATGCAATTGGGCT', IUPACUnambiguousDNA())
>>> mut_seq.complement()
>>> mut_seq
MutableSeq('TACGTTAACCCGA', IUPACUnambiguousDNA())
>>> mut_seq.reverse_complement()
>>> mut_seq
MutableSeq('TCGGGTTAACGTA', IUPACUnambiguousDNA())
```
### SeqRecord
La clase **Seq** es importante porque almacena el sujeto principal de estudio en bioinformática: la secuencia. A veces necesitamos más información que la secuencia sola como, el nombre, el id, la descripción y las referencias cruzadas a bases de datos externas y anotaciones. Para toda esta información relacionada con la secuencia existe la clase **SeqRecord**. En otras palabras, un **SeqRecord** es un objeto **Seq** con metadata asociada.
{line-numbers=off}
```
>>> from Bio.SeqRecord import SeqRecord
>>> SeqRecord(seq, id='001', name='MHC gene')
SeqRecord(seq=Seq('CCGGGTTAACGTA', IUPACUnambiguousDNA()), id='001'<=
, name='MHC gene', description='<unknown description>', dbxrefs=[])
```
SeqRecord tiene dos atributos principales:
**id** Una cadena con un identificador. Este atributo es opcional pero altamente recomendado.
**seq** Un objeto Seq. Este atributo es requerido.
También hay algunos atributos adicionales:
**name** Una cadena con el nombre de la secuencia.
**description** Una cadena con más información.
**dbxrefs** Una lista de cadenas; cada cadena es el id de una base de datos de referencia cruzada.
**features** Una lista de objetos **SeqFeature** que representan las caracteristicas de las secuencias de los registros en Genbank. Este atributo es usualmente completado cuando recuperamos una secuencia de GenBank (usando por ejemplo el parser **SeIO**). Dicho atributo contiene la ubicación de la secuencia, el tipo, la hebra y otras variables.
**annotations** Un diccionario con más información de la secuencia entera. Este atributo no puede ser establecido cuando se inició un objeto **SeqRecord**.
Creando un objeto **SeqRecord** desde cero:
{line-numbers=off}
```
>>> from Bio.SeqRecord import SeqRecord
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import generic_protein
>>> rec = SeqRecord(Seq('mdstnvrsgmksrkkkpkttvidddddcmtcsacqs'
'klvkisditkvsldyintmrgntlacaacgsslkll',
generic_protein),
id = 'P20994.1', name = 'P20994',
description = 'Protein A19',
dbxrefs = ['Pfam:PF05077', 'InterPro:IPR007769',
'DIP:2186N'])
>>> rec.annotations['note'] = 'A simple note'
>>> print(rec)
ID: P20994.1
Name: P20994
Description: Protein A19
Database cross-references: Pfam:PF05077, InterPro:IPR007769, DIP<=
:2186N
Number of features: 0
/note=A simple note
Seq('mdstnvrsgmksrkkkpkttvidddddcmtcsacqsklvkisditkvsldyint...kl<=
l', ProteinAlphabet())
```
Para crear un SeqRecord desde un archivo GenBank, ver la [sección de SeqIO](#cap9-seqio).
### Align
El módulo **Align** contiene el código para trabajar con alineamientos. El objeto central de este módulo es la clase **MultipleSeqAlignment**. Este objeto almacena los alineamientos de secuencias. Lo cual no significa que hace los alineamientos, se supone que las secuencias ya están alineadas antes de almacenar los alineamientos en el objeto.
Aquí podemos ver un alineamiento simple de dos péptidos pequeños:
{line-numbers=off}
```
MHQAIFIYQIGYPLKSGYIQSIRSPEYDNW
|| ||||||||*|||||||||||||| ||
MH--IFIYQIGYALKSGYIQSIRSPEY-NW
```
Este alineamiento puede ser almacenado en un objeto usando Biopython como se muestra en el Listado 9.1:
**Listado 9.1:** `align2seqs.py`: Usando el módulo **Align**
```
from Bio.Alphabet import generic_protein
from Bio.Align import MultipleSeqAlignment
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
seq1 = 'MHQAIFIYQIGYPLKSGYIQSIRSPEYDNW'
seq2 = 'MH--IFIYQIGYALKSGYIQSIRSPEY-NW'
seq_rec_1 = SeqRecord(Seq(seq1, generic_protein), id = 'asp')
seq_rec_2 = SeqRecord(Seq(seq2, generic_protein), id = 'unk')
align = MultipleSeqAlignment([seq_rec_1, seq_rec_2])
print(align)
```
**Explicación del código**: La clase **MultipleSeqAlignment** es llamada en la línea 9. `align` es el nombre del objeto MultipleSeqAlignment. Ambas secuencias son agregadas en la inicialización del objeto **MultipleSeqAlignment** como objetos **SeqRecord**.
Salida del código previo:
{line-numbers=off}
```
ProteinAlphabet() alignment with 2 rows and 30 columns
MHQAIFIYQIGYPLKSGYIQSIRSPEYDNW asp
MH--IFIYQIGYALKSGYIQSIRSPEY-NW unk
```
**MultipleSeqAlignment** puede ser tratado como una lista de secuencias (o los objetos **SeqRecord**), este comparte varios de sus métodos. Para agregar una nueva secuencia al alineamiento usamos **append** y para agregar secuencias múltiples, **extend**:
{line-numbers=off}
```
>>> seq3 = 'M---IFIYQIGYAAKSGYIQSIRSPEY--W'
>>> seq_rec_3 = SeqRecord(Seq(seq3, generic_protein), id = 'cas')
>>> align.append(seq_rec_3)
>>> print(align)
ProteinAlphabet() alignment with 3 rows and 30 columns
MHQAIFIYQIGYPLKSGYIQSIRSPEYDNW asp
MH--IFIYQIGYALKSGYIQSIRSPEY-NW unk
M---IFIYQIGYAAKSGYIQSIRSPEY--W cas
```
Como podemos ver el nuevo objeto **SeqRecord** debe tener la misma longitud que el alineamiento original y un alfabeto compatible con el alfabeto del alineamiento.
Otra propiedad en común que tiene con las listas es que podes traer un elemento (una fila o un objeto **SeqRecord**) usándolo como un índice entero:
{line-numbers=off}
```
>>> align[0]
SeqRecord(seq=Seq('MHQAIFIYQIGYPLKSGYIQSIRSPEYDNW', ProteinAlphabet()),<=
id='asp', name='<unknown name>', description='<unknown description>', <=
dbxrefs=[])
```
Usar *slice notation* de Python en lugar de un índice entero para traer un subalineamiento:
{line-numbers=off}
```
>>> print(align[:2,5:11])
ProteinAlphabet() alignment with 2 rows and 6 columns
FIYQIG asp
FIYQIG unk
```
Como en cualquier secuencia de Python podemos obtener la longitud del alineamiento con **len()**:
{line-numbers=off}
```
>>> len(align)
3
```
También soporta la interacción sobre todos sus elementos retornando un objeto **SeqRecord** para cada secuencia.
El siguiente código calcula el punto isoeléctrico de cada secuencia del alineamiento:
{line-numbers=off}
```
>>> from Bio.SeqUtils.ProtParam import ProteinAnalysis
>>> for seq in align:
... print(ProteinAnalysis(str(seq.seq)).isoelectric_point())
6.50421142578125
8.16033935546875
8.13848876953125
```
### AlignIO
Para leer un archivo con un alineamiento usamos **AlignIO.read()**. Esto requiere dos parámetros: El nombre del archivo (o el file handle) y el formato del alineamiento. Los formatos son: clustal, emboss, fasta, fasta-m10, ig, maf, nexus, phylip, phylip-sequential, phylip-relaxed y stockholm. El método **AlignIO.read()** devuelve un objeto **Multiple-SeqAlignment**.
{line-numbers=off}
```
>>> from Bio import AlignIO
>>> AlignIO.read('cas9al.fasta', 'fasta')
print(align)
SingleLetterAlphabet() alignment with 8 rows and 1407 columns
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD J7M7J1
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD A0A0C6FZC2
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD A0A1C2CVQ9
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD A0A1C2CV43
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD Q48TU5
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD M4YX12
MKKPYSIGLDIGTNSVGWAVVTDDYKVPAKKMKVLGNTDKSHIK...GGD A0A0E2EP65
--------------------------------------------...GED A0A150NVN1
```
Para leer archivos con más de un alineamiento usamos **AlignIO.parse()**. Este toma los mismos argumentos que **AlignIO.read()** y devuelve un iterador con todos los alineamientos presentes en el archivo. Lo que significa que será usado como un loop:
{line-numbers=off}
```
>>> from Bio import AlignIO
>>> for alignment in AlignIO.parse('example.aln', 'clustal'):
... print(len(alignment))
1098
233
```
Para escribir un alineamiento a disco usamos **AlignIO.write()**. Este método requiere como primer parámetro el objeto **MultipleSeqAlignment** y luego necesita los mismos parámetros que **AlignIO.read()** (nombre del archivo y formato). Los formatos aceptados son: clustal, fasta, maf, nexus, phylip, phylip-sequential, phylip-relaxed y stockholm. El método **AlignIO.write()** retorna el número de alineamientos guardados:
{line-numbers=off}
```
>>> from Bio import AlignIO
>>> AlignIO.write(align, 'cas9al.phy', 'phylip')
1
```
Hay una función *helper* para convertir archivos de alineamientos en un paso: **AlignIO.convert()**. Tomamos cuatro parámetros: nombre del archivo a leer, formato del archivo para leer, nombre del archivo a escribir y el formato del archivo a escribir. También retorna el número de alineamientos guardados:
{line-numbers=off}
```
>>> from Bio import AlignIO
>>> AlignIO.convert('cas9al.fasta', 'fasta', 'cas9al.aln', 'clustal')
1
```
**AlignInfo**
El módulo AlignInfo es usado para extraer información de los objetos alineamientos. El módulo provee la función y las clases **SummaryInfo** y **PSSM**:
* **print_info_content**:
Veamoslo en acción:
{line-numbers=off}
```
>>> from Bio import AlignIO
>>> from Bio.Align.AlignInfo import SummaryInfo
>>> from Bio.Alphabet import ProteinAlphabet
>>> align = AlignIO.read('cas9align.fasta', 'fasta')
>>> align._alphabet = ProteinAlphabet()
>>> summary = SummaryInfo(align)
>>> print(summary.information_content())
4951.072487965924
>>> summary.dumb_consensus(consensus_alpha=ProteinAlphabet())
Seq('MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIKKNL...GGD',<=
ProteinAlphabet())
>>> summary.gap_consensus(consensus_alpha=ProteinAlphabet())
Seq('MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIKKNL...GGD',<=
ProteinAlphabet())
>>> print(summary.alignment)
ProteinAlphabet() alignment with 8 rows and 1407 columns
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD J7M7J1
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD A0A0C6FZC2
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD A0A1C2CVQ9
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD A0A1C2CV43
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD Q48TU5
MDKKYSIGLDIGTNSVGWAVITDDYKVPSKKFKVLGNTDRHSIK...GGD M4YX12
MKKPYSIGLDIGTNSVGWAVVTDDYKVPAKKMKVLGNTDKSHIK...GGD A0A0E2EP65
--------------------------------------------...GED A0A150NVN1
>>> print(summary.pos_specific_score_matrix())
- A C D E F G H I K L M N P Q
M 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7.0 0.0 0.0
D 1.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0
K 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7.0 0.0 0.0 0.0 0.0
K 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 1.0
Y 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
S 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
I 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7.0 0.0 0.0 0.0 0.0 0.0
G 1.0 0.0 0.0 0.0 0.0 0.0 7.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
L 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7.0 0.0 0.0 0.0
D 1.0 0.0 0.0 7.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
```
### ClustalW
Este módulo tiene clases y funciones para interactuar con el **ClustalW**[^nota9-9]. Seguramente conocen **ClustaIX**, un programa gráfico para alineamientos múltiples muy popular creado por Julie Thompson y Francois Jeanmougin. El ClustalX es una interfaz gráfica para el ClustalW, un programa para hacer alineamientos múltiples desde la línea de comando.
Biopython tiene soporte para ClustalW con el wrapper **ClustalCommandline**. Esta clase puede ser usada para construir la línea de comando del ClustalW.
[^nota9-9]: Este programa está disponible en <http://www.clustal.org/download/current>.
{line-numbers=off}
```
>>> from Bio.Align.Applications import ClustalwCommandline
>>> clustalw_exe = 'clustalw2'
>>> ccli = ClustalwCommandline(clustalw_exe, <=
infile="input4align.fasta", outfile='../../aoutput.aln')
>>> print(ccli)
clustalw2 -infile=input4align.fasta -outfile=../../aoutput.aln
```
Si el programa `clustalw` no está en el path de tu sistema se debe especificar la ubicación cuando se inicializa el objeto. Por ejemplo, si el `clustalw` esta en `c:\windows\program file\clustal\clustalw.exe` reemplazamos la línea:
{line-numbers=off}
```
>>> clustalw_exe = 'clustalw2'
```
por
{line-numbers=off}
```
>>> clustalw_exe='c:\\windows\\program file\\clustal\\clustalw.exe'
```
Para correr el programa llamamos a la instancia creada:
{line-numbers=off}
```
>>> from Bio.Align.Applications import ClustalwCommandline
>>> clustalw_exe = 'clustalw2'
>>> ccli = ClustalwCommandline(clustalw_exe,
infile="input4align.fasta", outfile='../../aoutput.aln')
>>> ccli()
('\n\n\n CLUSTAL 2.1 Multiple Sequence Alignments\n\n\nSequence <=
format is Pearson\nSequence 1: AGA92859.1 106 aa\nSequence 2: <=
AML31452.1 116 aa\nSequence 3: AAH03888.1 473 aa\nSequence 4 <=
: BAE71953.1 118 aa\nStart of Pairwise alignments\nAligning... <=
\n\nSequences (1:2) Aligned. Score: 88\nSequences (1:3) Aligned <=
. Score: 93\nSequences (1:4) Aligned. Score: 82\nSequences (2: <=
(...)
[alignoutput.txt]\n\n', '')
```
La función retorna una tupla con dos valores. El primer valor es lo que devuelve el programa (también denominado salida estándar) mientras que el segundo es el mensaje de error, si lo hay.
Para procesar la salida, se lee el archivo con **AlignIO.read()**:
{line-numbers=off}
```
>>> from Bio import AlignIO
>>> seqs = AlignIO.read('../../aoutput.aln', 'clustal')
>>> seqs[0] SeqRecord(seq=Seq('-------------------QVQLQQSDAELVKPGASVKISCKVSG<=
YTFTDHTIH...---', SingleLetterAlphabet()), id='AGA92859.1', name<=
='<unknown name>', description='AGA92859.1', dbxrefs=[])
>>> seqs[1]
SeqRecord(seq=Seq('MEWSWVFLFFLSVTTGVHSQVQLQQSDAELVKPGASVKISCKVSG<=
YTFTDHTIH...PGK', SingleLetterAlphabet()), id='AAH03888.1', name<=
='<unknown name>', description='AAH03888.1', dbxrefs=[])
>>> seqs[2]
SeqRecord(seq=Seq('-------------------EVQLQESDAELVKPGASVKISCKVSG<=
YTFTDHSIH...---', SingleLetterAlphabet()), id='AML31452.1', name<=
='<unknown name>', description='AML31452.1', dbxrefs=[])
```
**Pasando parámetros al ClustalW**
Para pasar más parámetros al Clustalw lo hacemos cuando se inicializa **ClustalwCommmandline**. Por ejemplo para cambiar el *Gap opening penalty* usamos *pwgapopen*:
{line-numbers=off}
```
>>> from Bio.Align.Applications import ClustalwCommandline
>>> clustalw_exe = 'clustalw2'
>>> ccli = ClustalwCommandline(clustalw_exe,
infile="input4align.fasta", outfile='../../aoutput.aln',
pwgapopen=5)
>>> print(ccli)
clustalw2 -infile=input4align.fasta -outfile=../../aoutput.aln <=
-pwgapopen=5
```
Para ver el resto de los parámetros disponibles hacer:
{line-numbers=off}
```
>>> from Bio.Align.Applications import ClustalwCommandline
>>> ccli = ClustalwCommandline()
>>> help(ccli)
```
o ver el manual online en <https://goo.gl/dJwoJx> o en la página de la página de la API: <http://biopython.org/DIST/docs/api/>.
### SeqIO {#cap9-seqio}
**BioSeqIO** es una interfaz común para entrada y salida de formatos de archivos de secuencias. Las secuencias traídas con esta interfaz son pasadas al programa como objetos **SeqRecord**. **Bio.SeqIO** puede leer también formatos de archivos de secuencias y retornar cada récord como un objeto **SeqRecord**. Para traer un alineamiento como un objeto **Alignment** usamos el módulo **Bio.AlignIO**.
**Leyendo archivos de secuencias**
El método usado para leer secuencias es **parse(file_handle, format)**. Donde `format` puede ser "fasta", "genbank" o cualquiera de los listados en la Tabla 10.1. Este parser retorna un generador. Los elementos retornados por este generador son del tipo SeqRecord:
{line-numbers=off}
```
>>> from Bio import SeqIO
>>> f_in = open('../../samples/a19.gp')
>>> seq = SeqIO.parse(f_in, 'genbank')
>>> next(seq)
SeqRecord(seq=Seq('MGHHHHHHHHHHSSGHIDDDDKHMLEMDSTNVRSGMKSRKKKPKT<=
TVIDDDDDC...FAS', IUPACProtein()), id='AAX78491.1', name='AAX784<=
91', description='unknown [synthetic construct]', dbxrefs=[])
```
Cuando solo hay una secuencia en el archivo usamos **SeqIO.read()** en lugar de **SeqIO.parse()**:
{line-numbers=off}
```
>>> f_in = open('../../samples/a19.gp')
>>> SeqIO.read(f_in, 'genbank')
SeqRecord(seq=Seq('MGHHHHHHHHHHSSGHIDDDDKHMLEMDSTNVRSGMKSRKKKPKT<=
TVIDDDDDC...FAS', IUPACProtein()), id='AAX78491.1', name='AAX784<=
91', description='unknown [synthetic construct]', dbxrefs=[])
```
En el Listado 9.2 hay un script que lee un archivo completo de secuencias en formato FASTA y muestra el título y la longitud de cada entrada:
**Listado 9.2:** `readfasta.py`: Leer un archivo de FASTA.
```
from Bio import SeqIO
FILE_IN = '../../samples/3seqs.fas'
with open(FILE_IN) as fh:
for record in SeqIO.parse(fh, 'fasta'):
id_ = record.id
seq = record.seq
print('Name: {0}, size: {1}'.format(id_, len(seq)))
```
Contenido del archivo de entrada (`3seqs.fas`)
{line-numbers=off}
```
>Protein-X [Simian immunodeficiency virus]
NYLNNLTVDPDHNKCDNTTGRKGNAPGPCVQRTYVACH
>Protein-Y [Homo sapiens]
MEEPQSDPSVEPPLSQETFSDLWKLLPENNVLSPLPSQAMDDLMLSPDDIEQWFTEDPGPDA
>Protein-Z [Rattus norvegicus]
MKAAVLAVALVFLTGCQAWEFWQQDEPQSQWDRVKDFATVYVDAVKDSGRDYVSQFESST
```
El Listado 9.2 parsea el archivo `3seqs.fas` y genera la siguiente salida:
{line-numbers=off}
```
(biopy169) $ python readfasta.py
Name: Protein-X, size: 38
Name: Protein-Y, size: 62
Name: Protein-Z, size: 60
```
Tabla 9.1 Formatos de secuencias y alineamientos.
| Nombre del formato | Descripión | Alineamiento (A) - Secuencia (S) |
| ------------------ | ---------- | -------------------------------- |
| ace | Lee las secuencias de un conting desde un archivo de ensamblado. | S |
| embl | Formato plano de archivos del EMBL | S |
| emboss | Formato de alineamientos "pares" y "simple" de las herramientas de EMBOSS. | A |
| fasta | Un formato simple donde cada récord comienza con una línea identificatoria que empieza con el carácter ">" seguido por las líneas de secuencias. | A / S |
| Fasta-m10 | Salida de alineamientos de de las herramientas FASTA de Bill Pearson cuando se usa desde la línea de comando la opción -m 10. | A |
| genbank | Los archivos de formato plano de Genbank o GenPept | S |
| ig | Formato de archivos IntelliGenetics, también usados por MASE. | A / S |
| nexus | Usado por MrBayes y PAUP. Ver también el módulo Bio.Nexus que también puede leer árboles filogenéticos en cualquiera de estos archivos. | A |
| phd | Salida del PHRED | S |
| phylip | Usado por las herramientas de PHYLIP | A |
| stockholm | Usado por PFAM | A |
| swiss | Formato Swiss-Prot (Uniprot). | S |
| tab | Archivos de secuencias separadas por un tab en dos columnas simples. | S |
**Archivos de secuencias escritas**
La **SeqIO** tiene un método para escribir secuencias **write(iterable, file_handle, format)**. El primer parámetro que está función toma es un objeto iterable con objetos **SeqRecord** (por ejemplo, una lista de objetos **SeqRecord**). El segundo parámetro es un manejador de archivo que le permitirá ser usado para escribir los secuencias. El argumento *format* funciona como en **parse**.
El Listado 9.3 muestra como leer un archivo con una secuencia como un texto plano y escribirlo como una secuencia FASTA.
**Listado 9.3:** `rwfasta.py`: Leer un archivo y escribirlo como una secuencia en formato FASTA.
```
from Bio
import SeqIO
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
with open('../../samples/NC2033.txt') as fh:
with open('NC2033.fasta','w') as f_out:
rawseq = fh.read().replace('\n','')
record = (SeqRecord(Seq(rawseq),'NC2033.txt','',''),)
SeqIO.write(record, f_out,'fasta')
```
Sabiendo como leer y escribir la mayoría de los formatos de los archivos biológicos podemos leer un archivo con secuencias en un formato y escribirlas en otro formato:
{line-numbers=off}
```
from Bio import SeqIO
fo_handle = open('myseqs.fasta','w')
readseq = SeqIO.parse(open('myseqs.gbk'), 'genbank')
SeqIO.write(readseq, fo_handle, "fasta") fo_handle.close()
```
Hay más ejemplos de uso de **SeqIO** en el Capítulo 15.
### AlignIO
**AlignIO** es la interfaz de entrada/salida para los alineamientos y funciona principalmente como el SeqIO con la diferencia de que en lugar de retornar un objeto SeqRecord retorna un objeto Alignment. AlignIO tiene tres métodos principales: **read**, **parse** y **write**. Los primeros dos métodos son usados como entrada y el último como salida.
* **read(handle,format[,sec_count])**: Toma el manejador de archivo y el formato del alineamiento como argumentos y retorna un objeto Alignment.
{line-numbers=off}
```
>>> from Bio import AlignIO
>>> fn = open('secu3.aln')
>>> align = AlignIO.read(fn, 'clustal')
>>> print(align)
SingleLetterAlphabet() alignment with 3 rows and 1098 columns
--------------------------------------...--- secu3
--------------------------------------...--- AT1G14990.1-CDS
GCTTTGCTATGCTATATGTTTATTACATTGTGCCTCTG...CAC AT1G14990.1-SEQ
```
El argumento *sec_count* puede ser usado con cualquier formato de archivo pero es más usado con alineamientos en formato FASTA. El *sec_count* indica el número de secuencias por alineamiento lo cual es útil para determinar si un archivo es solo un alineamiento con 15 secuencias o tres alineamientos de 5 secuencias.
* **write(iterable,handle,format)**: Toma un conjunto de objetos Alignment, un manejador de archivo y un formato de archivo para escribirlos en un archivo. Se espera que llamemos esta función con todos los alineamientos en `iterable` y cerrando el manejador de archivos. El código siguiente lee un alineamiento en formato Clustal y lo escribe en formato Phylip.
**Listado 9.4:** `clustal2phylip.py`: Convertir de Clustal a Phylip
```
from Bio import AlignIO
fi = open('../../samples/example.aln')
with open('../../samples/example.phy', 'w') as fo:
align = AlignIO.read(fi, 'clustal')
AlignIO.write([align], fo, 'phylip')
```
### BLAST
El BLAST (por su sigla en inglés **B**asic **L**ocal **A**lignment **S**earch **T**ool) es un programa para buscar similitud secuencial, usado para comparar una búsqueda del usuario contra una base de datos de secuencias. Dada una secuencia de ADN o de aminoácidos, el algoritmo heurístico del BLAST encuentra pequeñas similitudes entre las dos secuencias e intenta comenzar el alineamiento desde estos "hot spots." El BLAST también proporciona información estadística sobre un alineamiento como por ejemplo el valor de "expect."[^nota9-10]
El BLAST no es un programa simple sino una familia de programas que se utilizan para buscar similitudes entre secuencias, existe un programa de BLAST para cada tipo de búsqueda que queramos hacer. *blastn* por ejemplo es usado par buscar en bases de datos de nucleótidos usando una secuencia nucleotídica como input. Cuando la base de datos es de proteínas (aminoácidos) y el input es una secuencia nucleotídica el programa que debemos usar es el *blastx*. El *blastx* traduce la secuencia nucleotídica a una secuencia aminoacídica y realiza la búsqueda contra la base de datos de proteínas. Ver la tabla 9.2 para ver la lista de programas de BLAST y cuando debemos utilizarlos.
[^nota9-10]: El valor de expect (E) es un parámetro que describe el número de hits que uno puede esperar ("expect") encontrar por azar cuando busca en una base de datos de un tamaño particular.
Tabla 9.2 Programas del BLAST
| Nombre del programa | Búsqueda / Combinación de base de datos |
| ------------------- | --------------------------------------- |
| blastn | nucléotidos vs nucléotidos. |
| blastp | proteínas vs proteínas. |
| blastx | nucleótidos traducidos vs proteínas. |
| tblastn | proteínas vs nucleótidos traducidos. |
| tblastx | nucleótidos traducidos vs nucleótidos traducidos. |
El BLAST es una de las herramientas bioinformáticas más ampliamente utilizada en investigación dado que tiene muchas aplicaciones. Veamos una lista de las aplicaciones típicas del BLAST:
* Seguir el descubrimiento de un gen previamente desconocido en una especie, buscar en otros genomas para ver si otras especies tiene un gen similar.
* Encontrar relaciones evolutivas y funcionales entre secuencias.
* Buscar patrones de consenso regulatorios tales señales de promotores, sitios de splicing y sitios de unión de factores de transcripción.
* Inferir la estructura de proteínas utilizando proteínas previamente cristalizadas.
* Ayudar a identificar los miembros de una familia de genes.
Si trabajas en bioinformática hay amplias chances de que tengas que correr búsquedas en BLAST o procesar búsquedas realizada por vos o por otras personas. Biopython provee herramientas para ambas tareas.
**Corriendo y procesando el BLAST con Biopython**
El BLAST se puede correr online, en el web-server del NCBI, o en forma local sobre tu computadora. Correr el BLAST en Internet es una buena opción para trabajos pequeños que involucran pocas secuencias. Los trabajos más grandes tienden a ser abortados por el servidor remoto con el mensaje "CPU usage limit was exceeded" (se excedió el límite de uso de la CPU). Dado que NCBI BLAST es un servicio público tienen que poner cuotas en el uso del CPU para evitar la sobrecarga de sus servidores. Otra razón convincente para usar una versión local de BLAST es cuando se necesita consultar una base de datos personalizada. Existe cierta flexibilidad con respecto a las bases de datos que se pueden usar en el servidor del NCBI BLAST, pero no puede incorporar todo tipo y tamaño de datos personalizados.
Por todas estas razones es frecuente que la mayoría de los laboratorios de investigación realicen búsquedas locales de BLAST.
**Comenzando un trabajo con BLAST**
Biopython tiene un *wrapper* para cada ejecutable de BLAST, por lo que se puede ejecutar un programa de BLAST desde un programa (script). El *wrapper* para el **blastn** es una función llamada **NcbiblastnCommandline**, dentro del módulo **Bio.Blast.Application**. El wrapper para **blastx** es *NcbiblastxCommandline*, y así sucesivamente. Veremos cómo usar *NcbiblastnCommandline*, vale aclarar que esto también se puede aplicar a todos los otros wrappers.
Esta es la sintaxis *NcbiblastnCommandline*:
{line-numbers=off}
```
NcbiblastnCommandline(blast executable, program name, database,<=
input file, [align_view=7], [parameters])
```
Esta función devuelve una tupla con dos archivos de objetos. El primero es el resultado real, mientras que el segundo es el mensaje de error de BLAST (si corresponde). La mayoría de los parámetros son autoexplicativos. En el listado 9.5 se lo puede ver claramente:
**Listado 9.5:** `runblastn.py`: Corriendo NCBI BlAST en modo local.
```
from Bio.Blast.Applications import NcbiblastnCommandline as blastn
BLAST_EXE = '~/opt/ncbi-blast-2.6.0+/bin/blastn'
f_in = 'seq3.txt'
b_db = 'db/samples/TAIR8cds'
blastn_cline = blastn(cmd=BLAST_EXE, query=f_in, db=b_db,
evalue=.0005, outfmt=5)
rh, eh = blastn_cline()
```
El programa BLAST se corre en la línea 5. Para obtener el resultado debemos leer el objeto obtenido como un archivo **rh**, tal como vimos en el capítulo 5:
{line-numbers=off}
```
>>> rh.readline()
<?xml version="1.0"?>
>>> rh.readline()
'<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN"<=
"http://www.ncbi.nlm.nih.gov/dtd/NCBI_BlastOutput.dtd">\n'
```
La salida está en formato XML. Esta información se puede analizar utilizando las herramientas que se van a ver en el Capítulo 11 o con las herramientas proporcionadas por **Biopython** (como veremos en la siguiente sección). También hay una manera para evitar trabajar con la salida XML forzando a **NcbiblastnCommandline** a usar texto plano como salida, usando **-outfmt 0**[^nota9-11] como un parámetro opcional en la línea de comandos o en la función Biopython. Esto dará como resultado una salida más fácil de leer (por un humano) pero difícil de analizar (por una computadora). Si la última oración parece extraña, tenga en cuenta algunos párrafos para comprender por qué un formato "legible por humanos" puede no ser adecuado para el procesamiento automatizado.
El manejador de archivo `eh` almacena el mensaje de error devuelto por **NcbiblastnCommandline**. En este caso está vacío (ya que no hubo error):
[^nota9-11]: **-outfmt 0** a 4 generará diferentes tipos de salidas legibles para humanos.
{line-numbers=off}
```
>>> eh.readline()
''
```
La función llamada en la línea 5 es equivalente a la entrada de la siguiente sentencia en línea de comando:
{line-numbers=off}
```
$ ./blastn -query seq3.fasta -db db/TAIR8cds -outfmt 5
```
Todos los parámetros en la línea de comando pueden combinarse con un parámetro en la función de Biopython NcbiblastnCommandline. El último parámetro (**-outfmt 5**) obliga al resultado a generar un XML. Otros formatos de salida de BLAST, como texto sin formato y HTML, tienden a cambiar de una versión a otra, lo que hace que sea muy difícil mantener un parser actualizado[^nota9-12]. El texto legible por humanos tiende a ser desestructurado por lo cual una salida fácil de leer termina siendo más difícil de analizar.
Hay muchos aspectos de una búsqueda de blast que pueden controlarse mediante parámetros opcionales que se adjuntan al final de la llamada a la función. Para obtener más información, consulte este apéndice en el Manual del usuario del NCBI BLAST en <https://www.ncbi.nlm.nih.gov/books/NBK279675>.
Una vez que tenga el resultado del BLAST como un objeto de archivo, es posible que debamos procesarlo. Si planeamos almacenar el resultado para su procesamiento posterior se debe guardar:
[^nota9-12]: Hay una sentencia oficial de NCBI sobre esto: “NCBI does not advocate the use of the plain text or HTML of BLAST output as a means of accurately parsing the data.” (El NCBI no aboga por el uso de texto plano o de HTML para analizar los datos de los resultados de BLAST con precisión.)
{line-numbers=off}
```
>>> fh = open('testblast.xml','w')
>>> fh.write(rh.read())
>>> fh.close()
```
La mayoría de las veces necesitaremos extraer alguna información de la salida del BLAST. Para este fin el parser NCBIXML, explicado en la siguiente subsección, es útil.
**Leyendo una salida de BLAST**
Analizar el contenido de un archivo BLAST es algo con lo que cualquier bioinformático debe lidiar. Biopython proporciona un parser útil en el módulo `Bio.Blast.NCBIXML` (llamado `parse`). Con este parser el programador puede extraer cualquier bit significativo de un archivo de salida de BLAST. Este parser toma como entrada un objeto de archivo con el resultado del BLAST y devuelve un iterador para cada registro dentro del archivo. En este contexto, el registro representa un objeto con toda la información de cada resultado del BLAST (suponiendo que el archivo BLAST tenga el resultado de varias consultas de BLAST en su interior[^nota9-13]) Dada la manera en que devuelve un iterador se pueden recuperar los registros de BLAST uno por uno utilizando un bucle *for*:
[^nota9-13]: Este es un bug en las versiones previas a la versión 2.2.14 por la manera que formatea los archivos XML con múltiples consultas, por lo cual debemos usar versiones más recientes.
{line-numbers=off}
```
from Bio.Blast import NCBIXML
for blast_record in NCBIXML.parse(rh):
# Do something with blast_record
```
**¿Qué hay en un objeto de registro del BLAST?**
Cada bit de información presente en un archivo BLAST puede recuperarse del objeto de registro de **blast**. A grandes rasgos: un registro BLAST contiene la información de la ejecución del BLAST. Esta información se divide en dos grupos. Primero, hay características fijas como las características del programa, la secuencia de consulta y la base de datos (como el nombre del programa, la versión del programa, el nombre de la consulta, la longitud de la base de datos y el nombre). El otro grupo de datos está relacionado con las alineaciones (o hits). Cada hit es el alineamiento entre la secuencia de consulta y el target encontrado. A su vez, cada alineamiento puede tener más de un HSP (de sus siglas en inglés High-scoring Segment Pairs). Un HSP es un segmento de una alineamiento. Veamos la figura 9.1 para clarificar estos conceptos.

El objeto récord del BLAST refleja esta estructura. El objeto tiene una propiedad *alignments*, que es una lista de (BLAST) objetos de alineamientos. Cada objeto alineamiento tiene la información del hit (`hit_id`, `hit_definition`, `title`) y una lista (`hsps`) con la información de cada HSP. La información asociada con cada HSP es la información más pedida del récord de un BLAST (como `bit score`, `E value`, `position`). Veamos una salida de BLAST en texto plano en el Listado 9.6:
**Listado 9.6:** Una salida de BLAST
{line-numbers=on,lang=text}
```
BLASTX 2.6.0+
Reference: Stephen F. Altschul, Thomas L. Madden, Alejandro A. Schaffer,<=
Jinghui Zhang, Zheng Zhang, Webb Miller, and David J. Lipman (1997), <=
"Gapped BLAST and PSI-BLAST: a new generation of protein database search<=
programs", Nucleic Acids Res. 25:3389-3402.
Database: Non-redundant UniProtKB/SwissProt sequences
466,658 sequences; 175,602,800 total letters
Query= sample X
Length=257
Score E
Sequences producing significant alignments: (Bits) Value
P04252.1 RecName: Full=Bacterial hemoglobin; ... 93.6 1e-34
Q9RC40.1 RecName: Full=Flavohemoprotein; AltN... 66.2 2e-17
Q8ETH0.1 RecName: Full=Flavohemoprotein; AltN... 66.6 1e-16
>P04252.1 RecName: Full=Bacterial hemoglobin; AltName:
Full=Soluble cytochrome O
Length=146
Score = 93.6 bits (231), Expect(2) = 1e-34,
Method: Compositional matrix adjust.
Identities = 45/45 (100%), Positives = 45/45 (100%),
Gaps = 0/45 (0%)
Frame = +3
Query 123 VAAAHYPIVGQELLGAIKEVLGDAATDDILDAWGKAYGVIADVFI 257
VAAAHYPIVGQELLGAIKEVLGDAATDDILDAWGKAYGVIADVFI
Sbjct 90 VAAAHYPIVGQELLGAIKEVLGDAATDDILDAWGKAYGVIADVFI 134
Score = 72.8 bits (177), Expect(2) = 1e-34,
Method: Compositional matrix adjust.
Identities = 36/36 (100%), Positives = 36/36 (100%),
Gaps = 0/36 (0%)
Frame = +2
Query 2 PKALAMTVLAAAQNIENLPAILPAVKKIAVKHCQAG 109
PKALAMTVLAAAQNIENLPAILPAVKKIAVKHCQAG
Sbjct 54 PKALAMTVLAAAQNIENLPAILPAVKKIAVKHCQAG 89