RNApolis 0.0.16__tar.gz → 0.1.1__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. {RNApolis-0.0.16 → RNApolis-0.1.1}/PKG-INFO +1 -1
  2. {RNApolis-0.0.16 → RNApolis-0.1.1}/setup.py +1 -1
  3. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/RNApolis.egg-info/PKG-INFO +1 -1
  4. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/rnapolis/annotator.py +26 -12
  5. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/rnapolis/common.py +54 -32
  6. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/rnapolis/motif_extractor.py +5 -1
  7. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/rnapolis/tertiary.py +4 -3
  8. {RNApolis-0.0.16 → RNApolis-0.1.1}/tests/test_bugfixes.py +12 -4
  9. {RNApolis-0.0.16 → RNApolis-0.1.1}/tests/test_common.py +5 -11
  10. {RNApolis-0.0.16 → RNApolis-0.1.1}/tests/test_quadruplexes.py +15 -5
  11. {RNApolis-0.0.16 → RNApolis-0.1.1}/LICENSE +0 -0
  12. {RNApolis-0.0.16 → RNApolis-0.1.1}/README.md +0 -0
  13. {RNApolis-0.0.16 → RNApolis-0.1.1}/pyproject.toml +0 -0
  14. {RNApolis-0.0.16 → RNApolis-0.1.1}/setup.cfg +0 -0
  15. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/RNApolis.egg-info/SOURCES.txt +0 -0
  16. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/RNApolis.egg-info/dependency_links.txt +0 -0
  17. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/RNApolis.egg-info/entry_points.txt +0 -0
  18. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/RNApolis.egg-info/requires.txt +0 -0
  19. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/RNApolis.egg-info/top_level.txt +0 -0
  20. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/rnapolis/clashfinder.py +0 -0
  21. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/rnapolis/metareader.py +0 -0
  22. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/rnapolis/parser.py +0 -0
  23. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/rnapolis/transformer.py +0 -0
  24. {RNApolis-0.0.16 → RNApolis-0.1.1}/src/rnapolis/util.py +0 -0
  25. {RNApolis-0.0.16 → RNApolis-0.1.1}/tests/test_annotator.py +0 -0
  26. {RNApolis-0.0.16 → RNApolis-0.1.1}/tests/test_metareader.py +0 -0
  27. {RNApolis-0.0.16 → RNApolis-0.1.1}/tests/test_parser.py +0 -0
  28. {RNApolis-0.0.16 → RNApolis-0.1.1}/tests/test_tertiary.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RNApolis
3
- Version: 0.0.16
3
+ Version: 0.1.1
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.0.16",
8
+ version="0.1.1",
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.0.16
3
+ Version: 0.1.1
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
@@ -19,6 +19,7 @@ from rnapolis.common import (
19
19
  BasePhosphate,
20
20
  BaseRibose,
21
21
  BPh,
22
+ BpSeq,
22
23
  LeontisWesthof,
23
24
  Residue,
24
25
  Saenger,
@@ -471,11 +472,26 @@ def find_stackings(structure: Structure3D, model: int = 1) -> List[Stacking]:
471
472
 
472
473
 
473
474
  def extract_secondary_structure(
474
- tertiary_structure: Structure3D, model: int = 1
475
+ tertiary_structure: Structure3D, model: int = 1, find_gaps: bool = False
475
476
  ) -> Structure2D:
476
477
  base_pairs, base_phosphate, base_ribose = find_pairs(tertiary_structure, model)
477
478
  stackings = find_stackings(tertiary_structure, model)
478
- return Structure2D(base_pairs, stackings, base_ribose, base_phosphate, [])
479
+ mapping = Mapping2D3D(tertiary_structure, base_pairs, stackings, find_gaps)
480
+ stems, single_strands, hairpins, loops = mapping.bpseq.elements
481
+ return Structure2D(
482
+ base_pairs,
483
+ stackings,
484
+ base_ribose,
485
+ base_phosphate,
486
+ [],
487
+ str(mapping.bpseq),
488
+ mapping.dot_bracket,
489
+ mapping.extended_dot_bracket,
490
+ stems,
491
+ single_strands,
492
+ hairpins,
493
+ loops,
494
+ )
479
495
 
480
496
 
481
497
  def write_json(path: str, structure2d: Structure2D):
@@ -541,9 +557,9 @@ def write_csv(path: str, structure2d: Structure2D):
541
557
  )
542
558
 
543
559
 
544
- def write_bpseq(path: str, mapping: Mapping2D3D):
560
+ def write_bpseq(path: str, bpseq: BpSeq):
545
561
  with open(path, "w") as f:
546
- f.write(str(mapping.bpseq))
562
+ f.write(str(bpseq))
547
563
 
548
564
 
549
565
  def main():
@@ -563,14 +579,14 @@ def main():
563
579
  parser.add_argument(
564
580
  "--find-gaps",
565
581
  action="store_true",
566
- help=f"(optional) if set, the program will detect gaps and break the PDB chain into two or more strands; "
567
- "the gap is defined as O3'-P distance greater then {1.5 * AVERAGE_OXYGEN_PHOSPHORUS_DISTANCE_COVALENT}",
582
+ help="(optional) if set, the program will detect gaps and break the PDB chain into two or more strands; "
583
+ f"the gap is defined as O3'-P distance greater then {1.5 * AVERAGE_OXYGEN_PHOSPHORUS_DISTANCE_COVALENT}",
568
584
  )
569
585
  args = parser.parse_args()
570
586
 
571
587
  file = handle_input_file(args.input)
572
588
  structure3d = read_3d_structure(file, 1)
573
- structure2d = extract_secondary_structure(structure3d)
589
+ structure2d = extract_secondary_structure(structure3d, 1, args.find_gaps)
574
590
 
575
591
  if args.csv:
576
592
  write_csv(args.csv, structure2d)
@@ -578,15 +594,13 @@ def main():
578
594
  if args.json:
579
595
  write_json(args.json, structure2d)
580
596
 
581
- mapping = Mapping2D3D(structure3d, structure2d, args.find_gaps)
582
-
583
597
  if args.bpseq:
584
- write_bpseq(args.bpseq, mapping)
598
+ write_bpseq(args.bpseq, structure2d.bpseq)
585
599
 
586
600
  if args.extended:
587
- print(mapping.extended_dot_bracket)
601
+ print(structure2d.extendedDotBracket)
588
602
  else:
589
- print(mapping.dot_bracket)
603
+ print(structure2d.dotBracket)
590
604
 
591
605
 
592
606
  if __name__ == "__main__":
@@ -321,15 +321,6 @@ class OtherInteraction(Interaction):
321
321
  pass
322
322
 
323
323
 
324
- @dataclass(frozen=True, order=True)
325
- class Structure2D:
326
- basePairs: List[BasePair]
327
- stackings: List[Stacking]
328
- baseRiboseInteractions: List[BaseRibose]
329
- basePhosphateInteractions: List[BasePhosphate]
330
- otherInteractions: List[OtherInteraction]
331
-
332
-
333
324
  @dataclass
334
325
  class Entry(Sequence):
335
326
  index_: int
@@ -380,12 +371,15 @@ class Strand:
380
371
  return f"{self.first}-{self.sequence}-{self.last}"
381
372
 
382
373
 
383
- @dataclass(frozen=True)
374
+ @dataclass
384
375
  class SingleStrand:
385
376
  strand: Strand
386
377
  is5p: bool
387
378
  is3p: bool
388
379
 
380
+ def __post_init__(self):
381
+ self.description = str(self)
382
+
389
383
  def __str__(self):
390
384
  if self.is5p:
391
385
  return f"SingleStrand5p {self.strand.first} {self.strand.last} {self.strand.sequence} {self.strand.structure}"
@@ -394,7 +388,7 @@ class SingleStrand:
394
388
  return f"SingleStrand {self.strand.first} {self.strand.last} {self.strand.sequence} {self.strand.structure}"
395
389
 
396
390
 
397
- @dataclass(frozen=True)
391
+ @dataclass
398
392
  class Stem:
399
393
  strand5p: Strand
400
394
  strand3p: Strand
@@ -410,22 +404,31 @@ class Stem:
410
404
  Strand.from_bpseq_entries(strand3p_entries, dotbracket),
411
405
  )
412
406
 
407
+ def __post_init__(self):
408
+ self.description = str(self)
409
+
413
410
  def __str__(self):
414
411
  return f"Stem {self.strand5p.first} {self.strand5p.last} {self.strand5p.sequence} {self.strand5p.structure} {self.strand3p.first} {self.strand3p.last} {self.strand3p.sequence} {self.strand3p.structure}"
415
412
 
416
413
 
417
- @dataclass(frozen=True)
414
+ @dataclass
418
415
  class Hairpin:
419
416
  strand: Strand
420
417
 
418
+ def __post_init__(self):
419
+ self.description = str(self)
420
+
421
421
  def __str__(self):
422
422
  return f"Hairpin {self.strand.first} {self.strand.last} {self.strand.sequence} {self.strand.structure}"
423
423
 
424
424
 
425
- @dataclass(frozen=True)
425
+ @dataclass
426
426
  class Loop:
427
427
  strands: List[Strand]
428
428
 
429
+ def __post_init__(self):
430
+ self.description = str(self)
431
+
429
432
  def __str__(self):
430
433
  desc = " ".join(
431
434
  [
@@ -516,30 +519,32 @@ class BpSeq:
516
519
  return stems
517
520
 
518
521
  @cached_property
519
- def elements(self):
522
+ def elements(
523
+ self,
524
+ ) -> Tuple[List[Stem], List[SingleStrand], List[Hairpin], List[Loop]]:
520
525
  if not self.__stems_entries:
521
- return []
526
+ return [], [], [], []
522
527
 
523
- elements = []
524
- stops = set()
528
+ stems, single_strands, hairpins, loops = [], [], [], []
529
+ stopset = set()
525
530
 
526
531
  # stems
527
532
  for stem_entries in self.__stems_entries:
528
533
  stem = Stem.from_bpseq_entries(
529
534
  stem_entries, self.entries, self.to_dot_bracket.structure
530
535
  )
531
- elements.append(stem)
532
- stops.add(stem.strand5p.first - 1)
533
- stops.add(stem.strand5p.last - 1)
534
- stops.add(stem.strand3p.first - 1)
535
- stops.add(stem.strand3p.last - 1)
536
+ stems.append(stem)
537
+ stopset.add(stem.strand5p.first - 1)
538
+ stopset.add(stem.strand5p.last - 1)
539
+ stopset.add(stem.strand3p.first - 1)
540
+ stopset.add(stem.strand3p.last - 1)
536
541
 
537
- stops = sorted(stops)
542
+ stops = sorted(stopset)
538
543
  loop_candidates = []
539
544
 
540
545
  # 5' single strand
541
546
  if stops[0] > 0:
542
- elements.append(
547
+ single_strands.append(
543
548
  SingleStrand(
544
549
  Strand.from_bpseq_entries(
545
550
  self.entries[: stops[0] + 1],
@@ -555,7 +560,7 @@ class BpSeq:
555
560
  candidate = self.entries[stops[i - 1] : stops[i] + 1]
556
561
  if all([entry.pair == 0 for entry in candidate[1:-1]]):
557
562
  if candidate[0].pair == candidate[-1].index_:
558
- elements.append(
563
+ hairpins.append(
559
564
  Hairpin(
560
565
  Strand.from_bpseq_entries(
561
566
  candidate, self.to_dot_bracket.structure
@@ -571,7 +576,7 @@ class BpSeq:
571
576
 
572
577
  # 3' single strand
573
578
  if stops[-1] < len(self.entries) - 1:
574
- elements.append(
579
+ single_strands.append(
575
580
  SingleStrand(
576
581
  Strand.from_bpseq_entries(
577
582
  self.entries[stops[-1] :], self.to_dot_bracket.structure
@@ -613,13 +618,13 @@ class BpSeq:
613
618
 
614
619
  if self.entries[loop[0].first - 1].pair == loop[-1].last:
615
620
  if not all([strand.last - strand.first <= 1 for strand in loop]):
616
- elements.append(Loop(loop))
621
+ loops.append(Loop(loop))
617
622
 
618
623
  for i in range(len(loop_candidates)):
619
624
  if i not in used:
620
- elements.append(SingleStrand(loop_candidates[i]))
625
+ single_strands.append(SingleStrand(loop_candidates[i], False, False))
621
626
 
622
- return elements
627
+ return stems, single_strands, hairpins, loops
623
628
 
624
629
  @cached_property
625
630
  def __regions(self) -> List[Tuple[int, int, int]]:
@@ -675,14 +680,14 @@ class BpSeq:
675
680
  vars_by_region[i].append(variable)
676
681
  vars_by_order[j].append(variable)
677
682
  var_by_region_order[(i, j)] = variable
678
- region_by_var[variable] = i
683
+ region_by_var[variable] = regions[i]
679
684
 
680
685
  # define objective function terms
681
686
  terms = []
682
687
 
683
688
  for order, vars in vars_by_order.items():
684
689
  for var in vars:
685
- length = len(regions[region_by_var[var]])
690
+ length = region_by_var[var][2]
686
691
  if order == 0:
687
692
  terms.append(var * length)
688
693
  else:
@@ -707,6 +712,7 @@ class BpSeq:
707
712
 
708
713
  # solve the problem
709
714
  try:
715
+ logging.debug(f"POA: problem formulation\n{problem}")
710
716
  problem.solve(solver)
711
717
  except pulp.PulpSolverError:
712
718
  logging.warning(
@@ -720,7 +726,7 @@ class BpSeq:
720
726
  return self.fcfs()
721
727
 
722
728
  # log solver time statistics
723
- logging.info(
729
+ logging.debug(
724
730
  f"POA: solver {solver.name} took {round(problem.solutionTime, 2)} seconds"
725
731
  )
726
732
 
@@ -833,3 +839,19 @@ class DotBracket:
833
839
 
834
840
  def __str__(self):
835
841
  return f"{self.sequence}\n{self.structure}"
842
+
843
+
844
+ @dataclass(frozen=True, order=True)
845
+ class Structure2D:
846
+ basePairs: List[BasePair]
847
+ stackings: List[Stacking]
848
+ baseRiboseInteractions: List[BaseRibose]
849
+ basePhosphateInteractions: List[BasePhosphate]
850
+ otherInteractions: List[OtherInteraction]
851
+ bpseq: str
852
+ dotBracket: str
853
+ extendedDotBracket: str
854
+ stems: List[Stem]
855
+ singleStrands: List[SingleStrand]
856
+ hairpins: List[Hairpin]
857
+ loops: List[Loop]
@@ -1,5 +1,6 @@
1
1
  #! /usr/bin/env python
2
2
  import argparse
3
+ import itertools
3
4
  from typing import IO, Dict, List
4
5
 
5
6
  import orjson
@@ -24,7 +25,10 @@ def main():
24
25
  parser.print_help()
25
26
  return
26
27
 
27
- for element in bpseq.elements:
28
+ print(f"Full dot-bracket:\n{bpseq.to_dot_bracket}")
29
+ stems, single_strands, hairpins, loops = bpseq.elements
30
+
31
+ for element in itertools.chain(stems, single_strands, hairpins, loops):
28
32
  print(element)
29
33
 
30
34
 
@@ -388,14 +388,15 @@ class Structure3D:
388
388
  @dataclass
389
389
  class Mapping2D3D:
390
390
  structure3d: Structure3D
391
- structure2d: Structure2D
391
+ base_pairs2d: List[BasePair]
392
+ stackings2d: List[Stacking]
392
393
  find_gaps: bool
393
394
 
394
395
  @cached_property
395
396
  def base_pairs(self) -> List[BasePair3D]:
396
397
  result = []
397
398
  used = set()
398
- for base_pair in self.structure2d.basePairs:
399
+ for base_pair in self.base_pairs2d:
399
400
  nt1 = self.structure3d.find_residue(base_pair.nt1.label, base_pair.nt1.auth)
400
401
  nt2 = self.structure3d.find_residue(base_pair.nt2.label, base_pair.nt2.auth)
401
402
  if nt1 is not None and nt2 is not None:
@@ -439,7 +440,7 @@ class Mapping2D3D:
439
440
  def stackings(self) -> List[Stacking3D]:
440
441
  result = []
441
442
  used = set()
442
- for stacking in self.structure2d.stackings:
443
+ for stacking in self.stackings2d:
443
444
  nt1 = self.structure3d.find_residue(stacking.nt1.label, stacking.nt1.auth)
444
445
  nt2 = self.structure3d.find_residue(stacking.nt2.label, stacking.nt2.auth)
445
446
  if nt1 is not None and nt2 is not None:
@@ -9,7 +9,9 @@ def test_1E7K():
9
9
  with open("tests/1E7K_1_C.cif") as f:
10
10
  structure3d = read_3d_structure(f, 1)
11
11
  structure2d = extract_secondary_structure(structure3d)
12
- mapping = Mapping2D3D(structure3d, structure2d, True)
12
+ mapping = Mapping2D3D(
13
+ structure3d, structure2d.basePairs, structure2d.stackings, True
14
+ )
13
15
  assert len(mapping.strands_sequences) == 2
14
16
 
15
17
 
@@ -25,7 +27,9 @@ def test_1DFU():
25
27
  assert b2g is not None
26
28
 
27
29
  structure2d = extract_secondary_structure(structure3d)
28
- mapping = Mapping2D3D(structure3d, structure2d, True)
30
+ mapping = Mapping2D3D(
31
+ structure3d, structure2d.basePairs, structure2d.stackings, True
32
+ )
29
33
  assert b2g not in mapping.base_pair_graph[b1u]
30
34
  assert b1u not in mapping.base_pair_graph[b2g]
31
35
 
@@ -35,7 +39,9 @@ def test_4WTI():
35
39
  with open("tests/4WTI_1_T-P.cif") as f:
36
40
  structure3d = read_3d_structure(f, 1)
37
41
  structure2d = extract_secondary_structure(structure3d)
38
- mapping = Mapping2D3D(structure3d, structure2d, True)
42
+ mapping = Mapping2D3D(
43
+ structure3d, structure2d.basePairs, structure2d.stackings, True
44
+ )
39
45
  assert mapping.dot_bracket == ">strand_T\nCGG\n.((\n>strand_P\nCC\n))"
40
46
 
41
47
 
@@ -44,7 +50,9 @@ def test_1HMH():
44
50
  with open("tests/1HMH_1_E.cif") as f:
45
51
  structure3d = read_3d_structure(f, 1)
46
52
  structure2d = extract_secondary_structure(structure3d)
47
- mapping = Mapping2D3D(structure3d, structure2d, True)
53
+ mapping = Mapping2D3D(
54
+ structure3d, structure2d.basePairs, structure2d.stackings, True
55
+ )
48
56
  assert mapping.dot_bracket == ">strand_E\nUG\n.."
49
57
 
50
58
 
@@ -85,7 +85,7 @@ def test_rnapdbee_adapters_api_compliance_other(obj):
85
85
  @given(st.from_type(Structure2D))
86
86
  @settings(max_examples=10)
87
87
  def test_rnapdbee_adapters_api_compliance_structure2d(obj):
88
- assert obj.__dict__.keys() == {
88
+ assert obj.__dict__.keys() >= {
89
89
  "basePairs",
90
90
  "stackings",
91
91
  "baseRiboseInteractions",
@@ -102,13 +102,7 @@ def test_bpseq_from_dotbracket():
102
102
 
103
103
  def test_elements():
104
104
  bpseq = BpSeq.from_dotbracket(DotBracket.from_file("tests/1EHZ.dbn"))
105
- stems = [element for element in bpseq.elements if isinstance(element, Stem)]
106
- single_strands = [
107
- element for element in bpseq.elements if isinstance(element, SingleStrand)
108
- ]
109
- hairpins = [element for element in bpseq.elements if isinstance(element, Hairpin)]
110
- loops = [element for element in bpseq.elements if isinstance(element, Loop)]
111
-
105
+ stems, single_strands, hairpins, loops = bpseq.elements
112
106
  assert len(stems) == 5
113
107
  assert len(single_strands) == 1
114
108
  assert len(hairpins) == 1
@@ -121,10 +115,10 @@ def test_pseudoknot_order_assignment():
121
115
 
122
116
  counter = Counter(dot_bracket.structure)
123
117
  assert counter["."] == 1185
124
- assert counter["("] == 1296
125
- assert counter["["] == 45
118
+ assert counter["("] == 1298
119
+ assert counter["["] == 44
126
120
  assert counter["{"] == 17
127
- assert counter["<"] == 8
121
+ assert counter["<"] == 7
128
122
  assert counter["A"] == 4
129
123
  assert counter["B"] == 1
130
124
  assert counter["C"] == 1
@@ -9,7 +9,9 @@ def test_2HY9():
9
9
  with open("tests/2HY9.cif") as f:
10
10
  structure3d = read_3d_structure(f, 1)
11
11
  structure2d = extract_secondary_structure(structure3d)
12
- mapping = Mapping2D3D(structure3d, structure2d, True)
12
+ mapping = Mapping2D3D(
13
+ structure3d, structure2d.basePairs, structure2d.stackings, True
14
+ )
13
15
 
14
16
  # tract 1
15
17
  g4 = structure3d.find_residue(ResidueLabel("A", 4, "DG"), None)
@@ -60,7 +62,9 @@ def test_6RS3():
60
62
  with open("tests/6RS3.cif") as f:
61
63
  structure3d = read_3d_structure(f, 1)
62
64
  structure2d = extract_secondary_structure(structure3d)
63
- mapping = Mapping2D3D(structure3d, structure2d, True)
65
+ mapping = Mapping2D3D(
66
+ structure3d, structure2d.basePairs, structure2d.stackings, True
67
+ )
64
68
 
65
69
  g1 = structure3d.find_residue(ResidueLabel("A", 1, "DG"), None)
66
70
  g2 = structure3d.find_residue(ResidueLabel("A", 2, "DG"), None)
@@ -103,7 +107,9 @@ def test_1JJP():
103
107
  with open("tests/1JJP.cif") as f:
104
108
  structure3d = read_3d_structure(f, 1)
105
109
  structure2d = extract_secondary_structure(structure3d)
106
- mapping = Mapping2D3D(structure3d, structure2d, True)
110
+ mapping = Mapping2D3D(
111
+ structure3d, structure2d.basePairs, structure2d.stackings, True
112
+ )
107
113
 
108
114
  ag1 = structure3d.find_residue(ResidueLabel("A", 1, "DG"), None)
109
115
  ag2 = structure3d.find_residue(ResidueLabel("A", 2, "DG"), None)
@@ -175,7 +181,9 @@ def test_6FC9():
175
181
  with open("tests/6FC9.cif") as f:
176
182
  structure3d = read_3d_structure(f, 1)
177
183
  structure2d = extract_secondary_structure(structure3d)
178
- mapping = Mapping2D3D(structure3d, structure2d, True)
184
+ mapping = Mapping2D3D(
185
+ structure3d, structure2d.basePairs, structure2d.stackings, True
186
+ )
179
187
 
180
188
  g1 = structure3d.find_residue(ResidueLabel("A", 1, "DG"), None)
181
189
  g2 = structure3d.find_residue(ResidueLabel("A", 2, "DG"), None)
@@ -249,7 +257,9 @@ def test_UGG_md():
249
257
  with open("tests/q-ugg-5k-salt_400-500ns_frame1065.pdb") as f:
250
258
  structure3d = read_3d_structure(f, 1)
251
259
  structure2d = extract_secondary_structure(structure3d)
252
- mapping = Mapping2D3D(structure3d, structure2d, True)
260
+ mapping = Mapping2D3D(
261
+ structure3d, structure2d.basePairs, structure2d.stackings, True
262
+ )
253
263
 
254
264
  u1 = structure3d.find_residue(None, ResidueAuth(" ", 1, None, "U5"))
255
265
  g2 = structure3d.find_residue(None, ResidueAuth(" ", 2, None, "G"))
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes