biotite 1.5.0__cp313-cp313-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-313-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-313-x86_64-linux-gnu.so +0 -0
  78. biotite/sequence/align/kmeralphabet.pyx +595 -0
  79. biotite/sequence/align/kmersimilarity.cpython-313-x86_64-linux-gnu.so +0 -0
  80. biotite/sequence/align/kmersimilarity.pyx +233 -0
  81. biotite/sequence/align/kmertable.cpython-313-x86_64-linux-gnu.so +0 -0
  82. biotite/sequence/align/kmertable.pyx +3411 -0
  83. biotite/sequence/align/localgapped.cpython-313-x86_64-linux-gnu.so +0 -0
  84. biotite/sequence/align/localgapped.pyx +892 -0
  85. biotite/sequence/align/localungapped.cpython-313-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-313-x86_64-linux-gnu.so +0 -0
  181. biotite/sequence/align/multiple.pyx +619 -0
  182. biotite/sequence/align/pairwise.cpython-313-x86_64-linux-gnu.so +0 -0
  183. biotite/sequence/align/pairwise.pyx +585 -0
  184. biotite/sequence/align/permutation.cpython-313-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-313-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-313-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-313-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-313-x86_64-linux-gnu.so +0 -0
  244. biotite/sequence/phylo/nj.pyx +221 -0
  245. biotite/sequence/phylo/tree.cpython-313-x86_64-linux-gnu.so +0 -0
  246. biotite/sequence/phylo/tree.pyx +1169 -0
  247. biotite/sequence/phylo/upgma.cpython-313-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-313-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-313-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-313-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-313-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-313-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-313-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,322 @@
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
+ Use this module to calculate the Solvent Accessible Surface Area (SASA) of
7
+ a protein or single atoms.
8
+ """
9
+
10
+ __name__ = "biotite.structure"
11
+ __author__ = "Patrick Kunzmann"
12
+ __all__ = ["sasa"]
13
+
14
+ cimport cython
15
+ cimport numpy as np
16
+ from libc.stdlib cimport malloc, free
17
+
18
+ import numpy as np
19
+ from .celllist import CellList
20
+ from .filter import filter_solvent, filter_monoatomic_ions
21
+ from .info.radii import vdw_radius_protor, vdw_radius_single
22
+
23
+ ctypedef np.uint8_t np_bool
24
+ ctypedef np.int64_t int64
25
+ ctypedef np.float32_t float32
26
+
27
+
28
+ @cython.boundscheck(False)
29
+ @cython.wraparound(False)
30
+ def sasa(array, float probe_radius=1.4, np.ndarray atom_filter=None,
31
+ bint ignore_ions=True, int point_number=1000,
32
+ point_distr="Fibonacci", vdw_radii="ProtOr"):
33
+ """
34
+ sasa(array, probe_radius=1.4, atom_filter=None, ignore_ions=True,
35
+ point_number=1000, point_distr="Fibonacci", vdw_radii="ProtOr")
36
+
37
+ Calculate the Solvent Accessible Surface Area (SASA) of a protein.
38
+
39
+ This function uses the Shrake-Rupley ("rolling probe")
40
+ algorithm :footcite:`Shrake1973`:
41
+ Every atom is occupied by a evenly distributed point mesh. The
42
+ points that can be reached by the "rolling probe", are surface
43
+ accessible.
44
+
45
+ Parameters
46
+ ----------
47
+ array : AtomArray
48
+ The protein model to calculate the SASA for.
49
+ probe_radius : float, optional
50
+ The VdW-radius of the solvent molecules.
51
+ atom_filter : ndarray, dtype=bool, optional
52
+ If this parameter is given, SASA is only calculated for the
53
+ filtered atoms.
54
+ ignore_ions : bool, optional
55
+ If true, all monoatomic ions are removed before SASA calculation.
56
+ point_number : int, optional
57
+ The number of points in the mesh occupying each atom for SASA
58
+ calculation.
59
+ The SASA calculation time is proportional to the amount of sphere points.
60
+ point_distr : str or function, optional
61
+ If a function is given, the function is used to calculate the
62
+ point distribution for the mesh (the function must take `float`
63
+ *n* as parameter and return a *(n x 3)* :class:`ndarray`).
64
+ Alternatively a string can be given to choose a built-in
65
+ distribution:
66
+
67
+ - **Fibonacci** - Distribute points using a golden section
68
+ spiral.
69
+
70
+ By default *Fibonacci* is used.
71
+ vdw_radii : str or ndarray, dtype=float, optional
72
+ Indicates the set of VdW radii to be used. If an `array`-length
73
+ :class:`ndarray` is given, each atom gets the radius at the
74
+ corresponding index. Radii given for atoms that are not used in
75
+ SASA calculation (e.g. solvent atoms) can have arbitrary values
76
+ (e.g. `NaN`). If instead a string is given, one of the
77
+ built-in sets is used:
78
+
79
+ - **ProtOr** - A set, which does not require hydrogen atoms
80
+ in the model. Suitable for crystal structures.
81
+ :footcite:`Tsai1999`
82
+ - **Single** - A set, which uses a defined VdW radius for
83
+ every single atom, therefore hydrogen atoms are required
84
+ in the model (e.g. NMR elucidated structures).
85
+ Values for main group elements are taken from :footcite:`Mantina2009`,
86
+ and for relevant transition metals from the :footcite:`RDKit`.
87
+
88
+ By default *ProtOr* is used.
89
+
90
+
91
+ Returns
92
+ -------
93
+ sasa : ndarray, dtype=bool, shape=(n,)
94
+ Atom-wise SASA. `NaN` for atoms where SASA has not been
95
+ calculated
96
+ (solvent atoms, hydrogen atoms (ProtOr), atoms not in `filter`).
97
+
98
+ References
99
+ ----------
100
+
101
+ .. footbibliography::
102
+
103
+ """
104
+ cdef int i=0, j=0, k=0, adj_atom_i=0, rel_atom_i=0
105
+
106
+ cdef np.ndarray sasa_filter
107
+ cdef np.ndarray occl_filter
108
+ if atom_filter is not None:
109
+ # Filter for all atoms to calculate SASA for
110
+ sasa_filter = np.array(atom_filter, dtype=bool)
111
+ else:
112
+ sasa_filter = np.ones(len(array), dtype=bool)
113
+ # Filter for all atoms that are considered for occlusion calculation
114
+ # sasa_filter is subfilter of occlusion_filter
115
+ occl_filter = np.ones(len(array), dtype=bool)
116
+ # Remove water residues, since it is the solvent
117
+ filter = ~filter_solvent(array)
118
+ sasa_filter = sasa_filter & filter
119
+ occl_filter = occl_filter & filter
120
+ if ignore_ions:
121
+ filter = ~filter_monoatomic_ions(array)
122
+ sasa_filter = sasa_filter & filter
123
+ occl_filter = occl_filter & filter
124
+
125
+ cdef np.ndarray sphere_points
126
+ if callable(point_distr):
127
+ sphere_points = point_distr(point_number)
128
+ elif point_distr == "Fibonacci":
129
+ sphere_points = _create_fibonacci_points(point_number)
130
+ else:
131
+ raise ValueError(f"'{point_distr}' is not a valid point distribution")
132
+ sphere_points = sphere_points.astype(np.float32)
133
+
134
+ cdef np.ndarray radii
135
+ if isinstance(vdw_radii, np.ndarray):
136
+ radii = vdw_radii.astype(np.float32)
137
+ if len(radii) != array.array_length():
138
+ raise ValueError(
139
+ f"Amount VdW radii ({len(radii)}) and "
140
+ f"amount of atoms ({array.array_length()}) are not equal"
141
+ )
142
+ elif vdw_radii == "ProtOr":
143
+ filter = (array.element != "H")
144
+ sasa_filter = sasa_filter & filter
145
+ occl_filter = occl_filter & filter
146
+ radii = np.full(len(array), np.nan, dtype=np.float32)
147
+ for i in np.arange(len(radii))[occl_filter]:
148
+ rad = vdw_radius_protor(array.res_name[i], array.atom_name[i])
149
+ # 1.8 is default radius
150
+ radii[i] = rad if rad is not None else 1.8
151
+ elif vdw_radii == "Single":
152
+ radii = np.full(len(array), np.nan, dtype=np.float32)
153
+ for i in np.arange(len(radii))[occl_filter]:
154
+ rad = vdw_radius_single(array.element[i])
155
+ # 1.5 is default radius
156
+ radii[i] = rad if rad is not None else 1.8
157
+ else:
158
+ raise KeyError(f"'{vdw_radii}' is not a valid radii set")
159
+ # Increase atom radii by probe size ("rolling probe")
160
+ radii += probe_radius
161
+
162
+ # Memoryview for filter
163
+ # Problem with creating boolean memoryviews
164
+ # -> Type uint8 is used
165
+ cdef np_bool[:] sasa_filter_view = np.frombuffer(sasa_filter,
166
+ dtype=np.uint8)
167
+
168
+ cdef np.ndarray occl_r = radii[occl_filter]
169
+ # Atom array containing occluding atoms
170
+ occl_array = array[occl_filter]
171
+
172
+ # Memoryviews for coordinates of entire (main) array
173
+ # and for coordinates of occluding atom array
174
+ cdef float32[:,:] main_coord = array.coord.astype(np.float32,
175
+ copy=False)
176
+ cdef float32[:,:] occl_coord = occl_array.coord.astype(np.float32,
177
+ copy=False)
178
+ # Memoryviews for sphere points
179
+ cdef float32[:,:] sphere_coord = sphere_points
180
+ # Check if any of these arrays are empty to prevent segfault
181
+ if main_coord.shape[0] == 0 \
182
+ or occl_coord.shape[0] == 0 \
183
+ or sphere_coord.shape[0] == 0:
184
+ raise ValueError("Coordinates are empty")
185
+ # Memoryviews for radii of SASA and occluding atoms
186
+ # their squares and their sum of sqaures
187
+ cdef float32[:] atom_radii = radii
188
+ cdef float32[:] atom_radii_sq = radii * radii
189
+ cdef float32[:] occl_radii = occl_r
190
+ cdef float32[:] occl_radii_sq = occl_r * occl_r
191
+ # Memoryview for atomwise SASA
192
+ cdef float32[:] sasa = np.full(len(array), np.nan, dtype=np.float32)
193
+
194
+ # Area of a sphere point on a unit sphere
195
+ cdef float32 area_per_point = 4.0 * np.pi / point_number
196
+
197
+ # Define further statically typed variables
198
+ # that are needed for SASA calculation
199
+ cdef int n_accesible = 0
200
+ cdef float32 radius = 0
201
+ cdef float32 radius_sq = 0
202
+ cdef float32 adj_radius = 0
203
+ cdef float32 adj_radius_sq = 0
204
+ cdef float32 dist_sq = 0
205
+ cdef float32 point_x = 0
206
+ cdef float32 point_y = 0
207
+ cdef float32 point_z = 0
208
+ cdef float32 atom_x = 0
209
+ cdef float32 atom_y = 0
210
+ cdef float32 atom_z = 0
211
+ cdef float32 occl_x = 0
212
+ cdef float32 occl_y = 0
213
+ cdef float32 occl_z = 0
214
+ cdef float32[:,:] relevant_occl_coord = None
215
+
216
+ # Cell size is as large as the maximum distance,
217
+ # where two atom can intersect.
218
+ # Therefore intersecting atoms are always in the same or adjacent cell.
219
+ cell_list = CellList(occl_array, np.max(radii[occl_filter])*2)
220
+ cdef np.ndarray cell_indices
221
+ cdef int[:,:] cell_indices_view
222
+ cdef int length
223
+ cdef int max_adj_list_length = 0
224
+ cdef int array_length = array.array_length()
225
+
226
+ cell_indices = cell_list.get_atoms_in_cells(array.coord)
227
+ cell_indices_view = cell_indices
228
+ max_adj_list_length = cell_indices.shape[0]
229
+
230
+ # Later on, this array stores coordinates for actual
231
+ # occluding atoms for a certain atom to calculate the
232
+ # SASA for
233
+ # The first three indices of the second axis
234
+ # are x, y and z, the last one is the squared radius
235
+ # This list is as long as the maximal length of a list of
236
+ # adjacent atoms
237
+ relevant_occl_coord = np.zeros((max_adj_list_length, 4),
238
+ dtype=np.float32)
239
+
240
+ # Actual SASA calculation
241
+ for i in range(array_length):
242
+ # First level: The atoms to calculate SASA for
243
+ if not sasa_filter_view[i]:
244
+ # SASA is not calculated for this atom
245
+ continue
246
+ n_accesible = point_number
247
+ atom_x = main_coord[i,0]
248
+ atom_y = main_coord[i,1]
249
+ atom_z = main_coord[i,2]
250
+ radius = atom_radii[i]
251
+ radius_sq = atom_radii_sq[i]
252
+ # Find occluding atoms from list of adjacent atoms
253
+ rel_atom_i = 0
254
+ for j in range(max_adj_list_length):
255
+ # Remove all atoms, where the distance to the relevant atom
256
+ # is larger than the sum of the radii,
257
+ # since those atoms do not touch
258
+ # If distance is 0, it is the same atom,
259
+ # and the atom is removed from the list as well
260
+ adj_atom_i = cell_indices_view[i,j]
261
+ if adj_atom_i == -1:
262
+ # -1 means end of list
263
+ break
264
+ occl_x = occl_coord[adj_atom_i,0]
265
+ occl_y = occl_coord[adj_atom_i,1]
266
+ occl_z = occl_coord[adj_atom_i,2]
267
+ adj_radius = occl_radii[adj_atom_i]
268
+ adj_radius_sq = occl_radii_sq[adj_atom_i]
269
+ dist_sq = distance_sq(atom_x, atom_y, atom_z,
270
+ occl_x, occl_y, occl_z)
271
+ if dist_sq != 0 \
272
+ and dist_sq < (adj_radius+radius) * (adj_radius+radius):
273
+ relevant_occl_coord[rel_atom_i,0] = occl_x
274
+ relevant_occl_coord[rel_atom_i,1] = occl_y
275
+ relevant_occl_coord[rel_atom_i,2] = occl_z
276
+ relevant_occl_coord[rel_atom_i,3] = adj_radius_sq
277
+ rel_atom_i += 1
278
+ for j in range(sphere_coord.shape[0]):
279
+ # Second level: The sphere points for that atom
280
+ # Transform sphere point to sphere of current atom
281
+ point_x = sphere_coord[j,0] * radius + atom_x
282
+ point_y = sphere_coord[j,1] * radius + atom_y
283
+ point_z = sphere_coord[j,2] * radius + atom_z
284
+ for k in range(rel_atom_i):
285
+ # Third level: Compare point to occluding atoms
286
+ dist_sq = distance_sq(point_x, point_y, point_z,
287
+ relevant_occl_coord[k, 0],
288
+ relevant_occl_coord[k, 1],
289
+ relevant_occl_coord[k, 2])
290
+ # Compare squared distance
291
+ # to squared radius of occluding atom
292
+ # (Radius is relevant_occl_coord[3])
293
+ if dist_sq < relevant_occl_coord[k, 3]:
294
+ # Point is occluded
295
+ # -> Continue with next point
296
+ n_accesible -= 1
297
+ break
298
+ sasa[i] = area_per_point * n_accesible * radius_sq
299
+ return np.asarray(sasa)
300
+
301
+
302
+ cdef inline float32 distance_sq(float32 x1, float32 y1, float32 z1,
303
+ float32 x2, float32 y2, float32 z2):
304
+ cdef float32 dx = x2 - x1
305
+ cdef float32 dy = y2 - y1
306
+ cdef float32 dz = z2 - z1
307
+ return dx*dx + dy*dy + dz*dz
308
+
309
+
310
+ def _create_fibonacci_points(n):
311
+ """
312
+ Get an array of approximately equidistant points on a sphere surface
313
+ using a golden section spiral.
314
+ """
315
+ phi = (3 - np.sqrt(5)) * np.pi * np.arange(n)
316
+ z = np.linspace(1 - 1.0/n, 1.0/n - 1, n)
317
+ radius = np.sqrt(1 - z*z)
318
+ coords = np.zeros((n, 3))
319
+ coords[:,0] = radius * np.cos(phi)
320
+ coords[:,1] = radius * np.sin(phi)
321
+ coords[:,2] = z
322
+ return coords
@@ -0,0 +1,328 @@
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"
6
+ __author__ = "Patrick Kunzmann"
7
+ __all__ = [
8
+ "get_segment_starts",
9
+ "apply_segment_wise",
10
+ "spread_segment_wise",
11
+ "get_segment_masks",
12
+ "get_segment_starts_for",
13
+ "get_segment_positions",
14
+ "get_all_segment_positions",
15
+ "segment_iter",
16
+ ]
17
+
18
+ import numpy as np
19
+
20
+
21
+ def get_segment_starts(
22
+ array, add_exclusive_stop, continuous_categories=(), equal_categories=()
23
+ ):
24
+ """
25
+ Generalized version of :func:`get_residue_starts()` for residues and chains.
26
+
27
+ The starts are determined from value changes in the given annotations.
28
+
29
+ Parameters
30
+ ----------
31
+ array : AtomArray or AtomArrayStack
32
+ The atom array (stack) to get the segment starts from.
33
+ add_exclusive_stop : bool, optional
34
+ If true, the exclusive stop of the input atom array,
35
+ i.e. ``array.array_length()``, is added to the returned array of start indices
36
+ as last element.
37
+ continuous_categories : tuple of str, optional
38
+ Annotation categories that are expected to be continuously increasing within a
39
+ segment.
40
+ This means if the value of such an annotation decreases from one atom to
41
+ another, a new segment is started.
42
+ equal_categories : tuple of str, optional
43
+ Annotation categories that are expected to be equal within a segment.
44
+ This means if the value of such an annotation changes from one atom to
45
+ another, a new segment is started.
46
+
47
+ Returns
48
+ -------
49
+ starts : ndarray, dtype=int
50
+ The start indices of segments in `array`.
51
+ """
52
+ if array.array_length() == 0:
53
+ return np.array([], dtype=int)
54
+
55
+ segment_start_mask = np.zeros(array.array_length() - 1, dtype=bool)
56
+ for annot_name in continuous_categories:
57
+ annotation = array.get_annotation(annot_name)
58
+ segment_start_mask |= np.diff(annotation) < 0
59
+ for annot_name in equal_categories:
60
+ annotation = array.get_annotation(annot_name)
61
+ segment_start_mask |= annotation[1:] != annotation[:-1]
62
+
63
+ # Convert mask to indices
64
+ # Add 1, to shift the indices from the end of a segment
65
+ # to the start of a new segment
66
+ segment_starts = np.where(segment_start_mask)[0] + 1
67
+
68
+ # The first chain is not included yet -> Insert '[0]'
69
+ if add_exclusive_stop:
70
+ return np.concatenate(([0], segment_starts, [array.array_length()]))
71
+ else:
72
+ return np.concatenate(([0], segment_starts))
73
+
74
+
75
+ def apply_segment_wise(starts, data, function, axis=None):
76
+ """
77
+ Generalized version of :func:`apply_residue_wise()` for
78
+ residues and chains.
79
+
80
+ Parameters
81
+ ----------
82
+ starts : ndarray, dtype=int
83
+ The sorted start indices of segments.
84
+ Includes exclusive stop, i.e. the length of the corresponding
85
+ atom array.
86
+ data : ndarray
87
+ The data, whose intervals are the parameter for `function`.
88
+ Must have same length as `array`.
89
+ function : function
90
+ The `function` must have either the form *f(data)* or
91
+ *f(data, axis)* in case `axis` is given. Every `function` call
92
+ must return a value with the same shape and data type.
93
+ axis : int, optional
94
+ This value is given to the `axis` parameter of `function`.
95
+
96
+ Returns
97
+ -------
98
+ processed_data : ndarray
99
+ Segment-wise evaluation of `data` by `function`.
100
+ The size of the first dimension of this array is equal to the amount of
101
+ residues.
102
+ """
103
+ # The result array
104
+ processed_data = None
105
+ for i in range(len(starts) - 1):
106
+ segment = data[starts[i] : starts[i + 1]]
107
+ if axis is None:
108
+ value = function(segment)
109
+ else:
110
+ value = function(segment, axis=axis)
111
+ # Identify the shape of the resulting array by evaluation
112
+ # of the function return value for the first segment
113
+ if processed_data is None:
114
+ if isinstance(value, np.ndarray):
115
+ # Maximum length of the processed data
116
+ # is length of segment of size 1 -> length of all IDs
117
+ # (equal to atom array length)
118
+ processed_data = np.zeros(
119
+ (len(starts) - 1,) + value.shape, dtype=value.dtype
120
+ )
121
+ else:
122
+ # Scalar value -> one dimensional result array
123
+ processed_data = np.zeros(len(starts) - 1, dtype=type(value))
124
+ # Write values into result arrays
125
+ processed_data[i] = value
126
+ return processed_data
127
+
128
+
129
+ def spread_segment_wise(starts, input_data):
130
+ """
131
+ Generalized version of :func:`spread_residue_wise()`
132
+ for residues and chains.
133
+
134
+ Parameters
135
+ ----------
136
+ starts : ndarray, dtype=int
137
+ The sorted start indices of segments.
138
+ Includes exclusive stop, i.e. the length of the corresponding
139
+ atom array.
140
+ input_data : ndarray
141
+ The data to be spread.
142
+ The length of the 0-th axis must be equal to the amount of different residue IDs
143
+ in `array`.
144
+
145
+ Returns
146
+ -------
147
+ output_data : ndarray
148
+ Segment-wise spread `input_data`.
149
+ Length is the same as `array_length()` of `array`.
150
+ """
151
+ seg_lens = starts[1:] - starts[:-1]
152
+ return np.repeat(input_data, seg_lens, axis=0)
153
+
154
+
155
+ def get_segment_masks(starts, indices):
156
+ """
157
+ Generalized version of :func:`get_residue_masks()`
158
+ for residues and chains.
159
+
160
+ Parameters
161
+ ----------
162
+ starts : ndarray, dtype=int
163
+ The sorted start indices of segments.
164
+ Includes exclusive stop, i.e. the length of the corresponding
165
+ atom array.
166
+ indices : ndarray, dtype=int, shape=(k,)
167
+ These indices indicate the atoms to get the corresponding
168
+ segments for.
169
+ Negative indices are not allowed.
170
+
171
+ Returns
172
+ -------
173
+ residues_masks : ndarray, dtype=bool, shape=(k,n)
174
+ Multiple boolean masks, one for each given index in `indices`.
175
+ Each array masks the atoms that belong to the same segment as
176
+ the atom at the given index.
177
+ """
178
+ indices = np.asarray(indices)
179
+ length = starts[-1]
180
+ masks = np.zeros((len(indices), length), dtype=bool)
181
+
182
+ if (indices < 0).any():
183
+ raise ValueError("This function does not support negative indices")
184
+ if (indices >= length).any():
185
+ index = np.min(np.where(indices >= length)[0])
186
+ raise ValueError(
187
+ f"Index {index} is out of range for an atom array with length {length}"
188
+ )
189
+
190
+ insertion_points = np.searchsorted(starts, indices, side="right") - 1
191
+ for i, point in enumerate(insertion_points):
192
+ masks[i, starts[point] : starts[point + 1]] = True
193
+
194
+ return masks
195
+
196
+
197
+ def get_segment_starts_for(starts, indices):
198
+ """
199
+ Generalized version of :func:`get_residue_starts_for()`
200
+ for residues and chains.
201
+
202
+ Parameters
203
+ ----------
204
+ starts : ndarray, dtype=int
205
+ The sorted start indices of segments.
206
+ Includes exclusive stop, i.e. the length of the corresponding
207
+ atom array.
208
+ indices : ndarray, dtype=int, shape=(k,)
209
+ These indices point to the atoms to get the corresponding
210
+ segment starts for.
211
+ Negative indices are not allowed.
212
+
213
+ Returns
214
+ -------
215
+ start_indices : ndarray, dtype=int, shape=(k,)
216
+ The indices that point to the segment starts for the input
217
+ `indices`.
218
+ """
219
+ indices = np.asarray(indices)
220
+ length = starts[-1]
221
+ # Remove exclusive stop
222
+ starts = starts[:-1]
223
+
224
+ if (indices < 0).any():
225
+ raise ValueError("This function does not support negative indices")
226
+ if (indices >= length).any():
227
+ index = np.min(np.where(indices >= length)[0])
228
+ raise ValueError(
229
+ f"Index {index} is out of range for an atom array with length {length}"
230
+ )
231
+
232
+ insertion_points = np.searchsorted(starts, indices, side="right") - 1
233
+ return starts[insertion_points]
234
+
235
+
236
+ def get_segment_positions(starts, indices):
237
+ """
238
+ Generalized version of :func:`get_residue_positions()`
239
+ for residues and chains.
240
+
241
+ Parameters
242
+ ----------
243
+ starts : ndarray, dtype=int
244
+ The sorted start indices of segments.
245
+ Includes exclusive stop, i.e. the length of the corresponding
246
+ atom array.
247
+ indices : ndarray, shape=(k,)
248
+ These indices point to the atoms to get the corresponding
249
+ residue positions for.
250
+ Negative indices are not allowed.
251
+
252
+ Returns
253
+ -------
254
+ segment_indices : ndarray, shape=(k,)
255
+ The indices that point to the position of the segments.
256
+
257
+ See Also
258
+ --------
259
+ get_all_segment_positions :
260
+ Similar to this function, but for all atoms in the :class:`struc.AtomArray`.
261
+ """
262
+ indices = np.asarray(indices)
263
+ length = starts[-1]
264
+ # Remove exclusive stop
265
+ starts = starts[:-1]
266
+
267
+ if (indices < 0).any():
268
+ raise ValueError("This function does not support negative indices")
269
+ if (indices >= length).any():
270
+ index = np.min(np.where(indices >= length)[0])
271
+ raise ValueError(
272
+ f"Index {index} is out of range for an atom array with length {length}"
273
+ )
274
+
275
+ return np.searchsorted(starts, indices, side="right") - 1
276
+
277
+
278
+ def get_all_segment_positions(starts, length):
279
+ """
280
+ Generalized version of :func:`get_all_residue_positions()`
281
+ for residues and chains.
282
+
283
+ Parameters
284
+ ----------
285
+ starts : ndarray, dtype=int
286
+ The sorted start indices of segments.
287
+ Includes exclusive stop, i.e. the length of the corresponding
288
+ atom array.
289
+ length : int
290
+ The length of the corresponding :class:`struc.AtomArray`.
291
+
292
+ Returns
293
+ -------
294
+ segment_indices : ndarray, shape=(k,)
295
+ For each atom the indices that point to the corresponding position of the
296
+ segments.
297
+
298
+ See Also
299
+ --------
300
+ get_segment_positions :
301
+ Similar to this function, but for a given subset of atom indices.
302
+ """
303
+ segment_changes = np.zeros(length, dtype=int)
304
+ segment_changes[starts[1:-1]] = 1
305
+ return np.cumsum(segment_changes)
306
+
307
+
308
+ def segment_iter(array, starts):
309
+ """
310
+ Generalized version of :func:`residue_iter()`
311
+ for residues and chains.
312
+
313
+ Parameters
314
+ ----------
315
+ array : AtomArray or AtomArrayStack
316
+ The structure to iterate over.
317
+ starts : ndarray, dtype=int
318
+ The sorted start indices of segments.
319
+ Includes exclusive stop, i.e. the length of the corresponding
320
+ atom array.
321
+
322
+ Yields
323
+ ------
324
+ segment : AtomArray or AtomArrayStack
325
+ Each residue or chain of the structure.
326
+ """
327
+ for i in range(len(starts) - 1):
328
+ yield array[..., starts[i] : starts[i + 1]]