brkraw-viewer 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. brkraw_viewer-0.2.3/PKG-INFO +168 -0
  2. brkraw_viewer-0.2.3/README.md +151 -0
  3. brkraw_viewer-0.2.3/pyproject.toml +39 -0
  4. brkraw_viewer-0.2.3/setup.cfg +4 -0
  5. brkraw_viewer-0.2.3/src/brkraw_viewer/__init__.py +4 -0
  6. brkraw_viewer-0.2.3/src/brkraw_viewer/apps/__init__.py +0 -0
  7. brkraw_viewer-0.2.3/src/brkraw_viewer/apps/config.py +90 -0
  8. brkraw_viewer-0.2.3/src/brkraw_viewer/apps/convert.py +1164 -0
  9. brkraw_viewer-0.2.3/src/brkraw_viewer/apps/hooks.py +36 -0
  10. brkraw_viewer-0.2.3/src/brkraw_viewer/apps/viewer.py +4779 -0
  11. brkraw_viewer-0.2.3/src/brkraw_viewer/assets/icon.ico +0 -0
  12. brkraw_viewer-0.2.3/src/brkraw_viewer/assets/icon.png +0 -0
  13. brkraw_viewer-0.2.3/src/brkraw_viewer/frames/__init__.py +2 -0
  14. brkraw_viewer-0.2.3/src/brkraw_viewer/frames/params_panel.py +80 -0
  15. brkraw_viewer-0.2.3/src/brkraw_viewer/frames/viewer_canvas.py +340 -0
  16. brkraw_viewer-0.2.3/src/brkraw_viewer/frames/viewer_config.py +102 -0
  17. brkraw_viewer-0.2.3/src/brkraw_viewer/plugin.py +125 -0
  18. brkraw_viewer-0.2.3/src/brkraw_viewer/registry.py +258 -0
  19. brkraw_viewer-0.2.3/src/brkraw_viewer/snippets/context_map/basic.yaml +4 -0
  20. brkraw_viewer-0.2.3/src/brkraw_viewer/snippets/context_map/enum-map.yaml +5 -0
  21. brkraw_viewer-0.2.3/src/brkraw_viewer/snippets/rule/basic.yaml +10 -0
  22. brkraw_viewer-0.2.3/src/brkraw_viewer/snippets/rule/when-contains.yaml +10 -0
  23. brkraw_viewer-0.2.3/src/brkraw_viewer/snippets/spec/basic.yaml +5 -0
  24. brkraw_viewer-0.2.3/src/brkraw_viewer/snippets/spec/list-source.yaml +5 -0
  25. brkraw_viewer-0.2.3/src/brkraw_viewer/snippets/spec/with-default.yaml +5 -0
  26. brkraw_viewer-0.2.3/src/brkraw_viewer/utils/__init__.py +2 -0
  27. brkraw_viewer-0.2.3/src/brkraw_viewer/utils/orientation.py +17 -0
  28. brkraw_viewer-0.2.3/src/brkraw_viewer.egg-info/PKG-INFO +168 -0
  29. brkraw_viewer-0.2.3/src/brkraw_viewer.egg-info/SOURCES.txt +31 -0
  30. brkraw_viewer-0.2.3/src/brkraw_viewer.egg-info/dependency_links.txt +1 -0
  31. brkraw_viewer-0.2.3/src/brkraw_viewer.egg-info/entry_points.txt +2 -0
  32. brkraw_viewer-0.2.3/src/brkraw_viewer.egg-info/requires.txt +6 -0
  33. brkraw_viewer-0.2.3/src/brkraw_viewer.egg-info/top_level.txt +1 -0
@@ -0,0 +1,168 @@
1
+ Metadata-Version: 2.4
2
+ Name: brkraw-viewer
3
+ Version: 0.2.3
4
+ Summary: BrkRaw scan viewer plugin for brkraw CLI.
5
+ Author: BrkRaw
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: brkraw>=0.5.0rc1
13
+ Requires-Dist: nibabel>=5.0
14
+ Requires-Dist: pillow>=10.0
15
+ Provides-Extra: docs
16
+ Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
17
+
18
+ <h1 align="left">
19
+ <picture>
20
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/brkraw-viewer-logo-dark.svg">
21
+ <img alt="BrkRaw Viewer" src="docs/assets/brkraw-viewer-logo-light.svg" width="410">
22
+ </picture>
23
+ </h1>
24
+
25
+ BrkRaw Viewer is an interactive dataset viewer implemented as a
26
+ separate CLI plugin for the `brkraw` command.
27
+
28
+ The viewer is intentionally maintained outside the BrkRaw core to
29
+ enable independent development and community contributions around
30
+ user-facing interfaces.
31
+
32
+ ---
33
+
34
+ ## Scope and intent
35
+
36
+ BrkRaw Viewer is designed for **interactive inspection** of Bruker
37
+ Paravision datasets. It focuses on quick exploration and validation
38
+ rather than data conversion or analysis.
39
+
40
+ The goal is to provide practical, researcher-focused features that are
41
+ useful in everyday workflows, such as quick dataset triage, metadata
42
+ checks, and lightweight visual QC.
43
+
44
+ Typical use cases include:
45
+
46
+ - Browsing studies, scans, and reconstructions
47
+ - Verifying scan and reconstruction IDs
48
+ - Inspecting acquisition metadata before conversion
49
+ - Lightweight visual sanity checks
50
+
51
+ All data conversion and reproducible workflows are handled by the
52
+ BrkRaw CLI and Python API.
53
+
54
+ ---
55
+
56
+ ## Why these features exist
57
+
58
+ **Viewer**
59
+ The Viewer tab makes it easy to confirm the right scan and orientation before
60
+ running a larger workflow.
61
+
62
+ **Registry**
63
+ The Registry reduces repeated filesystem navigation and lets you re-open the
64
+ current session with a single menu action.
65
+
66
+ **Extensions/hooks**
67
+ Extensions allow modality-specific panels (MRS, BIDS, etc.) to live outside the
68
+ core viewer so the default install stays lightweight.
69
+
70
+ ---
71
+
72
+ ## Design goal: shared extensibility
73
+
74
+ brkraw-viewer keeps the BrkRaw design philosophy: extend the ecosystem
75
+ without changing core logic. The viewer uses the same rules/spec/layout
76
+ system as the CLI and Python API, and it exposes UI extensions via the
77
+ `brkraw.viewer.hook` entry point so new tabs can be added with standalone
78
+ packages. Viewer hooks can coexist with converter hooks and CLI hooks,
79
+ so modality-specific logic can flow from conversion into UI without
80
+ patching the viewer itself.
81
+
82
+ ---
83
+
84
+ ## UI direction
85
+
86
+ The default viewer targets a **tkinter-based** implementation.
87
+
88
+ This choice is intentional: we want a lightweight tool that can be
89
+ used directly on scanner consoles or constrained environments with
90
+ minimal dependencies.
91
+
92
+ More modern GUI frameworks are welcome, but should be developed as
93
+ separate CLI extensions to keep the default viewer small and easy to
94
+ install.
95
+
96
+ ---
97
+
98
+ ## Viewer hooks
99
+
100
+ Viewer extensions are implemented as hooks discovered through
101
+ `brkraw.viewer.hook`. Each hook can register a new tab and provide
102
+ dataset callbacks, enabling feature panels to live outside the core
103
+ viewer while staying compatible with BrkRaw rules, specs, and converter
104
+ hooks. See `docs/dev/hooks.md` for the hook interface and entry point
105
+ setup.
106
+
107
+ ---
108
+
109
+ ## Installation
110
+
111
+ For development and testing, install in editable mode:
112
+
113
+ pip install -e .
114
+
115
+ ---
116
+
117
+ ## Usage
118
+
119
+ Launch the viewer via the BrkRaw CLI:
120
+
121
+ brkraw viewer /path/to/bruker/study
122
+
123
+ Optional arguments allow opening a specific scan or slice:
124
+
125
+ brkraw viewer /path/to/bruker/study \
126
+ --scan 3 \
127
+ --reco 1
128
+
129
+ The viewer can also open `.zip` or Paravision-exported `.PvDatasets`
130
+ archives using `Load` (folder or archive file).
131
+
132
+ ---
133
+
134
+ ## Update
135
+
136
+ Recent updates:
137
+
138
+ - Open folders or archives (`.zip` / `.PvDatasets`)
139
+ - Viewer: `Space` (`raw/scanner/subject_ras`), nibabel RAS display, click-to-set `X/Y/Z`, optional crosshair + zoom,
140
+ slicepack/frame sliders only when needed
141
+ - Info: rule + spec selection (installed or file), parameter search, lazy Viewer refresh on tab focus
142
+ - Registry: add the current session from the `+` menu when a dataset is loaded
143
+ - Convert: BrkRaw layout engine, template + suffix defaults from `~/.brkraw/config.yaml`, keys browser (click to add),
144
+ optional config `layout_entries`
145
+ - Config: edit `~/.brkraw/config.yaml` in-app; basic focus/icon UX
146
+
147
+ This update keeps dependencies minimal and preserves compatibility with
148
+ the core BrkRaw rule/spec/hook system.
149
+
150
+ ---
151
+
152
+ ## Contributing
153
+
154
+ We welcome contributions related to:
155
+
156
+ - New viewer hooks that add modality-specific panels or workflows
157
+ - Alternative UI implementations delivered as separate CLI extensions
158
+ - fMRI/MRS/BIDS-focused visualization or QC helpers built on hooks
159
+ - Multi-dataset session management and registry enhancements
160
+ - Performance and memory improvements for large datasets
161
+
162
+ Contributions should prefer designs where new hooks extend the viewer
163
+ implicitly through shared BrkRaw abstractions, and where richer UIs are
164
+ provided as optional CLI extensions rather than increasing the default
165
+ dependency footprint.
166
+
167
+ If you are interested in contributing, please start a discussion or
168
+ open an issue describing your use case and goals.
@@ -0,0 +1,151 @@
1
+ <h1 align="left">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/brkraw-viewer-logo-dark.svg">
4
+ <img alt="BrkRaw Viewer" src="docs/assets/brkraw-viewer-logo-light.svg" width="410">
5
+ </picture>
6
+ </h1>
7
+
8
+ BrkRaw Viewer is an interactive dataset viewer implemented as a
9
+ separate CLI plugin for the `brkraw` command.
10
+
11
+ The viewer is intentionally maintained outside the BrkRaw core to
12
+ enable independent development and community contributions around
13
+ user-facing interfaces.
14
+
15
+ ---
16
+
17
+ ## Scope and intent
18
+
19
+ BrkRaw Viewer is designed for **interactive inspection** of Bruker
20
+ Paravision datasets. It focuses on quick exploration and validation
21
+ rather than data conversion or analysis.
22
+
23
+ The goal is to provide practical, researcher-focused features that are
24
+ useful in everyday workflows, such as quick dataset triage, metadata
25
+ checks, and lightweight visual QC.
26
+
27
+ Typical use cases include:
28
+
29
+ - Browsing studies, scans, and reconstructions
30
+ - Verifying scan and reconstruction IDs
31
+ - Inspecting acquisition metadata before conversion
32
+ - Lightweight visual sanity checks
33
+
34
+ All data conversion and reproducible workflows are handled by the
35
+ BrkRaw CLI and Python API.
36
+
37
+ ---
38
+
39
+ ## Why these features exist
40
+
41
+ **Viewer**
42
+ The Viewer tab makes it easy to confirm the right scan and orientation before
43
+ running a larger workflow.
44
+
45
+ **Registry**
46
+ The Registry reduces repeated filesystem navigation and lets you re-open the
47
+ current session with a single menu action.
48
+
49
+ **Extensions/hooks**
50
+ Extensions allow modality-specific panels (MRS, BIDS, etc.) to live outside the
51
+ core viewer so the default install stays lightweight.
52
+
53
+ ---
54
+
55
+ ## Design goal: shared extensibility
56
+
57
+ brkraw-viewer keeps the BrkRaw design philosophy: extend the ecosystem
58
+ without changing core logic. The viewer uses the same rules/spec/layout
59
+ system as the CLI and Python API, and it exposes UI extensions via the
60
+ `brkraw.viewer.hook` entry point so new tabs can be added with standalone
61
+ packages. Viewer hooks can coexist with converter hooks and CLI hooks,
62
+ so modality-specific logic can flow from conversion into UI without
63
+ patching the viewer itself.
64
+
65
+ ---
66
+
67
+ ## UI direction
68
+
69
+ The default viewer targets a **tkinter-based** implementation.
70
+
71
+ This choice is intentional: we want a lightweight tool that can be
72
+ used directly on scanner consoles or constrained environments with
73
+ minimal dependencies.
74
+
75
+ More modern GUI frameworks are welcome, but should be developed as
76
+ separate CLI extensions to keep the default viewer small and easy to
77
+ install.
78
+
79
+ ---
80
+
81
+ ## Viewer hooks
82
+
83
+ Viewer extensions are implemented as hooks discovered through
84
+ `brkraw.viewer.hook`. Each hook can register a new tab and provide
85
+ dataset callbacks, enabling feature panels to live outside the core
86
+ viewer while staying compatible with BrkRaw rules, specs, and converter
87
+ hooks. See `docs/dev/hooks.md` for the hook interface and entry point
88
+ setup.
89
+
90
+ ---
91
+
92
+ ## Installation
93
+
94
+ For development and testing, install in editable mode:
95
+
96
+ pip install -e .
97
+
98
+ ---
99
+
100
+ ## Usage
101
+
102
+ Launch the viewer via the BrkRaw CLI:
103
+
104
+ brkraw viewer /path/to/bruker/study
105
+
106
+ Optional arguments allow opening a specific scan or slice:
107
+
108
+ brkraw viewer /path/to/bruker/study \
109
+ --scan 3 \
110
+ --reco 1
111
+
112
+ The viewer can also open `.zip` or Paravision-exported `.PvDatasets`
113
+ archives using `Load` (folder or archive file).
114
+
115
+ ---
116
+
117
+ ## Update
118
+
119
+ Recent updates:
120
+
121
+ - Open folders or archives (`.zip` / `.PvDatasets`)
122
+ - Viewer: `Space` (`raw/scanner/subject_ras`), nibabel RAS display, click-to-set `X/Y/Z`, optional crosshair + zoom,
123
+ slicepack/frame sliders only when needed
124
+ - Info: rule + spec selection (installed or file), parameter search, lazy Viewer refresh on tab focus
125
+ - Registry: add the current session from the `+` menu when a dataset is loaded
126
+ - Convert: BrkRaw layout engine, template + suffix defaults from `~/.brkraw/config.yaml`, keys browser (click to add),
127
+ optional config `layout_entries`
128
+ - Config: edit `~/.brkraw/config.yaml` in-app; basic focus/icon UX
129
+
130
+ This update keeps dependencies minimal and preserves compatibility with
131
+ the core BrkRaw rule/spec/hook system.
132
+
133
+ ---
134
+
135
+ ## Contributing
136
+
137
+ We welcome contributions related to:
138
+
139
+ - New viewer hooks that add modality-specific panels or workflows
140
+ - Alternative UI implementations delivered as separate CLI extensions
141
+ - fMRI/MRS/BIDS-focused visualization or QC helpers built on hooks
142
+ - Multi-dataset session management and registry enhancements
143
+ - Performance and memory improvements for large datasets
144
+
145
+ Contributions should prefer designs where new hooks extend the viewer
146
+ implicitly through shared BrkRaw abstractions, and where richer UIs are
147
+ provided as optional CLI extensions rather than increasing the default
148
+ dependency footprint.
149
+
150
+ If you are interested in contributing, please start a discussion or
151
+ open an issue describing your use case and goals.
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "brkraw-viewer"
7
+ version = "0.2.3"
8
+ description = "BrkRaw scan viewer plugin for brkraw CLI."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ dependencies = [
12
+ "brkraw>=0.5.0rc1",
13
+ "nibabel>=5.0",
14
+ "pillow>=10.0",
15
+ ]
16
+ authors = [{name = "BrkRaw"}]
17
+ license = {text = "MIT"}
18
+ classifiers = [
19
+ "Programming Language :: Python :: 3",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Operating System :: OS Independent",
22
+ ]
23
+
24
+ [project.entry-points."brkraw.cli"]
25
+ viewer = "brkraw_viewer.plugin:register"
26
+
27
+ [project.optional-dependencies]
28
+ docs = [
29
+ "mkdocs-material>=9.5.0",
30
+ ]
31
+
32
+ [tool.setuptools]
33
+ package-dir = {"" = "src"}
34
+
35
+ [tool.setuptools.packages.find]
36
+ where = ["src"]
37
+
38
+ [tool.setuptools.package-data]
39
+ brkraw_viewer = ["assets/*.png", "assets/*.ico", "snippets/**/*.yaml"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,4 @@
1
+ """BrkRaw viewer plugin package."""
2
+
3
+ __all__ = ["__version__"]
4
+ __version__ = '0.2.3'
File without changes
@@ -0,0 +1,90 @@
1
+ from __future__ import annotations
2
+
3
+ import datetime as dt
4
+ import logging
5
+ import shutil
6
+ import tkinter as tk
7
+ from tkinter import messagebox, ttk
8
+ from pathlib import Path
9
+
10
+ from brkraw.core import config as config_core
11
+
12
+ logger = logging.getLogger("brkraw.viewer")
13
+
14
+
15
+ class ConfigTabMixin:
16
+ _config_text: tk.Text
17
+ _config_path_var: tk.StringVar
18
+
19
+ def _build_config_tab(self, config_tab: ttk.Frame) -> None:
20
+ config_tab.columnconfigure(0, weight=1)
21
+ config_tab.rowconfigure(1, weight=1)
22
+ config_bar = ttk.Frame(config_tab, padding=(6, 6))
23
+ config_bar.grid(row=0, column=0, sticky="ew")
24
+ ttk.Button(config_bar, text="Save", command=self._save_config_text).pack(side=tk.LEFT)
25
+ ttk.Button(config_bar, text="Backup", command=self._backup_config_text).pack(side=tk.LEFT, padx=(6, 0))
26
+ ttk.Button(config_bar, text="Reset", command=self._reset_config_text).pack(side=tk.LEFT, padx=(6, 0))
27
+ self._config_path_var = tk.StringVar(value="")
28
+ ttk.Label(config_bar, textvariable=self._config_path_var).pack(side=tk.LEFT, padx=(12, 0))
29
+
30
+ config_body = ttk.Frame(config_tab, padding=(6, 6))
31
+ config_body.grid(row=1, column=0, sticky="nsew")
32
+ config_body.columnconfigure(0, weight=1)
33
+ config_body.rowconfigure(0, weight=1)
34
+ self._config_text = tk.Text(config_body, wrap="none")
35
+ self._config_text.grid(row=0, column=0, sticky="nsew")
36
+ config_scroll = ttk.Scrollbar(config_body, orient="vertical", command=self._config_text.yview)
37
+ config_scroll.grid(row=0, column=1, sticky="ns")
38
+ self._config_text.configure(yscrollcommand=config_scroll.set)
39
+
40
+ def _load_config_text(self) -> None:
41
+ try:
42
+ paths = config_core.ensure_initialized(root=None, create_config=True, exist_ok=True)
43
+ self._config_path_var.set(str(paths.config_file))
44
+ content = paths.config_file.read_text(encoding="utf-8")
45
+ except Exception as exc:
46
+ logger.error("Failed to load config.yaml: %s", exc, exc_info=logger.isEnabledFor(logging.DEBUG))
47
+ self._config_path_var.set("")
48
+ self._config_text.delete("1.0", tk.END)
49
+ self._config_text.insert(tk.END, f"# Failed to load config.yaml: {exc}\n")
50
+ return
51
+ self._config_text.delete("1.0", tk.END)
52
+ self._config_text.insert(tk.END, content)
53
+
54
+ def _save_config_text(self) -> None:
55
+ try:
56
+ paths = config_core.ensure_initialized(root=None, create_config=True, exist_ok=True)
57
+ self._config_path_var.set(str(paths.config_file))
58
+ text = self._config_text.get("1.0", tk.END)
59
+ paths.config_file.write_text(text, encoding="utf-8")
60
+ logger.info("Saved config.yaml: %s", paths.config_file)
61
+ except Exception as exc:
62
+ logger.error("Failed to save config.yaml: %s", exc, exc_info=logger.isEnabledFor(logging.DEBUG))
63
+ messagebox.showerror("Save error", f"Failed to save config.yaml:\n{exc}")
64
+
65
+ def _backup_config_text(self) -> None:
66
+ try:
67
+ paths = config_core.ensure_initialized(root=None, create_config=True, exist_ok=True)
68
+ config_path = paths.config_file
69
+ self._config_path_var.set(str(config_path))
70
+ if not config_path.exists():
71
+ messagebox.showwarning("Backup", f"Config file not found:\n{config_path}")
72
+ return
73
+ ts = dt.datetime.now().strftime("%Y%m%d-%H%M%S")
74
+ backup_path = Path(f"{config_path}.bak-{ts}")
75
+ shutil.copy2(config_path, backup_path)
76
+ logger.info("Backed up config.yaml: %s", backup_path)
77
+ messagebox.showinfo("Backup", f"Created backup:\n{backup_path}")
78
+ except Exception as exc:
79
+ logger.error("Failed to back up config.yaml: %s", exc, exc_info=logger.isEnabledFor(logging.DEBUG))
80
+ messagebox.showerror("Backup error", f"Failed to back up config.yaml:\n{exc}")
81
+
82
+ def _reset_config_text(self) -> None:
83
+ try:
84
+ config_core.reset_config(root=None)
85
+ logger.info("Reset config.yaml to defaults.")
86
+ except Exception as exc:
87
+ logger.error("Failed to reset config.yaml: %s", exc, exc_info=logger.isEnabledFor(logging.DEBUG))
88
+ messagebox.showerror("Reset error", f"Failed to reset config.yaml:\n{exc}")
89
+ return
90
+ self._load_config_text()