Treballarem amb els formats textuals de seqüenciació d'ADN, ARN i proteïnes més habituals en bioinformàtica, el FASTA i el Genbank; i també repassarem d'altres de coneguts.
Format FASTA
Probablement és el format de fitxer més utilitzat per a seqüències i un dels tipus de formats de fitxer més comuns en bioinformàtica.
El format de fitxer FASTA
té els seus orígens en el programa FAST, utilitzat per a l'alineació de seqüències.
El format de fitxer es defineix simplement com un fitxer de text pla amb una o més entrades que consisteixen en una línia amb un símbol >
seguit d'una línia de definició identificativa única, o defline
, i una o més línies de dades de seqüència
.
Crear un fitxer de text fasta és molt fàcil, tant en un editor de text pla com notepad
o VSCode
.
Podem crear un fitxer unifasta (una sola seqüencia) que es digui uniseq.fasta
amb l'editor VSCode, simplement copia el text i guarda'l.
>Seqüència aminoàcids de prova
MTHCP*MTI*
O bé crear un fitxer multifasta (més d'una seqüència) anomenat sequences.fa
des del terminal Linux:
echo ">a
ACGCGTACGTGACGACGATCG
>b
ATTTCGCGACTCTGCCTACGCTAC
>c
GGGAAACCTTTTTTT" > sequences.fa
Bingo! Ja tenim un fitxer multifasta :) amb les seqüències a, b i c.
El requisit fonamental és que el fitxer sigui plain text
per tal que es pugui tractar amb qualsevol aplicació de processament de textos o llenguatge de programació.
Per tant, aquests fitxers es tracten millor en editors de text com nano
, sublime
o VSCode
.
Per veure un fitxer FASTA
des de la línia d'ordres sense editar-lo, pots fer servir la aplicació cat
.
cat uniseq.fasta
>Seqüència aminoàcids de prova
MTHCP*MTI*
També pots llegir-les linia a linia amb more
i less
; que això és ideal per a fitxers grans:
less sequences.fa
Per sortir de less només has d’apretar la tecla q
(“quit”).
També pots filtrar les primeres i últimes files amb les comandes: head
i tail
.
Característiques.
Realment no hi ha cap restricció sobre la seqüència de la definició en el format estàndard, excepte que la definició ha de seguir immediatament el >
sense cap espai intermedi.
Per tant, dins de d’seqüència, hi ha dos coses:
- Un
comentari/descripció
que comença per>
i esuna sola linea
- La
seqüència de bases
dividides per línies de ...[70] caràcters, pot variar.
Si es un fitxer MULTI-FASTA (més d'una línia), és separen les seqüències amb una linea de capçalera ( > ).
Qualsevol tipus de seqüència o conjunt de seqüències es pot posar en un fitxer FASTA: els 3.000 milions de parells de bases del genoma humà complet, la seqüència d'ARN completa d'un virus o la seqüència d'ADN del promotor del gen del teu ratolí favorit són exemples vàlids.
On trobar fitxers FASTA.
Ja sabeu que un dels millors llocs on aconseguir fitxers .fasta
d’organismes reals de forma legal és el repositori públic de l’NCBI
, que ens facilita un cercador molt complet.
Exposem algusns enllaços directes com a exemples.
Gènoma complet del SarsCov2:
Gen de la orquídea:
Gen insulina a l’ésser humà.
Gen de l'insulina al gos:
Com descarregar-los ?
Per automatitzar el nostre programari, pots descarregar-te fitxers fasta com qualsevol fitxer.
Des del terminal (bash
):
wget -O ls_orchid.fasta https://raw.githubusercontent.com/biopython/biopython/refs/heads/master/Doc/examples/ls_orchid.fasta
També pots veure com fer-ho amb Python
i la llibreria urllib3
; per tal de descarregar-lo únicament si no hi és.
https://xtec.dev/python/http/#cache
⚠️ Però compte! Hi ha restriccions si els volem baixar d'NCBI. ⚠️
NCBI té obert un repositori FTP
amb fitxers de les seves bases de dades (com els articles PMC o PUBMED) que es troba a:
Però ni des d'aquest repositori ni des de programari fet amb Python o bash se'ns permet baixar directament qualsevol fitxer fasta.
Més endavant veurem com fer-ho amb un programari específic que distribueix NCBI/Entrez:
Lectura i tractament de fitxers fasta amb GNU/Linux (Bash).
Mostrar contingut fitxers
Obre un terminal en Linux (la icona és una finestra negra) o bé prem la drecera Ctrl + Alt + T, que funciona en distribucions basades en Debian (Ubuntu, Mint, PopOS …)
Introdueix aquesta comanda, que ens permet veure la capçalera i el contingut de les seqüències del fitxer sequences.fa (que hem creat abans):
grep -E '^\S+$' sequences.fa | awk '{printf "%s ", $0; getline; print $0}'
Resultat:
>a ACGCGTACGTGACGACGATCG
>b ATTTCGCGACTCTGCCTACGCTAC
>c GGGAAACCTTTTTTT
Gràcies al llenguatge del shell awk
podem aconseguir-ho.
Una altra manera és usar un script de bash
; que anomenarem readfasta.sh
:
#!/bin/bash
echo 'Llegim tots els fitxers fasta de la carpeta actual.'
for i in *.fasta; do
echo "Núm Seqüències"
grep -c "^>" $i
echo "Info Seqüències"
# Capçalera seqüència.
grep "^>" $i
# Contingut seqüència:
grep -v "^>" $i
done
Recorda com executar-lo:
chmod u+x readfasta.sh
./readfasta.sh
Recompte dades de seqüències
Una altra ordre útil de GNU/Linux és wc
(abreviatura de "recompte de paraules") per comptar el nombre de línies d'un fitxer; juntament amb el programa de filtratge d'expressions grep
:
$ grep '>' sequences.fasta | wc
3 3 9
El símbol pipa |
(pipe) envia la sortida d'un programa (grep '>' sequences.fasta
) a l'entrada d'un altre programa (wc
), ja que amb aquest exemple estem enviant la sortida de grep al wc per comptar.
Important! Aneu amb compte per assegurar-vos que el símbol >
estigui inclòs entre cometes en aquesta ordre. Si no s'inclouen les cometes, es sobreescriurà el fitxer!
Guardar resultats en nous fitxers
A més a més; un símbol >
a la línia d'ordres redirigeix la sortida d'un programa a un fitxer i sobreescriu el fitxer.
Per exemple, podem redirigir la sortida de l'exemple anterior així:
$ grep ">" sequences.fasta | wc > numSequences.txt
D'aquesta manera no imprimeix res a la pantalla, sinó emmagatzema la informació en un fitxer.
Transcripció i edició de seqüències
També podem realitzar algunes operacions, com la transcripció; amb la comanda sed
(stream editor).
cat seq_3.fasta | sed ‘s/T/U/g’
Lectura de fitxers amb Python
Podem llegir fàcilment fitxers textuals amb Python, i agafar tota la informació de les cadenes.
# Llegir el fitxer amb 'with open' per assegurar que es tanca correctament.
with open('sequences.fa', 'r') as f:
lines = f.read().splitlines()
# Diccionari per emmagatzemar les seqüències
genes = {}
# Variables per mantenir el context mentre iterem
gene_id = None
sequence = []
for line in lines:
if line.startswith('>'): # Les capçaleres comencen amb '>'
if gene_id:
# Guarda la seqüència acumulada abans de processar una nova capçalera
genes[gene_id] = ''.join(sequence)
gene_id = line[1:].strip() # Guarda el nou identificador
sequence = [] # Reinicia la seqüència
else:
sequence.append(line.strip()) # Afegeix la línia de seqüència
# Guarda l'última seqüència
if gene_id:
genes[gene_id] = ''.join(sequence)
# Mostra els resultats
for gene_id, sequence in genes.items():
print(f'ID: {gene_id}, Sequence: {sequence}, Seq.Long: {len(sequence)})')
Lectura de fitxers amb (Bio)Python
Si només necessitem llegir els fitxers i obtenir informació molt bàsica aquestes solucions que aporta GNU/Linux
són bones i eficients.
Però en el nostre cas volem fer operacions complexes, com obtenir estadístiques, alinear seqüències, crear arbres… i per això és preferible usar Python
.
Pots usar mètodes de Python per obrir i obtenir informació bàsica d’un fitxer fasta i obtenir estadístiques bàsiques (longitud, percentatge gc…) amb el suport de llibreries com Biopython
.
Per exemple, aquest codi llegirà el contingut del fitxer sequence.fa
, guardarà el contingut en l’objecte sequences i el mostrarà per pantalla.
from Bio import SeqIO
file = "sequences.fa"
sequences = SeqIO.parse(open(file), "fasta")
for record in sequences:
print(record.id, record.seq)
El resultat és
a ACGCGTACGTGACGACGATCG
b ATTTCGCGACTCTGCCTACGCTAC
c GGGAAACCTTTTTTT
Pots observar que també hem introduït un altre objecte anomenat record
, i cada seqüència del nostre fitxer FASTA s'emmagatzema en aquest objecte.
La crida als mètodes id
i seq
de l’objecte record retorna el text de defline i un objecte Seq
.
Estructura dels SeqRecord de BioPython.
La classe SeqIO
, ens servirà per llegir fitxers fasta, genbank i altres i fins i tot per a crear-ne de nous.
Tenim 2 mètodes de lectura:
read() --> Llegeix fitxers (.fasta i .genbank) que tenen només UNA (seqüència o fitxa) Resultat = SeqRecord
parse() --> Llegeix fitxers (.fasta i .genbank) que tenen només UNA O MOLTES (seqüències o fitxes de genbank)
Resultat = Llista SeqRecord's
Cada objecte SeqRecord
conté, en el cas dels fitxers fasta:
- Objecte
Seq
, amb la seqüència completa. id
. El que surt just després del símbol>
name
. Metadada primera linia amb el nom.description
. Metadada primera linia amb descripció addicional.
Tenim el mètode d’escritura write
, si volem guardar ràpidament les nostres investigacions (tot i que habitualment s'escriu als Genbank, no els fasta)
write(seq,info,format)
- seq → La seqüència o llista de seqüències en format SeqRecord o format Seq.
- info → Aquí hi ha la informació de la capçalera, es pot passar en un diccionari que contingui id, name, … Com abans, si volem un multifasta li hem de passar una llista.
- format → ‘fasta’, ‘genbank’ ...
Script lectura de fitxer fasta millorat.
Si necessites un programa que en comptes de definir-li el fitxer .fasta
dins del codi li puguis passar un fitxer .fasta
que t’has descarregat prèviament pots usar aquest codi; que un cop llegit el fitxer transcriu a ARN totes les seqüències (tant si el fasta té 1 o diverses):
import sys
import os
from Bio import SeqIO, Seq
# Validacions
if len(sys.argv) != 2:
print("Instruccions ús: " + sys.argv[0] + " <fitxer fasta>")
sys.exit()
fastaFile = sys.argv[1]
if not os.path.isfile(fastaFile):
print(f"Error: El fitxer {fastaFile} no existeix!")
sys.exit()
print(f"Fitxer {fastaFile} llegit correctament. Transcrivint seqüències.")
sequences = SeqIO.parse(fastaFile, 'fasta')
for record in sequences:
print(record.id, record.seq.transcribe())
print("Seqüències transcrites! Fins aviat!")
Aquí sota teniu la prova del seu funcionament:
>> $ python3 read_fasta.py sequences.fa
Fitxer sequences.fa llegit correctament. Transcrivint seqüències.
a ACGCGUACGUGACGACGAUCG
b AUUUCGCGACUCUGCCUACGCUAC
c GGGAAACCUUUUUUU
Seqüències transcrites! Fins aviat!
>> $ python3 read_fasta.py
Instruccions ús: read_fasta.py <fitxer fasta>
>> $ python3 read_fasta.py xd
Error: El fitxer xd no existeix!
Lectura de fitxers fasta d'aminoàcids.
Copia't aquesta seqüència en un fitxer fasta, disponible a https://www.ncbi.nlm.nih.gov/protein/AAD44166.1?report=fasta
echo ">gi|5524211|gb|AAD44166.1| cytochrome b [Elephas maximus maximus]
LCLYTHIGRNIYYGSYLYSETWNTGIMLLLITMATAFMGYVLPWGQMSFWGATVITNLFSAIPYIGTNLV
EWIWGGFSVDKATLNRFFAFHFILPFTMVALAGVHLTFLHETGSNNPLGLTSDSDKIPFHPYYTIKDFLG
LLILILLLLLLALLSPDMLGDPDNHMPADPLNTPLHIKPEWYFLFAYAILRSVPNKLGGVLALFLSIVIL
GLMPFLHTSKHRSMMLRPLSQALFWTLTMDLLTLTWIGSQPVEYPYTIIGQMASILYFSIILAFLPIAGX
IENY" > elephas_prog.fasta
Ara, prova el mateix programa que has creat per llegir el fitxer i veuràs que, tret de la transcrició que la ignorarà, funciona exactament igual.
Fitxer de prova:
>> $python3 read_fasta.py elephas_prog.fasta
Fitxer elephas_prog.fasta llegit correctament. Transcrivint seqüències.
gi|5524211|gb|AAD44166.1| LCLYUHIGRNIYYGSYLYSEUWNUGIMLLLIUMAUAFMGYVLPWGQMSFWGAUVIUNLFSAIPYIGUNLVEWIWGGFSVDKAULNRFFAFHFILPFUMVALAGVHLUFLHEUGSNNPLGLUSDSDKIPFHPYYUIKDFLGLLILILLLLLLALLSPDMLGDPDNHMPADPLNUPLHIKPEWYFLFAYAILRSVPNKLGGVLALFLSIVILGLMPFLHUSKHRSMMLRPLSQALFWULUMDLLULUWIGSQPVEYPYUIIGQMASILYFSIILAFLPIAGXIENY
Seqüències transcrites! Fins aviat!
Execució de l'script:
python3 read_fasta.py sequences.fa
Fitxer sequences.fa llegit correctament. Transcrivint seqüències.
a 0.6190476190476191 TRT*RRS
b 0.5416666666666666 ISRLCLRY
c 0.3333333333333333 GKPFF
Seqüències transcrites! Fins aviat!
Activitat.
1.- Crea un programa com a script que llegeixi un fitxer fasta per paràmetre, calculi el percentatge GC i tradueixi les 30 primeres bases.
Ha de contolar que l'usuari hagi enviat un fitxer fasta ben formatat (amb les capçaleres que comencin per >).
import sys
import os
from Bio import SeqIO
from Bio.SeqUtils import gc_fraction
# Validacions
if len(sys.argv) != 2:
print("Instruccions ús: " + sys.argv[0] + " <fitxer fasta>")
sys.exit()
fastaFile = sys.argv[1]
if not os.path.isfile(fastaFile):
print(f"Error: El fitxer {fastaFile} no existeix!")
sys.exit()
print(f"Fitxer {fastaFile} llegit correctament. Transcrivint seqüències.")
sequences = SeqIO.parse(fastaFile, 'fasta')
for record in sequences:
print(record.id, gc_fraction(record.seq,"weighted"), record.seq[0:30].translate())
print("Seqüències transcrites! Fins aviat!")
2.- Crea un nou programa que tradueixi un seqüència d’ADN a una de proteïnes. Al final, ha de guardar la proteïna en un altre fitxer que tingui el mateix nom juntament amb el text "_newprot". La capçalera ha de ser la mateixa que el fasta de nucleòtids, afegint el text ", translated by Biopython".
import sys
from Bio.Seq import Seq
from Bio import SeqIO
from Bio.SeqRecord import SeqRecord
import os
def tradueix_adn_a_proteines(input_file):
"""Tradueix seqüències d'ADN a proteïnes i les guarda en un nou fitxer FASTA."""
try:
# Llegeix el fitxer FASTA
sequences = SeqIO.parse(open(input_file), "fasta")
print(f"Fitxer llegit: {input_file}")
# Inicialitza una llista per les seqüències traduïdes
seq_records_proteina = []
# Traducció de seqüències
for seq_record in sequences:
try:
# Traduir a proteïna
seq_proteina = seq_record.seq.translate()
# Actualitzar la capçalera
nova_capcalera = f"{seq_record.description}, translated by Biopython"
# Crear un nou SeqRecord
seq_record_proteina = SeqRecord(seq_proteina, id=seq_record.id, description=nova_capcalera)
seq_records_proteina.append(seq_record_proteina)
except Exception as e:
print(f"Error en traduir {seq_record.id}: {e}")
# Guarda les seqüències traduïdes
output_file = os.path.splitext(input_file)[0] + "_newprot.fasta"
SeqIO.write(seq_records_proteina, output_file, "fasta")
print(f"Les seqüències traduïdes s'han guardat a {output_file}")
except Exception as e:
print(f"Error en processar el fitxer {input_file}: {e}")
if __name__ == "__main__":
# Comprova si s'ha passat un argument d'entrada
if len(sys.argv) != 2:
print(f"Ús: {sys.argv[0]} <fitxer fasta d'ADN o ARN>")
sys.exit(1)
# Nom del fitxer d'entrada
input_file = sys.argv[1]
tradueix_adn_a_proteines(input_file)
Ho provem amb un fitxer fasta creat per nosaltres:
echo ">Demofa by Miquel
AGACTAGCAGACTATCGGTACGTCACATAG" > act2-nuc.fasta
python3 bioprot.py act2-nuc.fasta
Veiem que efectivament ha guardat un nou fitxer amb la traducció:
cat demo_newprot.fasta
>Demofa by Miquel, translated by Biopython
RLADYRYVT*
Fastaiterator
Per a llegir fitxers multifasta grans, ens convé usar la classe FastaIterator
per millorar el rendiment.
És més eficient en termes de memòria RAM quan tractes amb fitxers grans, ja que només es llegeix una seqüència a la vegada.
Anem a provar com funciona amb el multifasta ls_orchid.fasta
i calcularem el temps d'execució.
from Bio import SeqIO
import time
MULTIFASTA_FILE = "ls_orchid.fasta"
def processa_multifasta(file_path):
"""
Llegeix un fitxer multifasta utilitzant SeqIO.parse i mostra la longitud de cada seqüència.
"""
try:
print("Processant el fitxer multifasta...\n")
start_time = time.time()
# Iterador de SeqRecords des del fitxer FASTA
for record in SeqIO.parse(file_path, "fasta"):
print(f"ID: {record.id}")
print(f"Descripció: {record.description}")
print(f"Longitud: {len(record.seq)}")
print("--------")
elapsed_time = time.time() - start_time
print(f"\nTemps total per processar el fitxer: {elapsed_time:.2f} segons")
except Exception as e:
print(f"Error en processar el fitxer: {e}")
if __name__ == "__main__":
processa_multifasta(MULTIFASTA_FILE)
Instruccions per executar el programa amb mesurament del temps:
- Guarda el programa en un fitxer, per exemple,
process_multifasta.py
. - Assegura't que tens un fitxer multifasta a la mateixa carpeta, com ara
ls_orchid.fasta
. - Executa el programa amb la comanda
time
des de la línia de comandes:
time python process_multifasta.py
La sortida del programa, llegint el fitxer ls_orchid.fasta
, seria:
Longitud: 744
--------
ID: gi|2765564|emb|Z78439.1|PBZ78439
Descripció: gi|2765564|emb|Z78439.1|PBZ78439 P.barbatum 5.8S rRNA gene and ITS1 and ITS2 DNA
Longitud: 592
--------
Temps total per processar el fitxer: 0.06 segons
Format FastQ
Aquí, treballarem amb fitxers FASTQ, la sortida en format estàndard que utilitzen els seqüenciadors moderns. Aprendràs a treballar amb puntuacions de qualitat per base.
Què és el format FASTQ?**
El format FASTQ s’utilitza àmpliament per informar de dades de seqüenciació d’alt rendiment. Cada entrada consta de quatre línies:
- Identificador: Comença amb
@
i conté informació sobre la seqüència. - Seqüència: La seqüència de nucleòtids corresponent.
- Separador: Una línia amb
+
(i un text amb comentaris, opcionals). - Qualitat: Una cadena que codifica les puntuacions de qualitat per a cada nucleòtid.
Exemple d’entrada FASTQ:
@SRR001666.1 071112_SLXA-EAS1_s_7:5:1:817:345 length=36
GGGTGATGGCCGCTGCCGATGGCGTCAAATCCCACC
+SRR001666.1 071112_SLXA-EAS1_s_7:5:1:817:345 length=36
IIIIIIIIIIIIIIIIIIIIIIIIIIIIII9IG9IC
Càlcul de puntuacions PHRED
Les puntuacions de qualitat en un fitxer FASTQ segueixen l’estàndard PHRED, que es defineix com:
S_PHRED = -10 * log10(p_err)
- p_err: Probabilitat d'error en la identificació d'una base.
- Una puntuació PHRED alta significa una probabilitat baixa d'error.
Conversió de puntuacions PHRED a caràcters ASCII:
- Cada caràcter de la cadena de qualitat representa una puntuació PHRED.
- La puntuació es calcula amb:
S_PHRED = ord(Q_char) - 33
- ord(Q_char): Retorna el valor ASCII (en decimal) del caràcter.
- El -33 ajusta per assegurar que el primer caràcter imprimible correspon a un valor de puntuació 0.
Probabilitat d'error derivada:
p_err = 10^(-S_PHRED / 10)
Per exemple, el primer caràcter imprimible és el !
, que dins de la taula ASCII és el 33 llavors aquest és el que indica una qualitat més baixa.
I si tenim els caràcters B
i E
; quin té qualitat més alta ? Doncs E
perquè té un número més alt de la taula ASCII (el 69) que la B
(el 66).
Codi exemple per calcular el % probabilitat d'error d'un caràcter de fastq
def calcular_probabilitats_error(puntuacions_qualitat):
probabilitats = [10 ** (-(ord(caracter) - 33) / 10.0) for caracter in puntuacions_qualitat]
return probabilitats
# Exemple d'ús:
puntuacions_qualitat = ['!', 'A', 'a', '%', '-']
probabilitats_error = calcular_probabilitats_error(puntuacions_qualitat)
for i in range(len(puntuacions_qualitat)):
print(f"Puntuació: {puntuacions_qualitat[i]}, Probabilitat d'error: {probabilitats_error[i]:.4f}")
Resultats:
Puntuació: !, Probabilitat d'error: 1.0000
Puntuació: A, Probabilitat d'error: 0.0006
Puntuació: a, Probabilitat d'error: 0.0000
Puntuació: %, Probabilitat d'error: 0.3981
Puntuació: -, Probabilitat d'error: 0.0631
Lectura i processament de fitxers FASTQ:
Biopython ens facilita la lectura del fitxer i també el càlcul de les probabilitats d'error
i el valor s_phred
de la qualitat dels caràcters.
Això és possible gràcies a que la classe Seq
te un atribut que es diu letter_annotations
i s'omple quan llegim un fitxer fastq
.
from Bio import SeqIO
file = "sequences.fq"
data = SeqIO.parse(file, "fastq")
for record in data:
print(f"ID: {record.id}")
print(f"Seqüència: {record.seq}")
print(f"Puntuacions PHRED: {record.letter_annotations['phred_quality']}")
# Càlcul de probabilitats d'error amb list comprehension
p_err_array = [round(10 ** (-float(Q) / 10.0),6) for Q in record.letter_annotations["phred_quality"]]
print(f"% p_err: {p_err_array}")
Sortida
ID: SRR993731.910
Seqüència: TGTCCTCTGGCTCCAGGTCTCATGATGAAAAAATTTATGGAGTCCTGGACA
Puntuacions PHRED: [26, 30, 27, 35, 26, 11, 17, 33, 32, 28, 18, 32, 10, 17, 32, 36, 26, 27, 27, 32, 27, 36, 36, 37, 29, 36, 31, 37, 27, 37, 37, 40, 32, 30, 35, 35, 34, 35, 27, 35, 26, 35, 24, 33, 24, 30, 2, 2, 35, 22, 36]
Com descarregar i llegir fitxers fastq comprimits.
Aquest és un fitxer força petit (27 MB) i representa part de les dades seqüenciades d'una dona yoruba (NA18489). Si consultes el 1.000 Genomes Project, veuràs que la gran majoria dels fitxers FASTQ són molt més grans (fins a dues ordres de magnitud més grans).
Per obtenir més informació sobre el 1.000 Genomes Project, pots visitar la seva pàgina oficial:
import os
import subprocess
import gzip
from Bio import SeqIO
url = "ftp://ftp.1000genomes.ebi.ac.uk/vol1/ftp/phase3/data/NA18489/sequence_read/SRR003265.filt.fastq.gz"
filename = "SRR003265.filt.fastq.gz"
if not os.path.exists(filename):
print(f"Descarregant {filename}...")
# Utilitzar el comandament 'wget' mitjançant subprocess, ja que sinó NCBI no ens deix.
subprocess.run(["wget", "-nd", url])
print(f"{filename} descarregat correctament.")
else:
print(f"El fitxer {filename} ja existeix, no es descarregarà.")
# Obrir i llegir el fitxer gzip un cop descarregat
with gzip.open(filename, 'rt', encoding='utf-8') as f:
recs = SeqIO.parse(f, 'fastq')
rec = next(recs) # Agafar el primer registre (read)
print(f"ID: {rec.id}")
print(f"Descripció: {rec.description}")
print(f"Seqüència: {rec.seq}")
print(f"Puntuacions de qualitat: {rec.letter_annotations['phred_quality']}")
Indexació d'un fitxer FASTQ - com llegir fitxers FASTQ grans més ràpidament?
Els fitxers FASTQ solen ser molt grans, amb milions de lectures. A causa de la gran quantitat de dades, no es poden carregar tots els registres a la memòria alhora. Per això, quan es realitzen tasques de filtratge i retallat, podem iterar sobre el fitxer observant només un SeqRecord
a la vegada.
No obstant això, de vegades no es pot utilitzar un gran bucle o un iterador - potser necessitaràs un accés aleatori a les lectures. En aquest cas, la funció Bio.SeqIO.index()
pot resultar molt útil, ja que et permet accedir a qualsevol lectura en el fitxer FASTQ pel seu nom.
Així que això és útil quan saps l'ID de la seqüència a la qual vols accedir, ja que et permet llegir-la de manera instantània, en comptes de fer un bucle sobre el fitxer fins trobar la seqüència desitjada.
Descarregar un fitxer FASTQ de ~1GB - triga uns 2 minuts
wget ftp://ftp.sra.ebi.ac.uk/vol1/fastq/SRR494/SRR494102/SRR494102.fastq.gz
Activitat.
3.- Agafa un fitxer fastq
d'NCBI o una altra font confiable i mostra el seu contingut i la seva qualitat.
Recursos útils
- Taula ASCII
- Exemples processament de FASTQ:
- Tutorial bioinformàtica.
Format Genbank
Genbank conté la majoria de les seqüències d'ADN, ARN i proteïnes conegudes del món, i també emmagatzema informació bibliogràfica per a les seqüències.
Va ser creat l’any 1979 i finalitzat l’any 1982. 10 anys més tard es va integrar totalment dins l’NCBI.
La versió actual de Genbank, a partir d'octubre de 2015, conté 188,372,017 seqüències, que inclouen 202,237,081,559 nucleòtids.
Pots accedir a les entrades de Genbank des de la seva pàgina principal:
També pots cercar les entrades .genbank
des de diverses bases de dades d’NCBI: com Nucleotide, Protein… de la mateixa manera que ho feiem amb els fitxers .fasta
Genbank és de naturalesa arxivística, de manera que pot contenir entrades redundants.
Genbank és una base de dades, però també és un format de fitxer molt detallat.
Com descarregar manualment fitxer Genbank i llegir-lo amb Biopython.
Ens descarregarem un exemple manualment per provar, del gen complet mitocondrial de l’elefant:
Si ens el descarreguem amb l’wget ens surt en format XML i per ara no ens interessa; per tant, millor ho fem del portal web de l’NCBI (opcions Complete Record, File, Genbank)
Hem renombrat el fitxer per a distigir-lo.
mv sequences.gb NC_005129.2_elephas_mitoc.genbank
Ara sí, podem usar el següent codi:
from Bio.Seq import Seq
from Bio import SeqIO
# Llegeix multifasta o multigenbank, retorna un Iterador.
demo_genbank = list(SeqIO.parse("NC_005129.2_elephas_mitoc.genbank", "genbank"))
print(demo_genbank)
Que com a sortida mostra un resum:
[SeqRecord(seq=Seq('GTTAATGTAGCTTAAAACAAAAGCAAGGTACTGAAAATACCTAGACGAGTATAT...CTC'), id='NC_005129.2', name='NC_005129', description='Elephas maximus mitochondrion, complete genome', dbxrefs=['BioProject:PRJNA927338'])]
Com descarregar fitxer Genbank llegir-lo amb Biopython i utilitat NCBI-Entrez.
Ara, aprendrem a utilitzar el mòdul de Biopython Entrez
per recuperar automàticament un fitxer en format Genbank.
Si ja coneixes un número d'accés gi per al gen, pots recuperar les dades directament de NCBI.
És molt interessant usar-lo si volem descarregar o revisar moltes seqüències alhora.
⚠️ Heu de saber que l’únic requeriment és assegurar-se de no fer més de 3 operacions per minut, i que cal indicar l’email si no tens una API Key. ⚠️
Aquí tens un exemple, amb una part de la sortida (el fitxer Genbank complet és massa gran per mostrar-lo aquí).
from Bio import Entrez
Entrez.email = "mamoro10@xtec.cat"
handle = Entrez.efetch(db="protein", id='NP_003173', rettype="gb", retmode="text")
print(handle.read())
Sortida (parcial):
LOCUS NP_003173 129 aa DNA_input linear PRI 28-NOV-2015
DEFINITION protachykinin-1 isoform beta precursor [Homo sapiens].
ACCESSION NP_003173
VERSION NP_003173.1 GI:4507341
DBSOURCE REFSEQ: accession NM_003182.2
KEYWORDS RefSeq.
SOURCE Homo sapiens (human)
ORGANISM Homo sapiens
Eukaryota; Metazoa; Chordata; Craniata; Vertebrata; Euteleostomi;
Mammalia; Eutheria; Euarchontoglires; Primates; Haplorrhini;
Catarrhini; Hominidae; Homo.
REFERENCE 1 (residues 1 to 129)
AUTHOR Agaeva,G.A., Agaeva,U.T. and Godjaev,N.M.
TITLE [Particularities of Spatial Organization of Human Hemokinin-1
and Mouse/Rat Hemokinin-1 Molecules]
JOURNAL Biofizika 60 (3), 457-470 (2015)
PUBMED 26349209
REMARK GeneRIF: The spatial structures of human, mouse, and rat
hemokinin-1 protein isoforms have been presented.
...
FEATURES Location/Qualifiers
source 1..129
/organism="Homo sapiens"
/db_xref="taxon:9606"
/chromosome="7"
/map="7q21-q22"
Protein 1..129
/product="protachykinin-1 isoform beta precursor"
/note="neuropeptide gamma; neuropeptide K; tachykinin,
precursor 1 (substance K, substance P, neurokinin 1,
neurokinin 2, neuromedin L, neurokinin alpha, neuropeptide
K, neuropeptide gamma); tachykinin 2; protachykinin;
preprotachykinin; neurokinin A; protachykinin-1; PPT"
...
CDS 1..129
/gene="TAC1"
/gene_synonym="Hs.2563; NK2; NKNA; NPK; TAC2"
/coded_by="NM_003182.2:247..636"
/note="isoform beta precursor is encoded by transcript variant beta"
/db_xref="CCDS:CCDS5649.1"
/db_xref="GeneID:6863"
/db_xref="HGNC:HGNC:11517"
/db_xref="HPRD:08876"
/db_xref="MIM:162320"
ORIGIN
1 mkilvalavf flvstqlfae eiganddlny wsdwydsdqi keelpepfeh llqriarrpk
61 pqqffglmgk rdadssiekq vallkalygh gqishkrhkt dsfvglmgkr alnsvayers
121 amqnyerrr
Podem millorar-lo una mica; assegurant-nos que només es descarrega si no el tenim:
from Bio import Entrez, SeqIO
import os
GENBANK_NAME = "SarsCov2.gb"
DATABASE = "nuccore"
ACCESSION = "NC_045512"
Entrez.email = "mamoro10@xtec.cat"
filepath = os.path.join(os.getcwd(), GENBANK_NAME)
if not os.path.exists(filepath):
with Entrez.efetch(db=DATABASE, id=ACCESSION, rettype="gb", retmode="text") as handle:
with open(filepath, 'w') as genbank_file:
genbank_file.write(handle.read())
print(f"Genbank descarregat i guardat com a {GENBANK_NAME}")
else:
print(f"Ja existeix el fitxer {GENBANK_NAME}.")
demo_genbank = list(SeqIO.parse(GENBANK_NAME, "genbank"))
print(demo_genbank)
Estructura d’un fitxer Genbank.
El format Genbank està pensat perquè nosaltres el poguem llegir sense eines especials fins a cert punt, però els fitxers tenen un format que els permet analitzar-los amb eines de programari, com el de Biopython.
En resum, l’esquema del format Genbank és:
Anem a centrar-nos en explicar els 2 primers blocs del Genbank; acompanyats d’un exemple que des del 2020 ha preocupat a tot el món i el coneixem força bé. Aquí el tenim:
Bloc 1 del Genbank: Header
Els GenBank sempre comencen amb la paraula LOCUS i contenen els següents camps al Header o annotations (com es coneixen en Biopython):
- Locus: Identificació del lloc.
- Definition: Descripció textual.
- ACCESSION: Identificador únic de la fitxa.
- Version: Notació general formada per l’ID + el número de versió.
- DBLINK: Projecte d’on prové la seqüència.
- KEYWORDS: Paraules clau per als cercadors.
- SOURCE: Descripció científica que pot incloure taxonomies (en format de llista).
- REFERENCE: Informació d’altres persones i publicacions relacionades. Inclou camps com:
- AUTHORS
- TITLE
- JOURNAL
- PUBMED (si escau).
- COMMENTS: Text lliure o informacions diverses.
Bloc 2 del Genbank: Gene Annotation
Aquest bloc, conegut en Biopython com a features i també com Gene Annotation, conté informació sobre els gens de la seqüència. Inclou dades sobre cadenes codificants (CDS), promotors, pèptids o regions no traduïdes. A continuació, els camps més importants:
- source: Informació general sobre la seqüència (longitud, organisme, tipus, etc.).
- gene: Detalls específics del gen.
- CDS:
- Cadena codificant (indica la regió codificant).
- translation: Seqüència proteica derivada.
- Sovint inclou diversos CDS o combinacions (joins).
- Dins de cada CDS:
- Gen associat.
- Codó d’inici (si és l’1 es tradueix amb la lletra M).
- ID de la proteïna funcional.
- Altres features:
- 5'UTR: Regió inicial no codificant (per exemple: 1..265 no codificat com a gene).
- mat_peptide: Regions concretes de la proteïna que tenen una funció específica (per exemple, unir-se a altres proteïnes).
Per més informació sobre els conceptes i la taula de codons, pots consultar:
Gene Expression
Bloc 3 del Genbanki i final: Seqüència
El tercer és la cadena d'ADN, ARN o aminoàcids. A Genbank surt en blocs de 10 en 10 per facilitat la lectura en paper, però BioPython ajunta la cadena automàticament.
La línia //
marca el final d'un fitxer genbank.
RefSeq
RefSeq (Reference Sequence) és una base de dades completa i no redundant de seqüències biològiques, mantinguda pel NCBI, que inclou ADN, ARN i proteïnes. Aquí tens els seus principals detalls i característiques:
-
RefSeq vs. GenBank:
- RefSeq: Seqüències seleccionades i anotades amb gran cura i precisió.
- GenBank: Format de fitxer i base de dades que inclou seqüències, revisades o no.
-
Connexió amb altres bases de dades:
- RefSeq enllaça proteïnes i seqüències d'àcids nucleics corresponents a un gen específic.
-
Estadístiques:
- RefSeq manté aproximadament 100,000,000 entrades, cadascuna amb un identificador únic.
-
Identificadors RefSeq:
- XR_: Seqüències d'ARN que no són ARN missatgers.
- XM_: ARN missatgers.
- XP_: Proteïnes.
- NP_: Proteïnes conegudes i confirmades.
- NC_: Cadenes de nucleòtids (normalment ADN).
- NR_: Seqüències d'ARN que no són ARN missatgers.
- NM_: ARN missatgers.
Exemple de lectura d'un registre RefSeq
from Bio import Entrez
Entrez.email = "mamoro10@xtec.cat"
record = Entrez.read(Entrez.esearch(db="protein", term="NP_003173"))
print(record['IdList'])
handle = Entrez.efetch(db="protein", id=record["IdList"][0], rettype="fasta")
print(handle.read())
Sortida del codi:
['4507341']
>gi|4507341|ref|NP_003173.1| protachykinin-1 isoform beta precursor [Homo sapiens]
MKILVALAVFFLVSTQLFAEEIGANDDLNYWSDWYDSDQIKEELPEPFEHLLQRIARRPKPQQFFGLMGK
RDADSSIEKQVALLKALYGHGQISHKRHKTDSFVGLMGKRALNSVAYERSAMQNYERRR
Altres bases de dades del NCBI
El NCBI és un recurs immens amb diverses bases de dades útils. A continuació, algunes destacades:
- Entrez: Motor de cerca global entre bases de dades NCBI (detall a la pròxima activitat).
- Gene: Base de dades de gens amb informació sobre nomenclatura, RefSeq, mapes, vies, variacions i fenotips.
- GEO: Gene Expression Omnibus. Base de dades d'expressió gènica i dades de seqüències d'alt rendiment.
- OMIM: Informació sobre trets heretables, fenotips genètics i variants al·lèliques associades a malalties.
- Taxonomy: Base de dades de classificació i nomenclatura (representa el 10% de les espècies del planeta).
- PubMed: Motor de cerca per accedir a MEDLINE (citacions i resums de recerca biomèdica).
- PMC: Arxiu electrònic d'articles científics de text complet, amb accés gratuït al contingut.
Exemple de lectura d'un article de PMC
Resum: A Systematic Review: Do the Use of Machine Learning, Deep Learning, and Artificial Intelligence Improve Patient Outcomes in Acute Myocardial Ischemia Compared to Clinician-Only Approaches?
Llegeix l’article complet:
PubMed
Altres Bases de Dades Biològiques
Ensembl
Ensembl és una base de dades europea especialitzada en seqüències biològiques, desenvolupada per l'European Bioinformatics Institute (EBI), part de l'EMBL.
Accessible a través de http://ensembl.org, proporciona una gran col·lecció de dades biològiques, similar a la base de dades NCBI/GenBank. A més, ofereix l'eina BioMart, que facilita la recuperació d'informació com ara gens, transcrits i seqüències de proteïnes.
UCSC Genome Bioinformatics
La University of California, Santa Cruz (UCSC) manté la base de dades UCSC Genome Bioinformatics, que proporciona recursos i eines per a la recerca genòmica, principalment en models animals.
Disponible a http://genome.ucsc.edu, inclou un navegador genòmic, pàgines de descàrregues i programari com BLAT per a alineaments ràpids de seqüències, amb integració directa als navegadors genòmics per a visualitzar els resultats.
UniProt
La Universal Protein Resource (UniProt) és una base de dades de seqüències de proteïnes creada per col·laboració entre l'EMBL, l'Swiss Institute of Bioinformatics, i el Protein Information Resource (PIR).
Inclou múltiples bases de dades, com UniRef, que organitza seqüències en clústers segons el percentatge d'identitat. Per exemple, UniRef100 agrupa seqüències idèntiques de com a mínim 11 residus, i UniRef90 fa clústers amb un 90% o més d'identitat.
DNA Data Bank of Japan (DDBJ)
És una base de dades pública que recopila, gestiona i distribueix dades de seqüències genòmiques. Com a membre del International Nucleotide Sequence Database Collaboration (INSDC), treballa conjuntament amb l'NCBI/GenBank als EUA i l'EMBL-EBI/ENA a Europa.
Accessible a través de https://www.ddbj.nig.ac.jp/index-e.html, és un recurs crític per a la recerca genòmica global.
També proporciona eines avançades com BLAST i sistemes per explorar les dades genòmiques. És especialment valuós per a dades genòmiques d'espècies asiàtiques, oferint un punt de vista complementari a altres bases de dades globals.
Nota final
Aquestes bases de dades són essencials per a la biologia computacional i la genòmica, ja que proporcionen accés a seqüències i eines per analitzar-les. Els investigadors poden triar entre Ensembl, UCSC, UniProt o DDBJ segons el tipus de dades o eines que necessitin.
Llegir tots els blocs del fitxer Genbank
Si volem tractar parts importants del Genbank (l’id Accession, l’organisme, taxonomia, la seqüència d’ADN, algunes de les cadenes codificants de proteïnes (CDS), la llista d’autors, comentaris, entre d’altres), el codi anterior ens és insuficient.
Per això us proporcionem una millora del codi anterior.
Per simplificar-lo, seguim amb el Genbank de l’exemple 1 (usant el mètode SeqIO.read, també pot funcionar amb parse).
from Bio import SeqIO # SeqIO is a module (several classes)
from Bio.SeqRecord import SeqRecord # SeqRecord is a class
#from Bio.SeqFeature import SeqFeature, FeatureLocation # Inner classes
from pprint import pformat, pp # Així veiem millor els diccionaris.
# Llegim un fitxer, que és unigenbank.
GENBANK_NAME: str = "NC_005129.2_elephas_mitoc.genbank"
with open(GENBANK_NAME, "r") as file:
demo_genbank: SeqRecord = SeqIO.read(GENBANK_NAME, "genbank")
# També funciona amb:
# demo_genbank: list[SeqRecord] = list(SeqIO.read(GENBANK_NAME, "genbank"))
print('SeqRecord from genbank file:')
# Com hem fet amb el fasta, podem llegir dades del SeqRecord del genbank.
# Annotacions, del bloc 1.
# Ens retorna un diccionari. Els camps compostos (com autors) són una llista.
pp(demo_genbank.annotations)
# Si només ens interessen les referències i els seus autors.
authors = []
for reference in demo_genbank.annotations.get('references', []):
authors.extend(reference.authors.split(", "))
# Si volem eliminar duplicats
authors = set(authors)
print("Llista d'autors:", authors)
# Solució més completa:
references = demo_genbank.annotations.get('references', [])
for i, reference in enumerate(references, 1):
authors = reference.authors.split(", ")
title = reference.title
journal = reference.journal
pubmed = reference.pubmed_id
print(f"Referència {i}:")
print(f" Autors: {authors}")
print(f" Títol: {title}")
print(f" Journal: {journal}")
print(f" PubMed ID: {pubmed}")
# Si volem obtenir totes les features en general.
# Per no allargar la sortida, posem les 3 primeres.
features = demo_genbank.features[0:3]
for feature in features:
print("Tipo de característica:", feature.type)
print("Ubicació:", feature.location)
# Accedeix als qualifiers (etiquetes) de la característica
qualifiers = feature.qualifiers
for key, value in qualifiers.items():
print(f"{key}: {value}")
print()
# Si només ens interessen els comentaris.
comments = demo_genbank.annotations.get('comment', None)
if comments:
print("Llista de comentaris:", comments)
# Per llegir seqüència de nucleòtids, del bloc 3, és igual que el fasta.
# Fixeu-vos que surt tota junta, a diferència del genbank.
print('Primers 100 caràcters Seqüència ')
print(demo_genbank.seq[0:100])
Editar un fitxer Genbank amb Biopython.
De la mateixa manera que passa amb els fasta i fastq, podem editar la informació del genbank fàcilment amb el mètode write del mòdul SeqIO.
Això és per a facilitar sinèrgies amb la comunitat científica.
Nosaltres no ho farem habitualment, però si us fa falta veiem un exemple. El codi:
from Bio import SeqIO
from Bio.SeqFeature import Reference
from pprint import pp
file_path = "./data/example.genbank"
with open(file_path, "r") as file:
# Lee el archivo GenBank
record = SeqIO.read(file, "genbank")
# Obtiene la lista de referencias existentes o crea una nueva lista
references = record.annotations.get('references', [])
# Crea una nueva referencia
new_reference = Reference()
new_reference.authors = 'Amoros,M.A.'
new_reference.title = 'Example Omnics'
new_reference.location = f"bases 1 to {len(record.seq)}"
# Agrega la nueva referencia a la lista de referencias
references.insert(0, new_reference)
record.annotations['references'] = references
# Ruta al archivo GenBank de salida
output_file_path = "./data/example_updated.genbank"
with open(output_file_path, "w") as output_file:
SeqIO.write(record, output_file, "genbank")
print(f"Nueva referencia y versión agregadas a {output_file path}")
Genbank original:
LOCUS 123456 9 bp DNA UNK 01-JAN-2024
DEFINITION GATA seq.
ACCESSION 123456
VERSION 123456
KEYWORDS .
SOURCE Random bacteria
ORGANISM Random bacteria
Bacteria; Random bacteria
REFERENCE 1 (bases 1 to 9)
AUTHORS Bacterio,P.
TITLE El sulfat atòmic
FEATURES Location/Qualifiers
ORIGIN
1 atggattga
//
El nou genbank ha de tenir les següents referències:
REFERENCE 1
AUTHORS Amoros,M.A.
TITLE Example Omnics
REFERENCE 2 (bases 1 to 9)
AUTHORS Bacterio,P.
TITLE El sulfat atòmic
Activitat
4.- Utilitzant el genbank del gènoma de referència del virus SarsCov2; respon als següents punts usant Biopython:
- Quina longitud té la secuencia ?
- Mostra’n els 30 primers caràcters.
- Mostrar quantes annotations (bloc 1) hi ha, l’accession i la referència més recent (la primera del fitxer genbank).
- Mostra el type i la location de totes les features del genbank.
Hauries de provar si funciona amb altres fitxers genbank.
Solució
5.- Crea una API per tal de tenir uns mètodes GET que serviran per consultar informació fasta i genbank que ja tinguem guardats al servidor. Retornaran la resposta en format JSON.
6.- Crea un portal web que proporcioni un formular per a permeti mostrar informació d'un genbank que ja tinguem al servidor.
Per exemple, pots tenir els fitxers de seqüències de la Orquídea i els del SarsCov2. Assegura’t que el seu nom coincideixi amb l’accession o codi; o que almenys el contingui.
Informació que podem aconseguir:
Dels fasta
:
- La descripció o descripcions (si és multifasta).
- Mostrar la seqüència o les seqüències (si és multifasta).
- Tractament errors: Si no existeix un fasta amb el codi indicat s’ha d’informar a l’usuari i proposar-li un accession que existeixi.
Dels genbank
:
- Títol
- Accesion id
- Enllaç directe a l’NCBI (no ho fa Biopython però és fàcil d’aconseguir)
- Referència més recent.
- Número de features
- Type i location de tots els CDS.
- 30 primers caràcters de la cadena d’origen.
- Tractament errors: Si no existeix un genbank amb l’accession indicat s’ha d’informar a l’usuari i proposar-li un accession que existeixi.
Solució (parcial)
Eines per a resoldre la activitat
En l'anterior projecte tens la manera d'aconseguir enviar per formulari dades al servidor:
I fins i tot tens un visualitzador de seqüències que et permet visualitzar totes les features d'una seqüència o d'un Genbank sencer:
Altres formats:
TODO Incorporar algún exemple més.