Lecture de fichiers CCSV

Un fichier CCSV (CSV commenté) est défini comme un fichier de type CSV incluant des lignes de commentaires, ces lignes commencent par un caractère #. Elles peuvent être regroupées dans une entête de fichier (une ou plusieurs lignes) ou apparaitre en nombre et positions indéfinies dans la suite du fichier.  Le module ccsv est chargé de traiter ces fichiers CSV commentés et de fournir une interface pour exporter ces ilots de données sans commentaires (fichiers ou chaines de caractères) ou en tant  qu’objets, chaines de caractères, ou fichiers CSVM.

1. Détection d’un fichier CCSV

Dans un premier temps il faut être sur qu’il s’agisse d’un fichier CCSV, car d’autres types de fichiers incluent des lignes commençant par #. C’est en particulier le cas des fichiers CSVM qui peuvent inclure aussi des commentaires. Sauf qu’avec CSVM nous avons forcément des lignes commençant par #TITLE, #HEADER, #TYPE, #WIDTH et #META. Donc la reconnaissance est possible sur ces bases, la fonction ccsv_str_csvmcheck l’effectue, sont argument étant une chaine de caractères, en retour elle fournit deux valeurs (ccsv_hit, csvm_hit). Si csvm_hit est égal à 4 ou 5, nous avons la signature d’un fichier CSVM. Si ccsv_hit est égal à zéro, il s’agit d’un pur fichier CSV, si ccsv_hit > 0 il peut s’agir d’un fichier CCSV. Si c’est le cas (et non un fichier CSVM) il ne restera qu’à éliminer les lignes avec un # et à le traiter comme un fichier CSV.

Dans cette approche nous perdons les lignes correspondant aux remarques, ce n’est l’objectif. Par contre, il est possible de parser des fichiers CSVM en embarquant les remarques, un attribut REMARKS existe dans l’objet csvm_ptr, qui permet d’agréger ces lignes (ou une sélection) dans une chaine de caractères.

2. Interface CSV

La fonction ccsv_str2csvstr permet de traiter une chaine de caractères ccsv_str en détectant s’il s’agit d’une chaine de type CCSV, et de la transformer en chaine CSV avec modification éventuelle du séparateur (on fournit le séparateur existant et le séparateur cible). la fonction renvoie une chaine de caractères.

Cette fonction est utilisée par ccsv_2csvstr qui lit un fichier CCSV et le transforme en chaine de caractères, et la fonction ccsv_2csv qui transforme un fichier CCSV en fichier CSV.

Prenons le cas d’un fichier CCSV DockingResults.mvdresults qui est issu d’un processus de calcul (arrimage moléculaire) ou nous avons une entête incluant des clés/valeurs concernant des paramètres pour le calcul et des colonnes correspondant à des descripteurs (ex: énergie des liaison entre un ligand et une protéine). Chaque ligne correspond à une pose, c’est à dire à un résultat caractéristique de plusieurs calculs ou la conformation du ligand dans le site de liaison de la protéine est considérée comme similaire (faisant partie d’un même cluster en termes de position, d’orientation, de conformation, et de conséquemment de score).

Pour traiter ce fichier et le transformer en CSV, avec changement de séparateur, élimination de l’entête et sauvegarde sous un autre nom de fichier, l’appel à la fonction ccsv_2csv est simplifié :

Nous aurons le résultat suivant si nous affichons le contenu du nouveau fichier DockingResults.csv :

Nous avons 50 colonnes de plusieurs types string, int et float, mais qui sont traitées comme des chaines de caractères, la dernière colonne correspond à une structure moléculaire (celle du ligand) au format SMILES (OC1C([NH3+])CSC1CCCCCCCCCCCCCC). Ce qui correspond à un analogue soufré (bioisostère sans stéréochimie définie dans la formule SMILES) de la Jaspine B (Pachastrissamine). Celle ci est une molécule naturelle, issue d’éponges marines, cytotoxique et notamment utilisée dans la recherche d’anticancéreux.

Nous constatons que les titres des colonnes sont conservés car ils n’étaient pas commentés. Une optimisation de ce type de code pourrait être une reconnaissance de ces titres, puis de les marquer par une double quote. Mais dans la mesure ou il existe une interface CSVM, il vaut mieux passer par un objet CSVM puis l’exporter, en CSV ou dans un autre format de table comme une DataFrame (Pandas).

Liens et lectures
  • Jaspine B [ https://www.chemspider.com/Chemical-Structure.7990567.html ].
  • Bioisostère [ https://fr.wikipedia.org/wiki/Bioisost%C3%A8re ].
  • Santos & coll. Identification of Novel CERT Ligands as Potential Ceramide
    Trafficking Inhibitors (2014) ChemBioChem 15, 2522-2528 [ https://doi.org/10.1002/cbic.201402366 ].

3. Interface CSVM en mode string

La fonction ccsv_str2csvm_ptr permet d’initialiser un objet CSVM et de le remplir (table et métadonnées) avec les données d’une chaine de caractères au format CCSV. A condition que la première ligne corresponde au aux titres des colonnes (et sans doubles quotes). Il n’y a pas de vérifications à ce niveau, un filtre texte doit avoir fait le travail nécessaire avant cette opération.

Toujours à partir d’une chaine de caractères au format CCSV la fonction ccsv_str2csvmstr transforme celle ci en chaine CSVM, avec changement éventuel de caractère séparateur. La fonction ccsv_str2csvm_ptr précédente est utilisée intermédiairement avec export en CSVM via csvm_ptr_make_csvm du module parsers.csvm.

Enfin la fonction ccsv_str2csvm utilise ccsv_str2csvmstr puis sauve la chaine de caractères au format CSVM produite sous la forme d’un fichier CSVM dont le nom est fourni en tant qu’argument.

Les trois fonctions s’appellent d’une manière simple :

ccsv_str2csvm_ptr(ccsv_str, ccsv_sep, csvmtype='UNKN')
ccsv_str2csvmstr(ccsv_str, ccsv_sep, csvmtype='UNKN', csvm_sep="\t")
ccsv_str2csvm(ccsv_str, ccsv_sep, csvm_name, csvmtype='UNKN', csvm_sep="\t")

Avec des arguments comme ccsv_str (la chaine de caractères en entrée) et les séparateurs pour la chaine CCSV (ccsv_sep) ou CSVM (csvm_sep) ainsi que le nom du fichier CSVM en export (csvm_name). L’argument csvmtype définit une valeur par défaut (chaine de caractères au choix de l’utilisateur, ce n’est pas un type prédéfini) pour le type des colonnes de la table CSVM, à ce niveau il n’y a pas de type casting.

4. Interface CSVM en mode file

La fonction ccsv_2csvm_ptr lit un fichier CCSV dans une chaine, puis utilise ccsv_str2csvm_ptr pour renvoyer un objet csvm_ptr.  La fonction ccsv_2csvm utilise la précédente pour réaliser une conversion d’un fichier CCSV en fichier CSVM. Les deux s’appellent avec le même type d’arguments que les fonctions en mode string :

ccsv_2csvm_ptr(ccsv_name, ccsv_sep, csvmtype='UNKN')
ccsv_2csvm(ccsv_name, ccsv_sep, csvm_name, csvmtype='UNKN', csvm_sep="\t", meta=False)

Si l’argument meta=True, le nom du fichier CSVM (csvm_name) est enregistré (remplacement)  dans le champ #TITLE et le nom du fichier CCSV initial (ccsv_name) est enregistré (remplacement) dans le champ #META.

Test drive et non-typage des données

Si nous reprenons le fichier CCSV DockingResults.mvdresults, la conversion en fichier CSVM s’effectue avec un minimum de code :

L’objet csvm_ptr intermédiaire est conforme, nous avons bien parsé un fichier CCSV :

Nous constatons que toutes les colonnes ont été identifiées, et qu’elles sont incluses dans les métadonnées CSVM, sans reconnaissance et typage des données.

Lorsque la structure csvm_ptr est initialisée et remplie, toutes les cellules de la table sont de type string. On peut mettre à jour toutes les colonnes avec le #TYPE positionné sur ‘TEXT‘ ou l’injecter via l’argument csvmtype. Dans cet exemple nous avons utilisé un type ‘UKN‘ pour l’ensemble des colonnes. Mais nous pourrions mettre n’importe quelle chaine de caractères dans l’argument csvmtype des fonctions ccsv_2csvm_ptr et ccsv_2csvm, cela resterait valide au sens du paradigme CSVM.

Ce non typage correspond à un des principes liés à l’approche CSVM : c’est le programme utilisateur qui doit fixer les types, car il est sensé connaître le titre de chaque colonne, donc le type de données afférent.

En fonction de ses connaissances et de l’entête des colonnes, le programme d’exploitation peut (éventuellement) renommer les champs #HEADER (titres de colonnes) et convertir (éventuellement) les cellules en un type Python (ex: int, float, string …) standard. Dans ce cas, il faut s’assurer que les champs #TYPE correspondent pour chaque colonne. Dans l’optique CSVM il n’y a pas de norme, chacun décide du type adéquat. Par exemple pour une colonne int ou float, j’utilise souvent le terme NUMERIC, pour une colonne string, j’utilise TEXT. Chacun fait ce qu’il veut et peut inventer un #TYPE à sa convenance.
Et ces règles peuvent être externalisées, les dictionnaires CSVM offrent un mécanisme qui permet de définir des termes #NAME alternatifs (on peut changer le nom de colonne), associés à des valeurs #TYPE et #WIDTH (ex: pour les SGBDRs) correspondant à la donnée ou grandeur (la colonne) d’intérêt, et d’autres choses encore …

Au final le fichier CSVM résultant, sans interprétation sera de la forme :

Liens et lectures

5. Conclusion

J’utilise peu ce module directement, c’est une collection de primitives. En général c’est mieux de programmer des fonctions d’interfaces, dédiées à un paquetage donné, qui combine le parseur (sans interprétation) et une couche d’interprétation pour aboutir à une table CSVM typée et filtrée. Par exemple on peut renommer les colonnes si le titre est trop long, on peut en supprimer, on peut en ajouter si on calcule de nouvelles grandeurs à partir des données de la table. Puis l’objet ou le fichier CSVM nous servira de fichier/format pivot pour la suite des opérations ou d’autres applications.

Retour en haut