diff --git a/.readthedocs.yml b/.readthedocs.yml
index 2ec2239..8168acb 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -4,6 +4,11 @@
# Required
version: 2
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.11"
+
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
@@ -18,12 +23,11 @@ formats:
# specify dependencies
python:
- version: 3.8
install:
- requirements: docs/requirements.txt
- #- method: pip
- #path: .
- #extra_requirements:
- # - docs
- # - gui
+ - method: pip
+ path: .
+ extra_requirements:
+ - docs
+ - gui
diff --git a/README.md b/README.md
index 0adfb48..918baac 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-[![Downloads](https://pepy.tech/badge/facemap)](https://pepy.tech/project/facemap)
-[![Downloads](https://pepy.tech/badge/facemap/month)](https://pepy.tech/project/facemap)
+[![Downloads](https://static.pepy.tech/badge/facemap)](https://pepy.tech/project/facemap)
+[![Downloads](https://static.pepy.tech/badge/facemap/month)](https://pepy.tech/project/facemap)
[![GitHub stars](https://badgen.net/github/stars/Mouseland/facemap)](https://github.com/MouseLand/facemap/stargazers)
[![GitHub forks](https://badgen.net/github/forks/Mouseland/facemap)](https://github.com/MouseLand/facemap/network/members)
[![](https://img.shields.io/github/license/MouseLand/facemap)](https://github.com/MouseLand/facemap/blob/main/LICENSE)
@@ -7,7 +7,7 @@
[![Documentation Status](https://readthedocs.org/projects/ansicolortags/badge/?version=latest)](https://pypi.org/project/facemap/)
[![GitHub open issues](https://badgen.net/github/open-issues/Mouseland/facemap)](https://github.com/MouseLand/facemap/issues)
-# Facemap
+# Facemap
Facemap is a framework for predicting neural activity from mouse orofacial movements. It includes a pose estimation model for tracking distinct keypoints on the mouse face, a neural network model for predicting neural activity using the pose estimates, and also can be used compute the singular value decomposition (SVD) of behavioral videos.
diff --git a/docs/api.rst b/docs/api.rst
index 55f42d6..c0144de 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -1,7 +1,6 @@
Facemap API Guide
===================================
-
Pose estimation
~~~~~~~~~~~~~~~~
.. autoclass:: facemap.pose.pose.Pose
diff --git a/docs/conf.py b/docs/conf.py
index d534de3..66b3e67 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -13,10 +13,14 @@
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
-# import os
-# import sys
-# sys.path.insert(0, os.path.abspath('.'))
+import os
+import sys
+sys.path.insert(0, os.path.abspath('.'))
+"""
+Use the following command to generate documentation
+ sphinx-build -b html docs docs/build/html
+"""
# -- Project information -----------------------------------------------------
project = "Facemap"
@@ -24,7 +28,7 @@
author = "Carsen Stringer & Atika Syeda"
# The full version, including alpha/beta/rc tags
-release = "1.0.1"
+release = "1.0.2"
# -- General configuration ---------------------------------------------------
@@ -39,7 +43,7 @@
"sphinx.ext.mathjax",
"sphinx.ext.viewcode",
"sphinx.ext.napoleon",
- "nbsphinx"
+ "nbsphinx",
]
# extensions = ['sphinx.ext.autodoc',
# 'sphinx.ext.mathjax',
@@ -73,9 +77,10 @@
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
-"""
+
html_theme = 'sphinx_rtd_theme'
html_theme_path = ["_themes"]
+"""
html_theme_options = {
'canonical_url': '',
'analytics_id': 'UA-XXXXXXX-1', # Provided by Google in your dashboard
diff --git a/docs/index.rst b/docs/index.rst
index 747b5ba..6d312f8 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -12,18 +12,9 @@ For more details, please see our `paper `__ and `refining keypoints model `__.
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 87d18ff..76c3b52 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,2 +1,5 @@
ipykernel
-nbsphinx
\ No newline at end of file
+nbsphinx
+sphinx==5.3.0
+sphinx_rtd_theme==1.1.1
+readthedocs-sphinx-search==0.1.1
\ No newline at end of file
diff --git a/facemap/__main__.py b/facemap/__main__.py
index 0d635f4..f2bd05b 100644
--- a/facemap/__main__.py
+++ b/facemap/__main__.py
@@ -7,9 +7,9 @@
import numpy as np
-from facemap import process
+from facemap import process, version_str
from facemap.gui import gui
-from facemap import version_str
+
def tic():
return time.time()
diff --git a/facemap/gui/gui.py b/facemap/gui/gui.py
index 96a5ea6..fc95e62 100644
--- a/facemap/gui/gui.py
+++ b/facemap/gui/gui.py
@@ -20,6 +20,7 @@
QCheckBox,
QComboBox,
QDesktopWidget,
+ QFileDialog,
QGridLayout,
QGroupBox,
QLabel,
@@ -32,7 +33,6 @@
QStatusBar,
QToolButton,
QWidget,
- QFileDialog
)
from scipy.stats import skew, zscore
@@ -43,8 +43,6 @@
istr = ["pupil", "motSVD", "blink", "running", "movSVD"]
-# TODO: Add pose instructions for CLI commands
-
class MainW(QtWidgets.QMainWindow):
def __init__(
@@ -75,7 +73,7 @@ def __init__(
QtCore.QCoreApplication.setApplicationName("Facemap")
pg.setConfigOptions(imageAxisOrder="row-major")
- self.setGeometry(55, 5, 1470, 800)
+ self.setGeometry(15, 5, 1470, 800)#(55, 5, 1470, 800)
self.setWindowTitle("Facemap")
self.setStyleSheet("QMainWindow {background: 'black';}")
self.styleUnpressed = (
@@ -114,7 +112,6 @@ def __init__(
menus.mainmenu(self)
self.online_mode = False
- # menus.onlinemenu(self)
self.central_widget = QWidget(self)
self.setCentralWidget(self.central_widget)
@@ -125,19 +122,19 @@ def __init__(
self.resize(self.sizeObject.width(), self.sizeObject.height())
self.video_window = pg.GraphicsLayoutWidget()
- self.video_window.move(self.sizeObject.height(), self.sizeObject.width())
- self.video_window.resize(self.sizeObject.height(), self.sizeObject.width())
- self.scene_grid_layout.addWidget(self.video_window, 1, 2, 10, 7)
+ #self.video_window.move(self.sizeObject.height(), self.sizeObject.width())
+ #self.video_window.resize(self.sizeObject.height(), self.sizeObject.width())
+ self.scene_grid_layout.addWidget(self.video_window, 0, 2, 6, 5)
# Create a window for embedding and ROI plot
self.roi_embed_window = pg.GraphicsLayoutWidget()
- self.roi_embed_window.move(self.sizeObject.height(), 0)
- self.roi_embed_window.resize(self.sizeObject.height(), self.sizeObject.width())
- self.scene_grid_layout.addWidget(self.roi_embed_window, 14, 2, 7, 7)
+ #self.roi_embed_window.move(self.sizeObject.height(), 0)
+ #self.roi_embed_window.resize(self.sizeObject.height(), self.sizeObject.width())
+ self.scene_grid_layout.addWidget(self.roi_embed_window, 6, 2, 3, 5)
# Create a window for plots
self.plots_window = pg.GraphicsLayoutWidget()
- self.scene_grid_layout.addWidget(self.plots_window, 0, 9, 24, 8)
+ self.scene_grid_layout.addWidget(self.plots_window, 0, 7, 9, 8)
# Add logo
# icon_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "mouse.png")
@@ -186,12 +183,10 @@ def __init__(
qlabel = QLabel("Saturation:")
qlabel.setStyleSheet("color: white;")
- self.saturation_groupbox.layout().addWidget(qlabel, 0, 0, 1, 1)
+ self.saturation_groupbox.layout().addWidget(qlabel, 0, 0)
video_saturation_slider = guiparts.Slider(0, self)
self.saturation_sliders.append(video_saturation_slider)
- self.saturation_groupbox.layout().addWidget(
- self.saturation_sliders[0], 0, 1, 1, 4
- )
+ self.saturation_groupbox.layout().addWidget(self.saturation_sliders[0], 0, 1)
# Add label to indicate saturation level
self.saturation_level_label = QLabel(str(self.saturation_sliders[0].value()))
@@ -204,7 +199,8 @@ def __init__(
self.reflector.clicked.connect(self.add_reflectROI)
self.rROI = []
self.reflectors = []
- self.scene_grid_layout.addWidget(self.reflector, 0, 6, 1, 1)
+ self.saturation_groupbox.layout().addWidget(self.reflector, 0, 2)
+ #self.scene_grid_layout.addWidget(self.reflector, 0, 6, 1, 1)
# roi Saturation groupbox
self.roi_saturation_groupbox = QGroupBox()
@@ -229,6 +225,7 @@ def __init__(
self.saturation_sliders[1].valueChanged.connect(self.set_ROI_saturation_label)
# Plots
+ # Add first plot
self.keypoints_traces_plot = self.plots_window.addPlot(
name="keypoints_traces_plot", row=0, col=1, title="Keypoints traces"
)
@@ -254,6 +251,7 @@ def __init__(
["paw"],
]
+ # Add second plot
self.svd_traces_plot = self.plots_window.addPlot(
name="svd_traces_plot", row=1, col=1, title="SVD traces"
)
@@ -393,8 +391,8 @@ def __init__(
if savedir is not None:
self.save_path = savedir
self.output_folder_set = True
- if len(savedir) > 20:
- self.savelabel.setText("..." + savedir[-20:])
+ if len(savedir) > 15:
+ self.savelabel.setText("..." + savedir[-15:])
else:
self.savelabel.setText(savedir)
if keypoints_file is not None:
@@ -420,14 +418,14 @@ def make_buttons(self):
# ~~~~~~~~~~~~~~~~~~~~~~~~ SVD variables ~~~~~~~~~~~~~~~~~~~~~~~~
self.svd_groupbox = QGroupBox("ROI settings:")
self.svd_groupbox.setStyleSheet(
- "QGroupBox { border: 1px solid white; border-style: outset; border-radius: 5px; color:white; padding: 20px 0px;}"
- ) # padding: 5px -10px;
+ "QGroupBox { border: 1px solid white; border-style: outset; border-radius: 5px; color:white; padding: 15px 0px;}"
+ )
self.svd_groupbox.setLayout(QGridLayout())
# Create ROI features
self.comboBox = QComboBox(self)
# Set size of combobox
- self.comboBox.setFixedWidth(int(0.05 * self.sizeObject.width()))
+ #self.comboBox.setFixedWidth(int(0.05 * self.sizeObject.width()))
self.comboBox.addItem("Select ROI")
self.comboBox.addItem("Pupil")
self.comboBox.addItem("motion SVD")
@@ -439,7 +437,7 @@ def make_buttons(self):
self.svd_groupbox.layout().addWidget(self.comboBox, 0, 0)
# self.comboBox.currentIndexChanged.connect(self.mode_change)
self.addROI = QPushButton("Add ROI")
- self.addROI.setFixedWidth(int(0.04 * self.sizeObject.width()))
+ #self.addROI.setFixedWidth(int(0.04 * self.sizeObject.width()))
self.addROI.setFont(QFont("Arial", 10, QFont.Bold))
self.addROI.clicked.connect(lambda clicked: self.add_ROI())
self.addROI.setEnabled(False)
@@ -453,7 +451,7 @@ def make_buttons(self):
self.svdbin_spinbox = QSpinBox()
self.svdbin_spinbox.setRange(1, 20)
self.svdbin_spinbox.setValue(self.ops["sbin"])
- self.svdbin_spinbox.setFixedWidth(int(0.03 * self.sizeObject.width()))
+ self.svdbin_spinbox.setFixedWidth(int(0.05 * self.sizeObject.width()))
self.svd_groupbox.layout().addWidget(
self.svdbin_spinbox, 1, 1, alignment=QtCore.Qt.AlignRight
)
@@ -464,7 +462,7 @@ def make_buttons(self):
)
self.sigma_box = QLineEdit()
self.sigma_box.setText(str(self.ops["pupil_sigma"]))
- self.sigma_box.setFixedWidth(int(0.02 * self.sizeObject.width()))
+ self.sigma_box.setFixedWidth(int(0.05 * self.sizeObject.width()))
self.pupil_sigma = float(self.sigma_box.text())
self.sigma_box.returnPressed.connect(self.pupil_sigma_change)
self.svd_groupbox.layout().addWidget(
@@ -474,7 +472,7 @@ def make_buttons(self):
# ~~~~~~~~~~~~~~~~~~~~~~~~ Pose/keypoints variables ~~~~~~~~~~~~~~~~~~~~~~~~
self.pose_groupbox = QGroupBox("Pose settings:")
self.pose_groupbox.setStyleSheet(
- "QGroupBox { border: 1px solid white; border-style: outset; border-radius: 10px; color:white; padding: 25px 5px;}"
+ "QGroupBox { border: 1px solid white; border-style: outset; border-radius: 5px; color:white; padding: 5px 0px;}"
)
self.pose_groupbox.setLayout(QGridLayout())
@@ -485,7 +483,7 @@ def make_buttons(self):
self.pose_model_combobox = QComboBox(self)
# Set size of combobox
- self.pose_model_combobox.setFixedWidth(int(0.085 * self.sizeObject.width()))
+ #self.pose_model_combobox.setFixedWidth(int(0.085 * self.sizeObject.width()))
# make combobox scrollable
self.pose_model_combobox.view().setVerticalScrollBarPolicy(
QtCore.Qt.ScrollBarAlwaysOn
@@ -494,7 +492,7 @@ def make_buttons(self):
self.pose_model_combobox.setStyleSheet("QComboBox { combobox-popup: 0; }")
self.update_pose_model_combo_box()
self.pose_groupbox.layout().addWidget(
- self.pose_model_combobox, 0, 1, alignment=QtCore.Qt.AlignLeft
+ self.pose_model_combobox, 0, 1
)
# Add a QLabel and spinbox for selecting batch size
@@ -504,7 +502,7 @@ def make_buttons(self):
self.batch_size_spinbox = QSpinBox()
self.batch_size_spinbox.setRange(1, 5000)
self.batch_size_spinbox.setValue(4)
- self.batch_size_spinbox.setFixedWidth(int(0.04 * self.sizeObject.width()))
+ #self.batch_size_spinbox.setFixedWidth(int(0.04 * self.sizeObject.width()))
self.pose_groupbox.layout().addWidget(
self.batch_size_spinbox, 1, 1, alignment=QtCore.Qt.AlignRight
)
@@ -517,9 +515,9 @@ def make_buttons(self):
self.keypoints_threshold_spinbox.setRange(0, 100)
self.keypoints_threshold_spinbox.setValue(0)
self.keypoints_threshold = self.keypoints_threshold_spinbox.value()
- self.keypoints_threshold_spinbox.setFixedWidth(
- int(0.04 * self.sizeObject.width())
- )
+ #self.keypoints_threshold_spinbox.setFixedWidth(
+ # int(0.04 * self.sizeObject.width())
+ #)
self.keypoints_threshold_spinbox.valueChanged.connect(
self.update_keypoints_threshold
)
@@ -530,7 +528,7 @@ def make_buttons(self):
# ~~~~~~~~~~~~~~~~~~~~~~~~ Process features ~~~~~~~~~~~~~~~~~~~~~~~~
self.process_groupbox = QGroupBox("Process settings:")
self.process_groupbox.setStyleSheet(
- "QGroupBox { border: 1px solid white; border-style: outset; border-radius: 10px; color:white; padding: 25px 5px;}"
+ "QGroupBox { border: 1px solid white; border-style: outset; border-radius: 5px; color:white; padding: 7px 0px;}"
)
self.process_groupbox.setLayout(QGridLayout())
@@ -565,9 +563,9 @@ def make_buttons(self):
self.process_groupbox.layout().addWidget(self.gpu_checkbox, 1, 2)
# ~~~~~~~~~~~~~~~~~~~~~~~~ Process buttons ~~~~~~~~~~~~~~~~~~~~~~~~
- self.process_buttons_groupbox = QGroupBox("Process buttons:")
+ self.process_buttons_groupbox = QGroupBox()
self.process_buttons_groupbox.setStyleSheet(
- "QGroupBox { border: 0px solid white; border-style: outset;}"
+ "QGroupBox { border: 0px solid white; border-style: outset; border-radius: 0px; color:white; padding: 0px 0px;}"
)
self.process_buttons_groupbox.setLayout(QGridLayout())
@@ -592,7 +590,7 @@ def make_buttons(self):
# ~~~~~~~~~~~~~~~~~~~~~~~~ Labels ~~~~~~~~~~~~~~~~~~~~~~~~
self.labels_groupbox = QGroupBox()
self.labels_groupbox.setStyleSheet(
- "QGroupBox { border: 0px solid white; border-style: outset;}"
+ "QGroupBox { border: 0px solid white; border-style: outset; border-radius: 0px; color:white; padding: 0px 0px;}"
)
self.labels_groupbox.setLayout(QGridLayout())
@@ -605,14 +603,21 @@ def make_buttons(self):
self.labels_groupbox.layout().addWidget(self.savelabel, 0, 1)
self.batchlist = []
+ # Add show batch button to labels groupbox
+ self.show_batch_button = QPushButton("Show batch")
+ self.show_batch_button.setFont(QFont("Arial", 10, QFont.Bold))
+ self.show_batch_button.clicked.connect(self.show_batch)
+ self.labels_groupbox.layout().addWidget(self.show_batch_button, 0, 2)
+ """
self.batchname = []
- # TODO: Change batchname to span 2 columns
- for k in range(5):
+ # TODO: Change batchname to be displayed in a pop-up message box that lists the filenames!!
+ for k in range(1):
self.batchname.append(QLabel(""))
self.batchname[-1].setStyleSheet("color: white;")
self.batchname[-1].setAlignment(QtCore.Qt.AlignCenter)
self.labels_groupbox.layout().addWidget(self.batchname[-1], k + 1, 0, 1, 2)
# self.scene_grid_layout.addWidget(self.batchname[-1], 6 + k, 0, 1, 4)
+ """
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Video playback options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.current_frame_lineedit = QLineEdit()
@@ -631,61 +636,14 @@ def make_buttons(self):
self.frame_slider.setTracking(False)
self.frame_slider.valueChanged.connect(self.go_to_frame)
self.frameDelta = 10
- istretch = 15
- iplay = istretch + 10
iconSize = QtCore.QSize(20, 20)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Video playback options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- self.video_playback_groupbox = QGroupBox()
- self.video_playback_groupbox.setStyleSheet(
- "QGroupBox { border: 0px solid white; border-style: outset;}"
- )
- self.video_playback_groupbox.setLayout(QGridLayout())
-
- iconSize = QtCore.QSize(30, 30)
- self.playButton = QToolButton()
- self.playButton.setIcon(
- self.style().standardIcon(QtWidgets.QStyle.SP_MediaPlay)
- )
- self.playButton.setIconSize(iconSize)
- self.playButton.setToolTip("Play")
- self.playButton.setCheckable(True)
- self.playButton.clicked.connect(self.start)
- self.playButton.setFixedSize(
- QtCore.QSize(
- np.floor(self.sizeObject.width() * 0.025).astype(int),
- np.floor(self.sizeObject.width() * 0.025).astype(int),
- )
- )
- self.video_playback_groupbox.layout().addWidget(self.playButton, 0, 0)
-
- self.pauseButton = QToolButton()
- self.pauseButton.setCheckable(True)
- self.pauseButton.setIcon(
- self.style().standardIcon(QtWidgets.QStyle.SP_MediaPause)
- )
- self.pauseButton.setIconSize(iconSize)
- self.pauseButton.setToolTip("Pause")
- self.pauseButton.clicked.connect(self.pause)
- self.pauseButton.setFixedSize(
- QtCore.QSize(
- np.floor(self.sizeObject.width() * 0.025).astype(int),
- np.floor(self.sizeObject.width() * 0.025).astype(int),
- )
- )
- self.video_playback_groupbox.layout().addWidget(self.pauseButton, 0, 1)
-
- btns = QButtonGroup(self)
- btns.addButton(self.playButton, 0)
- btns.addButton(self.pauseButton, 1)
- btns.setExclusive(True)
-
# Add clustering analysis/visualization features
self.roi_embed_combobox = QComboBox(self)
self.roi_embed_combobox.addItem("--Select display--")
self.roi_embed_combobox.addItem("ROI")
- self.roi_embed_combobox.addItem("UMAP")
- self.roi_embed_combobox.addItem("tSNE")
+ #self.roi_embed_combobox.addItem("UMAP")
+ #self.roi_embed_combobox.addItem("tSNE")
self.roi_embed_combobox.currentIndexChanged.connect(
self.vis_combobox_selection_changed
)
@@ -727,52 +685,43 @@ def make_buttons(self):
# ~~~~~~~~~~ motsvd/movsvd options ~~~~~~~~~~
self.scene_grid_layout.addWidget(self.svd_groupbox, 0, 0, 1, 2)
# ~~~~~~~~~~ Pose features ~~~~~~~~~~
- self.scene_grid_layout.addWidget(self.pose_groupbox, 1, 0, 3, 2)
+ self.scene_grid_layout.addWidget(self.pose_groupbox, 1, 0, 2, 2)
# ~~~~~~~~~~ Process features ~~~~~~~~~~
- self.scene_grid_layout.addWidget(self.process_groupbox, 5, 0, 1, 2)
+ self.scene_grid_layout.addWidget(self.process_groupbox, 3, 0, 1, 2)
# ~~~~~~~~~~ Process buttons features ~~~~~~~~~~
- self.scene_grid_layout.addWidget(self.process_buttons_groupbox, 6, 0, 1, 2)
+ self.scene_grid_layout.addWidget(self.process_buttons_groupbox, 4, 0, 1, 2)
# ~~~~~~~~~~ Save/file IO ~~~~~~~~~~
- self.scene_grid_layout.addWidget(self.labels_groupbox, 7, 0, 1, 2)
- # ~~~~~~~~~~ Saturation ~~~~~~~~~~
- self.scene_grid_layout.addWidget(self.saturation_groupbox, 0, 2, 1, 3)
- # ~~~~~~~~~~ embedding & ROI visualization window features
- self.scene_grid_layout.addWidget(self.roi_saturation_groupbox, 11, 2, 1, 3)
- self.scene_grid_layout.addWidget(self.roi_embed_combobox, 11, 6, 1, 1)
- self.scene_grid_layout.addWidget(self.zoom_in_button, 11, 7, 1, 1)
- self.scene_grid_layout.addWidget(self.zoom_out_button, 11, 8, 1, 1)
- self.scene_grid_layout.addWidget(self.roi_display_combobox, 11, 7, 1, 1)
- self.scene_grid_layout.addWidget(self.save_clustering_button, 12, 7, 1, 1)
- # ~~~~~~~~~~ Video playback ~~~~~~~~~~
- self.scene_grid_layout.addWidget(self.video_playback_groupbox, iplay, 0, 1, 1)
- self.playButton.setEnabled(False)
- self.pauseButton.setEnabled(False)
- self.pauseButton.setChecked(True)
- self.scene_grid_layout.addWidget(QLabel(""), istretch, 0, 1, 3)
- self.scene_grid_layout.setRowStretch(istretch, 1)
- self.scene_grid_layout.addWidget(
- self.current_frame_lineedit, istretch + 9, 0, 1, 1
+ self.scene_grid_layout.addWidget(self.labels_groupbox, 5, 0, 1, 2)
+
+ # ~~~~~~~~~~ Plot 1 and 2 features ~~~~~~~~~~
+ self.keypoints_chckbox_groupbox = QGroupBox("Keypoints traces")
+ self.keypoints_chckbox_groupbox.setStyleSheet(
+ "QGroupBox { border: 1px solid white; border-style: outset; border-radius: 5px; color:white; padding: 10px 15px;}"
)
- self.scene_grid_layout.addWidget(self.total_frames_label, istretch + 9, 1, 1, 1)
- self.scene_grid_layout.addWidget(self.frame_slider, istretch + 10, 1, 1, 16)
+ self.keypoints_chckbox_groupbox.setLayout(QGridLayout())
- # Plot 1 and 2 features
- plot_label = QLabel("Keypoints traces")
- plot_label.setStyleSheet("color: gray;")
- self.scene_grid_layout.addWidget(plot_label, istretch, 0, 1, 1)
+ self.svd_chckbox_groupbox = QGroupBox("SVD traces")
+ self.svd_chckbox_groupbox.setStyleSheet(
+ "QGroupBox { border: 1px solid white; border-style: outset; border-radius: 5px; color:white; padding: 10px 15px;}"
+ )
+ self.svd_chckbox_groupbox.setLayout(QGridLayout())
+ """
+ #plot_label = QLabel("Keypoints traces")
+ #plot_label.setStyleSheet("color: gray;")
+ #self.scene_grid_layout.addWidget(plot_label, istretch, 0, 1, 1)
plot_label = QLabel("SVD traces")
plot_label.setStyleSheet("color: gray;")
- self.scene_grid_layout.addWidget(plot_label, istretch, 1, 1, 1)
- self.load_trace2_button = QPushButton("Load 1D data")
- self.load_trace2_button.setFont(QFont("Arial", 12))
- self.load_trace2_button.clicked.connect(
- lambda: self.load_1dtrace_button_clicked(2)
- )
- self.load_trace2_button.setEnabled(False)
- self.load_trace2_button.setFixedWidth(int(0.07 * self.sizeObject.width()))
+ self.scene_grid_layout.addWidget(plot_label, istretch, 1, 1, 1)"""
+ #self.load_trace2_button = QPushButton("Load 1D data")
+ #self.load_trace2_button.setFont(QFont("Arial", 12))
+ #self.load_trace2_button.clicked.connect(
+ # lambda: self.load_1dtrace_button_clicked(2)
+ #)
+ #self.load_trace2_button.setEnabled(False)
+ #self.load_trace2_button.setFixedWidth(int(0.07 * self.sizeObject.width()))
self.trace2_data_loaded = None
self.trace2_legend = pg.LegendItem(labelTextSize="12pt", horSpacing=30)
- self.scene_grid_layout.addWidget(self.load_trace2_button, istretch + 1, 1, 1, 1)
+ #self.scene_grid_layout.addWidget(self.load_trace2_button, istretch + 1, 1, 1, 1)
self.plot1_checkboxes = []
self.plot2_checkboxes = []
self.lbls = []
@@ -784,22 +733,111 @@ def make_buttons(self):
self.plot1_checkboxes[-1].toggled.connect(
self.keypoint_subgroup_checkbox_toggled
)
- self.scene_grid_layout.addWidget(
- self.plot1_checkboxes[-1], istretch + 1 + i, 0, 1, 1
- )
+ self.keypoints_chckbox_groupbox.layout().addWidget(self.plot1_checkboxes[-1], i, 0)
+ #self.scene_grid_layout.addWidget(
+ # self.plot1_checkboxes[-1], istretch + 1 + i, 0, 1, 1
+ #)
+ self.scene_grid_layout.addWidget(self.keypoints_chckbox_groupbox, 6, 0, 3, 1)
# Set plot 2 checkboxes
- for k in range(7):
+ for k in range(5):
self.plot2_checkboxes.append(QCheckBox(""))
- self.scene_grid_layout.addWidget(
- self.plot2_checkboxes[-1], istretch + 2 + k, 1, 1, 1
- )
+ self.svd_chckbox_groupbox.layout().addWidget(self.plot2_checkboxes[-1], k, 1)
+ #self.scene_grid_layout.addWidget(
+ # self.plot2_checkboxes[-1], istretch + 1 + k, 1, 1, 1
+ #)
self.plot2_checkboxes[-1].toggled.connect(self.plot_processed)
self.plot2_checkboxes[-1].setEnabled(False)
self.plot2_checkboxes[k].setStyleSheet("color: gray;")
self.lbls.append(QLabel(""))
self.lbls[-1].setStyleSheet("color: white;")
+ self.scene_grid_layout.addWidget(self.svd_chckbox_groupbox, 6, 1, 3, 1)
+
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Video playback options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ self.video_playback_groupbox = QGroupBox()
+ self.video_playback_groupbox.setStyleSheet(
+ "QGroupBox { border: 0px solid white; border-style: outset;}"
+ )
+ self.video_playback_groupbox.setLayout(QGridLayout())
+
+ iconSize = QtCore.QSize(30, 30)
+ self.playButton = QToolButton()
+ self.playButton.setIcon(
+ self.style().standardIcon(QtWidgets.QStyle.SP_MediaPlay)
+ )
+ self.playButton.setIconSize(iconSize)
+ self.playButton.setToolTip("Play")
+ self.playButton.setCheckable(True)
+ self.playButton.clicked.connect(self.start)
+ self.playButton.setFixedSize(
+ QtCore.QSize(
+ np.floor(self.sizeObject.width() * 0.025).astype(int),
+ np.floor(self.sizeObject.width() * 0.025).astype(int),
+ )
+ )
+ self.video_playback_groupbox.layout().addWidget(self.playButton, 0, 0)
+
+ self.pauseButton = QToolButton()
+ self.pauseButton.setCheckable(True)
+ self.pauseButton.setIcon(
+ self.style().standardIcon(QtWidgets.QStyle.SP_MediaPause)
+ )
+ self.pauseButton.setIconSize(iconSize)
+ self.pauseButton.setToolTip("Pause")
+ self.pauseButton.clicked.connect(self.pause)
+ self.pauseButton.setFixedSize(
+ QtCore.QSize(
+ np.floor(self.sizeObject.width() * 0.025).astype(int),
+ np.floor(self.sizeObject.width() * 0.025).astype(int),
+ )
+ )
+ self.video_playback_groupbox.layout().addWidget(self.pauseButton, 0, 1)
+
+ btns = QButtonGroup(self)
+ btns.addButton(self.playButton, 0)
+ btns.addButton(self.pauseButton, 1)
+ btns.setExclusive(True)
+
+ self.playButton.setEnabled(False)
+ self.pauseButton.setEnabled(False)
+ self.pauseButton.setChecked(True)
+
+ # Frame number labels
+ self.video_playback_groupbox.layout().addWidget(self.current_frame_lineedit, 0, 2)
+ self.video_playback_groupbox.layout().addWidget(self.total_frames_label, 0, 3)
+ self.scene_grid_layout.addWidget(self.video_playback_groupbox, 9, 0, 1, 2)
+ """
+ self.scene_grid_layout.addWidget(QLabel(""), istretch, 0, 1, 3)
+ self.scene_grid_layout.setRowStretch(istretch, 1)
+ self.scene_grid_layout.addWidget(
+ self.current_frame_lineedit, istretch + 6, 0, 1, 1
+ )
+ self.scene_grid_layout.addWidget(self.total_frames_label, istretch + 6, 1, 1, 1)
+ """
+ self.scene_grid_layout.addWidget(self.frame_slider, 9, 2, 1, 13)
+ # ~~~~~~~~~~ Saturation ~~~~~~~~~~
+ self.scene_grid_layout.addWidget(self.saturation_groupbox, 0, 2, 1, 4)
+ # ~~~~~~~~~~ embedding & ROI visualization window features
+ self.scene_grid_layout.addWidget(self.roi_saturation_groupbox, 5, 2, 1, 3)
+ self.scene_grid_layout.addWidget(self.roi_embed_combobox, 5, 5, 1, 1)
+ #self.scene_grid_layout.addWidget(self.zoom_in_button, 4, 7, 1, 1)
+ #self.scene_grid_layout.addWidget(self.zoom_out_button, 4, 8, 1, 1)
+ self.scene_grid_layout.addWidget(self.roi_display_combobox, 5, 6, 1, 1)
+ #self.scene_grid_layout.addWidget(self.save_clustering_button, 5, 7, 1, 1)
+
+ video_path_label = QLabel("Save path:")
+ video_path_label.setStyleSheet("color: gray;")
+ self.labels_groupbox.layout().addWidget(video_path_label, 0, 0)
+
self.update_frame_slider()
+ def show_batch(self):
+ if not self.batchlist:
+ QMessageBox.information(self, "Batch List", "No filenames in batchlist.")
+ else:
+ message = "List of filenames in batchlist:\n\n"
+ message += "\n".join(self.batchlist) # Items will be separated by new lines
+ QMessageBox.information(self, "Batch List", message)
+
def add_pose_model(self):
# Open a file dialog to browse and select a pose model
pose_model_path = QFileDialog.getOpenFileName(
@@ -1177,7 +1215,7 @@ def update_buttons(self):
self.saverois.setEnabled(True)
self.multivideo_svd_checkbox.setChecked(True)
self.save_mat.setChecked(True)
- self.load_trace2_button.setEnabled(True)
+ #self.load_trace2_button.setEnabled(True)
# Enable pose features for single video only
self.keypoints_checkbox.setEnabled(True)
@@ -2290,6 +2328,10 @@ def load_neural_data(self):
neural_data_cancel_button = QtWidgets.QPushButton("Cancel")
neural_data_cancel_button.clicked.connect(dialog.reject)
neural_data_buttons_hbox.addWidget(neural_data_cancel_button)
+ # Add a help button
+ neural_data_help_button = QtWidgets.QPushButton("Help")
+ neural_data_help_button.clicked.connect(lambda clicked: self.load_neural_data_help_clicked(clicked, dialog))
+ neural_data_buttons_hbox.addWidget(neural_data_help_button)
# Add a done button
neural_data_done_button = QtWidgets.QPushButton("Done")
neural_data_done_button.clicked.connect(
@@ -2407,7 +2449,7 @@ def show_run_neural_predictions_dialog(self):
"QGroupBox {border: 1px solid gray; border-radius: 9px; margin-top: 1em;} "
)
dialog.neural_model_hyperparameters_groupbox.setTitle(
- "Keypoints network hyperparameters"
+ "Training hyperparameters"
)
learning_rate_label = QtWidgets.QLabel("Learning rate:")
dialog.learning_rate_line_edit = QtWidgets.QLineEdit()
@@ -2585,6 +2627,9 @@ def update_hyperparameter_box(self, dialog):
dialog.neural_model_hyperparameters_groupbox.hide()
dialog.linear_regression_hyperparameters_groupbox.show()
+ def load_neural_data_help_clicked(self, clicked, dialog):
+ help_windows.LoadNeuralDataHelp(parent=dialog, window_size=self.sizeObject)
+
def neural_data_help_button_clicked(self, clicked, dialog):
help_windows.NeuralModelTrainingWindow(
parent=dialog, window_size=self.sizeObject
diff --git a/facemap/gui/help_windows.py b/facemap/gui/help_windows.py
index 332b5d2..46cecaf 100644
--- a/facemap/gui/help_windows.py
+++ b/facemap/gui/help_windows.py
@@ -2,6 +2,7 @@
Copright © 2023 Howard Hughes Medical Institute, Authored by Carsen Stringer and Atika Syeda.
"""
import os
+import typing
import numpy as np
from PyQt5 import QtCore
@@ -17,9 +18,11 @@
QPushButton,
QScrollArea,
QSizePolicy,
+ QTextEdit,
QVBoxLayout,
QWidget,
)
+
from ..version import version_str
@@ -59,7 +62,7 @@ def __init__(self, parent=None, window_size=None):
layout.addWidget(main_text, stretch=1)
# Pose tracking section
- pose_tracking_group = QGroupBox("Pose tracking", self)
+ pose_tracking_group = QGroupBox()
pose_tracking_group.setStyleSheet(
"QGroupBox {background: 'black'; border: 0px ;}"
)
@@ -85,7 +88,7 @@ def __init__(self, parent=None, window_size=None):
layout.addWidget(pose_tracking_group, stretch=1)
# SVD section
- svd_group = QGroupBox("SVD", self)
+ svd_group = QGroupBox()
svd_group.setStyleSheet("QGroupBox {background: 'black'; border: 0px ;}")
svd_group.setLayout(QVBoxLayout())
svd_text = """
@@ -112,13 +115,54 @@ def __init__(self, parent=None, window_size=None):
self.show()
- # TODO - Add instructions for filetypes accepted for different load buttons
- # TODO - Add instructions for loading neural data
+class LoadNeuralDataHelp(QDialog):
+ def __init__(self, window_size, parent=None):
+ super(LoadNeuralDataHelp, self).__init__(parent)
+ self.setWindowTitle("Help")
+ width, height = int(window_size.width() * 0.28), int(
+ window_size.height() * 0.25
+ )
+ self.resize(width, height)
+ self.win = QWidget(self)
+ layout = QVBoxLayout()
+ layout.setAlignment(QtCore.Qt.AlignCenter)
+ self.win.setLayout(layout)
+
+ self.scrollArea = QScrollArea(self)
+ self.scrollArea.setFixedHeight(height)
+ self.scrollArea.setFixedWidth(width)
+ self.scrollArea.setWidgetResizable(True)
+ self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+ self.scrollArea.setWidget(self.win)
+
+ text = """
+
+ - Load neural data file (*.npy) containing an array of shape neurons x time.
+ - Select whether to view neural data as heatmap or traces (for small number of neurons).
+ - (Optional) Load neural timestamps file (*.npy) containing a 1D array.
+ - (Optional) Load behavioral timestamps file (*.npy) containing a 1D array.
+ - Note: the timestamps file are used for resampling behavioral data to neural timescale.
+
+ """
+
+ label = QLabel(text, self)
+ label.setStyleSheet(
+ "font-size: 12pt; font-family: Arial; text-align: center; "
+ )
+ label.setWordWrap(True)
+ layout.addWidget(label, stretch=1)
+
+ # Add a ok button to close the window
+ self.ok_button = QPushButton("Ok")
+ self.ok_button.clicked.connect(self.close)
+ layout.addWidget(self.ok_button, alignment=QtCore.Qt.AlignCenter)
+
+ self.show()
class AboutWindow(QDialog):
- def __init__(self, parent=None, window_size=None):
+ def __init__(self, parent, window_size):
super(AboutWindow, self).__init__(parent)
width, height = int(window_size.width() * 0.28), int(
window_size.height() * 0.42
@@ -155,7 +199,7 @@ def __init__(self, parent=None, window_size=None):
text = """
- Pose tracking of mouse face from different camera views (python only) and svd processing of videos (python and MATLAB).
+ Framework for predicting neural activity from mouse orofacial movements tracked using a pose estimation model. Package also includes singular value decomposition (SVD) of behavioral videos.
Authors: Carsen Stringer & Atika Syeda
@@ -169,15 +213,15 @@ def __init__(self, parent=None, window_size=None):
Version: {version}
- Visit our github page for more information.
+ Visit our GitHub page for more information.
""".format(version=version_str)
- text = QLabel(text, self)
- text.setStyleSheet(
- "font-size: 12pt; font-family: Arial; color: white; text-align: center; "
+ text = QTextEdit(text, self)
+ text.setStyleSheet(
+ "font-size: 12pt; color: white; background-color: #000000;"
)
- text.setWordWrap(True)
- text.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ text.setReadOnly(True)
+ text.setFixedSize(width*0.98, height)
layout.addWidget(text, stretch=1)
self.show()
@@ -187,7 +231,7 @@ class PoseRefinementStep2HelpWindow(QDialog):
def __init__(self, parent=None, window_size=None):
super(PoseRefinementStep2HelpWindow, self).__init__(parent)
width, height = int(window_size.width() * 0.3), int(window_size.height() * 0.3)
- self.resize(width, height)
+ self.resize(width * 0.95, height * 0.75)
self.setWindowTitle("Help")
self.win = QWidget(self)
layout = QVBoxLayout()
@@ -196,16 +240,19 @@ def __init__(self, parent=None, window_size=None):
text = """
- - Select the initial/base model to use for further finetuning.
- - Set the name of output model after refinement.
- - (If applicable) Select data files containing refined keypoints from previous training to include during current model training.
- - Select 'Refine current video' to refine predicted keypoints for a subset of frames from the current video after selecting the number of frames. Note: the suggested number of frames for each new animal are 20-25.
- - Select '+' to set the hyperparameters for training.
+ - Select base model for finetuning.
+ - Set name of finetuned model.
+ - Select whether to 'Refine current video' and the number of frames to refine from current video.
+ - Set proportion of random frames to include during training. Rest of the frames are selected based on keypoint values that lie above likelihood threshold.
+ - (Optional) Select whether to use refined keypoints from previous training.
+ - Select '+' to change hyperparameter settings for training.
"""
- label = QLabel(text)
- label.setStyleSheet("font-size: 12pt; font-family: Arial; color: white;")
- label.setWordWrap(True)
+ label = QTextEdit(text) #QLabel(text)
+ label.setReadOnly(True) # Make the text area read-only
+ label.setStyleSheet("font-size: 12pt; color: white; background-color: black;")
+ label.setHtml(text)
+ label.setFixedSize(width * 0.9, height * 0.6)
layout.addWidget(label, alignment=QtCore.Qt.AlignCenter)
# Add a ok button to close the window
@@ -246,83 +293,84 @@ def __init__(self, parent=None, window_size=None):
Refinement keys
- - Left click: Press left button and drag mouse to move a keypoint
- - Right click: To add a deleted keypoint currently selected in the radio buttons at current mouse position
- - Shift + D: To delete a keypoint selected in the radio buttons
+ - Move Keypoint: Hold down the left mouse button and drag the mouse to reposition a keypoint.
+ - Restore Keypoint: Right-click to add a previously deleted keypoint at the current mouse position, matching the radio button selection.
+ - Delete Keypoint: Use Shift + D to remove the keypoint selected in the radio buttons.
- Labelling instructions
+ Guidelines for Labeling
- Keypoints for different facial regions are labelled as shown above in the side view and top view. Detailed instructions for each region are given below for different views:
+ Keypoints representing various facial regions are annotated according to the illustrations provided for the side view and top view. For each viewpoint, detailed instructions for labeling different regions are outlined below:
Eye
-
- EYE(TOP): Upper eyelid point centered at the top of the eye.
+ EYE(TOP): Mark the upper eyelid's central point, located at the eye's highest point.
-
- EYE(BOTTOM): Lower eyelid point centered at the bottom of the eye.
+ EYE(BOTTOM): Identify the lower eyelid's central point, situated at the eye's lowest point.
-
- EYE(FRONT): Point at the front of the eye near the nose.
+ EYE(FRONT): Annotate the point at the eye's front, closest to the nose.
-
- EYE(BACK): Point opposite the front eye keypoint.
+ EYE(BACK): Mark the point opposite the front eye keypoint.
Nose
-
- NOSEBRIDGE: Point at the top of the nose in line with the EYE(FRONT) keypoint.
+ NOSEBRIDGE: Place a point at the top of the nose, aligned with the "EYE(FRONT)" keypoint.
-
- NOSE(TOP): Point at the top of the nose.
+ NOSE(TOP): Place a point at the top of the nose.
-
- NOSE(TIP): Point at the tip/middle of the nose.
+ NOSE(TIP): Annotate the point at the tip or middle of the nose.
-
- NOSE(BOTTOM): Point at the bottom of the nose if viewed from the side. If viewed from the top, this is the point opposite the nose(Right) keypoint to track left/right movements.
+ NOSE(BOTTOM): Place a point at the nose's bottom, visible from the side. In a top view, this point corresponds to the opposite side of the "Nose (Right)" keypoint, tracking lateral movements.
-
- NOSE(R): Point at the right side of the nose which is only labeled if viewed from the top. The point tracks left/right movements.
+ NOSE(R): Label this point only when viewing from the top. It tracks left/right movements.
Whiskers
- To label whiskers, find a set of 3 whiskers in the triangular configuration as shown above. The easiest way to do this is to identify most prominent whiskers that are easily identifiable across frames. Whiskers are labeled in clockwise order (C1->D1-C3) when viewed from the right side and in counterclockwise order (C1->D1-C3) when viewed from the top/left view.
+ For whisker labeling, identify a set of three whiskers forming a triangular pattern as shown. Look for prominent whiskers consistently recognizable across frames. Label whiskers in a clockwise order (I->II-III) when viewed from the right side, or counterclockwise order (I->II-III) when viewed from the top/left view.
-
- WHISKER(I): First whisker in the third row from top.
+ WHISKER(I): The first whisker in the third row from the top.
-
- WHISKER(II): First whisker in the fourth row from top.
+ WHISKER(II): The first whisker in the fourth row from the top.
-
- WHISKER(III): Second whisker in the fourth row from top.
+ WHISKER(III): The second whisker in the fourth row from the top.
Paw
-
- PAW: Point is only labelled when visible in frame. Select any region of the paw to label the paw.
+ PAW: Label this point only when visible within the frame. Select any region of the paw for labeling.
Mouth
-
- MOUTH: Point indicating the center of the mouth (opening). The point is only labeled when visible (usually from the sideview).
+ MOUTH: Mark the point at the center of the mouth opening. Label only when visible, usually in the side view.
-
- LOWERLIP: Point at the bottom of the lower lip near the mouth keypoint. The point is only labeled when visible (usually from the sideview).
+ LOWERLIP: Place a point at the bottom of the lower lip near the mouth keypoint. Label only when visible, typically from the side view.
+ Please follow these instructions to accurately label the keypoints for each facial region in the provided illustrations.
"""
- label = QLabel(text)
+ label = QTextEdit(text)
label.setStyleSheet(
"font-size: 12pt; font-family: Arial; color: white; text-align: center; padding: 15;"
)
- label.setWordWrap(True)
- label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ label.setReadOnly(True)
+ label.setFixedSize(width * 0.9, height * 0.6)
layout.addWidget(label, alignment=QtCore.Qt.AlignLeft, stretch=1)
# Add ok button to close the window
@@ -336,13 +384,10 @@ def __init__(self, parent=None, window_size=None):
self.show()
-# TODO: Update help button with correct instructions about keypoints labels (specially whiskers)
-
-
class NeuralModelTrainingWindow(QDialog):
def __init__(self, parent=None, window_size=None):
super(NeuralModelTrainingWindow, self).__init__(parent)
- width, height = int(window_size.width() * 0.4), int(window_size.height() * 0.45)
+ width, height = int(window_size.width() * 0.3), int(window_size.height() * 0.45)
self.resize(width, height)
self.setWindowTitle("Help - Neural Model Training")
@@ -356,32 +401,36 @@ def __init__(self, parent=None, window_size=None):
self.scrollArea.setFixedWidth(width)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
- self.scrollArea.setStyleSheet("background: 'black'; ")
self.scrollArea.setWidget(self.win)
# Add a list of hyperparameters and their descriptions with recommended values
main_text = """
- Training instructions
+ Instructions for Training
-
- - Select input data to be used for training the model and prediction
- - Set the hyperparameters for training the model
- - Select whether to save the model and predictions
-
+
+ - Choose the input data to be used for neural activity prediction.
+ - Select the output of the neural activity prediction model (neural principal components or neurons).
+ - Configure the hyperparameters for training the model.
+ - Indicate whether to save the output of the neural activity prediction model as yes/no.
+
- Hyperparameters
+
Output of the Model
- - Learning rate: Learning rate for the optimizer. Recommended value: 0.001
- - Weight decay: Weight decay for the optimizer. Recommended value: 0.0001
- - # Epochs: Number of epochs to train the model. Recommended value: 100
- - # Neurons split: Number of neurons in the split layer. Recommended value: 100
+ - The results of predicting neural activity are stored in files with the extensions *.npy and/or *.mat.
+ - The output comprises a dictionary with the following entries:
+
+ - predictions: a two-dimensional array containing the predicted neural activity, organized as (number of features x time)
+ - test_indices: a list of indices indicating which data segments were used for testing, thus determining the variance explained by the model
+ - variance_explained: the amount of variability accounted for by the model with respect to the test data
+ - plot_extent: the dimensions of the plot area employed to visualize the projected neural activity, presented in the order [x1, y1, x2, y2]
+
"""
main_text = QLabel(main_text, self)
main_text.setStyleSheet(
- "font-size: 12pt; font-family: Arial; color: white; text-align: center; "
+ "font-size: 12pt; font-family: Arial; text-align: center; "
)
main_text.setWordWrap(True)
layout.addWidget(main_text, stretch=1)
@@ -390,7 +439,7 @@ def __init__(self, parent=None, window_size=None):
self.ok_button = QPushButton("Ok")
self.ok_button.clicked.connect(self.close)
self.ok_button.setStyleSheet(
- "background: 'black'; color: 'white'; font-size: 12pt; font-family: Arial; "
+ "font-size: 12pt; font-family: Arial; "
)
layout.addWidget(self.ok_button, alignment=QtCore.Qt.AlignCenter)
diff --git a/facemap/gui/io.py b/facemap/gui/io.py
index 7243fb1..286d79a 100644
--- a/facemap/gui/io.py
+++ b/facemap/gui/io.py
@@ -234,7 +234,7 @@ def open_proc(parent, file_name=None):
int(parent.saturation[parent.iROI] * 100 / 255)
)
parent.ROIs[parent.iROI].plot(parent)
- if parent.processed and k <= 7:
+ if parent.processed and k <= 5:
parent.plot2_checkboxes[k].setText(
"%s%d" % (parent.typestr[r["rind"]], kt[r["rind"]])
)
@@ -380,8 +380,8 @@ def save_folder(parent):
if folderName:
parent.save_path = folderName
parent.output_folder_set = True
- if len(folderName) > 30:
- parent.savelabel.setText("..." + folderName[-30:])
+ if len(folderName) > 15:
+ parent.savelabel.setText("..." + folderName[-15:])
else:
parent.savelabel.setText(folderName)
diff --git a/facemap/gui/menus.py b/facemap/gui/menus.py
index 1544748..a6986b3 100644
--- a/facemap/gui/menus.py
+++ b/facemap/gui/menus.py
@@ -8,7 +8,6 @@
def mainmenu(parent):
# --------------- MENU BAR --------------------------
- # run suite2p from scratch
open_file = QAction("Load video", parent)
open_file.setShortcut("Ctrl+L")
open_file.triggered.connect(lambda: io.open_file(parent))
diff --git a/facemap/gui/ops_user.npy b/facemap/gui/ops_user.npy
index dcebfb2..a5f4c34 100755
Binary files a/facemap/gui/ops_user.npy and b/facemap/gui/ops_user.npy differ
diff --git a/facemap/mouse.png b/facemap/mouse.png
index fcf1e2e..7d8987e 100644
Binary files a/facemap/mouse.png and b/facemap/mouse.png differ
diff --git a/facemap/mouse_big.png b/facemap/mouse_big.png
new file mode 100644
index 0000000..3dbb287
Binary files /dev/null and b/facemap/mouse_big.png differ
diff --git a/facemap/pose/pose_helper_functions.py b/facemap/pose/pose_helper_functions.py
index a6995ce..13a7636 100644
--- a/facemap/pose/pose_helper_functions.py
+++ b/facemap/pose/pose_helper_functions.py
@@ -1,15 +1,15 @@
"""
Copright © 2023 Howard Hughes Medical Institute, Authored by Carsen Stringer and Atika Syeda.
"""
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Import packages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-import numpy as np
-
import random
from platform import python_version
import cv2 # opencv
import matplotlib
import matplotlib.pyplot as plt
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Import packages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+import numpy as np
import pyqtgraph as pg
import torch # pytorch
from PyQt5 import QtWidgets
diff --git a/facemap/pose/refine_pose.py b/facemap/pose/refine_pose.py
index 7e657f2..3a4db93 100644
--- a/facemap/pose/refine_pose.py
+++ b/facemap/pose/refine_pose.py
@@ -305,7 +305,7 @@ def show_choose_training_files(self):
self.spinbox_nframes = QSpinBox(self)
self.spinbox_nframes.setRange(1, self.gui.cumframes[-1])
- self.spinbox_nframes.setValue(25)
+ self.spinbox_nframes.setValue(15)
self.spinbox_nframes.setStyleSheet("QSpinBox {color: 'black';}")
self.get_num_frames_groupbox.layout().addWidget(self.spinbox_nframes)
diff --git a/facemap/version.py b/facemap/version.py
index f9b23d4..50515d4 100644
--- a/facemap/version.py
+++ b/facemap/version.py
@@ -2,10 +2,12 @@
Copright © 2023 Howard Hughes Medical Institute, Authored by Carsen Stringer and Atika Syeda.
"""
+import sys
from importlib.metadata import PackageNotFoundError, version
-import sys
from platform import python_version
-import torch, numpy
+
+import numpy
+import torch
try:
version = version("facemap")
diff --git a/paper/fig1.py b/paper/fig1.py
index 7710046..2e05ace 100644
--- a/paper/fig1.py
+++ b/paper/fig1.py
@@ -1,12 +1,14 @@
"""
Copright © 2023 Howard Hughes Medical Institute, Authored by Carsen Stringer and Atika Syeda.
"""
-import matplotlib
+import cv2
+import matplotlib
import matplotlib.pyplot as plt
+from fig_utils import *
from scipy.stats import wilcoxon
-import cv2
+
from facemap import keypoints
-from fig_utils import *
+
def panel_percentile_error(ax, data_path):
errors = np.load(f'{data_path}net_results/facemap_benchmark_distances.npy', allow_pickle=True).item()['test_distances']
diff --git a/paper/neuralpred.py b/paper/neuralpred.py
index ab8a2de..8a279c3 100644
--- a/paper/neuralpred.py
+++ b/paper/neuralpred.py
@@ -10,7 +10,7 @@
from scipy.interpolate import interp1d
from scipy.linalg import eigh
from scipy.ndimage import gaussian_filter1d
-from scipy.stats import zscore
+from scipy.stats import zscore
from sklearn.decomposition import PCA
from torch import nn
from torch.nn import functional as F
diff --git a/paper/suppfigs.py b/paper/suppfigs.py
index 0fd1350..e860a3c 100644
--- a/paper/suppfigs.py
+++ b/paper/suppfigs.py
@@ -10,6 +10,7 @@
from facemap.utils import bin1d
+
def varexp_ranks(data_path, dbs, evals=None, save_fig=False):
colors = [[0.5, 0.5, 0.5], [0.75, 0.75, 0.25]]
lbls = ["keypoints", "movie PCs"]