biotite 1.5.0__cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of biotite might be problematic. Click here for more details.

Files changed (354) hide show
  1. biotite/__init__.py +18 -0
  2. biotite/application/__init__.py +69 -0
  3. biotite/application/application.py +276 -0
  4. biotite/application/autodock/__init__.py +12 -0
  5. biotite/application/autodock/app.py +500 -0
  6. biotite/application/blast/__init__.py +14 -0
  7. biotite/application/blast/alignment.py +92 -0
  8. biotite/application/blast/webapp.py +428 -0
  9. biotite/application/clustalo/__init__.py +12 -0
  10. biotite/application/clustalo/app.py +223 -0
  11. biotite/application/dssp/__init__.py +12 -0
  12. biotite/application/dssp/app.py +216 -0
  13. biotite/application/localapp.py +342 -0
  14. biotite/application/mafft/__init__.py +12 -0
  15. biotite/application/mafft/app.py +116 -0
  16. biotite/application/msaapp.py +363 -0
  17. biotite/application/muscle/__init__.py +13 -0
  18. biotite/application/muscle/app3.py +227 -0
  19. biotite/application/muscle/app5.py +163 -0
  20. biotite/application/sra/__init__.py +18 -0
  21. biotite/application/sra/app.py +447 -0
  22. biotite/application/tantan/__init__.py +12 -0
  23. biotite/application/tantan/app.py +199 -0
  24. biotite/application/util.py +77 -0
  25. biotite/application/viennarna/__init__.py +18 -0
  26. biotite/application/viennarna/rnaalifold.py +310 -0
  27. biotite/application/viennarna/rnafold.py +254 -0
  28. biotite/application/viennarna/rnaplot.py +208 -0
  29. biotite/application/viennarna/util.py +77 -0
  30. biotite/application/webapp.py +76 -0
  31. biotite/copyable.py +71 -0
  32. biotite/database/__init__.py +23 -0
  33. biotite/database/afdb/__init__.py +12 -0
  34. biotite/database/afdb/download.py +197 -0
  35. biotite/database/entrez/__init__.py +15 -0
  36. biotite/database/entrez/check.py +60 -0
  37. biotite/database/entrez/dbnames.py +101 -0
  38. biotite/database/entrez/download.py +228 -0
  39. biotite/database/entrez/key.py +44 -0
  40. biotite/database/entrez/query.py +263 -0
  41. biotite/database/error.py +16 -0
  42. biotite/database/pubchem/__init__.py +21 -0
  43. biotite/database/pubchem/download.py +258 -0
  44. biotite/database/pubchem/error.py +30 -0
  45. biotite/database/pubchem/query.py +819 -0
  46. biotite/database/pubchem/throttle.py +98 -0
  47. biotite/database/rcsb/__init__.py +13 -0
  48. biotite/database/rcsb/download.py +161 -0
  49. biotite/database/rcsb/query.py +963 -0
  50. biotite/database/uniprot/__init__.py +13 -0
  51. biotite/database/uniprot/check.py +40 -0
  52. biotite/database/uniprot/download.py +126 -0
  53. biotite/database/uniprot/query.py +292 -0
  54. biotite/file.py +244 -0
  55. biotite/interface/__init__.py +19 -0
  56. biotite/interface/openmm/__init__.py +20 -0
  57. biotite/interface/openmm/state.py +93 -0
  58. biotite/interface/openmm/system.py +227 -0
  59. biotite/interface/pymol/__init__.py +201 -0
  60. biotite/interface/pymol/cgo.py +346 -0
  61. biotite/interface/pymol/convert.py +185 -0
  62. biotite/interface/pymol/display.py +267 -0
  63. biotite/interface/pymol/object.py +1228 -0
  64. biotite/interface/pymol/shapes.py +178 -0
  65. biotite/interface/pymol/startup.py +169 -0
  66. biotite/interface/rdkit/__init__.py +19 -0
  67. biotite/interface/rdkit/mol.py +490 -0
  68. biotite/interface/version.py +94 -0
  69. biotite/interface/warning.py +19 -0
  70. biotite/sequence/__init__.py +84 -0
  71. biotite/sequence/align/__init__.py +199 -0
  72. biotite/sequence/align/alignment.py +702 -0
  73. biotite/sequence/align/banded.cpython-311-x86_64-linux-gnu.so +0 -0
  74. biotite/sequence/align/banded.pyx +652 -0
  75. biotite/sequence/align/buckets.py +71 -0
  76. biotite/sequence/align/cigar.py +425 -0
  77. biotite/sequence/align/kmeralphabet.cpython-311-x86_64-linux-gnu.so +0 -0
  78. biotite/sequence/align/kmeralphabet.pyx +595 -0
  79. biotite/sequence/align/kmersimilarity.cpython-311-x86_64-linux-gnu.so +0 -0
  80. biotite/sequence/align/kmersimilarity.pyx +233 -0
  81. biotite/sequence/align/kmertable.cpython-311-x86_64-linux-gnu.so +0 -0
  82. biotite/sequence/align/kmertable.pyx +3411 -0
  83. biotite/sequence/align/localgapped.cpython-311-x86_64-linux-gnu.so +0 -0
  84. biotite/sequence/align/localgapped.pyx +892 -0
  85. biotite/sequence/align/localungapped.cpython-311-x86_64-linux-gnu.so +0 -0
  86. biotite/sequence/align/localungapped.pyx +279 -0
  87. biotite/sequence/align/matrix.py +631 -0
  88. biotite/sequence/align/matrix_data/3Di.mat +24 -0
  89. biotite/sequence/align/matrix_data/BLOSUM100.mat +31 -0
  90. biotite/sequence/align/matrix_data/BLOSUM30.mat +31 -0
  91. biotite/sequence/align/matrix_data/BLOSUM35.mat +31 -0
  92. biotite/sequence/align/matrix_data/BLOSUM40.mat +31 -0
  93. biotite/sequence/align/matrix_data/BLOSUM45.mat +31 -0
  94. biotite/sequence/align/matrix_data/BLOSUM50.mat +31 -0
  95. biotite/sequence/align/matrix_data/BLOSUM50_13p.mat +25 -0
  96. biotite/sequence/align/matrix_data/BLOSUM50_14.3.mat +25 -0
  97. biotite/sequence/align/matrix_data/BLOSUM50_5.0.mat +25 -0
  98. biotite/sequence/align/matrix_data/BLOSUM55.mat +31 -0
  99. biotite/sequence/align/matrix_data/BLOSUM60.mat +31 -0
  100. biotite/sequence/align/matrix_data/BLOSUM62.mat +31 -0
  101. biotite/sequence/align/matrix_data/BLOSUM62_13p.mat +25 -0
  102. biotite/sequence/align/matrix_data/BLOSUM62_14.3.mat +25 -0
  103. biotite/sequence/align/matrix_data/BLOSUM62_5.0.mat +25 -0
  104. biotite/sequence/align/matrix_data/BLOSUM65.mat +31 -0
  105. biotite/sequence/align/matrix_data/BLOSUM70.mat +31 -0
  106. biotite/sequence/align/matrix_data/BLOSUM75.mat +31 -0
  107. biotite/sequence/align/matrix_data/BLOSUM80.mat +31 -0
  108. biotite/sequence/align/matrix_data/BLOSUM85.mat +31 -0
  109. biotite/sequence/align/matrix_data/BLOSUM90.mat +31 -0
  110. biotite/sequence/align/matrix_data/BLOSUMN.mat +31 -0
  111. biotite/sequence/align/matrix_data/CorBLOSUM49_5.0.mat +25 -0
  112. biotite/sequence/align/matrix_data/CorBLOSUM57_13p.mat +25 -0
  113. biotite/sequence/align/matrix_data/CorBLOSUM57_14.3.mat +25 -0
  114. biotite/sequence/align/matrix_data/CorBLOSUM61_5.0.mat +25 -0
  115. biotite/sequence/align/matrix_data/CorBLOSUM66_13p.mat +25 -0
  116. biotite/sequence/align/matrix_data/CorBLOSUM67_14.3.mat +25 -0
  117. biotite/sequence/align/matrix_data/DAYHOFF.mat +32 -0
  118. biotite/sequence/align/matrix_data/GONNET.mat +26 -0
  119. biotite/sequence/align/matrix_data/IDENTITY.mat +25 -0
  120. biotite/sequence/align/matrix_data/MATCH.mat +25 -0
  121. biotite/sequence/align/matrix_data/NUC.mat +25 -0
  122. biotite/sequence/align/matrix_data/PAM10.mat +34 -0
  123. biotite/sequence/align/matrix_data/PAM100.mat +34 -0
  124. biotite/sequence/align/matrix_data/PAM110.mat +34 -0
  125. biotite/sequence/align/matrix_data/PAM120.mat +34 -0
  126. biotite/sequence/align/matrix_data/PAM130.mat +34 -0
  127. biotite/sequence/align/matrix_data/PAM140.mat +34 -0
  128. biotite/sequence/align/matrix_data/PAM150.mat +34 -0
  129. biotite/sequence/align/matrix_data/PAM160.mat +34 -0
  130. biotite/sequence/align/matrix_data/PAM170.mat +34 -0
  131. biotite/sequence/align/matrix_data/PAM180.mat +34 -0
  132. biotite/sequence/align/matrix_data/PAM190.mat +34 -0
  133. biotite/sequence/align/matrix_data/PAM20.mat +34 -0
  134. biotite/sequence/align/matrix_data/PAM200.mat +34 -0
  135. biotite/sequence/align/matrix_data/PAM210.mat +34 -0
  136. biotite/sequence/align/matrix_data/PAM220.mat +34 -0
  137. biotite/sequence/align/matrix_data/PAM230.mat +34 -0
  138. biotite/sequence/align/matrix_data/PAM240.mat +34 -0
  139. biotite/sequence/align/matrix_data/PAM250.mat +34 -0
  140. biotite/sequence/align/matrix_data/PAM260.mat +34 -0
  141. biotite/sequence/align/matrix_data/PAM270.mat +34 -0
  142. biotite/sequence/align/matrix_data/PAM280.mat +34 -0
  143. biotite/sequence/align/matrix_data/PAM290.mat +34 -0
  144. biotite/sequence/align/matrix_data/PAM30.mat +34 -0
  145. biotite/sequence/align/matrix_data/PAM300.mat +34 -0
  146. biotite/sequence/align/matrix_data/PAM310.mat +34 -0
  147. biotite/sequence/align/matrix_data/PAM320.mat +34 -0
  148. biotite/sequence/align/matrix_data/PAM330.mat +34 -0
  149. biotite/sequence/align/matrix_data/PAM340.mat +34 -0
  150. biotite/sequence/align/matrix_data/PAM350.mat +34 -0
  151. biotite/sequence/align/matrix_data/PAM360.mat +34 -0
  152. biotite/sequence/align/matrix_data/PAM370.mat +34 -0
  153. biotite/sequence/align/matrix_data/PAM380.mat +34 -0
  154. biotite/sequence/align/matrix_data/PAM390.mat +34 -0
  155. biotite/sequence/align/matrix_data/PAM40.mat +34 -0
  156. biotite/sequence/align/matrix_data/PAM400.mat +34 -0
  157. biotite/sequence/align/matrix_data/PAM410.mat +34 -0
  158. biotite/sequence/align/matrix_data/PAM420.mat +34 -0
  159. biotite/sequence/align/matrix_data/PAM430.mat +34 -0
  160. biotite/sequence/align/matrix_data/PAM440.mat +34 -0
  161. biotite/sequence/align/matrix_data/PAM450.mat +34 -0
  162. biotite/sequence/align/matrix_data/PAM460.mat +34 -0
  163. biotite/sequence/align/matrix_data/PAM470.mat +34 -0
  164. biotite/sequence/align/matrix_data/PAM480.mat +34 -0
  165. biotite/sequence/align/matrix_data/PAM490.mat +34 -0
  166. biotite/sequence/align/matrix_data/PAM50.mat +34 -0
  167. biotite/sequence/align/matrix_data/PAM500.mat +34 -0
  168. biotite/sequence/align/matrix_data/PAM60.mat +34 -0
  169. biotite/sequence/align/matrix_data/PAM70.mat +34 -0
  170. biotite/sequence/align/matrix_data/PAM80.mat +34 -0
  171. biotite/sequence/align/matrix_data/PAM90.mat +34 -0
  172. biotite/sequence/align/matrix_data/PB.license +21 -0
  173. biotite/sequence/align/matrix_data/PB.mat +18 -0
  174. biotite/sequence/align/matrix_data/RBLOSUM52_5.0.mat +25 -0
  175. biotite/sequence/align/matrix_data/RBLOSUM59_13p.mat +25 -0
  176. biotite/sequence/align/matrix_data/RBLOSUM59_14.3.mat +25 -0
  177. biotite/sequence/align/matrix_data/RBLOSUM64_5.0.mat +25 -0
  178. biotite/sequence/align/matrix_data/RBLOSUM69_13p.mat +25 -0
  179. biotite/sequence/align/matrix_data/RBLOSUM69_14.3.mat +25 -0
  180. biotite/sequence/align/multiple.cpython-311-x86_64-linux-gnu.so +0 -0
  181. biotite/sequence/align/multiple.pyx +619 -0
  182. biotite/sequence/align/pairwise.cpython-311-x86_64-linux-gnu.so +0 -0
  183. biotite/sequence/align/pairwise.pyx +585 -0
  184. biotite/sequence/align/permutation.cpython-311-x86_64-linux-gnu.so +0 -0
  185. biotite/sequence/align/permutation.pyx +313 -0
  186. biotite/sequence/align/primes.txt +821 -0
  187. biotite/sequence/align/selector.cpython-311-x86_64-linux-gnu.so +0 -0
  188. biotite/sequence/align/selector.pyx +954 -0
  189. biotite/sequence/align/statistics.py +264 -0
  190. biotite/sequence/align/tracetable.cpython-311-x86_64-linux-gnu.so +0 -0
  191. biotite/sequence/align/tracetable.pxd +64 -0
  192. biotite/sequence/align/tracetable.pyx +370 -0
  193. biotite/sequence/alphabet.py +555 -0
  194. biotite/sequence/annotation.py +836 -0
  195. biotite/sequence/codec.cpython-311-x86_64-linux-gnu.so +0 -0
  196. biotite/sequence/codec.pyx +155 -0
  197. biotite/sequence/codon.py +476 -0
  198. biotite/sequence/codon_tables.txt +202 -0
  199. biotite/sequence/graphics/__init__.py +33 -0
  200. biotite/sequence/graphics/alignment.py +1101 -0
  201. biotite/sequence/graphics/color_schemes/3di_flower.json +48 -0
  202. biotite/sequence/graphics/color_schemes/autumn.json +51 -0
  203. biotite/sequence/graphics/color_schemes/blossom.json +51 -0
  204. biotite/sequence/graphics/color_schemes/clustalx_dna.json +11 -0
  205. biotite/sequence/graphics/color_schemes/clustalx_protein.json +28 -0
  206. biotite/sequence/graphics/color_schemes/flower.json +51 -0
  207. biotite/sequence/graphics/color_schemes/jalview_buried.json +31 -0
  208. biotite/sequence/graphics/color_schemes/jalview_hydrophobicity.json +31 -0
  209. biotite/sequence/graphics/color_schemes/jalview_prop_helix.json +31 -0
  210. biotite/sequence/graphics/color_schemes/jalview_prop_strand.json +31 -0
  211. biotite/sequence/graphics/color_schemes/jalview_prop_turn.json +31 -0
  212. biotite/sequence/graphics/color_schemes/jalview_taylor.json +28 -0
  213. biotite/sequence/graphics/color_schemes/jalview_zappo.json +28 -0
  214. biotite/sequence/graphics/color_schemes/ocean.json +51 -0
  215. biotite/sequence/graphics/color_schemes/pb_flower.json +40 -0
  216. biotite/sequence/graphics/color_schemes/rainbow_dna.json +11 -0
  217. biotite/sequence/graphics/color_schemes/rainbow_protein.json +30 -0
  218. biotite/sequence/graphics/color_schemes/spring.json +51 -0
  219. biotite/sequence/graphics/color_schemes/sunset.json +51 -0
  220. biotite/sequence/graphics/color_schemes/wither.json +51 -0
  221. biotite/sequence/graphics/colorschemes.py +170 -0
  222. biotite/sequence/graphics/dendrogram.py +231 -0
  223. biotite/sequence/graphics/features.py +544 -0
  224. biotite/sequence/graphics/logo.py +102 -0
  225. biotite/sequence/graphics/plasmid.py +712 -0
  226. biotite/sequence/io/__init__.py +12 -0
  227. biotite/sequence/io/fasta/__init__.py +22 -0
  228. biotite/sequence/io/fasta/convert.py +283 -0
  229. biotite/sequence/io/fasta/file.py +265 -0
  230. biotite/sequence/io/fastq/__init__.py +19 -0
  231. biotite/sequence/io/fastq/convert.py +117 -0
  232. biotite/sequence/io/fastq/file.py +507 -0
  233. biotite/sequence/io/genbank/__init__.py +17 -0
  234. biotite/sequence/io/genbank/annotation.py +269 -0
  235. biotite/sequence/io/genbank/file.py +573 -0
  236. biotite/sequence/io/genbank/metadata.py +336 -0
  237. biotite/sequence/io/genbank/sequence.py +173 -0
  238. biotite/sequence/io/general.py +201 -0
  239. biotite/sequence/io/gff/__init__.py +26 -0
  240. biotite/sequence/io/gff/convert.py +128 -0
  241. biotite/sequence/io/gff/file.py +449 -0
  242. biotite/sequence/phylo/__init__.py +36 -0
  243. biotite/sequence/phylo/nj.cpython-311-x86_64-linux-gnu.so +0 -0
  244. biotite/sequence/phylo/nj.pyx +221 -0
  245. biotite/sequence/phylo/tree.cpython-311-x86_64-linux-gnu.so +0 -0
  246. biotite/sequence/phylo/tree.pyx +1169 -0
  247. biotite/sequence/phylo/upgma.cpython-311-x86_64-linux-gnu.so +0 -0
  248. biotite/sequence/phylo/upgma.pyx +164 -0
  249. biotite/sequence/profile.py +561 -0
  250. biotite/sequence/search.py +117 -0
  251. biotite/sequence/seqtypes.py +720 -0
  252. biotite/sequence/sequence.py +373 -0
  253. biotite/setup_ccd.py +197 -0
  254. biotite/structure/__init__.py +135 -0
  255. biotite/structure/alphabet/__init__.py +25 -0
  256. biotite/structure/alphabet/encoder.py +332 -0
  257. biotite/structure/alphabet/encoder_weights_3di.kerasify +0 -0
  258. biotite/structure/alphabet/i3d.py +109 -0
  259. biotite/structure/alphabet/layers.py +86 -0
  260. biotite/structure/alphabet/pb.license +21 -0
  261. biotite/structure/alphabet/pb.py +170 -0
  262. biotite/structure/alphabet/unkerasify.py +128 -0
  263. biotite/structure/atoms.py +1562 -0
  264. biotite/structure/basepairs.py +1403 -0
  265. biotite/structure/bonds.cpython-311-x86_64-linux-gnu.so +0 -0
  266. biotite/structure/bonds.pyx +2036 -0
  267. biotite/structure/box.py +724 -0
  268. biotite/structure/celllist.cpython-311-x86_64-linux-gnu.so +0 -0
  269. biotite/structure/celllist.pyx +864 -0
  270. biotite/structure/chains.py +310 -0
  271. biotite/structure/charges.cpython-311-x86_64-linux-gnu.so +0 -0
  272. biotite/structure/charges.pyx +520 -0
  273. biotite/structure/compare.py +683 -0
  274. biotite/structure/density.py +109 -0
  275. biotite/structure/dotbracket.py +213 -0
  276. biotite/structure/error.py +39 -0
  277. biotite/structure/filter.py +591 -0
  278. biotite/structure/geometry.py +817 -0
  279. biotite/structure/graphics/__init__.py +13 -0
  280. biotite/structure/graphics/atoms.py +243 -0
  281. biotite/structure/graphics/rna.py +298 -0
  282. biotite/structure/hbond.py +425 -0
  283. biotite/structure/info/__init__.py +24 -0
  284. biotite/structure/info/atom_masses.json +121 -0
  285. biotite/structure/info/atoms.py +98 -0
  286. biotite/structure/info/bonds.py +149 -0
  287. biotite/structure/info/ccd.py +200 -0
  288. biotite/structure/info/components.bcif +0 -0
  289. biotite/structure/info/groups.py +128 -0
  290. biotite/structure/info/masses.py +121 -0
  291. biotite/structure/info/misc.py +137 -0
  292. biotite/structure/info/radii.py +267 -0
  293. biotite/structure/info/standardize.py +185 -0
  294. biotite/structure/integrity.py +213 -0
  295. biotite/structure/io/__init__.py +29 -0
  296. biotite/structure/io/dcd/__init__.py +13 -0
  297. biotite/structure/io/dcd/file.py +67 -0
  298. biotite/structure/io/general.py +243 -0
  299. biotite/structure/io/gro/__init__.py +14 -0
  300. biotite/structure/io/gro/file.py +343 -0
  301. biotite/structure/io/mol/__init__.py +20 -0
  302. biotite/structure/io/mol/convert.py +112 -0
  303. biotite/structure/io/mol/ctab.py +420 -0
  304. biotite/structure/io/mol/header.py +120 -0
  305. biotite/structure/io/mol/mol.py +149 -0
  306. biotite/structure/io/mol/sdf.py +940 -0
  307. biotite/structure/io/netcdf/__init__.py +13 -0
  308. biotite/structure/io/netcdf/file.py +64 -0
  309. biotite/structure/io/pdb/__init__.py +20 -0
  310. biotite/structure/io/pdb/convert.py +389 -0
  311. biotite/structure/io/pdb/file.py +1380 -0
  312. biotite/structure/io/pdb/hybrid36.cpython-311-x86_64-linux-gnu.so +0 -0
  313. biotite/structure/io/pdb/hybrid36.pyx +242 -0
  314. biotite/structure/io/pdbqt/__init__.py +15 -0
  315. biotite/structure/io/pdbqt/convert.py +113 -0
  316. biotite/structure/io/pdbqt/file.py +688 -0
  317. biotite/structure/io/pdbx/__init__.py +23 -0
  318. biotite/structure/io/pdbx/bcif.py +674 -0
  319. biotite/structure/io/pdbx/cif.py +1091 -0
  320. biotite/structure/io/pdbx/component.py +251 -0
  321. biotite/structure/io/pdbx/compress.py +362 -0
  322. biotite/structure/io/pdbx/convert.py +2113 -0
  323. biotite/structure/io/pdbx/encoding.cpython-311-x86_64-linux-gnu.so +0 -0
  324. biotite/structure/io/pdbx/encoding.pyx +1078 -0
  325. biotite/structure/io/trajfile.py +696 -0
  326. biotite/structure/io/trr/__init__.py +13 -0
  327. biotite/structure/io/trr/file.py +43 -0
  328. biotite/structure/io/util.py +38 -0
  329. biotite/structure/io/xtc/__init__.py +13 -0
  330. biotite/structure/io/xtc/file.py +43 -0
  331. biotite/structure/mechanics.py +72 -0
  332. biotite/structure/molecules.py +337 -0
  333. biotite/structure/pseudoknots.py +622 -0
  334. biotite/structure/rdf.py +245 -0
  335. biotite/structure/repair.py +302 -0
  336. biotite/structure/residues.py +716 -0
  337. biotite/structure/rings.py +451 -0
  338. biotite/structure/sasa.cpython-311-x86_64-linux-gnu.so +0 -0
  339. biotite/structure/sasa.pyx +322 -0
  340. biotite/structure/segments.py +328 -0
  341. biotite/structure/sequence.py +110 -0
  342. biotite/structure/spacegroups.json +1567 -0
  343. biotite/structure/spacegroups.license +26 -0
  344. biotite/structure/sse.py +306 -0
  345. biotite/structure/superimpose.py +511 -0
  346. biotite/structure/tm.py +581 -0
  347. biotite/structure/transform.py +736 -0
  348. biotite/structure/util.py +160 -0
  349. biotite/version.py +34 -0
  350. biotite/visualize.py +375 -0
  351. biotite-1.5.0.dist-info/METADATA +162 -0
  352. biotite-1.5.0.dist-info/RECORD +354 -0
  353. biotite-1.5.0.dist-info/WHEEL +6 -0
  354. biotite-1.5.0.dist-info/licenses/LICENSE.rst +30 -0
@@ -0,0 +1,451 @@
1
+ # This source code is part of the Biotite package and is distributed
2
+ # under the 3-Clause BSD License. Please see 'LICENSE.rst' for further
3
+ # information.
4
+
5
+ """
6
+ This module provides functions related to aromatic rings.
7
+ """
8
+
9
+ __name__ = "biotite.structure"
10
+ __author__ = "Patrick Kunzmann"
11
+ __all__ = [
12
+ "find_aromatic_rings",
13
+ "find_stacking_interactions",
14
+ "find_pi_cation_interactions",
15
+ "PiStacking",
16
+ ]
17
+
18
+
19
+ from enum import IntEnum
20
+ import networkx as nx
21
+ import numpy as np
22
+ from biotite.structure.bonds import BondType
23
+ from biotite.structure.error import BadStructureError
24
+ from biotite.structure.geometry import displacement
25
+ from biotite.structure.util import norm_vector, vector_dot
26
+
27
+
28
+ class PiStacking(IntEnum):
29
+ """
30
+ The type of pi-stacking interaction.
31
+
32
+ - ``PARALLEL``: parallel pi-stacking (also called *staggered* or *Sandwich*)
33
+ - ``PERPENDICULAR``: perpendicular pi-stacking (also called *T-shaped*)
34
+ """
35
+
36
+ PARALLEL = 0
37
+ PERPENDICULAR = 1
38
+
39
+
40
+ def find_aromatic_rings(atoms):
41
+ """
42
+ Find (anti-)aromatic rings in a structure.
43
+
44
+ Parameters
45
+ ----------
46
+ atoms : AtomArray or AtomArrayStack
47
+ The atoms to be searched for aromatic rings.
48
+ Requires an associated :class:`BondList`.
49
+
50
+ Returns
51
+ -------
52
+ rings : list of ndarray
53
+ The indices of the atoms that form aromatic rings.
54
+ Each ring is represented by a list of indices.
55
+ Only rings with minimum size are returned, i.e. two connected rings
56
+ (e.g. in tryptophan) are reported as separate rings.
57
+
58
+ Notes
59
+ -----
60
+ This function does not distinguish between aromatic and antiaromatic rings.
61
+ All cycles containing atoms that are completely connected by aromatic bonds
62
+ are considered aromatic rings.
63
+
64
+ The PDB *Chemical Component Dictionary* (CCD) does not identify aromatic rings in
65
+ all compounds as such.
66
+ Prominent examples are the nucleobases, where the 6-membered rings are not
67
+ flagged as aromatic.
68
+
69
+ Examples
70
+ --------
71
+
72
+ >>> nad = residue("NAD")
73
+ >>> rings = find_aromatic_rings(nad)
74
+ >>> print(rings)
75
+ [array([41, 37, 36, 35, 43, 42]), array([19, 18, 16, 15, 21, 20]), array([12, 13, 14, 15, 21])]
76
+ >>> for atom_indices in rings:
77
+ ... print(np.sort(nad.atom_name[atom_indices]))
78
+ ['C2N' 'C3N' 'C4N' 'C5N' 'C6N' 'N1N']
79
+ ['C2A' 'C4A' 'C5A' 'C6A' 'N1A' 'N3A']
80
+ ['C4A' 'C5A' 'C8A' 'N7A' 'N9A']
81
+ """
82
+ if atoms.bonds is None:
83
+ raise BadStructureError("Structure must have an associated BondList")
84
+ bond_array = atoms.bonds.as_array()
85
+ # To detect aromatic rings, only keep bonds that are aromatic
86
+ aromatic_bond_array = bond_array[
87
+ np.isin(
88
+ bond_array[:, 2],
89
+ [
90
+ BondType.AROMATIC,
91
+ BondType.AROMATIC_SINGLE,
92
+ BondType.AROMATIC_DOUBLE,
93
+ BondType.AROMATIC_TRIPLE,
94
+ ],
95
+ ),
96
+ # We can omit the bond type now
97
+ :2,
98
+ ]
99
+ aromatic_bond_graph = nx.from_edgelist(aromatic_bond_array.tolist())
100
+ # Find the cycles with minimum size -> cycle basis
101
+ rings = nx.cycle_basis(aromatic_bond_graph)
102
+ return [np.array(ring, dtype=int) for ring in rings]
103
+
104
+
105
+ def find_stacking_interactions(
106
+ atoms,
107
+ centroid_cutoff=6.5,
108
+ plane_angle_tol=np.deg2rad(30.0),
109
+ shift_angle_tol=np.deg2rad(30.0),
110
+ ):
111
+ """
112
+ Find pi-stacking interactions between aromatic rings.
113
+
114
+ Parameters
115
+ ----------
116
+ atoms : AtomArray
117
+ The atoms to be searched for aromatic rings.
118
+ Requires an associated :class:`BondList`.
119
+ centroid_cutoff : float
120
+ The cutoff distance for ring centroids.
121
+ plane_angle_tol : float
122
+ The tolerance for the angle between ring planes that must be either
123
+ parallel or perpendicular.
124
+ Given in radians.
125
+ shift_angle_tol : float
126
+ The tolerance for the angle between the ring plane normals and the
127
+ centroid difference vector.
128
+ Given in radians.
129
+
130
+ Returns
131
+ -------
132
+ interactions : list of tuple(ndarray, ndarray, PiStacking)
133
+ The stacking interactions between aromatic rings.
134
+ Each element in the list represents one stacking interaction.
135
+ The first two elements of each tuple represent atom indices of the stacked
136
+ rings.
137
+ The third element of each tuple is the type of stacking interaction.
138
+
139
+ See Also
140
+ --------
141
+ find_aromatic_rings : Used for finding the aromatic rings in this function.
142
+
143
+ Notes
144
+ -----
145
+ This function does not distinguish between aromatic and antiaromatic rings.
146
+ Furthermore, it does not distinguish between repulsive and attractive stacking:
147
+ Usually, stacking two rings directly above each other is repulsive, as the pi
148
+ orbitals above the rings repel each other, so a slight horizontal shift is
149
+ usually required to make the interaction attractive.
150
+ However, in details this is strongly dependent on heteroatoms and the exact
151
+ orientation of the rings.
152
+ Hence, this function aggregates all stacking interactions to simplify the
153
+ conditions for pi-stacking.
154
+
155
+ The conditions for pi-stacking are :footcite:`Wojcikowski2015` :
156
+
157
+ - The ring centroids must be within cutoff `centroid_cutoff` distance.
158
+ While :footcite:`Wojcikowski2015` uses a cutoff of 5.0 Å, 6.5 Å was
159
+ adopted from :footcite:`Bouysset2021` to better identify perpendicular
160
+ stacking interactions.
161
+ - The planes must be parallel or perpendicular to each other within a default
162
+ tolerance of 30°.
163
+ - The angle between the plane normals and the centroid difference vector must be
164
+ be either 0° or 90° within a default tolerance of 30°, to check for lateral
165
+ shifts.
166
+
167
+ References
168
+ ----------
169
+
170
+ .. footbibliography::
171
+
172
+ Examples
173
+ --------
174
+
175
+ Detect base stacking interactions in a DNA helix
176
+
177
+ >>> from os.path import join
178
+ >>> dna_helix = load_structure(
179
+ ... join(path_to_structures, "base_pairs", "1qxb.cif"), include_bonds=True
180
+ ... )
181
+ >>> interactions = find_stacking_interactions(dna_helix)
182
+ >>> for ring_atom_indices_1, ring_atom_indices_2, stacking_type in interactions:
183
+ ... print(
184
+ ... dna_helix.res_id[ring_atom_indices_1[0]],
185
+ ... dna_helix.res_id[ring_atom_indices_2[0]],
186
+ ... PiStacking(stacking_type).name
187
+ ... )
188
+ 17 18 PARALLEL
189
+ 17 18 PARALLEL
190
+ 5 6 PARALLEL
191
+ 5 6 PARALLEL
192
+ 5 6 PARALLEL
193
+ """
194
+ rings = find_aromatic_rings(atoms)
195
+ if len(rings) == 0:
196
+ return []
197
+
198
+ ring_centroids = np.array(
199
+ [atoms.coord[atom_indices].mean(axis=0) for atom_indices in rings]
200
+ )
201
+ ring_normals = np.array(
202
+ [_get_ring_normal(atoms.coord[atom_indices]) for atom_indices in rings]
203
+ )
204
+
205
+ # Create an index array that contains the Cartesian product of all rings
206
+ indices = np.stack(
207
+ [
208
+ np.repeat(np.arange(len(rings)), len(rings)),
209
+ np.tile(np.arange(len(rings)), len(rings)),
210
+ ],
211
+ axis=-1,
212
+ )
213
+ # Do not include duplicate pairs
214
+ indices = indices[indices[:, 0] > indices[:, 1]]
215
+
216
+ ## Condition 1: Ring centroids are close enough to each other
217
+ diff = displacement(ring_centroids[indices[:, 0]], ring_centroids[indices[:, 1]])
218
+ # Use squared distance to avoid time consuming sqrt computation
219
+ sq_distance = vector_dot(diff, diff)
220
+ is_interacting = sq_distance < centroid_cutoff**2
221
+ indices = indices[is_interacting]
222
+
223
+ ## Condition 2: Ring planes are parallel or perpendicular
224
+ plane_angles = _minimum_angle(
225
+ ring_normals[indices[:, 0]], ring_normals[indices[:, 1]]
226
+ )
227
+ is_parallel = _is_within_tolerance(plane_angles, 0, plane_angle_tol)
228
+ is_perpendicular = _is_within_tolerance(plane_angles, np.pi / 2, plane_angle_tol)
229
+ is_interacting = is_parallel | is_perpendicular
230
+ indices = indices[is_interacting]
231
+ # Keep in sync with the shape of the filtered indices,
232
+ # i.e. after filtering, `is_parallel==False` means a perpendicular interaction
233
+ is_parallel = is_parallel[is_interacting]
234
+
235
+ ## Condition 3: The ring centroids are not shifted too much
236
+ ## (in terms of normal-centroid angle)
237
+ diff = displacement(ring_centroids[indices[:, 0]], ring_centroids[indices[:, 1]])
238
+ norm_vector(diff)
239
+ angles = np.stack(
240
+ [_minimum_angle(ring_normals[indices[:, i]], diff) for i in range(2)]
241
+ )
242
+ is_interacting = (
243
+ # For parallel stacking, the lateral shift may not exceed the tolerance
244
+ (is_parallel & np.any(_is_within_tolerance(angles, 0, shift_angle_tol), axis=0))
245
+ # For perpendicular stacking, one ring must be above the other,
246
+ # but from the perspective of the other ring, the first ring is approximately
247
+ # in the same plane
248
+ | (
249
+ ~is_parallel
250
+ & (
251
+ (
252
+ _is_within_tolerance(angles[0], 0, shift_angle_tol)
253
+ & _is_within_tolerance(angles[1], np.pi / 2, shift_angle_tol)
254
+ )
255
+ | (
256
+ _is_within_tolerance(angles[0], np.pi / 2, shift_angle_tol)
257
+ & _is_within_tolerance(angles[1], 0, shift_angle_tol)
258
+ )
259
+ )
260
+ )
261
+ )
262
+ indices = indices[is_interacting]
263
+ is_parallel = is_parallel[is_interacting]
264
+
265
+ # Only return pairs of rings where all conditions were fulfilled
266
+ return [
267
+ (
268
+ rings[ring_i],
269
+ rings[ring_j],
270
+ PiStacking.PARALLEL if is_parallel[i] else PiStacking.PERPENDICULAR,
271
+ )
272
+ for i, (ring_i, ring_j) in enumerate(indices)
273
+ ]
274
+
275
+
276
+ def find_pi_cation_interactions(
277
+ atoms,
278
+ distance_cutoff=5.0,
279
+ angle_tol=np.deg2rad(30.0),
280
+ ):
281
+ """
282
+ Find pi-cation interactions between aromatic rings and cations.
283
+
284
+ Parameters
285
+ ----------
286
+ atoms : AtomArray
287
+ The atoms to be searched for pi-cation interactions.
288
+ Requires an associated :class:`BondList` and ``charge`` annotation.
289
+ distance_cutoff : float, optional
290
+ The cutoff distance between ring centroid and cation.
291
+ angle_tol : float, optional
292
+ The tolerance for the angle between the ring plane normal
293
+ and the centroid-cation vector. Perfect pi-cation interaction
294
+ has 0° angle (perpendicular to ring plane).
295
+ Given in radians.
296
+
297
+ Returns
298
+ -------
299
+ interactions : list of tuple(ndarray, int)
300
+ The pi-cation interactions between aromatic rings and cations.
301
+ Each element in the list represents one pi-cation interaction.
302
+ The first element of each tuple represents atom indices of the
303
+ aromatic ring, the second element is the atom index of the cation.
304
+
305
+ See Also
306
+ --------
307
+ find_aromatic_rings : Used for finding the aromatic rings in this function.
308
+ find_stacking_interactions : Find pi-stacking interactions between rings.
309
+
310
+ Notes
311
+ -----
312
+ The conditions for pi-cation interactions are:
313
+ - The distance between ring centroid and cation must be within
314
+ `distance_cutoff`. :footcite:`Wojcikowski2015` uses 5.0 Å,
315
+ whereas :footcite:`Bouysset2021` uses 4.5 Å.
316
+ - The angle between the ring plane normal and the centroid-cation
317
+ vector must be within `angle_tol` of 0° (perpendicular to plane).
318
+
319
+ Examples
320
+ --------
321
+ >>> from os.path import join
322
+ >>> structure = load_structure(join(path_to_structures, "3wip.cif"), include_bonds=True, extra_fields=["charge"])
323
+ >>> interactions = find_pi_cation_interactions(structure)
324
+ >>> for ring_indices, cation_index in interactions:
325
+ ... print(
326
+ ... structure.res_name[ring_indices[0]],
327
+ ... structure.res_name[cation_index]
328
+ ... )
329
+ TYR ACH
330
+ TRP ACH
331
+ """
332
+ if atoms.bonds is None:
333
+ raise BadStructureError("Structure must have an associated BondList")
334
+
335
+ if atoms.charge is None:
336
+ raise BadStructureError(
337
+ "Structure must have a 'charge' annotation to identify cations."
338
+ )
339
+
340
+ rings = find_aromatic_rings(atoms)
341
+ if len(rings) == 0:
342
+ return []
343
+
344
+ cation_mask = atoms.charge > 0
345
+ cation_indices = np.where(cation_mask)[0]
346
+
347
+ if len(cation_indices) == 0:
348
+ return []
349
+
350
+ # Calculate ring centroids and normals
351
+ ring_centroids = np.array(
352
+ [atoms.coord[atom_indices].mean(axis=0) for atom_indices in rings]
353
+ )
354
+ ring_normals = np.array(
355
+ [_get_ring_normal(atoms.coord[atom_indices]) for atom_indices in rings]
356
+ )
357
+
358
+ cation_coords = atoms.coord[cation_indices]
359
+
360
+ # Create an index array that contains the Cartesian product of all rings and cations
361
+ indices = np.stack(
362
+ [
363
+ np.repeat(np.arange(len(rings)), len(cation_indices)),
364
+ np.tile(np.arange(len(cation_indices)), len(rings)),
365
+ ],
366
+ axis=-1,
367
+ )
368
+
369
+ ## Condition 1: Ring centroids and cations are close enough to each other
370
+ diff = displacement(ring_centroids[indices[:, 0]], cation_coords[indices[:, 1]])
371
+ # Use squared distance to avoid time consuming sqrt computation
372
+ sq_distance = vector_dot(diff, diff)
373
+ is_interacting = sq_distance < distance_cutoff**2
374
+ indices = indices[is_interacting]
375
+
376
+ ## Condition 2: Angle between ring normal and centroid-cation vector
377
+ diff = displacement(ring_centroids[indices[:, 0]], cation_coords[indices[:, 1]])
378
+ norm_vector(diff)
379
+ angles = _minimum_angle(ring_normals[indices[:, 0]], diff)
380
+ is_interacting = _is_within_tolerance(angles, 0, angle_tol)
381
+ indices = indices[is_interacting]
382
+
383
+ # Only return pairs where all conditions were fulfilled
384
+ return [(rings[ring_i], cation_indices[cation_j]) for ring_i, cation_j in indices]
385
+
386
+
387
+ def _get_ring_normal(ring_coord):
388
+ """
389
+ Get the normal vector perpendicular to the ring plane.
390
+
391
+ Parameters
392
+ ----------
393
+ ring_coord : ndarray
394
+ The coordinates of the atoms in the ring.
395
+
396
+ Returns
397
+ -------
398
+ normal : ndarray
399
+ The normal vector of the ring plane.
400
+ """
401
+ # Simply use any three atoms in the ring to calculate the normal vector
402
+ # We can also safely assume that there are at least three atoms in the ring,
403
+ # as otherwise it would not be a ring
404
+ normal = np.cross(ring_coord[1] - ring_coord[0], ring_coord[2] - ring_coord[0])
405
+ norm_vector(normal)
406
+ return normal
407
+
408
+
409
+ def _minimum_angle(v1, v2):
410
+ """
411
+ Get the minimum angle between two vectors, i.e. the possible angle range is
412
+ ``[0, pi/2]``.
413
+
414
+ Parameters
415
+ ----------
416
+ v1, v2 : ndarray, shape=(n,3), dtype=float
417
+ The vectors to measure the angle between.
418
+
419
+ Returns
420
+ -------
421
+ angle : ndarray, shape=(n,), dtype=float
422
+ The minimum angle between the two vectors.
423
+
424
+ Notes
425
+ -----
426
+ This restriction is added here as the normal vectors of the ring planes
427
+ have no 'preferred side'.
428
+ """
429
+ # Do not distinguish between the 'sides' of the rings -> take absolute of cosine
430
+ return np.arccos(np.abs(vector_dot(v1, v2)))
431
+
432
+
433
+ def _is_within_tolerance(angles, expected_angle, tolerance):
434
+ """
435
+ Check if the angles are within a certain tolerance.
436
+
437
+ Parameters
438
+ ----------
439
+ angles : ndarray, shape=x, dtype=float
440
+ The angles to check.
441
+ expected_angle : float
442
+ The expected angle.
443
+ tolerance : float
444
+ The tolerance.
445
+
446
+ Returns
447
+ -------
448
+ is_within_tolerance : ndarray, shape=x, dtype=bool
449
+ True if the angles are within the tolerance, False otherwise.
450
+ """
451
+ return np.abs(angles - expected_angle) < tolerance