biotite 1.1.0__cp312-cp312-macosx_11_0_arm64.whl → 1.3.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 (160) 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 +10 -8
  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 +20 -0
  32. biotite/interface/openmm/state.py +93 -0
  33. biotite/interface/openmm/system.py +227 -0
  34. biotite/interface/pymol/__init__.py +201 -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 +19 -0
  42. biotite/interface/rdkit/mol.py +490 -0
  43. biotite/interface/version.py +94 -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 +22 -22
  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/multiple.pyx +1 -2
  62. biotite/sequence/align/pairwise.cpython-312-darwin.so +0 -0
  63. biotite/sequence/align/pairwise.pyx +37 -39
  64. biotite/sequence/align/permutation.cpython-312-darwin.so +0 -0
  65. biotite/sequence/align/selector.cpython-312-darwin.so +0 -0
  66. biotite/sequence/align/selector.pyx +2 -2
  67. biotite/sequence/align/statistics.py +1 -1
  68. biotite/sequence/align/tracetable.cpython-312-darwin.so +0 -0
  69. biotite/sequence/alphabet.py +2 -2
  70. biotite/sequence/annotation.py +19 -13
  71. biotite/sequence/codec.cpython-312-darwin.so +0 -0
  72. biotite/sequence/codon.py +1 -2
  73. biotite/sequence/graphics/alignment.py +25 -39
  74. biotite/sequence/graphics/dendrogram.py +4 -2
  75. biotite/sequence/graphics/features.py +2 -2
  76. biotite/sequence/graphics/logo.py +10 -12
  77. biotite/sequence/io/fasta/convert.py +1 -2
  78. biotite/sequence/io/fasta/file.py +1 -1
  79. biotite/sequence/io/fastq/file.py +3 -3
  80. biotite/sequence/io/genbank/file.py +3 -3
  81. biotite/sequence/io/genbank/sequence.py +2 -0
  82. biotite/sequence/io/gff/convert.py +1 -1
  83. biotite/sequence/io/gff/file.py +1 -2
  84. biotite/sequence/phylo/nj.cpython-312-darwin.so +0 -0
  85. biotite/sequence/phylo/tree.cpython-312-darwin.so +0 -0
  86. biotite/sequence/phylo/upgma.cpython-312-darwin.so +0 -0
  87. biotite/sequence/profile.py +19 -25
  88. biotite/sequence/search.py +0 -1
  89. biotite/sequence/seqtypes.py +12 -5
  90. biotite/sequence/sequence.py +1 -2
  91. biotite/structure/__init__.py +2 -0
  92. biotite/structure/alphabet/i3d.py +1 -2
  93. biotite/structure/alphabet/pb.py +1 -2
  94. biotite/structure/alphabet/unkerasify.py +8 -2
  95. biotite/structure/atoms.py +35 -27
  96. biotite/structure/basepairs.py +39 -40
  97. biotite/structure/bonds.cpython-312-darwin.so +0 -0
  98. biotite/structure/bonds.pyx +8 -5
  99. biotite/structure/box.py +159 -23
  100. biotite/structure/celllist.cpython-312-darwin.so +0 -0
  101. biotite/structure/celllist.pyx +83 -68
  102. biotite/structure/chains.py +17 -55
  103. biotite/structure/charges.cpython-312-darwin.so +0 -0
  104. biotite/structure/compare.py +420 -13
  105. biotite/structure/density.py +1 -1
  106. biotite/structure/dotbracket.py +31 -32
  107. biotite/structure/filter.py +8 -8
  108. biotite/structure/geometry.py +15 -15
  109. biotite/structure/graphics/rna.py +19 -16
  110. biotite/structure/hbond.py +18 -21
  111. biotite/structure/info/atoms.py +11 -2
  112. biotite/structure/info/ccd.py +0 -2
  113. biotite/structure/info/components.bcif +0 -0
  114. biotite/structure/info/groups.py +0 -3
  115. biotite/structure/info/misc.py +0 -1
  116. biotite/structure/info/radii.py +92 -22
  117. biotite/structure/info/standardize.py +1 -2
  118. biotite/structure/integrity.py +4 -6
  119. biotite/structure/io/general.py +2 -2
  120. biotite/structure/io/gro/file.py +8 -9
  121. biotite/structure/io/mol/convert.py +1 -1
  122. biotite/structure/io/mol/ctab.py +33 -28
  123. biotite/structure/io/mol/mol.py +1 -1
  124. biotite/structure/io/mol/sdf.py +39 -13
  125. biotite/structure/io/pdb/convert.py +86 -5
  126. biotite/structure/io/pdb/file.py +90 -24
  127. biotite/structure/io/pdb/hybrid36.cpython-312-darwin.so +0 -0
  128. biotite/structure/io/pdbqt/file.py +4 -4
  129. biotite/structure/io/pdbx/bcif.py +22 -7
  130. biotite/structure/io/pdbx/cif.py +20 -7
  131. biotite/structure/io/pdbx/component.py +6 -0
  132. biotite/structure/io/pdbx/compress.py +71 -34
  133. biotite/structure/io/pdbx/convert.py +429 -77
  134. biotite/structure/io/pdbx/encoding.cpython-312-darwin.so +0 -0
  135. biotite/structure/io/pdbx/encoding.pyx +39 -23
  136. biotite/structure/io/trajfile.py +9 -6
  137. biotite/structure/io/util.py +38 -0
  138. biotite/structure/mechanics.py +0 -1
  139. biotite/structure/molecules.py +0 -15
  140. biotite/structure/pseudoknots.py +13 -19
  141. biotite/structure/repair.py +2 -4
  142. biotite/structure/residues.py +20 -48
  143. biotite/structure/rings.py +335 -0
  144. biotite/structure/sasa.cpython-312-darwin.so +0 -0
  145. biotite/structure/sasa.pyx +30 -30
  146. biotite/structure/segments.py +123 -9
  147. biotite/structure/sequence.py +0 -1
  148. biotite/structure/spacegroups.json +1567 -0
  149. biotite/structure/spacegroups.license +26 -0
  150. biotite/structure/sse.py +0 -2
  151. biotite/structure/superimpose.py +75 -253
  152. biotite/structure/tm.py +581 -0
  153. biotite/structure/transform.py +232 -26
  154. biotite/structure/util.py +3 -3
  155. biotite/version.py +9 -4
  156. biotite/visualize.py +111 -1
  157. {biotite-1.1.0.dist-info → biotite-1.3.0.dist-info}/METADATA +8 -36
  158. {biotite-1.1.0.dist-info → biotite-1.3.0.dist-info}/RECORD +160 -138
  159. {biotite-1.1.0.dist-info → biotite-1.3.0.dist-info}/WHEEL +3 -1
  160. {biotite-1.1.0.dist-info → biotite-1.3.0.dist-info}/licenses/LICENSE.rst +0 -0
@@ -48,7 +48,6 @@ class GROFile(TextFile):
48
48
  >>> file = GROFile()
49
49
  >>> file.set_structure(array_stack_mod)
50
50
  >>> file.write(os.path.join(path_to_directory, "1l2y_mod.gro"))
51
-
52
51
  """
53
52
 
54
53
  def get_model_count(self):
@@ -89,13 +88,13 @@ class GROFile(TextFile):
89
88
  The return type depends on the `model` parameter.
90
89
  """
91
90
 
92
- def get_atom_line_i(model_start_i, model_atom_counts):
91
+ def _get_atom_line_i(model_start_i, model_atom_counts):
93
92
  """
94
93
  Helper function to get the indices of all atoms for a model
95
94
  """
96
95
  return np.arange(model_start_i + 1, model_start_i + 1 + model_atom_counts)
97
96
 
98
- def set_box_dimen(box_param):
97
+ def _set_box_dimen(box_param):
99
98
  """
100
99
  Helper function to create the box vectors from the values
101
100
  in the GRO file
@@ -145,7 +144,7 @@ class GROFile(TextFile):
145
144
 
146
145
  # Line indices for annotation determination is determined
147
146
  # from model 1
148
- annot_i = get_atom_line_i(model_start_i[0], length)
147
+ annot_i = _get_atom_line_i(model_start_i[0], length)
149
148
  else:
150
149
  if model == 0:
151
150
  raise ValueError("The model index must not be 0")
@@ -160,7 +159,7 @@ class GROFile(TextFile):
160
159
  length = model_atom_counts[model - 1]
161
160
  array = AtomArray(length)
162
161
 
163
- annot_i = get_atom_line_i(model_start_i[model - 1], length)
162
+ annot_i = _get_atom_line_i(model_start_i[model - 1], length)
164
163
 
165
164
  # Replace empty strings for elements with guessed types
166
165
  # i is index in array, line_i is line index
@@ -183,11 +182,11 @@ class GROFile(TextFile):
183
182
  # Box is stored in last line (after coordinates)
184
183
  box_i = atom_i[-1] + 1
185
184
  box_param = [float(e) * 10 for e in self.lines[box_i].split()]
186
- array.box = set_box_dimen(box_param)
185
+ array.box = _set_box_dimen(box_param)
187
186
 
188
187
  elif isinstance(array, AtomArrayStack):
189
188
  for m in range(len(model_start_i)):
190
- atom_i = get_atom_line_i(model_start_i[m], model_atom_counts[m])
189
+ atom_i = _get_atom_line_i(model_start_i[m], model_atom_counts[m])
191
190
  for i, line_i in enumerate(atom_i):
192
191
  line = self.lines[line_i]
193
192
  array.coord[m, i, 0] = float(line[20:28]) * 10
@@ -196,7 +195,7 @@ class GROFile(TextFile):
196
195
  # Box is stored in last line (after coordinates)
197
196
  box_i = atom_i[-1] + 1
198
197
  box_param = [float(e) * 10 for e in self.lines[box_i].split()]
199
- box = set_box_dimen(box_param)
198
+ box = _set_box_dimen(box_param)
200
199
  # Create a box in the stack if not already existing
201
200
  # and the box is not a dummy
202
201
  if box is not None:
@@ -311,7 +310,7 @@ class GROFile(TextFile):
311
310
 
312
311
  for i in range(array.stack_depth()):
313
312
  self.lines.append(
314
- f"Generated by Biotite at {datetime.now()}, model={i+1}"
313
+ f"Generated by Biotite at {datetime.now()}, model={i + 1}"
315
314
  )
316
315
  self.lines.append(str(array.array_length()))
317
316
 
@@ -52,7 +52,7 @@ def set_structure(
52
52
  ----------
53
53
  mol_file : MOLFile
54
54
  The MOL file.
55
- array : AtomArray
55
+ atoms : AtomArray
56
56
  The array to be saved into this file.
57
57
  Must have an associated :class:`BondList`.
58
58
  Bond type fallback for the *Bond block*, if a
@@ -19,24 +19,19 @@ from biotite.file import InvalidFileError
19
19
  from biotite.structure.atoms import AtomArray, AtomArrayStack
20
20
  from biotite.structure.bonds import BondList, BondType
21
21
  from biotite.structure.error import BadStructureError
22
+ from biotite.structure.io.util import number_of_integer_digits
22
23
 
23
24
  BOND_TYPE_MAPPING = {
24
25
  1: BondType.SINGLE,
25
26
  2: BondType.DOUBLE,
26
27
  3: BondType.TRIPLE,
28
+ 4: BondType.AROMATIC,
27
29
  5: BondType.ANY,
28
- 6: BondType.SINGLE,
29
- 7: BondType.DOUBLE,
30
+ 6: BondType.AROMATIC_SINGLE,
31
+ 7: BondType.AROMATIC_DOUBLE,
30
32
  8: BondType.ANY,
31
33
  }
32
- BOND_TYPE_MAPPING_REV = {
33
- BondType.SINGLE: 1,
34
- BondType.DOUBLE: 2,
35
- BondType.TRIPLE: 3,
36
- BondType.AROMATIC_SINGLE: 1,
37
- BondType.AROMATIC_DOUBLE: 2,
38
- BondType.ANY: 8,
39
- }
34
+ BOND_TYPE_MAPPING_REV = {v: k for k, v in BOND_TYPE_MAPPING.items()}
40
35
 
41
36
  CHARGE_MAPPING = {0: 0, 1: 3, 2: 2, 3: 1, 5: -1, 6: -2, 7: -3}
42
37
  CHARGE_MAPPING_REV = {val: key for key, val in CHARGE_MAPPING.items()}
@@ -56,7 +51,7 @@ def read_structure_from_ctab(ctab_lines):
56
51
  ----------
57
52
  ctab_lines : lines of str
58
53
  The lines containing the *ctab*.
59
- Must begin with the *counts* line and end with the `M END` line
54
+ Must begin with the *counts* line and end with the `M END` line.
60
55
 
61
56
  Returns
62
57
  -------
@@ -71,7 +66,6 @@ def read_structure_from_ctab(ctab_lines):
71
66
  `<https://discover.3ds.com/sites/default/files/2020-08/biovia_ctfileformats_2020.pdf>`_.
72
67
 
73
68
  .. footbibliography::
74
-
75
69
  """
76
70
  match _get_version(ctab_lines[0]):
77
71
  case "V2000":
@@ -119,11 +113,10 @@ def write_structure_to_ctab(atoms, default_bond_type=BondType.ANY, version=None)
119
113
  `<https://discover.3ds.com/sites/default/files/2020-08/biovia_ctfileformats_2020.pdf>`_.
120
114
 
121
115
  .. footbibliography::
122
-
123
116
  """
124
117
  if isinstance(atoms, AtomArrayStack):
125
118
  raise TypeError(
126
- "An 'AtomArrayStack' was given, " "but only a single model can be written"
119
+ "An 'AtomArrayStack' was given, but only a single model can be written"
127
120
  )
128
121
  if atoms.bonds is None:
129
122
  raise BadStructureError("Input AtomArray has no associated BondList")
@@ -141,8 +134,7 @@ def write_structure_to_ctab(atoms, default_bond_type=BondType.ANY, version=None)
141
134
  atoms.array_length(), atoms.bonds.get_bond_count()
142
135
  ):
143
136
  raise ValueError(
144
- "The given number of atoms or bonds is too large "
145
- "for V2000 format"
137
+ "The given number of atoms or bonds is too large for V2000 format"
146
138
  )
147
139
  return _write_structure_to_ctab_v2000(atoms, default_bond_type)
148
140
  case "V3000":
@@ -174,7 +166,7 @@ def _read_structure_from_ctab_v2000(ctab_lines):
174
166
  charge = CHARGE_MAPPING.get(int(line[36:39]))
175
167
  if charge is None:
176
168
  warnings.warn(
177
- f"Cannot handle MDL charge type {int(line[36 : 39])}, "
169
+ f"Cannot handle MDL charge type {int(line[36:39])}, "
178
170
  f"0 is used instead"
179
171
  )
180
172
  charge = 0
@@ -194,7 +186,7 @@ def _read_structure_from_ctab_v2000(ctab_lines):
194
186
  bond_type = BOND_TYPE_MAPPING.get(int(line[6:9]))
195
187
  if bond_type is None:
196
188
  warnings.warn(
197
- f"Cannot handle MDL bond type {int(line[6 : 9])}, "
189
+ f"Cannot handle MDL bond type {int(line[6:9])}, "
198
190
  f"BondType.ANY is used instead"
199
191
  )
200
192
  bond_type = BondType.ANY
@@ -247,8 +239,7 @@ def _read_structure_from_ctab_v3000(ctab_lines):
247
239
  bond_type = BOND_TYPE_MAPPING.get(v30_type)
248
240
  if bond_type is None:
249
241
  warnings.warn(
250
- f"Cannot handle MDL bond type {v30_type}, "
251
- f"BondType.ANY is used instead"
242
+ f"Cannot handle MDL bond type {v30_type}, BondType.ANY is used instead"
252
243
  )
253
244
  bond_type = BondType.ANY
254
245
  bond_array[i, 0] = v30_atom_indices[v30_atom_index_1]
@@ -307,10 +298,17 @@ def _write_structure_to_ctab_v2000(atoms, default_bond_type):
307
298
  " 0 0 0 0 0 0 0 1 V2000"
308
299
  )
309
300
 
301
+ for i, coord_name in enumerate(["x", "y", "z"]):
302
+ n_coord_digits = number_of_integer_digits(atoms.coord[:, i])
303
+ if n_coord_digits > 5:
304
+ raise BadStructureError(
305
+ f"5 pre-decimal columns for {coord_name}-coordinates are "
306
+ f"available, but array would require {n_coord_digits}"
307
+ )
310
308
  atom_lines = [
311
- f"{atoms.coord[i,0]:>10.4f}"
312
- f"{atoms.coord[i,1]:>10.4f}"
313
- f"{atoms.coord[i,2]:>10.4f}"
309
+ f"{atoms.coord[i, 0]:>10.4f}"
310
+ f"{atoms.coord[i, 1]:>10.4f}"
311
+ f"{atoms.coord[i, 2]:>10.4f}"
314
312
  f" {atoms.element[i].capitalize():3}"
315
313
  f"{0:>2}" # Mass difference -> unused
316
314
  f"{CHARGE_MAPPING_REV.get(charge[i], 0):>3d}"
@@ -321,7 +319,7 @@ def _write_structure_to_ctab_v2000(atoms, default_bond_type):
321
319
 
322
320
  default_bond_value = BOND_TYPE_MAPPING_REV[default_bond_type]
323
321
  bond_lines = [
324
- f"{i+1:>3d}{j+1:>3d}"
322
+ f"{i + 1:>3d}{j + 1:>3d}"
325
323
  f"{BOND_TYPE_MAPPING_REV.get(bond_type, default_bond_value):>3d}"
326
324
  + f"{0:>3d}"
327
325
  * 4
@@ -337,7 +335,7 @@ def _write_structure_to_ctab_v2000(atoms, default_bond_type):
337
335
  ):
338
336
  charge_lines.append(
339
337
  f"M CHG{len(batch):>3d}"
340
- + "".join(f" {atom_i+1:>3d} {c:>3d}" for atom_i, c in batch)
338
+ + "".join(f" {atom_i + 1:>3d} {c:>3d}" for atom_i, c in batch)
341
339
  )
342
340
 
343
341
  return [counts_line] + atom_lines + bond_lines + charge_lines + ["M END"]
@@ -351,12 +349,19 @@ def _write_structure_to_ctab_v3000(atoms, default_bond_type):
351
349
 
352
350
  counts_line = f"COUNTS {atoms.array_length()} {atoms.bonds.get_bond_count()} 0 0 0"
353
351
 
352
+ for i, coord_name in enumerate(["x", "y", "z"]):
353
+ n_coord_digits = number_of_integer_digits(atoms.coord[:, i])
354
+ if n_coord_digits > 5:
355
+ raise BadStructureError(
356
+ f"5 pre-decimal columns for {coord_name}-coordinates are "
357
+ f"available, but array would require {n_coord_digits}"
358
+ )
354
359
  atom_lines = [
355
360
  f"{i + 1}"
356
361
  f" {_quote(atoms.element[i].capitalize())}"
357
- f" {atoms.coord[i,0]:.4f}"
358
- f" {atoms.coord[i,1]:.4f}"
359
- f" {atoms.coord[i,2]:.4f}"
362
+ f" {atoms.coord[i, 0]:.4f}"
363
+ f" {atoms.coord[i, 1]:.4f}"
364
+ f" {atoms.coord[i, 2]:.4f}"
360
365
  # 'aamap' is unused
361
366
  f" 0"
362
367
  f" {_to_property(charges[i])}"
@@ -122,7 +122,7 @@ class MOLFile(TextFile):
122
122
 
123
123
  Parameters
124
124
  ----------
125
- array : AtomArray
125
+ atoms : AtomArray
126
126
  The array to be saved into this file.
127
127
  Must have an associated :class:`BondList`.
128
128
  default_bond_type : BondType, optional
@@ -78,7 +78,6 @@ class Metadata(MutableMapping):
78
78
  >>> print(metadata[Metadata.Key(number=42, name="bar")])
79
79
  dolor sit amet,
80
80
  consectetur
81
-
82
81
  """
83
82
 
84
83
  @dataclass(frozen=True, kw_only=True)
@@ -144,12 +143,18 @@ class Metadata(MutableMapping):
144
143
  @staticmethod
145
144
  def deserialize(text):
146
145
  """
147
- Create an object by deserializing the given text content.
146
+ Create a :class:`Metadata.Key` object by deserializing the given text
147
+ content.
148
148
 
149
149
  Parameters
150
150
  ----------
151
- content : str
151
+ text : str
152
152
  The content to be deserialized.
153
+
154
+ Returns
155
+ -------
156
+ key : Metadata.Key
157
+ The parsed key.
153
158
  """
154
159
  # Omit the leading '>'
155
160
  key_components = text[1:].split()
@@ -207,12 +212,17 @@ class Metadata(MutableMapping):
207
212
  @staticmethod
208
213
  def deserialize(text):
209
214
  """
210
- Create an object by deserializing the given text content.
215
+ Create a :class:`Metadata` objtect by deserializing the given text content.
211
216
 
212
217
  Parameters
213
218
  ----------
214
- content : str
219
+ text : str
215
220
  The content to be deserialized.
221
+
222
+ Returns
223
+ -------
224
+ metadata : Metadata
225
+ The parsed metadata.
216
226
  """
217
227
  metadata = {}
218
228
  current_key = None
@@ -423,19 +433,23 @@ class SDRecord:
423
433
  self._metadata = Metadata(metadata)
424
434
  else:
425
435
  raise TypeError(
426
- "Expected 'Metadata' or Mapping, "
427
- f"but got '{type(metadata).__name__}'"
436
+ f"Expected 'Metadata' or Mapping, but got '{type(metadata).__name__}'"
428
437
  )
429
438
 
430
439
  @staticmethod
431
440
  def deserialize(text):
432
441
  """
433
- Create an object by deserializing the given text content.
442
+ Create an :class:`SDRecord` by deserializing the given text content.
434
443
 
435
444
  Parameters
436
445
  ----------
437
- content : str
446
+ text : str
438
447
  The content to be deserialized.
448
+
449
+ Returns
450
+ -------
451
+ record : SDRecord
452
+ The parsed record.
439
453
  """
440
454
  lines = text.splitlines()
441
455
  ctab_end = _get_ctab_stop(lines)
@@ -494,7 +508,7 @@ class SDRecord:
494
508
 
495
509
  Parameters
496
510
  ----------
497
- array : AtomArray
511
+ atoms : AtomArray
498
512
  The array to be saved into this file.
499
513
  Must have an associated :class:`BondList`.
500
514
  default_bond_type : BondType, optional
@@ -539,6 +553,13 @@ class SDFile(File, MutableMapping):
539
553
  :class:`SDRecord` object via :func:`get_structure()` or
540
554
  :func:`set_structure()`, respectively.
541
555
 
556
+ Parameters
557
+ ----------
558
+ records : dict (str -> SDRecord), optional
559
+ The initial records of the file.
560
+ Maps the record names to the corresponding :class:`SDRecord` objects.
561
+ By default no initial records are added.
562
+
542
563
  Attributes
543
564
  ----------
544
565
  record : CIFBlock
@@ -732,12 +753,17 @@ class SDFile(File, MutableMapping):
732
753
  @staticmethod
733
754
  def deserialize(text):
734
755
  """
735
- Create an object by deserializing the given text content.
756
+ Create an :class:`SDFile` by deserializing the given text content.
736
757
 
737
758
  Parameters
738
759
  ----------
739
- content : str
760
+ text : str
740
761
  The content to be deserialized.
762
+
763
+ Returns
764
+ -------
765
+ file_object : SDFile
766
+ The parsed file.
741
767
  """
742
768
  lines = text.splitlines()
743
769
  record_ends = np.array(
@@ -896,7 +922,7 @@ def _to_metadata_key(key):
896
922
  return Metadata.Key(name=key)
897
923
  else:
898
924
  raise TypeError(
899
- "Expected 'Metadata.Key' or str, " f"but got '{type(key).__name__}'"
925
+ f"Expected 'Metadata.Key' or str, but got '{type(key).__name__}'"
900
926
  )
901
927
 
902
928
 
@@ -15,9 +15,11 @@ __all__ = [
15
15
  "set_structure",
16
16
  "list_assemblies",
17
17
  "get_assembly",
18
- "get_symmetry_mates",
18
+ "get_unit_cell",
19
19
  ]
20
20
 
21
+ import warnings
22
+
21
23
 
22
24
  def get_model_count(pdb_file):
23
25
  """
@@ -89,14 +91,13 @@ def get_structure(
89
91
  -------
90
92
  array : AtomArray or AtomArrayStack
91
93
  The return type depends on the `model` parameter.
92
-
93
94
  """
94
95
  return pdb_file.get_structure(model, altloc, extra_fields, include_bonds)
95
96
 
96
97
 
97
98
  def set_structure(pdb_file, array, hybrid36=False):
98
99
  """
99
- write an :class:`AtomArray` or :class:`AtomArrayStack` into a
100
+ Write an :class:`AtomArray` or :class:`AtomArrayStack` into a
100
101
  :class:`PDBFile`.
101
102
 
102
103
  This function is a thin wrapper around the :class:`PDBFile` method
@@ -114,7 +115,7 @@ def set_structure(pdb_file, array, hybrid36=False):
114
115
  array : AtomArray or AtomArrayStack
115
116
  The structure to be written. If a stack is given, each array in
116
117
  the stack will be in a separate model.
117
- hybrid36: boolean, optional
118
+ hybrid36 : boolean, optional
118
119
  Defines wether the file should be written in hybrid-36 format.
119
120
 
120
121
  Notes
@@ -233,6 +234,80 @@ def get_assembly(
233
234
  )
234
235
 
235
236
 
237
+ def get_unit_cell(
238
+ pdb_file, model=None, altloc="first", extra_fields=[], include_bonds=False
239
+ ):
240
+ """
241
+ Build a structure model containing all symmetric copies
242
+ of the structure within a single unit cell, given by the space
243
+ group.
244
+
245
+ This function receives the data from ``REMARK 290`` records in
246
+ the file.
247
+ Consequently, this remark must be present in the file, which is
248
+ usually only true for crystal structures.
249
+
250
+ Parameters
251
+ ----------
252
+ pdb_file : PDBFile
253
+ The file object.
254
+ model : int, optional
255
+ If this parameter is given, the function will return an
256
+ :class:`AtomArray` from the atoms corresponding to the given
257
+ model number (starting at 1).
258
+ Negative values are used to index models starting from the
259
+ last model instead of the first model.
260
+ If this parameter is omitted, an :class:`AtomArrayStack`
261
+ containing all models will be returned, even if the
262
+ structure contains only one model.
263
+ altloc : {'first', 'occupancy', 'all'}
264
+ This parameter defines how *altloc* IDs are handled:
265
+ - ``'first'`` - Use atoms that have the first
266
+ *altloc* ID appearing in a residue.
267
+ - ``'occupancy'`` - Use atoms that have the *altloc* ID
268
+ with the highest occupancy for a residue.
269
+ - ``'all'`` - Use all atoms.
270
+ Note that this leads to duplicate atoms.
271
+ When this option is chosen, the ``altloc_id``
272
+ annotation array is added to the returned structure.
273
+ extra_fields : list of str, optional
274
+ The strings in the list are optional annotation categories
275
+ that should be stored in the output array or stack.
276
+ These are valid values:
277
+ ``'atom_id'``, ``'b_factor'``, ``'occupancy'`` and
278
+ ``'charge'``.
279
+ include_bonds : bool, optional
280
+ If set to true, a :class:`BondList` will be created for the
281
+ resulting :class:`AtomArray` containing the bond information
282
+ from the file.
283
+ Bonds, whose order could not be determined from the
284
+ *Chemical Component Dictionary*
285
+ (e.g. especially inter-residue bonds),
286
+ have :attr:`BondType.ANY`, since the PDB format itself does
287
+ not support bond orders.
288
+
289
+ Returns
290
+ -------
291
+ symmetry_mates : AtomArray or AtomArrayStack
292
+ All atoms within a single unit cell.
293
+ The return type depends on the `model` parameter.
294
+
295
+ Notes
296
+ -----
297
+ To expand the structure beyond a single unit cell, use
298
+ :func:`repeat_box()` with the return value as its
299
+ input.
300
+
301
+ Examples
302
+ --------
303
+
304
+ >>> import os.path
305
+ >>> file = PDBFile.read(os.path.join(path_to_structures, "1aki.pdb"))
306
+ >>> atoms_in_unit_cell = get_unit_cell(file, model=1)
307
+ """
308
+ return pdb_file.get_unit_cell(model, altloc, extra_fields, include_bonds)
309
+
310
+
236
311
  def get_symmetry_mates(
237
312
  pdb_file, model=None, altloc="first", extra_fields=[], include_bonds=False
238
313
  ):
@@ -246,6 +321,8 @@ def get_symmetry_mates(
246
321
  Consequently, this remark must be present in the file, which is
247
322
  usually only true for crystal structures.
248
323
 
324
+ DEPRECATED: Use :func:`get_unit_cell()` instead.
325
+
249
326
  Parameters
250
327
  ----------
251
328
  pdb_file : PDBFile
@@ -304,4 +381,8 @@ def get_symmetry_mates(
304
381
  >>> file = PDBFile.read(os.path.join(path_to_structures, "1aki.pdb"))
305
382
  >>> atoms_in_unit_cell = get_symmetry_mates(file, model=1)
306
383
  """
307
- return pdb_file.get_symmetry_mates(model, altloc, extra_fields, include_bonds)
384
+ warnings.warn(
385
+ "'get_symmetry_mates()' is deprecated, use 'get_unit_cell()' instead",
386
+ DeprecationWarning,
387
+ )
388
+ return pdb_file.get_unit_cell(model, altloc, extra_fields, include_bonds)