VibecoderMcSwaggins commited on
Commit
da08b3c
·
1 Parent(s): 8e0cd11

Refactor documentation for Docker and Gradio implementation. Removed outdated permission fix code and fallback matplotlib rendering section. Updated Gradio approach to use direct Base64 injection instead of FastAPI endpoints, enhancing simplicity and performance.

Browse files
docs/specs/03-phase-2-deepisles-docker.md CHANGED
@@ -795,23 +795,6 @@ def build_docker_command(
795
  return cmd
796
  ```
797
 
798
- Alternative: Fix permissions after Docker completes (less clean but works):
799
-
800
- ```python
801
- def fix_docker_output_permissions(output_dir: Path) -> None:
802
- """Fix permissions on Docker-created files."""
803
- import subprocess
804
- # Only needed if running as non-root and files are root-owned
805
- try:
806
- subprocess.run(
807
- ["sudo", "chown", "-R", f"{os.getuid()}:{os.getgid()}", str(output_dir)],
808
- check=True,
809
- capture_output=True,
810
- )
811
- except (subprocess.CalledProcessError, FileNotFoundError):
812
- pass # sudo not available or not needed
813
- ```
814
-
815
  ### critical: gpu availability check
816
 
817
  **Reviewer feedback (valid)**: We check for Docker daemon but not NVIDIA Container Runtime. A user might have Docker but lack GPU passthrough setup.
 
795
  return cmd
796
  ```
797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
798
  ### critical: gpu availability check
799
 
800
  **Reviewer feedback (valid)**: We check for Docker daemon but not NVIDIA Container Runtime. A user might have Docker but lack GPU passthrough setup.
docs/specs/05-phase-4-gradio-ui.md CHANGED
@@ -91,17 +91,17 @@ Key patterns from Tobias's implementation:
91
  nv.opts.show3Dcrosshair = true;
92
  ```
93
 
94
- ### recommended approach: hybrid fastapi + gradio
95
 
96
- For our demo, we use a **hybrid approach**:
97
  - **Gradio** for case selection dropdown and "Run Segmentation" button
98
- - **FastAPI endpoints** for serving NIfTI data as base64
99
  - **NiiVue via `gr.HTML`** for interactive 3D visualization
100
 
101
  This gives us:
102
  - Gradio's nice UI components for inputs
103
- - Proven NiiVue rendering from Tobias's implementation
104
- - No iframe complexity
105
 
106
  ### concrete implementation
107
 
@@ -169,44 +169,6 @@ def create_niivue_viewer_html(
169
  """
170
  ```
171
 
172
- ### fallback: matplotlib 2d slices
173
-
174
- For environments where WebGL fails, provide matplotlib fallback:
175
-
176
- ```python
177
- import matplotlib.pyplot as plt
178
- import nibabel as nib
179
-
180
- def render_slices_fallback(nifti_path: Path, mask_path: Path | None = None) -> Figure:
181
- """Render 3-panel slice view with optional mask overlay."""
182
- img = nib.load(nifti_path)
183
- data = img.get_fdata()
184
-
185
- fig, axes = plt.subplots(1, 3, figsize=(15, 5))
186
-
187
- # Middle slices
188
- ax_slice = data.shape[2] // 2
189
- cor_slice = data.shape[1] // 2
190
- sag_slice = data.shape[0] // 2
191
-
192
- axes[0].imshow(data[:, :, ax_slice].T, cmap='gray', origin='lower')
193
- axes[0].set_title('Axial')
194
- axes[1].imshow(data[:, cor_slice, :].T, cmap='gray', origin='lower')
195
- axes[1].set_title('Coronal')
196
- axes[2].imshow(data[sag_slice, :, :].T, cmap='gray', origin='lower')
197
- axes[2].set_title('Sagittal')
198
-
199
- if mask_path:
200
- mask = nib.load(mask_path).get_fdata()
201
- # Overlay in red with alpha
202
- for ax, sl in zip(axes, [mask[:,:,ax_slice].T, mask[:,cor_slice,:].T, mask[sag_slice,:,:].T]):
203
- ax.imshow(sl, cmap='Reds', alpha=0.5, origin='lower')
204
-
205
- return fig
206
- ```
207
-
208
- **Recommendation**: Use NiiVue as primary (proven working), matplotlib as fallback.
209
-
210
  ## interfaces and types
211
 
212
  ### `ui/app.py`
@@ -369,7 +331,8 @@ def create_niivue_html(
369
  template = f"""
370
  <div id="gl" style="width:100%; height:{height}px;"></div>
371
  <script type="module">
372
- import {{ Niivue }} from 'https://niivue.github.io/niivue/features/niivue.esm.js';
 
373
  const nv = new Niivue({{ show3Dcrosshair: true }});
374
  nv.attachToCanvas(document.getElementById('gl'));
375
  const volumes = [{{ url: '{volume_url}' }}];
@@ -802,9 +765,7 @@ if __name__ == "__main__":
802
 
803
  ```toml
804
  # Add to pyproject.toml dependencies
805
- "matplotlib>=3.8.0",
806
- "fastapi>=0.115.0", # For API endpoints if using hybrid approach
807
- "uvicorn[standard]>=0.32.0", # For local development
808
  ```
809
 
810
  ## reference implementation
 
91
  nv.opts.show3Dcrosshair = true;
92
  ```
93
 
94
+ ### implementation approach: gradio + direct base64 injection
95
 
96
+ For our demo, we use:
97
  - **Gradio** for case selection dropdown and "Run Segmentation" button
98
+ - **Direct Base64 data URLs** injected into HTML (no separate API endpoints)
99
  - **NiiVue via `gr.HTML`** for interactive 3D visualization
100
 
101
  This gives us:
102
  - Gradio's nice UI components for inputs
103
+ - Proven NiiVue rendering pattern from Tobias's implementation
104
+ - No iframe complexity, no proxy issues in HF Spaces
105
 
106
  ### concrete implementation
107
 
 
169
  """
170
  ```
171
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  ## interfaces and types
173
 
174
  ### `ui/app.py`
 
331
  template = f"""
332
  <div id="gl" style="width:100%; height:{height}px;"></div>
333
  <script type="module">
334
+ const niivueModule = await import('https://unpkg.com/@niivue/niivue@0.57.0/dist/index.js');
335
+ const Niivue = niivueModule.Niivue;
336
  const nv = new Niivue({{ show3Dcrosshair: true }});
337
  nv.attachToCanvas(document.getElementById('gl'));
338
  const volumes = [{{ url: '{volume_url}' }}];
 
765
 
766
  ```toml
767
  # Add to pyproject.toml dependencies
768
+ "matplotlib>=3.8.0", # For static slice rendering in viewer.py
 
 
769
  ```
770
 
771
  ## reference implementation