Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RNAdist/dashboard/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def get_navbar():

dbc.Collapse(
[
dbc.NavItem(dbc.NavLink(f"{page['name']}", href=page["relative_path"], id={"type": f"nav-item", "index": idx}), className="p-1") for
dbc.NavItem(dbc.NavLink(f"{page['name']}", href=page["relative_path"], id={"type": f"nav-item", "index": idx}), className="p-1 nav-link-white") for
idx, page in enumerate(dash.page_registry.values())
],
is_open=False,
Expand Down
20 changes: 18 additions & 2 deletions RNAdist/dashboard/assets/custom.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions RNAdist/dashboard/assets/tableFix.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
background: #fff;
}

.nav-link {
color: white !important;
}

.warning {
border-left: 4px solid var(--bs-info);
background-color: var(--bs-info-bg);
padding: 10px;
margin: 10px 0;
border-radius: 4px;
}


.dash-spreadsheet-container .dash-spreadsheet-inner table .dash-cell.active {
background-color: inherit !important;
Expand Down
29 changes: 25 additions & 4 deletions RNAdist/dashboard/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,29 @@

This is the RNAdist Webserver used to calculate nucleotide distances on the ensemble of RNA secondary structures.

In the Navbar at the top you can find and Input field to set your session token. Everything you compute here will be
stored using this token. If you want to access your data later store your token somewhere.
## What does it do
The thermodynamic ensemble of RNA secondary structures refers to the collection of all possible conformations an RNA
molecule can adopt, each associated with a specific probability determined by its free energy.

Note that data will be stored no longer than 7 days and there is the possibility that it gets deleted even earlier
depending on website traffic. Further all our jobs will be public. Meaning everyone that knows your token can access it.
Each RNA secondary structure can be represented as a graph, where nucleotides are nodes and connections are edges.
For simplicity, both backbone links and hydrogen bonds between base pairs are assigned an edge distance of 1, allowing
the structure to be analyzed using standard graph-theoretical methods.

By sampling structures from the RNA thermodynamic ensemble, one can compute the distances between any two nucleotides
$i$ and $j$ across the sampled graphs. This generates a distribution of distances, reflecting how often different spatial
separations occur in the ensemble and providing insights into the flexibility and connectivity of the RNA molecule.


## How to use
Use the Navbar at the top to enter your session token. All computations will be associated with this token, so make
sure to save it if you want to access your data later.

Next, go to the [**Submission**](/submission) page to enter your RNA sequence and folding/sampling parameters.
Once your job is complete, it will appear as "finished" in the submissions table.

Finally, visit the [**Visualization**](/visualization) page to explore nucleotide distance distributions and view the
sampled RNA structures.
<div class="warning">
<strong>Warning:</strong> Note that data will be stored no longer than 7 days and there is the possibility that it gets deleted even earlier
depending on website traffic. Further all our jobs will be public. Meaning everyone that knows your token can access it.
</div>
2 changes: 1 addition & 1 deletion RNAdist/dashboard/pages/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def welcome_layout(text):
[
html.Div(
[
dcc.Markdown(text, dangerously_allow_html=True, ),
dcc.Markdown(text, dangerously_allow_html=True, mathjax=True),
]
)
]
Expand Down
3 changes: 2 additions & 1 deletion RNAdist/dashboard/pages/visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,8 @@ def plot_histo(seq_hash, i, j, switch):
fig = plot_distances_with_running_j(matrix, i-1, mfe=mfe)
fig.update_layout(legend=dict(orientation="h"))
else:
fig = distance_histo_from_matrix(matrix, i-1, j-1)
fig = distance_histo_from_matrix(matrix, i-1, j-1, vertical_spacing=0, row_heights=[0.8, 0.2])
fig.update_layout(showlegend=False)
fig.update_layout({"margin": {"b": 20, "r": 10, "t": 10, "l": 10}})
if not switch:
fig.update_layout(DARK_LAYOUT)
Expand Down
50 changes: 43 additions & 7 deletions RNAdist/plots/sampling_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import re
import time

from plotly.subplots import make_subplots


def empty_figure(annotation: str = None):
fig = go.Figure()
Expand Down Expand Up @@ -39,18 +41,52 @@ def empty_figure(annotation: str = None):
)
return fig

def distance_histo_from_matrix(distances, i, j, color:str ="#00a082"):
fig = go.Figure()
def distance_histo_from_matrix(distances, i, j, color:str ="#00a082", **kwargs):
total_counts = distances[0, 0, 0]

hist = distances[i, j]
q1 = histogram_quantile(hist, 0.25, total_counts)
median = histogram_quantile(hist, 0.5, total_counts)
q3 = histogram_quantile(hist, 0.75, total_counts)
iqr = q3 - q1
d_min = hist.nonzero()[0].min()
d_max = hist.nonzero()[0].max()
lower_whisker = max(d_min, q1 - 1.5 * iqr)
upper_whisker = min(d_max, q3 + 1.5 * iqr)
x = np.arange(hist.shape[-1])
weighted_sum = np.sum(hist * x)
ed = weighted_sum / total_counts

fig = make_subplots(rows=2, shared_xaxes=True, **kwargs)
fig.add_trace(
go.Bar(
x=np.arange(distances.shape[-1]),
y=distances[i, j] / distances[i, j].sum(),
x=x,
y=hist / hist.sum(),
marker=dict(color=color),
)
name="Histogram",
),
row=1, col=1
)
fig.add_trace(
go.Box(
lowerfence=[float(lower_whisker)],
q1=[float(q1)],
median=[float(median)],
q3=[float(q3)],
upperfence=[float(upper_whisker)],
mean=[float(ed)],
name=f'Box',
marker=dict(color=color),
y=["Distribution"],
boxpoints=False # hide individual points
),
row=2, col=1
)
fig.update_layout(
xaxis=dict(title="Distance [nt]"),
yaxis=dict(title="Probability")
xaxis2=dict(title="Distance [nt]", showgrid=True),
xaxis=dict(showgrid=True),
yaxis=dict(title="Probability", showgrid=True),
yaxis2=dict(showticklabels=False),
)
return fig

Expand Down
Loading