Hello everyone,
I’m trying to make my first panel app. Its supposed to be a dashboard for a study dataset to quickly skim over the data and check everything looks right for every participant and session. I use 2 pn.widgets.Select to select the participant and the session you want to look at and there are overviews for each level (so without participant selected, with participant but no session selected yet and the last one details for a session of a participant).
When switching the screens between participants and the dataset overview everything loads very fast but when selecting a session, there is like a 2.5 seconds delay and I cant figure out why and if I can reduce that. Some notes: the details page are just 4 plots which by themselves are computed within like 0.1s each. The code is down below.
I’m still very new to panel so just let me know if I’m doing something wrong and why the switching to the details page is so slow?
Thank you in advance for your help!
import matplotlib
import panel as pn
import numpy as np
from pathlib import Path
from motion_utils import plot_accelorometer_from_tsv
from edf_utils import plot_body_temp_from_edf, plot_eeg_spectrogram_from_edf
pn.extension(loading_spinner='dots')
matplotlib.use('agg')
DATASET_ROOT = Path("../BIDS/")
def get_participants():
return sorted(
p.name for p in DATASET_ROOT.glob("sub-*")
if p.is_dir()
)
def get_sessions(participant):
if participant is None:
return []
return sorted(
p.name for p in (DATASET_ROOT / participant).glob("ses-*")
if p.is_dir()
)
participant_select = pn.widgets.Select(
name="Participant",
options=[None] + get_participants(),
value=None
)
session_select = pn.widgets.Select(
name="Session",
options=[],
value=None
)
session_select.options = pn.bind(lambda p: [None] + get_sessions(p), participant_select)
session_select.disabled = pn.bind(lambda p: p is None, participant_select)
def dataset_overview():
return pn.Column(
f"## General Overview Page",
f"Number of participants: {len(get_participants())}"
)
def participant_overview(participant):
sessions = get_sessions(participant)
return pn.Column(
f"## Participant {participant}",
f"Number of sessions: {len(sessions)}",
)
def session_overview(participant, session):
session_path = DATASET_ROOT / participant / session
files = []
for path in session_path.rglob("*"):
if path.is_file():
files.append(path.relative_to(session_path))
edf_status = get_edf_status(session_path)
motion_status = get_motion_status(session_path)
return pn.Column(
f"## {participant} / {session}",
f"Files in session: {len(files)}",
pn.pane.Markdown("\n".join(f"- {f}" for f in files)),
edf_status,
motion_status,
)
def get_edf_status(session_path):
edf_status = pn.pane.Markdown("## Edf Data is missing")
edf_files = []
for path in session_path.rglob("*_eeg.edf"):
if path.is_file():
edf_files.append(path)
if len(edf_files) > 0:
eeg_left_plot = plot_eeg_spectrogram_from_edf(edf_files[0], channel_name="EEG_LEFT")
eeg_right_plot = plot_eeg_spectrogram_from_edf(edf_files[0], channel_name="EEG_RIGHT")
body_temp_plot = plot_body_temp_from_edf(edf_files[0])
edf_status = pn.Column(
pn.pane.Matplotlib(eeg_left_plot, dpi=144, sizing_mode='stretch_width'),
pn.pane.Matplotlib(eeg_right_plot, dpi=144, sizing_mode='stretch_width'),
pn.pane.Matplotlib(body_temp_plot, dpi=144, sizing_mode='stretch_width')
)
return edf_status
def get_motion_status(session_path):
motion_status = pn.pane.Markdown("## Accelerometer Data is missing")
motion_files = []
for path in session_path.rglob("*_motion.tsv"):
if path.is_file():
motion_files.append(path)
if len(motion_files) > 0:
motion_plot = plot_accelorometer_from_tsv(motion_files[0])
motion_status = pn.pane.Matplotlib(motion_plot, dpi=144, sizing_mode='stretch_width')
return motion_status
def main_view(participant, session):
if participant is None:
return dataset_overview()
if session is None:
return participant_overview(participant)
return session_overview(participant, session)
main = pn.panel(
pn.bind(main_view, participant_select, session_select),
loading_indicator=True
)
template = pn.template.FastListTemplate(
title="Dataset Explorer",
sidebar=[
pn.pane.Markdown("### Navigation"),
participant_select,
session_select,
],
main=[
main
],
)
template.servable()