biotite 1.1.0__cp312-cp312-macosx_11_0_arm64.whl → 1.2.0__cp312-cp312-macosx_11_0_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 (155) hide show
  1. biotite/application/application.py +3 -3
  2. biotite/application/autodock/app.py +1 -1
  3. biotite/application/blast/webapp.py +1 -1
  4. biotite/application/clustalo/app.py +1 -1
  5. biotite/application/localapp.py +2 -2
  6. biotite/application/msaapp.py +10 -10
  7. biotite/application/muscle/app3.py +3 -3
  8. biotite/application/muscle/app5.py +3 -3
  9. biotite/application/sra/app.py +0 -5
  10. biotite/application/util.py +21 -1
  11. biotite/application/viennarna/rnaalifold.py +8 -8
  12. biotite/application/viennarna/rnaplot.py +3 -1
  13. biotite/application/viennarna/util.py +1 -1
  14. biotite/application/webapp.py +1 -1
  15. biotite/database/afdb/__init__.py +12 -0
  16. biotite/database/afdb/download.py +191 -0
  17. biotite/database/entrez/dbnames.py +10 -0
  18. biotite/database/entrez/download.py +9 -10
  19. biotite/database/entrez/key.py +1 -1
  20. biotite/database/entrez/query.py +5 -4
  21. biotite/database/pubchem/download.py +6 -6
  22. biotite/database/pubchem/error.py +10 -0
  23. biotite/database/pubchem/query.py +12 -23
  24. biotite/database/rcsb/download.py +3 -2
  25. biotite/database/rcsb/query.py +2 -3
  26. biotite/database/uniprot/check.py +2 -2
  27. biotite/database/uniprot/download.py +2 -5
  28. biotite/database/uniprot/query.py +3 -4
  29. biotite/file.py +14 -2
  30. biotite/interface/__init__.py +19 -0
  31. biotite/interface/openmm/__init__.py +16 -0
  32. biotite/interface/openmm/state.py +93 -0
  33. biotite/interface/openmm/system.py +227 -0
  34. biotite/interface/pymol/__init__.py +198 -0
  35. biotite/interface/pymol/cgo.py +346 -0
  36. biotite/interface/pymol/convert.py +185 -0
  37. biotite/interface/pymol/display.py +267 -0
  38. biotite/interface/pymol/object.py +1226 -0
  39. biotite/interface/pymol/shapes.py +178 -0
  40. biotite/interface/pymol/startup.py +169 -0
  41. biotite/interface/rdkit/__init__.py +15 -0
  42. biotite/interface/rdkit/mol.py +490 -0
  43. biotite/interface/version.py +71 -0
  44. biotite/interface/warning.py +19 -0
  45. biotite/sequence/align/__init__.py +0 -4
  46. biotite/sequence/align/alignment.py +33 -11
  47. biotite/sequence/align/banded.cpython-312-darwin.so +0 -0
  48. biotite/sequence/align/banded.pyx +21 -21
  49. biotite/sequence/align/cigar.py +2 -2
  50. biotite/sequence/align/kmeralphabet.cpython-312-darwin.so +0 -0
  51. biotite/sequence/align/kmeralphabet.pyx +2 -2
  52. biotite/sequence/align/kmersimilarity.cpython-312-darwin.so +0 -0
  53. biotite/sequence/align/kmertable.cpython-312-darwin.so +0 -0
  54. biotite/sequence/align/kmertable.pyx +6 -6
  55. biotite/sequence/align/localgapped.cpython-312-darwin.so +0 -0
  56. biotite/sequence/align/localgapped.pyx +47 -47
  57. biotite/sequence/align/localungapped.cpython-312-darwin.so +0 -0
  58. biotite/sequence/align/localungapped.pyx +10 -10
  59. biotite/sequence/align/matrix.py +12 -3
  60. biotite/sequence/align/multiple.cpython-312-darwin.so +0 -0
  61. biotite/sequence/align/pairwise.cpython-312-darwin.so +0 -0
  62. biotite/sequence/align/pairwise.pyx +35 -35
  63. biotite/sequence/align/permutation.cpython-312-darwin.so +0 -0
  64. biotite/sequence/align/selector.cpython-312-darwin.so +0 -0
  65. biotite/sequence/align/selector.pyx +2 -2
  66. biotite/sequence/align/statistics.py +1 -1
  67. biotite/sequence/align/tracetable.cpython-312-darwin.so +0 -0
  68. biotite/sequence/alphabet.py +2 -2
  69. biotite/sequence/annotation.py +19 -13
  70. biotite/sequence/codec.cpython-312-darwin.so +0 -0
  71. biotite/sequence/codon.py +1 -2
  72. biotite/sequence/graphics/alignment.py +25 -39
  73. biotite/sequence/graphics/dendrogram.py +4 -2
  74. biotite/sequence/graphics/features.py +2 -2
  75. biotite/sequence/graphics/logo.py +10 -12
  76. biotite/sequence/io/fasta/convert.py +1 -2
  77. biotite/sequence/io/fasta/file.py +1 -1
  78. biotite/sequence/io/fastq/file.py +3 -3
  79. biotite/sequence/io/genbank/file.py +3 -3
  80. biotite/sequence/io/genbank/sequence.py +2 -0
  81. biotite/sequence/io/gff/convert.py +1 -1
  82. biotite/sequence/io/gff/file.py +1 -2
  83. biotite/sequence/phylo/nj.cpython-312-darwin.so +0 -0
  84. biotite/sequence/phylo/tree.cpython-312-darwin.so +0 -0
  85. biotite/sequence/phylo/upgma.cpython-312-darwin.so +0 -0
  86. biotite/sequence/profile.py +19 -25
  87. biotite/sequence/search.py +0 -1
  88. biotite/sequence/seqtypes.py +12 -5
  89. biotite/sequence/sequence.py +1 -2
  90. biotite/structure/__init__.py +2 -0
  91. biotite/structure/alphabet/i3d.py +1 -2
  92. biotite/structure/alphabet/pb.py +1 -2
  93. biotite/structure/alphabet/unkerasify.py +8 -2
  94. biotite/structure/atoms.py +35 -27
  95. biotite/structure/basepairs.py +26 -26
  96. biotite/structure/bonds.cpython-312-darwin.so +0 -0
  97. biotite/structure/bonds.pyx +8 -5
  98. biotite/structure/box.py +19 -21
  99. biotite/structure/celllist.cpython-312-darwin.so +0 -0
  100. biotite/structure/celllist.pyx +83 -67
  101. biotite/structure/chains.py +5 -37
  102. biotite/structure/charges.cpython-312-darwin.so +0 -0
  103. biotite/structure/compare.py +420 -13
  104. biotite/structure/density.py +1 -1
  105. biotite/structure/dotbracket.py +27 -28
  106. biotite/structure/filter.py +8 -8
  107. biotite/structure/geometry.py +15 -15
  108. biotite/structure/hbond.py +17 -19
  109. biotite/structure/info/atoms.py +11 -2
  110. biotite/structure/info/ccd.py +0 -2
  111. biotite/structure/info/components.bcif +0 -0
  112. biotite/structure/info/groups.py +0 -3
  113. biotite/structure/info/misc.py +0 -1
  114. biotite/structure/info/radii.py +92 -22
  115. biotite/structure/info/standardize.py +1 -2
  116. biotite/structure/integrity.py +4 -6
  117. biotite/structure/io/general.py +2 -2
  118. biotite/structure/io/gro/file.py +8 -9
  119. biotite/structure/io/mol/convert.py +1 -1
  120. biotite/structure/io/mol/ctab.py +33 -28
  121. biotite/structure/io/mol/mol.py +1 -1
  122. biotite/structure/io/mol/sdf.py +39 -13
  123. biotite/structure/io/pdb/convert.py +2 -3
  124. biotite/structure/io/pdb/file.py +11 -22
  125. biotite/structure/io/pdb/hybrid36.cpython-312-darwin.so +0 -0
  126. biotite/structure/io/pdbqt/file.py +4 -4
  127. biotite/structure/io/pdbx/bcif.py +22 -7
  128. biotite/structure/io/pdbx/cif.py +20 -7
  129. biotite/structure/io/pdbx/component.py +6 -0
  130. biotite/structure/io/pdbx/compress.py +2 -2
  131. biotite/structure/io/pdbx/convert.py +222 -33
  132. biotite/structure/io/pdbx/encoding.cpython-312-darwin.so +0 -0
  133. biotite/structure/io/trajfile.py +9 -6
  134. biotite/structure/io/util.py +38 -0
  135. biotite/structure/mechanics.py +0 -1
  136. biotite/structure/molecules.py +0 -15
  137. biotite/structure/pseudoknots.py +7 -13
  138. biotite/structure/repair.py +2 -4
  139. biotite/structure/residues.py +13 -24
  140. biotite/structure/rings.py +335 -0
  141. biotite/structure/sasa.cpython-312-darwin.so +0 -0
  142. biotite/structure/sasa.pyx +2 -1
  143. biotite/structure/segments.py +68 -9
  144. biotite/structure/sequence.py +0 -1
  145. biotite/structure/sse.py +0 -2
  146. biotite/structure/superimpose.py +74 -62
  147. biotite/structure/tm.py +581 -0
  148. biotite/structure/transform.py +12 -25
  149. biotite/structure/util.py +3 -3
  150. biotite/version.py +9 -4
  151. biotite/visualize.py +111 -1
  152. {biotite-1.1.0.dist-info → biotite-1.2.0.dist-info}/METADATA +5 -3
  153. {biotite-1.1.0.dist-info → biotite-1.2.0.dist-info}/RECORD +155 -135
  154. {biotite-1.1.0.dist-info → biotite-1.2.0.dist-info}/WHEEL +0 -0
  155. {biotite-1.1.0.dist-info → biotite-1.2.0.dist-info}/licenses/LICENSE.rst +0 -0
@@ -28,10 +28,10 @@ ctypedef np.uint8_t uint8
28
28
  cdef class CellList:
29
29
  """
30
30
  __init__(atom_array, cell_size, periodic=False, box=None, selection=None)
31
-
31
+
32
32
  This class enables the efficient search of atoms in vicinity of a
33
33
  defined location.
34
-
34
+
35
35
  This class stores the indices of an atom array in virtual "cells",
36
36
  each corresponding to a specific coordinate interval.
37
37
  If the atoms in vicinity of a specific location are searched, only
@@ -41,7 +41,7 @@ cdef class CellList:
41
41
  after the :class:`CellList` has been created.
42
42
  Therefore a :class:`CellList` saves calculation time in those
43
43
  cases, where vicinity is checked for multiple locations.
44
-
44
+
45
45
  Parameters
46
46
  ----------
47
47
  atom_array : AtomArray or ndarray, dtype=float, shape=(n,3)
@@ -64,14 +64,14 @@ cdef class CellList:
64
64
  If provided, only the atoms masked by this array are stored in
65
65
  the cell list. However, the indices stored in the cell list
66
66
  will still refer to the original unfiltered `atom_array`.
67
-
67
+
68
68
  Examples
69
69
  --------
70
-
70
+
71
71
  >>> cell_list = CellList(atom_array, cell_size=5)
72
72
  >>> near_atoms = atom_array[cell_list.get_atoms(np.array([1,2,3]), radius=7.0)]
73
73
  """
74
-
74
+
75
75
  # The atom coordinates
76
76
  cdef float32[:,:] _coord
77
77
  # A boolean mask that covers the selected atoms
@@ -99,8 +99,8 @@ cdef class CellList:
99
99
  cdef int _orig_length
100
100
  cdef float32[:] _orig_min_coord
101
101
  cdef float32[:] _orig_max_coord
102
-
103
-
102
+
103
+
104
104
  @cython.initializedcheck(False)
105
105
  @cython.boundscheck(False)
106
106
  @cython.wraparound(False)
@@ -119,14 +119,10 @@ cdef class CellList:
119
119
  # if 'periodic' is true
120
120
  self._orig_length = coord.shape[0]
121
121
  self._box = None
122
- if coord.ndim != 2:
123
- raise ValueError("Coordinates must have shape (n,3)")
124
- if coord.shape[0] == 0:
125
- raise ValueError("Coordinates must not be empty")
126
- if coord.shape[1] != 3:
127
- raise ValueError("Coordinates must have form (x,y,z)")
128
- if np.isnan(coord).any():
129
- raise ValueError("Coordinates contain NaN values")
122
+ if selection is None:
123
+ _check_coord(coord)
124
+ else:
125
+ _check_coord(coord[selection])
130
126
 
131
127
  if periodic:
132
128
  if box is not None:
@@ -145,7 +141,7 @@ cdef class CellList:
145
141
  raise ValueError("Box contains NaN values")
146
142
  coord = move_inside_box(coord, self._box)
147
143
  coord, indices = repeat_box_coord(coord, self._box)
148
-
144
+
149
145
  if self._has_initialized_cells():
150
146
  raise Exception("Duplicate call of constructor")
151
147
  self._cells = None
@@ -155,23 +151,23 @@ cdef class CellList:
155
151
  self._coord = coord.astype(np.float32, copy=False)
156
152
  self._cellsize = cell_size
157
153
  # calculate how many cells are required for each dimension
158
- min_coord = np.min(coord, axis=0).astype(np.float32)
159
- max_coord = np.max(coord, axis=0).astype(np.float32)
154
+ min_coord = np.nanmin(coord, axis=0).astype(np.float32)
155
+ max_coord = np.nanmax(coord, axis=0).astype(np.float32)
160
156
  self._min_coord = min_coord
161
157
  self._max_coord = max_coord
162
158
  cell_count = (((max_coord - min_coord) / cell_size) +1).astype(int)
163
159
  if self._periodic:
164
- self._orig_min_coord = np.min(coord[:self._orig_length], axis=0) \
160
+ self._orig_min_coord = np.nanmin(coord[:self._orig_length], axis=0) \
165
161
  .astype(np.float32)
166
- self._orig_max_coord = np.max(coord[:self._orig_length], axis=0) \
162
+ self._orig_max_coord = np.nanmax(coord[:self._orig_length], axis=0) \
167
163
  .astype(np.float32)
168
-
164
+
169
165
  # ndarray of pointers to C-arrays
170
166
  # containing indices to atom array
171
167
  self._cells = np.zeros(cell_count, dtype=np.uint64)
172
168
  # Stores the length of the C-arrays
173
169
  self._cell_length = np.zeros(cell_count, dtype=np.int32)
174
-
170
+
175
171
  # Prepare selection
176
172
  if selection is not None:
177
173
  self._has_selection = True
@@ -183,7 +179,7 @@ cdef class CellList:
183
179
  )
184
180
  else:
185
181
  self._has_selection = False
186
-
182
+
187
183
  # Fill cells
188
184
  for atom_array_i in range(self._coord.shape[0]):
189
185
  # Only put selected atoms into cell list
@@ -208,34 +204,34 @@ cdef class CellList:
208
204
  # Store new cell pointer and length
209
205
  self._cell_length[i,j,k] = length
210
206
  self._cells[i,j,k] = <ptr> cell_ptr
211
-
212
-
207
+
208
+
213
209
  def __dealloc__(self):
214
210
  if self._has_initialized_cells():
215
211
  deallocate_ptrs(self._cells)
216
-
217
-
212
+
213
+
218
214
  @cython.initializedcheck(False)
219
215
  @cython.boundscheck(False)
220
216
  @cython.wraparound(False)
221
217
  def create_adjacency_matrix(self, float32 threshold_distance):
222
218
  """
223
219
  create_adjacency_matrix(threshold_distance)
224
-
220
+
225
221
  Create an adjacency matrix for the atoms in this cell list.
226
222
 
227
223
  An adjacency matrix depicts which atoms *i* and *j* have
228
224
  a distance lower than a given threshold distance.
229
225
  The values in the adjacency matrix ``m`` are
230
226
  ``m[i,j] = 1 if distance(i,j) <= threshold else 0``
231
-
227
+
232
228
  Parameters
233
229
  ----------
234
230
  threshold_distance : float
235
231
  The threshold distance. All atom pairs that have a distance
236
232
  lower than this value are indicated by ``True`` values in
237
233
  the resulting matrix.
238
-
234
+
239
235
  Returns
240
236
  -------
241
237
  matrix : ndarray, dtype=bool, shape=(n,n)
@@ -244,7 +240,7 @@ cdef class CellList:
244
240
  :class:`CellList`, the rows and columns corresponding to
245
241
  atoms, that are not masked by the selection, have all
246
242
  elements set to ``False``.
247
-
243
+
248
244
  Notes
249
245
  -----
250
246
  The highest performance is achieved when the the cell size is
@@ -269,7 +265,7 @@ cdef class CellList:
269
265
  if threshold_distance < 0:
270
266
  raise ValueError("Threshold must be a positive value")
271
267
  cdef int i=0
272
-
268
+
273
269
  # Get atom position for all original positions
274
270
  # (no periodic copies)
275
271
  coord = np.asarray(self._coord[:self._orig_length])
@@ -287,17 +283,17 @@ cdef class CellList:
287
283
  return matrix
288
284
  else:
289
285
  return self.get_atoms(coord, threshold_distance, as_mask=True)
290
-
291
-
286
+
287
+
292
288
  @cython.initializedcheck(False)
293
289
  @cython.boundscheck(False)
294
290
  @cython.wraparound(False)
295
291
  def get_atoms(self, np.ndarray coord, radius, bint as_mask=False):
296
292
  """
297
293
  get_atoms(coord, radius, as_mask=False)
298
-
294
+
299
295
  Find atoms with a maximum distance from given coordinates.
300
-
296
+
301
297
  Parameters
302
298
  ----------
303
299
  coord : ndarray, dtype=float, shape=(3,) or shape=(m,3)
@@ -321,7 +317,7 @@ cdef class CellList:
321
317
  as_mask : bool, optional
322
318
  If true, the result is returned as boolean mask, instead
323
319
  of an index array.
324
-
320
+
325
321
  Returns
326
322
  -------
327
323
  indices : ndarray, dtype=int32, shape=(p,) or shape=(m,p)
@@ -335,7 +331,7 @@ cdef class CellList:
335
331
  The values are true for atoms in the atom array,
336
332
  that are in the defined vicinity.
337
333
  Only returned with `as_mask` set to true.
338
-
334
+
339
335
  See Also
340
336
  --------
341
337
  get_atoms_in_cells
@@ -376,7 +372,7 @@ cdef class CellList:
376
372
  A 18 PRO HA H 2.719 3.181 1.316
377
373
  A 18 PRO HB3 H 2.781 3.223 3.618
378
374
  A 18 PRO CB C 3.035 4.190 3.187
379
-
375
+
380
376
  Get adjacent atoms for mutliple positions:
381
377
 
382
378
  >>> cell_list = CellList(atom_array, 3)
@@ -403,14 +399,14 @@ cdef class CellList:
403
399
  cdef float32 sq_radius
404
400
  cdef float32[:] sq_radii
405
401
  cdef np.ndarray cell_radii
406
-
402
+
407
403
  cdef int[:,:] all_indices
408
404
  cdef int[:,:] indices
409
405
  cdef float32[:,:] coord_v
410
406
 
411
407
  if len(coord) == 0:
412
408
  return _empty_result(as_mask)
413
-
409
+
414
410
  # Handle periodicity for the input coordinates
415
411
  if self._periodic:
416
412
  coord = move_inside_box(coord, self._box)
@@ -437,7 +433,7 @@ cdef class CellList:
437
433
  )
438
434
  # These have to be narrowed down in the next step
439
435
  # using the Euclidian distance
440
-
436
+
441
437
  # Filter all indices from all_indices
442
438
  # where squared distance is smaller than squared radius
443
439
  # Using the squared distance is computationally cheaper than
@@ -464,23 +460,23 @@ cdef class CellList:
464
460
  array_i += 1
465
461
  if array_i > max_array_length:
466
462
  max_array_length = array_i
467
-
463
+
468
464
  return self._post_process(
469
465
  np.asarray(indices)[:, :max_array_length],
470
466
  as_mask, is_multi_coord
471
467
  )
472
-
473
-
468
+
469
+
474
470
  @cython.boundscheck(False)
475
471
  @cython.wraparound(False)
476
472
  def get_atoms_in_cells(self, np.ndarray coord,
477
473
  cell_radius=1, bint as_mask=False):
478
474
  """
479
475
  get_atoms_in_cells(coord, cell_radius=1, as_mask=False)
480
-
476
+
481
477
  Find atoms with a maximum cell distance from given
482
478
  coordinates.
483
-
479
+
484
480
  Instead of using the radius as maximum euclidian distance to the
485
481
  given coordinates,
486
482
  the radius is measured as the amount of cells:
@@ -489,7 +485,7 @@ cdef class CellList:
489
485
  that the atoms indices from this cell and the 8 surrounding
490
486
  cells are returned and so forth.
491
487
  This is more efficient than `get_atoms()`.
492
-
488
+
493
489
  Parameters
494
490
  ----------
495
491
  coord : ndarray, dtype=float, shape=(3,) or shape=(m,3)
@@ -518,7 +514,7 @@ cdef class CellList:
518
514
  as_mask : bool, optional
519
515
  If true, the result is returned as boolean mask, instead
520
516
  of an index array.
521
-
517
+
522
518
  Returns
523
519
  -------
524
520
  indices : ndarray, dtype=int32, shape=(p,) or shape=(m,p)
@@ -563,8 +559,8 @@ cdef class CellList:
563
559
  coord, cell_radius, is_multi_radius
564
560
  )
565
561
  return self._post_process(array_indices, as_mask, is_multi_coord)
566
-
567
-
562
+
563
+
568
564
  @cython.boundscheck(False)
569
565
  @cython.wraparound(False)
570
566
  def _get_atoms_in_cells(self,
@@ -573,7 +569,7 @@ cdef class CellList:
573
569
  bint is_multi_radius):
574
570
  """
575
571
  Get the indices of atoms in `cell_radii` adjacency of `coord`.
576
-
572
+
577
573
  Parameters
578
574
  ----------
579
575
  coord : ndarray, dtype=float32, shape=(n,3)
@@ -583,7 +579,7 @@ cdef class CellList:
583
579
  is_multi_radius : bool
584
580
  True indicates, that all values in `cell_radii` are the
585
581
  same.
586
-
582
+
587
583
  Returns
588
584
  -------
589
585
  array_indices : ndarray, dtype=int32, shape=(m,p)
@@ -607,8 +603,8 @@ cdef class CellList:
607
603
  cdef int max_array_length \
608
604
  = self._find_adjacent_atoms(coord, array_indices, cell_radii)
609
605
  return array_indices[:, :max_array_length]
610
-
611
-
606
+
607
+
612
608
  @cython.boundscheck(False)
613
609
  @cython.wraparound(False)
614
610
  cdef int _find_adjacent_atoms(self,
@@ -618,7 +614,7 @@ cdef class CellList:
618
614
  """
619
615
  This method fills the given empty index array
620
616
  with actual indices of adjacent atoms.
621
-
617
+
622
618
  Since the length of 'indices' (second dimension) is
623
619
  the worst case assumption, this method returns the actual
624
620
  required length, i.e. the highest length of all arrays
@@ -632,11 +628,17 @@ cdef class CellList:
632
628
  cdef int pos_i, array_i, cell_i
633
629
  cdef int max_array_length = 0
634
630
  cdef int cell_r
635
-
631
+
636
632
  cdef ptr[:,:,:] cells = self._cells
637
633
  cdef int[:,:,:] cell_length = self._cell_length
634
+ cdef uint8[:] finite_mask = (
635
+ np.isfinite(np.asarray(coord)).all(axis=-1).astype(np.uint8, copy=False)
636
+ )
638
637
 
639
638
  for pos_i in range(coord.shape[0]):
639
+ if not finite_mask[pos_i]:
640
+ # For non-finite coordinates, there are no adjacent atoms
641
+ continue
640
642
  array_i = 0
641
643
  cell_r = cell_radius[pos_i]
642
644
  x = coord[pos_i, 0]
@@ -663,7 +665,7 @@ cdef class CellList:
663
665
  if array_i > max_array_length:
664
666
  max_array_length = array_i
665
667
  return max_array_length
666
-
668
+
667
669
 
668
670
  @cython.boundscheck(False)
669
671
  @cython.wraparound(False)
@@ -695,8 +697,8 @@ cdef class CellList:
695
697
  return indices
696
698
  else:
697
699
  return indices[0]
698
-
699
-
700
+
701
+
700
702
  @cython.initializedcheck(False)
701
703
  @cython.boundscheck(False)
702
704
  @cython.wraparound(False)
@@ -706,7 +708,7 @@ cdef class CellList:
706
708
  i[0] = <int>((x - self._min_coord[0]) / self._cellsize)
707
709
  j[0] = <int>((y - self._min_coord[1]) / self._cellsize)
708
710
  k[0] = <int>((z - self._min_coord[2]) / self._cellsize)
709
-
711
+
710
712
  @cython.initializedcheck(False)
711
713
  @cython.boundscheck(False)
712
714
  @cython.wraparound(False)
@@ -718,7 +720,7 @@ cdef class CellList:
718
720
  if z < self._min_coord[2] or z > self._max_coord[2]:
719
721
  return False
720
722
  return True
721
-
723
+
722
724
  @cython.initializedcheck(False)
723
725
  @cython.boundscheck(False)
724
726
  @cython.wraparound(False)
@@ -737,7 +739,7 @@ cdef class CellList:
737
739
  break
738
740
  matrix[i, index] = True
739
741
  return np.asarray(matrix, dtype=bool)
740
-
742
+
741
743
  cdef inline bint _has_initialized_cells(self):
742
744
  # Memoryviews are not initialized on class creation
743
745
  # This method checks if the _cells memoryview was initialized
@@ -751,6 +753,20 @@ cdef class CellList:
751
753
  return False
752
754
 
753
755
 
756
+ def _check_coord(coord):
757
+ """
758
+ Perform checks on validity of coordinates.
759
+ """
760
+ if coord.ndim != 2:
761
+ raise ValueError("Coordinates must have shape (n,3)")
762
+ if coord.shape[0] == 0:
763
+ raise ValueError("Coordinates must not be empty")
764
+ if coord.shape[1] != 3:
765
+ raise ValueError("Coordinates must have form (x,y,z)")
766
+ if not np.isfinite(coord).all():
767
+ raise ValueError("Coordinates contain non-finite values")
768
+
769
+
754
770
  def _empty_result(as_mask):
755
771
  """
756
772
  Create return value for :func:`get_atoms()` and
@@ -774,11 +790,11 @@ def _prepare_vectorization(np.ndarray coord, radius, radius_dtype):
774
790
  radii/coordinates were given.
775
791
 
776
792
  The shapes before and after conversion are:
777
-
793
+
778
794
  - coord: (3, ), radius: scalar -> coord: (1,3), radius: (1,)
779
795
  - coord: (n,3), radius: scalar -> coord: (n,3), radius: (n,)
780
796
  - coord: (n,3), radius: (n, ) -> coord: (n,3), radius: (n,)
781
-
797
+
782
798
  Thes resulting values have the same dimensionality for all cases and
783
799
  can be handeled uniformly by `get_atoms()` and
784
800
  `get_atoms_in_cells()`.
@@ -798,7 +814,7 @@ def _prepare_vectorization(np.ndarray coord, radius, radius_dtype):
798
814
  raise ValueError(
799
815
  f"Invalid shape for input coordinates"
800
816
  )
801
-
817
+
802
818
  if isinstance(radius, np.ndarray):
803
819
  # Multiple radii
804
820
  # Check whether amount of coordinates match amount of radii
@@ -59,11 +59,10 @@ def get_chain_starts(array, add_exclusive_stop=False):
59
59
  -----
60
60
  This method is internally used by all other chain-related
61
61
  functions.
62
-
63
- See also
64
- --------
65
- get_residue_starts
66
62
  """
63
+ if array.array_length() == 0:
64
+ return np.array([], dtype=int)
65
+
67
66
  diff = np.diff(array.res_id)
68
67
  res_id_decrement = diff < 0
69
68
  # This mask is 'true' at indices where the value changes
@@ -115,10 +114,6 @@ def apply_chain_wise(array, data, function, axis=None):
115
114
  Chain-wise evaluation of `data` by `function`. The size of the
116
115
  first dimension of this array is equal to the amount of
117
116
  chains.
118
-
119
- See also
120
- --------
121
- apply_residue_wise
122
117
  """
123
118
  starts = get_chain_starts(array, add_exclusive_stop=True)
124
119
  return apply_segment_wise(starts, data, function, axis)
@@ -148,10 +143,6 @@ def spread_chain_wise(array, input_data):
148
143
  output_data : ndarray
149
144
  Chain-wise spread `input_data`. Length is the same as
150
145
  `array_length()` of `array`.
151
-
152
- See also
153
- --------
154
- spread_residue_wise
155
146
  """
156
147
  starts = get_chain_starts(array, add_exclusive_stop=True)
157
148
  return spread_segment_wise(starts, input_data)
@@ -177,10 +168,6 @@ def get_chain_masks(array, indices):
177
168
  Multiple boolean masks, one for each given index in `indices`.
178
169
  Each array masks the atoms that belong to the same chain as
179
170
  the atom at the given index.
180
-
181
- See also
182
- --------
183
- get_residue_masks
184
171
  """
185
172
  starts = get_chain_starts(array, add_exclusive_stop=True)
186
173
  return get_segment_masks(starts, indices)
@@ -205,10 +192,6 @@ def get_chain_starts_for(array, indices):
205
192
  start_indices : ndarray, dtype=int, shape=(k,)
206
193
  The indices that point to the chain starts for the input
207
194
  `indices`.
208
-
209
- See also
210
- --------
211
- get_residue_starts_for
212
195
  """
213
196
  starts = get_chain_starts(array, add_exclusive_stop=True)
214
197
  return get_segment_starts_for(starts, indices)
@@ -235,10 +218,6 @@ def get_chain_positions(array, indices):
235
218
  -------
236
219
  start_indices : ndarray, dtype=int, shape=(k,)
237
220
  The indices that point to the position of the chains.
238
-
239
- See also
240
- --------
241
- get_residue_positions
242
221
  """
243
222
  starts = get_chain_starts(array, add_exclusive_stop=True)
244
223
  return get_segment_positions(starts, indices)
@@ -260,10 +239,6 @@ def get_chains(array):
260
239
  -------
261
240
  ids : ndarray, dtype=str
262
241
  List of chain IDs.
263
-
264
- See also
265
- --------
266
- get_residues
267
242
  """
268
243
  return array.chain_id[get_chain_starts(array)]
269
244
 
@@ -284,10 +259,6 @@ def get_chain_count(array):
284
259
  -------
285
260
  count : int
286
261
  Amount of chains.
287
-
288
- See also
289
- --------
290
- get_residue_count
291
262
  """
292
263
  return len(get_chain_starts(array))
293
264
 
@@ -305,10 +276,7 @@ def chain_iter(array):
305
276
  ------
306
277
  chain : AtomArray or AtomArrayStack
307
278
  A single chain of the input `array`.
308
-
309
- See also
310
- --------
311
- residue_iter
312
279
  """
313
280
  starts = get_chain_starts(array, add_exclusive_stop=True)
314
- return segment_iter(array, starts)
281
+ for chain in segment_iter(array, starts):
282
+ yield chain