biotite 0.41.1__cp312-cp312-macosx_10_16_arm64.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 (340) hide show
  1. biotite/__init__.py +19 -0
  2. biotite/application/__init__.py +43 -0
  3. biotite/application/application.py +265 -0
  4. biotite/application/autodock/__init__.py +12 -0
  5. biotite/application/autodock/app.py +505 -0
  6. biotite/application/blast/__init__.py +14 -0
  7. biotite/application/blast/alignment.py +83 -0
  8. biotite/application/blast/webapp.py +421 -0
  9. biotite/application/clustalo/__init__.py +12 -0
  10. biotite/application/clustalo/app.py +238 -0
  11. biotite/application/dssp/__init__.py +12 -0
  12. biotite/application/dssp/app.py +152 -0
  13. biotite/application/localapp.py +306 -0
  14. biotite/application/mafft/__init__.py +12 -0
  15. biotite/application/mafft/app.py +122 -0
  16. biotite/application/msaapp.py +374 -0
  17. biotite/application/muscle/__init__.py +13 -0
  18. biotite/application/muscle/app3.py +254 -0
  19. biotite/application/muscle/app5.py +171 -0
  20. biotite/application/sra/__init__.py +18 -0
  21. biotite/application/sra/app.py +456 -0
  22. biotite/application/tantan/__init__.py +12 -0
  23. biotite/application/tantan/app.py +222 -0
  24. biotite/application/util.py +59 -0
  25. biotite/application/viennarna/__init__.py +18 -0
  26. biotite/application/viennarna/rnaalifold.py +304 -0
  27. biotite/application/viennarna/rnafold.py +269 -0
  28. biotite/application/viennarna/rnaplot.py +187 -0
  29. biotite/application/viennarna/util.py +72 -0
  30. biotite/application/webapp.py +77 -0
  31. biotite/copyable.py +71 -0
  32. biotite/database/__init__.py +23 -0
  33. biotite/database/entrez/__init__.py +15 -0
  34. biotite/database/entrez/check.py +61 -0
  35. biotite/database/entrez/dbnames.py +89 -0
  36. biotite/database/entrez/download.py +223 -0
  37. biotite/database/entrez/key.py +44 -0
  38. biotite/database/entrez/query.py +223 -0
  39. biotite/database/error.py +15 -0
  40. biotite/database/pubchem/__init__.py +21 -0
  41. biotite/database/pubchem/download.py +260 -0
  42. biotite/database/pubchem/error.py +20 -0
  43. biotite/database/pubchem/query.py +827 -0
  44. biotite/database/pubchem/throttle.py +99 -0
  45. biotite/database/rcsb/__init__.py +13 -0
  46. biotite/database/rcsb/download.py +167 -0
  47. biotite/database/rcsb/query.py +959 -0
  48. biotite/database/uniprot/__init__.py +13 -0
  49. biotite/database/uniprot/check.py +32 -0
  50. biotite/database/uniprot/download.py +134 -0
  51. biotite/database/uniprot/query.py +209 -0
  52. biotite/file.py +251 -0
  53. biotite/sequence/__init__.py +73 -0
  54. biotite/sequence/align/__init__.py +49 -0
  55. biotite/sequence/align/alignment.py +658 -0
  56. biotite/sequence/align/banded.cpython-312-darwin.so +0 -0
  57. biotite/sequence/align/banded.pyx +652 -0
  58. biotite/sequence/align/buckets.py +69 -0
  59. biotite/sequence/align/cigar.py +434 -0
  60. biotite/sequence/align/kmeralphabet.cpython-312-darwin.so +0 -0
  61. biotite/sequence/align/kmeralphabet.pyx +574 -0
  62. biotite/sequence/align/kmersimilarity.cpython-312-darwin.so +0 -0
  63. biotite/sequence/align/kmersimilarity.pyx +233 -0
  64. biotite/sequence/align/kmertable.cpython-312-darwin.so +0 -0
  65. biotite/sequence/align/kmertable.pyx +3400 -0
  66. biotite/sequence/align/localgapped.cpython-312-darwin.so +0 -0
  67. biotite/sequence/align/localgapped.pyx +892 -0
  68. biotite/sequence/align/localungapped.cpython-312-darwin.so +0 -0
  69. biotite/sequence/align/localungapped.pyx +279 -0
  70. biotite/sequence/align/matrix.py +405 -0
  71. biotite/sequence/align/matrix_data/BLOSUM100.mat +31 -0
  72. biotite/sequence/align/matrix_data/BLOSUM30.mat +31 -0
  73. biotite/sequence/align/matrix_data/BLOSUM35.mat +31 -0
  74. biotite/sequence/align/matrix_data/BLOSUM40.mat +31 -0
  75. biotite/sequence/align/matrix_data/BLOSUM45.mat +31 -0
  76. biotite/sequence/align/matrix_data/BLOSUM50.mat +31 -0
  77. biotite/sequence/align/matrix_data/BLOSUM50_13p.mat +25 -0
  78. biotite/sequence/align/matrix_data/BLOSUM50_14.3.mat +25 -0
  79. biotite/sequence/align/matrix_data/BLOSUM50_5.0.mat +25 -0
  80. biotite/sequence/align/matrix_data/BLOSUM55.mat +31 -0
  81. biotite/sequence/align/matrix_data/BLOSUM60.mat +31 -0
  82. biotite/sequence/align/matrix_data/BLOSUM62.mat +31 -0
  83. biotite/sequence/align/matrix_data/BLOSUM62_13p.mat +25 -0
  84. biotite/sequence/align/matrix_data/BLOSUM62_14.3.mat +25 -0
  85. biotite/sequence/align/matrix_data/BLOSUM62_5.0.mat +25 -0
  86. biotite/sequence/align/matrix_data/BLOSUM65.mat +31 -0
  87. biotite/sequence/align/matrix_data/BLOSUM70.mat +31 -0
  88. biotite/sequence/align/matrix_data/BLOSUM75.mat +31 -0
  89. biotite/sequence/align/matrix_data/BLOSUM80.mat +31 -0
  90. biotite/sequence/align/matrix_data/BLOSUM85.mat +31 -0
  91. biotite/sequence/align/matrix_data/BLOSUM90.mat +31 -0
  92. biotite/sequence/align/matrix_data/BLOSUMN.mat +31 -0
  93. biotite/sequence/align/matrix_data/CorBLOSUM49_5.0.mat +25 -0
  94. biotite/sequence/align/matrix_data/CorBLOSUM57_13p.mat +25 -0
  95. biotite/sequence/align/matrix_data/CorBLOSUM57_14.3.mat +25 -0
  96. biotite/sequence/align/matrix_data/CorBLOSUM61_5.0.mat +25 -0
  97. biotite/sequence/align/matrix_data/CorBLOSUM66_13p.mat +25 -0
  98. biotite/sequence/align/matrix_data/CorBLOSUM67_14.3.mat +25 -0
  99. biotite/sequence/align/matrix_data/DAYHOFF.mat +32 -0
  100. biotite/sequence/align/matrix_data/GONNET.mat +26 -0
  101. biotite/sequence/align/matrix_data/IDENTITY.mat +25 -0
  102. biotite/sequence/align/matrix_data/MATCH.mat +25 -0
  103. biotite/sequence/align/matrix_data/NUC.mat +25 -0
  104. biotite/sequence/align/matrix_data/PAM10.mat +34 -0
  105. biotite/sequence/align/matrix_data/PAM100.mat +34 -0
  106. biotite/sequence/align/matrix_data/PAM110.mat +34 -0
  107. biotite/sequence/align/matrix_data/PAM120.mat +34 -0
  108. biotite/sequence/align/matrix_data/PAM130.mat +34 -0
  109. biotite/sequence/align/matrix_data/PAM140.mat +34 -0
  110. biotite/sequence/align/matrix_data/PAM150.mat +34 -0
  111. biotite/sequence/align/matrix_data/PAM160.mat +34 -0
  112. biotite/sequence/align/matrix_data/PAM170.mat +34 -0
  113. biotite/sequence/align/matrix_data/PAM180.mat +34 -0
  114. biotite/sequence/align/matrix_data/PAM190.mat +34 -0
  115. biotite/sequence/align/matrix_data/PAM20.mat +34 -0
  116. biotite/sequence/align/matrix_data/PAM200.mat +34 -0
  117. biotite/sequence/align/matrix_data/PAM210.mat +34 -0
  118. biotite/sequence/align/matrix_data/PAM220.mat +34 -0
  119. biotite/sequence/align/matrix_data/PAM230.mat +34 -0
  120. biotite/sequence/align/matrix_data/PAM240.mat +34 -0
  121. biotite/sequence/align/matrix_data/PAM250.mat +34 -0
  122. biotite/sequence/align/matrix_data/PAM260.mat +34 -0
  123. biotite/sequence/align/matrix_data/PAM270.mat +34 -0
  124. biotite/sequence/align/matrix_data/PAM280.mat +34 -0
  125. biotite/sequence/align/matrix_data/PAM290.mat +34 -0
  126. biotite/sequence/align/matrix_data/PAM30.mat +34 -0
  127. biotite/sequence/align/matrix_data/PAM300.mat +34 -0
  128. biotite/sequence/align/matrix_data/PAM310.mat +34 -0
  129. biotite/sequence/align/matrix_data/PAM320.mat +34 -0
  130. biotite/sequence/align/matrix_data/PAM330.mat +34 -0
  131. biotite/sequence/align/matrix_data/PAM340.mat +34 -0
  132. biotite/sequence/align/matrix_data/PAM350.mat +34 -0
  133. biotite/sequence/align/matrix_data/PAM360.mat +34 -0
  134. biotite/sequence/align/matrix_data/PAM370.mat +34 -0
  135. biotite/sequence/align/matrix_data/PAM380.mat +34 -0
  136. biotite/sequence/align/matrix_data/PAM390.mat +34 -0
  137. biotite/sequence/align/matrix_data/PAM40.mat +34 -0
  138. biotite/sequence/align/matrix_data/PAM400.mat +34 -0
  139. biotite/sequence/align/matrix_data/PAM410.mat +34 -0
  140. biotite/sequence/align/matrix_data/PAM420.mat +34 -0
  141. biotite/sequence/align/matrix_data/PAM430.mat +34 -0
  142. biotite/sequence/align/matrix_data/PAM440.mat +34 -0
  143. biotite/sequence/align/matrix_data/PAM450.mat +34 -0
  144. biotite/sequence/align/matrix_data/PAM460.mat +34 -0
  145. biotite/sequence/align/matrix_data/PAM470.mat +34 -0
  146. biotite/sequence/align/matrix_data/PAM480.mat +34 -0
  147. biotite/sequence/align/matrix_data/PAM490.mat +34 -0
  148. biotite/sequence/align/matrix_data/PAM50.mat +34 -0
  149. biotite/sequence/align/matrix_data/PAM500.mat +34 -0
  150. biotite/sequence/align/matrix_data/PAM60.mat +34 -0
  151. biotite/sequence/align/matrix_data/PAM70.mat +34 -0
  152. biotite/sequence/align/matrix_data/PAM80.mat +34 -0
  153. biotite/sequence/align/matrix_data/PAM90.mat +34 -0
  154. biotite/sequence/align/matrix_data/RBLOSUM52_5.0.mat +25 -0
  155. biotite/sequence/align/matrix_data/RBLOSUM59_13p.mat +25 -0
  156. biotite/sequence/align/matrix_data/RBLOSUM59_14.3.mat +25 -0
  157. biotite/sequence/align/matrix_data/RBLOSUM64_5.0.mat +25 -0
  158. biotite/sequence/align/matrix_data/RBLOSUM69_13p.mat +25 -0
  159. biotite/sequence/align/matrix_data/RBLOSUM69_14.3.mat +25 -0
  160. biotite/sequence/align/multiple.cpython-312-darwin.so +0 -0
  161. biotite/sequence/align/multiple.pyx +620 -0
  162. biotite/sequence/align/pairwise.cpython-312-darwin.so +0 -0
  163. biotite/sequence/align/pairwise.pyx +587 -0
  164. biotite/sequence/align/permutation.cpython-312-darwin.so +0 -0
  165. biotite/sequence/align/permutation.pyx +305 -0
  166. biotite/sequence/align/primes.txt +821 -0
  167. biotite/sequence/align/selector.cpython-312-darwin.so +0 -0
  168. biotite/sequence/align/selector.pyx +956 -0
  169. biotite/sequence/align/statistics.py +265 -0
  170. biotite/sequence/align/tracetable.cpython-312-darwin.so +0 -0
  171. biotite/sequence/align/tracetable.pxd +64 -0
  172. biotite/sequence/align/tracetable.pyx +370 -0
  173. biotite/sequence/alphabet.py +566 -0
  174. biotite/sequence/annotation.py +829 -0
  175. biotite/sequence/codec.cpython-312-darwin.so +0 -0
  176. biotite/sequence/codec.pyx +155 -0
  177. biotite/sequence/codon.py +466 -0
  178. biotite/sequence/codon_tables.txt +202 -0
  179. biotite/sequence/graphics/__init__.py +33 -0
  180. biotite/sequence/graphics/alignment.py +1034 -0
  181. biotite/sequence/graphics/color_schemes/autumn.json +51 -0
  182. biotite/sequence/graphics/color_schemes/blossom.json +51 -0
  183. biotite/sequence/graphics/color_schemes/clustalx_dna.json +11 -0
  184. biotite/sequence/graphics/color_schemes/clustalx_protein.json +28 -0
  185. biotite/sequence/graphics/color_schemes/flower.json +51 -0
  186. biotite/sequence/graphics/color_schemes/jalview_buried.json +31 -0
  187. biotite/sequence/graphics/color_schemes/jalview_hydrophobicity.json +31 -0
  188. biotite/sequence/graphics/color_schemes/jalview_prop_helix.json +31 -0
  189. biotite/sequence/graphics/color_schemes/jalview_prop_strand.json +31 -0
  190. biotite/sequence/graphics/color_schemes/jalview_prop_turn.json +31 -0
  191. biotite/sequence/graphics/color_schemes/jalview_taylor.json +28 -0
  192. biotite/sequence/graphics/color_schemes/jalview_zappo.json +28 -0
  193. biotite/sequence/graphics/color_schemes/ocean.json +51 -0
  194. biotite/sequence/graphics/color_schemes/pb_flower.json +39 -0
  195. biotite/sequence/graphics/color_schemes/rainbow_dna.json +11 -0
  196. biotite/sequence/graphics/color_schemes/rainbow_protein.json +30 -0
  197. biotite/sequence/graphics/color_schemes/spring.json +51 -0
  198. biotite/sequence/graphics/color_schemes/sunset.json +51 -0
  199. biotite/sequence/graphics/color_schemes/wither.json +51 -0
  200. biotite/sequence/graphics/colorschemes.py +139 -0
  201. biotite/sequence/graphics/dendrogram.py +184 -0
  202. biotite/sequence/graphics/features.py +510 -0
  203. biotite/sequence/graphics/logo.py +110 -0
  204. biotite/sequence/graphics/plasmid.py +661 -0
  205. biotite/sequence/io/__init__.py +12 -0
  206. biotite/sequence/io/fasta/__init__.py +22 -0
  207. biotite/sequence/io/fasta/convert.py +273 -0
  208. biotite/sequence/io/fasta/file.py +278 -0
  209. biotite/sequence/io/fastq/__init__.py +19 -0
  210. biotite/sequence/io/fastq/convert.py +120 -0
  211. biotite/sequence/io/fastq/file.py +551 -0
  212. biotite/sequence/io/genbank/__init__.py +17 -0
  213. biotite/sequence/io/genbank/annotation.py +277 -0
  214. biotite/sequence/io/genbank/file.py +575 -0
  215. biotite/sequence/io/genbank/metadata.py +324 -0
  216. biotite/sequence/io/genbank/sequence.py +172 -0
  217. biotite/sequence/io/general.py +192 -0
  218. biotite/sequence/io/gff/__init__.py +26 -0
  219. biotite/sequence/io/gff/convert.py +133 -0
  220. biotite/sequence/io/gff/file.py +434 -0
  221. biotite/sequence/phylo/__init__.py +36 -0
  222. biotite/sequence/phylo/nj.cpython-312-darwin.so +0 -0
  223. biotite/sequence/phylo/nj.pyx +221 -0
  224. biotite/sequence/phylo/tree.cpython-312-darwin.so +0 -0
  225. biotite/sequence/phylo/tree.pyx +1169 -0
  226. biotite/sequence/phylo/upgma.cpython-312-darwin.so +0 -0
  227. biotite/sequence/phylo/upgma.pyx +164 -0
  228. biotite/sequence/profile.py +456 -0
  229. biotite/sequence/search.py +116 -0
  230. biotite/sequence/seqtypes.py +556 -0
  231. biotite/sequence/sequence.py +374 -0
  232. biotite/structure/__init__.py +132 -0
  233. biotite/structure/atoms.py +1455 -0
  234. biotite/structure/basepairs.py +1415 -0
  235. biotite/structure/bonds.cpython-312-darwin.so +0 -0
  236. biotite/structure/bonds.pyx +1933 -0
  237. biotite/structure/box.py +592 -0
  238. biotite/structure/celllist.cpython-312-darwin.so +0 -0
  239. biotite/structure/celllist.pyx +849 -0
  240. biotite/structure/chains.py +298 -0
  241. biotite/structure/charges.cpython-312-darwin.so +0 -0
  242. biotite/structure/charges.pyx +520 -0
  243. biotite/structure/compare.py +274 -0
  244. biotite/structure/density.py +114 -0
  245. biotite/structure/dotbracket.py +216 -0
  246. biotite/structure/error.py +31 -0
  247. biotite/structure/filter.py +585 -0
  248. biotite/structure/geometry.py +697 -0
  249. biotite/structure/graphics/__init__.py +13 -0
  250. biotite/structure/graphics/atoms.py +226 -0
  251. biotite/structure/graphics/rna.py +282 -0
  252. biotite/structure/hbond.py +409 -0
  253. biotite/structure/info/__init__.py +25 -0
  254. biotite/structure/info/atom_masses.json +121 -0
  255. biotite/structure/info/atoms.py +82 -0
  256. biotite/structure/info/bonds.py +145 -0
  257. biotite/structure/info/ccd/README.rst +8 -0
  258. biotite/structure/info/ccd/amino_acids.txt +1663 -0
  259. biotite/structure/info/ccd/carbohydrates.txt +1135 -0
  260. biotite/structure/info/ccd/components.bcif +0 -0
  261. biotite/structure/info/ccd/nucleotides.txt +798 -0
  262. biotite/structure/info/ccd.py +95 -0
  263. biotite/structure/info/groups.py +90 -0
  264. biotite/structure/info/masses.py +123 -0
  265. biotite/structure/info/misc.py +144 -0
  266. biotite/structure/info/radii.py +197 -0
  267. biotite/structure/info/standardize.py +196 -0
  268. biotite/structure/integrity.py +268 -0
  269. biotite/structure/io/__init__.py +30 -0
  270. biotite/structure/io/ctab.py +72 -0
  271. biotite/structure/io/dcd/__init__.py +13 -0
  272. biotite/structure/io/dcd/file.py +65 -0
  273. biotite/structure/io/general.py +257 -0
  274. biotite/structure/io/gro/__init__.py +14 -0
  275. biotite/structure/io/gro/file.py +343 -0
  276. biotite/structure/io/mmtf/__init__.py +21 -0
  277. biotite/structure/io/mmtf/assembly.py +214 -0
  278. biotite/structure/io/mmtf/convertarray.cpython-312-darwin.so +0 -0
  279. biotite/structure/io/mmtf/convertarray.pyx +341 -0
  280. biotite/structure/io/mmtf/convertfile.cpython-312-darwin.so +0 -0
  281. biotite/structure/io/mmtf/convertfile.pyx +501 -0
  282. biotite/structure/io/mmtf/decode.cpython-312-darwin.so +0 -0
  283. biotite/structure/io/mmtf/decode.pyx +152 -0
  284. biotite/structure/io/mmtf/encode.cpython-312-darwin.so +0 -0
  285. biotite/structure/io/mmtf/encode.pyx +183 -0
  286. biotite/structure/io/mmtf/file.py +233 -0
  287. biotite/structure/io/mol/__init__.py +20 -0
  288. biotite/structure/io/mol/convert.py +115 -0
  289. biotite/structure/io/mol/ctab.py +414 -0
  290. biotite/structure/io/mol/header.py +116 -0
  291. biotite/structure/io/mol/mol.py +193 -0
  292. biotite/structure/io/mol/sdf.py +916 -0
  293. biotite/structure/io/netcdf/__init__.py +13 -0
  294. biotite/structure/io/netcdf/file.py +63 -0
  295. biotite/structure/io/npz/__init__.py +20 -0
  296. biotite/structure/io/npz/file.py +152 -0
  297. biotite/structure/io/pdb/__init__.py +20 -0
  298. biotite/structure/io/pdb/convert.py +293 -0
  299. biotite/structure/io/pdb/file.py +1240 -0
  300. biotite/structure/io/pdb/hybrid36.cpython-312-darwin.so +0 -0
  301. biotite/structure/io/pdb/hybrid36.pyx +242 -0
  302. biotite/structure/io/pdbqt/__init__.py +15 -0
  303. biotite/structure/io/pdbqt/convert.py +107 -0
  304. biotite/structure/io/pdbqt/file.py +640 -0
  305. biotite/structure/io/pdbx/__init__.py +23 -0
  306. biotite/structure/io/pdbx/bcif.py +648 -0
  307. biotite/structure/io/pdbx/cif.py +1032 -0
  308. biotite/structure/io/pdbx/component.py +246 -0
  309. biotite/structure/io/pdbx/convert.py +1597 -0
  310. biotite/structure/io/pdbx/encoding.cpython-312-darwin.so +0 -0
  311. biotite/structure/io/pdbx/encoding.pyx +950 -0
  312. biotite/structure/io/pdbx/legacy.py +267 -0
  313. biotite/structure/io/tng/__init__.py +13 -0
  314. biotite/structure/io/tng/file.py +46 -0
  315. biotite/structure/io/trajfile.py +710 -0
  316. biotite/structure/io/trr/__init__.py +13 -0
  317. biotite/structure/io/trr/file.py +46 -0
  318. biotite/structure/io/xtc/__init__.py +13 -0
  319. biotite/structure/io/xtc/file.py +46 -0
  320. biotite/structure/mechanics.py +75 -0
  321. biotite/structure/molecules.py +353 -0
  322. biotite/structure/pseudoknots.py +642 -0
  323. biotite/structure/rdf.py +243 -0
  324. biotite/structure/repair.py +253 -0
  325. biotite/structure/residues.py +562 -0
  326. biotite/structure/resutil.py +178 -0
  327. biotite/structure/sasa.cpython-312-darwin.so +0 -0
  328. biotite/structure/sasa.pyx +322 -0
  329. biotite/structure/sequence.py +112 -0
  330. biotite/structure/sse.py +327 -0
  331. biotite/structure/superimpose.py +727 -0
  332. biotite/structure/transform.py +504 -0
  333. biotite/structure/util.py +98 -0
  334. biotite/temp.py +86 -0
  335. biotite/version.py +16 -0
  336. biotite/visualize.py +251 -0
  337. biotite-0.41.1.dist-info/METADATA +187 -0
  338. biotite-0.41.1.dist-info/RECORD +340 -0
  339. biotite-0.41.1.dist-info/WHEEL +4 -0
  340. biotite-0.41.1.dist-info/licenses/LICENSE.rst +30 -0
@@ -0,0 +1,640 @@
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.structure.io.pdbqt"
6
+ __author__ = "Patrick Kunzmann, Daniel Bauer"
7
+ __all__ = ["PDBQTFile"]
8
+
9
+ import warnings
10
+ import numpy as np
11
+ from ....file import TextFile, InvalidFileError
12
+ from ...error import BadStructureError
13
+ from ...atoms import AtomArray, AtomArrayStack
14
+ from ...charges import partial_charges
15
+ from ...bonds import BondList, BondType, find_connected, find_rotatable_bonds
16
+
17
+
18
+ PARAMETRIZED_ELEMENTS = [
19
+ "H", "C", "N", "O", "P", "S",
20
+ "F", "Cl", "Br", "I",
21
+ "Mg", "Ca", "Mn", "Fe", "Zn"
22
+ ]
23
+
24
+
25
+ class PDBQTFile(TextFile):
26
+ """
27
+ This class represents an *AutoDock* PDBQT file.
28
+
29
+ This class only provides rudimentary support for reading/writing
30
+ the pure atom information.
31
+
32
+ EXPERIMENTAL: Future API changes are probable.
33
+
34
+ Examples
35
+ --------
36
+
37
+ Write biotin as flexible ligand into a PDBQT file:
38
+
39
+ >>> import os.path
40
+ >>> ligand = residue("BTN")
41
+ >>> file = PDBQTFile()
42
+ >>> mask = file.set_structure(ligand, rotatable_bonds="all")
43
+ >>> # Print removed nonpolar hydrogen atoms
44
+ >>> print(ligand[~mask])
45
+ HET 0 BTN H101 H 3.740 1.170 0.970
46
+ HET 0 BTN H102 H 4.070 1.340 -0.770
47
+ HET 0 BTN H91 H 2.800 -0.740 -1.210
48
+ HET 0 BTN H92 H 2.480 -0.910 0.530
49
+ HET 0 BTN H81 H 1.290 1.260 0.520
50
+ HET 0 BTN H82 H 1.620 1.440 -1.220
51
+ HET 0 BTN H71 H 0.350 -0.650 -1.660
52
+ HET 0 BTN H72 H 0.020 -0.820 0.080
53
+ HET 0 BTN H2 H -0.840 1.580 -1.630
54
+ HET 0 BTN H61 H -3.800 1.840 1.290
55
+ HET 0 BTN H62 H -3.370 2.740 -0.200
56
+ HET 0 BTN H5 H -4.310 0.810 -1.210
57
+ HET 0 BTN H4 H -2.450 -0.040 -2.250
58
+ >>> print(file)
59
+ ROOT
60
+ HETATM 1 C11 BTN 0 5.090 -0.280 0.170 1.00 0.00 0.258 C
61
+ HETATM 2 O11 BTN 0 4.960 -1.470 0.030 1.00 0.00 -0.264 OA
62
+ ENDROOT
63
+ BRANCH 1 3
64
+ HETATM 3 O12 BTN 0 6.300 0.230 0.440 1.00 0.00 -0.331 OA
65
+ HETATM 17 HO2 BTN 0 7.030 -0.390 0.520 1.00 0.00 0.221 HD
66
+ ENDBRANCH 1 3
67
+ BRANCH 1 4
68
+ HETATM 4 C10 BTN 0 3.900 0.630 0.040 1.00 0.00 0.105 C
69
+ BRANCH 4 5
70
+ HETATM 5 C9 BTN 0 2.650 -0.200 -0.280 1.00 0.00 0.010 C
71
+ BRANCH 5 6
72
+ HETATM 6 C8 BTN 0 1.440 0.720 -0.410 1.00 0.00 0.002 C
73
+ BRANCH 6 7
74
+ HETATM 7 C7 BTN 0 0.200 -0.110 -0.730 1.00 0.00 0.016 C
75
+ BRANCH 7 8
76
+ HETATM 8 C2 BTN 0 -1.020 0.820 -0.860 1.00 0.00 0.065 C
77
+ HETATM 9 S1 BTN 0 -1.420 1.600 0.750 1.00 0.00 -0.154 SA
78
+ HETATM 10 C6 BTN 0 -3.200 1.830 0.370 1.00 0.00 0.090 C
79
+ HETATM 11 C5 BTN 0 -3.530 0.580 -0.480 1.00 0.00 0.091 C
80
+ HETATM 12 N1 BTN 0 -3.970 -0.510 0.410 1.00 0.00 -0.239 NA
81
+ HETATM 13 C3 BTN 0 -3.140 -1.550 0.270 1.00 0.00 0.272 C
82
+ HETATM 14 O3 BTN 0 -3.270 -2.590 0.890 1.00 0.00 -0.259 OA
83
+ HETATM 15 N2 BTN 0 -2.150 -1.340 -0.610 1.00 0.00 -0.239 NA
84
+ HETATM 16 C4 BTN 0 -2.290 0.010 -1.170 1.00 0.00 0.093 C
85
+ HETATM 18 HN1 BTN 0 -4.740 -0.470 1.000 1.00 0.00 0.132 HD
86
+ HETATM 19 HN2 BTN 0 -1.460 -1.980 -0.840 1.00 0.00 0.132 HD
87
+ ENDBRANCH 7 8
88
+ ENDBRANCH 6 7
89
+ ENDBRANCH 5 6
90
+ ENDBRANCH 4 5
91
+ ENDBRANCH 1 4
92
+ TORSDOF 6
93
+ >>> file.write(os.path.join(path_to_directory, "1l2y_mod.pdb"))
94
+ """
95
+
96
+ def get_remarks(self, model=None):
97
+ """
98
+ Get the content of ``REMARKS`` lines.
99
+
100
+ Parameters
101
+ ----------
102
+ model : int, optional
103
+ If this parameter is given, the function will return a
104
+ string from the remarks corresponding to the given
105
+ model number (starting at 1).
106
+ Negative values are used to index models starting from the
107
+ last model insted of the first model.
108
+ If this parameter is omitted, a list of strings
109
+ containing all models will be returned, even if the
110
+ structure contains only one model.
111
+
112
+ Returns
113
+ -------
114
+ lines : str or list of str
115
+ The content of ``REMARKS`` lines, without the leading
116
+ ``'REMARKS'``.
117
+ """
118
+ # Line indices where a new model starts
119
+ model_start_i = np.array([i for i in range(len(self.lines))
120
+ if self.lines[i].startswith(("MODEL"))],
121
+ dtype=int)
122
+ # Line indices with ATOM or HETATM records
123
+ remark_line_i = np.array([i for i in range(len(self.lines)) if
124
+ self.lines[i].startswith("REMARK")],
125
+ dtype=int)
126
+ # Structures containing only one model may omit MODEL record
127
+ # In these cases model starting index is set to 0
128
+ if len(model_start_i) == 0:
129
+ model_start_i = np.array([0])
130
+
131
+ if model is None:
132
+ # Add exclusive end of file
133
+ model_start_i = np.concatenate((model_start_i, [len(self.lines)]))
134
+ model_i = 0
135
+ remarks = []
136
+ for i in range(len(model_start_i) - 1):
137
+ start = model_start_i[i]
138
+ stop = model_start_i[i+1]
139
+ model_remark_line_i = remark_line_i[
140
+ (remark_line_i >= start) & (remark_line_i < stop)
141
+ ]
142
+ remarks.append(
143
+ "\n".join([self.lines[i][7:] for i in model_remark_line_i])
144
+ )
145
+ return remarks
146
+
147
+ else:
148
+ last_model = len(model_start_i)
149
+ if model == 0:
150
+ raise ValueError("The model index must not be 0")
151
+ # Negative models mean index starting from last model
152
+ model = last_model + model + 1 if model < 0 else model
153
+
154
+ if model < last_model:
155
+ line_filter = ( ( remark_line_i >= model_start_i[model-1] ) &
156
+ ( remark_line_i < model_start_i[model ] ) )
157
+ elif model == last_model:
158
+ line_filter = (remark_line_i >= model_start_i[model-1])
159
+ else:
160
+ raise ValueError(
161
+ f"The file has {last_model} models, "
162
+ f"the given model {model} does not exist"
163
+ )
164
+ remark_line_i = remark_line_i[line_filter]
165
+
166
+ # Do not include 'REMARK ' itself -> begin from pos 8
167
+ return "\n".join([self.lines[i][7:] for i in remark_line_i])
168
+
169
+
170
+ def get_structure(self, model=None):
171
+ """
172
+ Get an :class:`AtomArray` or :class:`AtomArrayStack` from the
173
+ PDBQT file.
174
+
175
+ Parameters
176
+ ----------
177
+ model : int, optional
178
+ If this parameter is given, the function will return an
179
+ :class:`AtomArray` from the atoms corresponding to the given
180
+ model number (starting at 1).
181
+ Negative values are used to index models starting from the
182
+ last model insted of the first model.
183
+ If this parameter is omitted, an :class:`AtomArrayStack`
184
+ containing all models will be returned, even if the
185
+ structure contains only one model.
186
+
187
+ Returns
188
+ -------
189
+ array : AtomArray or AtomArrayStack
190
+ The return type depends on the `model` parameter.
191
+ """
192
+ # Line indices where a new model starts
193
+ model_start_i = np.array([i for i in range(len(self.lines))
194
+ if self.lines[i].startswith(("MODEL"))],
195
+ dtype=int)
196
+ # Line indices with ATOM or HETATM records
197
+ atom_line_i = np.array([i for i in range(len(self.lines)) if
198
+ self.lines[i].startswith(("ATOM", "HETATM"))],
199
+ dtype=int)
200
+ # Structures containing only one model may omit MODEL record
201
+ # In these cases model starting index is set to 0
202
+ if len(model_start_i) == 0:
203
+ model_start_i = np.array([0])
204
+
205
+ if model is None:
206
+ depth = len(model_start_i)
207
+ length = self._get_model_length(model_start_i, atom_line_i)
208
+ array = AtomArrayStack(depth, length)
209
+ # Line indices for annotation determination
210
+ # Annotation is determined from model 1,
211
+ # therefore from ATOM records before second MODEL record
212
+ if len(model_start_i) == 1:
213
+ annot_i = atom_line_i
214
+ else:
215
+ annot_i = atom_line_i[atom_line_i < model_start_i[1]]
216
+ # Line indices for coordinate determination
217
+ coord_i = atom_line_i
218
+
219
+ else:
220
+ last_model = len(model_start_i)
221
+ if model == 0:
222
+ raise ValueError("The model index must not be 0")
223
+ # Negative models mean index starting from last model
224
+ model = last_model + model + 1 if model < 0 else model
225
+
226
+ if model < last_model:
227
+ line_filter = ( ( atom_line_i >= model_start_i[model-1] ) &
228
+ ( atom_line_i < model_start_i[model ] ) )
229
+ elif model == last_model:
230
+ line_filter = (atom_line_i >= model_start_i[model-1])
231
+ else:
232
+ raise ValueError(
233
+ f"The file has {last_model} models, "
234
+ f"the given model {model} does not exist"
235
+ )
236
+ annot_i = coord_i = atom_line_i[line_filter]
237
+ array = AtomArray(len(coord_i))
238
+
239
+ # Save atom IDs for later sorting into the original atom order
240
+ atom_id = np.zeros(array.array_length(), int)
241
+
242
+ # Create annotation arrays
243
+ chain_id = np.zeros(array.array_length(), array.chain_id.dtype)
244
+ res_id = np.zeros(array.array_length(), array.res_id.dtype)
245
+ ins_code = np.zeros(array.array_length(), array.ins_code.dtype)
246
+ res_name = np.zeros(array.array_length(), array.res_name.dtype)
247
+ hetero = np.zeros(array.array_length(), array.hetero.dtype)
248
+ atom_name = np.zeros(array.array_length(), array.atom_name.dtype)
249
+ element = np.zeros(array.array_length(), array.element.dtype)
250
+
251
+ # Fill annotation array
252
+ # i is index in array, line_i is line index
253
+ for i, line_i in enumerate(annot_i):
254
+ line = self.lines[line_i]
255
+
256
+ atom_id[i] = int(line[6:11])
257
+ chain_id[i] = line[21].strip()
258
+ res_id[i] = int(line[22:26])
259
+ ins_code[i] = line[26].strip()
260
+ res_name[i] = line[17:20].strip()
261
+ hetero[i] = (False if line[0:4] == "ATOM" else True)
262
+ atom_name[i] = line[12:16].strip()
263
+ element[i] = line[76:78].strip()
264
+
265
+ # Add annotation arrays to atom array (stack)
266
+ array.chain_id = chain_id
267
+ array.res_id = res_id
268
+ array.ins_code = ins_code
269
+ array.res_name = res_name
270
+ array.hetero = hetero
271
+ array.atom_name = atom_name
272
+ array.element = element
273
+
274
+ # Fill in coordinates
275
+ if isinstance(array, AtomArray):
276
+ for i, line_i in enumerate(coord_i):
277
+ line = self.lines[line_i]
278
+ array.coord[i,0] = float(line[30:38])
279
+ array.coord[i,1] = float(line[38:46])
280
+ array.coord[i,2] = float(line[46:54])
281
+
282
+ elif isinstance(array, AtomArrayStack):
283
+ m = 0
284
+ i = 0
285
+ for line_i in atom_line_i:
286
+ if m < len(model_start_i)-1 and line_i > model_start_i[m+1]:
287
+ m += 1
288
+ i = 0
289
+ line = self.lines[line_i]
290
+ array.coord[m,i,0] = float(line[30:38])
291
+ array.coord[m,i,1] = float(line[38:46])
292
+ array.coord[m,i,2] = float(line[46:54])
293
+ i += 1
294
+
295
+ # Sort into the original atom order
296
+ array = array[..., np.argsort(atom_id)]
297
+
298
+ return array
299
+
300
+
301
+ def set_structure(self, atoms, charges=None, atom_types=None,
302
+ rotatable_bonds=None, root=None, include_torsdof=True):
303
+ """
304
+ Write an :class:`AtomArray` into the PDBQT file.
305
+
306
+ Parameters
307
+ ----------
308
+ atoms : AtomArray, shape=(n,)
309
+ The atoms to be written into this file.
310
+ Must have an associated :class:`BondList`.
311
+ charges : ndarray, shape=(n,), dtype=float, optional
312
+ Partial charges for each atom in `atoms`.
313
+ By default, the charges are calculated using the PEOE method
314
+ (:func:`partial_charges()`).
315
+ atom_types : ndarray, shape=(n,), dtype="U1", optional
316
+ Custom *AutoDock* atom types for each atom in `atoms`.
317
+ rotatable_bonds : None or 'rigid' or 'all' or BondList, optional
318
+ This parameter describes, how rotatable bonds are handled,
319
+ with respect to ``ROOT``, ``BRANCH`` and ``ENDBRANCH``
320
+ lines.
321
+
322
+ - ``None`` - The molecule is handled as rigid receptor:
323
+ No ``ROOT``, ``BRANCH`` and ``ENDBRANCH`` lines will
324
+ be written.
325
+ - ``'rigid'`` - The molecule is handled as rigid ligand:
326
+ Only a ``ROOT`` line will be written.
327
+ - ``'all'`` - The molecule is handled as flexible
328
+ ligand:
329
+ A ``ROOT`` line will be written and all rotatable
330
+ bonds are included using ``BRANCH`` and ``ENDBRANCH``
331
+ lines.
332
+ - :class:`BondList` - The molecule is handled as
333
+ flexible ligand:
334
+ A ``ROOT`` line will be written and all bonds in the
335
+ given :class:`BondList` are considered flexible via
336
+ ``BRANCH`` and ``ENDBRANCH`` lines.
337
+
338
+ root : int, optional
339
+ Specifies the index of the atom following the ``ROOT`` line.
340
+ Setting the root atom is useful for specifying the *anchor*
341
+ in flexible side chains.
342
+ This parameter has no effect, if `rotatable_bonds` is
343
+ ``None``.
344
+ By default, the first atom is also the root atom.
345
+ include_torsdof : bool, optional
346
+ By default, a ``TORSDOF`` (torsional degrees of freedom)
347
+ record is written at the end of the file.
348
+ By setting this parameter to false, the record is omitted.
349
+
350
+ Returns
351
+ -------
352
+ mask : ndarray, shape=(n,), dtype=bool
353
+ A boolean mask, that is ``False`` for each atom of the input
354
+ ``atoms``, that was removed due to being a nonpolar
355
+ hydrogen.
356
+ """
357
+ # Check if AtomArray is suitable for PDBQT
358
+ max_atoms, max_residues = 99999, 9999
359
+ if atoms.array_length() > max_atoms:
360
+ warnings.warn(f"More then {max_atoms:,} atoms per model")
361
+ if (atoms.res_id > max_residues).any():
362
+ warnings.warn(f"Residue IDs exceed {max_residues:,}")
363
+ if np.isnan(atoms.coord).any():
364
+ raise BadStructureError("Coordinates contain 'NaN' values")
365
+ if any([len(name) > 1 for name in atoms.chain_id]):
366
+ raise BadStructureError("Some chain IDs exceed 1 character")
367
+ if any([len(name) > 3 for name in atoms.res_name]):
368
+ raise BadStructureError("Some residue names exceed 3 characters")
369
+ if any([len(name) > 4 for name in atoms.atom_name]):
370
+ raise BadStructureError("Some atom names exceed 4 characters")
371
+
372
+ if charges is None:
373
+ charges = partial_charges(atoms)
374
+ charges[np.isnan(charges)] = 0
375
+ else:
376
+ if np.isnan(charges).any():
377
+ raise ValueError("Input charges contain NaN values")
378
+
379
+ # Get AutoDock atom types and remove nonpolar hydrogen atoms
380
+ atoms, charges, types, mask = convert_atoms(atoms, charges)
381
+ # Overwrite calculated atom types with input atom types
382
+ if atom_types is not None:
383
+ types = atom_types[mask]
384
+
385
+ if rotatable_bonds is None:
386
+ # No rotatable bonds -> the BondList contains no bonds
387
+ rotatable_bonds = BondList(atoms.bonds.get_atom_count())
388
+ use_root = False
389
+ elif rotatable_bonds == "rigid":
390
+ rotatable_bonds = BondList(atoms.bonds.get_atom_count())
391
+ use_root = True
392
+ elif rotatable_bonds == "all":
393
+ rotatable_bonds = find_rotatable_bonds(atoms.bonds)
394
+ use_root = True
395
+ else:
396
+ if rotatable_bonds.ndim != 2 or rotatable_bonds.shape[1] != 2:
397
+ raise ValueError(
398
+ "An (nx2) array is expected for rotatable bonds"
399
+ )
400
+ rotatable_bonds = BondList(
401
+ len(mask), np.asarray(rotatable_bonds)
402
+ )[mask]
403
+ use_root = True
404
+
405
+ if root is None:
406
+ root_index = 0
407
+ else:
408
+ # Find new index of root atom, since the index might have
409
+ # been shifted due to removed atoms
410
+ original_indices = np.arange(len(mask))
411
+ new_indices = original_indices[mask]
412
+ try:
413
+ root_index = np.where(new_indices == root)[0][0]
414
+ except IndexError:
415
+ raise ValueError(
416
+ "The given root atom index points to an nonpolar hydrogen "
417
+ "atom, that has been removed"
418
+ )
419
+ # Add bonds of the rigid root to rotatable bonds,
420
+ # as they probably have been filtered out,
421
+ # as the root is probably a terminal atom
422
+ for atom, bond_type in zip(*atoms.bonds.get_bonds(root_index)):
423
+ rotatable_bonds.add_bond(root_index, atom, bond_type)
424
+
425
+ # Break rotatable bonds
426
+ # for simple branch determination in '_write_atoms()'
427
+ atoms.bonds.remove_bonds(rotatable_bonds)
428
+
429
+ hetero = ["ATOM" if e == False else "HETATM" for e in atoms.hetero]
430
+ if "atom_id" in atoms.get_annotation_categories():
431
+ atom_id = atoms.atom_id
432
+ else:
433
+ atom_id = np.arange(1, atoms.array_length()+1)
434
+ occupancy = np.ones(atoms.array_length())
435
+ b_factor = np.zeros(atoms.array_length())
436
+
437
+ # Convert rotatable bonds into array for easier handling
438
+ # The bond type is irrelevant from this point on
439
+ rotatable_bonds = rotatable_bonds.as_array()[:,:2]
440
+
441
+ self.lines = []
442
+ self._write_atoms(
443
+ atoms, charges, types,
444
+ atom_id, hetero, occupancy, b_factor,
445
+ root_index, rotatable_bonds,
446
+ np.zeros(len(rotatable_bonds), dtype=bool), use_root
447
+ )
448
+ if include_torsdof:
449
+ self.lines.append(f"TORSDOF {len(rotatable_bonds)}")
450
+
451
+ return mask
452
+
453
+
454
+ def _write_atoms(self, atoms, charges, types,
455
+ atom_id, hetero, occupancy, b_factor,
456
+ root_atom, rotatable_bonds, visited_rotatable_bonds,
457
+ is_root):
458
+ if len(rotatable_bonds) != 0:
459
+ # Get the indices to atoms of this branch, i.e. a group of
460
+ # atoms that are connected by non-rotatable bonds
461
+ # Use 'find_connected()', since rotatable bonds were removed
462
+ # from the BondList before
463
+ this_branch_indices = find_connected(atoms.bonds, root_atom)
464
+ # The root atom of the branch, i.e. the atom connected by
465
+ # the rotatable bond should always be listed first
466
+ # -> Remove root atom and insert it at the beginning
467
+ this_branch_indices = np.insert(
468
+ this_branch_indices[this_branch_indices != root_atom],
469
+ 0,
470
+ root_atom
471
+ )
472
+ else:
473
+ # No rotatable bonds
474
+ # -> all atom are in root i.e. this branch
475
+ this_branch_indices = np.arange(atoms.array_length())
476
+
477
+ if is_root:
478
+ self.lines.append("ROOT")
479
+ for i in this_branch_indices:
480
+ self.lines.append(
481
+ f"{hetero[i]:6}"
482
+ f"{atom_id[i]:>5d} "
483
+ f"{atoms.atom_name[i]:4} "
484
+ f"{atoms.res_name[i]:3} "
485
+ f"{atoms.chain_id[i]:1}"
486
+ f"{atoms.res_id[i]:>4d}"
487
+ f"{atoms.ins_code[i]:1} "
488
+ f"{atoms.coord[i,0]:>8.3f}"
489
+ f"{atoms.coord[i,1]:>8.3f}"
490
+ f"{atoms.coord[i,2]:>8.3f}"
491
+ f"{occupancy[i]:>6.2f}"
492
+ f"{b_factor[i]:>6.2f} "
493
+ f"{charges[i]:>6.3f} "
494
+ f"{types[i]:2}"
495
+ )
496
+ if is_root:
497
+ self.lines.append("ENDROOT")
498
+
499
+ if len(rotatable_bonds) == 0:
500
+ # No rotatable bonds -> no branching
501
+ return
502
+
503
+ for k, (i, j) in enumerate(rotatable_bonds):
504
+ if visited_rotatable_bonds[k]:
505
+ continue
506
+
507
+ # Create a new branch for each rotatable bond,
508
+ # that connects to an atom of this branch
509
+ if i in this_branch_indices:
510
+ this_br_i = i
511
+ new_br_i = j
512
+ elif j in this_branch_indices:
513
+ this_br_i = j
514
+ new_br_i = i
515
+ else:
516
+ # Rotatable bond does not start from this branch
517
+ continue
518
+
519
+ # Mark rotatable bond as visited as otherwise branches would
520
+ # be created back and forth over the same rotatable bond and
521
+ # this method would never terminate
522
+ visited_rotatable_bonds[k] = True
523
+
524
+ self.lines.append(
525
+ f"BRANCH {atom_id[this_br_i]:>3d} {atom_id[new_br_i]:>3d}"
526
+ )
527
+ self._write_atoms(
528
+ atoms, charges, types,
529
+ atom_id, hetero, occupancy, b_factor,
530
+ # The root atom of the branch
531
+ #is the other atom of the rotatable bond
532
+ new_br_i, rotatable_bonds, visited_rotatable_bonds,
533
+ False
534
+ )
535
+ self.lines.append(
536
+ f"ENDBRANCH {atom_id[this_br_i]:>3d} {atom_id[new_br_i]:>3d}"
537
+ )
538
+
539
+
540
+ def _get_model_length(self, model_start_i, atom_line_i):
541
+ """
542
+ Determine length of models and check that all models
543
+ have equal length.
544
+ """
545
+ n_models = len(model_start_i)
546
+ length = None
547
+ for model_i in range(len(model_start_i)):
548
+ model_start = model_start_i[model_i]
549
+ model_stop = model_start_i[model_i+1] if model_i+1 < n_models \
550
+ else len(self.lines)
551
+ model_length = np.count_nonzero(
552
+ (atom_line_i >= model_start) & (atom_line_i < model_stop)
553
+ )
554
+ if length is None:
555
+ length = model_length
556
+ if model_length != length:
557
+ raise InvalidFileError(
558
+ f"Model {model_i+1} has {model_length} atoms, "
559
+ f"but model 1 has {length} atoms, must be equal"
560
+ )
561
+ return length
562
+
563
+
564
+ def convert_atoms(atoms, charges):
565
+ """
566
+ Convert atoms into *AutoDock* compatible atoms.
567
+
568
+ Parameters
569
+ ----------
570
+ atoms : AtomArray
571
+ The atoms to be converted.
572
+ charges : ndarray, dtype=float
573
+ Partial charges for the atoms.
574
+
575
+ Returns
576
+ -------
577
+ converted_atoms : AtomArray
578
+ The input `atoms`, but with deleted nonpolar hydrogen atoms.
579
+ charges : ndarray, dtype=float
580
+ The input `charges`, but with deleted entries for nonpolar
581
+ hydrogen atoms.
582
+ atom_types : ndarray, dtype="U1"
583
+ The *AutoDock* atom types.
584
+ mask : ndarray, shape=(n,), dtype=bool
585
+ A boolean mask, that is ``False`` for each atom of the input
586
+ ``atoms``, that was removed due to being a nonpolar hydrogen.
587
+ """
588
+ charges = charges.copy()
589
+ all_bonds, all_bond_types = atoms.bonds.get_all_bonds()
590
+
591
+ atom_types = np.zeros(atoms.array_length(), dtype="U2")
592
+ hydrogen_removal_mask = np.zeros(atoms.array_length(), dtype=bool)
593
+ for i in range(atoms.array_length()):
594
+ element = atoms.element[i]
595
+ bonded_atoms = all_bonds[i][all_bonds[i] != -1]
596
+ if element == "H":
597
+ if len(bonded_atoms) == 0:
598
+ # Free proton
599
+ atom_types[i] = "H"
600
+ elif len(bonded_atoms) == 1:
601
+ j = bonded_atoms[0]
602
+ bonded_element = atoms.element[j]
603
+ if bonded_element == "C":
604
+ # Remove hydrogen and add its charge
605
+ # to charge of bonded carbon
606
+ charges[j] += charges[i]
607
+ hydrogen_removal_mask[i] = True
608
+ else:
609
+ atom_types[i] = "HD"
610
+ else:
611
+ raise BadStructureError(
612
+ "Structure contains hydrogen with multiple bonds"
613
+ )
614
+ elif element == "C":
615
+ if np.isin(
616
+ all_bond_types[i],
617
+ [BondType.AROMATIC_SINGLE, BondType.AROMATIC_DOUBLE]
618
+ ).any():
619
+ # Aromatic carbon
620
+ atom_types[i] = "A"
621
+ else:
622
+ # Alphatic carbon
623
+ atom_types[i] = "C"
624
+ elif element == "N":
625
+ atom_types[i] = "NA"
626
+ elif element == "O":
627
+ atom_types[i] = "OA"
628
+ elif element == "S":
629
+ atom_types[i] = "SA"
630
+ elif element.capitalize() in PARAMETRIZED_ELEMENTS:
631
+ atom_types[i] = element.capitalize()
632
+ else:
633
+ warnings.warn(
634
+ f"Element {element} is not paramtrized, "
635
+ f"using parameters for hydrogen instead"
636
+ )
637
+ atom_types[i] = "H"
638
+
639
+ mask = ~hydrogen_removal_mask
640
+ return atoms[mask], charges[mask], atom_types[mask], mask
@@ -0,0 +1,23 @@
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 subpackage provides support for the the modern PDBx file formats.
7
+ The :class:`CIFFile` class provides dictionary-like access to
8
+ every field in text-based *mmCIF* files.
9
+ :class:`BinaryCIFFile` provides analogous functionality for the
10
+ *BinaryCIF* format.
11
+ Additional utility functions allow reading and writing structures
12
+ from/to these files.
13
+ """
14
+
15
+ __name__ = "biotite.structure.io.pdbx"
16
+ __author__ = "Patrick Kunzmann"
17
+
18
+ from .convert import *
19
+ from .bcif import *
20
+ from .cif import *
21
+ from .component import *
22
+ from .encoding import *
23
+ from .legacy import *