RNApolis 0.6.2__py3-none-any.whl → 0.7.0__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 +537 -0
- {rnapolis-0.6.2.dist-info → rnapolis-0.7.0.dist-info}/METADATA +1 -1
- {rnapolis-0.6.2.dist-info → rnapolis-0.7.0.dist-info}/RECORD +7 -6
- {rnapolis-0.6.2.dist-info → rnapolis-0.7.0.dist-info}/entry_points.txt +1 -0
- {rnapolis-0.6.2.dist-info → rnapolis-0.7.0.dist-info}/WHEEL +0 -0
- {rnapolis-0.6.2.dist-info → rnapolis-0.7.0.dist-info}/licenses/LICENSE +0 -0
- {rnapolis-0.6.2.dist-info → rnapolis-0.7.0.dist-info}/top_level.txt +0 -0
rnapolis/adapter.py
ADDED
@@ -0,0 +1,537 @@
|
|
1
|
+
#! /usr/bin/env python
|
2
|
+
import argparse
|
3
|
+
import csv
|
4
|
+
import logging
|
5
|
+
import os
|
6
|
+
from enum import Enum
|
7
|
+
from typing import Dict, List, Optional, Tuple
|
8
|
+
|
9
|
+
import orjson
|
10
|
+
|
11
|
+
from rnapolis.common import (
|
12
|
+
BR,
|
13
|
+
BaseInteractions,
|
14
|
+
BasePair,
|
15
|
+
BasePhosphate,
|
16
|
+
BaseRibose,
|
17
|
+
BPh,
|
18
|
+
BpSeq,
|
19
|
+
LeontisWesthof,
|
20
|
+
OtherInteraction,
|
21
|
+
Residue,
|
22
|
+
ResidueAuth,
|
23
|
+
Stacking,
|
24
|
+
StackingTopology,
|
25
|
+
Structure2D,
|
26
|
+
)
|
27
|
+
from rnapolis.parser import read_3d_structure
|
28
|
+
from rnapolis.tertiary import Mapping2D3D, Structure3D
|
29
|
+
from rnapolis.util import handle_input_file
|
30
|
+
|
31
|
+
|
32
|
+
class ExternalTool(Enum):
|
33
|
+
FR3D = "fr3d"
|
34
|
+
DSSR = "dssr"
|
35
|
+
|
36
|
+
|
37
|
+
logging.basicConfig(level=os.getenv("LOGLEVEL", "INFO").upper())
|
38
|
+
|
39
|
+
|
40
|
+
def parse_unit_id(nt: str) -> Residue:
|
41
|
+
"""Parse FR3D unit ID format into a Residue object."""
|
42
|
+
fields = nt.split("|")
|
43
|
+
icode = fields[7] if len(fields) >= 8 and fields[7] != "" else None
|
44
|
+
auth = ResidueAuth(fields[2], int(fields[4]), icode, fields[3])
|
45
|
+
return Residue(None, auth)
|
46
|
+
|
47
|
+
|
48
|
+
def unify_classification(fr3d_name: str) -> tuple:
|
49
|
+
"""Convert FR3D classification to internal format."""
|
50
|
+
original_name = fr3d_name # Keep for logging
|
51
|
+
|
52
|
+
# Handle 'n' prefix (e.g., ncWW -> cWW, ns55 -> s55)
|
53
|
+
if fr3d_name.startswith("n"):
|
54
|
+
fr3d_name = fr3d_name[1:]
|
55
|
+
logging.debug(
|
56
|
+
f"Detected 'n' prefix: removed from {original_name} -> {fr3d_name}"
|
57
|
+
)
|
58
|
+
|
59
|
+
# Handle alternative base pairs with 'a' suffix (e.g., cWWa -> cWW)
|
60
|
+
if len(fr3d_name) >= 3 and fr3d_name.endswith("a"):
|
61
|
+
fr3d_name = fr3d_name[:-1] # Remove the 'a' suffix
|
62
|
+
logging.debug(
|
63
|
+
f"Detected alternative base pair: removed 'a' suffix from {original_name} -> {fr3d_name}"
|
64
|
+
)
|
65
|
+
|
66
|
+
# Handle backbone interactions: 0BR, 1BR, ... 9BR for base-ribose
|
67
|
+
if len(fr3d_name) == 3 and fr3d_name[1:] == "BR" and fr3d_name[0].isdigit():
|
68
|
+
try:
|
69
|
+
br_type = f"_{fr3d_name[0]}"
|
70
|
+
return ("base-ribose", BR[br_type])
|
71
|
+
except (ValueError, KeyError):
|
72
|
+
logging.debug(f"Unknown base-ribose interaction: {original_name}")
|
73
|
+
return ("other", None)
|
74
|
+
|
75
|
+
# Handle backbone interactions: 0BPh, 1BPh, ... 9BPh for base-phosphate
|
76
|
+
if len(fr3d_name) == 4 and fr3d_name[1:] == "BPh" and fr3d_name[0].isdigit():
|
77
|
+
try:
|
78
|
+
bph_type = f"_{fr3d_name[0]}"
|
79
|
+
return ("base-phosphate", BPh[bph_type])
|
80
|
+
except (ValueError, KeyError):
|
81
|
+
logging.debug(f"Unknown base-phosphate interaction: {original_name}")
|
82
|
+
return ("other", None)
|
83
|
+
|
84
|
+
# Handle the stacking notation from direct FR3D service (s33, s35, s53, s55)
|
85
|
+
if (
|
86
|
+
len(fr3d_name) == 3
|
87
|
+
and fr3d_name.startswith("s")
|
88
|
+
and fr3d_name[1] in ("3", "5")
|
89
|
+
and fr3d_name[2] in ("3", "5")
|
90
|
+
):
|
91
|
+
if fr3d_name == "s33":
|
92
|
+
return ("stacking", StackingTopology.downward)
|
93
|
+
if fr3d_name == "s55":
|
94
|
+
return ("stacking", StackingTopology.upward)
|
95
|
+
if fr3d_name == "s35":
|
96
|
+
return ("stacking", StackingTopology.outward)
|
97
|
+
if fr3d_name == "s53":
|
98
|
+
return ("stacking", StackingTopology.inward)
|
99
|
+
|
100
|
+
# Handle the cWW style notation from direct FR3D service output
|
101
|
+
# Support both uppercase and lowercase edge names (e.g., cWW, cww, tHS, ths, tSs, etc.)
|
102
|
+
if len(fr3d_name) == 3 and fr3d_name[0].lower() in ("c", "t"):
|
103
|
+
try:
|
104
|
+
# Convert to the format expected by LeontisWesthof
|
105
|
+
edge_type = fr3d_name[0].lower() # c or t
|
106
|
+
edge1 = fr3d_name[1].upper() # W, H, S (convert to uppercase)
|
107
|
+
edge2 = fr3d_name[2].upper() # W, H, S (convert to uppercase)
|
108
|
+
|
109
|
+
lw_format = f"{edge_type}{edge1}{edge2}"
|
110
|
+
return ("base-pair", LeontisWesthof[lw_format])
|
111
|
+
except KeyError:
|
112
|
+
logging.debug(
|
113
|
+
f"Fr3d unknown interaction from service: {original_name} -> {fr3d_name}"
|
114
|
+
)
|
115
|
+
return ("other", None)
|
116
|
+
|
117
|
+
# Handle other classifications with different formatting
|
118
|
+
logging.debug(f"Fr3d unknown interaction: {fr3d_name}")
|
119
|
+
return ("other", None)
|
120
|
+
|
121
|
+
|
122
|
+
def _process_interaction_line(
|
123
|
+
line: str,
|
124
|
+
interactions_data: Dict[str, list],
|
125
|
+
):
|
126
|
+
"""
|
127
|
+
Process a single interaction line and add it to the appropriate list.
|
128
|
+
|
129
|
+
Args:
|
130
|
+
line: The tab-separated interaction line
|
131
|
+
interactions_data: Dictionary containing all interaction lists
|
132
|
+
|
133
|
+
Returns:
|
134
|
+
True if successfully processed, False otherwise
|
135
|
+
"""
|
136
|
+
try:
|
137
|
+
# Split by tabs and get the first three fields
|
138
|
+
parts = line.split("\t")
|
139
|
+
if len(parts) < 3:
|
140
|
+
logging.warning(f"Invalid interaction line format: {line}")
|
141
|
+
return False
|
142
|
+
|
143
|
+
nt1 = parts[0]
|
144
|
+
interaction_type = parts[1]
|
145
|
+
nt2 = parts[2]
|
146
|
+
|
147
|
+
nt1_residue = parse_unit_id(nt1)
|
148
|
+
nt2_residue = parse_unit_id(nt2)
|
149
|
+
|
150
|
+
# Convert the interaction type to our internal format
|
151
|
+
interaction_category, classification = unify_classification(interaction_type)
|
152
|
+
|
153
|
+
# Add to the appropriate list based on the interaction category
|
154
|
+
if interaction_category == "base-pair":
|
155
|
+
interactions_data["base_pairs"].append(
|
156
|
+
BasePair(nt1_residue, nt2_residue, classification, None)
|
157
|
+
)
|
158
|
+
elif interaction_category == "stacking":
|
159
|
+
interactions_data["stackings"].append(
|
160
|
+
Stacking(nt1_residue, nt2_residue, classification)
|
161
|
+
)
|
162
|
+
elif interaction_category == "base-ribose":
|
163
|
+
interactions_data["base_ribose_interactions"].append(
|
164
|
+
BaseRibose(nt1_residue, nt2_residue, classification)
|
165
|
+
)
|
166
|
+
elif interaction_category == "base-phosphate":
|
167
|
+
interactions_data["base_phosphate_interactions"].append(
|
168
|
+
BasePhosphate(nt1_residue, nt2_residue, classification)
|
169
|
+
)
|
170
|
+
elif interaction_category == "other":
|
171
|
+
interactions_data["other_interactions"].append(
|
172
|
+
OtherInteraction(nt1_residue, nt2_residue)
|
173
|
+
)
|
174
|
+
|
175
|
+
return True
|
176
|
+
except (ValueError, IndexError) as e:
|
177
|
+
logging.warning(f"Error parsing interaction: {e}")
|
178
|
+
return False
|
179
|
+
|
180
|
+
|
181
|
+
def match_dssr_name_to_residue(
|
182
|
+
structure3d: Structure3D, nt_id: Optional[str]
|
183
|
+
) -> Optional[Residue]:
|
184
|
+
if nt_id is not None:
|
185
|
+
nt_id = nt_id.split(":")[-1]
|
186
|
+
for residue in structure3d.residues:
|
187
|
+
if residue.full_name == nt_id:
|
188
|
+
return residue
|
189
|
+
logging.warning(f"Failed to find residue {nt_id}")
|
190
|
+
return None
|
191
|
+
|
192
|
+
|
193
|
+
def match_dssr_lw(lw: Optional[str]) -> Optional[LeontisWesthof]:
|
194
|
+
return LeontisWesthof[lw] if lw in dir(LeontisWesthof) else None
|
195
|
+
|
196
|
+
|
197
|
+
def parse_dssr_output(
|
198
|
+
file_path: str, structure3d: Structure3D, model: Optional[int] = None
|
199
|
+
) -> BaseInteractions:
|
200
|
+
"""
|
201
|
+
Parse DSSR JSON output and convert to BaseInteractions.
|
202
|
+
|
203
|
+
Args:
|
204
|
+
file_path: Path to DSSR JSON output file
|
205
|
+
structure3d: The 3D structure parsed from PDB/mmCIF
|
206
|
+
model: Model number to use (if None, use first model)
|
207
|
+
|
208
|
+
Returns:
|
209
|
+
BaseInteractions object containing the interactions found by DSSR
|
210
|
+
"""
|
211
|
+
base_pairs: List[BasePair] = []
|
212
|
+
stackings: List[Stacking] = []
|
213
|
+
|
214
|
+
with open(file_path) as f:
|
215
|
+
dssr = orjson.loads(f.read())
|
216
|
+
|
217
|
+
# Handle multi-model files
|
218
|
+
if "models" in dssr:
|
219
|
+
if model is None and dssr.get("models"):
|
220
|
+
# If model is None, use the first model
|
221
|
+
dssr = dssr.get("models")[0].get("parameters", {})
|
222
|
+
else:
|
223
|
+
# Otherwise find the specified model
|
224
|
+
for result in dssr.get("models", []):
|
225
|
+
if result.get("model", None) == model:
|
226
|
+
dssr = result.get("parameters", {})
|
227
|
+
break
|
228
|
+
|
229
|
+
for pair in dssr.get("pairs", []):
|
230
|
+
nt1 = match_dssr_name_to_residue(structure3d, pair.get("nt1", None))
|
231
|
+
nt2 = match_dssr_name_to_residue(structure3d, pair.get("nt2", None))
|
232
|
+
lw = match_dssr_lw(pair.get("LW", None))
|
233
|
+
|
234
|
+
if nt1 is not None and nt2 is not None and lw is not None:
|
235
|
+
base_pairs.append(BasePair(nt1, nt2, lw, None))
|
236
|
+
|
237
|
+
for stack in dssr.get("stacks", []):
|
238
|
+
nts = [
|
239
|
+
match_dssr_name_to_residue(structure3d, nt)
|
240
|
+
for nt in stack.get("nts_long", "").split(",")
|
241
|
+
]
|
242
|
+
for i in range(1, len(nts)):
|
243
|
+
nt1 = nts[i - 1]
|
244
|
+
nt2 = nts[i]
|
245
|
+
if nt1 is not None and nt2 is not None:
|
246
|
+
stackings.append(Stacking(nt1, nt2, None))
|
247
|
+
|
248
|
+
return BaseInteractions(base_pairs, stackings, [], [], [])
|
249
|
+
|
250
|
+
|
251
|
+
def parse_external_output(
|
252
|
+
file_path: str, tool: ExternalTool, structure3d: Structure3D
|
253
|
+
) -> BaseInteractions:
|
254
|
+
"""
|
255
|
+
Parse the output from an external tool (FR3D, DSSR, etc.) and convert it to BaseInteractions.
|
256
|
+
|
257
|
+
Args:
|
258
|
+
file_path: Path to the external tool output file
|
259
|
+
tool: The external tool that generated the output
|
260
|
+
structure3d: The 3D structure parsed from PDB/mmCIF
|
261
|
+
|
262
|
+
Returns:
|
263
|
+
BaseInteractions object containing the interactions found by the external tool
|
264
|
+
"""
|
265
|
+
if tool == ExternalTool.FR3D:
|
266
|
+
return parse_fr3d_output(file_path)
|
267
|
+
elif tool == ExternalTool.DSSR:
|
268
|
+
return parse_dssr_output(file_path, structure3d)
|
269
|
+
else:
|
270
|
+
raise ValueError(f"Unsupported external tool: {tool}")
|
271
|
+
|
272
|
+
|
273
|
+
def parse_fr3d_output(file_path: str) -> BaseInteractions:
|
274
|
+
"""
|
275
|
+
Parse FR3D output file and convert to BaseInteractions.
|
276
|
+
|
277
|
+
Args:
|
278
|
+
file_path: Path to a concatenated FR3D output file containing basepair, stacking,
|
279
|
+
and backbone interactions
|
280
|
+
|
281
|
+
Returns:
|
282
|
+
BaseInteractions object containing the interactions found by FR3D
|
283
|
+
"""
|
284
|
+
# Initialize the interaction data dictionary
|
285
|
+
interactions_data = {
|
286
|
+
"base_pairs": [],
|
287
|
+
"stackings": [],
|
288
|
+
"base_ribose_interactions": [],
|
289
|
+
"base_phosphate_interactions": [],
|
290
|
+
"other_interactions": [],
|
291
|
+
}
|
292
|
+
|
293
|
+
# Process the concatenated file
|
294
|
+
with open(file_path, "r") as f:
|
295
|
+
for line in f:
|
296
|
+
line = line.strip()
|
297
|
+
if not line or line.startswith("#"):
|
298
|
+
continue
|
299
|
+
|
300
|
+
# Process every non-empty, non-comment line
|
301
|
+
_process_interaction_line(line, interactions_data)
|
302
|
+
|
303
|
+
# Return a BaseInteractions object with all the processed interactions
|
304
|
+
return BaseInteractions(
|
305
|
+
interactions_data["base_pairs"],
|
306
|
+
interactions_data["stackings"],
|
307
|
+
interactions_data["base_ribose_interactions"],
|
308
|
+
interactions_data["base_phosphate_interactions"],
|
309
|
+
interactions_data["other_interactions"],
|
310
|
+
)
|
311
|
+
|
312
|
+
|
313
|
+
def process_external_tool_output(
|
314
|
+
structure3d: Structure3D,
|
315
|
+
external_file_path: str,
|
316
|
+
tool: ExternalTool,
|
317
|
+
model: Optional[int] = None,
|
318
|
+
find_gaps: bool = False,
|
319
|
+
all_dot_brackets: bool = False,
|
320
|
+
) -> Tuple[Structure2D, List[str]]:
|
321
|
+
"""
|
322
|
+
Process external tool output and create a secondary structure representation.
|
323
|
+
|
324
|
+
This function can be used from other code to process external tool outputs
|
325
|
+
and get a Structure2D object with the secondary structure information.
|
326
|
+
|
327
|
+
Args:
|
328
|
+
structure3d: The 3D structure parsed from PDB/mmCIF
|
329
|
+
external_file_path: Path to the external tool output file
|
330
|
+
tool: The external tool that generated the output (FR3D, DSSR, etc.)
|
331
|
+
model: Model number to use (if None, use first model)
|
332
|
+
find_gaps: Whether to detect gaps in the structure
|
333
|
+
all_dot_brackets: Whether to return all possible dot-bracket notations
|
334
|
+
|
335
|
+
Returns:
|
336
|
+
A tuple containing the Structure2D object and a list of dot-bracket notations
|
337
|
+
"""
|
338
|
+
# Parse external tool output
|
339
|
+
base_interactions = parse_external_output(external_file_path, tool, structure3d)
|
340
|
+
|
341
|
+
# Extract secondary structure using the external tool's interactions
|
342
|
+
return extract_secondary_structure_from_external(
|
343
|
+
structure3d, base_interactions, model, find_gaps, all_dot_brackets
|
344
|
+
)
|
345
|
+
|
346
|
+
|
347
|
+
def extract_secondary_structure_from_external(
|
348
|
+
tertiary_structure: Structure3D,
|
349
|
+
base_interactions: BaseInteractions,
|
350
|
+
model: Optional[int] = None,
|
351
|
+
find_gaps: bool = False,
|
352
|
+
all_dot_brackets: bool = False,
|
353
|
+
) -> Tuple[Structure2D, List[str]]:
|
354
|
+
"""
|
355
|
+
Create a secondary structure representation using interactions from an external tool.
|
356
|
+
|
357
|
+
Args:
|
358
|
+
tertiary_structure: The 3D structure parsed from PDB/mmCIF
|
359
|
+
base_interactions: Interactions parsed from external tool output
|
360
|
+
model: Model number to use (if None, use all models)
|
361
|
+
find_gaps: Whether to detect gaps in the structure
|
362
|
+
all_dot_brackets: Whether to return all possible dot-bracket notations
|
363
|
+
|
364
|
+
Returns:
|
365
|
+
A tuple containing the Structure2D object and a list of dot-bracket notations
|
366
|
+
"""
|
367
|
+
mapping = Mapping2D3D(
|
368
|
+
tertiary_structure,
|
369
|
+
base_interactions.basePairs,
|
370
|
+
base_interactions.stackings,
|
371
|
+
find_gaps,
|
372
|
+
)
|
373
|
+
stems, single_strands, hairpins, loops = mapping.bpseq.elements
|
374
|
+
structure2d = Structure2D(
|
375
|
+
base_interactions,
|
376
|
+
str(mapping.bpseq),
|
377
|
+
mapping.dot_bracket,
|
378
|
+
mapping.extended_dot_bracket,
|
379
|
+
stems,
|
380
|
+
single_strands,
|
381
|
+
hairpins,
|
382
|
+
loops,
|
383
|
+
)
|
384
|
+
if all_dot_brackets:
|
385
|
+
return structure2d, mapping.all_dot_brackets
|
386
|
+
else:
|
387
|
+
return structure2d, [structure2d.dotBracket]
|
388
|
+
|
389
|
+
|
390
|
+
def write_json(path: str, structure2d: BaseInteractions):
|
391
|
+
with open(path, "wb") as f:
|
392
|
+
f.write(orjson.dumps(structure2d))
|
393
|
+
|
394
|
+
|
395
|
+
def write_csv(path: str, structure2d: Structure2D):
|
396
|
+
with open(path, "w") as f:
|
397
|
+
writer = csv.writer(f)
|
398
|
+
writer.writerow(["nt1", "nt2", "type", "classification-1", "classification-2"])
|
399
|
+
for base_pair in structure2d.baseInteractions.basePairs:
|
400
|
+
writer.writerow(
|
401
|
+
[
|
402
|
+
base_pair.nt1.full_name,
|
403
|
+
base_pair.nt2.full_name,
|
404
|
+
"base pair",
|
405
|
+
base_pair.lw.value,
|
406
|
+
(
|
407
|
+
base_pair.saenger.value or ""
|
408
|
+
if base_pair.saenger is not None
|
409
|
+
else ""
|
410
|
+
),
|
411
|
+
]
|
412
|
+
)
|
413
|
+
for stacking in structure2d.baseInteractions.stackings:
|
414
|
+
writer.writerow(
|
415
|
+
[
|
416
|
+
stacking.nt1.full_name,
|
417
|
+
stacking.nt2.full_name,
|
418
|
+
"stacking",
|
419
|
+
stacking.topology.value if stacking.topology is not None else "",
|
420
|
+
"",
|
421
|
+
]
|
422
|
+
)
|
423
|
+
for base_phosphate in structure2d.baseInteractions.basePhosphateInteractions:
|
424
|
+
writer.writerow(
|
425
|
+
[
|
426
|
+
base_phosphate.nt1.full_name,
|
427
|
+
base_phosphate.nt2.full_name,
|
428
|
+
"base-phosphate interaction",
|
429
|
+
base_phosphate.bph.value if base_phosphate.bph is not None else "",
|
430
|
+
"",
|
431
|
+
]
|
432
|
+
)
|
433
|
+
for base_ribose in structure2d.baseInteractions.baseRiboseInteractions:
|
434
|
+
writer.writerow(
|
435
|
+
[
|
436
|
+
base_ribose.nt1.full_name,
|
437
|
+
base_ribose.nt2.full_name,
|
438
|
+
"base-ribose interaction",
|
439
|
+
base_ribose.br.value if base_ribose.br is not None else "",
|
440
|
+
"",
|
441
|
+
]
|
442
|
+
)
|
443
|
+
for other in structure2d.baseInteractions.otherInteractions:
|
444
|
+
writer.writerow(
|
445
|
+
[
|
446
|
+
other.nt1.full_name,
|
447
|
+
other.nt2.full_name,
|
448
|
+
"other interaction",
|
449
|
+
"",
|
450
|
+
"",
|
451
|
+
]
|
452
|
+
)
|
453
|
+
|
454
|
+
|
455
|
+
def write_bpseq(path: str, bpseq: BpSeq):
|
456
|
+
with open(path, "w") as f:
|
457
|
+
f.write(str(bpseq))
|
458
|
+
|
459
|
+
|
460
|
+
def main():
|
461
|
+
parser = argparse.ArgumentParser()
|
462
|
+
parser.add_argument("input", help="Path to PDB or mmCIF file")
|
463
|
+
parser.add_argument(
|
464
|
+
"--external",
|
465
|
+
required=True,
|
466
|
+
help="Path to external tool output file (FR3D, DSSR, etc.)",
|
467
|
+
)
|
468
|
+
parser.add_argument(
|
469
|
+
"--tool",
|
470
|
+
choices=[t.value for t in ExternalTool],
|
471
|
+
required=True,
|
472
|
+
help="External tool that generated the output file",
|
473
|
+
)
|
474
|
+
parser.add_argument(
|
475
|
+
"-a",
|
476
|
+
"--all-dot-brackets",
|
477
|
+
action="store_true",
|
478
|
+
help="(optional) print all dot-brackets, not only optimal one (exclusive with -e/--extended)",
|
479
|
+
)
|
480
|
+
parser.add_argument("-b", "--bpseq", help="(optional) path to output BPSEQ file")
|
481
|
+
parser.add_argument("-c", "--csv", help="(optional) path to output CSV file")
|
482
|
+
parser.add_argument(
|
483
|
+
"-j",
|
484
|
+
"--json",
|
485
|
+
help="(optional) path to output JSON file",
|
486
|
+
)
|
487
|
+
parser.add_argument(
|
488
|
+
"-e",
|
489
|
+
"--extended",
|
490
|
+
action="store_true",
|
491
|
+
help="(optional) if set, the program will print extended secondary structure to the standard output",
|
492
|
+
)
|
493
|
+
parser.add_argument(
|
494
|
+
"-f",
|
495
|
+
"--find-gaps",
|
496
|
+
action="store_true",
|
497
|
+
help="(optional) if set, the program will detect gaps and break the PDB chain into two or more strands",
|
498
|
+
)
|
499
|
+
parser.add_argument("-d", "--dot", help="(optional) path to output DOT file")
|
500
|
+
args = parser.parse_args()
|
501
|
+
|
502
|
+
file = handle_input_file(args.input)
|
503
|
+
structure3d = read_3d_structure(file, None)
|
504
|
+
|
505
|
+
# Process external tool output and get secondary structure
|
506
|
+
structure2d, dot_brackets = process_external_tool_output(
|
507
|
+
structure3d,
|
508
|
+
args.external,
|
509
|
+
ExternalTool(args.tool),
|
510
|
+
None,
|
511
|
+
args.find_gaps,
|
512
|
+
args.all_dot_brackets,
|
513
|
+
)
|
514
|
+
|
515
|
+
if args.csv:
|
516
|
+
write_csv(args.csv, structure2d)
|
517
|
+
|
518
|
+
if args.json:
|
519
|
+
write_json(args.json, structure2d)
|
520
|
+
|
521
|
+
if args.bpseq:
|
522
|
+
write_bpseq(args.bpseq, structure2d.bpseq)
|
523
|
+
|
524
|
+
if args.extended:
|
525
|
+
print(structure2d.extendedDotBracket)
|
526
|
+
elif args.all_dot_brackets:
|
527
|
+
for dot_bracket in dot_brackets:
|
528
|
+
print(dot_bracket)
|
529
|
+
else:
|
530
|
+
print(structure2d.dotBracket)
|
531
|
+
|
532
|
+
if args.dot:
|
533
|
+
print(BpSeq.from_string(structure2d.bpseq).graphviz)
|
534
|
+
|
535
|
+
|
536
|
+
if __name__ == "__main__":
|
537
|
+
main()
|
@@ -1,3 +1,4 @@
|
|
1
|
+
rnapolis/adapter.py,sha256=n7f5e8dbP-grJI7L9GycYAbMjpMvTuUM5aXiiCqG91k,18239
|
1
2
|
rnapolis/aligner.py,sha256=o7rQyjAZ3n4VXcnSPY3HVB8nLNRkVbl552O3NVh0mfg,3429
|
2
3
|
rnapolis/annotator.py,sha256=hRRzRmneYxbg2tvwVHMWLfzmJb4szV0JL_6EOC09Gwg,22101
|
3
4
|
rnapolis/clashfinder.py,sha256=AC9_tIx7QIk57sELq_aKfU1u3UMOXbgcccQeGHhMR6c,8517
|
@@ -18,9 +19,9 @@ rnapolis/tertiary_v2.py,sha256=I1uyHWIUePNGO5m-suoL4ibtz02qAJUMvYm0BUKUygY,22480
|
|
18
19
|
rnapolis/transformer.py,sha256=aC0nBmHHJf5TyLvBIV57Jj3tlwpvHbPo347opfAOlQA,3844
|
19
20
|
rnapolis/unifier.py,sha256=DR1_IllgaAYT9_FUE6XC9B-2wgqbBHs2D1MjyZT2j2g,5438
|
20
21
|
rnapolis/util.py,sha256=IdquFO3PV1_KDqodjupzm0Rqvgy0CeSzxGHaGEHYXVU,543
|
21
|
-
rnapolis-0.
|
22
|
-
rnapolis-0.
|
23
|
-
rnapolis-0.
|
24
|
-
rnapolis-0.
|
25
|
-
rnapolis-0.
|
26
|
-
rnapolis-0.
|
22
|
+
rnapolis-0.7.0.dist-info/licenses/LICENSE,sha256=ZGRu12MzCgbYA-Lt8MyBlmjvPZh7xfiD5u5wBx0enq4,1066
|
23
|
+
rnapolis-0.7.0.dist-info/METADATA,sha256=Rrnbq7pKHvcPKcHPp9nWjAZZ6x8PflF2WaJCTxaRgbo,54537
|
24
|
+
rnapolis-0.7.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
25
|
+
rnapolis-0.7.0.dist-info/entry_points.txt,sha256=D630mec6slaw_QMmzDNeBIy7p0pTtuOGnu8xTjmx8VA,404
|
26
|
+
rnapolis-0.7.0.dist-info/top_level.txt,sha256=LcO18koxZcWoJ21KDRRRo_tyIbmXL5z61dPitZpy8yc,9
|
27
|
+
rnapolis-0.7.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|