RNApolis 0.10.3__py3-none-any.whl → 0.10.5__py3-none-any.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.
- rnapolis/adapter.py +28 -13
 - rnapolis/annotator.py +17 -110
 - rnapolis/common.py +98 -1
 - {rnapolis-0.10.3.dist-info → rnapolis-0.10.5.dist-info}/METADATA +1 -1
 - {rnapolis-0.10.3.dist-info → rnapolis-0.10.5.dist-info}/RECORD +9 -9
 - {rnapolis-0.10.3.dist-info → rnapolis-0.10.5.dist-info}/WHEEL +0 -0
 - {rnapolis-0.10.3.dist-info → rnapolis-0.10.5.dist-info}/entry_points.txt +0 -0
 - {rnapolis-0.10.3.dist-info → rnapolis-0.10.5.dist-info}/licenses/LICENSE +0 -0
 - {rnapolis-0.10.3.dist-info → rnapolis-0.10.5.dist-info}/top_level.txt +0 -0
 
    
        rnapolis/adapter.py
    CHANGED
    
    | 
         @@ -317,10 +317,14 @@ def parse_dssr_output( 
     | 
|
| 
       317 
317 
     | 
    
         
             
                        if nt1 is not None and nt2 is not None:
         
     | 
| 
       318 
318 
     | 
    
         
             
                            stackings.append(Stacking(nt1, nt2, None))
         
     | 
| 
       319 
319 
     | 
    
         | 
| 
       320 
     | 
    
         
            -
                return BaseInteractions( 
     | 
| 
      
 320 
     | 
    
         
            +
                return BaseInteractions.from_structure3d(
         
     | 
| 
      
 321 
     | 
    
         
            +
                    structure3d, base_pairs, stackings, [], [], []
         
     | 
| 
      
 322 
     | 
    
         
            +
                )
         
     | 
| 
       321 
323 
     | 
    
         | 
| 
       322 
324 
     | 
    
         | 
| 
       323 
     | 
    
         
            -
            def parse_maxit_output( 
     | 
| 
      
 325 
     | 
    
         
            +
            def parse_maxit_output(
         
     | 
| 
      
 326 
     | 
    
         
            +
                file_paths: List[str], structure3d: Structure3D
         
     | 
| 
      
 327 
     | 
    
         
            +
            ) -> BaseInteractions:
         
     | 
| 
       324 
328 
     | 
    
         
             
                """
         
     | 
| 
       325 
329 
     | 
    
         
             
                Parse MAXIT output files and convert to BaseInteractions.
         
     | 
| 
       326 
330 
     | 
    
         | 
| 
         @@ -448,10 +452,14 @@ def parse_maxit_output(file_paths: List[str]) -> BaseInteractions: 
     | 
|
| 
       448 
452 
     | 
    
         
             
                except Exception as e:
         
     | 
| 
       449 
453 
     | 
    
         
             
                    logging.warning(f"Error processing MAXIT file {cif_file}: {e}", exc_info=True)
         
     | 
| 
       450 
454 
     | 
    
         | 
| 
       451 
     | 
    
         
            -
                return BaseInteractions( 
     | 
| 
      
 455 
     | 
    
         
            +
                return BaseInteractions.from_structure3d(
         
     | 
| 
      
 456 
     | 
    
         
            +
                    structure3d, all_base_pairs, [], [], [], all_other_interactions
         
     | 
| 
      
 457 
     | 
    
         
            +
                )
         
     | 
| 
       452 
458 
     | 
    
         | 
| 
       453 
459 
     | 
    
         | 
| 
       454 
     | 
    
         
            -
            def parse_bpnet_output( 
     | 
| 
      
 460 
     | 
    
         
            +
            def parse_bpnet_output(
         
     | 
| 
      
 461 
     | 
    
         
            +
                file_paths: List[str], structure3d: Structure3D
         
     | 
| 
      
 462 
     | 
    
         
            +
            ) -> BaseInteractions:
         
     | 
| 
       455 
463 
     | 
    
         
             
                """
         
     | 
| 
       456 
464 
     | 
    
         
             
                Parse BPNet output files and convert to BaseInteractions.
         
     | 
| 
       457 
465 
     | 
    
         | 
| 
         @@ -649,7 +657,8 @@ def parse_bpnet_output(file_paths: List[str]) -> BaseInteractions: 
     | 
|
| 
       649 
657 
     | 
    
         
             
                            f"Error processing BPNet rob file {rob_file}: {e}", exc_info=True
         
     | 
| 
       650 
658 
     | 
    
         
             
                        )
         
     | 
| 
       651 
659 
     | 
    
         | 
| 
       652 
     | 
    
         
            -
                return BaseInteractions(
         
     | 
| 
      
 660 
     | 
    
         
            +
                return BaseInteractions.from_structure3d(
         
     | 
| 
      
 661 
     | 
    
         
            +
                    structure3d,
         
     | 
| 
       653 
662 
     | 
    
         
             
                    base_pairs,
         
     | 
| 
       654 
663 
     | 
    
         
             
                    stackings,
         
     | 
| 
       655 
664 
     | 
    
         
             
                    base_ribose_interactions,
         
     | 
| 
         @@ -986,7 +995,8 @@ def parse_rnaview_output( 
     | 
|
| 
       986 
995 
     | 
    
         
             
                except Exception as e:
         
     | 
| 
       987 
996 
     | 
    
         
             
                    logging.warning(f"Error processing RNAView file {out_file}: {e}", exc_info=True)
         
     | 
| 
       988 
997 
     | 
    
         | 
| 
       989 
     | 
    
         
            -
                return BaseInteractions(
         
     | 
| 
      
 998 
     | 
    
         
            +
                return BaseInteractions.from_structure3d(
         
     | 
| 
      
 999 
     | 
    
         
            +
                    structure3d,
         
     | 
| 
       990 
1000 
     | 
    
         
             
                    base_pairs,
         
     | 
| 
       991 
1001 
     | 
    
         
             
                    stackings,
         
     | 
| 
       992 
1002 
     | 
    
         
             
                    base_ribose_interactions,
         
     | 
| 
         @@ -1077,7 +1087,7 @@ def parse_barnaba_output( 
     | 
|
| 
       1077 
1087 
     | 
    
         
             
                            f"Residue name mismatch for {residue_info}: expected {name}, found {residue.auth.name}"
         
     | 
| 
       1078 
1088 
     | 
    
         
             
                        )
         
     | 
| 
       1079 
1089 
     | 
    
         | 
| 
       1080 
     | 
    
         
            -
                    return residue
         
     | 
| 
      
 1090 
     | 
    
         
            +
                    return Residue(residue.label, residue.auth)
         
     | 
| 
       1081 
1091 
     | 
    
         | 
| 
       1082 
1092 
     | 
    
         
             
                base_pairs: List[BasePair] = []
         
     | 
| 
       1083 
1093 
     | 
    
         
             
                stackings: List[Stacking] = []
         
     | 
| 
         @@ -1142,7 +1152,9 @@ def parse_barnaba_output( 
     | 
|
| 
       1142 
1152 
     | 
    
         
             
                                    f"Unknown barnaba stacking topology: {interaction_str}"
         
     | 
| 
       1143 
1153 
     | 
    
         
             
                                )
         
     | 
| 
       1144 
1154 
     | 
    
         | 
| 
       1145 
     | 
    
         
            -
                return BaseInteractions( 
     | 
| 
      
 1155 
     | 
    
         
            +
                return BaseInteractions.from_structure3d(
         
     | 
| 
      
 1156 
     | 
    
         
            +
                    structure3d, base_pairs, stackings, [], [], other_interactions
         
     | 
| 
      
 1157 
     | 
    
         
            +
                )
         
     | 
| 
       1146 
1158 
     | 
    
         | 
| 
       1147 
1159 
     | 
    
         | 
| 
       1148 
1160 
     | 
    
         
             
            def parse_external_output(
         
     | 
| 
         @@ -1160,13 +1172,13 @@ def parse_external_output( 
     | 
|
| 
       1160 
1172 
     | 
    
         
             
                    BaseInteractions object containing the interactions found by the external tool
         
     | 
| 
       1161 
1173 
     | 
    
         
             
                """
         
     | 
| 
       1162 
1174 
     | 
    
         
             
                if tool == ExternalTool.FR3D:
         
     | 
| 
       1163 
     | 
    
         
            -
                    return parse_fr3d_output(file_paths)
         
     | 
| 
      
 1175 
     | 
    
         
            +
                    return parse_fr3d_output(file_paths, structure3d)
         
     | 
| 
       1164 
1176 
     | 
    
         
             
                elif tool == ExternalTool.DSSR:
         
     | 
| 
       1165 
1177 
     | 
    
         
             
                    return parse_dssr_output(file_paths, structure3d)
         
     | 
| 
       1166 
1178 
     | 
    
         
             
                elif tool == ExternalTool.MAXIT:
         
     | 
| 
       1167 
     | 
    
         
            -
                    return parse_maxit_output(file_paths)
         
     | 
| 
      
 1179 
     | 
    
         
            +
                    return parse_maxit_output(file_paths, structure3d)
         
     | 
| 
       1168 
1180 
     | 
    
         
             
                elif tool == ExternalTool.BPNET:
         
     | 
| 
       1169 
     | 
    
         
            -
                    return parse_bpnet_output(file_paths)
         
     | 
| 
      
 1181 
     | 
    
         
            +
                    return parse_bpnet_output(file_paths, structure3d)
         
     | 
| 
       1170 
1182 
     | 
    
         
             
                elif tool == ExternalTool.RNAVIEW:
         
     | 
| 
       1171 
1183 
     | 
    
         
             
                    return parse_rnaview_output(file_paths, structure3d)
         
     | 
| 
       1172 
1184 
     | 
    
         
             
                elif tool == ExternalTool.BARNABA:
         
     | 
| 
         @@ -1175,7 +1187,9 @@ def parse_external_output( 
     | 
|
| 
       1175 
1187 
     | 
    
         
             
                    raise ValueError(f"Unsupported external tool: {tool}")
         
     | 
| 
       1176 
1188 
     | 
    
         | 
| 
       1177 
1189 
     | 
    
         | 
| 
       1178 
     | 
    
         
            -
            def parse_fr3d_output( 
     | 
| 
      
 1190 
     | 
    
         
            +
            def parse_fr3d_output(
         
     | 
| 
      
 1191 
     | 
    
         
            +
                file_paths: List[str], structure3d: Structure3D
         
     | 
| 
      
 1192 
     | 
    
         
            +
            ) -> BaseInteractions:
         
     | 
| 
       1179 
1193 
     | 
    
         
             
                """
         
     | 
| 
       1180 
1194 
     | 
    
         
             
                Parse FR3D output files and convert to BaseInteractions.
         
     | 
| 
       1181 
1195 
     | 
    
         | 
| 
         @@ -1208,7 +1222,8 @@ def parse_fr3d_output(file_paths: List[str]) -> BaseInteractions: 
     | 
|
| 
       1208 
1222 
     | 
    
         
             
                            _process_interaction_line(line, interactions_data)
         
     | 
| 
       1209 
1223 
     | 
    
         | 
| 
       1210 
1224 
     | 
    
         
             
                # Return a BaseInteractions object with all the processed interactions
         
     | 
| 
       1211 
     | 
    
         
            -
                return BaseInteractions(
         
     | 
| 
      
 1225 
     | 
    
         
            +
                return BaseInteractions.from_structure3d(
         
     | 
| 
      
 1226 
     | 
    
         
            +
                    structure3d,
         
     | 
| 
       1212 
1227 
     | 
    
         
             
                    interactions_data["base_pairs"],
         
     | 
| 
       1213 
1228 
     | 
    
         
             
                    interactions_data["stackings"],
         
     | 
| 
       1214 
1229 
     | 
    
         
             
                    interactions_data["base_ribose_interactions"],
         
     | 
    
        rnapolis/annotator.py
    CHANGED
    
    | 
         @@ -85,15 +85,6 @@ def detect_cis_trans(residue_i: Residue3D, residue_j: Residue3D) -> Optional[str 
     | 
|
| 
       85 
85 
     | 
    
         
             
                return "c" if -90.0 < torsion < 90.0 else "t"
         
     | 
| 
       86 
86 
     | 
    
         | 
| 
       87 
87 
     | 
    
         | 
| 
       88 
     | 
    
         
            -
            def detect_saenger(
         
     | 
| 
       89 
     | 
    
         
            -
                residue_i: Residue3D, residue_j: Residue3D, lw: LeontisWesthof
         
     | 
| 
       90 
     | 
    
         
            -
            ) -> Optional[Saenger]:
         
     | 
| 
       91 
     | 
    
         
            -
                key = (f"{residue_i.one_letter_name}{residue_j.one_letter_name}", lw.value)
         
     | 
| 
       92 
     | 
    
         
            -
                if key in Saenger.table():
         
     | 
| 
       93 
     | 
    
         
            -
                    return Saenger[Saenger.table()[key]]
         
     | 
| 
       94 
     | 
    
         
            -
                return None
         
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
88 
     | 
    
         
             
            def detect_bph_br_classification(
         
     | 
| 
       98 
89 
     | 
    
         
             
                donor_residue: Residue3D, donor: Atom, acceptor: Atom
         
     | 
| 
       99 
90 
     | 
    
         
             
            ) -> Optional[int]:
         
     | 
| 
         @@ -367,7 +358,9 @@ def find_pairs( 
     | 
|
| 
       367 
358 
     | 
    
         
             
                            Residue(residue_i.label, residue_i.auth),
         
     | 
| 
       368 
359 
     | 
    
         
             
                            Residue(residue_j.label, residue_j.auth),
         
     | 
| 
       369 
360 
     | 
    
         
             
                            lw,
         
     | 
| 
       370 
     | 
    
         
            -
                             
     | 
| 
      
 361 
     | 
    
         
            +
                            Saenger.from_leontis_westhof(
         
     | 
| 
      
 362 
     | 
    
         
            +
                                residue_i.one_letter_name, residue_j.one_letter_name, lw
         
     | 
| 
      
 363 
     | 
    
         
            +
                            ),
         
     | 
| 
       371 
364 
     | 
    
         
             
                        )
         
     | 
| 
       372 
365 
     | 
    
         
             
                    )
         
     | 
| 
       373 
366 
     | 
    
         | 
| 
         @@ -483,7 +476,9 @@ def extract_base_interactions( 
     | 
|
| 
       483 
476 
     | 
    
         
             
            ) -> BaseInteractions:
         
     | 
| 
       484 
477 
     | 
    
         
             
                base_pairs, base_phosphate, base_ribose = find_pairs(tertiary_structure, model)
         
     | 
| 
       485 
478 
     | 
    
         
             
                stackings = find_stackings(tertiary_structure, model)
         
     | 
| 
       486 
     | 
    
         
            -
                return BaseInteractions( 
     | 
| 
      
 479 
     | 
    
         
            +
                return BaseInteractions.from_structure3d(
         
     | 
| 
      
 480 
     | 
    
         
            +
                    tertiary_structure, base_pairs, stackings, base_ribose, base_phosphate, []
         
     | 
| 
      
 481 
     | 
    
         
            +
                )
         
     | 
| 
       487 
482 
     | 
    
         | 
| 
       488 
483 
     | 
    
         | 
| 
       489 
484 
     | 
    
         
             
            def generate_pymol_script(mapping: Mapping2D3D, stems: List[Stem]) -> str:
         
     | 
| 
         @@ -688,91 +683,6 @@ def add_common_output_arguments(parser: argparse.ArgumentParser): 
     | 
|
| 
       688 
683 
     | 
    
         
             
                )
         
     | 
| 
       689 
684 
     | 
    
         | 
| 
       690 
685 
     | 
    
         | 
| 
       691 
     | 
    
         
            -
            def unify_structure_data(structure2d: Structure2D, mapping: Mapping2D3D) -> Structure2D:
         
     | 
| 
       692 
     | 
    
         
            -
                """
         
     | 
| 
       693 
     | 
    
         
            -
                Unify structure data by:
         
     | 
| 
       694 
     | 
    
         
            -
                1. Adding missing Saenger classifications to base pairs
         
     | 
| 
       695 
     | 
    
         
            -
                2. Filling in empty residue labels from Structure3D
         
     | 
| 
       696 
     | 
    
         
            -
                """
         
     | 
| 
       697 
     | 
    
         
            -
                # Create a mapping from residue to residue3d for label filling
         
     | 
| 
       698 
     | 
    
         
            -
                residue_to_residue3d = {}
         
     | 
| 
       699 
     | 
    
         
            -
                for residue3d in mapping.structure3d.residues:
         
     | 
| 
       700 
     | 
    
         
            -
                    residue_key = Residue(residue3d.label, residue3d.auth)
         
     | 
| 
       701 
     | 
    
         
            -
                    residue_to_residue3d[residue_key] = residue3d
         
     | 
| 
       702 
     | 
    
         
            -
             
     | 
| 
       703 
     | 
    
         
            -
                def fill_residue_label(residue: Residue) -> Residue:
         
     | 
| 
       704 
     | 
    
         
            -
                    """Fill empty label from Structure3D if available."""
         
     | 
| 
       705 
     | 
    
         
            -
                    if residue.label is not None:
         
     | 
| 
       706 
     | 
    
         
            -
                        return residue
         
     | 
| 
       707 
     | 
    
         
            -
             
     | 
| 
       708 
     | 
    
         
            -
                    # Try to find matching residue3d by auth
         
     | 
| 
       709 
     | 
    
         
            -
                    for residue3d in mapping.structure3d.residues:
         
     | 
| 
       710 
     | 
    
         
            -
                        if residue.auth == residue3d.auth:
         
     | 
| 
       711 
     | 
    
         
            -
                            return Residue(residue3d.label, residue.auth)
         
     | 
| 
       712 
     | 
    
         
            -
             
     | 
| 
       713 
     | 
    
         
            -
                    return residue
         
     | 
| 
       714 
     | 
    
         
            -
             
     | 
| 
       715 
     | 
    
         
            -
                # Process base pairs
         
     | 
| 
       716 
     | 
    
         
            -
                unified_base_pairs = []
         
     | 
| 
       717 
     | 
    
         
            -
                for base_pair in structure2d.base_pairs:
         
     | 
| 
       718 
     | 
    
         
            -
                    # Fill in missing labels
         
     | 
| 
       719 
     | 
    
         
            -
                    nt1 = fill_residue_label(base_pair.nt1)
         
     | 
| 
       720 
     | 
    
         
            -
                    nt2 = fill_residue_label(base_pair.nt2)
         
     | 
| 
       721 
     | 
    
         
            -
             
     | 
| 
       722 
     | 
    
         
            -
                    # Detect missing Saenger classification
         
     | 
| 
       723 
     | 
    
         
            -
                    saenger = base_pair.saenger
         
     | 
| 
       724 
     | 
    
         
            -
                    if saenger is None:
         
     | 
| 
       725 
     | 
    
         
            -
                        # Find corresponding 3D residues for Saenger detection
         
     | 
| 
       726 
     | 
    
         
            -
                        residue3d_1 = residue_to_residue3d.get(Residue(nt1.label, nt1.auth))
         
     | 
| 
       727 
     | 
    
         
            -
                        residue3d_2 = residue_to_residue3d.get(Residue(nt2.label, nt2.auth))
         
     | 
| 
       728 
     | 
    
         
            -
             
     | 
| 
       729 
     | 
    
         
            -
                        if residue3d_1 is not None and residue3d_2 is not None:
         
     | 
| 
       730 
     | 
    
         
            -
                            saenger = detect_saenger(residue3d_1, residue3d_2, base_pair.lw)
         
     | 
| 
       731 
     | 
    
         
            -
             
     | 
| 
       732 
     | 
    
         
            -
                    unified_base_pairs.append(BasePair(nt1, nt2, base_pair.lw, saenger))
         
     | 
| 
       733 
     | 
    
         
            -
             
     | 
| 
       734 
     | 
    
         
            -
                # Process other interaction types (fill labels only)
         
     | 
| 
       735 
     | 
    
         
            -
                unified_stackings = []
         
     | 
| 
       736 
     | 
    
         
            -
                for stacking in structure2d.stackings:
         
     | 
| 
       737 
     | 
    
         
            -
                    nt1 = fill_residue_label(stacking.nt1)
         
     | 
| 
       738 
     | 
    
         
            -
                    nt2 = fill_residue_label(stacking.nt2)
         
     | 
| 
       739 
     | 
    
         
            -
                    unified_stackings.append(Stacking(nt1, nt2, stacking.topology))
         
     | 
| 
       740 
     | 
    
         
            -
             
     | 
| 
       741 
     | 
    
         
            -
                unified_base_ribose = []
         
     | 
| 
       742 
     | 
    
         
            -
                for base_ribose in structure2d.base_ribose_interactions:
         
     | 
| 
       743 
     | 
    
         
            -
                    nt1 = fill_residue_label(base_ribose.nt1)
         
     | 
| 
       744 
     | 
    
         
            -
                    nt2 = fill_residue_label(base_ribose.nt2)
         
     | 
| 
       745 
     | 
    
         
            -
                    unified_base_ribose.append(BaseRibose(nt1, nt2, base_ribose.br))
         
     | 
| 
       746 
     | 
    
         
            -
             
     | 
| 
       747 
     | 
    
         
            -
                unified_base_phosphate = []
         
     | 
| 
       748 
     | 
    
         
            -
                for base_phosphate in structure2d.base_phosphate_interactions:
         
     | 
| 
       749 
     | 
    
         
            -
                    nt1 = fill_residue_label(base_phosphate.nt1)
         
     | 
| 
       750 
     | 
    
         
            -
                    nt2 = fill_residue_label(base_phosphate.nt2)
         
     | 
| 
       751 
     | 
    
         
            -
                    unified_base_phosphate.append(BasePhosphate(nt1, nt2, base_phosphate.bph))
         
     | 
| 
       752 
     | 
    
         
            -
             
     | 
| 
       753 
     | 
    
         
            -
                unified_other = []
         
     | 
| 
       754 
     | 
    
         
            -
                for other in structure2d.other_interactions:
         
     | 
| 
       755 
     | 
    
         
            -
                    nt1 = fill_residue_label(other.nt1)
         
     | 
| 
       756 
     | 
    
         
            -
                    nt2 = fill_residue_label(other.nt2)
         
     | 
| 
       757 
     | 
    
         
            -
                    unified_other.append(OtherInteraction(nt1, nt2))
         
     | 
| 
       758 
     | 
    
         
            -
             
     | 
| 
       759 
     | 
    
         
            -
                # Create new Structure2D with unified data
         
     | 
| 
       760 
     | 
    
         
            -
                unified_base_interactions = BaseInteractions(
         
     | 
| 
       761 
     | 
    
         
            -
                    unified_base_pairs,
         
     | 
| 
       762 
     | 
    
         
            -
                    unified_stackings,
         
     | 
| 
       763 
     | 
    
         
            -
                    unified_base_ribose,
         
     | 
| 
       764 
     | 
    
         
            -
                    unified_base_phosphate,
         
     | 
| 
       765 
     | 
    
         
            -
                    unified_other,
         
     | 
| 
       766 
     | 
    
         
            -
                )
         
     | 
| 
       767 
     | 
    
         
            -
             
     | 
| 
       768 
     | 
    
         
            -
                # Recreate Structure2D with unified interactions
         
     | 
| 
       769 
     | 
    
         
            -
                unified_structure2d, _ = mapping.structure3d.extract_secondary_structure(
         
     | 
| 
       770 
     | 
    
         
            -
                    unified_base_interactions, False
         
     | 
| 
       771 
     | 
    
         
            -
                )
         
     | 
| 
       772 
     | 
    
         
            -
             
     | 
| 
       773 
     | 
    
         
            -
                return unified_structure2d
         
     | 
| 
       774 
     | 
    
         
            -
             
     | 
| 
       775 
     | 
    
         
            -
             
     | 
| 
       776 
686 
     | 
    
         
             
            def handle_output_arguments(
         
     | 
| 
       777 
687 
     | 
    
         
             
                args: argparse.Namespace,
         
     | 
| 
       778 
688 
     | 
    
         
             
                structure2d: Structure2D,
         
     | 
| 
         @@ -780,34 +690,31 @@ def handle_output_arguments( 
     | 
|
| 
       780 
690 
     | 
    
         
             
                input_filename: str,
         
     | 
| 
       781 
691 
     | 
    
         
             
            ):
         
     | 
| 
       782 
692 
     | 
    
         
             
                """Handles writing output based on provided arguments."""
         
     | 
| 
       783 
     | 
    
         
            -
                # Unify the structure data before processing outputs
         
     | 
| 
       784 
     | 
    
         
            -
                unified_structure2d = unify_structure_data(structure2d, mapping)
         
     | 
| 
       785 
     | 
    
         
            -
             
     | 
| 
       786 
693 
     | 
    
         
             
                input_basename = os.path.basename(input_filename)
         
     | 
| 
       787 
694 
     | 
    
         
             
                if args.csv:
         
     | 
| 
       788 
     | 
    
         
            -
                    write_csv(args.csv,  
     | 
| 
      
 695 
     | 
    
         
            +
                    write_csv(args.csv, structure2d)
         
     | 
| 
       789 
696 
     | 
    
         | 
| 
       790 
697 
     | 
    
         
             
                if args.json:
         
     | 
| 
       791 
     | 
    
         
            -
                    write_json(args.json,  
     | 
| 
      
 698 
     | 
    
         
            +
                    write_json(args.json, structure2d)
         
     | 
| 
       792 
699 
     | 
    
         | 
| 
       793 
700 
     | 
    
         
             
                if args.bpseq:
         
     | 
| 
       794 
     | 
    
         
            -
                    write_bpseq(args.bpseq,  
     | 
| 
      
 701 
     | 
    
         
            +
                    write_bpseq(args.bpseq, structure2d.bpseq)
         
     | 
| 
       795 
702 
     | 
    
         | 
| 
       796 
703 
     | 
    
         
             
                if args.extended:
         
     | 
| 
       797 
     | 
    
         
            -
                    print( 
     | 
| 
      
 704 
     | 
    
         
            +
                    print(structure2d.extended_dot_bracket)
         
     | 
| 
       798 
705 
     | 
    
         
             
                else:
         
     | 
| 
       799 
     | 
    
         
            -
                    print( 
     | 
| 
      
 706 
     | 
    
         
            +
                    print(structure2d.dot_bracket)
         
     | 
| 
       800 
707 
     | 
    
         | 
| 
       801 
708 
     | 
    
         
             
                if args.dot:
         
     | 
| 
       802 
     | 
    
         
            -
                    print(BpSeq.from_string( 
     | 
| 
      
 709 
     | 
    
         
            +
                    print(BpSeq.from_string(structure2d.bpseq).graphviz)
         
     | 
| 
       803 
710 
     | 
    
         | 
| 
       804 
711 
     | 
    
         
             
                if args.pml:
         
     | 
| 
       805 
     | 
    
         
            -
                    pml_script = generate_pymol_script(mapping,  
     | 
| 
      
 712 
     | 
    
         
            +
                    pml_script = generate_pymol_script(mapping, structure2d.stems)
         
     | 
| 
       806 
713 
     | 
    
         
             
                    with open(args.pml, "w") as f:
         
     | 
| 
       807 
714 
     | 
    
         
             
                        f.write(pml_script)
         
     | 
| 
       808 
715 
     | 
    
         | 
| 
       809 
716 
     | 
    
         
             
                if args.inter_stem_csv:
         
     | 
| 
       810 
     | 
    
         
            -
                    if  
     | 
| 
      
 717 
     | 
    
         
            +
                    if structure2d.inter_stem_parameters:
         
     | 
| 
       811 
718 
     | 
    
         
             
                        # Convert list of dataclasses to list of dicts
         
     | 
| 
       812 
719 
     | 
    
         
             
                        params_list = [
         
     | 
| 
       813 
720 
     | 
    
         
             
                            {
         
     | 
| 
         @@ -820,7 +727,7 @@ def handle_output_arguments( 
     | 
|
| 
       820 
727 
     | 
    
         
             
                                "min_endpoint_distance_pdf": p.min_endpoint_distance_pdf,
         
     | 
| 
       821 
728 
     | 
    
         
             
                                "coaxial_probability": p.coaxial_probability,
         
     | 
| 
       822 
729 
     | 
    
         
             
                            }
         
     | 
| 
       823 
     | 
    
         
            -
                            for p in  
     | 
| 
      
 730 
     | 
    
         
            +
                            for p in structure2d.interStemParameters
         
     | 
| 
       824 
731 
     | 
    
         
             
                        ]
         
     | 
| 
       825 
732 
     | 
    
         
             
                        df = pd.DataFrame(params_list)
         
     | 
| 
       826 
733 
     | 
    
         
             
                        df["input_basename"] = input_basename
         
     | 
| 
         @@ -838,9 +745,9 @@ def handle_output_arguments( 
     | 
|
| 
       838 
745 
     | 
    
         
             
                        # pd.DataFrame(columns=['input_basename', 'stem1_idx', ...]).to_csv(args.inter_stem_csv, index=False)
         
     | 
| 
       839 
746 
     | 
    
         | 
| 
       840 
747 
     | 
    
         
             
                if args.stems_csv:
         
     | 
| 
       841 
     | 
    
         
            -
                    if  
     | 
| 
      
 748 
     | 
    
         
            +
                    if structure2d.stems:
         
     | 
| 
       842 
749 
     | 
    
         
             
                        stems_data = []
         
     | 
| 
       843 
     | 
    
         
            -
                        for i, stem in enumerate( 
     | 
| 
      
 750 
     | 
    
         
            +
                        for i, stem in enumerate(structure2d.stems):
         
     | 
| 
       844 
751 
     | 
    
         
             
                            try:
         
     | 
| 
       845 
752 
     | 
    
         
             
                                res5p_first = mapping.bpseq_index_to_residue_map.get(
         
     | 
| 
       846 
753 
     | 
    
         
             
                                    stem.strand5p.first
         
     | 
    
        rnapolis/common.py
    CHANGED
    
    | 
         @@ -5,7 +5,7 @@ import re 
     | 
|
| 
       5 
5 
     | 
    
         
             
            import string
         
     | 
| 
       6 
6 
     | 
    
         
             
            from collections import defaultdict
         
     | 
| 
       7 
7 
     | 
    
         
             
            from collections.abc import Sequence
         
     | 
| 
       8 
     | 
    
         
            -
            from dataclasses import dataclass
         
     | 
| 
      
 8 
     | 
    
         
            +
            from dataclasses import InitVar, dataclass
         
     | 
| 
       9 
9 
     | 
    
         
             
            from enum import Enum
         
     | 
| 
       10 
10 
     | 
    
         
             
            from functools import cache, cached_property, total_ordering
         
     | 
| 
       11 
11 
     | 
    
         
             
            from typing import Dict, List, Optional, Tuple
         
     | 
| 
         @@ -152,6 +152,18 @@ class Saenger(Enum): 
     | 
|
| 
       152 
152 
     | 
    
         
             
                        ("TG", "cWW"): "XXVIII",
         
     | 
| 
       153 
153 
     | 
    
         
             
                    }
         
     | 
| 
       154 
154 
     | 
    
         | 
| 
      
 155 
     | 
    
         
            +
                @classmethod
         
     | 
| 
      
 156 
     | 
    
         
            +
                def from_leontis_westhof(
         
     | 
| 
      
 157 
     | 
    
         
            +
                    cls,
         
     | 
| 
      
 158 
     | 
    
         
            +
                    residue_i_one_letter_name: str,
         
     | 
| 
      
 159 
     | 
    
         
            +
                    residue_j_one_letter_name: str,
         
     | 
| 
      
 160 
     | 
    
         
            +
                    lw: LeontisWesthof,
         
     | 
| 
      
 161 
     | 
    
         
            +
                ) -> Optional["Saenger"]:
         
     | 
| 
      
 162 
     | 
    
         
            +
                    key = (f"{residue_i_one_letter_name}{residue_j_one_letter_name}", lw.value)
         
     | 
| 
      
 163 
     | 
    
         
            +
                    if key in Saenger.table():
         
     | 
| 
      
 164 
     | 
    
         
            +
                        return Saenger[Saenger.table()[key]]
         
     | 
| 
      
 165 
     | 
    
         
            +
                    return None
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
       155 
167 
     | 
    
         
             
                @property
         
     | 
| 
       156 
168 
     | 
    
         
             
                def is_canonical(self) -> bool:
         
     | 
| 
       157 
169 
     | 
    
         
             
                    return self == Saenger.XIX or self == Saenger.XX or self == Saenger.XXVIII
         
     | 
| 
         @@ -1062,6 +1074,91 @@ class BaseInteractions: 
     | 
|
| 
       1062 
1074 
     | 
    
         
             
                base_phosphate_interactions: List[BasePhosphate]
         
     | 
| 
       1063 
1075 
     | 
    
         
             
                other_interactions: List[OtherInteraction]
         
     | 
| 
       1064 
1076 
     | 
    
         | 
| 
      
 1077 
     | 
    
         
            +
                @classmethod
         
     | 
| 
      
 1078 
     | 
    
         
            +
                def from_structure3d(
         
     | 
| 
      
 1079 
     | 
    
         
            +
                    cls,
         
     | 
| 
      
 1080 
     | 
    
         
            +
                    structure3d: "Structure3D",
         
     | 
| 
      
 1081 
     | 
    
         
            +
                    base_pairs: List[BasePair],
         
     | 
| 
      
 1082 
     | 
    
         
            +
                    stackings: List[Stacking],
         
     | 
| 
      
 1083 
     | 
    
         
            +
                    base_ribose_interactions: List[BaseRibose],
         
     | 
| 
      
 1084 
     | 
    
         
            +
                    base_phosphate_interactions: List[BasePhosphate],
         
     | 
| 
      
 1085 
     | 
    
         
            +
                    other_interactions: List[OtherInteraction],
         
     | 
| 
      
 1086 
     | 
    
         
            +
                ) -> "BaseInteractions":
         
     | 
| 
      
 1087 
     | 
    
         
            +
                    auth2residue3d = {}
         
     | 
| 
      
 1088 
     | 
    
         
            +
                    auth2label = {}
         
     | 
| 
      
 1089 
     | 
    
         
            +
                    label2auth = {}
         
     | 
| 
      
 1090 
     | 
    
         
            +
             
     | 
| 
      
 1091 
     | 
    
         
            +
                    for residue3d in structure3d.residues:
         
     | 
| 
      
 1092 
     | 
    
         
            +
                        auth2residue3d[residue3d.auth] = residue3d
         
     | 
| 
      
 1093 
     | 
    
         
            +
                        auth2label[residue3d.auth] = residue3d.label
         
     | 
| 
      
 1094 
     | 
    
         
            +
                        label2auth[residue3d.label] = residue3d.auth
         
     | 
| 
      
 1095 
     | 
    
         
            +
             
     | 
| 
      
 1096 
     | 
    
         
            +
                    def unify_nt(nt: Residue) -> Residue:
         
     | 
| 
      
 1097 
     | 
    
         
            +
                        if nt.auth is not None and nt.label is not None:
         
     | 
| 
      
 1098 
     | 
    
         
            +
                            return nt
         
     | 
| 
      
 1099 
     | 
    
         
            +
                        if nt.auth is not None:
         
     | 
| 
      
 1100 
     | 
    
         
            +
                            return Residue(label=auth2label.get(nt.auth, None), auth=nt.auth)
         
     | 
| 
      
 1101 
     | 
    
         
            +
                        if nt.label is not None:
         
     | 
| 
      
 1102 
     | 
    
         
            +
                            return Residue(label=nt.label, auth=label2auth.get(nt.label, None))
         
     | 
| 
      
 1103 
     | 
    
         
            +
                        return nt
         
     | 
| 
      
 1104 
     | 
    
         
            +
             
     | 
| 
      
 1105 
     | 
    
         
            +
                    base_pairs_new = []
         
     | 
| 
      
 1106 
     | 
    
         
            +
                    for base_pair in base_pairs:
         
     | 
| 
      
 1107 
     | 
    
         
            +
                        nt1 = unify_nt(base_pair.nt1)
         
     | 
| 
      
 1108 
     | 
    
         
            +
                        nt2 = unify_nt(base_pair.nt2)
         
     | 
| 
      
 1109 
     | 
    
         
            +
                        saenger = base_pair.saenger or Saenger.from_leontis_westhof(
         
     | 
| 
      
 1110 
     | 
    
         
            +
                            auth2residue3d[nt1.auth].one_letter_name,
         
     | 
| 
      
 1111 
     | 
    
         
            +
                            auth2residue3d[nt2.auth].one_letter_name,
         
     | 
| 
      
 1112 
     | 
    
         
            +
                            base_pair.lw,
         
     | 
| 
      
 1113 
     | 
    
         
            +
                        )
         
     | 
| 
      
 1114 
     | 
    
         
            +
                        if (
         
     | 
| 
      
 1115 
     | 
    
         
            +
                            nt1 != base_pair.nt1
         
     | 
| 
      
 1116 
     | 
    
         
            +
                            or nt2 != base_pair.nt2
         
     | 
| 
      
 1117 
     | 
    
         
            +
                            or saenger != base_pair.saenger
         
     | 
| 
      
 1118 
     | 
    
         
            +
                        ):
         
     | 
| 
      
 1119 
     | 
    
         
            +
                            base_pair = BasePair(nt1=nt1, nt2=nt2, lw=base_pair.lw, saenger=saenger)
         
     | 
| 
      
 1120 
     | 
    
         
            +
                        base_pairs_new.append(base_pair)
         
     | 
| 
      
 1121 
     | 
    
         
            +
             
     | 
| 
      
 1122 
     | 
    
         
            +
                    stackings_new = []
         
     | 
| 
      
 1123 
     | 
    
         
            +
                    for stacking in stackings:
         
     | 
| 
      
 1124 
     | 
    
         
            +
                        nt1 = unify_nt(stacking.nt1)
         
     | 
| 
      
 1125 
     | 
    
         
            +
                        nt2 = unify_nt(stacking.nt2)
         
     | 
| 
      
 1126 
     | 
    
         
            +
                        if nt1 != stacking.nt1 or nt2 != stacking.nt2:
         
     | 
| 
      
 1127 
     | 
    
         
            +
                            stacking = Stacking(nt1=nt1, nt2=nt2, topology=stacking.topology)
         
     | 
| 
      
 1128 
     | 
    
         
            +
                        stackings_new.append(stacking)
         
     | 
| 
      
 1129 
     | 
    
         
            +
             
     | 
| 
      
 1130 
     | 
    
         
            +
                    base_ribose_interactions_new = []
         
     | 
| 
      
 1131 
     | 
    
         
            +
                    for base_ribose in base_ribose_interactions:
         
     | 
| 
      
 1132 
     | 
    
         
            +
                        nt1 = unify_nt(base_ribose.nt1)
         
     | 
| 
      
 1133 
     | 
    
         
            +
                        nt2 = unify_nt(base_ribose.nt2)
         
     | 
| 
      
 1134 
     | 
    
         
            +
                        if nt1 != base_ribose.nt1 or nt2 != base_ribose.nt2:
         
     | 
| 
      
 1135 
     | 
    
         
            +
                            base_ribose = BaseRibose(nt1=nt1, nt2=nt2, br=base_ribose.br)
         
     | 
| 
      
 1136 
     | 
    
         
            +
                        base_ribose_interactions_new.append(base_ribose)
         
     | 
| 
      
 1137 
     | 
    
         
            +
             
     | 
| 
      
 1138 
     | 
    
         
            +
                    base_phosphate_interactions_new = []
         
     | 
| 
      
 1139 
     | 
    
         
            +
                    for base_phosphate in base_phosphate_interactions:
         
     | 
| 
      
 1140 
     | 
    
         
            +
                        nt1 = unify_nt(base_phosphate.nt1)
         
     | 
| 
      
 1141 
     | 
    
         
            +
                        nt2 = unify_nt(base_phosphate.nt2)
         
     | 
| 
      
 1142 
     | 
    
         
            +
                        if nt1 != base_phosphate.nt1 or nt2 != base_phosphate.nt2:
         
     | 
| 
      
 1143 
     | 
    
         
            +
                            base_phosphate = BasePhosphate(nt1=nt1, nt2=nt2, bph=base_phosphate.bph)
         
     | 
| 
      
 1144 
     | 
    
         
            +
                        base_phosphate_interactions_new.append(base_phosphate)
         
     | 
| 
      
 1145 
     | 
    
         
            +
             
     | 
| 
      
 1146 
     | 
    
         
            +
                    other_interactions_new = []
         
     | 
| 
      
 1147 
     | 
    
         
            +
                    for other_interaction in other_interactions:
         
     | 
| 
      
 1148 
     | 
    
         
            +
                        nt1 = unify_nt(other_interaction.nt1)
         
     | 
| 
      
 1149 
     | 
    
         
            +
                        nt2 = unify_nt(other_interaction.nt2)
         
     | 
| 
      
 1150 
     | 
    
         
            +
                        if nt1 != other_interaction.nt1 or nt2 != other_interaction.nt2:
         
     | 
| 
      
 1151 
     | 
    
         
            +
                            other_interaction = OtherInteraction(nt1=nt1, nt2=nt2)
         
     | 
| 
      
 1152 
     | 
    
         
            +
                        other_interactions_new.append(other_interaction)
         
     | 
| 
      
 1153 
     | 
    
         
            +
             
     | 
| 
      
 1154 
     | 
    
         
            +
                    return cls(
         
     | 
| 
      
 1155 
     | 
    
         
            +
                        base_pairs=base_pairs_new,
         
     | 
| 
      
 1156 
     | 
    
         
            +
                        stackings=stackings_new,
         
     | 
| 
      
 1157 
     | 
    
         
            +
                        base_ribose_interactions=base_ribose_interactions_new,
         
     | 
| 
      
 1158 
     | 
    
         
            +
                        base_phosphate_interactions=base_phosphate_interactions_new,
         
     | 
| 
      
 1159 
     | 
    
         
            +
                        other_interactions=other_interactions_new,
         
     | 
| 
      
 1160 
     | 
    
         
            +
                    )
         
     | 
| 
      
 1161 
     | 
    
         
            +
             
     | 
| 
       1065 
1162 
     | 
    
         | 
| 
       1066 
1163 
     | 
    
         
             
            @dataclass(frozen=True, order=True)
         
     | 
| 
       1067 
1164 
     | 
    
         
             
            class InterStemParameters:
         
     | 
| 
         @@ -1,8 +1,8 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            rnapolis/adapter.py,sha256= 
     | 
| 
      
 1 
     | 
    
         
            +
            rnapolis/adapter.py,sha256=0Awt6owSeGcWq8kgLtkDv19suhrmcJgQip_Hi4Y3tK4,48513
         
     | 
| 
       2 
2 
     | 
    
         
             
            rnapolis/aligner.py,sha256=o7rQyjAZ3n4VXcnSPY3HVB8nLNRkVbl552O3NVh0mfg,3429
         
     | 
| 
       3 
     | 
    
         
            -
            rnapolis/annotator.py,sha256= 
     | 
| 
      
 3 
     | 
    
         
            +
            rnapolis/annotator.py,sha256=HA2hfEUXdmBElObqRlASAB1FgkysjiHgwMTjEhsDiDE,30277
         
     | 
| 
       4 
4 
     | 
    
         
             
            rnapolis/clashfinder.py,sha256=AC9_tIx7QIk57sELq_aKfU1u3UMOXbgcccQeGHhMR6c,8517
         
     | 
| 
       5 
     | 
    
         
            -
            rnapolis/common.py,sha256= 
     | 
| 
      
 5 
     | 
    
         
            +
            rnapolis/common.py,sha256=hamlW892ZF5A0dSWsl7cOCZqOpbVQMgXjVPYDFzk3pE,36347
         
     | 
| 
       6 
6 
     | 
    
         
             
            rnapolis/component_A.csv,sha256=koirS-AwUZwoYGItT8yn3wS6Idvmh2FANfTQcOS_xh8,2897
         
     | 
| 
       7 
7 
     | 
    
         
             
            rnapolis/component_C.csv,sha256=NtvsAu_YrUgTjzZm3j4poW4IZ99x3dPARB09XVIiMCc,2803
         
     | 
| 
       8 
8 
     | 
    
         
             
            rnapolis/component_G.csv,sha256=Z5wl8OnHRyx4XhTyBiWgRZiEvmZXhoxtVRH8bn6Vxf0,2898
         
     | 
| 
         @@ -22,9 +22,9 @@ rnapolis/tertiary_v2.py,sha256=SgijTv0bPqMJwsMqyQk0O8QAnS2Ozk45vk8igxt9hRs,38001 
     | 
|
| 
       22 
22 
     | 
    
         
             
            rnapolis/transformer.py,sha256=aC0nBmHHJf5TyLvBIV57Jj3tlwpvHbPo347opfAOlQA,3844
         
     | 
| 
       23 
23 
     | 
    
         
             
            rnapolis/unifier.py,sha256=2ge7IB9FdRgzSAiVD39U_ciwtdDJ2fGzf8mUIudbrqY,5820
         
     | 
| 
       24 
24 
     | 
    
         
             
            rnapolis/util.py,sha256=IdquFO3PV1_KDqodjupzm0Rqvgy0CeSzxGHaGEHYXVU,543
         
     | 
| 
       25 
     | 
    
         
            -
            rnapolis-0.10. 
     | 
| 
       26 
     | 
    
         
            -
            rnapolis-0.10. 
     | 
| 
       27 
     | 
    
         
            -
            rnapolis-0.10. 
     | 
| 
       28 
     | 
    
         
            -
            rnapolis-0.10. 
     | 
| 
       29 
     | 
    
         
            -
            rnapolis-0.10. 
     | 
| 
       30 
     | 
    
         
            -
            rnapolis-0.10. 
     | 
| 
      
 25 
     | 
    
         
            +
            rnapolis-0.10.5.dist-info/licenses/LICENSE,sha256=ZGRu12MzCgbYA-Lt8MyBlmjvPZh7xfiD5u5wBx0enq4,1066
         
     | 
| 
      
 26 
     | 
    
         
            +
            rnapolis-0.10.5.dist-info/METADATA,sha256=LbY2r44uwiIoVASkHv1_TAwwKIOCi8Az33PDuTs7gdg,54611
         
     | 
| 
      
 27 
     | 
    
         
            +
            rnapolis-0.10.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
         
     | 
| 
      
 28 
     | 
    
         
            +
            rnapolis-0.10.5.dist-info/entry_points.txt,sha256=MZMWnYBUYnis-zWDmFfuA5yXtU3W5YdQrm5HA5LrkeM,474
         
     | 
| 
      
 29 
     | 
    
         
            +
            rnapolis-0.10.5.dist-info/top_level.txt,sha256=LcO18koxZcWoJ21KDRRRo_tyIbmXL5z61dPitZpy8yc,9
         
     | 
| 
      
 30 
     | 
    
         
            +
            rnapolis-0.10.5.dist-info/RECORD,,
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     |