Els àcids nucleics, i l'ADN en particular, són macromolècules que tenen tota la informació sobre com i quan s'han de construiïr les proteines.

Introducció

Els àcids nucleics són macromolècules compostes d'unitats anomenades nucleòtids.

Hi ha dos tipus: àcid desoxirribonucleic (ADN) i àcid ribonucleic (ARN).

ADN

L'ADN és el material genètic dels organismes vius, des dels bacteris unicel·lulars fins als mamífers multicel·lulars com tu i jo.

Alguns virus utilitzen l'ARN com el seu material genètic, però no es cosidern éssers vius ja que no es poden reproduir sense l'ajuda d'un hoste.

L'ADN es divideix en cromosomes, i cada cromosoma pot contenir desenes de milers de gens.

En organimes procariotes, com els bacteris, l'ADN es troba en una regió especialitzada de la cèl·lula anomenada nucleoide, i els cromosomes són molt més petits i sovint circulars (en forma d'anell).

En cèl·lules eucariotes, com les de les plantes i animals, l'ADN es troba al nucli, una càmera especialitzada envoltada de membrana dins de la cèl·lula, així com en certs tipus diferents d'organels (com els mitocondris i els cloroplasts de les plantes).

Gen

Encara que l'ADN sigui enorme, nomeś una part és codificant, i un dels reptes dels bioinformàtics es descobrir aquells segments d'ADN que proporcionen instruccions sobre com fer un producte particular que necessita la cèl·lula.

L'ADN no s'utilitza directament, sinò que es fan còpies en ARN de la part que codifica el gen cada cop que es necessita.

Molts gens indiquen la seqüència d'aminoàcids que es fan servir per sintetitzar una proteïna en un ribosoma mitjnaçant ARN missatger (ARNm).

Com hem dit abans, no tots els gens codifiquen per a productes proteics.

A contiuanció tens alguns exemples de diferents tipus d'ARN:

  • ARN ribosòmic (ARNr): Serveix com a component estructural dels ribosomes

  • ARN de transferència (ARNt). Són molècules d'ARN en forma de trèvol que transporten aminoàcids al ribosoma per a la síntesi de proteïnes.

  • Micro ARN (coneguts com miRNA). ctuen com a reguladors d'altres gens.

Nucleòtids

L'ADN i l'ARN són polímers (en el cas de l'ADN solen ser polímers molt llargs) i es componen de monòmers coneguts com nucleòtids (A,C,G...). Quan aquests monòmers es combinen, la cadena resultant es diu polinucleòtid (poli- = "molts").

Cada nucleòtid es compon de tres parts:

  1. Un sucre de cinc carbonis que té una posició central.
  2. Una estructura anular que conté nitrogen anomenada base nitrogenada.
  3. Almenys un grup fosfat.

La molècula de sucre té una posició central al nucleòtid, la base es connecta a un dels seus carbonis i el grup (o grups) fosfat, a un altre. Vegem cada part d'un nucleòtid alhora.

Imatge dels components de l'ADN i l'ARN, que inclouen el sucre (desoxiribosa o ribosa), el grup fosfat i la base nitrogenada. Les bases comprenen les bases pirimidines que tenen un anell (citosina i timina a l'ADN, i uracil a l'ARN) i les bases purines amb dos anells (adenina i guanina). El grup fosfat s'uneix al carboni 5'. El carboni 2' té un grup hidroxil a la ribosa, però només hidrogen (no hidroxil) a la desoxiribosa.

Bases nitrogenades

Les bases nitrogenades dels nucleòtids són molècules orgàniques (basades en carboni), compostes per estructures anulars que contenen nitrogen. Per què es diuen bases?. Atès que alguns dels nitrogens de la base poden protonar-se (rebre un ió H+), les bases nitrogenades disminueixen la concentració d'ions hidrogen en una solució i per tant són bases en el sentit àcid-base.

Cada nucleòtid a l'ADN conté una de quatre possibles bases nitrogenades: adenina (A), guanina (G) citosina (C) i timina (T).

L'adenina i la guanina són purines, el que significa que les seves estructures contenen dos anells fusionats de carboni i nitrogen.

En canvi, la citosina i la timina són pirimidines i tenen només un anell de carboni i nitrogen.

Els nucleòtids d'ARN també poden contenir bases d'adenina, guanina i citosina, però tenen una altra base tipus pirimidina anomenada uracil (U) en lloc de la timina. Com es mostra a la figura anterior, cada base té una estructura única, amb el seu conjunt de grups funcionals units a l'estructura anular.

Com a abreviatures a la biologia molecular, les bases nitrogenades se solen anomenar pels seus símbols d'una lletra: A, T, G, C i U.

L'ADN conté A, T, G i C, mentre que l'ARN conté A, U, G i C (és a dir, la U s'intercanvia per T).

Els sucres

A més de tenir conjunts de bases lleugerament diferents, els nucleòtids d'ADN i ARN també tenen sucres lleugerament diferents. El sucre de cinc carbonis de l'ADN s'anomena desoxiribosa, mentre que a l'ARN el sucre és la ribosa. Aquestes dues molècules són semblants en estructura, només amb una diferència: el segon carboni de la ribosa té un grup hidroxil, mentre que el carboni equivalent a la desoxiribosa té un hidrogen al seu lloc.

Els àtoms de carboni d'una molècula de sucre es numeren 1', 2', 3', 4' i 5' (1' es llegeix "una cosina"), com es mostra a la figura anterior.

En un nucleòtid, el sucre ocupa la posició central, la base s'uneix al carboni 1' i el grup (o grups) fosfat s'uneix al carboni 5'.

El fosfat

Els nucleòtids només poden tenir un grup fosfat o una cadena de fins a tres grups fosfat que s'uneixen al carboni 5' del sucre. Algunes fonts d'informació química utilitzen el terme "nucleòtid" només per al cas d'un fosfat, però en biologia molecular s'accepta generalment la definició més àmplia.

En una cèl·lula, el nucleòtid que cal afegir al final d'una cadena de polinucleòtids contindrà una sèrie de tres grups fosfat. Quan el nucleòtid s'uneix a la cadena creixent d'ADN o ARN perd dos grups fosfat. Per tant, en una cadena d'ADN o ARN, cada nucleòtid només té un grup fosfat.

Cadenes de polinucleòtids

Una conseqüència de l'estructura dels nucleòtids és que una cadena de polinucleòtids té direccionalitat, és a dir té dos extrems que són diferents entre si.

Al extrem 5', o inici de la cadena, sobresurt el grup fosfat unit al carboni 5' del primer nucleòtid. A l'altre extrem, anomenat extrem 3', està exposat l'hidroxil unit al carboni 3' de l'últim nucleòtid.

Les seqüències d'ADN generalment s'escriuen a l'adreça 5' a 3', cosa que significa que el nucleòtid de l'extrem 5' és el primer i el nucleòtid de l'extrem 3' és l'últim.

Conforme s'agreguen nous nucleòtids a una cadena d'ADN o ARN, aquesta creix a l'extrem 3', quan s'uneix el fosfat 5′ del nucleòtid entrant al grup hidroxil a l'extrem 3' de la cadena. Això produeix una cadena on cada sucre s'uneix als seus veïns per una sèrie d'enllaços anomenats enllaços fosfodièster.

Característiques de l'ADN

A l'àcid desoxirribonucleic, o ADN, les cadenes es troben normalment en una doble hèlix, una estructura en què dues cadenes aparellades (complementàries) s'uneixen entre si, com es mostra al diagrama.

Les dues cadenes de l'hèlix corren en adreces oposades, cosa que significa que l'extrem 5′ d′una cadena s′uneix a l′extrem 3′ de la seva cadena corresponent. Això es coneix com a orientació antiparal·lel i és important a l'hora de replicar l'ADN.

Aleshores, dues bases qualsevol poden decidir unir-se i formar un parell a la doble hèlix? La resposta és un no definitiu. A causa de les mides i els grups funcionals de les bases, l'aparellament de les bases és summament específic: A només es pot unir amb T i G només es pot unir amb C, com es mostra a continuació.

Per exemple, si sabeu que la seqüència d'una cadena és 5'-AATTGGCC-3', la cadena complementària ha de tenir la seqüència 3'-TTAACCGG-5'.

Això permet a cada base unir-se amb la parella: els parells A-T estan units per dos ponts d'hidrogen i els parells G-C per tres.

Es diu que dues seqüències d'ADN són complementaris quan les seves bases poden aparellar-se i unir-se entre si de forma antiparal·lela, formant una hèlix.

Les cadenes d'ADN s'uneixen en una doble hèlix de cadenes antiparal·leles mitjançant ponts d'hidrogen entre les bases complementàries . La timina forma dos ponts d´hidrogen amb l´adenina i la guanina forma tres ponts d´hidrogen amb la citosina.

Replicació de l'ADN.

La replicació de l'ADN és el procés pel qual es produeix a partir d'una molècula original d'ADN dues còpies idèntiques. La replicació té lloc en tots els organismes vius i és la base biològica de l'herència, és a dir, que és la molècula que serà transmesa a la descendència.

Durant la replicació de l'ADN, la doble hèlix es divideix en dues parts: les bases nitrogenades de cada meitat s'acoblen amb la base homòloga, formant així la cadena mancant. Això vol dir que cada una de les cadenes originals servirà de motlle per la síntesi d'una nova cadena.

Aquest fet assegura una alta fidelitat en la replicació, així com facilita la correcció d'errors que es poguessin donar durant la replicació.

Una mutació és un error en l'aparellament de bases. Per exemple, a la seqüència AATTGGCC, una mutació pot fer que la segona T canviï a una G. La majoria de vegades quan això succeeix l'ADN és capaç de fixar-se i tornar la base original a la seqüència.

No obstant això, de vegades la reparació no té èxit, cosa que resulta en la creació de diferents proteïnes.

Característiques de l'ARN

  1. Estructura de l'ARN:

    • L'ARN és monocatenari amb ribosa com a sucre.
    • Té bases nitrogenades A, U, G, C.
  2. Tipus d'ARN:

    • ARN missatger (ARNm):
      • Serveix com a intermediari entre un gen i la seva proteïna.
      • Es transcriu a partir de l'ADN substituint T per U.
      • L'ARNm interactua amb el ribosoma per sintetitzar proteïnes a partir de codons (grups de tres nucleòtids).
    • ARN ribosòmic (ARNr):
      • Component essencial dels ribosomes.
      • Pot actuar com a enzim (ribozima), catalitzant la unió d'aminoàcids en proteïnes.
    • ARN de transferència (ARNt):
      • Porta aminoàcids al ribosoma segons la seqüència de l'ARNm.
      • Té una estructura tridimensional complexa per la seva funció.
    • ARN regulatori:
      • Inclou miRNA i siRNA, que regulen l'expressió gènica.
      • S'uneixen a l'ARNm per reduir-ne la traducció o estabilitat.
      • Poden estar relacionats amb malalties com el càncer.

Cada vegada hi ha més evidència que els miRNA i altres ARN petits, no codificants, participen en certes malalties humanes, com en alguns trastorns genètics i tipus de càncer.

A més, els investigadors estan desenvolupant microARN artificials que serveixen com a eines terapèutiques en el tractament de malalties humanes.

Aquests són només alguns exemples d'ARN reguladors. Hi ha molts altres i, amb el temps, se segueixen descobrint més.


Aplicacions i Perspectives

  • El coneixement dels diferents tipus d'ARN està avançant, amb la descoberta de nous tipus com ARNlnc i piRNA.
  • Els microARN artificials s'estan desenvolupant per al tractament de trastorns genètics i càncers.

Aquest resum sintetitza els punts principals i facilita la comprensió del tema! 😊

Activitat Biopython

Introducció

El projecte Biopython és una col·lecció de codi obert d'eines Python no comercials per a la biologia computacional i la bioinformàtica, possiblement la més reconeguda en Python. Ha estat creada per una associació internacional de desenvolupadors.

Conté classes per representar seqüències biològiques i anotacions de seqüències, i és capaç de llegir i escriure en una varietat de formats de fitxer. També permet un mitjà programàtic d'accés a bases de dades en línia d'informació biològica, com les de NCBI.

Els mòduls separats amplien les capacitats de Biopython a l'alinement de seqüències, BLAST, estructura de proteïnes, genètica de poblacions, filogenètica, motius de seqüències i aprenentatge automàtic.

La documentació oficial de la versió més recent de Biopython la pots trobar a:

API Biopython, lastest version

Instal·lació

Per agilitzar la sessió, clona el repositori git que hem preparat i segueix les instruccions del readme.md

git clone https://gitlab.com/xtec/bio/biopython-api.git

En cas que vulguis instal·lar i usar Biopython en un projecte de Python i Poetry existent usa la comanda:

poetry install
poetry add biopython

Si vols, pots recordar com funciona el gestor de paquets i entorns Poetry:

https://xtec.dev/python/poetry/

Seq

L’objecte Seq és el mecanisme de Biopython per tractar les seqüències, que són essencialment “strings” de lletres com AGTACACTGGT.

La diferència més important entre els objectes Seq i els string estàndard de Python és que tenen mètodes diferents.

Encara que l’objecte Seq admet molts dels mateixos mètodes que un simple string, el mètode translate() de Seq és diferent perquè fa una traducció biològica, com també hi ha mètodes addicionals biològicament rellevants com reverse_complement().

Crea un fitxer app/sequence.py.

En molts aspectes podem tractar els objectes Seq com si fossin “strings” normals de Python, per exemple, obtenint la longitud o iterant sobre els elements:

from Bio.Seq import Seq

seq = Seq("GATCG")
for index, letter in enumerate(seq):
    print("%i %s" % (index, letter))
print(len(seq))

El resultat obtingut és:

miqamorosal/biopython-api$ python3 app/sequence.py 
0 G
1 A
2 T
3 C
4 G
5

Pots accedir als elements de la seqüència de la mateixa manera que si fos un “string” ( recorda que Python comença a comptar des de zero!):

Com ja saps, per provar el codi amb el que treballem pots usar la llibreria pytest.

Crea el fitxer tests/test_seq.py

from Bio.Seq import Seq

def test():
   seq = Seq("GATCG")
   assert seq[0] == "G"  # primera lletra
   assert seq[2] == "T"  # tercera lletra
   assert seq[-1] == "G"  # darrera lletra

Prova que funciona:

miqamorosal/biopython-api$ python3 app/test_seq.py pytest tests/tests_seq.py 

====== test session starts ==================
platform linux -- Python 3.10.12, pytest-8.3.4, pluggy-1.5.0
rootdir: /mnt/c/Users/USUARI/biopython-api
configfile: pyproject.toml
plugins: anyio-4.7.0
collected 1 item  

tests/tests_seq. py .                  [100%]
========== 1 passed in 0.50s =================

L’objecte Seq té un mètode .count() igual que un “string”.

Això vol dir que al igual que un “string” el resultat del recompte no es solapa:

from Bio.Seq import Seq

def test():
   assert "AAAA".count("AA") == 2
   assert Seq("AAAA").count("AA") == 2

Per a alguns usos biològics, és possible que vulguis un recompte superposat (és a dir, 3 en aquest exemple trivial). Quan cerqueu lletres senzilles, això no fa cap diferència:

from Bio.Seq import Seq

def test():
   seq = Seq("GATCGATGGGCCCTATATAGGATCGAAAATCGC")

   assert len(seq) == 33
   assert seq.count("G") == 9

   gc_fraction = (seq.count("G") + seq.count("C")) / len(seq)
   assert round(gc_fraction, 2) == 0.48

Tallar una seqüència (slices)

Al igual que un “string” podem tallar una seqüència amb la tècnica dels slices; que si vols pots repassar a https://xtec.dev/python/sequence/

from Bio.Seq import Seq

def test():
   seq = Seq("GATCGATGGGCCCTATATAGGATCGAAAATCGC")
   assert seq[4:12] == Seq("GATGGGCC")

Els objectes Seq segueixen les convencions d'indexació habituals dels “strings” amb el primer element de la seqüència numerat 0.

Quan fas un slice:

seq[4:12]

El primer element s’inclou (‍4 en aquest cas) i l'últim s'exclou (12 en aquest cas).

Al igual que amb un “string” també pots fer un slice amb un “stride” (la mida de cada pas, que per defecte és 1).

Per exemple, podem obtenir la primera, segona i tercera posició del codó d'aquesta seqüència d'ADN:

from Bio.Seq import Seq

def test():
   
   seq = Seq("GATCGATGGGCCCTATATAGGATCGAAAATCGC")

   assert seq[0::3] == Seq("GCTGCTAAGAC")
   assert seq[1::3] == Seq("AGGCTAGTAAG")
   assert seq[2::3] == Seq("TAGCATGCATC")

Un altre truc que es pot fer amb un string per invertir l’string, que és fer servir un “stride” de -1, també es pot fer servir amb un objecte Seq:

from Bio.Seq import Seq

def test():

   seq = Seq("GATCGATGGGCCCTATATAGGATCGAAAATCGC")
   assert seq[::-1] == Seq("CGCTAAAAGCTAGGATATATCCCGGGTAGCTAG")

Convertir objectes Seq en “strings”

Si només necessites un “string” per escriure’l en un fitxer a una base de dades, és molt fàcil de fer:

from Bio.Seq import Seq

def test():

   seq = Seq("GATCGATGGGCCCTATATAGGATCGAAAATCGC")
   assert str(seq) == "GATCGATGGGCCCTATATAGGATCGAAAATCGC"

Com que la funció str() aplicada a un objecte Seq retorna la seqüència completa com un “string”, no és necessari fer aquesta conversió de manera explícita. Per exemple, Python ho fa automàticament en la funció print():

from Bio.Seq import Seq

seq = Seq("GATCGATGGGCCCTATATAGGATCGAAAATCGC")
print(seq)

Canvi de majúscules a minúscules (upper/lower)

Els mètodes upper i lower et permeten canviar entre majúscules i minúscules:

from Bio.Seq import Seq

def test():
   seq = Seq("acgtACGT")

   assert seq.upper() == Seq("ACGTACGT")
   assert seq.lower() == Seq("acgtacgt")

Aquest mètodes són molt útils per fer una comparació que no distingeixi entre majúscules i minúscules:

from Bio.Seq import Seq

def test():
   seq = Seq("acgtACGT")

   assert not "GTAC" in seq
   assert "GTAC" in seq.upper()

Seqüències de nucleòtids i complements (invers).

Per a seqüències de nucleòtids, podeu obtenir fàcilment el complement o el complement invers de l’objecte Seq :

from Bio.Seq import Seq

def test():
   seq = Seq("GATCGA")

   assert seq.complement() == Seq("CTAGCT")
   assert seq.reverse_complement() == Seq("TCGATC")

Com s'ha esmentat anteriorment, una manera senzilla de revertir un objecte Seq (o una cadena de Python) és fer un slice amb stride -1:

from Bio.Seq import Seq

def test():
   seq = Seq("GATCGA")
   assert seq[::-1] == Seq("AGCTAG")

Això només té sentit biològic amb una seqüència d’ADN (no de proteïnes)

Com verificar si la cadena ADN no és ambigua

Una cadena d'ADN ambigua consisteix en una cadena en la que hi ha almenys un nucleòtid que no sabem del cert si és una de les 4 bases (A,C,G,T); i aquesta casuística encara és present en molts gens.

Per a poder aprofitar les parts de l'ADN que ens interessi i tractar aquestes ambigüitats la comunitat científica ha definit uns caràcters de consens:

IUPAC Ambigüity codes

Sorprenentment, BioPython no té un mètode predefinit per a detectar-les (o no és conegut) i ho hem de fer nosaltres.

Hi ha moltes maneres de fer-ho; però una de les preferides per la comunitat d’Stackoverflow és aquest:

   seq_valida = all(base in "ACGTacgt" for base in seq_adn)

Alternativament, també es poden usar expressions regulars; que són molt eficients i serveixen per a molts llenguatges de programació:

   import re
   seq_valida = bool(re.match("^[ACGT]+$", seq))

Aquesta expressió valida que des de la primera lletra (caràcter ^) fins a la última (caràcter +$) només hi ha els caràcters que estan entre brackets [ACGT].

Pots repassar el funcionament de les expressions regulars amb aquests reptes: https://regexone.com/

Càlcul %GC.

El percentatge GC (guanina-citosina) és una mesura que indica la proporció de parells de bases guanina-citosina en una seqüència d'àcid nucleic (ADN o ARN) respecte al total de parells de bases.

Aquesta mesura és important en genètica i biologia molecular perquè pot donar indicacions sobre la estabilitat de la molècula d'ADN o ARN, ja que els parells de bases GC tenen una força de vincle més gran que els parells adenina-timina o adenina-uracil.

El genoma humà es caracteritza per presentar una gran heterogeneïtat en la seva seqüència. En particular, la riquesa en bases de guanina (G) i citosina (C) enfront de les d'adenina (A) i timina (T) es distribuïx heterogèniament, amb regions molt riques en G+C flanquejades per regions molt pobres, sent el contingut mitjà de G+C del 41%, menor al teòricament esperat (50%).

Aquesta heterogeneïtat està correlacionada amb la riquesa en gens, de manera que els gens tendeixen a concentrar-se en les regions més riques en G+C.

Per últim, tingues en compte que igual que un string l’objecte Seq és de "només de lectura". Si necessites editar una seqüència per simular una mutació puntual pots fer servir l’objecte MutableSeq.

És bastant fàcil calcular el percentatge GC%; anem a recuperar una solució eficient; que en un sol bucle compta les bases i et retorna el percentatge.

def adn_percent_gc(adn):
    """Retorna el percentatge GC"""
    counter = 0
    for x in adn:
        if x == "G" or x == "C":
            counter += 1
    
    percent = round(counter / len(adn), 4)

    return percent 

Aquesta solució és molt eficient si estem segurs que és una cadena sense ambigüitats.

Però com ja hem explicat abans, ens podem trobar cadenes ambigües, que poden tenir altres caràcters (per exemple, la R (coneguda com la Purina); implica que el nucleòtid pot ser una A o una G).

Llavors el càlcul es complica una mica; ja que podem sumar 0.5 (tenim un 50% de possibilitats que sigui una G) o ser estrictes i si no estem segurs sumar 0.

Aquí és on Biopython aporta valor afegit; ja que el mòdul Bio.SeqUtils té diverses funcions per calcular G+C.

La més habitual és gc_fraction(), la més actualitzada de Biopython, és capaç de gestionar seqüències amb majúscules i minúscules així com gestionar nucleòtids ambigus com el S (que significa G o C).

from Bio.Seq import Seq
from Bio.SeqUtils import gc_fraction

seq = Seq("SATCGASS")
   fraction = gc_fraction(seq)
   print(seq)

   assert round(fraction, 4) == 0.6250

Més detalls a la documentació oficial de Biopyhton:

https://biopython.org/docs/latest/api/Bio.SeqUtils.html#Bio.SeqUtils.gc_fraction

Per a què et facis una idea; aquí tens les 3 maneres que té la funció de calular.

>>> seq = "ACTGN"
>>> gc = gc_fraction(seq, "ignore")
>>> print(f"GC content of {seq} : {gc:.2f}")
GC content of ACTGN : 0.40
>>> gc = gc_fraction(seq, "weighted")
>>> print(f"GC content with ambiguous counting: {gc:.2f}")
GC content with ambiguous counting: 0.50
>>> gc = gc_fraction(seq, "remove")
>>> print(f"GC content with ambiguous removing: {gc:.2f}")
GC content with ambiguous removing: 0.50

Si l'usuari envia caràcters que no pertanyen a la taula de consens, els ignora.

Diferències entre versions.

Respecte el percentatge GC, cal anar molt en compte perquè a partir de la versió 1.8 s'ha creat la funció gc_fraction() i s'ha eliminat la funció GC().

Fan exactament el mateix, però cal anar amb compte amb aquest canvi arquitectòtnic perquè hi ha papers i els algorismes IA com ChatGPT, que aquest canvi sobtat els ha passat factura, ja que no ho han actualitzat !!!

Transcripció

Considera el següent tram (composat) d'ADN de doble cadena que codifica un pèptid curt:

5’ ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG 3|||||||||||||||||||||||||||||||||||||||
3’ TACCGGTAACATTACCCGGCGACTTTCCCACGGGCTATC 5’
DNA template strand (aka Watson strand, strand −1)
|
Transcription
↓
5’ AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG 3

Recorda que per convenció les seqüències de nucleòtids normalment es llegeixen des de la direcció 5' a 3'.

Observació: Un exemple conegut de pèptid curt és l'oxitocina, que té un paper en la regulació de les contraccions uterines i altres processos fisiològics. Un pèptid curt es refereix a una cadena de pèptids relativament curta, que és una successió d'aminoàcids units per enllaços peptídics.

El procés de transcripció biològica real funciona a partir de la cadena de plantilla (template strand), fent un complement invers (TCAG → CUGA) per donar l'ARNm.

from Bio.Seq import Seq

def test():
   coding_dna = Seq("ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG")

   template_dna = coding_dna.reverse_complement()
   messenger_rna = template_dna.reverse_complement().transcribe()

   assert messenger_rna == Seq("AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG")

Tanmateix, a Biopython i a la bioinformàtica en general, normalment treballem directament amb la cadena de codificació (coding strand) perquè això vol dir que podem obtenir la seqüència d'ARNm només canviant T → U.

from Bio.Seq import Seq

def test():
   
   coding_dna = Seq("ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG")
   messenger_rna = coding_dna.transcribe()

   assert messenger_rna == Seq("AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG")

L'objecte Seq també inclou un mètode de retrotranscripció per passar de l'ARNm a la cadena codificant de l'ADN.

De nou, aquesta és una substitució simple U → T:

from Bio.Seq import Seq

def test():

   messenger_rna = Seq("AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG")
   coding_dna = messenger_rna.transcribe()

   assert coding_dna == Seq("ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG")

Scripts amb Biopython.

Aquí tenim un programa que, si li passes una cadena d'ADN com a argument, et transcriu l'ARN i et calcula el %GC.

# Importació llibreries
from Bio.Seq import Seq
from Bio.SeqUtils import gc_fraction
import sys

dna: str = ""
# El programa només funciona si l'usuari passa una cadena d'ADN com a argument.
if len(sys.argv) != 2:
    print("Instruccions d'ús: " + sys.argv[0] + " <cadena d'ADN>")
    sys.exit()
else:
    dna = sys.argv[1]
    # Convertim la cadena a objecte Seq.
    dna_seq = Seq(dna)

# Aquí surten els resultats per pantalla.
print(f"Seqüència ADN original: {dna}")
print(f"Seqüència ADN reversa complementaria : {dna_seq.reverse_complement()}")
arn = dna_seq.transcribe()
print(f"Seqüència ARN: {arn}")
print(f"Percentatge GC: {gc_fraction(dna)}")

Fixeu-vos com surt del programa si l'usuari no li passa cap argument:

# El programa només funciona si l'usuari passa una cadena d'ADN com a argument.
if len(sys.argv) != 2:
    print("Instruccions d'ús: " + sys.argv[0] + " <cadena d'ADN>")
    sys.exit()

Amb aquest simple canvi has aconseguit que teu programa terminal sigui més útil per a investigadors, ja que no han de tocar el codi per obtenir dades de l'ADN.

Creació de serveis web amb FastAPI.

Dins del projecte que t'hem proporcionat, tens una API que funciona amb FastAPI

from fastapi import FastAPI, HTTPException
from Bio.Seq import Seq
import time

app = FastAPI()

@app.get("/api/time")
def get_current_time():
    return {"time": time.time()}

@app.get("/api/sequence/rna/{seq}")
def rna(seq: str):
    if not seq or seq.strip() == "":
        raise HTTPException(status_code=400, detail="DNA sequence is required")
    
    seq_obj = Seq(seq.upper())
    rna = seq_obj.transcribe()
    # Hem de convertir l'ARN a string per serialitzar el JSON.
    return { "rna": str(rna) }

if __name__ == "__main__":
    app.run()

Revisa el document de FastAPI i el readme.md del nostre projecte per arrencar i fer els teus web services.

Per exemple, pots provar tots els endpoints a: http://localhost:8000/docs

O provar des del terminal el endpoint que transcriu un ADN a ARN:

biopython-api$ curl -X 'GET' \
  'http://localhost:8000/api/sequence/rna/AGTCGT' \
  -H 'accept: application/json'
{"rna":"AGUCGU"}

Exercicis, back-end.

Crea endpoints (mètode d’un web service) de tipus GET i POST que donada una seqüència d’ADN calculi:

    • El porcentatge gc (de bases G i C respecte el total)
    • La transcripció a ARNm.

from fastapi import FastAPI, HTTPException
from Bio.Seq import Seq
from Bio.SeqUtils import gc_fraction
import time

app = FastAPI()

# Mètode d'utilitat per llegir la cadena o si no hi ha cap error.
def read_seq(seq: str) -> Seq:
    if not seq or seq.strip() == "":
        raise HTTPException(status_code=400, detail="DNA sequence is required")
    
    seq_obj = Seq(seq.upper())
    return seq_obj

@app.get("/api/time")
def get_current_time():
    return {"time": time.time()}

@app.get("/api/sequence/gc_percent/{seq}")
def gc_percent(seq: str):
    seq_obj = read_seq(seq)
    result = f'{gc_fraction(seq_obj, "weighted"):.4f}'
    # Hem de convertir l'ARN a string per serialitzar el JSON.
    return { "gc_fraction": result }

@app.get("/api/sequence/rna/{seq}")
def rna(seq: str):
    seq_obj = read_seq(seq)

    rna = seq_obj.transcribe()
    # Hem de convertir l'ARN a string per serialitzar el JSON.
    return { "rna": str(rna) }

if __name__ == "__main__":
    app.run()
    • Que informi si la seqüència és ambigua (amb altres caràcters diferents a l'A,C,G,T) o no ho és.
    • Crea un nou endpoint anomenat info faci totes les operacions (1, 2 i 3) alhora per estalviar-nos crides al servidors.

from fastapi import FastAPI, HTTPException
from Bio.Seq import Seq
from Bio.SeqUtils import gc_fraction
import time

app = FastAPI()

@app.get("/api/sequence/info/{seq}")
def rna(seq: str):
    seq_obj = read_seq(seq)

    rna = seq_obj.transcribe()
    gc = f'{gc_fraction(seq_obj, "weighted"):.4f}'
    is_ambiguous = bool(re.match("^[ACGT]+$", seq))
    # Hem de convertir l'ARN a string per serialitzar el JSON.
    return { "rna": str(rna), "gc_fraction": gc, "is_ambiguous" : is_ambiguous }
    • Crea un programa en el terminal (carpeta script) que realizi totes les operacions i informi a l'usuari els resultats.

from Bio.Seq import Seq
from Bio.SeqUtils import gc_fraction
import sys
import re

dna: str = ""
if len(sys.argv) != 2:
    print("Instruccions d'ús: " + sys.argv[0] + " <cadena d'ADN>")
    sys.exit()
else:
    dna = sys.argv[1]
    # Convertim la cadena a objecte Seq.
    dna_seq = Seq(dna)

print(f"Seqüència ADN original: {dna}")
print(f"Seqüència ADN complementaria : {dna_seq.complement()}")
arn = dna_seq.transcribe()
print(f"Seqüència ARN: {arn}")

print(f"Percentatge GC: {gc_fraction(dna)}")

seq_valida = bool(re.match("^[ACGT]+$", dna))
print(f"La seqüència és ambigüa ? {not(seq_valida)}")

Tots aquests mètodes haurien de convertir a majúscules la cadena.

A més a més, cal que t'asseguris que l'usuari passi una cadena d'ADN.

Exercicis, front-end.

A partir del projecte amb FastAPI, Vite i React: https://gitlab.com/xtec/bio/sequence.

    • Crea una pàgina web que agafi una cadena d'ADN i obtingui el revers complementar i transcrigui el seu ARN; sense fer cap crida al servidor.

Per aconseguir-ho podem aprofitar la llibreria bionode-seq.

En el projecte d'exemple tens una part de la solució.

L'aspecte hauria de ser el següent:

No és necessari que funcioni amb cadenes no ambigües.

    • A sota del camp de text de l'ARN; fes que també es vegi de quin tipus és la cadena d'ADN introduïda per l'usuari, ajudant-te del mètode checktype de Bionode.

CheckType:

https://doc.bionode.io/?javascript#checktype

Documentació oficial React:

https://react.dev/reference/react-dom/components/form

Projecte any anterior (però no és exactament igual)

https://gitlab.com/mamorosdev/m14-uf2-bioseq-2/

    • Investiga si bionode o alguna altra llibreria de Javascript té un mètode per a calcular el %GC.