buildez.pdb : matrice uniq et requêtes en aveugle

Le module residue contient une collection de fonction qui permettent les extractions/sélections des résidus (acides aminés, ligands) que l’on peut trouver dans une structure PDB. Des structures de données telles que resmap et reslist sont associées à ces fonctions, en combinaison avec une pdbm ou des dictionnaires. Ces fonctions permettent à la fois 1) de disposer de résultats synthétiques utilisables dans des calculs ultérieurs et 2) d’alléger les calculs intermédiaires.

Mais le module residue.py contient également une autre structures de données: la matrice uniq. Cette matrice est produite à partir d’une matrice pdbm et agrège toutes les informations qui sont identiques en informations uniques. Par exemple, toutes les lignes atomiques d’une matrice pdbm qui correspondent à un même résidu vont être agrégées en une seule ligne.
Nous allons voir dans cet article quelques propriétés de ces matrices uniq qui permettent de les utiliser en tant que masque pour des recherches évoluées, et une application qui montre comment les utiliser pour décomposer une structure moléculaire sans connaitre les composants (par exemple noms de résidus pour le ligand ou plus simplement s’il y a un ligand) qui la constituent. Ce type de recherche ‘en aveugle’ correspond à une brique de base pour des outils d’extraction robustes et automatisés d’informations dans les fichiers PDB avec des applications multiples.

D’après un article publié en 2012 sur buildez.net – Revu en Avril 2025.

Navigation dans le guide

Guide [ Composants : buildez.pdb ]




1. Génération d’une matrice uniq

De manière à pouvoir faire des comparaisons, nous allons utiliser la même structure que dans l’article qui présente la resmap, c’est à dire la structure 1OGS [Dvir_2003] et en particulier sa composante (protéine et hétéro-atomes) correspondant à la chaîne A. On considère donc que la matrice pdbm m0 et la resmap r0 correspondant à cette structure ont déjà été calculées:

La longueur de r0 est de 952, on a donc ce nombre total de résidus dans la structure qui se décompose en 444 molécules d’eau, 10 molécules de SO4, 1 molécule de NDG, 497 résidus (acides aminés) dans la chaîne polypeptidique A. Maintenant nous allons calculer une matrice uniq u0 en utilisant la matrice pdbm m0 avec la fonction pdb_pdbm2uniq. On utilise comme masque les colonnes 4, 5 et 6 de la matrice pdbm, ce qui correspond aux noms de résidus, à l’identificateur de chaîne (‘A’, ‘B’, ‘W’ …) aux numéros de résidus:

Ce qui va donner le résultat suivant:

Nous constatons donc que l’on renvoie une matrice pdbm dans laquelle les colonnes qui ne correspondaient pas au masque ont été conservées mais vidées, et que seules les lignes de coordonnées moléculaires ont été conservées.

Cette matrice ne contient qu’une occurrence pour chaque ligne, en fonction de ce qui a été défini dans le masque. Par exemple, les lignes atomiques correspondant au premier résidu de la matrice pdbm ont toutes trois points en commun: le résidu est ‘ALA’, le numéro de séquence est 1 et la chaîne est ‘A’. Ce sont précisément les colonnes qui ont été choisies dans le masque, et donc toutes les lignes correspondantes ont été regroupées en ALA-'A'-1 dans la première ligne de la matrice uniq résultante.

On pourrait ce dire qu’il s’agit d’un autre moyen de réaliser une resmap puisque dans ce cas précis nous produisons une liste de résidu (la longueur=952 de la matrice u0 est égale à celle de la resmap r0). En fait la matrice uniq va plus loin, car on sélectionne les colonnes que l’on veut, ce qui ouvre quelques possibilités intéressantes si ce concept simple est poussé jusqu’au bout.

2. Cadre de recherche

L’intérêt de ce type de matrice (d’où le nom) est qu’elle certifie que chaque ligne ne contient qu’un résultat unique. Par exemple deux résidus de même nom, dans la même chaine, mais avec des numéros de séquences différent vont être discriminés, même s’ils sont contigus dans la matrice pdbm.

Une matrice uniq peut également être utilisée en tant que masque de recherche, prenons l’exemple suivant :

Nous allons utiliser la fonction pdb_pdbm2block (qui fait partie du même module pdb.residue) pour faire une recherche dans la matrice pdbm m0 précédente. Cette fonction utilise la matrice pdbm, la matrice uniq, un numéro d’indice dans la matrice uniq et un masque. L’indice (troisième argument) étant positionné à zéro, on sélectionne en fait la première ligne de u0, qui correspond aux données ALA-A-1. On garde un masque (par exemple [4,6] ou [4,5,6]) compatible avec la recherche, et le résultat devient:

La nouvelle matrice pdbm produite par la fonction pdb_pdbm2block (ligne 7) ne contient en fait que les atomes correspondant à des résidus ALA. On peut le vérifier en calculant la resmap correspondante (ligne 11) :

printing the new resmap r2
['ALA', 1, 4, 8, -1, '']
['ALA', 20, 143, 147, -1, '']
['ALA', 33, 245, 249, -1, '']
...
['ALA', 448, 3544, 3548, -1, '']
['ALA', 456, 3600, 3604, -1, '']
['ALA', 476, 3750, 3754, -1, '']

Pour alléger la présentation des résidus intermédiaires (…) ont été masqués. On obtient au passage le nombre de résidus ALA présents dans la chaîne (longueur de la resmap r2). Sachant que l’on dispose d’une resmap valide on peut générer une chaîne de caractères compatible en termes de données (numéros d’atomes  …) avec le fichier PDB original:

Ce qui donne pour les deux premiers résidus ALA de la structure:

=> regenerating original protein string for two first ALA residues.
ATOM 1 N ALA A 1 24.859 73.199 -4.325 1.00 42.99
ATOM 2 CA ALA A 1 24.462 74.606 -4.600 1.00 40.12
ATOM 3 C ALA A 1 23.740 74.728 -5.939 1.00 39.15
ATOM 4 O ALA A 1 23.516 75.835 -6.430 1.00 40.24
ATOM 5 CB ALA A 1 25.691 75.499 -4.595 1.00 40.93
ATOM 140 N ALA A 20 25.970 65.080 -18.095 1.00 27.39
ATOM 141 CA ALA A 20 27.414 65.108 -17.869 1.00 28.79
ATOM 142 C ALA A 20 27.961 66.358 -17.164 1.00 28.49
ATOM 143 O ALA A 20 28.995 66.292 -16.487 1.00 27.51
ATOM 144 CB ALA A 20 28.146 64.915 -19.211 1.00 29.30

On dispose donc d’un outil qui permet en quelques lignes de réaliser automatiquement des extractions de blocs de coordonnées, sans modification des données initiales et de manière très robuste, à partir d’une structure PDB.

3. Recherche en aveugle

Qui dit extraction automatique dit recherche en aveugle. Il est simple d’utiliser une fonction de filtrage en mode texte (type GREP) quand on sait ce que l’on veut chercher, par exemple un grep 'SO4' sur la structure sortira tous les ions sulfates. Mais si nous définissons une requête du type: ‘sortir tous les hétéro atomes qui ne sont pas de l’eau, sans connaitre ces molécules et en les discriminant (individualisation) pour produire une liste’ ? Dans ce cas, la stratégie va devenir beaucoup plus compliquée, même avec des expressions régulières.

Alors que avec des outils tels que les matrices pdbm, resmap, uniq cela devient au contraire très simple et ceci sans avoir la moindre connaissance des éléments qui composent la structure et sans nécessité de réaliser des identifications de résidus (types de résidus basés sur le nom de résidu).

Une matrice uniq + une requête

La première étape va être de générer une matrice uniq qui servira de cadre de recherche dans la structure PDB:

Nous générons donc une matrice uniq u3 avec un masque correspondant à la clef ATOM ou HETATM (colonne 0) et au nom de résidu (colonne 4). En fait cette matrice u3 contient tout les résidus, marqués ‘ATOM’ ou ‘HETATM’. Par exemple pour la première et la dernière ligne de u3:

Nous utilisons cette matrice pour identifier les HETATM qui ne correspondent pas à de l’eau en utilisant un compteur dans la boucle, ce qui va donner:

=> derivating hetero residues list and a simplified uniq matrix
hetlist = ['SO4', 'NDG']
new uniq matrix (hetuniq) = [['HETATM', '', '', '', 'SO4', '', '', '', '', '', '', '', '', '', '', '', ''], ['HETATM', '', '', '', 'NDG', '', '', '', '', '', '', '', '', '', '', '', '']]

Nous venons de préparer une matrice uniq de nom hetuniq, sans rien connaitre de la structure qui va nous servir à générer les coordonnées moléculaires correspondantes des résidus SO4, NDG et de les compter/extraire à la demande.

Génération des coordonnées du premier ligand

Le code suivant va exposer la première ligne de hetuniq, donc le premier type (globalement) d’hétéro-résidu qui ne soit pas de l’eau:

Ce qui va donner comme résultat:

La matrice hetuniq est utilisée pour générer la matrice pdbm m5 correspondant aux résidus SO4, puis une resmap r5 et des chaines PDB compatibles avec le fichier original pour deux cas de figures: un résidu unique (le premier SO4) ou un groupe de résidu (les 2 premiers en utilisant une liste de résidus et la fonction pdb_reslist2pdbm du module residue).

A aucun moment il n’y a eu d’hypothèse sur la composition de la structure et pourtant on extrait à peu près ce que l’on veut et qui peut servir dans une analyse structurale.

Coordonnées du ligand suivant

Nous pouvons appliquer le même type de stratégie pour la seconde ligne de la matrice hetuniq:

Dans ce cas on va avoir la reslist r5 produite qui n’aura qu’un élément (le résidu NDG), on peut alors utiliser directement la fonction pdb_resmap2pdbm (du module residue) pour générer le bloc de coordonnées moléculaires correspondant car on n’a pas besoin d’utiliser une liste de résidus (il n’y en a qu’un).
Le résultat du code précédent va être:

Il s’agit ici de deux cas d’applications d’une matrice uniq à des fins d’exploitation de contenu d’un fichier PDB, sans en connaitre ses différentes composantes.

Mais ce n’est pas fini

Nous pouvons encore imaginer des situations ou cette approche n’est pas encore assez robuste. Par exemple, il arrive que des ligands soient composés d’acides aminés, par exemple des polypeptides inhibiteurs ou effecteurs qui ont été co-cristallisés avec une protéine. Ces ligands sont identifiés par des blocs ATOM et non HETATM. Dans ce cas il faut réaliser en plus, une reconnaissance de chaîne polypeptidique. Nous notons aussi que nous n’avons pas encore de résolution du bloc de connexion pour chaque ligand.

En fait toutes ces fonction sont implémentées dans une séquence d’opérations qui définit le parseur qui décompose la protéine en briques dédiées à des opérations données. Par exemple un split et un regroupement de molécules qui correspondent à une même chaine (mais sans utiliser les informations du fichier PDB qui peuvent être absentes ou problématiques).

4. Référentiel

Fonctions du module residue.py en relation avec la matrice  uniq, en mode abrégé (avril 2025).
Consulter l’article [ buildez.pdb: la matrice resmap ] pour les autres fonctions du module.

Fonction Utilisation
pdb_pdbm2uniq Calcule une matrice uniq au format pdbm, qui ne contient que les lignes qui sont similaires pour un jeu de colonnes de la pdbm.
pdb_pdbm2block Utilise une ligne (row) d’une matrice uniq pour extraire des blocs d’une matrice pdbm.
pdb_reslist2pdbm A partir d’une pdbm (source), d’une resmap et d’une reslist (filtres), produit une nouvelle pdbm.

5. Conclusion

Le concept de matrice uniq est bien intéressant dans des cas ‘désespérés’ et cet outil s’ajoute à l’ensemble des fonctions du module pdb.residue. Le dernier exemple montre qu’il est très facile de réaliser des extractions en aveugle, tout en restant proche des données manipulées par un chimiste médicinal. Une matrice, une boucle, deux compteurs, on ne peut pas dire que l’on fasse appel à des concepts de programmation objet très avancés. C’est également l’intérêt de ce type de stratégie, qui fournit des outils robustes (quasiment orientés script) et simples à utiliser pour ‘travailler’ les structures de macromolécules.

Liens et lectures
Retour en haut