RNApolis 0.4.2__tar.gz → 0.4.4__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. {rnapolis-0.4.2/src/RNApolis.egg-info → rnapolis-0.4.4}/PKG-INFO +1 -1
  2. {rnapolis-0.4.2 → rnapolis-0.4.4}/setup.py +1 -1
  3. {rnapolis-0.4.2 → rnapolis-0.4.4/src/RNApolis.egg-info}/PKG-INFO +1 -1
  4. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/rnapolis/tertiary.py +60 -21
  5. {rnapolis-0.4.2 → rnapolis-0.4.4}/tests/test_common.py +44 -0
  6. {rnapolis-0.4.2 → rnapolis-0.4.4}/LICENSE +0 -0
  7. {rnapolis-0.4.2 → rnapolis-0.4.4}/README.md +0 -0
  8. {rnapolis-0.4.2 → rnapolis-0.4.4}/pyproject.toml +0 -0
  9. {rnapolis-0.4.2 → rnapolis-0.4.4}/setup.cfg +0 -0
  10. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/RNApolis.egg-info/SOURCES.txt +0 -0
  11. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/RNApolis.egg-info/dependency_links.txt +0 -0
  12. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/RNApolis.egg-info/entry_points.txt +0 -0
  13. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/RNApolis.egg-info/requires.txt +0 -0
  14. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/RNApolis.egg-info/top_level.txt +0 -0
  15. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/rnapolis/annotator.py +0 -0
  16. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/rnapolis/clashfinder.py +0 -0
  17. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/rnapolis/common.py +0 -0
  18. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/rnapolis/metareader.py +0 -0
  19. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/rnapolis/molecule_filter.py +0 -0
  20. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/rnapolis/motif_extractor.py +0 -0
  21. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/rnapolis/parser.py +0 -0
  22. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/rnapolis/rfam_folder.py +0 -0
  23. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/rnapolis/transformer.py +0 -0
  24. {rnapolis-0.4.2 → rnapolis-0.4.4}/src/rnapolis/util.py +0 -0
  25. {rnapolis-0.4.2 → rnapolis-0.4.4}/tests/test_annotator.py +0 -0
  26. {rnapolis-0.4.2 → rnapolis-0.4.4}/tests/test_bugfixes.py +0 -0
  27. {rnapolis-0.4.2 → rnapolis-0.4.4}/tests/test_metareader.py +0 -0
  28. {rnapolis-0.4.2 → rnapolis-0.4.4}/tests/test_parser.py +0 -0
  29. {rnapolis-0.4.2 → rnapolis-0.4.4}/tests/test_quadruplexes.py +0 -0
  30. {rnapolis-0.4.2 → rnapolis-0.4.4}/tests/test_rfam_folder.py +0 -0
  31. {rnapolis-0.4.2 → rnapolis-0.4.4}/tests/test_tertiary.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RNApolis
3
- Version: 0.4.2
3
+ Version: 0.4.4
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
@@ -5,7 +5,7 @@ with open("README.md") as f:
5
5
 
6
6
  setup(
7
7
  name="RNApolis",
8
- version="0.4.2",
8
+ version="0.4.4",
9
9
  packages=["rnapolis"],
10
10
  package_dir={"": "src"},
11
11
  author="Tomasz Zok",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RNApolis
3
- Version: 0.4.2
3
+ Version: 0.4.4
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
@@ -7,6 +7,7 @@ from typing import Dict, List, Optional, Set, Tuple, Union
7
7
 
8
8
  import numpy
9
9
  import numpy.typing
10
+
10
11
  from rnapolis.common import (
11
12
  BasePair,
12
13
  BpSeq,
@@ -16,6 +17,7 @@ from rnapolis.common import (
16
17
  Residue,
17
18
  ResidueAuth,
18
19
  ResidueLabel,
20
+ Saenger,
19
21
  Stacking,
20
22
  )
21
23
 
@@ -497,34 +499,71 @@ class Mapping2D3D:
497
499
 
498
500
  @cached_property
499
501
  def strands_sequences(self) -> List[Tuple[str, str]]:
500
- result = defaultdict(list)
502
+ nucleotides = list(filter(lambda r: r.is_nucleotide, self.structure3d.residues))
501
503
 
502
- for i, residue in enumerate(
503
- filter(lambda r: r.is_nucleotide, self.structure3d.residues)
504
- ):
505
- if i > 0 and self.find_gaps:
506
- previous = self.structure3d.residues[i - 1]
504
+ if not nucleotides:
505
+ return []
507
506
 
508
- if (
509
- not previous.is_connected(residue)
510
- and previous.chain == residue.chain
511
- ):
512
- for k in range(residue.number - previous.number - 1):
513
- result[residue.chain].append("?")
507
+ result = [(nucleotides[0].chain, [nucleotides[0].one_letter_name])]
514
508
 
515
- result[residue.chain].append(residue.one_letter_name)
509
+ for i in range(1, len(nucleotides)):
510
+ previous = nucleotides[i - 1]
511
+ residue = nucleotides[i]
516
512
 
517
- return [(chain, "".join(sequence)) for chain, sequence in result.items()]
513
+ if residue.chain != previous.chain:
514
+ result.append((residue.chain, [residue.one_letter_name]))
515
+ else:
516
+ if self.find_gaps:
517
+ if not previous.is_connected(residue):
518
+ for k in range(residue.number - previous.number - 1):
519
+ result[-1][1].append("?")
520
+ result[-1][1].append(residue.one_letter_name)
521
+
522
+ return [(chain, "".join(sequence)) for chain, sequence in result]
518
523
 
519
524
  @cached_property
520
525
  def bpseq(self) -> BpSeq:
521
- return self.__generate_bpseq(
522
- [
523
- base_pair
524
- for base_pair in self.base_pairs
525
- if base_pair.is_canonical and base_pair.nt1 < base_pair.nt2
526
- ]
527
- )
526
+ def pair_scoring_function(pair: BasePair3D) -> int:
527
+ if pair.saenger is not None:
528
+ if pair.saenger in (Saenger.XIX, Saenger.XX):
529
+ return 0, pair.nt1, pair.nt2
530
+ else:
531
+ return 1, pair.nt1, pair.nt2
532
+
533
+ sequence = "".join(
534
+ sorted(
535
+ [
536
+ pair.nt1_3d.one_letter_name.upper(),
537
+ pair.nt2_3d.one_letter_name.upper(),
538
+ ]
539
+ )
540
+ )
541
+ if sequence in ("AU", "AT", "CG"):
542
+ return 0, pair.nt1, pair.nt2
543
+ return 1, pair.nt1, pair.nt2
544
+
545
+ canonical = [
546
+ base_pair
547
+ for base_pair in self.base_pairs
548
+ if base_pair.is_canonical and base_pair.nt1 < base_pair.nt2
549
+ ]
550
+
551
+ while True:
552
+ matches = defaultdict(set)
553
+
554
+ for base_pair in canonical:
555
+ matches[base_pair.nt1_3d].add(base_pair)
556
+ matches[base_pair.nt2_3d].add(base_pair)
557
+
558
+ for pairs in matches.values():
559
+ if len(pairs) > 1:
560
+ pairs = sorted(pairs, key=pair_scoring_function)
561
+ canonical.remove(pairs[-1])
562
+ break
563
+ else:
564
+ break
565
+
566
+ return self.__generate_bpseq(canonical)
528
567
 
529
568
  def __generate_bpseq(self, base_pairs):
530
569
  result: Dict[int, List] = {}
@@ -1,7 +1,9 @@
1
1
  from collections import Counter
2
2
 
3
+ import orjson
3
4
  from hypothesis import given, settings
4
5
  from hypothesis import strategies as st
6
+
5
7
  from rnapolis.common import (
6
8
  BaseInteractions,
7
9
  BasePair,
@@ -10,13 +12,17 @@ from rnapolis.common import (
10
12
  BpSeq,
11
13
  DotBracket,
12
14
  Interaction,
15
+ LeontisWesthof,
13
16
  MultiStrandDotBracket,
14
17
  OtherInteraction,
15
18
  Residue,
16
19
  ResidueAuth,
17
20
  ResidueLabel,
21
+ Saenger,
18
22
  Stacking,
19
23
  )
24
+ from rnapolis.parser import read_3d_structure
25
+ from rnapolis.tertiary import Mapping2D3D
20
26
 
21
27
 
22
28
  @given(st.from_type(ResidueLabel))
@@ -136,3 +142,41 @@ def test_multi_strand_dot_bracket():
136
142
  assert dot_bracket.strands[1].structure == (
137
143
  ")))))))))))..(((...[[[[[[...)))......)))))...]]]]]][[[[[.((((((]]]]].....((((((......((((((....)))))).......))))))..))))))."
138
144
  )
145
+
146
+
147
+ def test_conflicted_base_pairs():
148
+ with open("tests/1A1T_1_B-rnaview.json", "rb") as f:
149
+ data = orjson.loads(f.read())
150
+
151
+ base_pairs = []
152
+
153
+ for obj in data.get("basePairs", []):
154
+ nt1 = Residue(
155
+ None,
156
+ ResidueAuth(
157
+ obj["nt1"]["auth"]["chain"],
158
+ obj["nt1"]["auth"]["number"],
159
+ obj["nt1"]["auth"]["icode"],
160
+ obj["nt1"]["auth"]["name"],
161
+ ),
162
+ )
163
+ nt2 = Residue(
164
+ None,
165
+ ResidueAuth(
166
+ obj["nt2"]["auth"]["chain"],
167
+ obj["nt2"]["auth"]["number"],
168
+ obj["nt2"]["auth"]["icode"],
169
+ obj["nt2"]["auth"]["name"],
170
+ ),
171
+ )
172
+ lw = LeontisWesthof(obj["lw"])
173
+ saenger = Saenger(obj["saenger"]) if obj["saenger"] else None
174
+ base_pairs.append(BasePair(nt1, nt2, lw, saenger))
175
+
176
+ with open("tests/1A1T_1_B.cif") as f:
177
+ structure3d = read_3d_structure(f)
178
+
179
+ mapping = Mapping2D3D(structure3d, base_pairs, [], True)
180
+ assert (
181
+ mapping.dot_bracket == ">strand_B\nGGACUAGCGGAGGCUAGUCC\n((((((((....))))))))"
182
+ )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes