Si nous disposons d’une collection moléculaire, implémentée au format CSVM, nous pouvons utiliser un convertisseur CSVM2SDF pour transformer cette CSVM en liste de molécules au format SDF. Il s’agit d’un code de démonstration, mais pleinement fonctionnel pour de nombreuses applications, car il est conçu pour être générique. Un des avantages de CSVM est d’être un format pivot capable d’embarquer d’autres formats ou objets. S’ils sont en made texte c’est plus facile, dans le cas de CSVM2SDF nous pouvons prendre en compte des molécules au format SMILES (le cas le plus fréquent) mais aussi MDL Mol (ou moyen d’une petite astuce) dans le fichier CSVM.
Ce code est basé sur les paquetages buildez.chem.pybel_interface, buildez.parsers (CSVM) et buildez.wrappers. Pour le coté chimie, nous utilisons donc la bibliothèque Python Openbabel/Pybel basée sur OpenBabel [O’Boyle_2011].
Le programme est utilisable au travers d’une interface scriptée, nous montrerons un exemple dans le cas d’un OS Windows. Le programme utilise des oplists avec quelques options qui permettent de contrôler son exécution. La ‘traduction’ en Linux/Cygwin est immédiate, car ce mécanisme de passage d’arguments complexes (parfois multichoix) est conçu pour être indépendant de l’OS.
Par définition, une table moléculaire au format SDF n’inclue qu’une seule colonne de molécules, par exemple une colonne Structure et des attributs/descripteurs dans les autres colonnes. Par contre, une table CSVM peut tout à fait embarquer des molécules dans plusieurs colonnes. Il y a plusieurs cas de figures ou nous avons besoin de cette fonctionnalité, et c’est pour cela qu’elle a été développée jusqu’à un nombre indéfinie de colonnes pour les molécules. Mais il y a une limite, dans une conversion vers SDF, il n’y aura qu’une colonnes moléculaire possible. Les autres devront être encodées en SMILES, ou nous devrons fusionner les colonnes. C’est ce que fait le convertisseur (wrapper) : il va simplement en sélectionner une ou deux, par exemple une molécule et son sel, puis les fusionner et les encoder en tant que colonne moléculaire unique dans le fichier SDF.
Publication initiale sur buildblog.buidez.net (2021) – Article mis à jour en Mars 2025.
1. Les arguments et les oplists
L’appel et le passage d’arguments des modules du paquetage buildez.wrappers est toujours basés sur la même syntaxe et le même mécanisme (que j’appelle oplists). Dans le cas de CSVM2SDF, nous avons :
|
1 |
python csvm2sdf.py -i csvm_file -o sdf_file [oplists] [options] |
Arguments
Nous retrouvons les arguments classiques d’une ligne de commande, il s’agit des options signalées par une syntaxe de type -flag valeur et qui permettent de contrôler les flux :
|
1 2 3 4 5 6 7 |
-i file CSVM file with embbeded molecules (SMI or MDL Mol strings). -o file SDF file, if CLEAN a _clean2d/_clean3d SDF will be produced. -v Verbose mode. -l logfile Logfile generation (CGI). -ref referer Add referer variable to logs (CGI). -u user Add user variable to logs (CGI). -h Displays this help. |
Nous pouvons donc entrer le fichier CSVM et le fichier SDF à produire, en utilisant un mode verbeux ou non pour suivre le déroulement des opérations (via un objet buildez.msg.msg_ptr).
Oplists
Les oplists permettent de piloter l’exécution et sont signalées par une syntaxe -op { clé string(s) } entre accolades. Au niveau des fonctions basiques, nous constatons que nous pouvons spécifier les caractères séparateurs du CSVM, les identifiants pour les cellules vides du CSVM et de la table SDF.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ CSVM_SEP 'TAB' } The character used as a separator in CSVM file. { CSVM_BLANK '-' } Blank char used in CSVM file. { SDF_BLANK 'n.d.' } Blank char used in SDF file. { CONVERT BLANKS 'True' } Replace characters/strings for empty cells. { BLANK_REPLACE 'True' } Replace character/string for empty cells. { CSVM_DUMP 'False' } Dump the csvm_ptr structure during conversion. { CLEAN 'yes' } Add a cleaned (2d or 3d) SDF file (yes|no). { CMODE '2D' } Clean mode (2D, 3D0, 3D1). { STRUCTURE 'Structure' } Label of CSVM column for molecules. { STRUCTURE2 'Salts' } Label of CSVM column for additional molecules. { ADD_MOLS 'False' } Add STRUCTURE2 in STRUCTURE if STYPE='SMI'. { COLDEL 'False' } Optional deletion of STRUCTURE2 column. { SDF_CORRECTOR 'False' } SDF corrector (signature based). |
L’oplist CLEAN permet de faire une optimisation géométrique (utile si les molécules sont codées en SMILES) des formules chimiques, soit en 2D soit en 3D avec un mode d’optimisation (3D0 à 3D1) plus ou moins poussé. Il est possible de choisir la colonne qui va encoder les structures pour le fichier SDF (oplist STRUCTURE) et de la fusionner avec une autre colonne (oplist STRUCTURE2) avec conservation ou non.
Nous constatons également que les options par défaut (valeurs entre simple quotes dans les oplists) sont similaires à celles adoptées dans les articles du blog (par exemple nom de la colonne utilisée pour stocker les structures de molécules, format SMILES, caractère séparateur, etc). Il s’agit d’un écosystème cohérent, il reste à voir si le CSVM généré à partir de la collection de produits chimiques nous génère un fichier SDF valide.
Oplist et accolades
La chaine de caractères après les mots clés (en majuscules) peut correspondre à plusieurs types de valeurs: unique, liste de valeurs, opérateur opérande valeur … à partir du moment ou on sait gérer dans cet espace d’arguments (les accolades) des mots, nous pouvons en faire ce que l’on veut, y compris de la microprogrammation
2. Environnement de fonctionnement
Le code se lance à l’intérieur d’un script, basiquement il faudra qu’un environnement Python 3.x soit correctement installé. Une série d’articles correspondant à cette question est disponible [ Installation de Python sous Win-x64 ]. Sous Windows, l’environnement de travail prod doit être initialisé par un script de type setvars.bat de manière à fixer les variables d’environnement associées à Openbabel.
3. Utilisation basique du script
Pour utiliser CSVM2SDF il suffit donc, sous MS Windows, d’éditer un script (par exemple csvm2sdf.bat également inclus dans buildez.wrappers) de la forme suivante:
|
1 2 3 |
set PDIR=test set RNAME=plaque-p04a python csvm2sdf.py -i %PDIR%\%RNAME%.csvm -o %PDIR%\%RNAME%.sdf -op { STRUCTURE 'Structure' } -op { CSVM_DUMP 'False' } -v |
Il s’agit d’une utilisation de base: la transformation d’un fichier CSVM en SDF, avec utilisation de la colonne dont le nom est Structure et qui contient les formules développées des produits. Si l’oplist CSVM_DUMP était positionnée à True, nous aurions pu afficher (dump) la structure CSVM en mémoire pendant le traitement, ce qui nous aurait donné une sortie du type :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
id=csvm2sdf.py ver=(v:1.07) date=october/06/2016 begin=14:10:21 user=() referer=() clean=True structure=Structure stype=SMI csvm_dump=True csvm_blank=- convert_blanks=True blank_replace=True sdf_blank=n.d. csvm_sep=(TAB) src=test\plaque-p04a.csvm dest=test\plaque-p04a.sdf cmode=2D cleanc=test\plaque-p04a_clean2d.sdf Checks: files {True} environment {True} Checks: files {True} environment {True} DUMP: CSVM info { SOURCE test\plaque-p04a.csvm CSV CSVM META [[possibilite produits photosensibles dans plaque]] TITLE_N 1 TITLE - HEADER_N 8 TYPE_N 8 WIDTH_N 8 0 50 SMI {Structure} 1 10 NUMERIC {No} 2 10 TEXT {CID} 3 10 TEXT {Confidence} 4 10 TEXT {Duplicates} 5 10 TEXT {Local-ID} 6 10 NUMERIC {Stock} 7 SMI SMI {Sel} DATA_R 96 DATA_C 8 96 8 0 [C(N1CCC(=C1)C1=CC=CC=C1)C1=CC=CC=C1][01][A1][False N][n.d.][NG7 7,157][2][n.d.] 1 [OC(=O)C1=CC=C(C=C1)N=[N+]=[N-]][02][A2][True][n.d.][CCI-26][5][n.d.] 2 [O=C(OCC1=CC=CC=C1)C1=CC2=CC=CC=C2C=C1OCC1=CC=CC=C1][03][A3][False Bn, COOBn, Obn ?][n.d.][n.d.][3][n.d.] … 93 [CC1(C)CC(=O)C2=C(C1)OC1=C(C2C2=CC=CC=C2)C(=O)CC(C)(C)C1][94][L6][True][n.d.][n.d.][5][n.d.] 94 [COC(=O)N1CC(=O)C=CC1=O][95][L7][True][n.d.][n.d.][5][n.d.] 95 [CC1(C)CCC2=C(C1)OC1=C(CCC(C)(C)C1)C2C1=CC=C(C=C1)C1C2=C(CC(C)(C)CC2)OC2=C1CCC(C)(C)C2][96][L8][True][n.d.][n.d.][4][n.d.] } done 2Dconverter=pybel end=14:10:42 ============================== *** Open Babel Warning in OpenBabel::MDLFormat::WriteMolecule No 2D or 3D coordinates exist. Stereochemical information will be stored using an Open Babel extension. To generate 2D or 3D coordinates instead use --gen2D or --gen3D. Appuyez sur une touche pour continuer... |
Pour simplifier, ne sont affichés (…) que les 3 premiers et 3 derniers enregistrements (lignes) CSVM. Nous constatons une alerte openbabel/pybel qui s’expliquera plus loin.
4. Des fichiers SDF sans molécules ?
Dans la table de molécules (CSVM) il existe des lignes qui n’incluent pas encore de formules développées, par exemple, la molécule d’index 05, il faut regarder à la seconde colonne :
|
1 |
[*][05][A5][n.d.][n.d.][CM110-3(2)][3][n.d.] |
Ces molécules particulières sont identifiées par la chaine ‘*‘ qui signifie: n’importe quel type d’atomes. Le fichier SDF généré apparaît de la minière suivante avec ChemAxon MarvinView (image de gauche). Nous constatons qu’il est possible de générer, sans crash, des fichiers SDF sans formules développées, puisque nos étoiles apparaissent dans la sortie molecule matrix de Marvin. Les molécules ‘*’ apparaissent également en mode tableur (image de droite).
![]() |
![]() |
| Mode molecule matrix | Mode table |
Il est possible d’éditer le fichier SDF (formules développées, valeurs des cellules) mais nous ne pouvons pas ajouter des lignes ou des colonnes. Pour ce type de raisons, la source de données primaires ou le master doivent être réalisées d’une autre manière, CSVM, Excel & JChem …
5. Des lignes multimoléculaires
Nous notons également que dans le fichier CSVM des lignes incluent une autre structure au format SMILES, par exemple une première colonne Structure et dernière colonne Sels :
|
1 |
O=C(C(=O)C1=CC=CC=C1)C1=CN(CC2=CC=CC=C2)N=N1 21 C5 True - mix red 0,25 1 [BH4-].[Na+] |
Donc oui, c’est possible d’avoir des tables moléculaires ou plusieurs colonnes de molécules coexistent. La dernière colonne est utilisée ici pour stocker les sels, dans le cas de la molécule numéro 21 (index), il s’agit de NaBH4, soit la chaîne [BH4-].[Na+] au format SMILES. Le wrapper inclue une oplist pour générer automatiquement les molécules + sels (ou molécules additionnelles) par la fusion des colonnes Structure et Sel. L’exemple suivant, montre un code d’appel du wrapper dans un script pour réaliser ce type de travail :
|
1 2 3 4 5 |
:CNTEST set PDIR=test set RNAME=plaque-p04a python csvm2sdf.py -i %PDIR%\%RNAME%.csvm -o %PDIR%\%RNAME%.sdf -op { STRUCTURE 'Structure' } -op { STRUCTURE2 'Sel' } -op { ADD_MOLS 'True' } -op { COLDEL 'True' } -op { CLEAN 'yes' } -op { SDF_CORRECTOR 'True' } -op { CSVM_DUMP 'True' } -v goto END |
Nous utilisons l’oplist ADD_MOLS (= True) qui permet d’ajouter les molécules de la colonne définie par l’oplist STRUCTURE2 (= ‘Sel’) à celles de la colonne définie par l’oplist STRUCTURE (= ‘Structure’). Après cette opération, la colonne STRUCTURE2 est supprimée de la table par l’oplist COLDEL (= ‘True’).
Si nous voulions supprimer une colonne indéfinie, il vaudrait mieux passer, par un wrapper de type CSVM2CSVM qui est orienté table et qui inclue des oplists spécialisées pour le travail sur les colonnes. Par exemple, dans le contexte CSVM2CSVM l’oplist COLDEL sera capable de supprimer une série de colonnes en utilisant leurs noms dans une énumération, par exemple
{ COLDEL 'col0 col1' }.
Enfin, les structures à inclure dans le fichier SDF sont optimisées en 2D (depiction). Un correcteur SDF est également utilisé, cette fonction recense tous les problèmes constatés dans ce type de conversion et les corrige. Par exemple des blocs MDL pour les ions ‘ Na 0 3 0 0 0 15 0 ‘ qui devraient s’écrire plutôt ‘ Na 0 3 0 0 0 0 0 ‘ pour des raisons de compatibilité en aval.
6. Conclusion
Nous avons eu un panorama des fonctions du convertisseur CSVM2SDF qui est un middleware construit sur un parseur CSVM associé à un translateur SDF. Le code exploite l’objet csvm_ptr en mémoire pour générer une liste de molécules et leurs attributs/descripteurs. Le mécanisme d’arguments (oplist) avancé permet d’utiliser le programme sans perte de fonctionnalités et d’une manière simple dans un script de conversion.
A partir du format pivot CSVM, ce middleware intègre des fonctions qui complètent celles de CSVM2CSVM pour la manipulation des tables en amont. La combinaison CSVM2CSVM + CSVM2SDF est simple à utiliser et très pratique pour générer, d’une manière générique et indépendante (OS, serveurs, SGBDR …) le flux SDF à destination d’un utilisateur final. Si les conversions sont plus spécifiques nous pouvons utiliser les outils présents dans les modules buildez.chem.pybel_interface (pour la chimie, qui inclue également une interface CSVM) et buildez.parsers pour les tables.
Liens et lectures
- Parsing [ https://en.wikipedia.org/wiki/Parsing ].
- Wrapper (data mining) [ https://en.wikipedia.org/wiki/Wrapper_(data_mining) ].
- Middleware [ Middleware ].
- Open Babel – the chemistry toolbox [ https://openbabel.org/ ].
- OpenBabel [ https://en.wikipedia.org/wiki/Open_Babel ].

