Repository with sources and generator of https://larlet.fr/david/ https://larlet.fr/david/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. <!doctype html>
  2. <html lang=fr>
  3. <head>
  4. <!-- Always define the charset before the title -->
  5. <meta charset=utf-8>
  6. <title>★ Parser un fichier PDB en python facilement et efficacement — Biologeek — David Larlet</title>
  7. <!-- Define a viewport to mobile devices to use - telling the browser to assume that the page is as wide as the device (width=device-width) and setting the initial page zoom level to be 1 (initial-scale=1.0) -->
  8. <meta name="viewport" content="width=device-width, initial-scale=1"/>
  9. <!-- Fake favicon, to avoid extra request to the server -->
  10. <link rel="icon" href="data:;base64,iVBORw0KGgo=">
  11. <link type="application/atom+xml" rel="alternate" title="Feed" href="/david/log/" />
  12. <link rel="manifest" href="/manifest.json">
  13. <link rel="stylesheet" href="/static/david/css/larlet-david-_J6Rv.css" data-instant-track />
  14. <noscript>
  15. <style type="text/css">
  16. /* Otherwise fonts are loaded by JS for faster initial rendering. See scripts at the bottom. */
  17. body {
  18. font-family: 'EquityTextB', serif;
  19. }
  20. h1, h2, h3, h4, h5, h6, time, nav a, nav a:link, nav a:visited {
  21. font-family: 'EquityCapsB', sans-serif;
  22. font-variant: normal;
  23. }
  24. </style>
  25. </noscript>
  26. <!-- Canonical URL for SEO purposes -->
  27. <link rel="canonical" href="https://larlet.fr/david/biologeek/archives/20051017-parser-un-fichier-pdb-en-python-facilement-et-efficacement">
  28. </head>
  29. <body>
  30. <div>
  31. <header>
  32. <nav>
  33. <p>
  34. <small>
  35. Je suis <a href="/david/" title="Profil public">David Larlet</a>, <a href="/david/pro/" title="Activité professionnelle">artisan</a> du web qui vous <a href="/david/pro/accompagnement/" title="Activité d’accompagnement">accompagne</a><span class="more-infos"> dans l’acquisition de savoirs pour concevoir des <a href="/david/pro/produits-essentiels/" title="Qu’est-ce qu’un produit essentiel ?">produits essentiels</a></span>. <span class="more-more-infos">Discutons ensemble d’une <a href="/david/pro/devis/" title="En savoir plus">non-demande de devis</a>.</span> Je partage ici mes <a href="/david/blog/" title="Expériences bienveillantes">réflexions</a> et <a href="/david/correspondances/2017/" title="Lettres hebdomadaires">correspondances</a>.
  36. </small>
  37. </p>
  38. </nav>
  39. </header>
  40. <section>
  41. <h1 property="schema:name">★ Parser un fichier PDB en python facilement et efficacement</h1>
  42. <article typeof="schema:BlogPosting">
  43. <div property="schema:articleBody">
  44. <img src="/static/david/biologeek/images/logos/python_nouveau.png" alt="vignette" style="float:left; margin: 0.5em 1em;" property="schema:thumbnailUrl" />
  45. <p>L'une des <del>galère</del> tâche quotidienne d'un bio-informaticien s'intéressant un tant soit peu à la biologie structurale et à la position d'une protéine dans l'espace est de parser des fichiers PDB. C'est fichiers, issus de la <a href="http://www.rcsb.org/pdb/">Protein Data Bank</a>, contiennent une foultitude d'informations plus ou moins pertinentes en fonction de son sujet de recherche. Or, les parsers actuels que je connais sont pour la plupart de véritables usines à gaz souvent inadaptés et lourds pour le traitement que j'ai à faire. Voici donc un «&nbsp;squelette » de parser de PDB en python, par «&nbsp;squelette » j'entend que vous allez devoir coder les parties spécifiques à vos besoins.</p>
  46. <h2>Structure d'un fichier PDB</h2>
  47. <p>Voila en gros à quoi ressemble un fichier PDB&nbsp;:</p>
  48. <pre>HEADER OXYGEN TRANSPORT 26-FEB-96 1SDK
  49. TITLE CROSS-LINKED, CARBONMONOXY HEMOGLOBIN A
  50. COMPND MOL_ID: 1;
  51. COMPND 2 MOLECULE: HEMOGLOBIN A;
  52. COMPND 3 CHAIN: A, B, C, D;
  53. COMPND 4 OTHER_DETAILS: CROSS-LINKED, CARBONMONOXY
  54. SOURCE MOL_ID: 1;
  55. SOURCE 2 ORGANISM_SCIENTIFIC: HOMO SAPIENS;
  56. SOURCE 3 ORGANISM_COMMON: HUMAN
  57. KEYWDS HEME, OXYGEN TRANSPORT, RESPIRATORY PROTEIN, ERYTHROCYTE,
  58. KEYWDS 2 DISEASE MUTATION, POLYMORPHISM
  59. EXPDTA X-RAY DIFFRACTION
  60. AUTHOR M.A.SCHUMACHER,M.M.DIXON,R.KLUGER,R.T.JONES,R.G.BRENNAN
  61. REVDAT 1 01-AUG-96 1SDK 0
  62. [SNIP]
  63. HELIX 1 1 PRO A 4 GLY A 15 1 12
  64. HELIX 2 2 GLY A 18 SER A 35 5 18
  65. HELIX 3 3 PRO A 37 PHE A 43 5 7
  66. HELIX 4 4 ALA A 53 ALA A 71 1 19
  67. HELIX 5 5 VAL A 73 HIS A 89 5 17
  68. HELIX 6 6 PRO A 95 HIS A 112 1 18
  69. HELIX 7 7 PRO A 119 TYR A 140 1 22
  70. HELIX 8 8 PRO B 5 LYS B 17 1 13
  71. HELIX 9 9 VAL B 23 VAL B 34 1 12
  72. HELIX 10 10 PRO B 36 PHE B 42 5 7
  73. [SNIP]
  74. ATOM 1 N VAL A 1 36.846 49.802 -14.919 1.00 89.28 N
  75. ATOM 2 CA VAL A 1 37.907 49.146 -14.140 1.00 89.20 C
  76. ATOM 3 C VAL A 1 37.655 49.392 -12.632 1.00 84.23 C
  77. ATOM 4 O VAL A 1 38.531 49.598 -11.742 1.00 82.54 O
  78. ATOM 5 CB VAL A 1 39.361 49.471 -14.649 1.00 93.91 C
  79. ATOM 6 CG1 VAL A 1 39.441 49.501 -16.172 1.00 93.10 C
  80. ATOM 7 CG2 VAL A 1 39.890 50.778 -14.094 1.00 94.26 C
  81. ATOM 8 N LEU A 2 36.364 49.205 -12.405 1.00 68.64 N
  82. ATOM 9 CA LEU A 2 35.719 49.461 -11.152 1.00 62.16 C
  83. ATOM 10 C LEU A 2 35.826 50.891 -10.976 1.00 69.86 C
  84. ATOM 11 O LEU A 2 36.748 51.514 -10.445 1.00 70.82 O
  85. ATOM 12 CB LEU A 2 35.859 48.504 -10.004 1.00 56.68 C
  86. ATOM 13 CG LEU A 2 34.686 47.515 -10.109 1.00 45.20 C
  87. ATOM 14 CD1 LEU A 2 34.868 46.618 -11.293 1.00 33.18 C
  88. ATOM 15 CD2 LEU A 2 34.615 46.658 -8.886 1.00 57.98 C
  89. ATOM 16 N SER A 3 35.120 51.235 -12.022 1.00 61.69 N
  90. ATOM 17 CA SER A 3 34.707 52.459 -12.504 1.00 57.56 C
  91. ATOM 18 C SER A 3 33.527 52.737 -11.624 1.00 50.93 C</pre>
  92. <p>Les morceaux présentés n'ont pas été choisis par hasard et vont servir dans la suite de la présentation. Si vous souhaitez obtenir un fichier PDB complet, voici <a href="#">celui de la protéine 1SDK</a> (sinon elle est aussi disponible dans l'archive proposée en téléchargement). Là vous vous dites comme n'importe quel geek&nbsp;: <em>«&nbsp;Les bio-informaticiens ne connaissent pas le XML ?! »</em> en fait si, ce format est aussi disponible mais malheureusement pour une même protéine, on atteint 5,1 Mo contre 440 Ko pour la même en texte brut. Sachant qu'il faut généralement commencer par les télécharger pour travailler dessus et qu'on compte en milliers de protéines, vous voyez aisément le problème sans parler de l'espace disque qu'il faut alors considérer...</p>
  93. <h2>Le template PDBParser.py</h2>
  94. <p>Le code est vraiment court mais il est très important de le comprendre pour continuer&nbsp;:</p>
  95. <pre>class PDBParser:
  96. def __init__(self, file_in):
  97. self.PDB = {}
  98. self.properties = []
  99. for line in file_in.readlines():
  100. try:
  101. self.PDB[line[0:6].strip()].append(line[0:-1])
  102. except KeyError:
  103. self.PDB[line[0:6].strip()] = [line[0:-1]]
  104. self.properties.append(line[0:6].strip())
  105. def __getitem__(self, key):
  106. try:
  107. parserName = "%sParser" % key.capitalize()
  108. parserClass = globals()[parserName]
  109. return parserClass(self.PDB[key])
  110. except KeyError:
  111. return DefaultClass(self.PDB[key])
  112. def __getslice__(self, begin, end):
  113. return [line for property in self.properties \
  114. for line in self.PDB[property]][begin:end]
  115. def __repr__(self):
  116. return [line for property in self.properties \
  117. for line in self.PDB[property]]
  118. def __str__(self):
  119. return "
  120. ".join([line for property in self.properties \
  121. for line in self.PDB[property]])
  122. class DefaultClass:
  123. def __init__(self, defaults): self.defaults = defaults
  124. def __getslice__(self, begin, end): return self.defaults[begin:end]
  125. def __getitem__(self, key): return self.defaults[key]
  126. def __repr__(self): return self.defaults
  127. def __str__(self): return "
  128. ".join(self.defaults)</pre>
  129. <p>Dans la classe PDBParser, __init__ et __getitem__ sont les méthodes spéciales de classe importantes, la première crée le dictionnaire PDB qui va contenir, pour chaque clé correspondant aux 6 premiers caractères d'une ligne, une liste de valeurs correspondant aux lignes en question.</p>
  130. <p>Par exemple PDB['COMPND'] contient&nbsp;:</p>
  131. <pre>['COMPND MOL_ID: 1; ',
  132. 'COMPND 2 MOLECULE: HEMOGLOBIN A; ',
  133. 'COMPND 3 CHAIN: A, B, C, D; ',
  134. 'COMPND 4 OTHER_DETAILS: CROSS-LINKED, CARBONMONOXY ']</pre>
  135. <p>La liste properties permet de conserver l'ordre des clés de façon à pouvoir restituer le PDB complet en cas de besoin. Par exemple pour un affichage au moyen des méthodes __getslice__, __repr__ ou __str__. Par exemple PDB[:10] renverra les dix premières lignes du fichier PDB sous forme de liste.</p>
  136. <p>La méthode __getitem__ est vraiment LA méthode clé de la classe, c'est elle qui rend le template modulable et donc si puissant&nbsp;! Elle est assez simple à comprendre&nbsp;: si une classe intitulée <strong>SixpremierscaractèresdelaligneParser</strong> existe, elle est instanciée, sinon c'est la classe DefaultClass qui va l'être. DefaultClass contenant les méthodes spéciales de classes usuelles, elle permet d'afficher tout ou partie des données, par exemple PDB['COMPND'].__repr__() renvoie la liste des lignes préfixées par 'COMPND'.</p>
  137. <p>Et c'est tout&nbsp;? Pour l'instant oui, après c'est à vous de coder ce dont vous avez besoin, allez je suis sympa voici quelques exemples concrêts :)</p>
  138. <h2>Les exemples d'application</h2>
  139. <p>Pas évident de voir à première vue comment fonctionne le template alors voila quelques classes d'exemples qui pourront peut-être même vous servir (probablement à adapter).</p>
  140. <h3>Récupérer les coordonnées atomiques de la chaîne C des acides aminés leucine (LEU) et des carbones alpha (CA)</h3>
  141. <p>Il est assez courant de ne vouloir que quelques atomes ou une seule chaîne ou qu'un type d'acides aminés, cette classe permet de récupérer simplement ces informations dans votre PDB, puisqu'on va traiter les lignes préfixées par 'ATOM', notre classe doit s'appeler AtomParser&nbsp;:</p>
  142. <pre>class AtomParser(DefaultClass):
  143. def __init__(self, atoms, *par):
  144. if len(par) == 0:
  145. self.atoms = atoms
  146. elif len(par[0]) == 1:
  147. self.atoms = [atom for atom in atoms if atom[21] == par[0]]
  148. elif len(par[0]) == 2:
  149. self.atoms = [atom for atom in atoms if atom[13:15] == par[0]]
  150. elif len(par[0]) == 3:
  151. self.atoms = [atom for atom in atoms if atom[17:20] == par[0]]
  152. DefaultClass.__init__(self, self.atoms)
  153. def __getitem__(self, key): return AtomParser(self.atoms, key)
  154. def get_coordinates(self):
  155. return [[atom[29:38].strip(),atom[38:46].strip(),atom[46:54].strip()]\
  156. for atom in self.atoms]</pre>
  157. <p>Cette classe permet d'obtenir les résultats suivants&nbsp;:</p>
  158. <pre>print PDB['ATOM']['C']['LEU']['CA']
  159. ATOM 2293 CA LEU C 2 56.540 41.891 -11.769 1.00 31.34 C
  160. ATOM 2483 CA LEU C 29 53.070 39.062 -36.319 1.00 5.06 C
  161. ATOM 2530 CA LEU C 34 49.611 32.028 -40.266 1.00 9.46 C
  162. ...
  163. print PDB['ATOM']['LEU']['C '].get_coordinates()[:10]
  164. [['35.826', '50.891', '-10.976'],
  165. ['28.628', '24.722', '-5.569'],
  166. ['27.926', '19.794', '-11.999'],
  167. ['28.129', '17.183', '-1.981'],
  168. [SNIP],
  169. ['32.035', '40.188', '-0.663']]</pre>
  170. <p>C'est donc assez pratique, l'ordre des paramètres n'a pas d'importance, PDB['ATOM']['C']['LEU']['CA'] est équivalent à PDB['ATOM']['C']['CA']['LEU'] et on peut omettre une information au besoin, par exemple pour récupérer les mêmes informations pour toutes les chaînes, PDB['ATOM']['LEU']['CA'] suffit.</p>
  171. <p>Bon maintenant comment ça marche&nbsp;?</p>
  172. <p>En fait l'astuce est de considérer ici la taille du paramètre passé en argument, par exemple pour le choix de la chaîne, sa taille est de 1 et l'on filtre les lignes composant atoms en conséquence. On initialise ensuite la classe DefaultClass parente avec les données appropriées ce qui permet d'hériter de ses méthodes spéciales. Deuxième astuce&nbsp;: la classe est récursive, ce qui permet d'enchaîner ou non les arguments et de les traiter un par un. Enfin la fonction <strong>get_coordinates()</strong> permet de récupérer les coordonnées atomiques des atomes considérés sous forme de liste sous la forme [x, y, z].</p>
  173. <p>Vous l'aurez compris, la première astuce est limitante pour désigner par exemple certains atomes qui sont nommés par plus de 2 lettres (par exemple CD1), si vous avez besoin spécifiquement de ce type d'atomes (très rare à mon avis), une solution rapide est de considérer alors que les atomes ont une taille de 4 lettres. Encore une fois, ce n'est qu'un exemple à adapter ;-)</p>
  174. <h3>Quelle est la position des hélices alpha de la chaîne B&nbsp;?</h3>
  175. <p>On passe maintenant aux structures secondaires et plus particulièrement aux lignes préfixées par 'HELIX'.</p>
  176. <pre>class HelixParser(DefaultClass):
  177. def __init__(self, helixs, *par):
  178. if len(par) == 0:
  179. self.helixs = helixs
  180. elif len(par[0]) == 1:
  181. self.helixs = [helix for helix in helixs if helix[19] == par[0]]
  182. elif len(par[0]) == 3:
  183. self.helixs = []
  184. for helix in helixs:
  185. if helix[15:18] == par[0]:
  186. self.helixs.append(helix[20:26].strip())
  187. elif helix[27:30] == par[0]:
  188. self.helixs.append(helix[32:38].strip())
  189. DefaultClass.__init__(self, self.helixs)
  190. def __getitem__(self, key): return HelixParser(self.helixs, key)</pre>
  191. <p>Cette classe permet d'obtenir les résultats suivants&nbsp;:</p>
  192. <pre>PDB['HELIX']['A']['GLY'].__repr__()
  193. ['15', '18']</pre>
  194. <p>Ici aussi on considère la taille de l'argument (1 pour la chaîne et 3 pour l'acide aminé) ce qui permet d'obtenir une liste des positions des acides aminés particuliers impliqués dans une hélice alpha. Lorsque l'on considère un acide aminé, il faut aller vérifier à deux endroits différents étant donné qu'il y a deux réponses par ligne.</p>
  195. <p>Vous remarquerez qu'on appel de PDB['HELIX']['A'] ne renvoie pas une liste de positions mais la liste contenant les lignes 'HELIX' de la chaîne A, si vous voulez obtenir une liste dans ce cas là, il faut un peu coder car je n'ai pas encore eu cette utilité.</p>
  196. <h3>Je voudrais les premier et dernier auteurs s'il vous plaît</h3>
  197. <p>Bon là vous commencez vraiment à comprendre le mécanisme, un dernier exemple sans grande utilité pour être sûr.</p>
  198. <pre>class AuthorParser(DefaultClass):
  199. def __init__(self, authors):
  200. self.authors = authors[0][6:-9].strip().split(',')
  201. DefaultClass.__init__(self, self.authors)</pre>
  202. <p>Cette classe permet d'obtenir les résultats suivants&nbsp;:</p>
  203. <pre>print PDB['AUTHOR'][0], PDB['AUTHOR'][-1]
  204. M.A.SCHUMACHER R.G.BRENNAN</pre>
  205. <p>Tout simple, on commence par créer une liste d'auteurs à l'initialisation et le fait d'initialiser la classe parente DefaultClass permet de disposer de toutes ses méthodes spéciales. On demande ensuite pour l'exemple d'afficher les premier et dernier auteurs.</p>
  206. <h2>Performances</h2>
  207. <p>Tout à un prix quand même et rien ne sera jamais plus rapide qu'un parsing «&nbsp;à la main » par exemple en testant sur un panel de 2300 protéines, on obtient 1 minute 20 secondes (avec un Celeron M 1,4GHz, disque dur 5400tr/min et 768Mo de ram) pour&nbsp;:</p>
  208. <pre>PDB = PDBParser(open("%s.pdb" % pdbid))
  209. coordinates.append(PDB['ATOM'][chain]['LEU']['CA'].get_coordinates())</pre>
  210. <p>contre 52 secondes pour&nbsp;:</p>
  211. <pre>coordinates = [[atom[29:38].strip(),atom[38:46].strip(),atom[46:54].strip()] \
  212. for atom in open("%s.pdb" % pdbid).readlines() \
  213. if atom.startswith('ATOM') and atom[21] == chain and \
  214. atom[13:15] == 'CA' and atom[17:20] == 'LEU']</pre>
  215. <p>Bon premier constat&nbsp;: vive les list-comprehension, second constat&nbsp;: on n'obtient pas les mêmes résultats en fait puisque le premier <strong>coordinates</strong> est une liste de listes alors que le second n'est qu'une liste, si l'on réitère les tests de façon à obtenir les mêmes résultats&nbsp;:</p>
  216. <pre>_coord = []
  217. for atom in open("%s.pdb" % pdbid).readlines():
  218. if atom.startswith('ATOM') and atom[21] == chain and \
  219. atom[13:15] == 'CA' and atom[17:20] == 'LEU':
  220. _coord.append([atom[29:38].strip(),atom[38:46].strip(),atom[46:54].strip()])
  221. coordinates.append(_coord)</pre>
  222. <p>On obtient le même résultat en 59 secondes... ce qui fait environ 25% de temps en plus lorsque l'on se sert du parser. Ça peut paraître énorme mais si l'on n'a à parser que quelques milliers de protéines ça peut devenir rentable en terme de temps d'implémentation/lisibilité du code. Sans compter la modularité vous permettant d'obtenir plusieurs informations pour un coût pratiquement équivalent. À vous encore de faire le bon compromis.</p>
  223. <p><strong>[edit]</strong>&nbsp;: je n'ai pas fait de tests plus poussés mais il est certain que l'appel à <strong>globals()</strong> dans la fonction __getitem__ de la classe <strong>PDBParser</strong> nuit aux performances du script donc si vous n'avez qu'une seule classe de parsing appelée, il vaut mieux la spécifier explicitement dans le script.</p>
  224. <h2>Téléchargement</h2>
  225. <p>Vous pouvez télécharger le code commenté, les exemples et un fichier PDB contenus <del><a href="#">dans cette archive</a></del> (mise à jour cf. ci-dessous).</p>
  226. <h2>En conclusion</h2>
  227. <p>Ce n'est pas révolutionnaire mais c'est bien pratique et plutôt élégant, je laisse votre imagination et surtout vos besoins compléter ces classes :-). Toute remarque/suggestion/correction/contribution est la bienvenue&nbsp;!</p>
  228. <h2>Mise à jour</h2>
  229. <p>On a souvent besoin des résolutions dans lesquelles ont été cristallisées les protéines, le problème est qu'il n'y a pas vraiment de standard pour placer cette information dans les PDB donc ça finit toujours en vrac dans les remarques... j'ai essayé de faire au mieux, ça passe pour 3000 protéines je vous laisse vérifier sur votre set (la fonction <strong>get_resolution()</strong> renvoie un float)&nbsp;:</p>
  230. <pre>class RemarkParser(DefaultClass):
  231. def __init__(self, remarks):
  232. self.remarks = remarks
  233. DefaultClass.__init__(self, self.remarks)
  234. def get_resolution(self):
  235. __angstrom_lines = [line for line in self.remarks if 'ANGSTROM' in line]
  236. # new standard (?)
  237. if 'REMARK 2 RESOLUTION.' in __angstrom_lines[0]:
  238. return float(__angstrom_lines[0][23:27])
  239. # old random remarks...
  240. else:
  241. try:
  242. return float(__angstrom_lines[0].split('ANGSTROM')[0][-5:].split()[-1])
  243. except:
  244. # print wrong line if needed (uncomment)
  245. #print angstrom_lines[0]
  246. return None</pre>
  247. <p>Et voici le <del><a href="#">fichier complet mis à jour</a></del> (mise à jour cf. ci-dessous).</p>
  248. <h2>Mise à jour du 25/04/06</h2>
  249. <p>Bon je voulais pas que ça devienne une usine à gaz mais c'est pas une raison pour ne pas faire une documentation potable :-).</p>
  250. <p>Voici donc la <del><a href="#">version 3 du parser</a></del>. Vous pouvez maintenant lancer le programme en ligne de commande suivi d'une liste de fichiers PDB, je vous laisse voir les options dans la documentation. Bien sûr la classe est toujours utilisable par simple import.</p>
  251. <h2>Mise à jour du 20/01/08</h2>
  252. <p>Un grand merci à François Vallée qui a remonté ses améliorations&nbsp;: il y a dorénavant une classe pour les lignes HETATM et une méthode (get_biomt) qui récupère les BIOMT des REMARK. Vous pouvez <a href="/static/david/biologeek/realisations/PDBParser/PDBParser4.zip">télécharger la version 4</a>.</p>
  253. </div>
  254. </article>
  255. <footer>
  256. <h6 property="schema:datePublished">— 17/10/2005</h6>
  257. </footer>
  258. </section>
  259. <section>
  260. <div>
  261. <h3>Articles peut-être en rapport</h3>
  262. <ul>
  263. <li><a href="/david/biologeek/archives/20101130-de-lopendata-au-linkeddata-exemple-de-nosdonneesfr/" title="Accès à ★ De l&#39;OpenData au LinkedData : exemple de nosdonnees.fr">★ De l&#39;OpenData au LinkedData : exemple de nosdonnees.fr</a></li>
  264. <li><a href="/david/biologeek/archives/20091211-pourquoi-python-et-django/" title="Accès à ★ Pourquoi Python et Django">★ Pourquoi Python et Django</a></li>
  265. <li><a href="/david/biologeek/archives/20090526-django-roa-pour-une-architecture-orientee-ressources/" title="Accès à ★ Django-ROA, pour une architecture orientée ressources">★ Django-ROA, pour une architecture orientée ressources</a></li>
  266. </ul>
  267. </div>
  268. </section>
  269. <section>
  270. <div id="comments">
  271. <h3>Commentaires</h3>
  272. <div class="comment" typeof="schema:UserComments">
  273. <p class="comment-meta">
  274. <span class="comment-author" property="schema:creator">Martin</span> le <span class="comment-date" property="schema:commentTime">18/04/2006</span> :
  275. </p>
  276. <div class="comment-content" property="schema:commentText">
  277. <p>Bonsoir<br />
  278. <br />
  279. Merci beaucoup pour partager ce &quot;bout&quot; de code... Maintenant, moi la seule chose que je veux est 'spliter' un PDB en ces chaines (A, B, C, etc). Si je prends vos classes et je met le print suivant: <br />
  280. <br />
  281. print PDB['ATOM']['C'].get_coordinates()[:10]<br />
  282. <br />
  283. j'obtient:<br />
  284. <br />
  285. #####<br />
  286. $ ./PDBparser.py 1RJD.pdb<br />
  287. Traceback (most recent call last):<br />
  288. File &quot;./PDBparser.py&quot;, line 64, in ?<br />
  289. print PDB['ATOM']['C'].get_coordinates()[:10]<br />
  290. NameError: name 'PDB' is not defined<br />
  291. <br />
  292. #####<br />
  293. <br />
  294. des idees ? merci encore!<br />
  295. martin<br />
  296. <br />
  297. [mgrana_at_gmail.com]</p>
  298. </div>
  299. </div>
  300. <div class="comment" typeof="schema:UserComments">
  301. <p class="comment-meta">
  302. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">19/04/2006</span> :
  303. </p>
  304. <div class="comment-content" property="schema:commentText">
  305. <p>Il faut d'abord créer une instance de PDBParser de la manière suivante dans le code :<br />
  306. <br />
  307. PDB = PDBParser(open(&quot;1SDK.pdb&quot;))<br />
  308. <br />
  309. Bon je suis d'accord c'est pas très pratique (surtout qu'à la dernière mise à jour les archives ont sautées :/) et il faut que je documente beaucoup mieux tout ça. À l'époque je ne savais pas le faire mais maintenant oui :)<br />
  310. <br />
  311. Je mettrais à jour prochaînement le billet avec de la documentation agile.</p>
  312. </div>
  313. </div>
  314. <div class="comment" typeof="schema:UserComments">
  315. <p class="comment-meta">
  316. <span class="comment-author" property="schema:creator">Jerome Pansanel</span> le <span class="comment-date" property="schema:commentTime">30/04/2007</span> :
  317. </p>
  318. <div class="comment-content" property="schema:commentText">
  319. <p>Est-ce que vous avez pensé à utiliser cette classe pour écrire un outil permettant de préparer une protéine pour un docking ?</p>
  320. </div>
  321. </div>
  322. <div class="comment" typeof="schema:UserComments">
  323. <p class="comment-meta">
  324. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">30/04/2007</span> :
  325. </p>
  326. <div class="comment-content" property="schema:commentText">
  327. <p>Non, cette bibliothèque est un peu à l'abandon en fait... mais bon le format pdb évolue peu donc elle est toujours utilisable.<br />
  328. <br />
  329. Si vous avez des suggestions d'améliorations, n'hésitez pas, je peux les publier ici.</p>
  330. </div>
  331. </div>
  332. <div class="comment" typeof="schema:UserComments">
  333. <p class="comment-meta">
  334. <span class="comment-author" property="schema:creator">Yann</span> le <span class="comment-date" property="schema:commentTime">21/06/2009</span> :
  335. </p>
  336. <div class="comment-content" property="schema:commentText">
  337. <p>Salut,</p>
  338. <p>je suis un développeur Python qui dispose de pas mal de temps libre devant lui et j&#39;aimerai bien jouer un peu avec les protéines. Léger problème : je manque cruellement de culture générale (pour l&#39;instant) à ce sujet.</p>
  339. <p>Par où (quelle documentation) pensez-vous que je devrais commencer pour, à terme, comprendre quelle protéïne fait quoi et pourquoi.</p>
  340. <p>Merci :)</p>
  341. </div>
  342. </div>
  343. <div class="comment" typeof="schema:UserComments">
  344. <p class="comment-meta">
  345. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">23/06/2009</span> :
  346. </p>
  347. <div class="comment-content" property="schema:commentText">
  348. <p>Hello Yann,</p>
  349. <p>Question difficile :)</p>
  350. <p>En fait ça dépend un peu de ta façon d&#39;apprendre, il y a 3 options à mon avis :</p>
  351. <p>* une formation, coûteux mais si les formateurs sont intéressants ça peut faire gagner un temps fou.<br />* un livre, je sais que &quot;le Campbell&quot; (du nom de son auteur) était notre bible en prépa. Mais il doit sûrement y avoir un peu plus accessible pour commencer.<br />* internet, les articles de wikipedia sont à mon avis un bon point de départ.</p>
  352. <p>Il y aurait peut-être une 4ème option qui serait de rencontrer des biologistes qui sont souvent intarissables sur le sujet et qui combineraient les 3 ;-).</p>
  353. <p>Bon courage !</p>
  354. </div>
  355. </div>
  356. <div class="comment" typeof="schema:UserComments">
  357. <p class="comment-meta">
  358. <span class="comment-author" property="schema:creator">Maamri sarra </span> le <span class="comment-date" property="schema:commentTime">26/10/2009</span> :
  359. </p>
  360. <div class="comment-content" property="schema:commentText">
  361. <p>bonjour ,<br />est ce que je peu avoir votre aide pour utilisé la classification CATCH dans le site PDB :et comment je lit les resultats</p>
  362. </div>
  363. </div>
  364. <div class="comment" typeof="schema:UserComments">
  365. <p class="comment-meta">
  366. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">26/10/2009</span> :
  367. </p>
  368. <div class="comment-content" property="schema:commentText">
  369. <p>Si le problème est suffisamment bien décrit pourquoi pas, puis ça te permettra peut-être de trouver la solution par toi-même d&#39;essayer de le formuler :-)</p>
  370. </div>
  371. </div>
  372. </div>
  373. </section>
  374. <footer>
  375. <nav>
  376. <p>
  377. <small>
  378. Je réponds quasiment toujours aux <a href="m&#x61;ilto:d&#x61;vid%40l&#x61;rlet&#46;fr" title="Envoyer un email">emails</a> (<a href="/david/signature/" title="Ma signature actuelle avec possibilité de chiffrement">signés</a>) et vous pouvez me rencontrer à Montréal. <span class="more-infos">N’hésitez pas à <a href="/david/log/" title="Être tenu informé des mises à jour">vous abonner</a> pour être tenu informé des publications récentes.</span>
  379. </small>
  380. </p>
  381. </nav>
  382. </footer>
  383. </div>
  384. <script src="/static/david/js/larlet-david-3ee43f.js" data-no-instant></script>
  385. <script data-no-instant>InstantClick.init()</script>
  386. </body>
  387. </html>