niivue-streamlit 0.0.0.dev14__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.
- niivue_streamlit-0.0.0.dev14/MANIFEST.in +9 -0
- niivue_streamlit-0.0.0.dev14/PKG-INFO +311 -0
- niivue_streamlit-0.0.0.dev14/README.md +282 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/README.md +105 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/__init__.py +182 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/.npmrc +2 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/.turbo/turbo-build.log +29 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/CHANGELOG.md +14 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/README.md +63 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/build/assets/blosc.js +1 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/build/assets/chunk-INHXZS53.js +1 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/build/assets/dcm2niix.jpeg-CR3ddVLp.wasm +0 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/build/assets/index.css +1 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/build/assets/index.js +2 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/build/assets/lz4.js +1 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/build/assets/worker.jpeg-Ci0Y_zaw.js +1 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/build/assets/zstd.js +1 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/build/index.html +13 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/index.html +12 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/package.json +45 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/postcss.config.js +6 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/tailwind.config.js +12 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/test/UnstyledCanvas.test.tsx +13 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/test/setup.ts +1 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/test/utils.test.ts +138 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/tsconfig.json +34 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/vite.config.ts +94 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/frontend/vitest.config.ts +27 -0
- niivue_streamlit-0.0.0.dev14/niivue_component/setup_dev.sh +37 -0
- niivue_streamlit-0.0.0.dev14/niivue_streamlit.egg-info/PKG-INFO +311 -0
- niivue_streamlit-0.0.0.dev14/niivue_streamlit.egg-info/SOURCES.txt +36 -0
- niivue_streamlit-0.0.0.dev14/niivue_streamlit.egg-info/dependency_links.txt +1 -0
- niivue_streamlit-0.0.0.dev14/niivue_streamlit.egg-info/requires.txt +6 -0
- niivue_streamlit-0.0.0.dev14/niivue_streamlit.egg-info/top_level.txt +1 -0
- niivue_streamlit-0.0.0.dev14/pyproject.toml +52 -0
- niivue_streamlit-0.0.0.dev14/setup.cfg +4 -0
- niivue_streamlit-0.0.0.dev14/tests/test_niivue_component.py +318 -0
- niivue_streamlit-0.0.0.dev14/tests/test_utils.py +39 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
include README.md
|
|
2
|
+
include LICENSE
|
|
3
|
+
recursive-include niivue_component *
|
|
4
|
+
recursive-include niivue_component/assets *
|
|
5
|
+
recursive-exclude niivue_component/frontend/node_modules *
|
|
6
|
+
recursive-exclude niivue_component/frontend/src *
|
|
7
|
+
recursive-exclude niivue_component/frontend/public *
|
|
8
|
+
global-exclude *.pyc
|
|
9
|
+
global-exclude __pycache__
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: niivue-streamlit
|
|
3
|
+
Version: 0.0.0.dev14
|
|
4
|
+
Summary: A Streamlit component for NiiVue neuroimaging viewer
|
|
5
|
+
Author: NiiVue Team
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/niivue/niivue
|
|
8
|
+
Project-URL: Documentation, https://niivue.github.io/niivue/
|
|
9
|
+
Project-URL: Repository, https://github.com/niivue/niivue
|
|
10
|
+
Project-URL: Issues, https://github.com/niivue/niivue/issues
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
22
|
+
Requires-Python: >=3.7
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
Requires-Dist: streamlit>=1.28.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest; extra == "dev"
|
|
27
|
+
Requires-Dist: black; extra == "dev"
|
|
28
|
+
Requires-Dist: flake8; extra == "dev"
|
|
29
|
+
|
|
30
|
+
# NiiVue Streamlit Component
|
|
31
|
+
|
|
32
|
+
A modern Streamlit component for visualizing neuroimaging data using NiiVue, built with TypeScript, Preact, and Vite.
|
|
33
|
+
|
|
34
|
+
## 🚀 Quick Start
|
|
35
|
+
|
|
36
|
+
### Simple Installation & Usage
|
|
37
|
+
|
|
38
|
+
1. **Install the component**:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install --index-url https://test.pypi.org/simple/ --no-deps niivue-streamlit
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
2. **Use in your Streamlit app**:
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
import streamlit as st
|
|
48
|
+
from niivue_component import niivue_viewer
|
|
49
|
+
|
|
50
|
+
uploaded_file = st.file_uploader("Choose a NIFTI file", type=["nii", "nii.gz"])
|
|
51
|
+
|
|
52
|
+
if uploaded_file is not None:
|
|
53
|
+
result = niivue_viewer(
|
|
54
|
+
nifti_data=uploaded_file.getvalue(),
|
|
55
|
+
filename=uploaded_file.name,
|
|
56
|
+
height=700
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Handle click events
|
|
60
|
+
if result:
|
|
61
|
+
st.write(f"Clicked voxel: {result['voxel']}, Value: {result['value']}")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## ✨ Features
|
|
65
|
+
|
|
66
|
+
- 🎨 **Two Component Modes**:
|
|
67
|
+
- `StyledViewer`: Full-featured viewer with interactive menu and controls
|
|
68
|
+
- `UnstyledCanvas`: Minimal canvas-only viewer for embedding
|
|
69
|
+
- 🔄 **Multiple View Modes**:
|
|
70
|
+
- Axial, Coronal, Sagittal slices
|
|
71
|
+
- 3D render view
|
|
72
|
+
- Multiplanar view with render
|
|
73
|
+
- 📊 **Advanced Capabilities**:
|
|
74
|
+
- Multiple overlay images with custom colormaps
|
|
75
|
+
- Surface mesh rendering (FreeSurfer pial, white, inflated, GIfTI, STL, OBJ, etc.)
|
|
76
|
+
- Mesh overlays (curvature, thickness, annotations)
|
|
77
|
+
- Combined volume + mesh visualization
|
|
78
|
+
- Configurable display settings (crosshair, radiological convention, colorbar, interpolation)
|
|
79
|
+
- Bidirectional communication (click events from viewer to Python)
|
|
80
|
+
- DICOM support
|
|
81
|
+
|
|
82
|
+
## 📖 Advanced Usage
|
|
83
|
+
|
|
84
|
+
### With Overlays
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from niivue_component import niivue_viewer
|
|
88
|
+
|
|
89
|
+
result = niivue_viewer(
|
|
90
|
+
nifti_data=main_image_bytes,
|
|
91
|
+
filename="brain.nii.gz",
|
|
92
|
+
overlays=[
|
|
93
|
+
{
|
|
94
|
+
"data": overlay_bytes,
|
|
95
|
+
"name": "activation.nii.gz",
|
|
96
|
+
"colormap": "hot",
|
|
97
|
+
"opacity": 0.7
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
view_mode="multiplanar",
|
|
101
|
+
styled=True,
|
|
102
|
+
settings={
|
|
103
|
+
"crosshair": True,
|
|
104
|
+
"radiological": False,
|
|
105
|
+
"colorbar": True,
|
|
106
|
+
"interpolation": True
|
|
107
|
+
},
|
|
108
|
+
height=800
|
|
109
|
+
)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### With Mesh Surfaces
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from niivue_component import niivue_viewer
|
|
116
|
+
|
|
117
|
+
# Load a FreeSurfer surface mesh
|
|
118
|
+
mesh_data = open("lh.pial", "rb").read()
|
|
119
|
+
|
|
120
|
+
result = niivue_viewer(
|
|
121
|
+
meshes=[{
|
|
122
|
+
"data": mesh_data,
|
|
123
|
+
"name": "lh.pial",
|
|
124
|
+
}],
|
|
125
|
+
view_mode="3d",
|
|
126
|
+
height=700
|
|
127
|
+
)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Mesh with Overlays (Curvature, Thickness)
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
mesh_data = open("lh.pial", "rb").read()
|
|
134
|
+
thickness_data = open("lh.thickness", "rb").read()
|
|
135
|
+
|
|
136
|
+
result = niivue_viewer(
|
|
137
|
+
meshes=[{
|
|
138
|
+
"data": mesh_data,
|
|
139
|
+
"name": "lh.pial",
|
|
140
|
+
"overlays": [{
|
|
141
|
+
"data": thickness_data,
|
|
142
|
+
"name": "lh.thickness",
|
|
143
|
+
"colormap": "redyell",
|
|
144
|
+
"opacity": 0.7
|
|
145
|
+
}]
|
|
146
|
+
}],
|
|
147
|
+
view_mode="3d",
|
|
148
|
+
height=700
|
|
149
|
+
)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Volume with Mesh
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
# Display a volume image alongside a surface mesh
|
|
156
|
+
volume_data = open("brain.nii.gz", "rb").read()
|
|
157
|
+
mesh_data = open("lh.pial", "rb").read()
|
|
158
|
+
|
|
159
|
+
result = niivue_viewer(
|
|
160
|
+
nifti_data=volume_data,
|
|
161
|
+
filename="brain.nii.gz",
|
|
162
|
+
meshes=[{
|
|
163
|
+
"data": mesh_data,
|
|
164
|
+
"name": "lh.pial",
|
|
165
|
+
}],
|
|
166
|
+
view_mode="3d",
|
|
167
|
+
height=700
|
|
168
|
+
)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Minimal Viewer (No Menu)
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
# Perfect for embedding in complex layouts
|
|
175
|
+
result = niivue_viewer(
|
|
176
|
+
nifti_data=image_bytes,
|
|
177
|
+
filename="scan.nii",
|
|
178
|
+
styled=False, # Hide menu
|
|
179
|
+
view_mode="axial",
|
|
180
|
+
height=400
|
|
181
|
+
)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 📚 API Reference
|
|
185
|
+
|
|
186
|
+
### `niivue_viewer()`
|
|
187
|
+
|
|
188
|
+
**Parameters:**
|
|
189
|
+
|
|
190
|
+
- `nifti_data` (bytes, optional): Raw NIFTI file data
|
|
191
|
+
- `filename` (str): Displayed filename
|
|
192
|
+
- `overlays` (list[dict], optional): Overlay images list
|
|
193
|
+
- `data` (bytes): Overlay data
|
|
194
|
+
- `name` (str): Overlay name
|
|
195
|
+
- `colormap` (str): Colormap (default: 'red')
|
|
196
|
+
- `opacity` (float): 0-1 (default: 0.5)
|
|
197
|
+
- `meshes` (list[dict], optional): Mesh surfaces list
|
|
198
|
+
- `data` (bytes): Mesh file data
|
|
199
|
+
- `name` (str): Mesh filename (must include extension, e.g. 'lh.pial', 'brain.gii')
|
|
200
|
+
- `overlays` (list[dict], optional): Mesh overlays (curvature, thickness, etc.)
|
|
201
|
+
- `data` (bytes): Overlay data
|
|
202
|
+
- `name` (str): Overlay filename
|
|
203
|
+
- `colormap` (str): Colormap (default: 'redyell')
|
|
204
|
+
- `opacity` (float): 0-1 (default: 0.7)
|
|
205
|
+
- `height` (int): Height in pixels (default: 600)
|
|
206
|
+
- `view_mode` (str): 'axial', 'coronal', 'sagittal', '3d', 'multiplanar' (default)
|
|
207
|
+
- `styled` (bool): Show menu (default: True)
|
|
208
|
+
- `settings` (dict, optional):
|
|
209
|
+
- `crosshair` (bool): default True
|
|
210
|
+
- `radiological` (bool): default False
|
|
211
|
+
- `colorbar` (bool): default False
|
|
212
|
+
- `interpolation` (bool): default True
|
|
213
|
+
- `key` (str, optional): Component key
|
|
214
|
+
|
|
215
|
+
**Returns:**
|
|
216
|
+
|
|
217
|
+
dict or None with click event data:
|
|
218
|
+
|
|
219
|
+
- `type`: 'voxel_click'
|
|
220
|
+
- `voxel`: [x, y, z]
|
|
221
|
+
- `mm`: [x, y, z]
|
|
222
|
+
- `value`: float
|
|
223
|
+
- `filename`: str
|
|
224
|
+
|
|
225
|
+
## 🛠️ Development
|
|
226
|
+
|
|
227
|
+
### Dev mode (live reload)
|
|
228
|
+
|
|
229
|
+
In dev mode, the Python package points to a local Vite dev server instead of built files.
|
|
230
|
+
|
|
231
|
+
Terminal 1 — start the frontend dev server (port 3001):
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
pnpm dev
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Terminal 2 — run the example app with the dev flag:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
NIIVUE_DEV=1 streamlit run app.py
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
The frontend hot-reloads on changes.
|
|
244
|
+
|
|
245
|
+
### Production mode (built files)
|
|
246
|
+
|
|
247
|
+
Build the frontend first, then run Streamlit normally:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
pnpm build
|
|
251
|
+
streamlit run app.py
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
`_RELEASE = True` (the default) serves from `niivue_component/frontend/build/`.
|
|
255
|
+
|
|
256
|
+
### Running Examples
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
# Simple example
|
|
260
|
+
streamlit run app.py
|
|
261
|
+
|
|
262
|
+
# Advanced example with all features
|
|
263
|
+
streamlit run app_advanced.py
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## 📁 Supported Formats
|
|
267
|
+
|
|
268
|
+
- **Volume-based**: NIFTI (.nii, .nii.gz), DICOM (.dcm), MINC (.mnc, .mnc.gz), MHA/MHD, NRRD, MGH/MGZ
|
|
269
|
+
- **Mesh-based**: [GIfTI](https://www.nitrc.org/projects/gifti/) (.gii), [FreeSurfer](http://www.grahamwideman.com/gw/brain/fs/surfacefileformats.htm) (pial, white, inflated), [MZ3](https://github.com/neurolabusc/surf-ice/tree/master/mz3) (.mz3), [STL](https://medium.com/3d-printing-stories/why-stl-format-is-bad-fea9ecf5e45) (.stl), [Wavefront OBJ](https://brainder.org/tag/obj/) (.obj), [PLY](https://en.wikipedia.org/wiki/PLY_%28file_format%29) (.ply), [BrainSuite DFS](http://brainsuite.org/formats/dfs/) (.dfs), [Legacy VTK](https://vtk.org/wp-content/uploads/2015/04/file-formats.pdf) (.vtk)
|
|
270
|
+
- **Mesh Overlays**: [GIfTI](https://www.nitrc.org/projects/gifti/) (.gii), [CIfTI-2](https://balsa.wustl.edu/about/fileTypes) (.nii), [MZ3](https://github.com/neurolabusc/surf-ice/tree/master/mz3) (.mz3), FreeSurfer (CURV, ANNOT), SMP, STC
|
|
271
|
+
- **Tractography**: [TCK](https://mrtrix.readthedocs.io/en/latest/getting_started/image_data.html#tracks-file-format-tck) (.tck), [TRK](http://trackvis.org/docs/?subsect=fileformat) (.trk), [TRX](https://github.com/frheault/tractography_file_format) (.trx), VTK (.vtk)
|
|
272
|
+
|
|
273
|
+
## 🏗️ Architecture
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
niivue_component/
|
|
277
|
+
├── __init__.py # Python API
|
|
278
|
+
├── frontend/
|
|
279
|
+
│ ├── src/
|
|
280
|
+
│ │ ├── components/
|
|
281
|
+
│ │ │ ├── StyledViewer.tsx
|
|
282
|
+
│ │ │ └── UnstyledCanvas.tsx
|
|
283
|
+
│ │ ├── types.ts
|
|
284
|
+
│ │ └── utils.ts
|
|
285
|
+
│ ├── vite.config.ts
|
|
286
|
+
│ └── package.json
|
|
287
|
+
└── build/ # Compiled assets (generated, not in git)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## 🔧 Building for Distribution
|
|
291
|
+
|
|
292
|
+
Build files are not committed to git. To prepare the Python package for release:
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
pnpm build
|
|
296
|
+
python -m build
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
This compiles frontend assets into `niivue_component/frontend/build/`, which is then bundled into the Python package.
|
|
300
|
+
|
|
301
|
+
## 📄 License
|
|
302
|
+
|
|
303
|
+
BSD-2-Clause
|
|
304
|
+
|
|
305
|
+
## 🙏 Credits
|
|
306
|
+
|
|
307
|
+
Built on top of:
|
|
308
|
+
|
|
309
|
+
- [NiiVue](https://github.com/niivue/niivue)
|
|
310
|
+
- [Streamlit](https://streamlit.io)
|
|
311
|
+
- [niivue-react](../../packages/niivue-react)
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# NiiVue Streamlit Component
|
|
2
|
+
|
|
3
|
+
A modern Streamlit component for visualizing neuroimaging data using NiiVue, built with TypeScript, Preact, and Vite.
|
|
4
|
+
|
|
5
|
+
## 🚀 Quick Start
|
|
6
|
+
|
|
7
|
+
### Simple Installation & Usage
|
|
8
|
+
|
|
9
|
+
1. **Install the component**:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install --index-url https://test.pypi.org/simple/ --no-deps niivue-streamlit
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
2. **Use in your Streamlit app**:
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
import streamlit as st
|
|
19
|
+
from niivue_component import niivue_viewer
|
|
20
|
+
|
|
21
|
+
uploaded_file = st.file_uploader("Choose a NIFTI file", type=["nii", "nii.gz"])
|
|
22
|
+
|
|
23
|
+
if uploaded_file is not None:
|
|
24
|
+
result = niivue_viewer(
|
|
25
|
+
nifti_data=uploaded_file.getvalue(),
|
|
26
|
+
filename=uploaded_file.name,
|
|
27
|
+
height=700
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Handle click events
|
|
31
|
+
if result:
|
|
32
|
+
st.write(f"Clicked voxel: {result['voxel']}, Value: {result['value']}")
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## ✨ Features
|
|
36
|
+
|
|
37
|
+
- 🎨 **Two Component Modes**:
|
|
38
|
+
- `StyledViewer`: Full-featured viewer with interactive menu and controls
|
|
39
|
+
- `UnstyledCanvas`: Minimal canvas-only viewer for embedding
|
|
40
|
+
- 🔄 **Multiple View Modes**:
|
|
41
|
+
- Axial, Coronal, Sagittal slices
|
|
42
|
+
- 3D render view
|
|
43
|
+
- Multiplanar view with render
|
|
44
|
+
- 📊 **Advanced Capabilities**:
|
|
45
|
+
- Multiple overlay images with custom colormaps
|
|
46
|
+
- Surface mesh rendering (FreeSurfer pial, white, inflated, GIfTI, STL, OBJ, etc.)
|
|
47
|
+
- Mesh overlays (curvature, thickness, annotations)
|
|
48
|
+
- Combined volume + mesh visualization
|
|
49
|
+
- Configurable display settings (crosshair, radiological convention, colorbar, interpolation)
|
|
50
|
+
- Bidirectional communication (click events from viewer to Python)
|
|
51
|
+
- DICOM support
|
|
52
|
+
|
|
53
|
+
## 📖 Advanced Usage
|
|
54
|
+
|
|
55
|
+
### With Overlays
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from niivue_component import niivue_viewer
|
|
59
|
+
|
|
60
|
+
result = niivue_viewer(
|
|
61
|
+
nifti_data=main_image_bytes,
|
|
62
|
+
filename="brain.nii.gz",
|
|
63
|
+
overlays=[
|
|
64
|
+
{
|
|
65
|
+
"data": overlay_bytes,
|
|
66
|
+
"name": "activation.nii.gz",
|
|
67
|
+
"colormap": "hot",
|
|
68
|
+
"opacity": 0.7
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
view_mode="multiplanar",
|
|
72
|
+
styled=True,
|
|
73
|
+
settings={
|
|
74
|
+
"crosshair": True,
|
|
75
|
+
"radiological": False,
|
|
76
|
+
"colorbar": True,
|
|
77
|
+
"interpolation": True
|
|
78
|
+
},
|
|
79
|
+
height=800
|
|
80
|
+
)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### With Mesh Surfaces
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from niivue_component import niivue_viewer
|
|
87
|
+
|
|
88
|
+
# Load a FreeSurfer surface mesh
|
|
89
|
+
mesh_data = open("lh.pial", "rb").read()
|
|
90
|
+
|
|
91
|
+
result = niivue_viewer(
|
|
92
|
+
meshes=[{
|
|
93
|
+
"data": mesh_data,
|
|
94
|
+
"name": "lh.pial",
|
|
95
|
+
}],
|
|
96
|
+
view_mode="3d",
|
|
97
|
+
height=700
|
|
98
|
+
)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Mesh with Overlays (Curvature, Thickness)
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
mesh_data = open("lh.pial", "rb").read()
|
|
105
|
+
thickness_data = open("lh.thickness", "rb").read()
|
|
106
|
+
|
|
107
|
+
result = niivue_viewer(
|
|
108
|
+
meshes=[{
|
|
109
|
+
"data": mesh_data,
|
|
110
|
+
"name": "lh.pial",
|
|
111
|
+
"overlays": [{
|
|
112
|
+
"data": thickness_data,
|
|
113
|
+
"name": "lh.thickness",
|
|
114
|
+
"colormap": "redyell",
|
|
115
|
+
"opacity": 0.7
|
|
116
|
+
}]
|
|
117
|
+
}],
|
|
118
|
+
view_mode="3d",
|
|
119
|
+
height=700
|
|
120
|
+
)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Volume with Mesh
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
# Display a volume image alongside a surface mesh
|
|
127
|
+
volume_data = open("brain.nii.gz", "rb").read()
|
|
128
|
+
mesh_data = open("lh.pial", "rb").read()
|
|
129
|
+
|
|
130
|
+
result = niivue_viewer(
|
|
131
|
+
nifti_data=volume_data,
|
|
132
|
+
filename="brain.nii.gz",
|
|
133
|
+
meshes=[{
|
|
134
|
+
"data": mesh_data,
|
|
135
|
+
"name": "lh.pial",
|
|
136
|
+
}],
|
|
137
|
+
view_mode="3d",
|
|
138
|
+
height=700
|
|
139
|
+
)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Minimal Viewer (No Menu)
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
# Perfect for embedding in complex layouts
|
|
146
|
+
result = niivue_viewer(
|
|
147
|
+
nifti_data=image_bytes,
|
|
148
|
+
filename="scan.nii",
|
|
149
|
+
styled=False, # Hide menu
|
|
150
|
+
view_mode="axial",
|
|
151
|
+
height=400
|
|
152
|
+
)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## 📚 API Reference
|
|
156
|
+
|
|
157
|
+
### `niivue_viewer()`
|
|
158
|
+
|
|
159
|
+
**Parameters:**
|
|
160
|
+
|
|
161
|
+
- `nifti_data` (bytes, optional): Raw NIFTI file data
|
|
162
|
+
- `filename` (str): Displayed filename
|
|
163
|
+
- `overlays` (list[dict], optional): Overlay images list
|
|
164
|
+
- `data` (bytes): Overlay data
|
|
165
|
+
- `name` (str): Overlay name
|
|
166
|
+
- `colormap` (str): Colormap (default: 'red')
|
|
167
|
+
- `opacity` (float): 0-1 (default: 0.5)
|
|
168
|
+
- `meshes` (list[dict], optional): Mesh surfaces list
|
|
169
|
+
- `data` (bytes): Mesh file data
|
|
170
|
+
- `name` (str): Mesh filename (must include extension, e.g. 'lh.pial', 'brain.gii')
|
|
171
|
+
- `overlays` (list[dict], optional): Mesh overlays (curvature, thickness, etc.)
|
|
172
|
+
- `data` (bytes): Overlay data
|
|
173
|
+
- `name` (str): Overlay filename
|
|
174
|
+
- `colormap` (str): Colormap (default: 'redyell')
|
|
175
|
+
- `opacity` (float): 0-1 (default: 0.7)
|
|
176
|
+
- `height` (int): Height in pixels (default: 600)
|
|
177
|
+
- `view_mode` (str): 'axial', 'coronal', 'sagittal', '3d', 'multiplanar' (default)
|
|
178
|
+
- `styled` (bool): Show menu (default: True)
|
|
179
|
+
- `settings` (dict, optional):
|
|
180
|
+
- `crosshair` (bool): default True
|
|
181
|
+
- `radiological` (bool): default False
|
|
182
|
+
- `colorbar` (bool): default False
|
|
183
|
+
- `interpolation` (bool): default True
|
|
184
|
+
- `key` (str, optional): Component key
|
|
185
|
+
|
|
186
|
+
**Returns:**
|
|
187
|
+
|
|
188
|
+
dict or None with click event data:
|
|
189
|
+
|
|
190
|
+
- `type`: 'voxel_click'
|
|
191
|
+
- `voxel`: [x, y, z]
|
|
192
|
+
- `mm`: [x, y, z]
|
|
193
|
+
- `value`: float
|
|
194
|
+
- `filename`: str
|
|
195
|
+
|
|
196
|
+
## 🛠️ Development
|
|
197
|
+
|
|
198
|
+
### Dev mode (live reload)
|
|
199
|
+
|
|
200
|
+
In dev mode, the Python package points to a local Vite dev server instead of built files.
|
|
201
|
+
|
|
202
|
+
Terminal 1 — start the frontend dev server (port 3001):
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
pnpm dev
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Terminal 2 — run the example app with the dev flag:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
NIIVUE_DEV=1 streamlit run app.py
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
The frontend hot-reloads on changes.
|
|
215
|
+
|
|
216
|
+
### Production mode (built files)
|
|
217
|
+
|
|
218
|
+
Build the frontend first, then run Streamlit normally:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
pnpm build
|
|
222
|
+
streamlit run app.py
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
`_RELEASE = True` (the default) serves from `niivue_component/frontend/build/`.
|
|
226
|
+
|
|
227
|
+
### Running Examples
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
# Simple example
|
|
231
|
+
streamlit run app.py
|
|
232
|
+
|
|
233
|
+
# Advanced example with all features
|
|
234
|
+
streamlit run app_advanced.py
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## 📁 Supported Formats
|
|
238
|
+
|
|
239
|
+
- **Volume-based**: NIFTI (.nii, .nii.gz), DICOM (.dcm), MINC (.mnc, .mnc.gz), MHA/MHD, NRRD, MGH/MGZ
|
|
240
|
+
- **Mesh-based**: [GIfTI](https://www.nitrc.org/projects/gifti/) (.gii), [FreeSurfer](http://www.grahamwideman.com/gw/brain/fs/surfacefileformats.htm) (pial, white, inflated), [MZ3](https://github.com/neurolabusc/surf-ice/tree/master/mz3) (.mz3), [STL](https://medium.com/3d-printing-stories/why-stl-format-is-bad-fea9ecf5e45) (.stl), [Wavefront OBJ](https://brainder.org/tag/obj/) (.obj), [PLY](https://en.wikipedia.org/wiki/PLY_%28file_format%29) (.ply), [BrainSuite DFS](http://brainsuite.org/formats/dfs/) (.dfs), [Legacy VTK](https://vtk.org/wp-content/uploads/2015/04/file-formats.pdf) (.vtk)
|
|
241
|
+
- **Mesh Overlays**: [GIfTI](https://www.nitrc.org/projects/gifti/) (.gii), [CIfTI-2](https://balsa.wustl.edu/about/fileTypes) (.nii), [MZ3](https://github.com/neurolabusc/surf-ice/tree/master/mz3) (.mz3), FreeSurfer (CURV, ANNOT), SMP, STC
|
|
242
|
+
- **Tractography**: [TCK](https://mrtrix.readthedocs.io/en/latest/getting_started/image_data.html#tracks-file-format-tck) (.tck), [TRK](http://trackvis.org/docs/?subsect=fileformat) (.trk), [TRX](https://github.com/frheault/tractography_file_format) (.trx), VTK (.vtk)
|
|
243
|
+
|
|
244
|
+
## 🏗️ Architecture
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
niivue_component/
|
|
248
|
+
├── __init__.py # Python API
|
|
249
|
+
├── frontend/
|
|
250
|
+
│ ├── src/
|
|
251
|
+
│ │ ├── components/
|
|
252
|
+
│ │ │ ├── StyledViewer.tsx
|
|
253
|
+
│ │ │ └── UnstyledCanvas.tsx
|
|
254
|
+
│ │ ├── types.ts
|
|
255
|
+
│ │ └── utils.ts
|
|
256
|
+
│ ├── vite.config.ts
|
|
257
|
+
│ └── package.json
|
|
258
|
+
└── build/ # Compiled assets (generated, not in git)
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## 🔧 Building for Distribution
|
|
262
|
+
|
|
263
|
+
Build files are not committed to git. To prepare the Python package for release:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
pnpm build
|
|
267
|
+
python -m build
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
This compiles frontend assets into `niivue_component/frontend/build/`, which is then bundled into the Python package.
|
|
271
|
+
|
|
272
|
+
## 📄 License
|
|
273
|
+
|
|
274
|
+
BSD-2-Clause
|
|
275
|
+
|
|
276
|
+
## 🙏 Credits
|
|
277
|
+
|
|
278
|
+
Built on top of:
|
|
279
|
+
|
|
280
|
+
- [NiiVue](https://github.com/niivue/niivue)
|
|
281
|
+
- [Streamlit](https://streamlit.io)
|
|
282
|
+
- [niivue-react](../../packages/niivue-react)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# NiiVue Streamlit Component
|
|
2
|
+
|
|
3
|
+
A Streamlit component for viewing NIFTI files using the NiiVue library.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### From PyPI (Recommended)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install niivue-streamlit
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Development Setup
|
|
14
|
+
|
|
15
|
+
1. Clone the repository and navigate to the component directory:
|
|
16
|
+
```bash
|
|
17
|
+
cd niivue_component
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
2. Install Python dependencies:
|
|
21
|
+
```bash
|
|
22
|
+
pip install -e .
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
3. Install and build the frontend:
|
|
26
|
+
```bash
|
|
27
|
+
cd frontend
|
|
28
|
+
npm install
|
|
29
|
+
npm run build
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
4. Install the component in development mode:
|
|
33
|
+
```bash
|
|
34
|
+
pip install -e .
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
The component handles all NiiVue assets internally, making it simple to use:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
import streamlit as st
|
|
43
|
+
from niivue_component import niivue_viewer
|
|
44
|
+
|
|
45
|
+
# Simple usage - no need to handle CSS/JS files
|
|
46
|
+
uploaded_file = st.file_uploader("Choose a NIFTI file", type=["nii", "nii.gz"])
|
|
47
|
+
|
|
48
|
+
if uploaded_file is not None:
|
|
49
|
+
file_bytes = uploaded_file.getvalue()
|
|
50
|
+
|
|
51
|
+
result = niivue_viewer(
|
|
52
|
+
nifti_data=file_bytes,
|
|
53
|
+
filename=uploaded_file.name,
|
|
54
|
+
height=600,
|
|
55
|
+
key="niivue_viewer"
|
|
56
|
+
)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## API Reference
|
|
60
|
+
|
|
61
|
+
### `niivue_viewer(nifti_data=None, filename="", height=600, key=None)`
|
|
62
|
+
|
|
63
|
+
Parameters:
|
|
64
|
+
- `nifti_data` (bytes, optional): Raw NIFTI file data
|
|
65
|
+
- `filename` (str, optional): Name of the file being displayed
|
|
66
|
+
- `height` (int, optional): Height of the component in pixels (default: 600)
|
|
67
|
+
- `key` (str, optional): Unique key for the component
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
- `dict` or `None`: Component return value (if any)
|
|
71
|
+
|
|
72
|
+
## Development
|
|
73
|
+
|
|
74
|
+
### For Development with Hot Reload
|
|
75
|
+
|
|
76
|
+
1. In one terminal, start the React development server:
|
|
77
|
+
```bash
|
|
78
|
+
cd frontend
|
|
79
|
+
npm start
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
2. In your Python component (`__init__.py`), set `_RELEASE = False`
|
|
83
|
+
|
|
84
|
+
3. In another terminal, run your Streamlit app:
|
|
85
|
+
```bash
|
|
86
|
+
streamlit run test_simplified_api.py
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Component Structure
|
|
90
|
+
|
|
91
|
+
- `__init__.py` - Main Python component with asset loading
|
|
92
|
+
- `assets/` - Bundled NiiVue CSS, JS, and WASM files (auto-generated, not in git)
|
|
93
|
+
- `frontend/` - React frontend
|
|
94
|
+
- `src/NiiVueViewer.tsx` - Main React component
|
|
95
|
+
- `package.json` - Node dependencies
|
|
96
|
+
- `pyproject.toml` - Package configuration
|
|
97
|
+
|
|
98
|
+
## Publishing to PyPI
|
|
99
|
+
|
|
100
|
+
The component is ready for PyPI publication with all assets bundled:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
python -m build
|
|
104
|
+
twine upload dist/*
|
|
105
|
+
```
|