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:
|
1 2 3 4 5 |
print("loading string for [1ogs-a.pdb] structure") s = pdb_file2str('test/1ogs-a.pdb') print("computing pdbm matrix m0 and resmap r0") m0 = pdb_str2pdbm(s) r0 = pdb_pdbm2resmap(m0) |
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:
|
1 2 3 4 5 6 7 8 9 10 |
print("*** Test uniq matrix implementation") print("given a pdbm matrix (first 5 rows) of length %d" % (len(m0))) print(m0[0:5]) print("=> compute u0 the uniq matrix, using mask=[4,5,6], of m0 (pdbm matrix)") u0 = pdb_pdbm2uniq(m0, [4,5,6], '-') print("found %d occurences" % (len(u0))) print("printing first 5 rows of u0") print(u0[0:4]) print("printing last 5 rows of u0") print(u0[len(u0)-6:(len(u0)-1)]) |
Ce qui va donner le résultat suivant:
|
1 2 3 4 5 6 7 8 9 |
*** Test uniq matrix implementation given a pdbm matrix (first 5 rows) of length 4444 [['-', 1], ['-', 2], ['-', 3], ['ATOM', 1, 'N', '', 'ALA', 'A', 1, '', 24.859, 73.199, -4.325, 1.0, 42.99, '', '', '', 4], ['ATOM', 2, 'CA', '', 'ALA', 'A', 1, '', 24.462, 74.606, -4.6, 1.0, 40.12, '', '', '', 5]] => compute u0 the uniq matrix, using mask=[4,5,6], of m0 (pdbm matrix) found 952 occurences printing first 5 rows of u0 [['', '', '', '', 'ALA', 'A', 1, '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', 'ARG', 'A', 2, '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', 'PRO', 'A', 3, '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', 'CYS', 'A', 4, '', '', '', '', '', '', '', '', '', '']] printing last 5 rows of u0 [['', '', '', '', 'HOH', 'W', 930, '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', 'HOH', 'W', 931, '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', 'HOH', 'W', 932, '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', 'HOH', 'W', 936, '', '', '', '', '', '', '', '', '', ''], ['', '', '', '', 'HOH', 'W', 938, '', '', '', '', '', '', '', '', '', '']] |
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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
print("*** Test multiple residue extraction using a resmap, uniq, pdbm matrixes") print("extract a block using u0 and m0 : u0[0] is an ALA residue") print("select mask=[4,6] outputs all rows of m0 with same occurences") print("in columns 4 (resname) and 6 (resseq) => all 'ALA' of protein and") print("stores them in a new pdbm matrix m1.") print("=> computing m1 and the corresponding resmap") m1 = pdb_pdbm2block(m0, u0, 0, [4,5,6]) print("print first 10 rows of m1") for i in range (0, 10, 1): print(m1[i]) r2 = pdb_pdbm2resmap(m1) print("printing the new resmap r2") for i in range (0, len(r2), 1): print(r2[i]) |
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:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
*** Test multiple residue extraction using a resmap, uniq, pdbm matrixes extract a block using u0 and m0 : u0[0] is an ALA residue select mask=[4,6] outputs all rows of m0 with same occurences in columns 4 (resname) and 6 (resseq) => all 'ALA' of protein and stores them in a new pdbm matrix m1. => computing m1 and the corresponding resmap print first 10 rows of m1 ['ATOM', 1, 'N', '', 'ALA', 'A', 1, '', 24.859, 73.199, -4.325, 1.0, 42.99, '', '', '', 4] ['ATOM', 2, 'CA', '', 'ALA', 'A', 1, '', 24.462, 74.606, -4.6, 1.0, 40.12, '', '', '', 5] ['ATOM', 3, 'C', '', 'ALA', 'A', 1, '', 23.74, 74.728, -5.939, 1.0, 39.15, '', '', '', 6] ['ATOM', 4, 'O', '', 'ALA', 'A', 1, '', 23.516, 75.835, -6.43, 1.0, 40.24, '', '', '', 7] ['ATOM', 5, 'CB', '', 'ALA', 'A', 1, '', 25.691, 75.499, -4.595, 1.0, 40.93, '', '', '', 8] ['ATOM', 140, 'N', '', 'ALA', 'A', 20, '', 25.97, 65.08, -18.095, 1.0, 27.39, '', '', '', 143] ['ATOM', 141, 'CA', '', 'ALA', 'A', 20, '', 27.414, 65.108, -17.869, 1.0, 28.79, '', '', '', 144] ['ATOM', 142, 'C', '', 'ALA', 'A', 20, '', 27.961, 66.358, -17.164, 1.0, 28.49, '', '', '', 145] ['ATOM', 143, 'O', '', 'ALA', 'A', 20, '', 28.995, 66.292, -16.487, 1.0, 27.51, '', '', '', 146] ['ATOM', 144, 'CB', '', 'ALA', 'A', 20, '', 28.146, 64.915, -19.211, 1.0, 29.3, '', '', '', 147] |
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:
|
1 2 |
print("=> regenerating original protein string for two first ALA residues.") print(pdb_resmap2str(s, r2[0:2])) |
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.99ATOM 2 CA ALA A 1 24.462 74.606 -4.600 1.00 40.12ATOM 3 C ALA A 1 23.740 74.728 -5.939 1.00 39.15ATOM 4 O ALA A 1 23.516 75.835 -6.430 1.00 40.24ATOM 5 CB ALA A 1 25.691 75.499 -4.595 1.00 40.93ATOM 140 N ALA A 20 25.970 65.080 -18.095 1.00 27.39ATOM 141 CA ALA A 20 27.414 65.108 -17.869 1.00 28.79ATOM 142 C ALA A 20 27.961 66.358 -17.164 1.00 28.49ATOM 143 O ALA A 20 28.995 66.292 -16.487 1.00 27.51ATOM 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:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
print("*** Test structure composition") print("without any structure knowledge and using uniq matrix u0") print("=> computing uniq matrix") u3 = pdb_pdbm2uniq(m0, [0,4], '-') print("=> derivating hetero residues list and a simplified uniq matrix") hetlist = [] hetuniq = [] for i in range (0, len(u3), 1): if (u3[i][0] == "HETATM"): hit = 0 if (u3[i][4] == "HOH"): hit += 1 if (u3[i][4] == "H20"): hit += 1 if (u3[i][4] == "WAT"): hit += 1 if (hit == 0): hetlist.append(u3[i][4]) hetuniq.append(u3[i]) print("hetlist = ", hetlist) print("new uniq matrix (hetuniq) = ", hetuniq) |
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:
|
1 2 3 4 5 6 7 8 9 10 |
[['ATOM', '', '', '', 'ALA', '', '', '', '', '', '', '', '', '', '', '', ''], ['ATOM', '', '', '', 'ARG', '', '', '', '', '', '', '', '', '', '', '', ''], ['ATOM', '', '', '', 'PRO', '', '', '', '', '', '', '', '', '', '', '', ''], ... ['ATOM', '', '', '', 'GLN', '', '', '', '', '', '', '', '', '', '', '', ''], ['ATOM', '', '', '', 'HIS', '', '', '', '', '', '', '', '', '', '', '', ''], ['ATOM', '', '', '', 'TRP', '', '', '', '', '', '', '', '', '', '', '', ''], ['HETATM', '', '', '', 'SO4', '', '', '', '', '', '', '', '', '', '', '', ''], ['HETATM', '', '', '', 'NDG', '', '', '', '', '', '', '', '', '', '', '', ''], ['HETATM', '', '', '', 'HOH', '', '', '', '', '', '', '', '', '', '', '', '']] |
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 matrixhetlist = ['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:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
print("================= for row = 0 of uniq matrix ===================") print("get pdbm matrix and resmap") m5 = pdb_pdbm2block(m0, hetuniq, 0, [0,4]) r5 = pdb_pdbm2resmap(m5) print(r5) print("regenerate original PDB string for first SO4") print(pdb_resmap2str(s, r5[0])) print("computing the corresponding reslist") rl = pdb_pdbm2reslist(m0, r5, 0) print(rl) print("extracting a sub-pdbm using a sub-reslist (the two first residues)") r5b = pdb_reslist2pdbm(m0, r5, rl[0:2], 0) for i in range (0, len(r5b), 1): print(r5b[i]) print() |
Ce qui va donner comme résultat:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
================= for row = 0 of uniq matrix =================== get pdbm matrix and resmap [['SO4', 1498, 3934, 3938, -1, ''], ['SO4', 1499, 3939, 3943, -1, ''], ['SO4', 1500, 3944, 3948, -1, ''], ['SO4', 1501, 3949, 3953, -1, ''], ['SO4', 1502, 3954, 3958, -1, ''], ['SO4', 1503, 3959, 3963, -1, ''], ['SO4', 1504, 3964, 3968, -1, ''], ['SO4', 1505, 3969, 3973, -1, ''], ['SO4', 1506, 3974, 3978, -1, ''], ['SO4', 1507, 3979, 3983, -1, '']] regenerate original PDB string for first SO4 HETATM 3930 S SO4 A1498 14.064 40.489 -7.362 1.00 95.67 HETATM 3931 O1 SO4 A1498 13.564 39.220 -7.927 1.00 96.27 HETATM 3932 O2 SO4 A1498 13.978 41.555 -8.381 1.00 94.12 HETATM 3933 O3 SO4 A1498 13.246 40.864 -6.192 1.00 95.65 HETATM 3934 O4 SO4 A1498 15.465 40.309 -6.944 1.00 95.03 computing the corresponding reslist [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] extracting a sub-pdbm using a sub-reslist (the two first residues) ['HETATM', 3930, 'S', '', 'SO4', 'A', 1498, '', 14.064, 40.489, -7.362, 1.0, 95.67, '', '', '', 3934] ['HETATM', 3931, 'O1', '', 'SO4', 'A', 1498, '', 13.564, 39.22, -7.927, 1.0, 96.27, '', '', '', 3935] ['HETATM', 3932, 'O2', '', 'SO4', 'A', 1498, '', 13.978, 41.555, -8.381, 1.0, 94.12, '', '', '', 3936] ['HETATM', 3933, 'O3', '', 'SO4', 'A', 1498, '', 13.246, 40.864, -6.192, 1.0, 95.65, '', '', '', 3937] ['HETATM', 3934, 'O4', '', 'SO4', 'A', 1498, '', 15.465, 40.309, -6.944, 1.0, 95.03, '', '', '', 3938] ['HETATM', 3935, 'S', '', 'SO4', 'A', 1499, '', 18.718, 69.995, -4.169, 1.0, 86.92, '', '', '', 3939] ['HETATM', 3936, 'O1', '', 'SO4', 'A', 1499, '', 19.555, 68.785, -4.313, 1.0, 85.58, '', '', '', 3940] ['HETATM', 3937, 'O2', '', 'SO4', 'A', 1499, '', 17.697, 70.009, -5.233, 1.0, 86.36, '', '', '', 3941] ['HETATM', 3938, 'O3', '', 'SO4', 'A', 1499, '', 18.049, 69.985, -2.855, 1.0, 86.83, '', '', '', 3942] ['HETATM', 3939, 'O4', '', 'SO4', 'A', 1499, '', 19.559, 71.204, -4.272, 1.0, 85.98, '', '', '', 3943] |
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:
|
1 2 3 4 5 6 7 8 9 10 11 |
print("================= for row = 1 of uniq matrix ===================") print("get pdbm matrix and resmap") m5 = pdb_pdbm2block(m0, hetuniq, 1, [0,4]) r5 = pdb_pdbm2resmap(m5) print(r5) print("regenerate original PDB string for ligand") print(pdb_resmap2str(s, r5)) print("extract original pdbm block using ligand resmap") r6 = pdb_resmap2pdbm(m0, r5, chain='A') for i in range (0, len(r6), 1): print(r6[i]) |
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:
|
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 |
================= for row = 1 of uniq matrix =================== get pdbm matrix and resmap [['NDG', 1997, 3984, 3997, -1, '']] regenerate original PDB string for ligand HETATM 3980 C1 NDG A1997 22.253 69.485 -19.213 1.00 45.53 HETATM 3981 C2 NDG A1997 23.178 69.976 -20.344 1.00 49.65 HETATM 3982 C3 NDG A1997 22.895 71.451 -20.616 1.00 49.23 HETATM 3983 C4 NDG A1997 21.962 72.062 -19.550 1.00 48.91 HETATM 3984 C5 NDG A1997 22.381 71.624 -18.130 1.00 47.48 HETATM 3985 C6 NDG A1997 21.335 72.009 -17.100 1.00 45.27 HETATM 3986 C7 NDG A1997 25.408 69.138 -20.759 1.00 53.53 HETATM 3987 C8 NDG A1997 26.435 69.952 -21.514 1.00 55.90 HETATM 3988 O NDG A1997 22.542 70.188 -18.012 1.00 46.64 HETATM 3989 O3 NDG A1997 22.326 71.604 -21.914 1.00 50.07 HETATM 3990 O4 NDG A1997 22.036 73.487 -19.618 1.00 48.57 HETATM 3991 O6 NDG A1997 20.051 72.069 -17.702 1.00 42.54 HETATM 3992 O7 NDG A1997 25.400 67.917 -20.861 1.00 53.06 HETATM 3993 N2 NDG A1997 24.574 69.819 -19.976 1.00 53.06 extract original pdbm block using ligand resmap ['HETATM', 3980, 'C1', '', 'NDG', 'A', 1997, '', 22.253, 69.485, -19.213, 1.0, 45.53, '', '', '', 3984] ['HETATM', 3981, 'C2', '', 'NDG', 'A', 1997, '', 23.178, 69.976, -20.344, 1.0, 49.65, '', '', '', 3985] ['HETATM', 3982, 'C3', '', 'NDG', 'A', 1997, '', 22.895, 71.451, -20.616, 1.0, 49.23, '', '', '', 3986] ['HETATM', 3983, 'C4', '', 'NDG', 'A', 1997, '', 21.962, 72.062, -19.55, 1.0, 48.91, '', '', '', 3987] ['HETATM', 3984, 'C5', '', 'NDG', 'A', 1997, '', 22.381, 71.624, -18.13, 1.0, 47.48, '', '', '', 3988] ['HETATM', 3985, 'C6', '', 'NDG', 'A', 1997, '', 21.335, 72.009, -17.1, 1.0, 45.27, '', '', '', 3989] ['HETATM', 3986, 'C7', '', 'NDG', 'A', 1997, '', 25.408, 69.138, -20.759, 1.0, 53.53, '', '', '', 3990] ['HETATM', 3987, 'C8', '', 'NDG', 'A', 1997, '', 26.435, 69.952, -21.514, 1.0, 55.9, '', '', '', 3991] ['HETATM', 3988, 'O', '', 'NDG', 'A', 1997, '', 22.542, 70.188, -18.012, 1.0, 46.64, '', '', '', 3992] ['HETATM', 3989, 'O3', '', 'NDG', 'A', 1997, '', 22.326, 71.604, -21.914, 1.0, 50.07, '', '', '', 3993] ['HETATM', 3990, 'O4', '', 'NDG', 'A', 1997, '', 22.036, 73.487, -19.618, 1.0, 48.57, '', '', '', 3994] ['HETATM', 3991, 'O6', '', 'NDG', 'A', 1997, '', 20.051, 72.069, -17.702, 1.0, 42.54, '', '', '', 3995] ['HETATM', 3992, 'O7', '', 'NDG', 'A', 1997, '', 25.4, 67.917, -20.861, 1.0, 53.06, '', '', '', 3996] ['HETATM', 3993, 'N2', '', 'NDG', 'A', 1997, '', 24.574, 69.819, -19.976, 1.0, 53.06, '', '', '', 3997] |
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
- Structure 1OGS [ https://www.rcsb.org/structure/1OGS ].
- Glucosylceramidase – GCase – Glucocerobrosidase [ https://en.wikipedia.org/wiki/Glucocerebrosidase ].
- UniProt P04062 · GBA1_HUMAN [ https://www.uniprot.org/uniprotkb/P04062/entry ].