RNApolis 0.3.17__py3-none-any.whl → 0.4.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RNApolis
3
- Version: 0.3.17
3
+ Version: 0.4.0
4
4
  Summary: A Python library containing RNA-related bioinformatics functions and classes
5
5
  Home-page: https://github.com/tzok/rnapolis-py
6
6
  Author: Tomasz Zok
@@ -21,6 +21,7 @@ Requires-Dist: mmcif
21
21
  Requires-Dist: numpy
22
22
  Requires-Dist: ordered-set
23
23
  Requires-Dist: orjson
24
+ Requires-Dist: pandas
24
25
  Requires-Dist: pulp
25
26
  Requires-Dist: requests
26
27
  Requires-Dist: scipy
@@ -0,0 +1,17 @@
1
+ rnapolis/annotator.py,sha256=7U3f0gchKdIGc6FwJx0UAc_95HJI5SgECj-b7-1yBhc,22086
2
+ rnapolis/clashfinder.py,sha256=i95kp0o6OWNqmJDBr-PbsZd7RY2iJtBDr7QqolJSuAQ,8513
3
+ rnapolis/common.py,sha256=PUYF01P2vevhyImhZjGYE0jJlsxWHX6GQmsxI4W7S-E,30255
4
+ rnapolis/metareader.py,sha256=I1-cXc2YNBPwa3zihAnMTjEsAo79tEKzSmWu5yvN1Pk,2071
5
+ rnapolis/molecule_filter.py,sha256=hB6-nXgjmw7FAsQ3bj0cZ2FvuW2I1PXunEfcdwEUB1o,7389
6
+ rnapolis/motif_extractor.py,sha256=duHvpi9Ulcny9K60E6VBpz5RpJZw-KdTB4_Ph0iP478,774
7
+ rnapolis/parser.py,sha256=wCA9rXqt51iLECgeBqOShFpuT8JwanNkHYD5uXYvLzU,13988
8
+ rnapolis/rfam_folder.py,sha256=SjiiyML_T1__saruFwSMJEoQ7Y55GIU8ktS8ZUn5-fw,11111
9
+ rnapolis/tertiary.py,sha256=iA5_ut1_nhwlbYpu2898h5li4pTEOc-iA_uK7vIvQ2o,20269
10
+ rnapolis/transformer.py,sha256=V9nOQvdq4-p7yUWo0vQg0CDQMpmyxz9t4TMSRVEKHnw,1817
11
+ rnapolis/util.py,sha256=IdquFO3PV1_KDqodjupzm0Rqvgy0CeSzxGHaGEHYXVU,543
12
+ RNApolis-0.4.0.dist-info/LICENSE,sha256=ZGRu12MzCgbYA-Lt8MyBlmjvPZh7xfiD5u5wBx0enq4,1066
13
+ RNApolis-0.4.0.dist-info/METADATA,sha256=kz7fPjyFm8j6HMwnDvtwlLkZGPpzw2Ce29XI1pVyIyU,54322
14
+ RNApolis-0.4.0.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
15
+ RNApolis-0.4.0.dist-info/entry_points.txt,sha256=foN2Pn5e-OzEz0fFmNoX6PnFSZFQntOlY8LbognP5F0,308
16
+ RNApolis-0.4.0.dist-info/top_level.txt,sha256=LcO18koxZcWoJ21KDRRRo_tyIbmXL5z61dPitZpy8yc,9
17
+ RNApolis-0.4.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.1.1)
2
+ Generator: setuptools (72.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
rnapolis/annotator.py CHANGED
@@ -10,8 +10,6 @@ from typing import Dict, List, Optional, Set, Tuple
10
10
  import numpy
11
11
  import numpy.typing
12
12
  from ordered_set import OrderedSet
13
- from scipy.spatial import KDTree
14
-
15
13
  from rnapolis.common import (
16
14
  BR,
17
15
  BaseInteractions,
@@ -43,6 +41,7 @@ from rnapolis.tertiary import (
43
41
  torsion_angle,
44
42
  )
45
43
  from rnapolis.util import handle_input_file
44
+ from scipy.spatial import KDTree
46
45
 
47
46
  HYDROGEN_BOND_MAX_DISTANCE = 4.0
48
47
  HYDROGEN_BOND_ANGLE_RANGE = (50.0, 130.0) # 90 degrees is ideal, so allow +- 40 degrees
@@ -149,7 +148,7 @@ def detect_bph_br_classification(
149
148
 
150
149
 
151
150
  def merge_and_clean_bph_br(
152
- pairs: List[Tuple[Residue3D, Residue3D, int]]
151
+ pairs: List[Tuple[Residue3D, Residue3D, int]],
153
152
  ) -> Dict[Tuple[Residue3D, Residue3D], OrderedSet[int]]:
154
153
  bph_br_map: Dict[Tuple[Residue3D, Residue3D], OrderedSet[int]] = defaultdict(
155
154
  OrderedSet
@@ -588,7 +587,7 @@ def main():
588
587
  "-a",
589
588
  "--all-dot-brackets",
590
589
  action="store_true",
591
- help=")optional) print all dot-brackets, not only optimal one (exclusive with -e/--extended)",
590
+ help="(optional) print all dot-brackets, not only optimal one (exclusive with -e/--extended)",
592
591
  )
593
592
  parser.add_argument("-b", "--bpseq", help="(optional) path to output BPSEQ file")
594
593
  parser.add_argument("-c", "--csv", help="(optional) path to output CSV file")
rnapolis/clashfinder.py CHANGED
@@ -8,11 +8,10 @@ from functools import cached_property
8
8
  from typing import List, Optional
9
9
 
10
10
  import numpy as np
11
- from scipy.spatial import KDTree
12
-
13
11
  from rnapolis.metareader import read_metadata
14
12
  from rnapolis.parser import read_3d_structure
15
13
  from rnapolis.tertiary import Atom, Residue3D
14
+ from scipy.spatial import KDTree
16
15
 
17
16
  CARBON_RADIUS = 0.6
18
17
  NITROGEN_RADIUS = 0.54
rnapolis/common.py CHANGED
@@ -8,7 +8,6 @@ from collections.abc import Sequence
8
8
  from dataclasses import dataclass
9
9
  from enum import Enum
10
10
  from functools import cache, cached_property, total_ordering
11
- from itertools import permutations
12
11
  from typing import Dict, List, Optional, Tuple
13
12
 
14
13
  import graphviz
rnapolis/metareader.py CHANGED
@@ -6,7 +6,6 @@ import orjson
6
6
  import pandas as pd
7
7
  from mmcif.io.IoAdapterPy import IoAdapterPy
8
8
  from mmcif.io.PdbxReader import DataContainer
9
-
10
9
  from rnapolis.util import handle_input_file
11
10
 
12
11
 
@@ -5,7 +5,6 @@ from typing import List, Set, Tuple
5
5
 
6
6
  from mmcif.io.IoAdapterPy import IoAdapterPy
7
7
  from mmcif.io.PdbxReader import DataCategory, DataContainer
8
-
9
8
  from rnapolis.util import handle_input_file
10
9
 
11
10
  # Source: https://mmcif.wwpdb.org/dictionaries/mmcif_pdbx_v50.dic/Items/_entity_poly.type.html
@@ -158,11 +157,17 @@ def main():
158
157
  parser = argparse.ArgumentParser()
159
158
  parser.add_argument(
160
159
  "--type",
161
- help="a type of molecule to select (default: polyribonucleotide)",
160
+ help="a type of molecule to select, you can provide this argument multiple times (default: polyribonucleotide)",
162
161
  action="append",
163
162
  default=["polyribonucleotide"],
164
163
  choices=ENTITY_POLY_TYPES,
165
164
  )
165
+ parser.add_argument(
166
+ "--chain",
167
+ help="a chain ID (label_asym_id) to select, you can provide this argument multiple times (if provided, it overrides the --type argument)",
168
+ action="append",
169
+ default=[],
170
+ )
166
171
  parser.add_argument("path", help="path to a PDBx/mmCIF file")
167
172
  args = parser.parse_args()
168
173
 
@@ -171,8 +176,15 @@ def main():
171
176
  data = adapter.readFile(file.name)
172
177
  output = DataContainer("rnapolis")
173
178
 
174
- entity_ids = select_ids(data, "entity_poly", "type", "entity_id", set(args.type))
175
- asym_ids = select_ids(data, "struct_asym", "entity_id", "id", entity_ids)
179
+ if args.chain:
180
+ entity_ids = select_ids(data, "struct_asym", "id", "entity_id", set(args.chain))
181
+ asym_ids = set(args.chain)
182
+ else:
183
+ entity_ids = select_ids(
184
+ data, "entity_poly", "type", "entity_id", set(args.type)
185
+ )
186
+ asym_ids = select_ids(data, "struct_asym", "entity_id", "id", entity_ids)
187
+
176
188
  auth_asym_ids = select_ids(
177
189
  data, "atom_site", "label_asym_id", "auth_asym_id", asym_ids
178
190
  )
rnapolis/parser.py CHANGED
@@ -2,7 +2,6 @@ import logging
2
2
  from typing import IO, Dict, List, Optional, Tuple, Union
3
3
 
4
4
  from mmcif.io.IoAdapterPy import IoAdapterPy
5
-
6
5
  from rnapolis.common import ResidueAuth, ResidueLabel
7
6
  from rnapolis.tertiary import BASE_ATOMS, Atom, Residue3D, Structure3D
8
7
 
@@ -13,7 +12,7 @@ logger = logging.getLogger(__name__)
13
12
  def read_3d_structure(
14
13
  cif_or_pdb: IO[str], model: Optional[int] = None, nucleic_acid_only: bool = False
15
14
  ) -> Structure3D:
16
- atoms, modified, sequence = (
15
+ atoms, modified, sequence_by_entity, is_nucleic_acid_by_entity = (
17
16
  parse_cif(cif_or_pdb) if is_cif(cif_or_pdb) else parse_pdb(cif_or_pdb)
18
17
  )
19
18
  available_models = {atom.model: None for atom in atoms}
@@ -25,7 +24,13 @@ def read_3d_structure(
25
24
  atoms = atoms_by_model[model]
26
25
  else:
27
26
  atoms = atoms_by_model[list(available_models.keys())[0]]
28
- return group_atoms(atoms, modified, sequence, nucleic_acid_only)
27
+ return group_atoms(
28
+ atoms,
29
+ modified,
30
+ sequence_by_entity,
31
+ is_nucleic_acid_by_entity,
32
+ nucleic_acid_only,
33
+ )
29
34
 
30
35
 
31
36
  def is_cif(cif_or_pdb: IO[str]) -> bool:
@@ -41,7 +46,8 @@ def parse_cif(
41
46
  ) -> Tuple[
42
47
  List[Atom],
43
48
  Dict[Union[ResidueLabel, ResidueAuth], str],
44
- Dict[Tuple[str, int], str],
49
+ Dict[str, str],
50
+ Dict[str, bool],
45
51
  ]:
46
52
  cif.seek(0)
47
53
 
@@ -49,7 +55,8 @@ def parse_cif(
49
55
  data = io_adapter.readFile(cif.name)
50
56
  atoms: List[Atom] = []
51
57
  modified: Dict[Union[ResidueLabel, ResidueAuth], str] = {}
52
- sequence = {}
58
+ sequence_by_entity = {}
59
+ is_nucleic_acid_by_entity = {}
53
60
 
54
61
  if data:
55
62
  atom_site = data[0].getObj("atom_site")
@@ -60,6 +67,7 @@ def parse_cif(
60
67
  for row in atom_site.getRowList():
61
68
  row_dict = dict(zip(atom_site.getAttributeList(), row))
62
69
 
70
+ label_entity_id = row_dict.get("label_entity_id", None)
63
71
  label_chain_name = row_dict.get("label_asym_id", None)
64
72
  label_residue_number = try_parse_int(row_dict.get("label_seq_id", None))
65
73
  label_residue_name = row_dict.get("label_comp_id", None)
@@ -128,7 +136,19 @@ def parse_cif(
128
136
  else None
129
137
  )
130
138
 
131
- atoms.append(Atom(label, auth, model, atom_name, x, y, z, occupancy))
139
+ atoms.append(
140
+ Atom(
141
+ label_entity_id,
142
+ label,
143
+ auth,
144
+ model,
145
+ atom_name,
146
+ x,
147
+ y,
148
+ z,
149
+ occupancy,
150
+ )
151
+ )
132
152
 
133
153
  if mod_residue:
134
154
  for row in mod_residue.getRowList():
@@ -179,17 +199,24 @@ def parse_cif(
179
199
  for row in entity_poly.getRowList():
180
200
  row_dict = dict(zip(entity_poly.getAttributeList(), row))
181
201
 
182
- pdbx_strand_id = row_dict.get("pdbx_strand_id", None)
202
+ entity_id = row_dict.get("entity_id", None)
203
+ type_ = row_dict.get("type", None)
183
204
  pdbx_seq_one_letter_code_can = row_dict.get(
184
205
  "pdbx_seq_one_letter_code_can", None
185
206
  )
186
207
 
187
- if pdbx_strand_id and pdbx_seq_one_letter_code_can:
188
- for strand in pdbx_strand_id.split(","):
189
- for i, letter in enumerate(pdbx_seq_one_letter_code_can):
190
- sequence[(strand, i + 1)] = letter
208
+ if entity_id and type_:
209
+ is_nucleic_acid_by_entity[entity_id] = type_ in (
210
+ "peptide nucleic acid",
211
+ "polydeoxyribonucleotide",
212
+ "polydeoxyribonucleotide/polyribonucleotide hybrid",
213
+ "polyribonucleotide",
214
+ )
215
+
216
+ if entity_id and pdbx_seq_one_letter_code_can:
217
+ sequence_by_entity[entity_id] = pdbx_seq_one_letter_code_can
191
218
 
192
- return atoms, modified, sequence
219
+ return atoms, modified, sequence_by_entity, is_nucleic_acid_by_entity
193
220
 
194
221
 
195
222
  def parse_pdb(
@@ -197,7 +224,8 @@ def parse_pdb(
197
224
  ) -> Tuple[
198
225
  List[Atom],
199
226
  Dict[Union[ResidueLabel, ResidueAuth], str],
200
- Dict[Tuple[str, int], str],
227
+ Dict[str, str],
228
+ Dict[str, bool],
201
229
  ]:
202
230
  pdb.seek(0)
203
231
  atoms: List[Atom] = []
@@ -223,7 +251,7 @@ def parse_pdb(
223
251
  auth = ResidueAuth(
224
252
  chain_identifier, residue_number, insertion_code, residue_name
225
253
  )
226
- atoms.append(Atom(None, auth, model, atom_name, x, y, z, occupancy))
254
+ atoms.append(Atom(None, None, auth, model, atom_name, x, y, z, occupancy))
227
255
  elif line.startswith("MODRES"):
228
256
  original_name = line[12:15]
229
257
  chain_identifier = line[16]
@@ -235,13 +263,14 @@ def parse_pdb(
235
263
  )
236
264
  modified[auth] = standard_residue_name
237
265
 
238
- return atoms, modified, {}
266
+ return atoms, modified, {}, {}
239
267
 
240
268
 
241
269
  def group_atoms(
242
270
  atoms: List[Atom],
243
271
  modified: Dict[Union[ResidueLabel, ResidueAuth], str],
244
- sequence: Dict[Tuple[str, int], str],
272
+ sequence_by_entity: Dict[str, str],
273
+ is_nucleic_acid_by_entity: Dict[str, bool],
245
274
  nucleic_acid_only: bool,
246
275
  ) -> Structure3D:
247
276
  if not atoms:
@@ -259,28 +288,45 @@ def group_atoms(
259
288
  label = key_previous[0]
260
289
  auth = key_previous[1]
261
290
  model = key_previous[2]
291
+ entity_id = residue_atoms[-1].entity_id
262
292
  name = get_residue_name(auth, label, modified)
263
- one_letter_name = get_one_letter_name(label, sequence, name)
264
- if one_letter_name not in "ACGUT":
293
+ one_letter_name = get_one_letter_name(
294
+ entity_id, label, sequence_by_entity, name
295
+ )
296
+
297
+ if one_letter_name not in "ACGUTN":
265
298
  one_letter_name = detect_one_letter_name(residue_atoms)
266
- residue = Residue3D(
267
- label, auth, model, one_letter_name, tuple(residue_atoms)
299
+
300
+ residues.append(
301
+ Residue3D(label, auth, model, one_letter_name, tuple(residue_atoms))
268
302
  )
269
- if not nucleic_acid_only or (nucleic_acid_only and residue.is_nucleotide):
270
- residues.append(residue)
303
+
271
304
  key_previous = key
272
305
  residue_atoms = [atom]
273
306
 
274
307
  label = key_previous[0]
275
308
  auth = key_previous[1]
276
309
  model = key_previous[2]
310
+ entity_id = residue_atoms[-1].entity_id
277
311
  name = get_residue_name(auth, label, modified)
278
- one_letter_name = get_one_letter_name(label, sequence, name)
279
- if one_letter_name not in "ACGUT":
312
+ one_letter_name = get_one_letter_name(entity_id, label, sequence_by_entity, name)
313
+
314
+ if one_letter_name not in "ACGUTN":
280
315
  one_letter_name = detect_one_letter_name(residue_atoms)
281
- residue = Residue3D(label, auth, model, one_letter_name, tuple(residue_atoms))
282
- if not nucleic_acid_only or (nucleic_acid_only and residue.is_nucleotide):
283
- residues.append(residue)
316
+
317
+ residues.append(
318
+ Residue3D(label, auth, model, one_letter_name, tuple(residue_atoms))
319
+ )
320
+
321
+ if nucleic_acid_only:
322
+ if is_nucleic_acid_by_entity:
323
+ residues = [
324
+ residue
325
+ for residue in residues
326
+ if is_nucleic_acid_by_entity[residue.atoms[0].entity_id]
327
+ ]
328
+ else:
329
+ residues = [residue for residue in residues if residue.is_nucleotide]
284
330
 
285
331
  return Structure3D(residues)
286
332
 
@@ -305,13 +351,14 @@ def get_residue_name(
305
351
 
306
352
 
307
353
  def get_one_letter_name(
308
- label: Optional[ResidueLabel], sequence: Dict[Tuple[str, int], str], name: str
354
+ entity_id: Optional[str],
355
+ label: Optional[ResidueLabel],
356
+ sequence_by_entity: Dict[str, str],
357
+ name: str,
309
358
  ) -> str:
310
359
  # try getting the value from _entity_poly first
311
- if label is not None:
312
- key = (label.chain, label.number)
313
- if key in sequence:
314
- return sequence[key]
360
+ if entity_id is not None and label is not None and entity_id in sequence_by_entity:
361
+ return sequence_by_entity[entity_id][label.number - 1]
315
362
  # RNA
316
363
  if len(name) == 1:
317
364
  return name
@@ -335,11 +382,13 @@ def detect_one_letter_name(atoms: List[Atom]) -> str:
335
382
  ) / len(atom_names_expected)
336
383
  score[candidate] = count
337
384
  items = sorted(score.items(), key=lambda kv: kv[1], reverse=True)
385
+ if items[0][1] == 0:
386
+ return "?"
338
387
  return items[0][0]
339
388
 
340
389
 
341
390
  def try_parse_int(s: str) -> Optional[int]:
342
391
  try:
343
392
  return int(s)
344
- except:
393
+ except ValueError:
345
394
  return None
rnapolis/rfam_folder.py CHANGED
@@ -14,7 +14,6 @@ from typing import List
14
14
  import appdirs
15
15
  import requests
16
16
  import RNA
17
-
18
17
  from rnapolis.common import BpSeq, DotBracket
19
18
 
20
19
  COMBINED_CM = "https://ftp.ebi.ac.uk/pub/databases/Rfam/CURRENT/Rfam.cm.gz"
rnapolis/tertiary.py CHANGED
@@ -7,7 +7,6 @@ from typing import Dict, List, Optional, Set, Tuple, Union
7
7
 
8
8
  import numpy
9
9
  import numpy.typing
10
-
11
10
  from rnapolis.common import (
12
11
  BasePair,
13
12
  BpSeq,
@@ -97,6 +96,7 @@ AVERAGE_OXYGEN_PHOSPHORUS_DISTANCE_COVALENT = 1.6
97
96
 
98
97
  @dataclass(frozen=True, order=True)
99
98
  class Atom:
99
+ entity_id: Optional[str]
100
100
  label: Optional[ResidueLabel]
101
101
  auth: Optional[ResidueAuth]
102
102
  model: int
@@ -129,6 +129,29 @@ class Residue3D(Residue):
129
129
  "C": set(["N1", "C2", "O2", "N3", "C4", "N4", "C5", "C6"]),
130
130
  "U": set(["N1", "C2", "O2", "N3", "C4", "O4", "C5", "C6"]),
131
131
  }
132
+ # Heavy atoms in nucleotide
133
+ nucleotide_heavy_atoms = (
134
+ set(
135
+ [
136
+ "P",
137
+ "OP1",
138
+ "OP2",
139
+ "O5'",
140
+ "C5'",
141
+ "C4'",
142
+ "O4'",
143
+ "C3'",
144
+ "O3'",
145
+ "C2'",
146
+ "O2'",
147
+ "C1'",
148
+ ]
149
+ )
150
+ .union(nucleobase_heavy_atoms["A"])
151
+ .union(nucleobase_heavy_atoms["G"])
152
+ .union(nucleobase_heavy_atoms["C"])
153
+ .union(nucleobase_heavy_atoms["U"])
154
+ )
132
155
 
133
156
  def __lt__(self, other):
134
157
  return (self.model, self.chain, self.number, self.icode or " ") < (
@@ -177,8 +200,8 @@ class Residue3D(Residue):
177
200
 
178
201
  @cached_property
179
202
  def is_nucleotide(self) -> bool:
180
- return len(self.atoms) > 1 and any(
181
- [atom for atom in self.atoms if atom.name == "C1'"]
203
+ return self.nucleotide_heavy_atoms.intersection(
204
+ set([atom.name for atom in self.atoms])
182
205
  )
183
206
 
184
207
  @cached_property
@@ -269,7 +292,7 @@ class Residue3D(Residue):
269
292
  logging.error(
270
293
  f"Failed to determine the outermost atom for nucleotide {self}, so an arbitrary atom will be used"
271
294
  )
272
- yield Atom(self.label, self.auth, self.model, "UNK", 0.0, 0.0, 0.0, None)
295
+ yield Atom(None, self.label, self.auth, self.model, "UNK", 0.0, 0.0, 0.0, None)
273
296
 
274
297
  def __inner_generator(self):
275
298
  # try to find expected atom name
@@ -297,7 +320,7 @@ class Residue3D(Residue):
297
320
  logging.error(
298
321
  f"Failed to determine the innermost atom for nucleotide {self}, so an arbitrary atom will be used"
299
322
  )
300
- yield Atom(self.label, self.auth, self.model, "UNK", 0.0, 0.0, 0.0, None)
323
+ yield Atom(None, self.label, self.auth, self.model, "UNK", 0.0, 0.0, 0.0, None)
301
324
 
302
325
 
303
326
  @dataclass(frozen=True, order=True)
@@ -1,17 +0,0 @@
1
- rnapolis/annotator.py,sha256=XnjFBeu3P_2UMdkD4Ao7m7K6JfeqYa-13xRzghrLvt8,22086
2
- rnapolis/clashfinder.py,sha256=jD3s_UovygWi01NUbQNeAeRRFkARTSRraLXUV43UbAA,8514
3
- rnapolis/common.py,sha256=tbmKV64nLClmzNN0HyKnvWA0-5aSyf4x8CGpBjpIJ4M,30290
4
- rnapolis/metareader.py,sha256=9HZIrpPsmmWkEUeSeKAeG1sstfqbBDKUw5QPsn5cshw,2072
5
- rnapolis/molecule_filter.py,sha256=NhjuqdCRnXgPefWZPeTq77tifmnAzamQtA0ODqPPG9k,6918
6
- rnapolis/motif_extractor.py,sha256=duHvpi9Ulcny9K60E6VBpz5RpJZw-KdTB4_Ph0iP478,774
7
- rnapolis/parser.py,sha256=nHRXcoKbzfMJuDMJO-8MSPkzfmD-788ZzgcfjLQpgFs,12666
8
- rnapolis/rfam_folder.py,sha256=3rgXEJR16uPFy_BOo8qkdClOAOQDVOkidnLE-yoRbeI,11112
9
- rnapolis/tertiary.py,sha256=VuATTN2SD7lBL9iUgT-doDwuEYsLodgV2u-SwQsyQcU,19658
10
- rnapolis/transformer.py,sha256=V9nOQvdq4-p7yUWo0vQg0CDQMpmyxz9t4TMSRVEKHnw,1817
11
- rnapolis/util.py,sha256=IdquFO3PV1_KDqodjupzm0Rqvgy0CeSzxGHaGEHYXVU,543
12
- RNApolis-0.3.17.dist-info/LICENSE,sha256=ZGRu12MzCgbYA-Lt8MyBlmjvPZh7xfiD5u5wBx0enq4,1066
13
- RNApolis-0.3.17.dist-info/METADATA,sha256=2h_8NfBq0uKpgXC-CYsvB1O1hglxTGyZHfGfJmsKrmI,54301
14
- RNApolis-0.3.17.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
15
- RNApolis-0.3.17.dist-info/entry_points.txt,sha256=foN2Pn5e-OzEz0fFmNoX6PnFSZFQntOlY8LbognP5F0,308
16
- RNApolis-0.3.17.dist-info/top_level.txt,sha256=LcO18koxZcWoJ21KDRRRo_tyIbmXL5z61dPitZpy8yc,9
17
- RNApolis-0.3.17.dist-info/RECORD,,