improvements for notifications and prepare for release
This commit is contained in:
1 parent
d1c9346e57
commit
a2456daca7
7 files changed
+221
-22
No files matched your search
+2
-1
@@ -184,4 +184,5 @@ flares-*
|
||||
*.flare
|
||||
*.cfg
|
||||
tempCodeRunnerFile.py
|
||||
*.pkl
|
||||
*.pkl
|
||||
*.joblib
|
||||
@@ -12,7 +12,10 @@
|
||||
- Export To CSV Viewer export options now perform the actions they claim rather than having no functionality
|
||||
- Logs on a per participant basis are now available to be viewed from within the application
|
||||
- They can be accessed by right clicking a participant bubble and selecting "Show Logs". Logs will be empty if they have not been processed
|
||||
- A notification now appears when processing completes even if the application is not focused
|
||||
- Fixed a regression where opening a folder would no longer load all the files in that folder
|
||||
- Added inspirational quotes to the About window
|
||||
- Licence is now clickable from the About window
|
||||
- Improved code stability and functionality
|
||||
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ from mne_nirs.statistics._glm_level_first import RegressionResults # type: igno
|
||||
from mne_connectivity.viz import plot_connectivity_circle # type: ignore
|
||||
from mne_connectivity import envelope_correlation, spectral_connectivity_epochs, spectral_connectivity_time # type: ignore
|
||||
|
||||
from src.shared.shareddata import PLATFORM_NAME, resource_path, get_app_dir
|
||||
from src.shared.shareddata import PLATFORM_NAME, resource_path, get_app_dir, METRIC_REGISTRY
|
||||
|
||||
|
||||
PRIMARY_COLORS = {
|
||||
@@ -7152,20 +7152,6 @@ def write_qc_excel_summary(
|
||||
wb.save(output_path)
|
||||
|
||||
|
||||
METRIC_REGISTRY = {
|
||||
'Peak_Amp': 'Peak_Amp',
|
||||
'TTP': 'Time_to_Peak',
|
||||
'AUC': 'AUC',
|
||||
'Rising_Slope': 'Rising_Slope',
|
||||
'Recovery_Slope': 'Recovery_Slope',
|
||||
'FWHM': 'FWHM',
|
||||
'Onset_Latency': 'Onset_Latency',
|
||||
'P2P_Amp': 'Peak_to_Peak_Amp',
|
||||
'Signal_Std': 'Signal_Std',
|
||||
'RMS': 'RMS'
|
||||
}
|
||||
|
||||
|
||||
def plot_and_enqueue_waveform_metrics(
|
||||
roi_curves,
|
||||
fir_delays,
|
||||
|
||||
@@ -31,7 +31,7 @@ if sys.platform.startswith("linux"):
|
||||
import psutil
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication, QWidget, QMessageBox, QVBoxLayout, QHBoxLayout, QTextEdit, QScrollArea, QComboBox, QGridLayout, QSplitter, QDialogButtonBox, QHeaderView,
|
||||
QApplication, QStyle, QSystemTrayIcon, QWidget, QMessageBox, QVBoxLayout, QHBoxLayout, QTextEdit, QScrollArea, QComboBox, QGridLayout, QSplitter, QDialogButtonBox, QHeaderView,
|
||||
QPushButton, QMainWindow, QLabel, QLineEdit, QGroupBox, QDialog, QMenu, QSpinBox, QTableWidget, QTableWidgetItem
|
||||
)
|
||||
from PySide6.QtCore import QEvent, QObject, Signal, Qt, QTimer
|
||||
@@ -738,6 +738,18 @@ class MainApplication(QMainWindow):
|
||||
|
||||
self.plugin_manager.reload_plugins()
|
||||
|
||||
self.tray_icon = QSystemTrayIcon(self)
|
||||
stock_icon = self.style().standardIcon(QStyle.StandardPixmap.SP_ComputerIcon) # Or use your own QIcon("path_to_logo.png")
|
||||
self.tray_icon.setIcon(stock_icon)
|
||||
self.tray_icon.show()
|
||||
|
||||
def bring_to_front():
|
||||
self.showNormal() # Restores if minimized
|
||||
self.raise_() # Brings to top of window stack (macOS/Linux)
|
||||
self.activateWindow() # Focuses the window (Windows)
|
||||
|
||||
self.tray_icon.messageClicked.connect(bring_to_front)
|
||||
|
||||
self.show()
|
||||
|
||||
# Check if we should pop up the welcome screen
|
||||
@@ -2361,9 +2373,16 @@ class MainApplication(QMainWindow):
|
||||
elapsed_str = self._format_elapsed(msg.get("elapsed", getattr(self, "_last_elapsed", 0)))
|
||||
speedup = msg.get("speedup")
|
||||
speedup_str = f" | Speedup: {speedup:.1f}x" if speedup else ""
|
||||
self.statusbar.showMessage(
|
||||
f"Complete: {success_count} succeeded, {fail_count} failed. | Total time: {elapsed_str}{speedup_str}"
|
||||
)
|
||||
status_text = f"Complete: {success_count} succeeded, {fail_count} failed. | Total time: {elapsed_str}{speedup_str}"
|
||||
self.statusbar.showMessage(status_text)
|
||||
|
||||
if hasattr(self, "tray_icon") and self.tray_icon.isSystemTrayAvailable():
|
||||
self.tray_icon.showMessage(
|
||||
"Process Completed",
|
||||
status_text,
|
||||
QSystemTrayIcon.MessageIcon.Information,
|
||||
4000 # Duration in milliseconds
|
||||
)
|
||||
|
||||
if success_count > 0:
|
||||
self.is_saved = False
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
"""
|
||||
Filename: inspiration.py
|
||||
Description: Contains inspiration quotes to be shown at random
|
||||
Note: Compliant with pylance strict type checking
|
||||
|
||||
Author: Tyler de Zeeuw
|
||||
License: GPL-3.0
|
||||
"""
|
||||
|
||||
# Built-in imports
|
||||
import random
|
||||
|
||||
FNIRS_QUOTES = [
|
||||
"Understanding the brain through light and data.",
|
||||
"Every signal offers another perspective on brain function.",
|
||||
"Exploring the relationship between brain activity and behavior.",
|
||||
"Using light to investigate the complexity of the human brain.",
|
||||
"Turning neural measurements into meaningful insights.",
|
||||
"A deeper understanding of the brain begins with better questions.",
|
||||
"Studying the brain means looking beyond what we can see.",
|
||||
"Connecting brain activity to the way we think, feel, and act.",
|
||||
"Even small changes in brain signals can reveal meaningful patterns.",
|
||||
"Advancing neuroscience through new ways of measuring brain activity.",
|
||||
"The brain is complex, and every measurement adds another piece.",
|
||||
"Using fNIRS to explore the connection between the brain and the world around us.",
|
||||
"Good science begins with curiosity and grows through careful observation.",
|
||||
"There is still so much to learn about how the brain works.",
|
||||
"Measuring brain activity is only the beginning; understanding it is the goal.",
|
||||
"Exploring what brain activity can tell us about the human experience.",
|
||||
"Every experiment brings a new opportunity to understand the brain.",
|
||||
"The more we measure, the more questions we learn to ask.",
|
||||
"Neuroscience advances through careful measurements and thoughtful interpretation.",
|
||||
"Understanding brain function requires looking at both signals and context.",
|
||||
"Each dataset offers a different view of the brain in action.",
|
||||
"Exploring the neural processes behind everyday human experiences.",
|
||||
"Better measurements can lead to better questions about the brain.",
|
||||
"The challenge is not just collecting data, but understanding what it means.",
|
||||
"Brain activity reflects a complex interaction of processes and experiences.",
|
||||
"Scientific progress begins with observing what we do not yet understand.",
|
||||
"Each discovery builds on the questions that came before it.",
|
||||
"There is more to brain activity than a single signal can reveal.",
|
||||
"New tools create new opportunities to investigate old questions.",
|
||||
"The goal is to connect what we measure with what we want to understand.",
|
||||
"Neural signals provide clues to the processes underlying human behavior.",
|
||||
"A better understanding of brain function starts with better evidence.",
|
||||
"The value of a measurement lies in what it helps us understand.",
|
||||
"Every experiment adds another perspective to a complex picture.",
|
||||
"Scientific discovery often begins with noticing something unexpected.",
|
||||
"Understanding the brain is an ongoing process of questioning and refinement.",
|
||||
"The best insights emerge when data meets thoughtful interpretation.",
|
||||
"Research moves forward when curiosity is matched with rigorous methods.",
|
||||
"There is always another question worth exploring.",
|
||||
"Investigating the brain means embracing complexity rather than avoiding it.",
|
||||
"Progress comes from asking precise questions about complicated systems.",
|
||||
"The brain does not work in isolation from the person or environment.",
|
||||
"Understanding behavior requires more than observing behavior alone.",
|
||||
"The smallest details can sometimes change how we interpret the bigger picture.",
|
||||
"Every method offers a different window into brain function.",
|
||||
"Different perspectives help build a more complete understanding of the brain.",
|
||||
"Good research turns uncertainty into questions that can be investigated.",
|
||||
"The process of discovery is as important as the result.",
|
||||
"Meaningful findings begin with reliable data and careful reasoning.",
|
||||
"The brain is not simple, and our methods should reflect that complexity.",
|
||||
"Scientific understanding grows when evidence challenges our assumptions.",
|
||||
"Research is a process of learning what the data can—and cannot—tell us.",
|
||||
"The most useful findings are those that move understanding forward.",
|
||||
"Each new method expands the questions we can ask about the brain.",
|
||||
"The path to understanding is built from observations, questions, and evidence.",
|
||||
"Neuroscience is about understanding the processes behind the patterns.",
|
||||
"The aim is not simply to measure brain activity, but to interpret it meaningfully.",
|
||||
"Better tools help us investigate the questions that matter.",
|
||||
"Progress in neuroscience depends on both technical precision and human curiosity.",
|
||||
"The brain is complex, but every careful observation helps clarify a part of it.",
|
||||
"Understanding brain function means connecting measurements to meaningful outcomes.",
|
||||
"Research turns curiosity into evidence and evidence into understanding.",
|
||||
"There is a story behind every pattern, but evidence determines what we can conclude.",
|
||||
"New insights emerge when we approach familiar questions from different angles.",
|
||||
"The strongest conclusions begin with careful measurements.",
|
||||
"Understanding the brain takes more than data; it takes context.",
|
||||
"The questions we ask shape what we learn from the brain.",
|
||||
"Good research is not about finding answers quickly, but finding them carefully.",
|
||||
"Every result contributes to a larger conversation about how the brain works.",
|
||||
"The human brain remains an evolving question for science.",
|
||||
"Measuring brain activity gives us another way to investigate human cognition.",
|
||||
"The connection between brain function and behavior is rarely straightforward.",
|
||||
"Scientific progress comes from combining new methods with careful interpretation.",
|
||||
"The more we learn about the brain, the better our questions become.",
|
||||
"Research is the practice of making uncertainty more understandable.",
|
||||
"Understanding the brain means being willing to revise what we think we know.",
|
||||
"Each experiment helps define what we know and what remains uncertain.",
|
||||
"The most interesting findings often begin with questions that have no easy answers.",
|
||||
"The purpose of research is to move beyond assumptions toward evidence.",
|
||||
"A measurement becomes useful when it helps answer a meaningful question.",
|
||||
"Neuroscience brings together technology, observation, and the study of human experience.",
|
||||
"fNIRS offers another way to investigate changes in brain hemodynamics.",
|
||||
"Optical measurements provide a noninvasive approach to studying brain function.",
|
||||
"Studying brain function outside the lab can reveal aspects of everyday cognition.",
|
||||
"The flexibility of fNIRS opens new possibilities for human neuroscience research.",
|
||||
"Brain measurements become more meaningful when considered alongside behavior.",
|
||||
"fNIRS provides a useful perspective on the relationship between physiology and cognition.",
|
||||
"Understanding the strengths and limitations of a method is part of good science.",
|
||||
"The future of neuroscience depends on asking better questions, not just collecting more data.",
|
||||
"Technology expands what we can measure, while critical thinking guides what we conclude.",
|
||||
"The goal of neuroscience is not just to observe the brain, but to understand its function.",
|
||||
"Every research method brings its own perspective, possibilities, and limitations.",
|
||||
"The most meaningful discoveries connect technical advances to real-world questions.",
|
||||
"Better ways to study the brain can lead to a better understanding of human experience.",
|
||||
"Science progresses when we remain curious about what the evidence cannot yet explain.",
|
||||
"Understanding the brain is a long-term effort built on many small discoveries.",
|
||||
"Behind every useful finding is a question worth investigating.",
|
||||
"The value of research lies in what we learn, not just what we measure.",
|
||||
"Good science makes room for complexity, uncertainty, and new perspectives.",
|
||||
"The next insight may come from looking at a familiar problem in a different way.",
|
||||
]
|
||||
|
||||
def get_quote() -> None:
|
||||
return f"'{random.choice(FNIRS_QUOTES)}'"
|
||||
@@ -8,12 +8,18 @@ License: GPL-3.0
|
||||
"""
|
||||
|
||||
# Built-in imports
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import platform
|
||||
|
||||
try:
|
||||
import winreg
|
||||
except ImportError:
|
||||
winreg = None
|
||||
|
||||
CURRENT_VERSION = "1.7.2"
|
||||
CURRENT_VERSION = "1.8.0"
|
||||
APP_NAME = "flares"
|
||||
APP_NAME_EXPANDED = "fNIRS Lightweight Analysis, Research, & Evaluation Suite"
|
||||
API_URL = f"https://git.research.dezeeuw.ca/api/v1/repos/tyler/{APP_NAME}/releases"
|
||||
@@ -72,6 +78,63 @@ DATA_SCHEMA = [
|
||||
]
|
||||
|
||||
|
||||
METRIC_REGISTRY = {
|
||||
"Peak_Amp": "Peak_Amp",
|
||||
"TTP": "Time_to_Peak",
|
||||
"AUC": "AUC",
|
||||
"Rising_Slope": "Rising_Slope",
|
||||
"Recovery_Slope": "Recovery_Slope",
|
||||
"FWHM": "FWHM",
|
||||
"Onset_Latency": "Onset_Latency",
|
||||
"P2P_Amp": "Peak_to_Peak_Amp",
|
||||
"Signal_Std": "Signal_Std",
|
||||
"RMS": "RMS",
|
||||
}
|
||||
|
||||
|
||||
def get_cpu_model_name():
|
||||
"""Detect detailed processor info, collapsing Windows registry whitespace padding."""
|
||||
try:
|
||||
system = platform.system()
|
||||
|
||||
if system == "Windows" and winreg is not None:
|
||||
with winreg.OpenKey(
|
||||
winreg.HKEY_LOCAL_MACHINE,
|
||||
r"HARDWARE\DESCRIPTION\System\CentralProcessor\0",
|
||||
) as key:
|
||||
raw_cpu_name, _ = winreg.QueryValueEx(key, "ProcessorNameString")
|
||||
cpu_name = " ".join(raw_cpu_name.split())
|
||||
|
||||
command = (
|
||||
"Get-CimInstance Win32_Processor | "
|
||||
"Select-Object NumberOfCores, NumberOfLogicalProcessors, MaxClockSpeed | "
|
||||
"ConvertTo-Json -Compress"
|
||||
)
|
||||
cpu = json.loads(subprocess.check_output(
|
||||
["powershell", "-NoProfile", "-Command", command],
|
||||
text=True,
|
||||
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
|
||||
))
|
||||
base_ghz = cpu["MaxClockSpeed"] / 1000
|
||||
return (f"{cpu_name} @ {base_ghz:.1f}GHz "
|
||||
f"{cpu['NumberOfCores']}c/{cpu['NumberOfLogicalProcessors']}t")
|
||||
|
||||
if system == "Darwin":
|
||||
return subprocess.check_output(
|
||||
["sysctl", "-n", "machdep.cpu.brand_string"], text=True
|
||||
).strip()
|
||||
|
||||
if system == "Linux":
|
||||
with open("/proc/cpuinfo") as f:
|
||||
for line in f:
|
||||
if "model name" in line:
|
||||
return line.split(":")[1].strip()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return platform.processor() or "Multi-Core CPU"
|
||||
|
||||
|
||||
def resource_path(relative_path: str) -> str:
|
||||
"""Get absolute path to resource regardless of running directly or packaged using PyInstaller"""
|
||||
base_path = getattr(sys, "_MEIPASS", os.path.abspath("."))
|
||||
|
||||
+11
-1
@@ -12,6 +12,7 @@ from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
from src.shared.shareddata import APP_NAME, APP_NAME_EXPANDED, CURRENT_VERSION
|
||||
from src.shared.inspiration import get_quote
|
||||
|
||||
|
||||
class AboutWindow(QWidget):
|
||||
@@ -30,12 +31,21 @@ class AboutWindow(QWidget):
|
||||
layout = QVBoxLayout()
|
||||
label = QLabel(f"About {APP_NAME.upper()}", self)
|
||||
label2 = QLabel(f"{APP_NAME_EXPANDED}", self)
|
||||
label3 = QLabel(f"{APP_NAME.upper()} is licensed under the GPL-3.0 licence. For more information, visit https://www.gnu.org/licenses/gpl-3.0.en.html", self)
|
||||
label3 = QLabel(
|
||||
f'{APP_NAME.upper()} is licensed under the GPL-3.0 licence. '
|
||||
'For more information, visit '
|
||||
'<a href="https://www.gnu.org/licenses/gpl-3.0.en.html">'
|
||||
'GNU GPL-3.0</a>',
|
||||
self,
|
||||
)
|
||||
label3.setOpenExternalLinks(True)
|
||||
label4 = QLabel(f"Version v{CURRENT_VERSION}")
|
||||
label5 = QLabel(f"{get_quote()}", self)
|
||||
|
||||
layout.addWidget(label)
|
||||
layout.addWidget(label2)
|
||||
layout.addWidget(label3)
|
||||
layout.addWidget(label4)
|
||||
layout.addWidget(label5)
|
||||
|
||||
self.setLayout(layout)
|
||||
Reference in new issue
Block a user