From d1a22c35859db331a8f8a6002bfd5f3fd674c6f1 Mon Sep 17 00:00:00 2001 From: Caleb Weinreb Date: Tue, 6 Feb 2024 22:39:06 -0500 Subject: [PATCH 1/2] add help menu --- docs/source/api.rst | 5 +-- docs/source/index.rst | 4 +- docs/source/tutorials.rst | 83 ++------------------------------------- setup.cfg | 2 + snub/gui/help.py | 60 ++++++++++++++++++++++++++++ snub/gui/main.py | 7 ++-- 6 files changed, 75 insertions(+), 86 deletions(-) create mode 100644 snub/gui/help.py diff --git a/docs/source/api.rst b/docs/source/api.rst index f76d7c9..4137aaf 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -1,5 +1,5 @@ -Browser API -=========== +Developer API +============= snub.io ------- @@ -7,7 +7,6 @@ snub.io .. automodule:: snub.io.project :members: - .. automodule:: snub.io.manifold :members: diff --git a/docs/source/index.rst b/docs/source/index.rst index ce27546..db3f871 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -36,8 +36,10 @@ SNUB Documentation tutorials + gui + nwb - snub.io + api diff --git a/docs/source/tutorials.rst b/docs/source/tutorials.rst index 33a9c68..f7af43a 100644 --- a/docs/source/tutorials.rst +++ b/docs/source/tutorials.rst @@ -1,5 +1,5 @@ -Tutorials -========= +Project setup +============= This tutorial describes how to setup a SNUB project with video, neural activity recordings and behavioral annotations. The neural activity is used to generate a low-dimensional UMAP embedding, and we describe some of the user-interface tools that help link the embedding to single-neuron traces and to behavior. There are two example pipelines for calcium imaging and electrophysiology respectively. The input data and processed outputs from these tutorials are `available on Zenodo `_. @@ -259,80 +259,5 @@ Add a plot of mouse velocity linewidth=2) - -Using the interface -------------------- - -Start SNUB from the command line:: - - conda activate snub - snub - -Open a project -~~~~~~~~~~~~~~ - -Open your project by going to ``File > Open Project``, navigating to the project directory, and hitting ``Choose`` with the directory selected. Multiple projects can be opened at once as different tabs. Projects can also be opened by including their paths as a command line arguments:: - - snub /path/to/project1 /path/to/project2 - -.. image:: ../media/use_case0.gif - :align: center - -| - -Navigate the timeline -~~~~~~~~~~~~~~~~~~~~~ - -The brower is divided into two sections. The track-stack (on the right below) contains data-views that have time as a dimension, such as heatmaps, trace plots and spike plots. The tracks are always synchronized so that the same horizontal coordinate represents the same point in time. - -* Click/drag to change the current time. -* Use scrolls/gestures to change the visible time window. -* Use the play button and speed slider at the bottom to watch in real time -* Toggle "center playhead" to keep the current time centered -* Toggle the timeline unit between minutes:seconds and "timestemps". Timesteps are multiples of the ``min_step`` parameters in the projects config file, and can be useful for accessing specific timepoinmts (e.g. video frames) outside of SNUB. - -.. image:: ../media/use_case1.gif - :align: center - -| - -Plot activity traces -~~~~~~~~~~~~~~~~~~~~ - -By default, all heatmaps and spike plots are paired with a trace plot (set ``add_traceplot=False`` to override). - -* Right click on any row of the heatmap/spike-plot to view it in the trace plot. -* View groups of rows in more detail using the vertical zoom and shift buttons in the right-click menu. - -.. image:: ../media/use_case3.gif - :align: center - -| - -Use selections -~~~~~~~~~~~~~~ - -The panel-stack (on the left below) contains data-views such as videos, scatter plots and 3D mesh views. The video panel always displays the current frame and the scatter plot highlights any nodes that represent the current time. A useful way to relate the scatter plot and timeline views is through selections. - -* Use shift+drag to select points in the scatter view or intervals in the timeline. -* Use command/control+drag to deselect points and intervals. -* Selections are synchronized across all views. -* Selections can also be used to re-order the rows of a heatmap based on the total activity within the selected interval(s). - -.. image:: ../media/use_case2.gif - :align: center - -| - -Color the scatter plot -~~~~~~~~~~~~~~~~~~~~~~ - -Another way to probe the scatter plot is through node coloring. - -* Use right-click -> "Color by ..." to view variables of interest in the scatter plot. -* Include variables using ``variables`` and ``variable_labels`` in :py:func:`snub.io.add_scatter`. -* Bring nodes with high values to the top using right-click -> "Sort by color value". - -.. image:: ../media/use_case4.gif - :align: center - +Next: `How to use the interface `_. +""" \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 760226f..36ae1bb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,6 +42,8 @@ install_requires = dev = pytest pytest-qt + sphinx==4.4.0 + sphinx_rtd_theme==1.0.0 [options.package_data] snub.gui = icons/* diff --git a/snub/gui/help.py b/snub/gui/help.py new file mode 100644 index 0000000..1e3b7e4 --- /dev/null +++ b/snub/gui/help.py @@ -0,0 +1,60 @@ +from PyQt5.QtCore import * +from PyQt5.QtWidgets import * +from PyQt5.QtGui import * + + +def _text_section(title, text): + groupBox = QGroupBox() + layout = QVBoxLayout() + + titleLabel = QLabel(title) + titleLabel.setFont(QFont("Arial", 14, QFont.Bold)) + layout.addWidget(titleLabel) + + textlabel = QLabel(text) + textlabel.setWordWrap(True) + layout.addWidget(textlabel) + layout.addStretch() + + groupBox.setLayout(layout) + return groupBox + + +class HelpMenu: + def __init__(self, parent): + self.parent = parent + self.helpMenu = QMenu("&Help", parent) + self._setup_actions() + + def _setup_actions(self): + action = QAction("Loading data", self.parent) + action.triggered.connect(lambda: self._show_load_page()) # Correct connection + self.helpMenu.addAction(action) + + def _show_load_page(self): + dialog = QDialog(self.parent) + dialog.setWindowTitle("Loading data") + dialog.setFixedWidth(600) + dialogLayout = QVBoxLayout() + dialog.setLayout(dialogLayout) + + subtitle = "Open a SNUB project" + text = ( + "To open a SNUB project, go to File > Open Project, navigate to the project " + 'directory, and hit "Choose" with the directory selected. Multiple projects ' + "can be opened at once as different tabs. Projects can also be opened by including " + "their paths as command line argument(s) when launching SNUB." + ) + dialogLayout.addWidget(_text_section(subtitle, text)) + + subtitle = "Reload a project" + text = ( + "If a project is already open and its files have been modified outside of SNUB, " + "the project can be reloaded in the SNUB GUI by going to File > Reload Project." + ) + dialogLayout.addWidget(_text_section(subtitle, text)) + dialogLayout.addStretch() + dialog.exec_() + + def get_menu(self): + return self.helpMenu diff --git a/snub/gui/main.py b/snub/gui/main.py index ae70661..e5de228 100644 --- a/snub/gui/main.py +++ b/snub/gui/main.py @@ -6,6 +6,7 @@ from snub.gui.utils import IntervalIndex, CheckBox from snub.gui.stacks import PanelStack, TrackStack from snub.gui.tracks import TracePlot +from snub.gui.help import HelpMenu def set_style(app): @@ -345,14 +346,14 @@ def __init__(self, args): editMenu = mainMenu.addMenu("&Edit") editMenu.addAction(deselect_all) - # saveMenu = fileMenu.addMenu('&Save...') - # saveMenu.addAction(save_layout) - windowMenu = mainMenu.addMenu("&Window") layoutMenu = windowMenu.addMenu("&Layout...") layoutMenu.addAction(self.set_layout_to_cols) layoutMenu.addAction(self.set_layout_to_rows) + helpMenu = HelpMenu(self) + mainMenu.addMenu(helpMenu.get_menu()) + # try to open projects that are passed as command line arguments self.open(project_directories=args) From b203dd6693a942d6f394d316ffbe43c99b47a261 Mon Sep 17 00:00:00 2001 From: Caleb Weinreb Date: Tue, 20 Feb 2024 19:13:14 +0900 Subject: [PATCH 2/2] added help menu ad help pages --- setup.cfg | 2 + snub/gui/__init__.py | 1 + snub/gui/help.py | 60 ----------------------- snub/gui/help/heatmaps.md | 20 ++++++++ snub/gui/help/help_menu.py | 89 ++++++++++++++++++++++++++++++++++ snub/gui/help/layout.md | 14 ++++++ snub/gui/help/loading_data.md | 7 +++ snub/gui/help/scatter_plots.md | 18 +++++++ snub/gui/help/selections.md | 33 +++++++++++++ snub/gui/help/timeline.md | 14 ++++++ snub/gui/help/trace_plots.md | 19 ++++++++ snub/gui/help/video.md | 10 ++++ snub/gui/main.py | 2 +- snub/gui/panels/scatter.py | 1 + snub/gui/tracks/trace.py | 8 ++- 15 files changed, 232 insertions(+), 66 deletions(-) delete mode 100644 snub/gui/help.py create mode 100644 snub/gui/help/heatmaps.md create mode 100644 snub/gui/help/help_menu.py create mode 100644 snub/gui/help/layout.md create mode 100644 snub/gui/help/loading_data.md create mode 100644 snub/gui/help/scatter_plots.md create mode 100644 snub/gui/help/selections.md create mode 100644 snub/gui/help/timeline.md create mode 100644 snub/gui/help/trace_plots.md create mode 100644 snub/gui/help/video.md diff --git a/setup.cfg b/setup.cfg index 36ae1bb..386ed6b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -37,6 +37,8 @@ install_requires = ndx-depth-moseq pandas dandi + markdown + PyQtWebEngine [options.extras_require] dev = diff --git a/snub/gui/__init__.py b/snub/gui/__init__.py index c626a80..1a2d33b 100644 --- a/snub/gui/__init__.py +++ b/snub/gui/__init__.py @@ -1,4 +1,5 @@ from . import panels from . import stacks from . import tracks +from . import help from . import main diff --git a/snub/gui/help.py b/snub/gui/help.py deleted file mode 100644 index 1e3b7e4..0000000 --- a/snub/gui/help.py +++ /dev/null @@ -1,60 +0,0 @@ -from PyQt5.QtCore import * -from PyQt5.QtWidgets import * -from PyQt5.QtGui import * - - -def _text_section(title, text): - groupBox = QGroupBox() - layout = QVBoxLayout() - - titleLabel = QLabel(title) - titleLabel.setFont(QFont("Arial", 14, QFont.Bold)) - layout.addWidget(titleLabel) - - textlabel = QLabel(text) - textlabel.setWordWrap(True) - layout.addWidget(textlabel) - layout.addStretch() - - groupBox.setLayout(layout) - return groupBox - - -class HelpMenu: - def __init__(self, parent): - self.parent = parent - self.helpMenu = QMenu("&Help", parent) - self._setup_actions() - - def _setup_actions(self): - action = QAction("Loading data", self.parent) - action.triggered.connect(lambda: self._show_load_page()) # Correct connection - self.helpMenu.addAction(action) - - def _show_load_page(self): - dialog = QDialog(self.parent) - dialog.setWindowTitle("Loading data") - dialog.setFixedWidth(600) - dialogLayout = QVBoxLayout() - dialog.setLayout(dialogLayout) - - subtitle = "Open a SNUB project" - text = ( - "To open a SNUB project, go to File > Open Project, navigate to the project " - 'directory, and hit "Choose" with the directory selected. Multiple projects ' - "can be opened at once as different tabs. Projects can also be opened by including " - "their paths as command line argument(s) when launching SNUB." - ) - dialogLayout.addWidget(_text_section(subtitle, text)) - - subtitle = "Reload a project" - text = ( - "If a project is already open and its files have been modified outside of SNUB, " - "the project can be reloaded in the SNUB GUI by going to File > Reload Project." - ) - dialogLayout.addWidget(_text_section(subtitle, text)) - dialogLayout.addStretch() - dialog.exec_() - - def get_menu(self): - return self.helpMenu diff --git a/snub/gui/help/heatmaps.md b/snub/gui/help/heatmaps.md new file mode 100644 index 0000000..57fa60f --- /dev/null +++ b/snub/gui/help/heatmaps.md @@ -0,0 +1,20 @@ +## Heatmaps + +Heatmaps dispay time-series data using color intensity (one time-series per row). They are aligned to the [timeline](timeline.md) at the bottom of the window and can be navigated using gestures (pan and zoom). + +* **To adjust the colormap**, right click on the heatmap and select "Adjust colormap range" and enter a new min or max value. +* **For vertical zoom**, right click on the heatmap and select "Zoom in (vertical)" or "Zoom out (vertical)". Zooming is centered in the point where you clicked. We do not provide a direct way to scroll along the vertical axis, so if you are zoomed in the top rows of the heatmap and want to see the bottom rows, you will need to zoom out from the top rows and then zoom back in to the bottom rows. +* **To highlight a row label**, hover over the column of labels on the left side of the heatmap and click on the label. The label currently under the mouse will enlarge. +* **To show/hide row labels**, right click on the heatmap and select "Hide row labels" or "Show row labels:. + + +### Plotting specific rows + +By default, when a heatmap is added to a SNUB project it is paired with a [trace plot](trace_plots.md). The trace plot contains a copy of each row of the heatmap and can be used to plot the time-series data for specific rows. There are two ways to plot the data for a given row: + +* Right click on the heatmap (over the row of interest) and select "Plot trace". +* Hover over the row label on the left side of the heatmap (so it becomes enlarged) and click. + +### Additional topics + +See [Selections](selections.md) for how to reorder the rows of the heatmap by their enrichment in a selection of time intervals. \ No newline at end of file diff --git a/snub/gui/help/help_menu.py b/snub/gui/help/help_menu.py new file mode 100644 index 0000000..a337da7 --- /dev/null +++ b/snub/gui/help/help_menu.py @@ -0,0 +1,89 @@ +from PyQt5.QtCore import * +from PyQt5.QtWidgets import * +from PyQt5.QtGui import * +import os +import markdown + +CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) + + +class MarkdownDialog(QDialog): + def __init__(self, markdown_text, parent=None): + super(MarkdownDialog, self).__init__(parent) + + self.viewer = QTextBrowser(self) + self.viewer.setReadOnly(True) + + html_text = markdown.markdown(markdown_text) + self.viewer.setHtml(html_text) + + layout = QVBoxLayout(self) + layout.addWidget(self.viewer) + self.resize(900, 640) + + +class MarkdownViewer(QDialog): + def __init__(self, markdown_file_path, parent=None): + super().__init__(parent) + self.initUI() + self.loadMarkdownFile(markdown_file_path) + + def initUI(self): + layout = QVBoxLayout(self) + self.textBrowser = QTextBrowser(self) + self.textBrowser.setOpenExternalLinks(False) # Prevent opening external links + self.textBrowser.anchorClicked.connect( + self.handleLinkClicked + ) # Handle internal links + layout.addWidget(self.textBrowser) + self.resize(900, 640) + + def loadMarkdownFile(self, file_path): + with open(file_path, "r", encoding="utf-8") as file: + markdown_content = file.read() + html_content = markdown.markdown(markdown_content) + self.textBrowser.setHtml(html_content) + + def handleLinkClicked(self, url): + link = url.toString() + if link.startswith("http"): + QDesktopServices.openUrl(QUrl(link)) + else: + self.loadMarkdownFile(os.path.join(CURRENT_DIR, link)) + + +class HelpMenu: + + menu_pages = { + "Loading data": "loading_data.md", + "Timeline": "timeline.md", + "Layout": "layout.md", + "Heatmaps": "heatmaps.md", + "Trace plots": "trace_plots.md", + "Scatter plots": "scatter_plots.md", + "Selections": "selections.md", + "Video player": "video.md", + } + + def __init__(self, parent): + self.parent = parent + self.helpMenu = QMenu("&Help", parent) + self._setup_actions() + + def _setup_actions(self): + for menu_text, page_name in self.menu_pages.items(): + action = QAction(menu_text, self.parent) + action.triggered.connect( + lambda _, mt=menu_text, pn=page_name: self._show_page(mt, pn) + ) + self.helpMenu.addAction(action) + self.helpMenu.addAction(action) + + def _show_page(self, menu_text, page_name): + page_path = os.path.join(CURRENT_DIR, page_name) + dialog = MarkdownViewer(page_path, self.parent) + dialog.setWindowTitle(menu_text) + dialog.exec_() + + def get_menu(self): + return self.helpMenu diff --git a/snub/gui/help/layout.md b/snub/gui/help/layout.md new file mode 100644 index 0000000..c5366a9 --- /dev/null +++ b/snub/gui/help/layout.md @@ -0,0 +1,14 @@ +## Layout + +The SNUB layout is organized hierarchically: each project is a tab, and each tab contains multiple data-views. + +* **To add a new tab**, [load a project](loading_data.md) using the "File" menu. +* **To remove a tab**, click the "x" in the top right corner of the tab. +* **To remove a data-view**, either minimize it using the minus sign in the top right corner or click the "x" in the top right corner. Minizing is temporary, whereas clicking the "x" is permanent. Removing/minimizing data-views can help improve performance, especially during playback. +* **To change data-view sizes**, drag the corresponding dividers (all dividers are draggable). + +### Track and panel stacks + +The layout is divided into two sections: a "panel stack" (left) and a "track stack" (right). The track stack contains the the [timeline](timeline.md) and all data-views that have time as a dimension, such as [heatmaps](heatmaps.md) and [trace plots](trace_plots.md). The panel stack contains all the data-views change over time, but don't have time as an explicit spatial dimension, such as [scatter plots](scatter_plots.md) and [video players](video.md). By default, these two components are arrayed horizontally, and their inner components are arrayed vertically. + +* **To move the panel stack above the track stack**, go to Window > Layout and check "Rows". This will also cause the panels in the panel stack to be arrayed horizontally. \ No newline at end of file diff --git a/snub/gui/help/loading_data.md b/snub/gui/help/loading_data.md new file mode 100644 index 0000000..0c157ee --- /dev/null +++ b/snub/gui/help/loading_data.md @@ -0,0 +1,7 @@ +## Open a SNUB project + +To open a SNUB project, go to File > Open Project, navigate to the project directory, and hit "Choose" with the directory selected. Multiple projects can be opened at once as different tabs. Projects can also be opened by including their paths as command line argument(s) when launching SNUB. + +## Reload a project + +If a project is already open and its files have been modified outside of SNUB, the project can be reloaded in the SNUB GUI by going to File > Reload Project. \ No newline at end of file diff --git a/snub/gui/help/scatter_plots.md b/snub/gui/help/scatter_plots.md new file mode 100644 index 0000000..d197d34 --- /dev/null +++ b/snub/gui/help/scatter_plots.md @@ -0,0 +1,18 @@ +## Scatter plots + +Scatter plots display two-dimensional data using points. In SNUB, each point corresponds to a time interval, and may also be associated with a value for one or more variables (e.g. the current speed of the animal). These variables (which are listed in a menu on the left) can be used to color the points. + +* **To show/hide the variable menu**, click the drop-down menu in the top right corner and click "Show/hide variable menu". The divider between the variable menu and the scatter plot can also be dragged to adjust the width of the menu. +* **To adjust the colormap**, right click on the scatter plot and select "Adjust colormap range" and enter a new min or max value. +* **To reorder points by the current variable**, right click on the scatter plot and ensure that "Plot high values on top" is checked. This is useful when a variable is very sparse and you want to see the points with the highest values. +* **To change the radius and border width of the markers**, right click on the scatter plot and select "Adjust marker appearance". + +### Visualizing dynamics + +The whenever the current time (as indicated by the vertical line in the [timeline](timeline.md)) falls within the interval of a point in the scatter plot, the point is highlighted with a big red dot. In some cases, it may also be useful to visulize temporal trajectories in the scatter plot. This can be done using a "marker trail", which uses red dots of decreasing radius to highlight markers that consecutively precede the current time. + +* **To show/hide the marker trail**, right click on the scatter plot and select "Show/hide marker trail". Note that you may need to play/scrub the timeline to see the trail initially. + +### Additional topics + +See [Selections](selections.md) for how to select points in the scatter plot and rank variables by their enrichment in the selection. \ No newline at end of file diff --git a/snub/gui/help/selections.md b/snub/gui/help/selections.md new file mode 100644 index 0000000..8fdd76d --- /dev/null +++ b/snub/gui/help/selections.md @@ -0,0 +1,33 @@ +## Selecting and deselecting + +Selections can be used to show relationships between data-views (such intervals on the [timeline](timeline.md) that correspond to a subset of points in a [scatter plot](scatter_plots.md)), or to identify variables that are enriched in a subset of the data. + +* Use shift+drag to select points in the scatter view or intervals in the timeline. +* Use command/control+drag to deselect points and intervals. +* Use Edit > Deselect All to deselect everything + +## Rank variables by enrichment + +### Scatter plot + + [Scatter plots](scatter_plots.md) may include user-defined variables that vary between points. By default, these variables are listed in a menu on the left side of the scatter plot. Ranking by enrichment helps identify variables that are particularly high in a subset of points. To perform this analysis: + +* Select a subset of points +* Right-click on the scatter plot to open the context menu +* Click "Rank by enrichment" +* The variable menu will reorder to show the most enriched variables at the top +* To return to the default ordering, right-click and select "Restore original variable order" + +*Note: Enrichment is calculated by Z-scoring each variable and then taking the mean Z-score for the selected points.* + +### Heatmap + +To identify rows of a [heatmap](heatmaps.md) that are enriched in a subset of the timeline: + +* Select one or more intervals on the timeline +* Right-click on the heatmap to open the context menu +* Click "Reorder by selection" (this may take a few seconds) +* The heatmap will reorder to show the most enriched rows at the top +* To return to the default ordering, right-click and select "Restore original order" + +*Note: Enrichment is calculated by Z-scoring each row and then taking the mean Z-score for the selected intervals.* \ No newline at end of file diff --git a/snub/gui/help/timeline.md b/snub/gui/help/timeline.md new file mode 100644 index 0000000..b0418fe --- /dev/null +++ b/snub/gui/help/timeline.md @@ -0,0 +1,14 @@ +## Timeline + +SNUB always shows a timeline on the bottom of the window. All data-views that have time as a dimension (such as [heatmaps](heatmaps.md) or [trace plots](trace_plots.md)) are aligned to the timeline, which indicates the currently visible time interval. SNUB also maintains a "current time" that determines e.g. which frame is shown in the [video player](video.md) or which point in a [scatter plot](scatter_plots.md) is highlighted. The current time is indicated by a vertical line in the timeline. If the current time is outside the interval of the timeline, this line is not shown. + +### Navigation + +* Use scrolls/gestures to change the currently visible time interval. +* Click on the timeline to set the current time. +* Use the play button and speed slider at the bottom of the window to animate the current time. +* Turn on "center playhead" to make the currently visible time interval be centered on the current time. +* Toggle the timeline unit between minutes:seconds and "timestemps". Timesteps are multiples of the "min_step" parameter that went into the construction of the current SNUB project. These discrete timesteps can be useful for accessing specific timepoinmts (e.g. video frames) outside of SNUB. + + +**Note: If playback is not smooth, try minimizing some of the visible panels (using the minus sign in the top right of each panel). Panels can be permanently removed by clicking the "x" in the top right of the panel.** \ No newline at end of file diff --git a/snub/gui/help/trace_plots.md b/snub/gui/help/trace_plots.md new file mode 100644 index 0000000..1439687 --- /dev/null +++ b/snub/gui/help/trace_plots.md @@ -0,0 +1,19 @@ +## Trace plots + +Trace plots display time-series data using lines. They are aligned to the [timeline](timeline.md) at the bottom of the window and can be navigated using gestures (pan and zoom). + +### Showing and hiding traces + +For each currently visible trace, a small color-matched label-box is displayed in the top-right. + +* **To show a trace**, click the drop-down menu in the top right corner and toggle the corresponding checkbox. +* **To hide a trace**, either toggle its checkbox in the drop-down menu or click on the corresponding label-box in the top-right. +* **To hide all traces**, right click on the trace plot and select "Hide all traces". + +### Adjusting the y-axis + +By default, the y-axis limits are determined automatically based on the currently visible traces; if traces are shown or hidden, the y-axis limits will be updated accordingly. + +* **To toggle automatic updating of y-axis limits**, right click on the trace plot and check or uncheck "Automatic y-axis limits". +* **To adjust y-axis limits**, right click on the trace plot and select "Adjust y-axis limits". This will temporarily disable automatic updating of y-axis limits. + diff --git a/snub/gui/help/video.md b/snub/gui/help/video.md new file mode 100644 index 0000000..f8388c3 --- /dev/null +++ b/snub/gui/help/video.md @@ -0,0 +1,10 @@ +## Video player + +A SNUB project can contain one or more video players. +* The video player always shows the frame associated with the current time (see [timeline](timeline.md)). +* If the current time is outside the interval of the video, the video player will show the first or last frame of the video. +* It is possible zoom in on specific areas of a video frame using pan/zoom gestures. + +### Playback + +See [timeline](timeline.md) for how to control the current time and speed of video playback. If playback is not smooth, try minimizing or closing parts of the layout (see [layout](layout.md)). \ No newline at end of file diff --git a/snub/gui/main.py b/snub/gui/main.py index e5de228..ea7d1d0 100644 --- a/snub/gui/main.py +++ b/snub/gui/main.py @@ -6,7 +6,7 @@ from snub.gui.utils import IntervalIndex, CheckBox from snub.gui.stacks import PanelStack, TrackStack from snub.gui.tracks import TracePlot -from snub.gui.help import HelpMenu +from snub.gui.help.help_menu import HelpMenu def set_style(app): diff --git a/snub/gui/panels/scatter.py b/snub/gui/panels/scatter.py index 9cda57c..935bcb2 100644 --- a/snub/gui/panels/scatter.py +++ b/snub/gui/panels/scatter.py @@ -279,6 +279,7 @@ def get_enriched_variables(self): np.std(self.data[:, 2:], axis=0) + self.eps ) enrichment = variables_zscore[self.is_selected].mean(0) + print(enrichment, self.data.shape, self.variable_labels) variable_order = [self.variable_labels[i] for i in np.argsort(-enrichment)] self.show_variable_menu(variable_order=variable_order) diff --git a/snub/gui/tracks/trace.py b/snub/gui/tracks/trace.py index dbd2b92..e13a478 100644 --- a/snub/gui/tracks/trace.py +++ b/snub/gui/tracks/trace.py @@ -94,8 +94,6 @@ def __init__( if not label in self.colors: self.colors[label] = _random_color() - self.clearButton = QPushButton("Clear") - self.clearButton.clicked.connect(self.clear) self.dropDown = CheckableComboBox() self.dropDown.toggleSignal.connect(self.toggle_trace) @@ -143,7 +141,6 @@ def initUI(self): for trace_label in self.trace_labels: control_layout.addWidget(trace_label, alignment=Qt.AlignTop) control_layout.addWidget(self.dropDown, alignment=Qt.AlignTop) - control_layout.addWidget(self.clearButton, alignment=Qt.AlignTop) self.update_controls_geometry() self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setMinimumSize(1, 1) @@ -247,6 +244,9 @@ def add_menu_item(name, slot, item_type="label"): contextMenu.addSeparator() add_menu_item("Adjust line width", self.show_adjust_linewidth_dialog) + contextMenu.addSeparator() + + add_menu_item("Hide all traces", self.clear) contextMenu.setStyleSheet( f""" @@ -274,8 +274,6 @@ def toggle_auto_yaxis_limits(self, state): self.auto_yaxis_limits = state if state: self.update_plot() - else: - self.show_adjust_yaxis_dialog() def update_yaxis_limits(self, ymin, ymax): self.yaxis_limits = (ymin, ymax)