Skip to content

Commit 839e8d7

Browse files
Merge remote-tracking branch 'upstream' into feat/improve-typing
2 parents 205c268 + 2c75dec commit 839e8d7

65 files changed

Lines changed: 383 additions & 181 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
A desktop application for annotating Deep Brain Stimulation (DBS) clinical programming sessions. Built for clinicians and researchers working with DBS systems (Medtronic Percept and others).
44

5-
**Version:** derived from `clinical_dbs_annotator.__version__`
5+
**Version:** derived from `dbs_annotator.__version__`
66
**Author:** Lucia Poma (lucia.poma@wysscenter.ch)
77

88
## For End Users
@@ -79,14 +79,14 @@ pip install -e .
7979
```bash
8080
python run.py
8181
# or
82-
python -m clinical_dbs_annotator
82+
python -m dbs_annotator
8383
```
8484

8585
### Project Structure
8686

8787
```
8888
App_ClinicalDBSAnnot/
89-
├── src/clinical_dbs_annotator/ # Application source code
89+
├── src/dbs_annotator/ # Application source code
9090
│ ├── models/ # Data models (session, scales, stimulation, electrode)
9191
│ ├── views/ # Qt views (step0-3, annotations, wizard window)
9292
│ ├── controllers/ # Business logic (wizard controller)
-95.2 MB
Binary file not shown.

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from datetime import datetime
44
from importlib import metadata
55

6-
_DIST_NAME = "clinical-dbs-annotator"
6+
_DIST_NAME = "dbs-annotator"
77

88
project = "Clinical DBS Annotator"
99
author = "Lucia Poma"

pyproject.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[project]
2-
name = "clinical-dbs-annotator"
2+
name = "dbs-annotator"
33
description = "A graphical user interface for annotating DBS clinical programming sessions"
44
readme = "README.md"
55
requires-python = ">=3.14"
@@ -52,22 +52,22 @@ docs = [
5252
]
5353

5454
[project.scripts]
55-
clinical-dbs-annotator = "clinical_dbs_annotator.__main__:main"
55+
dbs-annotator = "dbs_annotator.__main__:main"
5656

5757
[project.urls]
58-
Homepage = "https://github.com/bml/clinical-dbs-annotator"
59-
Repository = "https://github.com/bml/clinical-dbs-annotator"
60-
Documentation = "https://github.com/bml/clinical-dbs-annotator/blob/main/README.md"
58+
Homepage = "https://github.com/bml/dbs-annotator"
59+
Repository = "https://github.com/bml/dbs-annotator"
60+
Documentation = "https://github.com/bml/dbs-annotator/blob/main/README.md"
6161

6262
[build-system]
6363
requires = ["hatchling"]
6464
build-backend = "hatchling.build"
6565

6666
[tool.hatch.version]
67-
path = "src/clinical_dbs_annotator/__init__.py"
67+
path = "src/dbs_annotator/__init__.py"
6868

6969
[tool.hatch.build.targets.wheel]
70-
packages = ["src/clinical_dbs_annotator"]
70+
packages = ["src/dbs_annotator"]
7171

7272
[tool.pytest.ini_options]
7373
testpaths = ["tests"]
@@ -76,7 +76,7 @@ python_classes = ["Test*"]
7676
python_functions = ["test_*"]
7777
addopts = [
7878
"--verbose",
79-
"--cov=clinical_dbs_annotator",
79+
"--cov=dbs_annotator",
8080
"--cov-report=html",
8181
"--cov-report=term-missing",
8282
]

run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
import sys
1212

13-
from clinical_dbs_annotator.__main__ import main
13+
from dbs_annotator.__main__ import main
1414

1515
if __name__ == "__main__":
1616
sys.exit(main())

scripts/ClinicalDBSAnnotator.iss

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
; Inno Setup installer script for ClinicalDBSAnnotator
2+
; Requires Inno Setup 6.x or later to compile
3+
; Auto-generated by generate_iss.py - DO NOT EDIT MANUALLY
4+
5+
#define AppName "ClinicalDBSAnnotator"
6+
#define AppVersion "0.3.0"
7+
#define AppPublisher "Brain Modulation Lab"
8+
#define AppURL "https://github.com/bml/dbs-annotator"
9+
#define AppExeName "ClinicalDBSAnnotator_Windows_0_3_0.exe"
10+
11+
[Setup]
12+
AppId={{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
13+
AppName={#AppName}
14+
AppVersion={#AppVersion}
15+
AppPublisher={#AppPublisher}
16+
AppPublisherURL={#AppURL}
17+
AppSupportURL={#AppURL}
18+
AppUpdatesURL={#AppURL}
19+
DefaultDirName={autopf}\{#AppName}
20+
DefaultGroupName={#AppName}
21+
AllowNoIcons=yes
22+
OutputDir=installer_output
23+
OutputBaseFilename={#AppName}_Setup_{#AppVersion}_Windows
24+
Compression=lzma2/max
25+
SolidCompression=yes
26+
WizardStyle=Modern
27+
SetupIconFile=..\icons\logoneutral.ico
28+
UninstallDisplayIcon={app}\{#AppExeName}
29+
ChangesAssociations=yes
30+
31+
[Languages]
32+
Name: "english"; MessagesFile: "compiler:Default.isl"
33+
Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"
34+
35+
[Tasks]
36+
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
37+
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; OnlyBelowVersion: 6.1
38+
39+
[Files]
40+
; Main application files from PyInstaller onedir build
41+
Source: "dist\ClinicalDBSAnnotator_Windows_0_3_0\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
42+
; Icon file for shortcuts
43+
Source: "..\icons\logoneutral.ico"; DestDir: "{app}"; Flags: ignoreversion
44+
45+
[Icons]
46+
Name: "{group}\{#AppName}"; Filename: "{app}\{#AppExeName}"; IconFilename: "{app}\logoneutral.ico"
47+
Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; IconFilename: "{app}\logoneutral.ico"; Tasks: desktopicon
48+
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#AppName}"; Filename: "{app}\{#AppExeName}"; IconFilename: "{app}\logoneutral.ico"; Tasks: quicklaunchicon
49+
50+
[Run]
51+
Filename: "{app}\{#AppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
52+
53+
[Registry]
54+
; File association for .tsv annotation files
55+
Root: HKCR; Subkey: ".tsv\OpenWithProgids"; ValueType: string; ValueName: "ClinicalDBSAnnotator.tsv"; ValueData: ""; Flags: uninsdeletevalue
56+
Root: HKCR; Subkey: "ClinicalDBSAnnotator.tsv"; ValueType: string; ValueName: ""; ValueData: "Clinical DBS Annotator File"; Flags: uninsdeletekey
57+
Root: HKCR; Subkey: "ClinicalDBSAnnotator.tsv\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\logoneutral.ico,0"
58+
Root: HKCR; Subkey: "ClinicalDBSAnnotator.tsv\shell\open\command"; ValueType: string; ValueName: ""; ValueData: ""{app}\{#AppExeName}" "%1""
59+
60+
[UninstallDelete]
61+
Type: filesandordirs; Name: "{app}"

scripts/build_macos.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424

2525
def _read_version() -> str:
26-
init_path = SRC_DIR / "clinical_dbs_annotator" / "__init__.py"
26+
init_path = SRC_DIR / "dbs_annotator" / "__init__.py"
2727
text = init_path.read_text(encoding="utf-8")
2828
m = re.search(
2929
r'^__version__\s*=\s*["\']([^"\']+)["\']\s*$', text, flags=re.MULTILINE
@@ -72,7 +72,7 @@ def build_macos_app(*, console: bool, onefile: bool):
7272
name = f"{APP_NAME}_{PLATFORM}_{VERSION.replace('.', '_')}"
7373
entrypoint = PROJECT_ROOT / "run.py"
7474
styles_dir = PROJECT_ROOT / "styles"
75-
config_dir = SRC_DIR / "clinical_dbs_annotator" / "config"
75+
config_dir = SRC_DIR / "dbs_annotator" / "config"
7676

7777
icon_icns = ICONS_DIR / "logoneutral.icns"
7878
icon_fallback = ICONS_DIR / "logoneutral.ico"
@@ -98,11 +98,11 @@ def build_macos_app(*, console: bool, onefile: bool):
9898
"--hidden-import=pandas",
9999
"--hidden-import=openpyxl",
100100
"--hidden-import=xlrd",
101-
"--hidden-import=PySide6.QtCore",
102-
"--hidden-import=PySide6.QtGui",
103-
"--hidden-import=PySide6.QtWidgets",
101+
"--hidden-import=dbs_annotator",
102+
"--collect-all=PySide6",
104103
"--exclude-module=PySide6.QtWebEngineWidgets",
105104
"--exclude-module=PySide6.QtWebEngineCore",
105+
"--osx-bundle-identifier=com.bml.dbs-annotator",
106106
# Add data files (macOS uses : separator)
107107
f"--add-data={ICONS_DIR / 'logoneutral.ico'}:icons",
108108
f"--add-data={ICONS_DIR / 'logoneutral.png'}:icons",
@@ -124,6 +124,16 @@ def build_macos_app(*, console: bool, onefile: bool):
124124
else:
125125
cmd.append("--windowed")
126126

127+
# Add package metadata for version detection (macOS venv layout)
128+
venv_lib = PROJECT_ROOT / ".venv" / "lib"
129+
if venv_lib.exists():
130+
# macOS: .venv/lib/pythonX.Y/site-packages
131+
dist_info_dirs = list(
132+
venv_lib.glob("python*/site-packages/dbs_annotator*.dist-info")
133+
)
134+
if dist_info_dirs:
135+
cmd.append(f"--add-data={dist_info_dirs[0]}:.")
136+
127137
# Run PyInstaller
128138
try:
129139
subprocess.run(cmd, check=True, cwd=PROJECT_ROOT)
@@ -168,8 +178,8 @@ def main():
168178
ICONS_DIR / "logoneutral.png",
169179
PROJECT_ROOT / "styles" / "dark_theme.qss",
170180
PROJECT_ROOT / "styles" / "light_theme.qss",
171-
SRC_DIR / "clinical_dbs_annotator" / "config" / "clinical_presets.json",
172-
SRC_DIR / "clinical_dbs_annotator" / "config" / "session_scales_presets.json",
181+
SRC_DIR / "dbs_annotator" / "config" / "clinical_presets.json",
182+
SRC_DIR / "dbs_annotator" / "config" / "session_scales_presets.json",
173183
]
174184

175185
for path in required_files:

scripts/build_windows.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222

2323
def _read_version() -> str:
24-
init_path = SRC_DIR / "clinical_dbs_annotator" / "__init__.py"
24+
init_path = SRC_DIR / "dbs_annotator" / "__init__.py"
2525
text = init_path.read_text(encoding="utf-8")
2626
m = re.search(
2727
r'^__version__\s*=\s*["\']([^"\']+)["\']\s*$', text, flags=re.MULTILINE
@@ -41,7 +41,7 @@ def build_windows_exe(*, console: bool, onefile: bool) -> bool:
4141
name = f"{APP_NAME}_{PLATFORM}_{VERSION.replace('.', '_')}"
4242
entrypoint = PROJECT_ROOT / "run.py"
4343
styles_dir = PROJECT_ROOT / "styles"
44-
config_dir = SRC_DIR / "clinical_dbs_annotator" / "config"
44+
config_dir = SRC_DIR / "dbs_annotator" / "config"
4545

4646
cmd = [
4747
sys.executable,
@@ -58,6 +58,7 @@ def build_windows_exe(*, console: bool, onefile: bool) -> bool:
5858
"--hidden-import=pandas",
5959
"--hidden-import=openpyxl",
6060
"--hidden-import=xlrd",
61+
"--hidden-import=dbs_annotator",
6162
]
6263

6364
if onefile:
@@ -84,6 +85,13 @@ def build_windows_exe(*, console: bool, onefile: bool) -> bool:
8485
]
8586
)
8687

88+
# Add package metadata for version detection
89+
venv_site_packages = PROJECT_ROOT / ".venv" / "Lib" / "site-packages"
90+
dist_info_dirs = list(venv_site_packages.glob("dbs_annotator*.dist-info"))
91+
if dist_info_dirs:
92+
dist_info = dist_info_dirs[0]
93+
cmd.append(f"--add-data={dist_info};.")
94+
8795
try:
8896
subprocess.run(cmd, check=True, cwd=PROJECT_ROOT)
8997
print("\n✓ Build successful!")

scripts/build_windows_nuitka.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@
2525
BUILD_DIR = PROJECT_ROOT / "build"
2626
ICONS_DIR = PROJECT_ROOT / "icons"
2727
STYLES_DIR = PROJECT_ROOT / "styles"
28-
CONFIG_DIR = SRC_DIR / "clinical_dbs_annotator" / "config"
28+
CONFIG_DIR = SRC_DIR / "dbs_annotator" / "config"
2929

3030
NAME = "ClinicalDBSAnnotator"
3131
ENTRYPOINT = PROJECT_ROOT / "run.py"
3232

3333

3434
def _read_version() -> str:
35-
init_path = SRC_DIR / "clinical_dbs_annotator" / "__init__.py"
35+
init_path = SRC_DIR / "dbs_annotator" / "__init__.py"
3636
text = init_path.read_text(encoding="utf-8")
3737
m = re.search(
3838
r'^__version__\s*=\s*["\']([^"\']+)["\']\s*$', text, flags=re.MULTILINE

scripts/generate_iss.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
"""Generate InnoSetup script with current version from __init__.py."""
2+
3+
import re
4+
from pathlib import Path
5+
6+
PROJECT_ROOT = Path(__file__).parent.parent
7+
SRC_DIR = PROJECT_ROOT / "src"
8+
INIT_PATH = SRC_DIR / "dbs_annotator" / "__init__.py"
9+
10+
11+
def read_version() -> str:
12+
"""Read version from __init__.py."""
13+
text = INIT_PATH.read_text(encoding="utf-8")
14+
m = re.search(
15+
r'^__version__\s*=\s*["\']([^"\']+)["\']\s*$', text, flags=re.MULTILINE
16+
)
17+
if not m:
18+
raise RuntimeError(f"Could not determine version from {INIT_PATH}")
19+
return m.group(1)
20+
21+
22+
def generate_iss(version: str) -> None:
23+
"""Generate ClinicalDBSAnnotator.iss with current version."""
24+
version_underscore = version.replace(".", "_")
25+
# Use $V$ and $VU$ as placeholders to avoid any conflict with InnoSetup braces
26+
iss_content = """\
27+
; Inno Setup installer script for ClinicalDBSAnnotator
28+
; Requires Inno Setup 6.x or later to compile
29+
; Auto-generated by generate_iss.py - DO NOT EDIT MANUALLY
30+
31+
#define AppName "ClinicalDBSAnnotator"
32+
#define AppVersion "$V$"
33+
#define AppPublisher "Brain Modulation Lab"
34+
#define AppURL "https://github.com/bml/dbs-annotator"
35+
#define AppExeName "ClinicalDBSAnnotator_Windows_$VU$.exe"
36+
37+
[Setup]
38+
AppId={{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
39+
AppName={#AppName}
40+
AppVersion={#AppVersion}
41+
AppPublisher={#AppPublisher}
42+
AppPublisherURL={#AppURL}
43+
AppSupportURL={#AppURL}
44+
AppUpdatesURL={#AppURL}
45+
DefaultDirName={autopf}\\{#AppName}
46+
DefaultGroupName={#AppName}
47+
AllowNoIcons=yes
48+
OutputDir=installer_output
49+
OutputBaseFilename={#AppName}_Setup_{#AppVersion}_Windows
50+
Compression=lzma2/max
51+
SolidCompression=yes
52+
WizardStyle=Modern
53+
SetupIconFile=..\\icons\\logoneutral.ico
54+
UninstallDisplayIcon={app}\\{#AppExeName}
55+
ChangesAssociations=yes
56+
57+
[Languages]
58+
Name: "english"; MessagesFile: "compiler:Default.isl"
59+
Name: "italian"; MessagesFile: "compiler:Languages\\Italian.isl"
60+
61+
[Tasks]
62+
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
63+
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; OnlyBelowVersion: 6.1
64+
65+
[Files]
66+
; Main application files from PyInstaller onedir build
67+
Source: "dist\\ClinicalDBSAnnotator_Windows_$VU$\\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
68+
; Icon file for shortcuts
69+
Source: "..\\icons\\logoneutral.ico"; DestDir: "{app}"; Flags: ignoreversion
70+
71+
[Icons]
72+
Name: "{group}\\{#AppName}"; Filename: "{app}\\{#AppExeName}"; IconFilename: "{app}\\logoneutral.ico"
73+
Name: "{commondesktop}\\{#AppName}"; Filename: "{app}\\{#AppExeName}"; IconFilename: "{app}\\logoneutral.ico"; Tasks: desktopicon
74+
Name: "{userappdata}\\Microsoft\\Internet Explorer\\Quick Launch\\{#AppName}"; Filename: "{app}\\{#AppExeName}"; IconFilename: "{app}\\logoneutral.ico"; Tasks: quicklaunchicon
75+
76+
[Run]
77+
Filename: "{app}\\{#AppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
78+
79+
[Registry]
80+
; File association for .tsv annotation files
81+
Root: HKCR; Subkey: ".tsv\\OpenWithProgids"; ValueType: string; ValueName: "ClinicalDBSAnnotator.tsv"; ValueData: ""; Flags: uninsdeletevalue
82+
Root: HKCR; Subkey: "ClinicalDBSAnnotator.tsv"; ValueType: string; ValueName: ""; ValueData: "Clinical DBS Annotator File"; Flags: uninsdeletekey
83+
Root: HKCR; Subkey: "ClinicalDBSAnnotator.tsv\\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\\logoneutral.ico,0"
84+
Root: HKCR; Subkey: "ClinicalDBSAnnotator.tsv\\shell\\open\\command"; ValueType: string; ValueName: ""; ValueData: "$DQ${app}\\{#AppExeName}$DQ$ $DQ$%1$DQ$"
85+
86+
[UninstallDelete]
87+
Type: filesandordirs; Name: "{app}"
88+
"""
89+
iss_content = (
90+
iss_content.replace("$V$", version)
91+
.replace("$VU$", version_underscore)
92+
.replace("$DQ$", '"')
93+
)
94+
iss_path = PROJECT_ROOT / "scripts" / "ClinicalDBSAnnotator.iss"
95+
iss_path.write_text(iss_content, encoding="utf-8")
96+
print(f"Generated {iss_path} with version {version}")
97+
98+
99+
if __name__ == "__main__":
100+
version = read_version()
101+
generate_iss(version)

0 commit comments

Comments
 (0)