1. Introducció als entorns de treball UNIX

1.15. Disseny de protocols automàtics al terminal

En aquest apartat us introduireu en el disseny de protocols automàtics en un terminal bash. Dins del camp de la bioinformàtica aprendre a dissenyar protocols és útil per diverses raons. En primer lloc, permet l’automatització de tasques repetitives, la qual cosa estalvia temps i redueix el risc d’errors. En segon lloc, permet la creació de fluxos de treball reproduïbles, que són essencials per a la recerca científica. En tercer lloc, bash és una eina poderosa i flexible que es pot utilitzar per manipular conjunts de dades grans i realitzar anàlisis complexes. Finalment, l’ús de protocols (en anglès, script) bash facilita la col·laboració i l’intercanvi de protocols, cosa que fa que sigui més fàcil per als investigadors reproduir la feina d’altres i construir-hi. En general, el disseny de protocols automàtics en un terminal bash és una forma eficient i efectiva de realitzar anàlisis de bioinformàtica.

En dissenyar un protocol en un terminal bash, hi ha diversos aspectes tècnics i paràmetres que s’han de tenir en compte. Aquí es presenten els aspectes més importants que cal considerar.

  • Sintaxi i gramàtica: el protocol ha de tenir una sintaxi i una gramàtica ben definides que siguin fàcils d’entendre i seguir.
  • Maneig d’errors: el protocol ha d’estar dissenyat per manejar errors i excepcions de manera elegant. Això inclou la definició de codis d’error i missatges.
  • Seguretat: el protocol ha d’estar dissenyat per garantir la privacitat i seguretat de les dades. Això inclou mesures com l’encriptació, l’autenticació i el control d’accés.
  • Compatibilitat: el protocol ha de ser compatible amb el hardware i el software del sistema en el qual s’utilitzarà.
  • Eficiència: el protocol ha d’estar dissenyat per ser eficient i optimitzar l’ús dels recursos del sistema, com la CPU i la memòria.
  • Escalabilitat: el protocol ha d’estar dissenyat per ser escalable, de manera que pugui manejar quantitats creixents de dades i usuaris sense degradació del rendiment.
  • Documentació: el protocol ha d’estar ben documentat, amb instruccions clares i exemples per a la seva implementació i ús.
  • Proves: el protocol ha de ser provat exhaustivament per assegurar que la seva funcionalitat i rendiment compleixin amb els requisits.

Tenint en compte aquests aspectes tècnics i paràmetres, el protocol pot ser dissenyat per ser efectiu, segur i eficient en el seu funcionament. En aquest apartat se us mostra com dissenyar protocols senzills, i no es tindrà en compte tot el que s’ha esmentat anteriorment, però sempre s’ha de treballar tenint en compte totes les consideracions esmentades.

En aquest exercici se us mostrarà com generar un protocol per obtenir informació biològica rellevant a partir de 3 seqüències FASTA. T’animo a realitzar tots els passos que es mostren a continuació. Obre un terminal i comença.

1) Crea un directori:

$ mkdir fasta_sequence
$ cd fasta_sequence

2) Descarrega, en l’anterior directori i des de la base de dades ENA (European Nucleotide Archive), les seqüències FASTA associades als gens humans de BRCA1, BRCA2 i HOXB13:

3) Quan es volen executar una sèrie d’ordres de forma seqüencial al terminal bash, es crea un script o protocol i es guarda en un arxiu de text amb extensió «.sh». Aquest script ens permet referir-nos internament als seus paràmetres de manera genèrica, la qual cosa significa que pot funcionar en qualsevol grup d’arguments del mateix tipus. A més, per fer-lo més flexible s’han d’especificar aquests paràmetres genèrics dins de l’script, de manera que, quan s’invoqui l’script des de la línia d’ordres, podem substituir aquests paràmetres genèrics per valors específics proporcionats per l’usuari juntament amb el nom de l’ordre. En utilitzar aquest enfocament, es poden automatitzar tasques repetitives o processos complexos, la qual cosa fa que la feina sigui més eficient i consistent.

$ vi analitza_fasta.sh

4) Abans d’introduir el codi per generar un protocol, dues consideracions a tenir en compte:

  • En la primera línia del protocol s’ha d’indicar, sempre, l’intèrpret d’ordres bash (GNU Bourne-Again SHell). En la majoria dels sistemes coexisteixen altres intèrprets com sh (Bourne) o csh (C shell). El directori on es localitza l’intèrpret s’escriu a continuació del conjunt de símbols #!
  • Per introduir comentaris en el protocol s’ha d’introduir el símbol # (en anglès, shebang) a la primera columna del fitxer.

5) Escriu cadascuna de les següents línies en el fitxer sh que acabes d’obrir. Has d’escriure en mode insert, el primer que has de fer és teclejar la lletra i, i a continuació escriu les línies següents:

#!/bin/bash

# Aquest protocol analitza un fitxer que conté una única seqüència FASTA

# Primer, se subministra el nom del fitxer com a argument

if [ $# -eq 0 ]

then

    echo "Per favor, subministra un nom de fitxer com a argument"

    exit 1

fi

# El símbol $$ indica el PID del procés

echo "El valor del PID del procés és";

echo "PID és $$";

# $1 representa el primer argument a analitzar. En aquest cas el nom del fitxer FASTA

echo "La mida del fitxer FASTA és:";

ls -sh $1 | gawk '{print $1}';

echo "Nombre de línies del fitxer FASTA:";

wc -l $1 | gawk '{ print $1 }';

echo "Extreu les primeres set línies del fitxer";

head -7 $1;

# Les següents dues línies considera comentar-les, si la seqüència FASTA té moltes línies

echo "Extreu la seqüència del fitxer FASTA";

sequence=$(awk '/^>/ {next} {printf "%s", $0} END {print ""}' "$1")

echo "$sequence"

# Càlcul de la longitud de la seqüència

length=$(echo -n "$sequence" | wc -c)

echo " Longitud de la seqüència: $length nucleotids"

# Compte el número de nucleòtids que té la seqüència

num_A=$(grep -o 'A' <<< "$sequence" | wc -l)

num_C=$(grep -o 'C' <<< "$sequence" | wc -l)

num_G=$(grep -o 'G' <<< "$sequence" | wc -l)

num_T=$(grep -o 'T' <<< "$sequence" | wc -l)

# S’han generat in situ 4 noves variables. Imprimeix cada nombre de nucleòtids

echo "Nombre de nucleòtid A: $num_A"

echo "Nombre de nucleòtid C: $num_C"

echo "Nombre de nucleòtid G: $num_G"

echo "Nombre de nucleòtid T: $num_T"

# Càlcul del contingut GC de la seqüència

num_GC=$((num_C + num_G))

total=$((num_A + num_C + num_G + num_T))

gc_content=$(bc -l <<< "scale=2; $num_GC / $total * 100")

echo "GC contenido: $gc_content%"

# Identificació dels ORFs de la seqüència

echo "Identificant ORFs..."

ORFs=$(echo -n "$sequence" | tr 'ATCG' 'tacg' | grep -Eo '(atg([acgt]{3})*?(taa|tag|tga))+' | tr 'tacg' 'ATCG')



if [ -z "$ORFs" ]

then

    echo "No es troben ORFs"

else

    num_ORFs=$(echo -n "$ORFs" | awk '{print length}' | wc -l)

    echo "Nombre d'ORFs: $num_ORFs"

    echo "ORFs: $ORFs"

fi

Salva el fitxer que s’ha creat escrivint: wq! analitza_fasta.sh

6) Per executar l’script, salva l’anterior fitxer amb l’extensió “.sh” i fes-lo executable amb l’ordre chmod +x. Executa’l amb el nom del fitxer FASTA a analitzar:

$ pwd
/home/student/fasta_sequence
 $ chmod +x analitza_fasta.sh
$ ./analitza_fasta.sh AC060780.18.fasta

7)Fins ara s’ha generat un protocol per analitzar fitxers FASTA, s’ha executat i comprovat que funciona. El següent pas és executar l’anterior fitxer d’anàlisi en un directori amb diferents seqüències. Per a això, es genera un altre protocol que inclogui l’anterior. El nou protocol es diu analitza_fasta_dir.sh. Els passos per seguir són:

$ pwd
/home/student
$ vi analitza_fasta_dir.sh

Les ordres que cal introduir en aquest fitxer són:

#! /bin/bash

echo "S’inicia l’execució amb el  PID $$";

echo "Nombre d’arguments a analitzar  $#";

echo "El nom del directori a analitzar  $1";

echo "Els noms dels fitxers que s’analitzen són";

ls $1;

echo "Execució del protocol d’anàlisi FASTA per a cadascun dels fitxers en el directori";

ls $1 |    while read file;

     do

          echo "execució analitza_fasta.sh $file";

          ./analitza_fasta.sh $1/$file;

     done

Salva el fitxer que s’ha creat escrivint :wq! analitza_fasta_dir.sh

8) Per executar l’script, salva l’anterior fitxer amb l’extensió .sh i fes-lo executable amb l’ordre chmod +x. Executa-ho amb el nom del directori que conté els fitxers FASTA a analitzar:

$ pwd
/home/student
$ cp fasta_sequence/analitza_fasta.sh .
$ chmod +x analitza_fasta_dir.sh
$ ./analitza_fasta_dir.sh fasta_sequence

Es pot observar que els protocols que s’executen es troben en el directori actual de treball (./) en lloc de només invocar el seu nom. No obstant això, un cop s’està segur que l’script funciona correctament, és més convenient guardar tota la nostra col·lecció de protocols en un sol directori del sistema. D’aquesta manera, no s’han de mantenir múltiples còpies i es podran executar des de qualsevol lloc en el nostre arbre de directoris.

Les plataformes Gnu/Linux tenen un conjunt de variables globals que contenen dades de caràcter general. Es resumeixen a la taula següent, la taula 16.

Taula 16. Ordres per a l’execució de scripts.

Ordre Descripció
set Estableix valors que seran usats pels programes, aplicació, scripts
echo Imprimeix el que se li encarrega que faci
printenv Llista la llista completa de variables d’entorn de la teva versió Gnu/Linux
which Localitza els arxius executables d’una determinada aplicació
export Crea/modifica una variable del sistema

Font: elaboració pròpia.

L’ordre set a Gnu/Linux mostra i estableix variables d’entorn per a la sessió actual. S’utilitza per veure el valor de les variables d’entorn del sistema i també per assignar valors a noves variables d’entorn. L’ordre echo, d’altra banda, s’utilitza per mostrar missatges de text o el valor de les variables a la pantalla. També es pot utilitzar per escriure text en arxius o per concatenar diversos missatges de text.

L’avantatge d’utilitzar echo és que permet seleccionar i mostrar només la informació que es necessita, el que fa que sigui més fàcil de llegir i entendre. D’altra banda, l’avantatge d’utilitzar set és que permet establir i modificar variables d’entorn, la qual cosa pot ser útil en automatitzar tasques i scripts a Gnu/Linux.

Obre un terminal de Gnu/Linux. Pots veure la llista completa de variables d’entorn de la teva versió de Gnu/Linux utilitzant l’ordre printenv. Pots tenir una llista més manejable afegint-hi diferents ordres:

$printenv | less

Cada línia conté el nom de la variable d’entorn Gnu/Linux seguit de = i del valor. Per exemple:

HOME=/home/student

Això vol dir que HOME és una variable d’entorn de Gnu/Linux que té el valor establert com a directori /home/student.

Les variables d’entorn solen estar en majúscules, tot i que també pots crear variables d’entorn en minúscules. La sortida de printenv mostra totes les variables d’entorn en majúscules. Una cosa important per tenir en compte és que les variables d’entorn de Gnu/Linux distingeixen entre majúscules i minúscules. Si desitges veure el valor d’una variable d’entorn específica, pots fer-ho considerant el nom d’aquesta variable com a argument de l’ordre printenv. La cadena de caràcters completa es veuria així en la línia d’ordre:

$ printenv HOME
/home/student
$ echo $USER
student

La sintaxi bàsica per crear una variable d’entorn a Gnu/Linux és la següent. És fàcil aconseguir-ho, només es necessita especificar un nom i un valor. Seguirem la convenció de mantenir totes les lletres en majúscules per al nom de la variable, i l’establirem com una cadena simple.

$ HIB_VAR='BioInformatica i BioEstadistica!'
$ export HIB_VAR
$ export HIB_VAR='BioInformatica i BioEstadistica!'    #en una única línia

S’han fet servir cometes simples, ja que el valor de la variable conté un espai. A més, s’han utilitzat cometes simples perquè el signe d’exclamació és un caràcter especial en la shell bash que normalment s’expandeix a l’historial de bash si no s’escapa o es col·loca entre cometes simples. Ara tenim una variable de la shell. Aquesta variable està disponible en la nostra sessió actual, però no es transmet als processos secundaris.

Es pot comprovar, buscant la nostra nova variable dins de la sortida de set:

$ set | grep HIB_VAR
HIB_VAR='BioInformartica i BioEstadistica!'

Si la variable s’ha definit correctament, podràs utilitzar-la en qualsevol protocol que executis en la mateixa sessió del terminal. Per exemple, si crees un arxiu de script en bash que requereix utilitzar la variable HIB_VAR, simplement pots referir-t’hi utilitzant el símbol $. Per exemple, si el teu arxiu de script s’anomena myscript.sh  i conté el següent codi:

#! /bin/bash

echo " El valor de HIB_VAR es: $HIB_VAR"

Si s’executa l’arxiu de script en la mateixa sessió del terminal utilitzant l’ordre bash,

$ chmod +x myscript.sh
$ bash myscript.sh
BioInformatica i Bioestadistica!

l’arxiu de script hauria d’imprimir el valor de la variable HIB_VAR que vas definir prèviament. Per revertir el valor d’una variable es pot fer servir l’ordre unset.

$ echo $HIB_VAR
BioInformartica i BioEstadistica!
$ unset HIB_VAR
$ echo $HIB_VAR

D’altra banda, tens en compte que, si tanques la sessió del terminal i la tornes a obrir, hauràs de tornar a definir la variable local utilitzant l’ordre export. Per evitar això, pots agregar la definició de la variable HIB_VAR al teu arxiu d’inici de bash (per exemple, ~/.bashrc), de manera que la variable estigui disponible cada vegada que iniciïs una nova sessió del terminal.

L’ordre which és una eina que permet trobar ràpidament els arxius executables d’una determinada aplicació i localitza els fitxers executables mitjançant la variable d’entorn PATH.

$ which nano docker gawk
/usr/bin/nano

/usr/bin/docker

/usr/bin/gawk

Finalment, es defineix la variable PATH. El contingut de la variable PATH és una cadena que conté paths de directoris separats per dos punts, i aquests són els directoris en què la shell busca l’ordre que l’usuari escriu des del teclat.

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:
/usr/games:/usr/local/games:/snap/bin

La recerca no es realitza en l’ordre en el qual estan els directoris en la variable PATH. Quan s’escriu una ordre a la shell buscarà primer a /usr/local/bin, després a /usr/bin, a continuació a /usr/games i finalment a /snap/bin. Des del moment en què la shell troba l’ordre, deté la recerca i executa l’ordre trobada. Podem escriure una ordre utilitzant:

  • El seu nom:
    El path absolut (/bin/cat /etc/passwd ).
    El path relatiu (utilitzant «.» o «….» en general per als programes o scripts que no es troben al PATH).
    Es pot afegir un directori a la variable PATH, afegim el directori on es troben tots els scripts que es generin.
  • Únicament per a la sessió activa:
    Si desitges afegir, per exemple: /home/student/HIB_scripts a la variable PATH, escriu a la shell el següent segons el cas.

# Per tenir el directori al final del PATH:

$ export PATH=$PATH:/home/student/HIB_scripts

# Per tenir el directori a l’inici del PATH:

$ export PATH=/home/student/HIB_scripts/:$PATH

Ara pots utilitzar el programa escrivint simplement el seu nom. En desconnectar-se, PATH reprendrà al seu valor per defecte, llavors /home/student/HIB_scripts no existirà més.

  • De manera permanent:
    Si desitges configurar PATH de forma permanent has d’editar l’arxiu de configuració de la seva shell de connexió. Com que en general la shell bash és el més utilitzat, has d’editar l’arxiu: /home/user/.bashrc. L’ordre llavors seria:

    $ echo 'export PATH=$PATH:/home/student/HIB_scripts' >> /home/user/.bashrc

    Després d’això, en cada connexió la variable PATH contindrà el directori /home/student HIB_scripts. Aquesta operació pot ser executada per l’usuari student, no es necessiten els permisos de root.