On se propose de re-implémenter la commande head (que nous avons précédemment lors des cours sur le language BASH). L'objectif est de créer un programme (sous sa forme la plus simple), capable de:
- Ouvrir un fichier tabulé.
- Parcourir le fichier ligne à ligne.
- Si le numéro de ligne est inférieur ou égal à 10.
- Imprimer la ligne.
A titre d'exemple, nous utiliserons un fichier gtf. Ce fichier qui contient les coordonnées des exons de 5000 transcrits dans le génome humain peut être téléchargé ici: hg38_5k.gtf
Le format GTF est un fichier tabulé (i.e. dont les colonnes sont séparées par des tabulations) qui contient des informations concernant des éléments génomiques (souvent des transcripts et leurs exons). Les informations portées par les colonnes sont les suivantes:
- Colonne 1 - Nom du chromosome.
- Colonne 2 - Source de l'annotation.
- Colonne 3 - Type d'élément (exon, CDS, 5'UTR, 3'UTR,...).
- Colonne 4 - Position de départ (Start).
- Colonne 5 - Position de fin (End).
- Colonne 6 - Score.
- Colonne 7 - Le brin (+ ou -).
- Colonne 8 - Frame (0,1,2). '0' indique que la première base de l'élément est la première base d'un codon, '1' que la deuxième base est la première base d'un codon, etc...
- Colonne 9 - Attribute. Une liste de couples clefs/valeurs séparées par un point virgule.
1 ensembl exon 182393 182746 . + . gene_id "ENSG00000279928"; transcript_id "ENST00000624431"; 1 ensembl exon 183114 183240 . + . gene_id "ENSG00000279928"; transcript_id "ENST00000624431"; 1 ensembl exon 183922 184158 . + . gene_id "ENSG00000279928"; transcript_id "ENST00000624431"; 1 ensembl exon 195263 195411 . - . gene_id "ENSG00000279457"; transcript_id "ENST00000623083"; 1 ensembl exon 925741 925800 . + . gene_id "ENSG00000187634"; transcript_id "ENST00000616016"; 1 ensembl exon 925741 925800 . + . gene_id "ENSG00000187634"; transcript_id "ENST00000618181"; 1 ensembl exon 925741 925800 . + . gene_id "ENSG00000187634"; transcript_id "ENST00000618323"; 1 ensembl exon 925741 925800 . + . gene_id "ENSG00000187634"; transcript_id "ENST00000620200"; 1 ensembl exon 925922 926013 . + . gene_id "ENSG00000187634"; transcript_id "ENST00000616016"; 1 ensembl exon 925922 926013 . + . gene_id "ENSG00000187634"; transcript_id "ENST00000618181"; 1 ensembl exon 925922 926013 . + . gene_id "ENSG00000187634"; transcript_id "ENST00000618323";
Cette solution fonctionne mais elle est longue puisque l'on parcourra l'ensemble du fichier en faisant un test sur chacune des lignes (on ne s'arrête pas à la dixième ligne).
# -*- coding: utf-8 -*-
# La ligne précédente permet d'utiliser des caractères accentués
# dans les commentaires
# Pensez à adapter le chemin vers le fichier.
# Ici, il est dans le dossier data présent dans le
# répertoire supérieur
file_handler = open("../data/hg38_5k.gtf", "r")
# On définit une variable line_number
# qui contiendra le numéro de la ligne courante
line_number = 0
# On utilise une boucle for pour
# lire des lignes renvoyées par l'objet
# file_handler
for line in file_handler:
# On incrémente la variable line_number
# On est maintenant à la ligne 'line_number'
line_number = line_number + 1
# On test si l'expression suivante (line_number <= 10)
# est vrai (i.e si elle est vérifiée).
if line_number <= 10:
# Si la condition est vrai on retire le caractère
# "\n" à droite. En effet, print produira lui même un
# caractère "\n".
line = line.rstrip("\n")
print(line)
Le temps d'execution est ici de **0.184 secondes**. Vous pouvez le tester sur votre machine en utilisant la ligne commande suivante dans le terminal:
Toujours avec une boucle for mais cette fois ci nous utilisons le module sys afin d'importer la fonction exit() permettant d'arrêter le programme si la condition n'est pas vérifiée.
# -*- coding: utf-8 -*-
# La ligne précédente permet d'utiliser des caractères accentués
# dans les commentaires
import sys # on importe le module sys
# Pensez à adapter le chemin vers le fichier.
# Ici, il est dans le dossier data présent dans le
# répertoire supérieur
file_handler = open("../data/hg38_5k.gtf", "r")
# On définit une variable line_number
# qui contiendra le numéro de la ligne courante
line_number = 0
# On utilise une boucle for pour
# lire des lignes renvoyées par l'objet
# file_handler
for line in file_handler:
# On incrémente la variable line_number
# On est maintenant à la ligne 'line_number'
line_number = line_number + 1
# On test si l'expression suivante (line_number <= 10)
# est vrai (i.e si elle est vérifiée).
if line_number <= 10:
# Si la condition est vrai on retire le caractère
# "\n" à droite. En effet, print produira lui même un
# caractère "\n".
line = line.rstrip("\n")
print(line)
else:
# Si on est au delà de la ligne 10
# on quitte le programme (on ne lit
# pas les lignes suivantes)
sys.exit()
Le temps d'exécution est ici de 0.022 secondes soit un gain de 0.162 secondes.
Toujours avec une boucle for mais cette fois ci nous utilisons le mot clef break permettant d'arrêter la boucle si la condition n'est pas vérifiée.
# -*- coding: utf-8 -*-
# La ligne précédente permet d'utiliser des caractères accentués
# dans les commentaires
# Pensez à adapter le chemin vers le fichier.
# Ici, il est dans le dossier data présent dans le
# répertoire supérieur
file_handler = open("../data/hg38_5k.gtf", "r")
# On définit une variable line_number
# qui contiendra le numéro de la ligne courante
line_number = 0
# On utilise une boucle for pour
# lire des lignes renvoyées par l'objet
# file_handler
for line in file_handler:
# On incrémente la variable line_number
# On est maintenant à la ligne 'line_number'
line_number = line_number + 1
# On test si l'expression suivante (line_number <= 10)
# est vrai (i.e si elle est vérifiée).
if line_number <= 10:
# Si la condition est vrai on retire le caractère
# "\n" à droite. En effet, print produira lui même un
# caractère "\n".
line = line.rstrip("\n")
print(line)
else:
# Si on est au delà de la ligne 10
# on quitte la boucle
break
On change de point de vue et on utilise une boucle while. Le principe est de dire:
- Tant que le numero de ligne est inférieur ou égal à 10
- Lit une ligne.
C'est un peu différent du point de vue de la syntaxe et plus élégant. A noter l'utilisation de la méthode readline() disponible pour les objets de type/classe file.
# -*- coding: utf-8 -*-
# La ligne précédente permet d'utiliser des caractères accentués
# dans les commentaires
# Pensez à adapter le chemin vers le fichier.
# Ici, il est dans le dossier data présent dans le
# répertoire supérieur
file_handler = open("../data/hg38_5k.gtf", "r")
# On définit une variable line_number
# qui contiendra le numéro de la ligne courante
line_number = 0
while line_number < 10:
# On lit une ligne du fichier avec
# la méthode readline()
line = file_handler.readline()
# On retire le caractère
# "\n" à droite. En effet, print produira lui même un
# caractère "\n".
line = line.rstrip("\n")
print(line)
# On ajoute 1 à line_number
# Sinon la condition 'line_number < 10'
# sera toujours vérifiée
line_number = line_number + 1
Le temps d'exécution est là aussi de **0.022 secondes.