Skip to content

Instantly share code, notes, and snippets.

@RuKrei
Created January 24, 2021 20:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RuKrei/5262770d5bf2d2d3a78decb22190a152 to your computer and use it in GitHub Desktop.
Save RuKrei/5262770d5bf2d2d3a78decb22190a152 to your computer and use it in GitHub Desktop.
MWE copypaster: plotly to mne.Report()
"""
Thank you all for looking into this.
What I am working on here is a pipeline to aid in diagnosis of epilepsy in a clinical setting (Long term video EEG monitoring).
The goal is to extract Annotations of an EEG-file and visualize them in a useful manner.
The number of Annotations might be anything between only a few to a few hundred. Data should be visualized and also shown in
tabular form.
Plotly is an obvious choice, since its defaults handle this dynamic setting well.
I copypasted some parts of the code in order to reproduce a visualization from the pipeline.
"""
import mne
from mne import Report
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# helper funcitons
def generate_random_events(tmin, tmax, nr_events=100):
# simulate extracted Events from raw file
type = ["e-", "s-", "t-"]
side = ["-l", "-r", "-b"]
e_names = ["Theta", "Suppression", "Something_frontal", "Something_temporal", "Something_parietal",
"Spikes", "Delta", "Shrap waves", "Beta", "Evolution"]
s_names = ["Figure4", "Jerks", "Numbness", "Arrest", "OAA", "Hypermotor", "Alien limb",
"Fumbling", "Version", "Head turn"]
t_name = "TestEvent"
time_from_onset = np.random.randint(tmin, tmax, nr_events)
time_from_onset.reshape(1,-1)
description = []
for i in range(nr_events):
t = np.random.randint(3, size=1)
s = np.random.randint(3, size=1)
n = np.random.randint(10, size=1)
if str(type[t[0]]) == "e-":
de = str(type[t[0]]) + str(e_names[n[0]]) + str(side[s[0]])
elif str(type[t[0]]) == "s-":
de = str(type[t[0]]) + str(s_names[n[0]]) + str(side[s[0]])
else:
de = str(type[t[0]]) + t_name + str(side[s[0]])
description.append(de)
return (description, time_from_onset)
def generate_df_with_pseudoevents(tmin, tmax, nr_events=150, source=None):
# put events into pd.DataFrame
description, time_from_onset = generate_random_events(tmin=tmin, tmax=tmax, nr_events=nr_events)
pseudoevents = dict()
pseudoevents["description"] = description
pseudoevents["time_from_onset"] = time_from_onset
df = pd.DataFrame(pseudoevents)
df.loc[:, "source"] = source
cols = list(df)
cols.insert(0, cols.pop(cols.index('source')))
df = df.loc[:, cols]
return df
def extract_ordered_groups(df, edf="df"):
df = df.drop_duplicates(subset=["description"], keep="first")
print(f"\nThe following Event-Groups were extracted from the file {edf}\n\n\n")
e_events = df[df["description"].str.startswith("e-")]
e_events["order_of_occurence"] = (np.arange(len(e_events.axes[0])) +1).astype(int)
print("EEG-Events: \n\n", e_events, "\n\n")
s_events = df[df["description"].str.startswith("s-")]
s_events["order_of_occurence"] = (np.arange(len(s_events.axes[0])) +1).astype(int)
print("Semiology-Events: \n\n", s_events, "\n\n")
t_events = df[~df["description"].str.startswith("s-")]
t_events = t_events[~df["description"].str.startswith("e-")]
t_events["order_of_occurence"] = (np.arange(len(t_events.axes[0])) +1).astype(int)
print("Clinical Testing - Events: \n\n", t_events, "\n\n")
return e_events, s_events, t_events
def plot_interactive_subplot_with_table(df=None, eeg=None, semio=None, testing=None, title=None):
xaxis_title="Time in seconds (from seizure onset)"
fig = make_subplots(rows=5, cols=1, shared_xaxes="all",
specs=[[{"type": "table"}],
[{"type": "scatter"}],
[{"type": "scatter"}],
[{"type": "scatter"}],
[{"type": "scatter"}]],
subplot_titles=("Events", "EEG", "Semiology", "Testing", "All events"),
row_width=[0.1, 0.1, 0.1, 0.1, 0.8])
# Add traces
# data
fig.add_trace(go.Table(
header=dict(
values=df.columns[:], font=dict(size=10)),
cells=dict(
values=[df[i].tolist() for i in df.columns[:]],
align="left")
),
row=1, col=1)
# scatter plots
x_axis = df["time_from_onset"]
y_axis = np.ones_like(x_axis)
# eeg
times, labels = extract_lab_sec(eeg)
fig.add_trace(go.Scatter(x=times, y=y_axis,
mode='markers', #mode="markers+text"
hoverinfo="name+x+text",
name='EEG',
text=labels,
marker_symbol="diamond"), row=2, col=1)
# semio
times, labels = extract_lab_sec(semio)
fig.add_trace(go.Scatter(x=times, y=y_axis,
mode='markers',
name='Semiology',
text=labels,
marker_symbol="x"), row=3, col=1)
# testing
times, labels = extract_lab_sec(testing)
fig.add_trace(go.Scatter(x=times, y=y_axis,
mode='markers',
name='Testing',
text=labels,
marker_symbol="circle"), row=4, col=1)
# grand average
times, labels = extract_lab_sec(df)
fig.add_trace(go.Scatter(x=times, y=y_axis,
mode='markers',
name='All events',
text=labels,
marker_symbol="hexagon2-open-dot"), row=5, col=1)
fig.update_layout(title=title, yaxis_title="")
fig.update_xaxes(rangeslider={"visible":True}, title={"text":xaxis_title}, row=5)
fig.update_yaxes(visible=False, showticklabels=False)
fig.update_layout(width=1200, height=1000)
return fig
def extract_lab_sec(df):
times = df["time_from_onset"]
labels = df["description"]
return times, labels
# ------------------------------------------------------------------
# main part
df1 = generate_df_with_pseudoevents(tmin=-20, tmax=90, nr_events=300, source="df1")
e_events, s_events, t_events = extract_ordered_groups(df1, edf="df1")
fig = plot_interactive_subplot_with_table(df1, e_events, s_events, t_events, title="Random events")
# show figure?
fig.show()
# report
report = Report(subject="Test Subject", title="Event summary")
# add to report - non of them work
fig.to_html("fig.html")
report.add_htmls_to_section("fig.html", section="test", captions="test_add_htmls")
report.add_custom_css(fig)
report.save("Report.html")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment