improvements for notifications and prepare for release

This commit is contained in:
tyler committed 2026-10-24 17:42:54 -07:00
1 parent d1c9346e57
commit a2456daca7
7 files changed
+221 -22

No files matched your search

+2 -1
View File
@@ -184,4 +184,5 @@ flares-*
*.flare
*.cfg
tempCodeRunnerFile.py
*.pkl
*.pkl
*.joblib
+3
View File
@@ -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
+1 -15
View File
@@ -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,
+23 -4
View File
@@ -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
+117
View File
@@ -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)}'"
+64 -1
View File
@@ -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
View File
@@ -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)