biotite 1.6.0__cp314-cp314-win_amd64.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.
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 +426 -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 +202 -0
  35. biotite/database/entrez/__init__.py +15 -0
  36. biotite/database/entrez/check.py +66 -0
  37. biotite/database/entrez/dbnames.py +101 -0
  38. biotite/database/entrez/download.py +224 -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 +259 -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 +191 -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 +127 -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 +491 -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 +763 -0
  73. biotite/sequence/align/banded.cp314-win_amd64.pyd +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.cp314-win_amd64.pyd +0 -0
  78. biotite/sequence/align/kmeralphabet.pyx +595 -0
  79. biotite/sequence/align/kmersimilarity.cp314-win_amd64.pyd +0 -0
  80. biotite/sequence/align/kmersimilarity.pyx +233 -0
  81. biotite/sequence/align/kmertable.cp314-win_amd64.pyd +0 -0
  82. biotite/sequence/align/kmertable.pyx +3411 -0
  83. biotite/sequence/align/localgapped.cp314-win_amd64.pyd +0 -0
  84. biotite/sequence/align/localgapped.pyx +892 -0
  85. biotite/sequence/align/localungapped.cp314-win_amd64.pyd +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.cp314-win_amd64.pyd +0 -0
  181. biotite/sequence/align/multiple.pyx +619 -0
  182. biotite/sequence/align/pairwise.cp314-win_amd64.pyd +0 -0
  183. biotite/sequence/align/pairwise.pyx +585 -0
  184. biotite/sequence/align/permutation.cp314-win_amd64.pyd +0 -0
  185. biotite/sequence/align/permutation.pyx +313 -0
  186. biotite/sequence/align/primes.txt +821 -0
  187. biotite/sequence/align/selector.cp314-win_amd64.pyd +0 -0
  188. biotite/sequence/align/selector.pyx +954 -0
  189. biotite/sequence/align/statistics.py +264 -0
  190. biotite/sequence/align/tracetable.cp314-win_amd64.pyd +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.cp314-win_amd64.pyd +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 +462 -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.cp314-win_amd64.pyd +0 -0
  244. biotite/sequence/phylo/nj.pyx +221 -0
  245. biotite/sequence/phylo/tree.cp314-win_amd64.pyd +0 -0
  246. biotite/sequence/phylo/tree.pyx +1169 -0
  247. biotite/sequence/phylo/upgma.cp314-win_amd64.pyd +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 +1596 -0
  264. biotite/structure/basepairs.py +1403 -0
  265. biotite/structure/bonds.cp314-win_amd64.pyd +0 -0
  266. biotite/structure/bonds.pyx +2036 -0
  267. biotite/structure/box.py +724 -0
  268. biotite/structure/celllist.cp314-win_amd64.pyd +0 -0
  269. biotite/structure/celllist.pyx +864 -0
  270. biotite/structure/chains.py +310 -0
  271. biotite/structure/charges.cp314-win_amd64.pyd +0 -0
  272. biotite/structure/charges.pyx +521 -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 +646 -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 +426 -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.cp314-win_amd64.pyd +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 +2122 -0
  323. biotite/structure/io/pdbx/encoding.cp314-win_amd64.pyd +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 +452 -0
  338. biotite/structure/sasa.cp314-win_amd64.pyd +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.6.0.dist-info/METADATA +162 -0
  352. biotite-1.6.0.dist-info/RECORD +354 -0
  353. biotite-1.6.0.dist-info/WHEEL +4 -0
  354. biotite-1.6.0.dist-info/licenses/LICENSE.rst +30 -0
@@ -0,0 +1,491 @@
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
+ __name__ = "biotite.interface.rdkit"
6
+ __author__ = "Patrick Kunzmann, Simon Mathis"
7
+ __all__ = ["to_mol", "from_mol"]
8
+
9
+ import copy
10
+ import numbers
11
+ import warnings
12
+ from collections import defaultdict
13
+ import numpy as np
14
+ import rdkit.Chem.AllChem as Chem
15
+ from rdkit.Chem import SanitizeFlags
16
+ from rdkit.rdBase import BlockLogs
17
+ from biotite.interface.version import requires_version
18
+ from biotite.interface.warning import LossyConversionWarning
19
+ from biotite.structure.atoms import AtomArray, AtomArrayStack
20
+ from biotite.structure.bonds import BondList, BondType
21
+ from biotite.structure.error import BadStructureError
22
+ from biotite.structure.filter import filter_heavy
23
+
24
+ _KEKULIZED_TO_AROMATIC_BOND_TYPE = {
25
+ BondType.SINGLE: BondType.AROMATIC_SINGLE,
26
+ BondType.DOUBLE: BondType.AROMATIC_DOUBLE,
27
+ BondType.TRIPLE: BondType.AROMATIC_TRIPLE,
28
+ }
29
+ _BIOTITE_TO_RDKIT_BOND_TYPE = {
30
+ BondType.ANY: Chem.BondType.UNSPECIFIED,
31
+ BondType.SINGLE: Chem.BondType.SINGLE,
32
+ BondType.DOUBLE: Chem.BondType.DOUBLE,
33
+ BondType.TRIPLE: Chem.BondType.TRIPLE,
34
+ BondType.QUADRUPLE: Chem.BondType.QUADRUPLE,
35
+ BondType.AROMATIC_SINGLE: Chem.BondType.AROMATIC,
36
+ BondType.AROMATIC_DOUBLE: Chem.BondType.AROMATIC,
37
+ BondType.AROMATIC_TRIPLE: Chem.BondType.AROMATIC,
38
+ BondType.AROMATIC: Chem.BondType.AROMATIC,
39
+ # Dative bonds may lead to a KekulizeException and may potentially be deprecated
40
+ # in the future (https://github.com/rdkit/rdkit/discussions/6995)
41
+ BondType.COORDINATION: Chem.BondType.SINGLE,
42
+ }
43
+ _RDKIT_TO_BIOTITE_BOND_TYPE = {
44
+ Chem.BondType.UNSPECIFIED: BondType.ANY,
45
+ Chem.BondType.SINGLE: BondType.SINGLE,
46
+ Chem.BondType.DOUBLE: BondType.DOUBLE,
47
+ Chem.BondType.TRIPLE: BondType.TRIPLE,
48
+ Chem.BondType.QUADRUPLE: BondType.QUADRUPLE,
49
+ Chem.BondType.DATIVE: BondType.COORDINATION,
50
+ }
51
+ _STANDARD_ANNOTATIONS = frozenset(
52
+ {
53
+ "chain_id",
54
+ "res_id",
55
+ "ins_code",
56
+ "res_name",
57
+ "hetero",
58
+ "atom_name",
59
+ "element",
60
+ "charge",
61
+ "b_factor",
62
+ "occupancy",
63
+ "altloc_id",
64
+ }
65
+ )
66
+
67
+
68
+ # `Conformer.SetPositions()` was added in RDKit 2024.09.1
69
+ @requires_version("rdkit", ">=2024.09.1")
70
+ def to_mol(
71
+ atoms,
72
+ kekulize=False,
73
+ use_dative_bonds=False,
74
+ include_extra_annotations=(),
75
+ explicit_hydrogen=None,
76
+ ):
77
+ """
78
+ Convert an :class:`.AtomArray` or :class:`.AtomArrayStack` into a
79
+ :class:`rdkit.Chem.rdchem.Mol`.
80
+
81
+ Parameters
82
+ ----------
83
+ atoms : AtomArray or AtomArrayStack
84
+ The molecule to be converted.
85
+ Must have an associated :class:`BondList`.
86
+ kekulize : bool, optional
87
+ If set to true, aromatic bonds are represented by single, double and triple
88
+ bonds.
89
+ By default, aromatic bond types are converted to
90
+ :attr:`rdkit.rdchem.BondType.AROMATIC`.
91
+ use_dative_bonds : bool, optional
92
+ If set to true, :attr:`BondType.COORDINATION` bonds are translated to
93
+ :attr:`rdkit.rdchem.BondType.DATIVE` bonds instead of
94
+ :attr:`rdkit.rdchem.BondType.SINGLE` bonds.
95
+ This may have the undesired side effect that a
96
+ :class:`rdkit.Chem.rdchem.KekulizeException` is raised for some molecules, when
97
+ the returned :class:`rdkit.Chem.rdchem.Mol` is kekulized.
98
+ include_extra_annotations : list of str, optional
99
+ Names of annotation arrays in `atoms` that are added as atom-level property with
100
+ the same name to the returned :class:`rdkit.Chem.rdchem.Mol`.
101
+ These properties can be accessed with :meth:`rdkit.Chem.rdchem.Mol.GetProp()`.
102
+ Note that standard annotations (e.g. ``'chain_id', 'atom_name', 'res_name'``)
103
+ are always included per default. These standard annotations can be accessed
104
+ with :meth:`rdkit.Chem.rdchem.Atom.GetPDBResidueInfo()` for each atom in the
105
+ returned :class:`rdkit.Chem.rdchem.Mol`.
106
+ explicit_hydrogen : bool, optional
107
+ If set to true, the conversion process expects that all hydrogen atoms are
108
+ explicit, i.e. each each hydrogen atom must be part of the :class:`AtomArray`.
109
+ If set to false, the conversion process treats all hydrogen atoms as implicit.
110
+ By default, explicit hydrogen atoms are only assumed if any hydrogen atoms are
111
+ present in `atoms`.
112
+
113
+ Returns
114
+ -------
115
+ mol : rdkit.Chem.rdchem.Mol
116
+ The *RDKit* molecule.
117
+ If the input `atoms` is an :class:`AtomArrayStack`, all models are included
118
+ as conformers with conformer IDs starting from ``0``.
119
+
120
+ Raises
121
+ ------
122
+ BadStructureError
123
+ If the input `atoms` does not have an associated :class:`BondList`.
124
+ Also raises a :class:`BadStructureError`, if `explicit_hydrogen` is set to
125
+ ``False`` despite hydrogen atoms being present in `atoms`.
126
+
127
+ Notes
128
+ -----
129
+ The atoms in the return value are in the same order as the input `atoms`,
130
+ i.e. indices pointing to the :class:`rdkit.Chem.rdchem.Mol` can be used to point to
131
+ the same atoms in the :class:`.AtomArray`.
132
+
133
+ Examples
134
+ --------
135
+
136
+ >>> from rdkit.Chem import MolToSmiles
137
+ >>> alanine_atom_array = residue("ALA")
138
+ >>> mol = to_mol(alanine_atom_array)
139
+ >>> print(MolToSmiles(mol))
140
+ [H]OC(=O)C([H])(N([H])[H])C([H])([H])[H]
141
+
142
+ By default, ``'atom_name'`` is stored in RDKit's PDBResidueInfo grouping
143
+ for each atom. We can access it manually as below
144
+
145
+ >>> for atom in mol.GetAtoms():
146
+ ... print(atom.GetPDBResidueInfo().GetName())
147
+ N
148
+ CA
149
+ C
150
+ O
151
+ CB
152
+ OXT
153
+ H
154
+ H2
155
+ HA
156
+ HB1
157
+ HB2
158
+ HB3
159
+ HXT
160
+ """
161
+ heavy_mask = filter_heavy(atoms)
162
+ _has_hydrogen = not heavy_mask.all()
163
+ if explicit_hydrogen is None:
164
+ explicit_hydrogen = _has_hydrogen
165
+ elif explicit_hydrogen:
166
+ if not _has_hydrogen:
167
+ warnings.warn(
168
+ "No hydrogen found, although 'explicit_hydrogen' is 'True'. "
169
+ "This may lead to radicals after sanitization in RDKit.",
170
+ UserWarning,
171
+ )
172
+ else:
173
+ if _has_hydrogen:
174
+ raise BadStructureError(
175
+ "Hydrogen atoms are present in the input, although 'explicit_hydrogen' "
176
+ "is set to 'False'"
177
+ )
178
+ atoms = atoms[..., heavy_mask]
179
+
180
+ mol = Chem.EditableMol(Chem.Mol())
181
+
182
+ has_annot = frozenset(atoms.get_annotation_categories())
183
+ extra_annot = set(include_extra_annotations) - _STANDARD_ANNOTATIONS
184
+
185
+ for i in range(atoms.array_length()):
186
+ rdkit_atom = Chem.Atom(atoms.element[i].capitalize())
187
+ if explicit_hydrogen:
188
+ # ... tell RDKit to not assume any implicit hydrogens
189
+ rdkit_atom.SetNoImplicit(True)
190
+ if "charge" in has_annot:
191
+ rdkit_atom.SetFormalCharge(atoms.charge[i].item())
192
+
193
+ # add standard pdb annotations
194
+ rdkit_atom_res_info = Chem.AtomPDBResidueInfo(
195
+ atomName=atoms.atom_name[i].item(),
196
+ residueName=atoms.res_name[i].item(),
197
+ chainId=atoms.chain_id[i].item(),
198
+ residueNumber=atoms.res_id[i].item(),
199
+ isHeteroAtom=atoms.hetero[i].item(),
200
+ insertionCode=atoms.ins_code[i].item(),
201
+ )
202
+ if "occupancy" in has_annot:
203
+ rdkit_atom_res_info.SetOccupancy(atoms.occupancy[i].item())
204
+ if "b_factor" in has_annot:
205
+ rdkit_atom_res_info.SetTempFactor(atoms.b_factor[i].item())
206
+ if "altloc_id" in has_annot:
207
+ rdkit_atom_res_info.SetAltLoc(atoms.altloc_id[i].item())
208
+ rdkit_atom.SetPDBResidueInfo(rdkit_atom_res_info)
209
+
210
+ # add extra annotations
211
+ for annot_name in extra_annot:
212
+ _set_property(
213
+ rdkit_atom, annot_name, atoms.get_annotation(annot_name)[i].item()
214
+ )
215
+
216
+ # add atom to molecule
217
+ mol.AddAtom(rdkit_atom)
218
+
219
+ if atoms.bonds is None:
220
+ raise BadStructureError("An AtomArray with associated BondList is required")
221
+ if kekulize:
222
+ bonds = atoms.bonds.copy()
223
+ bonds.remove_aromaticity()
224
+ else:
225
+ bonds = atoms.bonds
226
+ for atom_i, atom_j, bond_type in bonds.as_array():
227
+ if not use_dative_bonds and bond_type == BondType.COORDINATION:
228
+ bond_type = BondType.SINGLE
229
+ mol.AddBond(
230
+ atom_i.item(), atom_j.item(), _BIOTITE_TO_RDKIT_BOND_TYPE[bond_type]
231
+ )
232
+
233
+ # Create a proper 'frozen' Mol object
234
+ mol = mol.GetMol()
235
+ coord = atoms.coord
236
+ if coord.ndim == 2:
237
+ # Handle AtomArray and AtomArrayStack consistently
238
+ coord = coord[None, :, :]
239
+ for model_coord in coord:
240
+ conformer = Chem.Conformer(mol.GetNumAtoms())
241
+ # RDKit silently expects the data to be in C-contiguous order
242
+ # Otherwise the coordinates would be completely misassigned
243
+ # (https://github.com/rdkit/rdkit/issues/8221)
244
+ conformer.SetPositions(np.ascontiguousarray(model_coord, dtype=np.float64))
245
+ conformer.Set3D(True)
246
+ mol.AddConformer(conformer)
247
+
248
+ return mol
249
+
250
+
251
+ @requires_version("rdkit", ">=2020")
252
+ def from_mol(mol, conformer_id=None, add_hydrogen=None):
253
+ """
254
+ Convert a :class:`rdkit.Chem.rdchem.Mol` into an :class:`.AtomArray` or
255
+ :class:`.AtomArrayStack`.
256
+
257
+ Parameters
258
+ ----------
259
+ mol : rdkit.Chem.rdchem.Mol
260
+ The molecule to be converted.
261
+ conformer_id : int or {"2D", "3D"}, optional
262
+ The ID of the conformer to be converted.
263
+ If set to "2D" or "3D", an :class:`AtomArrayStack` with only the 2D or 3D
264
+ conformer is returned, respectively.
265
+ By default, an :class:`AtomArrayStack` with all conformers (2D and 3D) is
266
+ returned.
267
+ add_hydrogen : bool, optional
268
+ If set to true, explicit hydrogen atoms are always added.
269
+ If set to false, explicit hydrogen atoms are never added.
270
+ By default, explicit hydrogen atoms are only added, if hydrogen atoms are not
271
+ already present.
272
+
273
+ Returns
274
+ -------
275
+ atoms : AtomArray or AtomArrayStack
276
+ The converted atoms.
277
+ An :class:`AtomArray` is returned if an integer `conformer_id` is given.
278
+ Otherwise, an :class:`AtomArrayStack` is returned.
279
+ If the input `mol` does not have a conformer, an `AtomArrayStack` with a
280
+ single model, where all coordinates are *NaN*, is returned.
281
+
282
+ Notes
283
+ -----
284
+ The atoms in the return value are in the same order as the input `mol`,
285
+ i.e. indices pointing to the :class:`rdkit.Chem.rdchem.Mol` can be used to point to
286
+ the same atoms in the :class:`.AtomArray`.
287
+
288
+ All atom-level properties of `mol`
289
+ (obtainable with :meth:`rdkit.Chem.rdchem.Mol.GetProp()`) are added as annotation
290
+ array with the same name.
291
+ ``element`` and ``charge`` are not inferred from properties but from the
292
+ dedicated attributes in the :class:`rdkit.Chem.rdchem.Mol` object.
293
+
294
+ Examples
295
+ --------
296
+
297
+ >>> from rdkit.Chem import MolFromSmiles
298
+ >>> from rdkit.Chem.rdDistGeom import EmbedMolecule
299
+ >>> from rdkit.Chem.rdForceFieldHelpers import UFFOptimizeMolecule
300
+ >>> from rdkit.Chem.rdmolops import AddHs
301
+ >>> mol = MolFromSmiles("C[C@@H](C(=O)O)N")
302
+ >>> mol = AddHs(mol)
303
+ >>> # Create a 3D conformer
304
+ >>> conformer_id = EmbedMolecule(mol)
305
+ >>> UFFOptimizeMolecule(mol)
306
+ 0
307
+ >>> alanine_atom_array = from_mol(mol, conformer_id)
308
+ >>> # RDKit does not assign atom names -> for convenience, do this in Biotite
309
+ >>> alanine_atom_array.atom_name = create_atom_names(alanine_atom_array)
310
+ >>> print(alanine_atom_array)
311
+ 0 C1 C -1.076 1.102 -0.094
312
+ 0 C2 C -0.363 -0.246 -0.218
313
+ 0 C3 C 1.129 -0.073 -0.109
314
+ 0 O1 O 1.644 0.373 0.952
315
+ 0 O2 O 1.943 -0.405 -1.187
316
+ 0 N1 N -0.861 -1.175 0.798
317
+ 0 H1 H -0.724 1.795 -0.888
318
+ 0 H2 H -2.171 0.960 -0.212
319
+ 0 H3 H -0.881 1.561 0.899
320
+ 0 H4 H -0.600 -0.664 -1.221
321
+ 0 H5 H 2.949 -0.295 -1.132
322
+ 0 H6 H -0.595 -0.830 1.750
323
+ 0 H7 H -0.395 -2.102 0.660
324
+ """
325
+ if add_hydrogen is None:
326
+ add_hydrogen = not _has_explicit_hydrogen(mol)
327
+ if add_hydrogen:
328
+ mol = copy.deepcopy(mol)
329
+ with BlockLogs():
330
+ # Avoid modifying the input molecule
331
+ Chem.SanitizeMol(mol, SanitizeFlags.SANITIZE_ADJUSTHS)
332
+ mol = Chem.AddHs(mol, addCoords=False, addResidueInfo=False)
333
+
334
+ rdkit_atoms = mol.GetAtoms()
335
+ if rdkit_atoms is None:
336
+ raise BadStructureError("Could not obtains atoms from Mol")
337
+
338
+ if conformer_id in (None, "2D", "3D"):
339
+ conformers = [conf for conf in mol.GetConformers()]
340
+ if conformer_id == "2D":
341
+ conformers = [conf for conf in conformers if not conf.Is3D()]
342
+ elif conformer_id == "3D":
343
+ conformers = [conf for conf in conformers if conf.Is3D()]
344
+ if len(conformers) == 0:
345
+ # No conformer in 'Mol' that fulfills the criteria
346
+ # -> create a single model with all coordinates set to NaN
347
+ atoms = AtomArrayStack(1, len(rdkit_atoms))
348
+ atoms.coord = np.full((1, len(rdkit_atoms), 3), np.nan)
349
+ else:
350
+ atoms = AtomArrayStack(len(conformers), len(rdkit_atoms))
351
+ for i, conformer in enumerate(conformers):
352
+ atoms.coord[i] = np.array(conformer.GetPositions(), dtype=np.float32)
353
+ else:
354
+ conformer = mol.GetConformer(conformer_id)
355
+ atoms = AtomArray(len(rdkit_atoms))
356
+ atoms.coord = np.array(conformer.GetPositions(), dtype=np.float32)
357
+
358
+ extra_annotations = defaultdict(
359
+ # The dtype of each annotation array is inferred later
360
+ lambda: [None] * atoms.array_length()
361
+ )
362
+ atoms.add_annotation("charge", int)
363
+ atoms.add_annotation("b_factor", float)
364
+ atoms.add_annotation("occupancy", float)
365
+ atoms.add_annotation("altloc_id", str)
366
+
367
+ for rdkit_atom in rdkit_atoms:
368
+ _atom_idx = rdkit_atom.GetIdx()
369
+
370
+ # ... add standard annotations
371
+ element = rdkit_atom.GetSymbol().upper().strip()
372
+ atoms.element[_atom_idx] = element
373
+ atoms.charge[_atom_idx] = rdkit_atom.GetFormalCharge()
374
+
375
+ # ... add PDB related annotations
376
+ residue_info = rdkit_atom.GetPDBResidueInfo()
377
+ if residue_info is None:
378
+ # ... default values for atoms with missing residue information
379
+ residue_info = Chem.AtomPDBResidueInfo(
380
+ atomName="",
381
+ occupancy=0.0,
382
+ tempFactor=float("nan"),
383
+ altLoc=".",
384
+ )
385
+ if element in ("H", "D"):
386
+ # ... attempt inferring residue information from nearest heavy atom
387
+ # in case of a hydrogen atom without explicit residue information
388
+ nearest_heavy_atom = rdkit_atom.GetNeighbors()[0]
389
+ nearest_heavy_atom_res_info = nearest_heavy_atom.GetPDBResidueInfo()
390
+ if nearest_heavy_atom_res_info is not None:
391
+ residue_info.SetChainId(nearest_heavy_atom_res_info.GetChainId())
392
+ residue_info.SetResidueName(
393
+ nearest_heavy_atom_res_info.GetResidueName()
394
+ )
395
+ residue_info.SetResidueNumber(
396
+ nearest_heavy_atom_res_info.GetResidueNumber()
397
+ )
398
+ residue_info.SetInsertionCode(
399
+ nearest_heavy_atom_res_info.GetInsertionCode()
400
+ )
401
+ residue_info.SetIsHeteroAtom(
402
+ nearest_heavy_atom_res_info.GetIsHeteroAtom()
403
+ )
404
+ residue_info.SetAltLoc(nearest_heavy_atom_res_info.GetAltLoc())
405
+
406
+ atoms.chain_id[_atom_idx] = residue_info.GetChainId()
407
+ atoms.res_id[_atom_idx] = residue_info.GetResidueNumber()
408
+ atoms.ins_code[_atom_idx] = residue_info.GetInsertionCode()
409
+ atoms.res_name[_atom_idx] = residue_info.GetResidueName()
410
+ atoms.altloc_id[_atom_idx] = residue_info.GetAltLoc()
411
+ atoms.hetero[_atom_idx] = residue_info.GetIsHeteroAtom()
412
+ atoms.b_factor[_atom_idx] = residue_info.GetTempFactor()
413
+ atoms.occupancy[_atom_idx] = residue_info.GetOccupancy()
414
+ atoms.atom_name[_atom_idx] = residue_info.GetName().strip()
415
+
416
+ # ... add extra annotations
417
+ for annot, value in rdkit_atom.GetPropsAsDict(includePrivate=False).items():
418
+ extra_annotations[annot][_atom_idx] = value
419
+
420
+ for annot, array in extra_annotations.items():
421
+ # Handle special case of implicit hydrogen atom flags,
422
+ # that is set by 'AddHs()' to hydrogen atoms
423
+ if annot == "isImplicit":
424
+ annotation_array = np.array(array, dtype=bool)
425
+ else:
426
+ annotation_array = np.array(array)
427
+ atoms.set_annotation(annot, annotation_array)
428
+
429
+ rdkit_bonds = list(mol.GetBonds())
430
+ is_aromatic = np.array(
431
+ [bond.GetBondType() == Chem.BondType.AROMATIC for bond in rdkit_bonds]
432
+ )
433
+ if np.any(is_aromatic):
434
+ # Determine the kekulized order of aromatic bonds
435
+ # Copy as 'Kekulize()' modifies the molecule in-place
436
+ mol = Chem.Mol(mol)
437
+ try:
438
+ with BlockLogs():
439
+ Chem.Kekulize(mol)
440
+ except Chem.KekulizeException:
441
+ warnings.warn(
442
+ "Kekulization failed, "
443
+ "using 'BondType.AROMATIC' instead for aromatic bonds instead",
444
+ LossyConversionWarning,
445
+ )
446
+ rdkit_bonds = list(mol.GetBonds())
447
+ bond_array = np.full((len(rdkit_bonds), 3), BondType.ANY, dtype=np.uint32)
448
+ for i, bond in enumerate(rdkit_bonds):
449
+ bond_type = _RDKIT_TO_BIOTITE_BOND_TYPE.get(bond.GetBondType())
450
+ if bond_type is None:
451
+ warnings.warn(
452
+ f"Bond type '{bond.GetBondType().name}' cannot be mapped to Biotite, "
453
+ "using 'BondType.ANY' instead",
454
+ LossyConversionWarning,
455
+ )
456
+ bond_type = BondType.ANY
457
+ if is_aromatic[i]:
458
+ try:
459
+ bond_type = _KEKULIZED_TO_AROMATIC_BOND_TYPE[bond_type]
460
+ except KeyError:
461
+ bond_type = BondType.AROMATIC
462
+ warnings.warn(
463
+ "Kekulization returned invalid bond type, "
464
+ "using generic 'BondType.AROMATIC' instead",
465
+ LossyConversionWarning,
466
+ )
467
+ bond_array[i, 0] = bond.GetBeginAtomIdx()
468
+ bond_array[i, 1] = bond.GetEndAtomIdx()
469
+ bond_array[i, 2] = bond_type
470
+ atoms.bonds = BondList(atoms.array_length(), bond_array)
471
+
472
+ return atoms
473
+
474
+
475
+ def _has_explicit_hydrogen(mol):
476
+ return mol.GetNumAtoms() > mol.GetNumHeavyAtoms()
477
+
478
+
479
+ def _set_property(atom, annot_name, value):
480
+ if isinstance(value, bool):
481
+ atom.SetBoolProp(annot_name, value)
482
+ elif isinstance(value, numbers.Integral):
483
+ atom.SetIntProp(annot_name, value)
484
+ elif isinstance(value, numbers.Real):
485
+ atom.SetDoubleProp(annot_name, value)
486
+ elif isinstance(value, str):
487
+ atom.SetProp(annot_name, value)
488
+ else:
489
+ raise TypeError(
490
+ f"Unsupported dtype '{type(value).__name__}' for annotation '{annot_name}'"
491
+ )
@@ -0,0 +1,94 @@
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
+ __name__ = "biotite.interface"
6
+ __author__ = "Patrick Kunzmann"
7
+ __all__ = ["VersionError", "requires_version"]
8
+
9
+
10
+ import functools
11
+ import importlib.metadata
12
+ from packaging.specifiers import SpecifierSet
13
+ from packaging.version import Version
14
+
15
+ # Stores the variant of interface functions
16
+ # compatible with the respective installed package version
17
+ _functions_for_version = {}
18
+
19
+
20
+ class VersionError(Exception):
21
+ """
22
+ This exception is raised when the installed version of an interfaced package is
23
+ incompatible with all implemented variants of a function.
24
+ """
25
+
26
+ pass
27
+
28
+
29
+ def require_package(package):
30
+ """
31
+ Check if the given package is installed and raise an exception if not.
32
+
33
+ Parameters
34
+ ----------
35
+ package : str
36
+ The name of the package to be checked.
37
+
38
+ Raises
39
+ ------
40
+ ImportError
41
+ If the package is not installed.
42
+
43
+ Notes
44
+ -----
45
+ It is useful to call this function in the ``__init__.py`` of each ``interface``
46
+ subpackage, to obtain clear error messages about missing dependencies.
47
+ """
48
+ if importlib.util.find_spec(package) is None:
49
+ raise ImportError(f"'{package}' is not installed")
50
+
51
+
52
+ def requires_version(package, version_specifier):
53
+ """
54
+ Declare a function variant that is compatible with a specific version range of the
55
+ interfaced package.
56
+
57
+ Parameters
58
+ ----------
59
+ package : str
60
+ The name of the interfaced package.
61
+ version_specifier : str or list of str
62
+ The :pep:`440` version specifier(s) for the interfaced package that are
63
+ compatible with the function.
64
+ Multiple constraints can be either given as a list of strings or as a single
65
+ comma-separated string.
66
+ """
67
+
68
+ def decorator(function):
69
+ @functools.wraps(function)
70
+ def wrapper(*args, **kwargs):
71
+ function_for_version = _functions_for_version.get(function.__name__)
72
+ if function_for_version is None:
73
+ raise VersionError(
74
+ f"No variant of '{function.__name__}()' "
75
+ f"found for installed '{package}'=={package_version}'"
76
+ )
77
+ return function_for_version(*args, **kwargs)
78
+
79
+ if isinstance(version_specifier, str):
80
+ specifier = SpecifierSet(version_specifier)
81
+ else:
82
+ specifier = SpecifierSet.intersection(*version_specifier)
83
+ try:
84
+ package_version = Version(importlib.metadata.version(package))
85
+ except importlib.metadata.PackageNotFoundError:
86
+ raise ImportError(
87
+ f"'{function.__name__}()' requires the '{package}' package"
88
+ )
89
+ if package_version in specifier:
90
+ _functions_for_version[function.__name__] = function
91
+
92
+ return wrapper
93
+
94
+ return decorator
@@ -0,0 +1,19 @@
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
+ __name__ = "biotite.interface"
6
+ __author__ = "Patrick Kunzmann"
7
+ __all__ = ["LossyConversionWarning"]
8
+
9
+
10
+ class LossyConversionWarning(UserWarning):
11
+ """
12
+ Warning raised, when some information is lost during conversion.
13
+
14
+ Note that most conversion functions will be inherently lossy to some extent.
15
+ This warning is only raised, when the loss of information happens only for
16
+ some edge case.
17
+ """
18
+
19
+ pass
@@ -0,0 +1,84 @@
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
+ A subpackage for handling sequences.
7
+
8
+ A :class:`Sequence` can be seen as a succession of symbols.
9
+ The set of symbols, that can occur in a sequence, is defined by an
10
+ :class:`Alphabet`.
11
+ For example, an unambiguous DNA sequence has an :class:`Alphabet`, that
12
+ includes the 4 letters (strings) ``'A'``, ``'C'``, ``'G'`` and ``'T'``.
13
+ But furthermore, an :class:`Alphabet` can also contain any immutable and
14
+ hashable Python object like :class:`int`, :class:`tuple`, etc.
15
+ If a :class:`Sequence` is created with at least a symbol,
16
+ that is not in the given :class:`Alphabet`, an :class:`AlphabetError` is
17
+ raised.
18
+
19
+ Internally, a :class:`Sequence` is saved as a *NumPy* :class:`ndarray`
20
+ of integer values, where each integer represents a symbol in the
21
+ :class:`Alphabet`.
22
+ For example, ``'A'``, ``'C'``, ``'G'`` and ``'T'`` would be encoded into
23
+ 0, 1, 2 and 3, respectively.
24
+ These integer values are called *symbol code*, the encoding of an entire
25
+ sequence of symbols is called *sequence code*.
26
+
27
+ .. figure:: /static/assets/figures/symbol_encoding.png
28
+ :alt: Symbol encoding in Biotite
29
+ :scale: 50%
30
+
31
+ Taken from
32
+ `Kunzmann & Hamacher 2018 <https://doi.org/10.1186/s12859-018-2367-z>`_
33
+ licensed under `CC BY 4.0 <https://creativecommons.org/licenses/by/4.0/>`_.
34
+
35
+ The size of the symbol code type in the array is determined by the
36
+ size of the :class:`Alphabet`:
37
+ If the :class:`Alphabet` contains 256 symbols or less, one byte is used
38
+ per array element, between 257 and 65536 symbols, two bytes are used,
39
+ and so on.
40
+
41
+ This approach has multiple advantages:
42
+
43
+ - Wider spectrum of what kind of objects can be represented by
44
+ :class:`Sequence` objects
45
+ - Efficient memory usage and faster calculations due to
46
+ alphabet-tailored *symbol code* type size
47
+ - C-acceleration due to usage of :class:`ndarray` objects
48
+ - Most functions applied on :class:`Sequence` objects are
49
+ indifferent to the actual type of sequence.
50
+ - Symbol codes are directly indices for substitution matrices in
51
+ alignments
52
+ - *k-mers* can be computed fast
53
+
54
+ The abstract :class:`Sequence` superclass cannot be instantiated
55
+ directly, as it does not define an :class:`Alphabet` by itself.
56
+ Instead usually the concrete subclasses :class:`NucleotideSequence`
57
+ (for DNA and RNA sequences) and :class:`ProteinSequence`
58
+ (for amino acid sequences) are used.
59
+ These classes have defined alphabets and provide additional sequence
60
+ type specific methods.
61
+ The class :class:`GeneralSequence` allows the usage of a custom
62
+ :class:`Alphabet` without the need to subclass :class:`Sequence`.
63
+
64
+ Additionally, this subpackage provides support for sequence features,
65
+ as used in e.g. GenBank or GFF files.
66
+ A :class:`Feature` stores its key name, its qualifiers and locations.
67
+ An :class:`Annotation` is a group of multiple :class:`Feature` objects
68
+ and offers convenient location based indexing.
69
+ An :class:`AnnotatedSequence` combines an :class:`Annotation` and a
70
+ :class:`Sequence`.
71
+
72
+ Sequence profiles can be created with the :class:`SequenceProfile` class.
73
+ """
74
+
75
+ __name__ = "biotite.sequence"
76
+ __author__ = "Patrick Kunzmann"
77
+
78
+ from .alphabet import *
79
+ from .annotation import *
80
+ from .codon import *
81
+ from .profile import *
82
+ from .search import *
83
+ from .seqtypes import *
84
+ from .sequence import *