biotite 0.41.2__cp310-cp310-win_amd64.whl → 1.0.1__cp310-cp310-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of biotite might be problematic. Click here for more details.
- biotite/__init__.py +2 -3
- biotite/application/__init__.py +1 -1
- biotite/application/application.py +20 -10
- biotite/application/autodock/__init__.py +1 -1
- biotite/application/autodock/app.py +74 -79
- biotite/application/blast/__init__.py +1 -1
- biotite/application/blast/alignment.py +19 -10
- biotite/application/blast/webapp.py +92 -85
- biotite/application/clustalo/__init__.py +1 -1
- biotite/application/clustalo/app.py +46 -61
- biotite/application/dssp/__init__.py +1 -1
- biotite/application/dssp/app.py +8 -11
- biotite/application/localapp.py +62 -60
- biotite/application/mafft/__init__.py +1 -1
- biotite/application/mafft/app.py +16 -22
- biotite/application/msaapp.py +78 -89
- biotite/application/muscle/__init__.py +1 -1
- biotite/application/muscle/app3.py +50 -64
- biotite/application/muscle/app5.py +23 -31
- biotite/application/sra/__init__.py +1 -1
- biotite/application/sra/app.py +64 -68
- biotite/application/tantan/__init__.py +1 -1
- biotite/application/tantan/app.py +22 -45
- biotite/application/util.py +7 -9
- biotite/application/viennarna/rnaalifold.py +34 -28
- biotite/application/viennarna/rnafold.py +24 -39
- biotite/application/viennarna/rnaplot.py +36 -21
- biotite/application/viennarna/util.py +17 -12
- biotite/application/webapp.py +13 -14
- biotite/copyable.py +13 -13
- biotite/database/__init__.py +1 -1
- biotite/database/entrez/__init__.py +1 -1
- biotite/database/entrez/check.py +2 -3
- biotite/database/entrez/dbnames.py +7 -5
- biotite/database/entrez/download.py +55 -49
- biotite/database/entrez/key.py +1 -1
- biotite/database/entrez/query.py +62 -23
- biotite/database/error.py +2 -1
- biotite/database/pubchem/__init__.py +1 -1
- biotite/database/pubchem/download.py +43 -45
- biotite/database/pubchem/error.py +2 -2
- biotite/database/pubchem/query.py +34 -31
- biotite/database/pubchem/throttle.py +3 -4
- biotite/database/rcsb/__init__.py +1 -1
- biotite/database/rcsb/download.py +44 -52
- biotite/database/rcsb/query.py +85 -80
- biotite/database/uniprot/check.py +6 -3
- biotite/database/uniprot/download.py +6 -11
- biotite/database/uniprot/query.py +115 -31
- biotite/file.py +12 -31
- biotite/sequence/__init__.py +3 -3
- biotite/sequence/align/__init__.py +2 -2
- biotite/sequence/align/alignment.py +99 -90
- biotite/sequence/align/banded.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/buckets.py +12 -10
- biotite/sequence/align/cigar.py +43 -52
- biotite/sequence/align/kmeralphabet.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/kmeralphabet.pyx +55 -51
- biotite/sequence/align/kmersimilarity.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/kmertable.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/kmertable.pyx +3 -2
- biotite/sequence/align/localgapped.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/localungapped.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/matrix.py +81 -82
- biotite/sequence/align/multiple.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/multiple.pyx +1 -1
- biotite/sequence/align/pairwise.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/permutation.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/permutation.pyx +12 -4
- biotite/sequence/align/selector.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/selector.pyx +52 -54
- biotite/sequence/align/statistics.py +32 -33
- biotite/sequence/align/tracetable.cp310-win_amd64.pyd +0 -0
- biotite/sequence/alphabet.py +51 -65
- biotite/sequence/annotation.py +78 -77
- biotite/sequence/codec.cp310-win_amd64.pyd +0 -0
- biotite/sequence/codon.py +90 -79
- biotite/sequence/graphics/__init__.py +1 -1
- biotite/sequence/graphics/alignment.py +184 -103
- biotite/sequence/graphics/colorschemes.py +10 -12
- biotite/sequence/graphics/dendrogram.py +79 -34
- biotite/sequence/graphics/features.py +133 -99
- biotite/sequence/graphics/logo.py +22 -28
- biotite/sequence/graphics/plasmid.py +229 -178
- biotite/sequence/io/fasta/__init__.py +1 -1
- biotite/sequence/io/fasta/convert.py +44 -33
- biotite/sequence/io/fasta/file.py +42 -55
- biotite/sequence/io/fastq/__init__.py +1 -1
- biotite/sequence/io/fastq/convert.py +11 -14
- biotite/sequence/io/fastq/file.py +68 -112
- biotite/sequence/io/genbank/__init__.py +2 -2
- biotite/sequence/io/genbank/annotation.py +12 -20
- biotite/sequence/io/genbank/file.py +74 -76
- biotite/sequence/io/genbank/metadata.py +74 -62
- biotite/sequence/io/genbank/sequence.py +13 -14
- biotite/sequence/io/general.py +39 -30
- biotite/sequence/io/gff/__init__.py +2 -2
- biotite/sequence/io/gff/convert.py +10 -15
- biotite/sequence/io/gff/file.py +81 -65
- biotite/sequence/phylo/__init__.py +1 -1
- biotite/sequence/phylo/nj.cp310-win_amd64.pyd +0 -0
- biotite/sequence/phylo/tree.cp310-win_amd64.pyd +0 -0
- biotite/sequence/phylo/upgma.cp310-win_amd64.pyd +0 -0
- biotite/sequence/profile.py +57 -28
- biotite/sequence/search.py +17 -15
- biotite/sequence/seqtypes.py +200 -164
- biotite/sequence/sequence.py +15 -17
- biotite/structure/__init__.py +3 -3
- biotite/structure/atoms.py +246 -236
- biotite/structure/basepairs.py +260 -271
- biotite/structure/bonds.cp310-win_amd64.pyd +0 -0
- biotite/structure/bonds.pyx +29 -32
- biotite/structure/box.py +67 -71
- biotite/structure/celllist.cp310-win_amd64.pyd +0 -0
- biotite/structure/chains.py +55 -39
- biotite/structure/charges.cp310-win_amd64.pyd +0 -0
- biotite/structure/compare.py +32 -32
- biotite/structure/density.py +13 -18
- biotite/structure/dotbracket.py +20 -22
- biotite/structure/error.py +10 -2
- biotite/structure/filter.py +83 -78
- biotite/structure/geometry.py +130 -119
- biotite/structure/graphics/atoms.py +60 -43
- biotite/structure/graphics/rna.py +81 -68
- biotite/structure/hbond.py +112 -93
- biotite/structure/info/__init__.py +0 -2
- biotite/structure/info/atoms.py +10 -11
- biotite/structure/info/bonds.py +41 -43
- biotite/structure/info/ccd.py +4 -5
- biotite/structure/info/groups.py +1 -3
- biotite/structure/info/masses.py +5 -10
- biotite/structure/info/misc.py +1 -1
- biotite/structure/info/radii.py +20 -20
- biotite/structure/info/standardize.py +15 -26
- biotite/structure/integrity.py +18 -71
- biotite/structure/io/__init__.py +3 -4
- biotite/structure/io/dcd/__init__.py +1 -1
- biotite/structure/io/dcd/file.py +22 -20
- biotite/structure/io/general.py +47 -61
- biotite/structure/io/gro/__init__.py +1 -1
- biotite/structure/io/gro/file.py +73 -72
- biotite/structure/io/mol/__init__.py +1 -1
- biotite/structure/io/mol/convert.py +8 -11
- biotite/structure/io/mol/ctab.py +37 -36
- biotite/structure/io/mol/header.py +14 -10
- biotite/structure/io/mol/mol.py +9 -53
- biotite/structure/io/mol/sdf.py +47 -50
- biotite/structure/io/netcdf/__init__.py +1 -1
- biotite/structure/io/netcdf/file.py +24 -23
- biotite/structure/io/pdb/__init__.py +1 -1
- biotite/structure/io/pdb/convert.py +32 -20
- biotite/structure/io/pdb/file.py +151 -172
- biotite/structure/io/pdb/hybrid36.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/pdbqt/__init__.py +1 -1
- biotite/structure/io/pdbqt/convert.py +17 -11
- biotite/structure/io/pdbqt/file.py +128 -80
- biotite/structure/io/pdbx/__init__.py +1 -2
- biotite/structure/io/pdbx/bcif.py +36 -44
- biotite/structure/io/pdbx/cif.py +140 -110
- biotite/structure/io/pdbx/component.py +10 -16
- biotite/structure/io/pdbx/convert.py +260 -258
- biotite/structure/io/pdbx/encoding.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/trajfile.py +90 -107
- biotite/structure/io/trr/__init__.py +1 -1
- biotite/structure/io/trr/file.py +12 -15
- biotite/structure/io/xtc/__init__.py +1 -1
- biotite/structure/io/xtc/file.py +11 -14
- biotite/structure/mechanics.py +9 -11
- biotite/structure/molecules.py +3 -4
- biotite/structure/pseudoknots.py +53 -67
- biotite/structure/rdf.py +23 -21
- biotite/structure/repair.py +137 -86
- biotite/structure/residues.py +26 -16
- biotite/structure/sasa.cp310-win_amd64.pyd +0 -0
- biotite/structure/{resutil.py → segments.py} +24 -23
- biotite/structure/sequence.py +10 -11
- biotite/structure/sse.py +100 -119
- biotite/structure/superimpose.py +39 -77
- biotite/structure/transform.py +97 -71
- biotite/structure/util.py +11 -13
- biotite/version.py +2 -2
- biotite/visualize.py +69 -55
- {biotite-0.41.2.dist-info → biotite-1.0.1.dist-info}/METADATA +6 -5
- biotite-1.0.1.dist-info/RECORD +322 -0
- biotite/structure/io/ctab.py +0 -72
- biotite/structure/io/mmtf/__init__.py +0 -21
- biotite/structure/io/mmtf/assembly.py +0 -214
- biotite/structure/io/mmtf/convertarray.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/convertarray.pyx +0 -341
- biotite/structure/io/mmtf/convertfile.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/convertfile.pyx +0 -501
- biotite/structure/io/mmtf/decode.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/decode.pyx +0 -152
- biotite/structure/io/mmtf/encode.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/encode.pyx +0 -183
- biotite/structure/io/mmtf/file.py +0 -233
- biotite/structure/io/npz/__init__.py +0 -20
- biotite/structure/io/npz/file.py +0 -152
- biotite/structure/io/pdbx/legacy.py +0 -267
- biotite/structure/io/tng/__init__.py +0 -13
- biotite/structure/io/tng/file.py +0 -46
- biotite/temp.py +0 -86
- biotite-0.41.2.dist-info/RECORD +0 -340
- {biotite-0.41.2.dist-info → biotite-1.0.1.dist-info}/WHEEL +0 -0
- {biotite-0.41.2.dist-info → biotite-1.0.1.dist-info}/licenses/LICENSE.rst +0 -0
biotite/structure/atoms.py
CHANGED
|
@@ -4,19 +4,27 @@
|
|
|
4
4
|
|
|
5
5
|
"""
|
|
6
6
|
This module contains the main types of the ``structure`` subpackage:
|
|
7
|
-
:class:`Atom`, :class:`AtomArray` and :class:`AtomArrayStack`.
|
|
7
|
+
:class:`Atom`, :class:`AtomArray` and :class:`AtomArrayStack`.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
__name__ = "biotite.structure"
|
|
11
11
|
__author__ = "Patrick Kunzmann"
|
|
12
|
-
__all__ = [
|
|
13
|
-
|
|
12
|
+
__all__ = [
|
|
13
|
+
"Atom",
|
|
14
|
+
"AtomArray",
|
|
15
|
+
"AtomArrayStack",
|
|
16
|
+
"array",
|
|
17
|
+
"stack",
|
|
18
|
+
"repeat",
|
|
19
|
+
"from_template",
|
|
20
|
+
"coord",
|
|
21
|
+
]
|
|
14
22
|
|
|
15
|
-
import numbers
|
|
16
23
|
import abc
|
|
24
|
+
import numbers
|
|
17
25
|
import numpy as np
|
|
18
|
-
from .
|
|
19
|
-
from
|
|
26
|
+
from biotite.copyable import Copyable
|
|
27
|
+
from biotite.structure.bonds import BondList
|
|
20
28
|
|
|
21
29
|
|
|
22
30
|
class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
@@ -26,7 +34,7 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
26
34
|
It implements functionality for annotation arrays and also
|
|
27
35
|
rudimentarily for coordinates.
|
|
28
36
|
"""
|
|
29
|
-
|
|
37
|
+
|
|
30
38
|
def __init__(self, length):
|
|
31
39
|
"""
|
|
32
40
|
Create the annotation arrays
|
|
@@ -43,14 +51,14 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
43
51
|
self.add_annotation("hetero", dtype=bool)
|
|
44
52
|
self.add_annotation("atom_name", dtype="U6")
|
|
45
53
|
self.add_annotation("element", dtype="U2")
|
|
46
|
-
|
|
54
|
+
|
|
47
55
|
def array_length(self):
|
|
48
56
|
"""
|
|
49
57
|
Get the length of the atom array.
|
|
50
|
-
|
|
58
|
+
|
|
51
59
|
This value is equivalent to the length of each annotation array.
|
|
52
60
|
For :class:`AtomArray` it is the same as ``len(array)``.
|
|
53
|
-
|
|
61
|
+
|
|
54
62
|
Returns
|
|
55
63
|
-------
|
|
56
64
|
length : int
|
|
@@ -71,15 +79,15 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
71
79
|
shape : tuple of int
|
|
72
80
|
Shape of the object.
|
|
73
81
|
"""
|
|
74
|
-
return
|
|
75
|
-
|
|
82
|
+
return
|
|
83
|
+
|
|
76
84
|
def add_annotation(self, category, dtype):
|
|
77
85
|
"""
|
|
78
86
|
Add an annotation category, if not already existing.
|
|
79
|
-
|
|
87
|
+
|
|
80
88
|
Initially the new annotation is filled with the *zero*
|
|
81
89
|
representation of the given type.
|
|
82
|
-
|
|
90
|
+
|
|
83
91
|
Parameters
|
|
84
92
|
----------
|
|
85
93
|
category : str
|
|
@@ -87,19 +95,33 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
87
95
|
dtype : type or str
|
|
88
96
|
A type instance or a valid *NumPy* *dtype* string.
|
|
89
97
|
Defines the type of the annotation
|
|
90
|
-
|
|
98
|
+
|
|
91
99
|
See Also
|
|
92
100
|
--------
|
|
93
101
|
set_annotation
|
|
102
|
+
|
|
103
|
+
Notes
|
|
104
|
+
-----
|
|
105
|
+
If the annotation category already exists, a compatible dtype is chosen,
|
|
106
|
+
that is also able to represent the old values.
|
|
94
107
|
"""
|
|
95
108
|
if category not in self._annot:
|
|
96
|
-
self._annot[str(category)] = np.zeros(self._array_length,
|
|
97
|
-
|
|
98
|
-
|
|
109
|
+
self._annot[str(category)] = np.zeros(self._array_length, dtype=dtype)
|
|
110
|
+
elif np.can_cast(self._annot[str(category)].dtype, dtype):
|
|
111
|
+
self._annot[str(category)] = self._annot[str(category)].astype(dtype)
|
|
112
|
+
elif np.can_cast(dtype, self._annot[str(category)].dtype):
|
|
113
|
+
# The existing dtype is more general
|
|
114
|
+
pass
|
|
115
|
+
else:
|
|
116
|
+
raise ValueError(
|
|
117
|
+
f"Cannot cast '{str(category)}' "
|
|
118
|
+
f"with dtype '{self._annot[str(category)].dtype}' into '{dtype}'"
|
|
119
|
+
)
|
|
120
|
+
|
|
99
121
|
def del_annotation(self, category):
|
|
100
122
|
"""
|
|
101
123
|
Removes an annotation category.
|
|
102
|
-
|
|
124
|
+
|
|
103
125
|
Parameters
|
|
104
126
|
----------
|
|
105
127
|
category : str
|
|
@@ -107,32 +129,30 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
107
129
|
"""
|
|
108
130
|
if category in self._annot:
|
|
109
131
|
del self._annot[str(category)]
|
|
110
|
-
|
|
132
|
+
|
|
111
133
|
def get_annotation(self, category):
|
|
112
134
|
"""
|
|
113
135
|
Return an annotation array.
|
|
114
|
-
|
|
136
|
+
|
|
115
137
|
Parameters
|
|
116
138
|
----------
|
|
117
139
|
category : str
|
|
118
140
|
The annotation category to be returned.
|
|
119
|
-
|
|
141
|
+
|
|
120
142
|
Returns
|
|
121
143
|
-------
|
|
122
144
|
array : ndarray
|
|
123
145
|
The annotation array.
|
|
124
146
|
"""
|
|
125
147
|
if category not in self._annot:
|
|
126
|
-
raise ValueError(
|
|
127
|
-
f"Annotation category '{category}' is not existing"
|
|
128
|
-
)
|
|
148
|
+
raise ValueError(f"Annotation category '{category}' is not existing")
|
|
129
149
|
return self._annot[category]
|
|
130
|
-
|
|
150
|
+
|
|
131
151
|
def set_annotation(self, category, array):
|
|
132
152
|
"""
|
|
133
153
|
Set an annotation array. If the annotation category does not
|
|
134
154
|
exist yet, the category is created.
|
|
135
|
-
|
|
155
|
+
|
|
136
156
|
Parameters
|
|
137
157
|
----------
|
|
138
158
|
category : str
|
|
@@ -140,31 +160,37 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
140
160
|
array : ndarray or None
|
|
141
161
|
The new value of the annotation category. The size of the
|
|
142
162
|
array must be the same as the array length.
|
|
163
|
+
|
|
164
|
+
Notes
|
|
165
|
+
-----
|
|
166
|
+
If the annotation category already exists, a compatible dtype is chosen,
|
|
167
|
+
that is able to represent the old and new array values.
|
|
143
168
|
"""
|
|
169
|
+
array = np.asarray(array)
|
|
144
170
|
if len(array) != self._array_length:
|
|
145
171
|
raise IndexError(
|
|
146
|
-
f"Expected array length {self._array_length}, "
|
|
147
|
-
f"but got {len(array)}"
|
|
172
|
+
f"Expected array length {self._array_length}, " f"but got {len(array)}"
|
|
148
173
|
)
|
|
149
174
|
if category in self._annot:
|
|
150
|
-
#
|
|
151
|
-
self._annot[category] =
|
|
152
|
-
|
|
175
|
+
# If the annotation already exists, find the compatible dtype
|
|
176
|
+
self._annot[category] = array.astype(
|
|
177
|
+
dtype=np.promote_types(self._annot[category].dtype, array.dtype),
|
|
178
|
+
copy=False,
|
|
153
179
|
)
|
|
154
180
|
else:
|
|
155
|
-
self._annot[category] =
|
|
156
|
-
|
|
181
|
+
self._annot[category] = array
|
|
182
|
+
|
|
157
183
|
def get_annotation_categories(self):
|
|
158
184
|
"""
|
|
159
185
|
Return a list containing all annotation array categories.
|
|
160
|
-
|
|
186
|
+
|
|
161
187
|
Returns
|
|
162
188
|
-------
|
|
163
189
|
categories : list
|
|
164
190
|
The list containing the names of each annotation array.
|
|
165
191
|
"""
|
|
166
192
|
return list(self._annot.keys())
|
|
167
|
-
|
|
193
|
+
|
|
168
194
|
def _subarray(self, index):
|
|
169
195
|
# Index is one dimensional (boolean mask, index array)
|
|
170
196
|
new_coord = self._coord[..., index, :]
|
|
@@ -180,10 +206,9 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
180
206
|
if self._box is not None:
|
|
181
207
|
new_object._box = self._box
|
|
182
208
|
for annotation in self._annot:
|
|
183
|
-
new_object._annot[annotation] =
|
|
184
|
-
.__getitem__(index))
|
|
209
|
+
new_object._annot[annotation] = self._annot[annotation].__getitem__(index)
|
|
185
210
|
return new_object
|
|
186
|
-
|
|
211
|
+
|
|
187
212
|
def _set_element(self, index, atom):
|
|
188
213
|
try:
|
|
189
214
|
if isinstance(index, (numbers.Integral, np.ndarray)):
|
|
@@ -191,12 +216,10 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
191
216
|
self._annot[name][index] = atom._annot[name]
|
|
192
217
|
self._coord[..., index, :] = atom.coord
|
|
193
218
|
else:
|
|
194
|
-
raise TypeError(
|
|
195
|
-
f"Index must be integer, not '{type(index).__name__}'"
|
|
196
|
-
)
|
|
219
|
+
raise TypeError(f"Index must be integer, not '{type(index).__name__}'")
|
|
197
220
|
except KeyError:
|
|
198
221
|
raise KeyError("The annotations of the 'Atom' are incompatible")
|
|
199
|
-
|
|
222
|
+
|
|
200
223
|
def _del_element(self, index):
|
|
201
224
|
if isinstance(index, numbers.Integral):
|
|
202
225
|
for name in self._annot:
|
|
@@ -208,20 +231,18 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
208
231
|
mask[index] = False
|
|
209
232
|
self._bonds = self._bonds[mask]
|
|
210
233
|
else:
|
|
211
|
-
raise TypeError(
|
|
212
|
-
|
|
213
|
-
)
|
|
214
|
-
|
|
234
|
+
raise TypeError(f"Index must be integer, not '{type(index).__name__}'")
|
|
235
|
+
|
|
215
236
|
def equal_annotations(self, item):
|
|
216
237
|
"""
|
|
217
238
|
Check, if this object shares equal annotation arrays with the
|
|
218
239
|
given :class:`AtomArray` or :class:`AtomArrayStack`.
|
|
219
|
-
|
|
240
|
+
|
|
220
241
|
Parameters
|
|
221
242
|
----------
|
|
222
243
|
item : AtomArray or AtomArrayStack
|
|
223
244
|
The object to compare the annotation arrays with.
|
|
224
|
-
|
|
245
|
+
|
|
225
246
|
Returns
|
|
226
247
|
-------
|
|
227
248
|
equality : bool
|
|
@@ -235,24 +256,24 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
235
256
|
if not np.array_equal(self._annot[name], item._annot[name]):
|
|
236
257
|
return False
|
|
237
258
|
return True
|
|
238
|
-
|
|
259
|
+
|
|
239
260
|
def equal_annotation_categories(self, item):
|
|
240
261
|
"""
|
|
241
262
|
Check, if this object shares equal annotation array categories
|
|
242
263
|
with the given :class:`AtomArray` or :class:`AtomArrayStack`.
|
|
243
|
-
|
|
264
|
+
|
|
244
265
|
Parameters
|
|
245
266
|
----------
|
|
246
267
|
item : AtomArray or AtomArrayStack
|
|
247
268
|
The object to compare the annotation arrays with.
|
|
248
|
-
|
|
269
|
+
|
|
249
270
|
Returns
|
|
250
271
|
-------
|
|
251
272
|
equality : bool
|
|
252
273
|
True, if the annotation array names are equal.
|
|
253
274
|
"""
|
|
254
275
|
return sorted(self._annot.keys()) == sorted(item._annot.keys())
|
|
255
|
-
|
|
276
|
+
|
|
256
277
|
def __getattr__(self, attr):
|
|
257
278
|
"""
|
|
258
279
|
If the attribute is an annotation, the annotation is returned
|
|
@@ -273,7 +294,7 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
273
294
|
raise AttributeError(
|
|
274
295
|
f"'{type(self).__name__}' object has no attribute '{attr}'"
|
|
275
296
|
)
|
|
276
|
-
|
|
297
|
+
|
|
277
298
|
def __setattr__(self, attr, value):
|
|
278
299
|
"""
|
|
279
300
|
If the attribute is an annotation, the :attr:`value` is saved
|
|
@@ -287,15 +308,13 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
287
308
|
if isinstance(self, AtomArray):
|
|
288
309
|
if value.ndim != 2:
|
|
289
310
|
raise ValueError(
|
|
290
|
-
"A 2-dimensional ndarray is expected "
|
|
291
|
-
|
|
292
|
-
)
|
|
311
|
+
"A 2-dimensional ndarray is expected " "for an AtomArray"
|
|
312
|
+
)
|
|
293
313
|
elif isinstance(self, AtomArrayStack):
|
|
294
314
|
if value.ndim != 3:
|
|
295
315
|
raise ValueError(
|
|
296
|
-
"A 3-dimensional ndarray is expected "
|
|
297
|
-
|
|
298
|
-
)
|
|
316
|
+
"A 3-dimensional ndarray is expected " "for an AtomArrayStack"
|
|
317
|
+
)
|
|
299
318
|
if value.shape[-2] != self._array_length:
|
|
300
319
|
raise ValueError(
|
|
301
320
|
f"Expected array length {self._array_length}, "
|
|
@@ -304,7 +323,7 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
304
323
|
if value.shape[-1] != 3:
|
|
305
324
|
raise TypeError("Expected 3 coordinates for each atom")
|
|
306
325
|
super().__setattr__("_coord", value.astype(np.float32, copy=False))
|
|
307
|
-
|
|
326
|
+
|
|
308
327
|
elif attr == "bonds":
|
|
309
328
|
if isinstance(value, BondList):
|
|
310
329
|
if value.get_atom_count() != self._array_length:
|
|
@@ -318,22 +337,21 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
318
337
|
super().__setattr__("_bonds", None)
|
|
319
338
|
else:
|
|
320
339
|
raise TypeError("Value must be 'BondList'")
|
|
321
|
-
|
|
340
|
+
|
|
322
341
|
elif attr == "box":
|
|
323
342
|
if isinstance(value, np.ndarray):
|
|
324
343
|
if isinstance(self, AtomArray):
|
|
325
344
|
if value.ndim != 2:
|
|
326
345
|
raise ValueError(
|
|
327
|
-
"A 2-dimensional ndarray is expected "
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
else: # AtomArrayStack
|
|
346
|
+
"A 2-dimensional ndarray is expected " "for an AtomArray"
|
|
347
|
+
)
|
|
348
|
+
else: # AtomArrayStack
|
|
331
349
|
if value.ndim != 3:
|
|
332
350
|
raise ValueError(
|
|
333
351
|
"A 3-dimensional ndarray is expected "
|
|
334
352
|
"for an AtomArrayStack"
|
|
335
|
-
|
|
336
|
-
if value.shape[-2:] != (3,3):
|
|
353
|
+
)
|
|
354
|
+
if value.shape[-2:] != (3, 3):
|
|
337
355
|
raise TypeError("Box must be a 3x3 matrix (three vectors)")
|
|
338
356
|
box = value.astype(np.float32, copy=False)
|
|
339
357
|
super().__setattr__("_box", box)
|
|
@@ -342,14 +360,14 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
342
360
|
super().__setattr__("_box", None)
|
|
343
361
|
else:
|
|
344
362
|
raise TypeError("Box must be ndarray of floats or None")
|
|
345
|
-
|
|
363
|
+
|
|
346
364
|
elif attr == "_annot":
|
|
347
365
|
super().__setattr__(attr, value)
|
|
348
366
|
elif attr in self._annot:
|
|
349
367
|
self.set_annotation(attr, value)
|
|
350
368
|
else:
|
|
351
369
|
super().__setattr__(attr, value)
|
|
352
|
-
|
|
370
|
+
|
|
353
371
|
def __dir__(self):
|
|
354
372
|
attr = super().__dir__()
|
|
355
373
|
attr.append("coord")
|
|
@@ -358,7 +376,7 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
358
376
|
for name in self._annot.keys():
|
|
359
377
|
attr.append(name)
|
|
360
378
|
return attr
|
|
361
|
-
|
|
379
|
+
|
|
362
380
|
def __eq__(self, item):
|
|
363
381
|
"""
|
|
364
382
|
See Also
|
|
@@ -376,30 +394,31 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
376
394
|
if not np.array_equal(self._box, item._box):
|
|
377
395
|
return False
|
|
378
396
|
return np.array_equal(self._coord, item._coord)
|
|
379
|
-
|
|
397
|
+
|
|
380
398
|
def __len__(self):
|
|
381
399
|
"""
|
|
382
400
|
The length of the annotation arrays.
|
|
383
|
-
|
|
401
|
+
|
|
384
402
|
Returns
|
|
385
403
|
-------
|
|
386
404
|
length : int
|
|
387
405
|
Length of the annotation arrays.
|
|
388
406
|
"""
|
|
389
407
|
return self._array_length
|
|
390
|
-
|
|
408
|
+
|
|
391
409
|
def __add__(self, array):
|
|
392
|
-
if
|
|
410
|
+
if not isinstance(self, type(array)):
|
|
393
411
|
raise TypeError("Can only concatenate two arrays or two stacks")
|
|
394
412
|
# Create either new array or stack, depending of the own type
|
|
395
413
|
if isinstance(self, AtomArray):
|
|
396
|
-
concat = AtomArray(length
|
|
414
|
+
concat = AtomArray(length=self._array_length + array._array_length)
|
|
397
415
|
if isinstance(self, AtomArrayStack):
|
|
398
|
-
concat = AtomArrayStack(
|
|
399
|
-
|
|
400
|
-
|
|
416
|
+
concat = AtomArrayStack(
|
|
417
|
+
self.stack_depth(), self._array_length + array._array_length
|
|
418
|
+
)
|
|
419
|
+
|
|
401
420
|
concat._coord = np.concatenate((self._coord, array.coord), axis=-2)
|
|
402
|
-
|
|
421
|
+
|
|
403
422
|
# Transfer only annotations,
|
|
404
423
|
# which are existent in both operands
|
|
405
424
|
arr_categories = list(array._annot.keys())
|
|
@@ -407,29 +426,29 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
407
426
|
if category in arr_categories:
|
|
408
427
|
annot = self._annot[category]
|
|
409
428
|
arr_annot = array._annot[category]
|
|
410
|
-
concat._annot[category] = np.concatenate((annot,arr_annot))
|
|
411
|
-
|
|
429
|
+
concat._annot[category] = np.concatenate((annot, arr_annot))
|
|
430
|
+
|
|
412
431
|
# Concatenate bonds lists,
|
|
413
432
|
# if at least one of them contains bond information
|
|
414
433
|
if self._bonds is not None or array._bonds is not None:
|
|
415
434
|
bonds1 = self._bonds
|
|
416
435
|
bonds2 = array._bonds
|
|
417
436
|
if bonds1 is None:
|
|
418
|
-
|
|
437
|
+
bonds1 = BondList(self._array_length)
|
|
419
438
|
if bonds2 is None:
|
|
420
439
|
bonds2 = BondList(array._array_length)
|
|
421
440
|
concat._bonds = bonds1 + bonds2
|
|
422
|
-
|
|
441
|
+
|
|
423
442
|
# Copy box
|
|
424
443
|
if self._box is not None:
|
|
425
444
|
concat._box = np.copy(self._box)
|
|
426
445
|
return concat
|
|
427
|
-
|
|
446
|
+
|
|
428
447
|
def __copy_fill__(self, clone):
|
|
429
448
|
super().__copy_fill__(clone)
|
|
430
449
|
self._copy_annotations(clone)
|
|
431
450
|
clone._coord = np.copy(self._coord)
|
|
432
|
-
|
|
451
|
+
|
|
433
452
|
def _copy_annotations(self, clone):
|
|
434
453
|
for name in self._annot:
|
|
435
454
|
clone._annot[name] = np.copy(self._annot[name])
|
|
@@ -437,23 +456,23 @@ class _AtomArrayBase(Copyable, metaclass=abc.ABCMeta):
|
|
|
437
456
|
clone._box = np.copy(self._box)
|
|
438
457
|
if self._bonds is not None:
|
|
439
458
|
clone._bonds = self._bonds.copy()
|
|
440
|
-
|
|
459
|
+
|
|
441
460
|
|
|
442
461
|
class Atom(Copyable):
|
|
443
462
|
"""
|
|
444
463
|
A representation of a single atom.
|
|
445
|
-
|
|
464
|
+
|
|
446
465
|
The coordinates an annotations can be accessed directly.
|
|
447
466
|
A detailed description of each annotation category can be viewed
|
|
448
467
|
:doc:`here </apidoc/biotite.structure>`.
|
|
449
|
-
|
|
468
|
+
|
|
450
469
|
Parameters
|
|
451
470
|
----------
|
|
452
471
|
coord: list or ndarray
|
|
453
472
|
The x, y and z coordinates.
|
|
454
473
|
kwargs
|
|
455
474
|
Atom annotations as key value pair.
|
|
456
|
-
|
|
475
|
+
|
|
457
476
|
Attributes
|
|
458
477
|
----------
|
|
459
478
|
{annot} : scalar
|
|
@@ -463,19 +482,19 @@ class Atom(Copyable):
|
|
|
463
482
|
shape : tuple of int
|
|
464
483
|
Shape of the object.
|
|
465
484
|
In case of an :class:`Atom`, the tuple is empty.
|
|
466
|
-
|
|
485
|
+
|
|
467
486
|
Examples
|
|
468
487
|
--------
|
|
469
|
-
|
|
488
|
+
|
|
470
489
|
>>> atom = Atom([1,2,3], chain_id="A")
|
|
471
490
|
>>> atom.atom_name = "CA"
|
|
472
491
|
>>> print(atom.atom_name)
|
|
473
492
|
CA
|
|
474
493
|
>>> print(atom.coord)
|
|
475
494
|
[1. 2. 3.]
|
|
476
|
-
|
|
495
|
+
|
|
477
496
|
"""
|
|
478
|
-
|
|
497
|
+
|
|
479
498
|
def __init__(self, coord, **kwargs):
|
|
480
499
|
self._annot = {}
|
|
481
500
|
self._annot["chain_id"] = ""
|
|
@@ -500,17 +519,17 @@ class Atom(Copyable):
|
|
|
500
519
|
"""Represent Atom as a string for debugging."""
|
|
501
520
|
# print out key-value pairs and format strings in quotation marks
|
|
502
521
|
annot_parts = [
|
|
503
|
-
f'{key}="{value}"' if isinstance(value, str) else f
|
|
522
|
+
f'{key}="{value}"' if isinstance(value, str) else f"{key}={value}"
|
|
504
523
|
for key, value in self._annot.items()
|
|
505
524
|
]
|
|
506
525
|
|
|
507
|
-
annot =
|
|
508
|
-
return f
|
|
526
|
+
annot = ", ".join(annot_parts)
|
|
527
|
+
return f"Atom(np.{np.array_repr(self.coord)}, {annot})"
|
|
509
528
|
|
|
510
529
|
@property
|
|
511
530
|
def shape(self):
|
|
512
531
|
return ()
|
|
513
|
-
|
|
532
|
+
|
|
514
533
|
def __getattr__(self, attr):
|
|
515
534
|
if attr in super().__getattribute__("_annot"):
|
|
516
535
|
return self._annot[attr]
|
|
@@ -518,7 +537,7 @@ class Atom(Copyable):
|
|
|
518
537
|
raise AttributeError(
|
|
519
538
|
f"'{type(self).__name__}' object has no attribute '{attr}'"
|
|
520
539
|
)
|
|
521
|
-
|
|
540
|
+
|
|
522
541
|
def __setattr__(self, attr, value):
|
|
523
542
|
if attr == "_annot":
|
|
524
543
|
super().__setattr__(attr, value)
|
|
@@ -526,16 +545,18 @@ class Atom(Copyable):
|
|
|
526
545
|
super().__setattr__(attr, value)
|
|
527
546
|
else:
|
|
528
547
|
self._annot[attr] = value
|
|
529
|
-
|
|
548
|
+
|
|
530
549
|
def __str__(self):
|
|
531
550
|
hetero = "HET" if self.hetero else ""
|
|
532
|
-
return
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
551
|
+
return (
|
|
552
|
+
f"{hetero:3} {self.chain_id:3} "
|
|
553
|
+
f"{self.res_id:5d}{self.ins_code:1} {self.res_name:3} "
|
|
554
|
+
f"{self.atom_name:6} {self.element:2} "
|
|
555
|
+
f"{self.coord[0]:8.3f} "
|
|
556
|
+
f"{self.coord[1]:8.3f} "
|
|
557
|
+
f"{self.coord[2]:8.3f}"
|
|
558
|
+
)
|
|
559
|
+
|
|
539
560
|
def __eq__(self, item):
|
|
540
561
|
if not isinstance(item, Atom):
|
|
541
562
|
return False
|
|
@@ -547,18 +568,18 @@ class Atom(Copyable):
|
|
|
547
568
|
if self._annot[name] != item._annot[name]:
|
|
548
569
|
return False
|
|
549
570
|
return True
|
|
550
|
-
|
|
571
|
+
|
|
551
572
|
def __ne__(self, item):
|
|
552
573
|
return not self == item
|
|
553
|
-
|
|
574
|
+
|
|
554
575
|
def __copy_create__(self):
|
|
555
576
|
return Atom(self.coord, **self._annot)
|
|
556
577
|
|
|
557
|
-
|
|
578
|
+
|
|
558
579
|
class AtomArray(_AtomArrayBase):
|
|
559
580
|
"""
|
|
560
581
|
An array representation of a model consisting of multiple atoms.
|
|
561
|
-
|
|
582
|
+
|
|
562
583
|
An :class:`AtomArray` can be seen as a list of :class:`Atom`
|
|
563
584
|
instances.
|
|
564
585
|
Instead of using directly a list, this class uses an *NumPy*
|
|
@@ -573,14 +594,14 @@ class AtomArray(_AtomArrayBase):
|
|
|
573
594
|
or :func:`set_annotation()`.
|
|
574
595
|
A detailed description of each annotation category can be viewed
|
|
575
596
|
:doc:`here </apidoc/biotite.structure>`.
|
|
576
|
-
|
|
597
|
+
|
|
577
598
|
In order to get an an subarray of an :class:`AtomArray`,
|
|
578
599
|
*NumPy* style indexing is used.
|
|
579
600
|
This includes slices, boolean arrays, index arrays and even
|
|
580
601
|
*Ellipsis* notation.
|
|
581
602
|
Using a single integer as index returns a single :class:`Atom`
|
|
582
603
|
instance.
|
|
583
|
-
|
|
604
|
+
|
|
584
605
|
Inserting or appending an :class:`AtomArray` to another
|
|
585
606
|
:class:`AtomArray` is done with the '+' operator.
|
|
586
607
|
Only the annotation categories, which are existing in both arrays,
|
|
@@ -611,7 +632,7 @@ class AtomArray(_AtomArrayBase):
|
|
|
611
632
|
----------
|
|
612
633
|
length : int
|
|
613
634
|
The fixed amount of atoms in the array.
|
|
614
|
-
|
|
635
|
+
|
|
615
636
|
Attributes
|
|
616
637
|
----------
|
|
617
638
|
{annot} : ndarray
|
|
@@ -629,44 +650,44 @@ class AtomArray(_AtomArrayBase):
|
|
|
629
650
|
Shape of the atom array.
|
|
630
651
|
The single value in the tuple is
|
|
631
652
|
the length of the atom array.
|
|
632
|
-
|
|
653
|
+
|
|
633
654
|
Examples
|
|
634
655
|
--------
|
|
635
656
|
Creating an atom array from atoms:
|
|
636
|
-
|
|
657
|
+
|
|
637
658
|
>>> atom1 = Atom([1,2,3], chain_id="A")
|
|
638
659
|
>>> atom2 = Atom([2,3,4], chain_id="A")
|
|
639
660
|
>>> atom3 = Atom([3,4,5], chain_id="B")
|
|
640
661
|
>>> atom_array = array([atom1, atom2, atom3])
|
|
641
662
|
>>> print(atom_array.array_length())
|
|
642
663
|
3
|
|
643
|
-
|
|
664
|
+
|
|
644
665
|
Accessing an annotation array:
|
|
645
|
-
|
|
666
|
+
|
|
646
667
|
>>> print(atom_array.chain_id)
|
|
647
668
|
['A' 'A' 'B']
|
|
648
|
-
|
|
669
|
+
|
|
649
670
|
Accessing the coordinates:
|
|
650
|
-
|
|
671
|
+
|
|
651
672
|
>>> print(atom_array.coord)
|
|
652
673
|
[[1. 2. 3.]
|
|
653
674
|
[2. 3. 4.]
|
|
654
675
|
[3. 4. 5.]]
|
|
655
|
-
|
|
676
|
+
|
|
656
677
|
*NumPy* style filtering:
|
|
657
|
-
|
|
678
|
+
|
|
658
679
|
>>> atom_array = atom_array[atom_array.chain_id == "A"]
|
|
659
680
|
>>> print(atom_array.array_length())
|
|
660
681
|
2
|
|
661
|
-
|
|
682
|
+
|
|
662
683
|
Inserting an atom array:
|
|
663
|
-
|
|
684
|
+
|
|
664
685
|
>>> insert = array([Atom([7,8,9], chain_id="C")])
|
|
665
686
|
>>> atom_array = atom_array[0:1] + insert + atom_array[1:2]
|
|
666
687
|
>>> print(atom_array.chain_id)
|
|
667
688
|
['A' 'C' 'A']
|
|
668
689
|
"""
|
|
669
|
-
|
|
690
|
+
|
|
670
691
|
def __init__(self, length):
|
|
671
692
|
super().__init__(length)
|
|
672
693
|
if length is None:
|
|
@@ -676,13 +697,13 @@ class AtomArray(_AtomArrayBase):
|
|
|
676
697
|
|
|
677
698
|
def __repr__(self):
|
|
678
699
|
"""Represent AtomArray as a string for debugging."""
|
|
679
|
-
atoms =
|
|
700
|
+
atoms = ""
|
|
680
701
|
for i in range(0, self.array_length()):
|
|
681
702
|
if len(atoms) == 0:
|
|
682
|
-
atoms =
|
|
703
|
+
atoms = "\n\t" + self.get_atom(i).__repr__()
|
|
683
704
|
else:
|
|
684
|
-
atoms = atoms +
|
|
685
|
-
return f
|
|
705
|
+
atoms = atoms + ",\n\t" + self.get_atom(i).__repr__()
|
|
706
|
+
return f"array([{atoms}\n])"
|
|
686
707
|
|
|
687
708
|
@property
|
|
688
709
|
def shape(self):
|
|
@@ -703,33 +724,33 @@ class AtomArray(_AtomArrayBase):
|
|
|
703
724
|
--------
|
|
704
725
|
array_length
|
|
705
726
|
"""
|
|
706
|
-
return self.array_length(),
|
|
727
|
+
return (self.array_length(),)
|
|
707
728
|
|
|
708
729
|
def get_atom(self, index):
|
|
709
730
|
"""
|
|
710
731
|
Obtain the atom instance of the array at the specified index.
|
|
711
|
-
|
|
732
|
+
|
|
712
733
|
The same as ``array[index]``, if `index` is an integer.
|
|
713
|
-
|
|
734
|
+
|
|
714
735
|
Parameters
|
|
715
736
|
----------
|
|
716
737
|
index : int
|
|
717
738
|
Index of the atom.
|
|
718
|
-
|
|
739
|
+
|
|
719
740
|
Returns
|
|
720
741
|
-------
|
|
721
742
|
atom : Atom
|
|
722
|
-
Atom at position `index`.
|
|
743
|
+
Atom at position `index`.
|
|
723
744
|
"""
|
|
724
745
|
kwargs = {}
|
|
725
746
|
for name, annotation in self._annot.items():
|
|
726
747
|
kwargs[name] = annotation[index]
|
|
727
|
-
return Atom(coord
|
|
728
|
-
|
|
748
|
+
return Atom(coord=self._coord[index], kwargs=kwargs)
|
|
749
|
+
|
|
729
750
|
def __iter__(self):
|
|
730
751
|
"""
|
|
731
752
|
Iterate through the array.
|
|
732
|
-
|
|
753
|
+
|
|
733
754
|
Yields
|
|
734
755
|
------
|
|
735
756
|
atom : Atom
|
|
@@ -738,16 +759,16 @@ class AtomArray(_AtomArrayBase):
|
|
|
738
759
|
while i < len(self):
|
|
739
760
|
yield self.get_atom(i)
|
|
740
761
|
i += 1
|
|
741
|
-
|
|
762
|
+
|
|
742
763
|
def __getitem__(self, index):
|
|
743
764
|
"""
|
|
744
765
|
Obtain a subarray or the atom instance at the specified index.
|
|
745
|
-
|
|
766
|
+
|
|
746
767
|
Parameters
|
|
747
768
|
----------
|
|
748
769
|
index : object
|
|
749
770
|
All index types *NumPy* accepts, are valid.
|
|
750
|
-
|
|
771
|
+
|
|
751
772
|
Returns
|
|
752
773
|
-------
|
|
753
774
|
sub_array : Atom or AtomArray
|
|
@@ -763,16 +784,14 @@ class AtomArray(_AtomArrayBase):
|
|
|
763
784
|
# If first index is "...", just ignore the first index
|
|
764
785
|
return self.__getitem__(index[1])
|
|
765
786
|
else:
|
|
766
|
-
raise IndexError(
|
|
767
|
-
"'AtomArray' does not accept multidimensional indices"
|
|
768
|
-
)
|
|
787
|
+
raise IndexError("'AtomArray' does not accept multidimensional indices")
|
|
769
788
|
else:
|
|
770
789
|
return self._subarray(index)
|
|
771
|
-
|
|
790
|
+
|
|
772
791
|
def __setitem__(self, index, atom):
|
|
773
792
|
"""
|
|
774
793
|
Set the atom at the specified array position.
|
|
775
|
-
|
|
794
|
+
|
|
776
795
|
Parameters
|
|
777
796
|
----------
|
|
778
797
|
index : int
|
|
@@ -781,38 +800,38 @@ class AtomArray(_AtomArrayBase):
|
|
|
781
800
|
The atom to be set.
|
|
782
801
|
"""
|
|
783
802
|
self._set_element(index, atom)
|
|
784
|
-
|
|
803
|
+
|
|
785
804
|
def __delitem__(self, index):
|
|
786
805
|
"""
|
|
787
806
|
Deletes the atom at the specified array position.
|
|
788
|
-
|
|
807
|
+
|
|
789
808
|
Parameters
|
|
790
809
|
----------
|
|
791
810
|
index : int
|
|
792
811
|
The position where the atom should be deleted.
|
|
793
812
|
"""
|
|
794
813
|
self._del_element(index)
|
|
795
|
-
|
|
814
|
+
|
|
796
815
|
def __len__(self):
|
|
797
816
|
"""
|
|
798
817
|
The length of the array.
|
|
799
|
-
|
|
818
|
+
|
|
800
819
|
Returns
|
|
801
820
|
-------
|
|
802
821
|
length : int
|
|
803
822
|
Length of the array.
|
|
804
823
|
"""
|
|
805
824
|
return self.array_length()
|
|
806
|
-
|
|
825
|
+
|
|
807
826
|
def __eq__(self, item):
|
|
808
827
|
"""
|
|
809
828
|
Check if the array equals another :class:`AtomArray`.
|
|
810
|
-
|
|
829
|
+
|
|
811
830
|
Parameters
|
|
812
831
|
----------
|
|
813
832
|
item : object
|
|
814
833
|
Object to campare the array with.
|
|
815
|
-
|
|
834
|
+
|
|
816
835
|
Returns
|
|
817
836
|
-------
|
|
818
837
|
equal : bool
|
|
@@ -824,15 +843,15 @@ class AtomArray(_AtomArrayBase):
|
|
|
824
843
|
if not isinstance(item, AtomArray):
|
|
825
844
|
return False
|
|
826
845
|
return True
|
|
827
|
-
|
|
846
|
+
|
|
828
847
|
def __str__(self):
|
|
829
848
|
"""
|
|
830
849
|
Get a string representation of the array.
|
|
831
|
-
|
|
850
|
+
|
|
832
851
|
Each line contains the attributes of one atom.
|
|
833
852
|
"""
|
|
834
853
|
return "\n".join([str(atom) for atom in self])
|
|
835
|
-
|
|
854
|
+
|
|
836
855
|
def __copy_create__(self):
|
|
837
856
|
return AtomArray(self.array_length())
|
|
838
857
|
|
|
@@ -841,7 +860,7 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
841
860
|
"""
|
|
842
861
|
A collection of multiple :class:`AtomArray` instances, where each
|
|
843
862
|
atom array has equal annotation arrays.
|
|
844
|
-
|
|
863
|
+
|
|
845
864
|
Effectively, this means that each atom is occuring in every array in
|
|
846
865
|
the stack at differing coordinates. This situation arises e.g. in
|
|
847
866
|
NMR-elucidated or simulated structures. Since the annotations are
|
|
@@ -849,7 +868,7 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
849
868
|
coordinate array is 3-D (m x n x 3).
|
|
850
869
|
A detailed description of each annotation category can be viewed
|
|
851
870
|
:doc:`here </apidoc/biotite.structure>`.
|
|
852
|
-
|
|
871
|
+
|
|
853
872
|
Indexing works similar to :class:`AtomArray`, with the difference,
|
|
854
873
|
that two index dimensions are possible:
|
|
855
874
|
The first index dimension specifies the array(s), the second index
|
|
@@ -857,24 +876,24 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
857
876
|
in :class:`AtomArray`).
|
|
858
877
|
Using a single integer as first dimension index returns a single
|
|
859
878
|
:class:`AtomArray` instance.
|
|
860
|
-
|
|
879
|
+
|
|
861
880
|
Concatenation of atoms for each array in the stack is done using the
|
|
862
881
|
'+' operator. For addition of atom arrays onto the stack use the
|
|
863
882
|
:func:`stack()` method.
|
|
864
883
|
|
|
865
884
|
The :attr:`box` attribute has the shape *m x 3 x 3*, as the cell
|
|
866
885
|
might be different for each frame in the atom array stack.
|
|
867
|
-
|
|
886
|
+
|
|
868
887
|
Parameters
|
|
869
888
|
----------
|
|
870
889
|
depth : int
|
|
871
890
|
The fixed amount of arrays in the stack. When indexing, this is
|
|
872
891
|
the length of the first dimension.
|
|
873
|
-
|
|
892
|
+
|
|
874
893
|
length : int
|
|
875
894
|
The fixed amount of atoms in each array in the stack. When
|
|
876
895
|
indexing, this is the length of the second dimension.
|
|
877
|
-
|
|
896
|
+
|
|
878
897
|
Attributes
|
|
879
898
|
----------
|
|
880
899
|
{annot} : ndarray, shape=(n,)
|
|
@@ -892,15 +911,15 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
892
911
|
Shape of the stack.
|
|
893
912
|
The numbers correspond to the stack depth
|
|
894
913
|
and array length, respectively.
|
|
895
|
-
|
|
914
|
+
|
|
896
915
|
See also
|
|
897
916
|
--------
|
|
898
917
|
AtomArray
|
|
899
|
-
|
|
918
|
+
|
|
900
919
|
Examples
|
|
901
920
|
--------
|
|
902
921
|
Creating an atom array stack from two arrays:
|
|
903
|
-
|
|
922
|
+
|
|
904
923
|
>>> atom1 = Atom([1,2,3], chain_id="A")
|
|
905
924
|
>>> atom2 = Atom([2,3,4], chain_id="A")
|
|
906
925
|
>>> atom3 = Atom([3,4,5], chain_id="B")
|
|
@@ -925,40 +944,40 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
925
944
|
[5. 6. 7.]
|
|
926
945
|
[6. 7. 8.]]]
|
|
927
946
|
"""
|
|
928
|
-
|
|
947
|
+
|
|
929
948
|
def __init__(self, depth, length):
|
|
930
949
|
super().__init__(length)
|
|
931
|
-
if depth
|
|
950
|
+
if depth is None or length is None:
|
|
932
951
|
self._coord = None
|
|
933
952
|
else:
|
|
934
953
|
self._coord = np.full((depth, length, 3), np.nan, dtype=np.float32)
|
|
935
954
|
|
|
936
955
|
def __repr__(self):
|
|
937
956
|
"""Represent AtomArrayStack as a string for debugging."""
|
|
938
|
-
arrays =
|
|
957
|
+
arrays = ""
|
|
939
958
|
for i in range(0, self.stack_depth()):
|
|
940
959
|
if len(arrays) == 0:
|
|
941
|
-
arrays =
|
|
960
|
+
arrays = "\n\t" + self.get_array(i).__repr__()
|
|
942
961
|
else:
|
|
943
|
-
arrays = arrays +
|
|
944
|
-
return f
|
|
962
|
+
arrays = arrays + ",\n\t" + self.get_array(i).__repr__()
|
|
963
|
+
return f"stack([{arrays}\n])"
|
|
945
964
|
|
|
946
965
|
def get_array(self, index):
|
|
947
966
|
"""
|
|
948
967
|
Obtain the atom array instance of the stack at the specified
|
|
949
968
|
index.
|
|
950
|
-
|
|
969
|
+
|
|
951
970
|
The same as ``stack[index]``, if `index` is an integer.
|
|
952
|
-
|
|
971
|
+
|
|
953
972
|
Parameters
|
|
954
973
|
----------
|
|
955
974
|
index : int
|
|
956
975
|
Index of the atom array.
|
|
957
|
-
|
|
976
|
+
|
|
958
977
|
Returns
|
|
959
978
|
-------
|
|
960
979
|
array : AtomArray
|
|
961
|
-
AtomArray at position `index`.
|
|
980
|
+
AtomArray at position `index`.
|
|
962
981
|
"""
|
|
963
982
|
array = AtomArray(self.array_length())
|
|
964
983
|
for name in self._annot:
|
|
@@ -970,14 +989,14 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
970
989
|
array._box = self._box[index]
|
|
971
990
|
|
|
972
991
|
return array
|
|
973
|
-
|
|
992
|
+
|
|
974
993
|
def stack_depth(self):
|
|
975
994
|
"""
|
|
976
995
|
Get the depth of the stack.
|
|
977
|
-
|
|
996
|
+
|
|
978
997
|
This value represents the amount of atom arrays in the stack.
|
|
979
998
|
It is the same as ``len(array)``.
|
|
980
|
-
|
|
999
|
+
|
|
981
1000
|
Returns
|
|
982
1001
|
-------
|
|
983
1002
|
length : int
|
|
@@ -1005,7 +1024,7 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
1005
1024
|
def __iter__(self):
|
|
1006
1025
|
"""
|
|
1007
1026
|
Iterate through the array.
|
|
1008
|
-
|
|
1027
|
+
|
|
1009
1028
|
Yields
|
|
1010
1029
|
------
|
|
1011
1030
|
array : AtomArray
|
|
@@ -1014,17 +1033,17 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
1014
1033
|
while i < len(self):
|
|
1015
1034
|
yield self.get_array(i)
|
|
1016
1035
|
i += 1
|
|
1017
|
-
|
|
1036
|
+
|
|
1018
1037
|
def __getitem__(self, index):
|
|
1019
1038
|
"""
|
|
1020
1039
|
Obtain the atom array instance or an substack at the specified
|
|
1021
1040
|
index.
|
|
1022
|
-
|
|
1041
|
+
|
|
1023
1042
|
Parameters
|
|
1024
1043
|
----------
|
|
1025
1044
|
index : object
|
|
1026
1045
|
All index types *NumPy* accepts are valid.
|
|
1027
|
-
|
|
1046
|
+
|
|
1028
1047
|
Returns
|
|
1029
1048
|
-------
|
|
1030
1049
|
sub_array : AtomArray or AtomArrayStack
|
|
@@ -1033,7 +1052,7 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
1033
1052
|
Otherwise an :class:`AtomArrayStack` with reduced depth and
|
|
1034
1053
|
length is returned.
|
|
1035
1054
|
In case the index is a tuple(int, int) an :class:`Atom`
|
|
1036
|
-
instance is returned.
|
|
1055
|
+
instance is returned.
|
|
1037
1056
|
"""
|
|
1038
1057
|
if isinstance(index, numbers.Integral):
|
|
1039
1058
|
return self.get_array(index)
|
|
@@ -1050,7 +1069,7 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
1050
1069
|
if isinstance(index[1], numbers.Integral):
|
|
1051
1070
|
# Prevent reduction in dimensionality
|
|
1052
1071
|
# in second dimension
|
|
1053
|
-
new_stack = self._subarray(slice(index[1], index[1]+1))
|
|
1072
|
+
new_stack = self._subarray(slice(index[1], index[1] + 1))
|
|
1054
1073
|
else:
|
|
1055
1074
|
new_stack = self._subarray(index[1])
|
|
1056
1075
|
if index[0] is not Ellipsis:
|
|
@@ -1065,14 +1084,13 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
1065
1084
|
if self._box is not None:
|
|
1066
1085
|
new_stack._box = self._box[index]
|
|
1067
1086
|
return new_stack
|
|
1068
|
-
|
|
1069
|
-
|
|
1087
|
+
|
|
1070
1088
|
def __setitem__(self, index, array):
|
|
1071
1089
|
"""
|
|
1072
1090
|
Set the atom array at the specified stack position.
|
|
1073
|
-
|
|
1091
|
+
|
|
1074
1092
|
The array and the stack must have equal annotation arrays.
|
|
1075
|
-
|
|
1093
|
+
|
|
1076
1094
|
Parameters
|
|
1077
1095
|
----------
|
|
1078
1096
|
index : int
|
|
@@ -1081,26 +1099,20 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
1081
1099
|
The atom array to be set.
|
|
1082
1100
|
"""
|
|
1083
1101
|
if not self.equal_annotations(array):
|
|
1084
|
-
raise ValueError(
|
|
1085
|
-
"The stack and the array have unequal annotations"
|
|
1086
|
-
)
|
|
1102
|
+
raise ValueError("The stack and the array have unequal annotations")
|
|
1087
1103
|
if self.bonds != array.bonds:
|
|
1088
|
-
raise ValueError(
|
|
1089
|
-
"The stack and the array have unequal bonds"
|
|
1090
|
-
)
|
|
1104
|
+
raise ValueError("The stack and the array have unequal bonds")
|
|
1091
1105
|
if isinstance(index, numbers.Integral):
|
|
1092
1106
|
self.coord[index] = array.coord
|
|
1093
1107
|
if self.box is not None:
|
|
1094
1108
|
self.box[index] = array.box
|
|
1095
1109
|
else:
|
|
1096
|
-
raise TypeError(
|
|
1097
|
-
|
|
1098
|
-
)
|
|
1099
|
-
|
|
1110
|
+
raise TypeError(f"Index must be integer, not '{type(index).__name__}'")
|
|
1111
|
+
|
|
1100
1112
|
def __delitem__(self, index):
|
|
1101
1113
|
"""
|
|
1102
1114
|
Deletes the atom array at the specified stack position.
|
|
1103
|
-
|
|
1115
|
+
|
|
1104
1116
|
Parameters
|
|
1105
1117
|
----------
|
|
1106
1118
|
index : int
|
|
@@ -1109,14 +1121,12 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
1109
1121
|
if isinstance(index, numbers.Integral):
|
|
1110
1122
|
self._coord = np.delete(self._coord, index, axis=0)
|
|
1111
1123
|
else:
|
|
1112
|
-
raise TypeError(
|
|
1113
|
-
|
|
1114
|
-
)
|
|
1115
|
-
|
|
1124
|
+
raise TypeError(f"Index must be integer, not '{type(index).__name__}'")
|
|
1125
|
+
|
|
1116
1126
|
def __len__(self):
|
|
1117
1127
|
"""
|
|
1118
1128
|
The depth of the stack, i.e. the amount of models.
|
|
1119
|
-
|
|
1129
|
+
|
|
1120
1130
|
Returns
|
|
1121
1131
|
-------
|
|
1122
1132
|
depth : int
|
|
@@ -1124,16 +1134,16 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
1124
1134
|
"""
|
|
1125
1135
|
# length is determined by length of coord attribute
|
|
1126
1136
|
return self._coord.shape[0]
|
|
1127
|
-
|
|
1137
|
+
|
|
1128
1138
|
def __eq__(self, item):
|
|
1129
1139
|
"""
|
|
1130
1140
|
Check if the array equals another :class:`AtomArray`
|
|
1131
|
-
|
|
1141
|
+
|
|
1132
1142
|
Parameters
|
|
1133
1143
|
----------
|
|
1134
1144
|
item : object
|
|
1135
1145
|
Object to campare the array with.
|
|
1136
|
-
|
|
1146
|
+
|
|
1137
1147
|
Returns
|
|
1138
1148
|
-------
|
|
1139
1149
|
equal : bool
|
|
@@ -1145,20 +1155,20 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
1145
1155
|
if not isinstance(item, AtomArrayStack):
|
|
1146
1156
|
return False
|
|
1147
1157
|
return True
|
|
1148
|
-
|
|
1158
|
+
|
|
1149
1159
|
def __str__(self):
|
|
1150
1160
|
"""
|
|
1151
1161
|
Get a string representation of the stack.
|
|
1152
|
-
|
|
1162
|
+
|
|
1153
1163
|
:class:`AtomArray` strings eparated by blank lines
|
|
1154
1164
|
and a line indicating the index.
|
|
1155
1165
|
"""
|
|
1156
1166
|
string = ""
|
|
1157
1167
|
for i, array in enumerate(self):
|
|
1158
|
-
string += "Model " + str(i+1) + "\n"
|
|
1168
|
+
string += "Model " + str(i + 1) + "\n"
|
|
1159
1169
|
string += str(array) + "\n" + "\n"
|
|
1160
1170
|
return string
|
|
1161
|
-
|
|
1171
|
+
|
|
1162
1172
|
def __copy_create__(self):
|
|
1163
1173
|
return AtomArrayStack(self.stack_depth(), self.array_length())
|
|
1164
1174
|
|
|
@@ -1166,23 +1176,23 @@ class AtomArrayStack(_AtomArrayBase):
|
|
|
1166
1176
|
def array(atoms):
|
|
1167
1177
|
"""
|
|
1168
1178
|
Create an :class:`AtomArray` from a list of :class:`Atom`.
|
|
1169
|
-
|
|
1179
|
+
|
|
1170
1180
|
Parameters
|
|
1171
1181
|
----------
|
|
1172
1182
|
atoms : iterable object of Atom
|
|
1173
1183
|
The atoms to be combined in an array.
|
|
1174
1184
|
All atoms must share the same annotation categories.
|
|
1175
|
-
|
|
1185
|
+
|
|
1176
1186
|
Returns
|
|
1177
1187
|
-------
|
|
1178
1188
|
array : AtomArray
|
|
1179
1189
|
The listed atoms as array.
|
|
1180
|
-
|
|
1190
|
+
|
|
1181
1191
|
Examples
|
|
1182
1192
|
--------
|
|
1183
|
-
|
|
1193
|
+
|
|
1184
1194
|
Creating an atom array from atoms:
|
|
1185
|
-
|
|
1195
|
+
|
|
1186
1196
|
>>> atom1 = Atom([1,2,3], chain_id="A")
|
|
1187
1197
|
>>> atom2 = Atom([2,3,4], chain_id="A")
|
|
1188
1198
|
>>> atom3 = Atom([3,4,5], chain_id="B")
|
|
@@ -1204,7 +1214,7 @@ def array(atoms):
|
|
|
1204
1214
|
array = AtomArray(len(atoms))
|
|
1205
1215
|
# Add all (also optional) annotation categories
|
|
1206
1216
|
for name in names:
|
|
1207
|
-
array.add_annotation(name, dtype=type(atoms[0]._annot[name]))
|
|
1217
|
+
array.add_annotation(name, dtype=type(atoms[0]._annot[name]))
|
|
1208
1218
|
# Add all atoms to AtomArray
|
|
1209
1219
|
for i in range(len(atoms)):
|
|
1210
1220
|
for name in names:
|
|
@@ -1216,23 +1226,23 @@ def array(atoms):
|
|
|
1216
1226
|
def stack(arrays):
|
|
1217
1227
|
"""
|
|
1218
1228
|
Create an :class:`AtomArrayStack` from a list of :class:`AtomArray`.
|
|
1219
|
-
|
|
1229
|
+
|
|
1220
1230
|
Parameters
|
|
1221
1231
|
----------
|
|
1222
1232
|
arrays : iterable object of AtomArray
|
|
1223
1233
|
The atom arrays to be combined in a stack.
|
|
1224
1234
|
All atom arrays must have an equal number of atoms and equal
|
|
1225
1235
|
annotation arrays.
|
|
1226
|
-
|
|
1236
|
+
|
|
1227
1237
|
Returns
|
|
1228
1238
|
-------
|
|
1229
1239
|
stack : AtomArrayStack
|
|
1230
1240
|
The stacked atom arrays.
|
|
1231
|
-
|
|
1241
|
+
|
|
1232
1242
|
Examples
|
|
1233
1243
|
--------
|
|
1234
1244
|
Creating an atom array stack from two arrays:
|
|
1235
|
-
|
|
1245
|
+
|
|
1236
1246
|
>>> atom1 = Atom([1,2,3], chain_id="A")
|
|
1237
1247
|
>>> atom2 = Atom([2,3,4], chain_id="A")
|
|
1238
1248
|
>>> atom3 = Atom([3,4,5], chain_id="B")
|
|
@@ -1272,7 +1282,7 @@ def stack(arrays):
|
|
|
1272
1282
|
array_stack = AtomArrayStack(array_count, ref_array.array_length())
|
|
1273
1283
|
for name, annotation in ref_array._annot.items():
|
|
1274
1284
|
array_stack._annot[name] = annotation
|
|
1275
|
-
coord_list = [array._coord for array in arrays]
|
|
1285
|
+
coord_list = [array._coord for array in arrays]
|
|
1276
1286
|
array_stack._coord = np.stack(coord_list, axis=0)
|
|
1277
1287
|
# Take bond list from first array
|
|
1278
1288
|
array_stack._bonds = ref_array._bonds
|
|
@@ -1296,14 +1306,14 @@ def repeat(atoms, coord):
|
|
|
1296
1306
|
The length of first dimension determines the number of repeats.
|
|
1297
1307
|
If `atoms` is an :class:`AtomArray` 3 dimensions, otherwise
|
|
1298
1308
|
4 dimensions are required.
|
|
1299
|
-
|
|
1309
|
+
|
|
1300
1310
|
Returns
|
|
1301
1311
|
-------
|
|
1302
1312
|
repeated: AtomArray, shape=(n*k,) or AtomArrayStack, shape=(m,n*k)
|
|
1303
1313
|
The repeated atoms.
|
|
1304
1314
|
Whether an :class:`AtomArray` or an :class:`AtomArrayStack` is
|
|
1305
1315
|
returned depends on the input `atoms`.
|
|
1306
|
-
|
|
1316
|
+
|
|
1307
1317
|
Examples
|
|
1308
1318
|
--------
|
|
1309
1319
|
|
|
@@ -1336,7 +1346,7 @@ def repeat(atoms, coord):
|
|
|
1336
1346
|
raise ValueError(
|
|
1337
1347
|
f"Expected 4 dimensions for the coordinate array, got {coord.ndim}"
|
|
1338
1348
|
)
|
|
1339
|
-
|
|
1349
|
+
|
|
1340
1350
|
repetitions = len(coord)
|
|
1341
1351
|
orig_length = atoms.array_length()
|
|
1342
1352
|
new_length = orig_length * repetitions
|
|
@@ -1358,24 +1368,24 @@ def repeat(atoms, coord):
|
|
|
1358
1368
|
)
|
|
1359
1369
|
repeated = AtomArrayStack(atoms.stack_depth(), new_length)
|
|
1360
1370
|
repeated.coord = coord.reshape((atoms.stack_depth(), new_length, 3))
|
|
1361
|
-
|
|
1371
|
+
|
|
1362
1372
|
else:
|
|
1363
1373
|
raise TypeError(
|
|
1364
1374
|
f"Expected 'AtomArray' or 'AtomArrayStack', "
|
|
1365
1375
|
f"but got {type(atoms).__name__}"
|
|
1366
1376
|
)
|
|
1367
|
-
|
|
1377
|
+
|
|
1368
1378
|
for category in atoms.get_annotation_categories():
|
|
1369
1379
|
annot = np.tile(atoms.get_annotation(category), repetitions)
|
|
1370
1380
|
repeated.set_annotation(category, annot)
|
|
1371
1381
|
if atoms.bonds is not None:
|
|
1372
1382
|
repeated_bonds = atoms.bonds.copy()
|
|
1373
|
-
for _ in range(repetitions-1):
|
|
1383
|
+
for _ in range(repetitions - 1):
|
|
1374
1384
|
repeated_bonds += atoms.bonds
|
|
1375
1385
|
repeated.bonds = repeated_bonds
|
|
1376
1386
|
if atoms.box is not None:
|
|
1377
1387
|
repeated.box = atoms.box.copy()
|
|
1378
|
-
|
|
1388
|
+
|
|
1379
1389
|
return repeated
|
|
1380
1390
|
|
|
1381
1391
|
|
|
@@ -1383,7 +1393,7 @@ def from_template(template, coord, box=None):
|
|
|
1383
1393
|
"""
|
|
1384
1394
|
Create an :class:`AtomArrayStack` using template atoms and given
|
|
1385
1395
|
coordinates.
|
|
1386
|
-
|
|
1396
|
+
|
|
1387
1397
|
Parameters
|
|
1388
1398
|
----------
|
|
1389
1399
|
template : AtomArray, shape=(n,) or AtomArrayStack, shape=(m,n)
|
|
@@ -1393,7 +1403,7 @@ def from_template(template, coord, box=None):
|
|
|
1393
1403
|
The coordinates for each model of the returned stack.
|
|
1394
1404
|
box : ndarray, optional, dtype=float, shape=(l,3,3)
|
|
1395
1405
|
The box for each model of the returned stack.
|
|
1396
|
-
|
|
1406
|
+
|
|
1397
1407
|
Returns
|
|
1398
1408
|
-------
|
|
1399
1409
|
array_stack : AtomArrayStack
|
|
@@ -1409,7 +1419,7 @@ def from_template(template, coord, box=None):
|
|
|
1409
1419
|
|
|
1410
1420
|
# Create empty stack with no models
|
|
1411
1421
|
new_stack = AtomArrayStack(0, template.array_length())
|
|
1412
|
-
|
|
1422
|
+
|
|
1413
1423
|
for category in template.get_annotation_categories():
|
|
1414
1424
|
annot = template.get_annotation(category)
|
|
1415
1425
|
new_stack.set_annotation(category, annot)
|
|
@@ -1417,30 +1427,30 @@ def from_template(template, coord, box=None):
|
|
|
1417
1427
|
new_stack.bonds = template.bonds.copy()
|
|
1418
1428
|
if box is not None:
|
|
1419
1429
|
new_stack.box = box.copy()
|
|
1420
|
-
|
|
1430
|
+
|
|
1421
1431
|
# After setting the coordinates the number of models is the number
|
|
1422
1432
|
# of models in the new coordinates
|
|
1423
1433
|
new_stack.coord = coord
|
|
1424
|
-
|
|
1434
|
+
|
|
1425
1435
|
return new_stack
|
|
1426
1436
|
|
|
1427
1437
|
|
|
1428
1438
|
def coord(item):
|
|
1429
1439
|
"""
|
|
1430
1440
|
Get the atom coordinates of the given array.
|
|
1431
|
-
|
|
1441
|
+
|
|
1432
1442
|
This may be directly and :class:`Atom`, :class:`AtomArray` or
|
|
1433
1443
|
:class:`AtomArrayStack` or
|
|
1434
1444
|
alternatively an (n x 3) or (m x n x 3) :class:`ndarray`
|
|
1435
1445
|
containing the coordinates.
|
|
1436
|
-
|
|
1446
|
+
|
|
1437
1447
|
Parameters
|
|
1438
1448
|
----------
|
|
1439
1449
|
item : Atom or AtomArray or AtomArrayStack or ndarray
|
|
1440
1450
|
Returns the :attr:`coord` attribute, if `item` is an
|
|
1441
1451
|
:class:`Atom`, :class:`AtomArray` or :class:`AtomArrayStack`.
|
|
1442
1452
|
Directly returns the input, if `item` is a :class:`ndarray`.
|
|
1443
|
-
|
|
1453
|
+
|
|
1444
1454
|
Returns
|
|
1445
1455
|
-------
|
|
1446
1456
|
coord : ndarray
|