Source code for dbs_annotator.config

"""
Configuration module for DBS Annotator.

This module contains all constants, presets, and configuration values used
throughout the application.
"""

from __future__ import annotations

from .version import get_version

# Human-facing product name (window titles, dialogs, documentation).
APP_NAME = "DBS Annotator"
APP_VERSION = get_version()

# Publisher (UI, About, docs). Not used for on-disk paths.
ORGANIZATION_PUBLISHER = "Wyss Center for Bio and Neuroengineering"

# Copyright holders shown in Help, documentation, and license notices.
COPYRIGHT_HOLDERS = (
    "Massachusetts General Hospital, "
    "Wyss Center for Bio and Neuroengineering, "
    "and Charité Universitätsmedizin Berlin"
)

# SPDX-style license name (see LICENSE in the repository root).
APP_LICENSE_NAME = "MIT License"

# Lead author (About; list same person first in package metadata).
APP_LEAD_AUTHOR = "Lucia Poma"
APP_MAINTAINER = "Richard Köhler"

# Qt application identity for :func:`QStandardPaths` and :class:`QSettings`.
# Use ASCII without spaces so per-user directories never contain spaces
# (``%LOCALAPPDATA%\\<org>\\<app>\\``, Application Support on macOS, etc.).
FS_ORG_NAME = "WyssGeneva"
FS_APP_NAME = "DBSAnnotator"

# Canonical upstream (releases + issue tracker; keep aligned with updater repo slug).
APP_REPOSITORY_URL = "https://github.com/Brain-Modulation-Lab/DBSAnnotator"
APP_ISSUES_URL = f"{APP_REPOSITORY_URL}/issues"


[docs] def github_repository_slug(repository_url: str) -> str: """Return ``owner/repo`` from a ``https://github.com/owner/repo`` URL.""" prefix = "https://github.com/" if not repository_url.startswith(prefix): raise ValueError( f"Expected a GitHub repository URL starting with {prefix!r}, " f"got {repository_url!r}" ) rest = repository_url.removeprefix(prefix).strip("/") owner, sep, repo = rest.partition("/") if not sep or not owner or not repo: raise ValueError( f"Could not parse owner/repo from GitHub URL {repository_url!r}" ) return f"{owner}/{repo.split('/')[0]}"
# GitHub Releases API slug for :mod:`dbs_annotator.utils.updater`. RELEASES_GITHUB_REPO = github_repository_slug(APP_REPOSITORY_URL) # Primary contact for feedback (same person as APP_LEAD_AUTHOR). UPDATE_FEEDBACK_EMAIL = "lucia.poma@wysscenter.ch" # File paths (relative to executable) ICON_FILENAME = "logosimple.png" ICO_FILENAME = "logosimple.ico" STYLE_FILENAME = "style.qss" ICONS_DIR = "icons/logosimple" # Window size ratios for responsive design WINDOW_SIZE_RATIO = { "width": 0.95, "height": 0.95, } # Responsive window size ratios based on screen size RESPONSIVE_WINDOW_RATIOS = { "small": {"width": 0.9, "height": 0.85}, # < 1400px width "medium": {"width": 0.85, "height": 0.8}, # 1400-1919px width "large": {"width": 0.75, "height": 0.75}, # >= 1920px width } # Screen size thresholds SCREEN_SIZE_THRESHOLDS = { "small": 1400, "medium": 1920, } # Minimum window size (in pixels) for usability WINDOW_MIN_SIZE = { "width": 1000, # Increased from 600 for better usability "height": 700, # Increased from 400 for better usability } # Maximum window size ratio (prevents window from being too large on big screens) WINDOW_MAX_SIZE_RATIO = { "width": 0.98, "height": 0.98, } # Responsive font scaling based on DPI FONT_SCALE_ENABLED = False # Disabilitato per schermi piccoli BASE_DPI = 96 # Standard DPI # TSV file configuration TSV_COLUMNS = [ "date", "time", "timezone", "block_ID", "session_ID", "is_initial", "scale_name", "scale_value", "electrode_model", "program_ID", "left_stim_freq", "left_anode", "left_cathode", "left_amplitude", "left_pulse_width", "right_stim_freq", "right_anode", "right_cathode", "right_amplitude", "right_pulse_width", "notes", ] # Annotations-only TSV file configuration. ANNOTATION_TSV_COLUMNS = [ "date", "time", "timezone", "notes", ] # Timezone configuration TIMEZONE = "local" # Validation limits STIMULATION_LIMITS = { "frequency": {"min": 10, "max": 200, "step1": 10, "step2": 5}, "amplitude": {"min": 0.0, "max": 15.0, "decimals": 2, "step1": 1, "step2": 0.5}, "pulse_width": {"min": 10, "max": 200, "step1": 10, "step2": 5}, } SESSION_SCALE_LIMITS = { "min": 0, "max": 10, "decimals": 2, "step1": 1, "step2": 0.5, } CLINICAL_SCALES_PRESETS: dict[str, list[str]] = { "OCD": [ "Y-BOCS", # Yale–Brown Obsessive–Compulsive Scale "Y-BOCS-o", # Yale–Brown Obsessive–Compulsive Scale - obsessions "Y-BOCS-c", # Yale–Brown Obsessive–Compulsive Scale - compulsions "MADRS", # Montgomery–Åsberg Depression Rating Scale "OCI-R", # Obsessive–Compulsive Inventory – Revised ], "MDD": [ "MADRS", # Montgomery–Åsberg Depression Rating Scale "HAM-D", # Hamilton Depression Rating Scale "BDI-II", # Beck Depression Inventory – Second Edition ], "PD": [ # Movement Disorder Society – Unified Parkinson’s Disease Rating Scale "MDS-UPDRS", "UPDRS-III", # Unified Parkinson’s Disease Rating Scale part III "PDQ-39", # Parkinson’s Disease Questionnaire (39-item) "UDysRS", # Unified Dyskinesia Rating Scale ], "ET": [ "FTM-TRS", # Fahn–Tolosa–Marin Tremor Rating Scale "TETRAS", # The Essential Tremor Rating Assessment Scale ], "Dystonia": [ "BFMDRS", # Burke–Fahn–Marsden Dystonia Rating Scale "TWSTRS", # Toronto Western Spasmodic Torticollis Rating Scale ], "TS": [ "YGTSS", # Yale Global Tic Severity Scale "PUTS", # Premonitory Urge for Tics Scale "TS-CGI", # Tourette Syndrome Clinical Global Impression "Y-BOCS", # Yale–Brown Obsessive–Compulsive Scale ], } SESSION_SCALES_PRESETS: dict[str, list[tuple[str, str, str]]] = { "OCD": [ ("Obsessions", "0", "10"), ("Compulsions", "0", "10"), ("Anxiety", "0", "10"), ("Mood", "0", "10"), ("Energy", "0", "10"), ], "MDD": [ ("Rumination", "0", "10"), ("Anxiety", "0", "10"), ("Mood", "0", "10"), ("Energy", "0", "10"), ], "PD": [ ("Tremor", "0", "10"), ("Rigidity", "0", "10"), ("Bradykinesia", "0", "10"), ("Dyskinesia", "0", "10"), ("Gait / balance", "0", "10"), ("Paresthesia", "0", "10"), ("Speech difficulty", "0", "10"), ], "ET": [ ("Action tremor", "0", "10"), ("Resting tremor", "0", "10"), ("Paresthesia", "0", "10"), ("Speech difficulty", "0", "10"), ], "Dystonia": [ ("Muscle contractions", "0", "10"), ("Abnormal posture", "0", "10"), ("Pain", "0", "10"), ], "TS": [ ("Tic severity", "0", "10"), ("Premonitory urge", "0", "10"), ("Control over tics", "0", "10"), ("Anxiety", "0", "10"), ("Impulsivity", "0", "10"), ], } PRESET_BUTTONS = ["OCD", "MDD", "PD", "ET", "Dystonia", "TS"] COLORS = { "primary": "#ff8800", "background": "#23272f", "text": "#e0e0e0", "button_pressed": "#ff6600", "separator": "#3a3a3a", } FONTS = { "default": ("Segoe UI", 12), "section": ("Segoe UI", 16), "title": ("Segoe UI", 20), } # Animation settings BUTTON_PULSE_COUNT = 3 BUTTON_PULSE_DURATION = 120 # milliseconds # UI Component sizes ICON_SIZES = { "logo_step1": 90, "logo_other": 70, "arrow": (22, 22), "increment": (16, 16), } BUTTON_SIZES = { "browse": 40, "navigation": 150, "preset": {"min_width": 30, "max_width": 40, "min_height": 18, "max_height": 24}, "increment": {"width": 20, "height": 14}, } PLACEHOLDERS = { "frequency": "Hz", "contact": "E#", "amplitude": "mA", "pulse_width": "µs", "scale_value": "Value", "scale_name": "Scale", "scale_score": "Score", "scale_min": "Min", "scale_max": "Max", }