pyfurnace 0.0.1__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.
Files changed (113) hide show
  1. pyfurnace/__init__.py +5 -0
  2. pyfurnace/__main__.py +33 -0
  3. pyfurnace/app/__init__.py +0 -0
  4. pyfurnace/app/pages/0_Home.py +37 -0
  5. pyfurnace/app/pages/1_Design.py +77 -0
  6. pyfurnace/app/pages/2_Generate.py +378 -0
  7. pyfurnace/app/pages/3_Convert.py +212 -0
  8. pyfurnace/app/pages/4_Prepare.py +565 -0
  9. pyfurnace/app/pages/__init__.py +0 -0
  10. pyfurnace/app/static/logo_hr.png +0 -0
  11. pyfurnace/app/static/logo_lr.png +0 -0
  12. pyfurnace/app/static/logo_text.png +0 -0
  13. pyfurnace/app/static/logo_text_hr.png +0 -0
  14. pyfurnace/app/static/pyfurnace.svg +692 -0
  15. pyfurnace/app/streamlit_app.py +12 -0
  16. pyfurnace/app/utils/__init__.py +211 -0
  17. pyfurnace/app/utils/commands/__init__.py +24 -0
  18. pyfurnace/app/utils/commands/aptamers_command.py +58 -0
  19. pyfurnace/app/utils/commands/connections_command.py +88 -0
  20. pyfurnace/app/utils/commands/dovetail_command.py +93 -0
  21. pyfurnace/app/utils/commands/general_edit_command.py +49 -0
  22. pyfurnace/app/utils/commands/kissing_loops_command.py +123 -0
  23. pyfurnace/app/utils/commands/motif_command.py +7 -0
  24. pyfurnace/app/utils/commands/stem_command.py +70 -0
  25. pyfurnace/app/utils/commands/structural_command.py +44 -0
  26. pyfurnace/app/utils/commands/tetraloop_command.py +45 -0
  27. pyfurnace/app/utils/design_functions.py +1424 -0
  28. pyfurnace/app/utils/motifs_icons.py +34 -0
  29. pyfurnace/app/utils/st_fixed_container.py +59 -0
  30. pyfurnace/app/utils/template_functions.py +71 -0
  31. pyfurnace/design/__init__.py +3 -0
  32. pyfurnace/design/core/__init__.py +14 -0
  33. pyfurnace/design/core/basepair.py +214 -0
  34. pyfurnace/design/core/callback.py +103 -0
  35. pyfurnace/design/core/coordinates_3d.py +1195 -0
  36. pyfurnace/design/core/motif.py +2771 -0
  37. pyfurnace/design/core/origami.py +1570 -0
  38. pyfurnace/design/core/position.py +284 -0
  39. pyfurnace/design/core/sequence.py +534 -0
  40. pyfurnace/design/core/strand.py +1924 -0
  41. pyfurnace/design/core/symbols.py +953 -0
  42. pyfurnace/design/motifs/__init__.py +25 -0
  43. pyfurnace/design/motifs/aptamers.py +229 -0
  44. pyfurnace/design/motifs/conf_files/Bend90.dat +12 -0
  45. pyfurnace/design/motifs/conf_files/Bend90_2.dat +7 -0
  46. pyfurnace/design/motifs/conf_files/Biotin.dat +36 -0
  47. pyfurnace/design/motifs/conf_files/BranchedKissingLoop.dat +10 -0
  48. pyfurnace/design/motifs/conf_files/BranchedKissingLoop_1.dat +11 -0
  49. pyfurnace/design/motifs/conf_files/BranchedKissingLoop_2.dat +5 -0
  50. pyfurnace/design/motifs/conf_files/BranchedKissingLoop_3.dat +12 -0
  51. pyfurnace/design/motifs/conf_files/Broccoli_1.dat +21 -0
  52. pyfurnace/design/motifs/conf_files/Broccoli_2.dat +26 -0
  53. pyfurnace/design/motifs/conf_files/Ispinach_1.dat +25 -0
  54. pyfurnace/design/motifs/conf_files/Ispinach_2.dat +20 -0
  55. pyfurnace/design/motifs/conf_files/KissingLoop120.dat +12 -0
  56. pyfurnace/design/motifs/conf_files/KissingLoop120_2.dat +12 -0
  57. pyfurnace/design/motifs/conf_files/KissingLoop180.dat +12 -0
  58. pyfurnace/design/motifs/conf_files/KissingLoop180_2.dat +12 -0
  59. pyfurnace/design/motifs/conf_files/L7Ae_1.dat +10 -0
  60. pyfurnace/design/motifs/conf_files/L7Ae_2.dat +130 -0
  61. pyfurnace/design/motifs/conf_files/L7Ae_2.top +3 -0
  62. pyfurnace/design/motifs/conf_files/LambdaTurn_1.dat +13 -0
  63. pyfurnace/design/motifs/conf_files/LambdaTurn_2.dat +11 -0
  64. pyfurnace/design/motifs/conf_files/MS2.dat +151 -0
  65. pyfurnace/design/motifs/conf_files/MS2.top +3 -0
  66. pyfurnace/design/motifs/conf_files/MalachiteGreen.dat +41 -0
  67. pyfurnace/design/motifs/conf_files/MalachiteGreenShort_1.dat +11 -0
  68. pyfurnace/design/motifs/conf_files/MalachiteGreenShort_2.dat +17 -0
  69. pyfurnace/design/motifs/conf_files/Mango.dat +34 -0
  70. pyfurnace/design/motifs/conf_files/PP7.dat +266 -0
  71. pyfurnace/design/motifs/conf_files/PP7.top +4 -0
  72. pyfurnace/design/motifs/conf_files/Pepper_1.dat +29 -0
  73. pyfurnace/design/motifs/conf_files/Pepper_2.dat +22 -0
  74. pyfurnace/design/motifs/conf_files/Pip3.dat +17 -0
  75. pyfurnace/design/motifs/conf_files/Pip3_mut1.dat +17 -0
  76. pyfurnace/design/motifs/conf_files/Pip3_mut3.dat +17 -0
  77. pyfurnace/design/motifs/conf_files/Pip3_mut5.dat +17 -0
  78. pyfurnace/design/motifs/conf_files/Streptavidin.dat +63 -0
  79. pyfurnace/design/motifs/conf_files/TAR_TAT.dat +50 -0
  80. pyfurnace/design/motifs/conf_files/TAR_TAT.top +3 -0
  81. pyfurnace/design/motifs/conf_files/TetraLoop.dat +9 -0
  82. pyfurnace/design/motifs/conf_files/ThreeWayJunction_1.dat +11 -0
  83. pyfurnace/design/motifs/conf_files/ThreeWayJunction_2.dat +10 -0
  84. pyfurnace/design/motifs/conf_files/ThreeWayJunction_3.dat +8 -0
  85. pyfurnace/design/motifs/conf_files/Thrombin_exosite1.dat +61 -0
  86. pyfurnace/design/motifs/conf_files/Thrombin_exosite2.dat +316 -0
  87. pyfurnace/design/motifs/conf_files/Thrombin_exosite2.top +4 -0
  88. pyfurnace/design/motifs/dovetail.py +244 -0
  89. pyfurnace/design/motifs/kissing_loops.py +417 -0
  90. pyfurnace/design/motifs/loops.py +60 -0
  91. pyfurnace/design/motifs/stem.py +192 -0
  92. pyfurnace/design/motifs/structural.py +58 -0
  93. pyfurnace/design/utils/__init__.py +2 -0
  94. pyfurnace/design/utils/motif_lib.py +69 -0
  95. pyfurnace/design/utils/origami_lib.py +175 -0
  96. pyfurnace/generate/__init__.py +2 -0
  97. pyfurnace/generate/pk_utils.py +178 -0
  98. pyfurnace/generate/road.py +291 -0
  99. pyfurnace/generate/road_bin/revolvr.pl +2503 -0
  100. pyfurnace/generate/road_bin/viennarna_funcs.py +44 -0
  101. pyfurnace/generate/utils.py +60 -0
  102. pyfurnace/generate/viennarna.py +87 -0
  103. pyfurnace/prepare/__init__.py +1 -0
  104. pyfurnace/prepare/oxdna_inputs/MC_relax.txt +46 -0
  105. pyfurnace/prepare/oxdna_inputs/MD_equil.txt +50 -0
  106. pyfurnace/prepare/oxdna_inputs/MD_prod.txt +49 -0
  107. pyfurnace/prepare/oxdna_inputs/MD_relax.txt +52 -0
  108. pyfurnace/prepare/oxdna_sim.py +142 -0
  109. pyfurnace-0.0.1.dist-info/METADATA +186 -0
  110. pyfurnace-0.0.1.dist-info/RECORD +113 -0
  111. pyfurnace-0.0.1.dist-info/WHEEL +5 -0
  112. pyfurnace-0.0.1.dist-info/licenses/LICENSE +674 -0
  113. pyfurnace-0.0.1.dist-info/top_level.txt +1 -0
pyfurnace/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ from .design import *
2
+
3
+ __all__ = ["motifs", "strand", "origami", "symbols"]
4
+ __version__ = "0.0.1"
5
+
pyfurnace/__main__.py ADDED
@@ -0,0 +1,33 @@
1
+ import os
2
+ import sys
3
+ import pathlib
4
+ import subprocess
5
+
6
+ def main():
7
+ config_options = {'theme.base': 'light',
8
+ 'theme.font': "monospace",
9
+ 'theme.primaryColor': "#00856A",
10
+ 'server.enableStaticServing': True,
11
+ 'logger.level': 'error',
12
+ 'global.showWarningOnDirectExecution': False,
13
+ 'client.toolbarMode': "minimal",
14
+ }
15
+ config_str = ' '.join([f'--{key} "{value}"'
16
+ for key, value in config_options.items()])
17
+
18
+ app_path = str(pathlib.Path(__file__).parent.resolve()/'app'/'streamlit_app.py')
19
+
20
+ ### COPY THE PYTHON PATH AND ADD RNAfold
21
+ python_path = sys.executable # Get path to the current Python interpreter
22
+ python_dir = os.path.dirname(python_path)
23
+
24
+ # Prepend it to PATH, to make sure the correct Python is used
25
+ env = os.environ.copy()
26
+ env["PATH"] = python_dir + os.pathsep + os.environ["PATH"]
27
+
28
+ subprocess.run(f'streamlit run "{app_path}" {config_str}',
29
+ shell=True,
30
+ env=env)
31
+
32
+ if __name__ == "__main__":
33
+ main()
File without changes
@@ -0,0 +1,37 @@
1
+ import streamlit as st
2
+ from utils import load_logo
3
+
4
+ if __name__ == '__main__':
5
+ load_logo()
6
+
7
+ st.write("# Hello and Welcome to pyFuRNAce!")
8
+
9
+ st.write('Design and generate RNA nanostructures in few simple steps.')
10
+
11
+ st.page_link("pages/1_Design.py",
12
+ label=":orange[Design:]",
13
+ icon=":material/draw:")
14
+
15
+ st.markdown("- Design your RNA nanostructure and download it as "
16
+ "textfile/python script.")
17
+
18
+ st.page_link("pages/2_Generate.py",
19
+ label=":orange[Generate:]",
20
+ icon=":material/network_node:")
21
+
22
+ st.markdown("- Generate the RNA sequence that matches the desired dot-bracket"
23
+ " notation for the nanostructure.")
24
+
25
+ st.page_link("pages/3_Convert.py",
26
+ label=":orange[Template:]",
27
+ icon=":material/genetics:")
28
+
29
+ st.markdown("- Prepare the DNA template for you RNA Origami, search subsequences "
30
+ "and search for dimers.")
31
+
32
+ st.page_link("pages/4_Prepare.py",
33
+ label=":orange[Prepare:]",
34
+ icon=":material/sync_alt:")
35
+
36
+ st.markdown("- Design primers for your DNA template or prepare the Origami for "
37
+ "OxDNA simulation.")
@@ -0,0 +1,77 @@
1
+ import streamlit as st
2
+ import matplotlib.pyplot as plt
3
+
4
+ ### My modules
5
+ from utils import check_import_pyfurnace, load_logo, save_origami
6
+ check_import_pyfurnace()
7
+ import utils.design_functions as des_func
8
+ from utils.st_fixed_container import sticky_container
9
+
10
+
11
+ if __name__ == "__main__":
12
+ load_logo()
13
+ ### initiate the session state
14
+ des_func.initiate_session_state()
15
+ st.header('Design',
16
+ help='Design your RNA nanostructure and '
17
+ 'download it as textfile/python script.')
18
+
19
+ ### make the general options for the RNA origami
20
+ des_func.origami_general_options(st.session_state.origami,
21
+ expanded=False)
22
+
23
+ cols = st.columns([1.3, 1.3] + [1] * 2 + [2, 1.3],
24
+ vertical_alignment='center')
25
+ with cols[0]:
26
+ with st.popover("Make a simple origami",
27
+ use_container_width=False,
28
+ help='Start by creating a simple origami rather than '
29
+ 'starting from scratch'):
30
+ des_func.simple_origami()
31
+
32
+ with cols[2]:
33
+ st.write('OxView 3D colormap:')
34
+
35
+ with cols[3]:
36
+ cmap = st.selectbox('OxView 3D colormap:',
37
+ ['Reds', None] + plt.colormaps(),
38
+ key='colormap',
39
+ label_visibility='collapsed',
40
+ help='Change the color of the OxView visualization.')
41
+ st.session_state.oxview_colormap = cmap
42
+ with cols[5]:
43
+ grad = st.toggle('Color gradient path',
44
+ key='grad',
45
+ help='Toggle the gradient color scheme for the nucleotides')
46
+ st.session_state.gradient = grad
47
+
48
+
49
+ def motif_menu_expander():
50
+ with st.expander("**Add motifs to the origami:**", expanded=True):
51
+ des_func.make_motif_menu(st.session_state.origami)
52
+
53
+ if st.session_state.motif_menu_sticky:
54
+ with sticky_container(mode="top", border=False):
55
+ motif_menu_expander()
56
+ view_opt = des_func.origami_select_display()
57
+ else:
58
+ motif_menu_expander()
59
+ view_opt = des_func.origami_select_display()
60
+
61
+ ### select the render mode
62
+ if not st.session_state.origami:
63
+ st.success('The origami is empty, add a motif!')
64
+ st.stop()
65
+ else:
66
+ des_func.origami_build_view(view_opt)
67
+
68
+ ### display the dot-bracket notation and sequence constraints
69
+ # and link to the Generate page
70
+
71
+ des_func.display_structure_sequence()
72
+
73
+ ### Download the RNA origami structure
74
+ save_origami()
75
+
76
+
77
+
@@ -0,0 +1,378 @@
1
+ from functools import partial
2
+ import streamlit as st
3
+ from colour import Color
4
+ import os
5
+ import warnings
6
+
7
+ ### My modules
8
+ from utils import (check_import_pyfurnace,
9
+ load_logo,
10
+ save_origami,
11
+ copy_to_clipboard)
12
+ check_import_pyfurnace()
13
+ from pyfurnace.generate import generate_road, fold_p
14
+
15
+ def format_text(text):
16
+ return "```\n" + text + "\n```"
17
+
18
+ def forna_options(lenght):
19
+ ### checkboxes for the options
20
+ col1, col2, col3 = st.columns(3, vertical_alignment='bottom')
21
+ with col1:
22
+ st.session_state.zoomable = st.checkbox("Zoomable",
23
+ value=True,
24
+ help = """Enable zooming in and out the structure""")
25
+ with col2:
26
+ st.session_state.animation = st.checkbox("Interact",
27
+ value=False,
28
+ help = """Enable interaction with the structure""")
29
+ with col3:
30
+ st.session_state.node_label = st.checkbox("Label",
31
+ value=True,
32
+ help = """Show the nucleotide label""")
33
+
34
+ ### second row of options
35
+ col1, col2, col3 = st.columns(3, vertical_alignment='center')
36
+ with col1:
37
+ ### color scheme options
38
+ scheme_options = ["sequence",
39
+ "structure",
40
+ "positions",
41
+ "color range",
42
+ "custom"]
43
+ st.session_state.color_scheme = st.selectbox("Color scheme",
44
+ scheme_options,
45
+ index=1)
46
+
47
+ with col2:
48
+ st.session_state.height = st.slider("Frame height",
49
+ min_value=10,
50
+ max_value=800,
51
+ value=300,
52
+ help = """Set the height of the frame""")
53
+
54
+ with col3:
55
+ st.session_state.label_interval = st.slider("Label every",
56
+ min_value=0,
57
+ max_value=max(lenght, 10),
58
+ value=min(lenght, 10),
59
+ help = """Show the nucleotide number every n nucleotides""")
60
+
61
+ st.session_state.color_text = ''
62
+ st.session_state.colors = {}
63
+
64
+ ### color scheme based on the sequence
65
+ if st.session_state.color_scheme == "color range":
66
+ st.session_state.color_scheme = "custom"
67
+
68
+ with col2: # start color
69
+ first = st.color_picker("Start color", "#ff0000")
70
+
71
+ with col3: # end color
72
+ last = st.color_picker("End color", "#00ff00")
73
+
74
+ # create the colors range
75
+ first = Color(first)
76
+ last = Color(last)
77
+
78
+ color_range = [first] + list(first.range_to(last, lenght))
79
+
80
+ # save the colors in the session state and create the colors string
81
+ for i, c in enumerate(color_range):
82
+ st.session_state.colors[i] = c.hex
83
+ st.session_state.color_text += str(i) + ":" + c.hex + " "
84
+
85
+ ### custom colors for each nucleotide
86
+ elif st.session_state.color_scheme == "custom":
87
+
88
+ with col2: # select nucleotide index
89
+ index = st.number_input("Select nucleotide index", 1, lenght, 1)
90
+
91
+ with col3: # select color
92
+ color = st.color_picker("Select a color", "#ffffff")
93
+
94
+ # save the color in the session state
95
+ st.session_state.colors[index] = color
96
+
97
+ # create the colors string
98
+ for i, c in st.session_state.colors.items():
99
+ st.session_state.color_text += str(i) + ":" + c + " "
100
+
101
+ ### display the custom colors
102
+ else:
103
+ st.session_state.color_text = None
104
+
105
+ def generate_sequence():
106
+ if not structure:
107
+ st.error('No structure input given')
108
+ return
109
+
110
+ if not sequence_constraint:
111
+ st.error('No sequence constraint input given')
112
+ return
113
+
114
+ # Initialize the UI elements
115
+ progress_bar = st.empty()
116
+ output_status = st.empty()
117
+
118
+ # Initialize the progress bar
119
+ progress_bar.progress(0, "Initializing...")
120
+
121
+ def callback_forna(structure, sequence, step, stage_name, n_stage):
122
+ # Update the progress bar
123
+ progress_bar.progress(n_stage, text = stage_name)
124
+ output_status.markdown(format_text(f"Structure:\n{structure}"
125
+ f"\nSequence:\n{sequence}"
126
+ f"\nSpool:\n{step}"))
127
+
128
+ ori_txt = '\n\n'.join(st.session_state.code)
129
+ opti_sequence, zip_out = generate_road(structure,
130
+ sequence_constraint,
131
+ pseudoknot_info,
132
+ name=filename,
133
+ callback=callback_forna,
134
+ zip_directory=True,
135
+ origami_code=ori_txt,
136
+ )
137
+
138
+ st.session_state.rna_origami_seq = opti_sequence
139
+ st.session_state.rna_origami_folds = fold_p(opti_sequence)
140
+ # if there was already a zip file, remove it
141
+ if 'zip_path' in st.session_state:
142
+ if os.path.exists(st.session_state.zip_path):
143
+ os.remove(st.session_state.zip_path)
144
+ # save the new zip file
145
+ st.session_state.zip_path = zip_out
146
+
147
+ # Clear the progress bar
148
+ progress_bar.progress(1.0, text = f"Generation Completed")
149
+ output_status.empty()
150
+
151
+ if ('origami' in st.session_state
152
+ and st.session_state.origami
153
+ and len(st.session_state.origami.sequence) == len(st.session_state.rna_origami_seq)):
154
+ # try:
155
+ st.session_state.origami.sequence = st.session_state.rna_origami_seq
156
+ if 'code' in st.session_state:
157
+ code_text = 'origami.sequence = "' + st.session_state.rna_origami_seq + '"'
158
+ st.session_state.code.append(code_text)
159
+ st.success("Sequence loaded to the origami design!")
160
+ # except Exception as e:
161
+ # st.error(f"Error while loading the sequence into the origami design: {e}")
162
+
163
+
164
+ if __name__ == "__main__":
165
+ # somehow st components cause `Thread 'MainThread': missing ScriptRunContext!`
166
+ # warning when using multiprocessing
167
+ from st_forna_component import forna_component
168
+
169
+ load_logo()
170
+
171
+ ### ignore warnings
172
+ warnings.filterwarnings("ignore")
173
+
174
+ ### initialize the session state
175
+
176
+ ### Forna options
177
+ if 'zoomable' not in st.session_state:
178
+ st.session_state.zoomable = True
179
+ if 'animation' not in st.session_state:
180
+ st.session_state.animation = False
181
+ if 'editable' not in st.session_state:
182
+ st.session_state.editable = False
183
+ if 'labels' not in st.session_state:
184
+ st.session_state.node_label = True
185
+ if 'height' not in st.session_state:
186
+ st.session_state.height = 300
187
+ if 'label_interval' not in st.session_state:
188
+ st.session_state.label_interval = 10
189
+ if 'color_scheme' not in st.session_state:
190
+ st.session_state.color_scheme = "structure"
191
+ if 'color_text' not in st.session_state:
192
+ st.session_state.color_text = ''
193
+
194
+ ### RNA origami options
195
+ if 'generate_structure' not in st.session_state:
196
+ st.session_state.generate_structure = ""
197
+ if 'generate_sequence' not in st.session_state:
198
+ st.session_state.generate_sequence = ""
199
+ if 'generate_pseudoknots' not in st.session_state:
200
+ st.session_state.generate_pseudoknots = ""
201
+ if 'rna_origami_seq' not in st.session_state:
202
+ st.session_state.rna_origami_seq = ""
203
+ if 'rna_origami_folds' not in st.session_state:
204
+ st.session_state.rna_origami_folds = ()
205
+
206
+ st.header('Generate', help='Generate the RNA sequence that matches the desired dot-bracket notation (and sequence constraints) for the nanostructure.')
207
+ structure = st.text_input("RNA strucutre (dot-bracket notation)", value=st.session_state.generate_structure)
208
+ sequence_constraint = st.text_input("Sequence constraints", value=st.session_state.generate_sequence)
209
+ pseudoknot_info = st.text_input("Pseudoknot constraints (semicolon-separated)", value=st.session_state.generate_pseudoknots)
210
+
211
+ if not sequence_constraint:
212
+ sequence_constraint = "N" * len(structure.replace("&", ""))
213
+
214
+ # check if the dot-bracket notation contains multiple strands
215
+ if "&" in structure:
216
+ st.warning("Experimental: the dot-bracket notation contains multiple strands")
217
+
218
+ with st.columns([1.3, 3])[0]:
219
+ with st.popover("RNA display options", use_container_width=True):
220
+ forna_options(len(structure))
221
+
222
+ partial_forna = partial(forna_component,
223
+ height = st.session_state.height,
224
+ animation = st.session_state.animation,
225
+ zoomable = st.session_state.zoomable,
226
+ label_interval = st.session_state.label_interval,
227
+ node_label = st.session_state.node_label,
228
+ editable = st.session_state.editable,
229
+ color_scheme = st.session_state.color_scheme,
230
+ colors = st.session_state.color_text)
231
+
232
+
233
+ # # Initialize the FORNA link for the target structure
234
+ if structure:
235
+ # st.markdown("#### Target Structure")
236
+ # st.markdown(format_text(structure))
237
+ edited = partial_forna(structure = structure,
238
+ sequence = sequence_constraint,
239
+ key='target_forna')
240
+
241
+ if sequence_constraint and sequence_constraint[0] != 'G':
242
+ col1, col2, col3 = st.columns(3, vertical_alignment='bottom')
243
+ with col1:
244
+ st.warning("The RNA sequence doens't start with G.")
245
+ with col2:
246
+ new_start = st.text_input("Start the sequence with", value='GGGA',
247
+ help='The transcription of the RNA sequence often '
248
+ 'often requires at least one G at the start of the sequence.')
249
+ with col3:
250
+ if st.button('Apply the sequence start'):
251
+
252
+ seq_list = list(sequence_constraint)
253
+ # pair_map = pf.dot_bracket_to_pair_map(structure) # unnecessary
254
+
255
+ for i in range(len(new_start)):
256
+ seq_list[i] = new_start[i]
257
+ ### NOT NECESSARY
258
+ # paired = pair_map[i]
259
+ # if paired is not None:
260
+ # paired_nucl = new_start[i].translate(pf.nucl_to_pair)
261
+ # seq_list[paired] = paired_nucl
262
+
263
+ st.session_state.generate_sequence = "".join(seq_list)
264
+ st.rerun()
265
+
266
+ col1, col2 = st.columns(2, vertical_alignment='bottom')
267
+ with col1:
268
+ filename = st.text_input('Name of RNA origami', value='Origami')
269
+ with col2:
270
+ generate = False
271
+ if st.button("Generate RNA sequence"):
272
+ generate = True
273
+ if generate:
274
+ generate_sequence()
275
+
276
+
277
+ if not st.session_state.rna_origami_seq:
278
+ st.stop()
279
+
280
+ st.divider()
281
+ sequence = st.session_state.rna_origami_seq
282
+ folds = st.session_state.rna_origami_folds
283
+
284
+ diversity = round(folds[6], 1)
285
+ if diversity < 30:
286
+ diversity_text = f":green[low {diversity}]"
287
+ elif diversity < 50:
288
+ diversity_text = f":orange[medium {diversity}]"
289
+ else:
290
+ diversity_text = f":red[high {diversity}]"
291
+
292
+ cols = st.columns(4, vertical_alignment='bottom')
293
+ st.markdown("### Last Optimized sequence "
294
+ f"(ensemble diversity: {diversity_text})",
295
+ help='The ensemble diversity is the average distance between the '
296
+ 'structures in the ensemble (the set of all the possible structures '
297
+ 'that can be formed by the sequence). A lower value means that the '
298
+ 'structures are more similar to each other (and therefore more '
299
+ 'similar to the Minimum Free Energy structure). A higher value '
300
+ 'means that the structures are more diverse and there are less '
301
+ 'chances to obtain the minimum free energy structure. '
302
+ )
303
+
304
+
305
+ col1, col2 = st.columns(2)
306
+ with col1:
307
+ with st.columns(3)[1]:
308
+ st.markdown("#### MFE Structure",
309
+ help='The Minimum Free Energy (MFE) structure is the structure with '
310
+ 'the lowest free energy. It is the most stable structure that can be '
311
+ 'formed by the sequence. '
312
+ )
313
+
314
+ subcol1, subcol2 = st.columns(2)
315
+ with subcol1:
316
+ st.markdown(f'Energy: {round(folds[1], 2)} Kcal/mol')
317
+ with subcol2:
318
+ st.markdown(f'Frequency in the ensemble: {round(folds[2] * 100, 4)} %',
319
+ help = 'The MFE frequency in the ensemble is the probability of '
320
+ 'obtaining the MFE structure among all the possible structures '
321
+ 'that can be formed by the sequence.'
322
+ )
323
+ partial_forna(structure = folds[0],
324
+ sequence = sequence,
325
+ key='struct_mfe')
326
+ with col2:
327
+ with st.columns(3)[1]:
328
+ st.markdown("#### Centroid",
329
+ help='The centroid structure is the structure that is the most similar to '
330
+ 'the average structure of the ensemble. It is the closest structure to '
331
+ 'represent the average of all the possible structures that can be '
332
+ 'formed by the sequence. '
333
+ )
334
+ subcol1, subcol2 = st.columns(2)
335
+ with subcol1:
336
+ st.markdown(f'Energy: {round(folds[4], 2)} Kcal/mol')
337
+ with subcol2:
338
+ st.markdown(f'Frequency in the ensemble: {round(folds[5] * 100, 4)} %',
339
+ help = 'The centroid frequency in the ensemble is the probability of '
340
+ 'obtaining the centroid structure among all the possible structures '
341
+ 'that can be formed by the sequence.'
342
+ )
343
+ partial_forna(structure = folds[3],
344
+ sequence = sequence,
345
+ key='struct_centroid')
346
+
347
+ st.divider()
348
+
349
+ st.markdown(format_text(st.session_state.rna_origami_seq))
350
+ col1, col2, col3, col4 = st.columns(4)
351
+ with col1:
352
+ st.page_link("pages/3_Convert.py",
353
+ label=":orange[Convert the RNA to the DNA template]",
354
+ icon=":material/genetics:")
355
+ with col2:
356
+ copy_to_clipboard(folds[0], 'Structure')
357
+ with col3:
358
+ copy_to_clipboard(sequence, 'Sequence')
359
+ with col4:
360
+ with open(st.session_state.zip_path, "rb") as fp:
361
+ st.download_button("Download Optimization Files",
362
+ data=fp,
363
+ file_name = f"{filename}.zip",
364
+ mime = "application/zip",
365
+ on_click='ignore',
366
+ )
367
+
368
+ if ('origami' in st.session_state
369
+ and st.session_state.origami
370
+ and str(st.session_state.origami.sequence) == st.session_state.rna_origami_seq):
371
+
372
+ st.session_state.prepare_ind = 1
373
+ st.page_link("pages/4_Prepare.py",
374
+ label=":orange[Prepare MD simulations]",
375
+ icon=":material/sync_alt:")
376
+
377
+ save_origami(filename)
378
+