319 lines
11 KiB
Markdown
319 lines
11 KiB
Markdown
# DICOM Project Journal
|
|
|
|
Transcripts are stored in `/mnt/transcripts/` (Claude's computer filesystem).
|
|
|
|
## Sessions
|
|
|
|
### 2025-12-12 - Version Management & Auto-Update System
|
|
|
|
**What was built:**
|
|
- Installation portal at http://inou.com:8000 (PIN-protected)
|
|
- Download pages for Windows/Mac with architecture options
|
|
- Auto-update system: bridge checks version on connect, blocks if outdated
|
|
- Semver comparison (1.0.10 > 1.0.2), allows ahead-of-release versions
|
|
- Dynamic update instructions using os.Executable() for actual path
|
|
- Server `/version?os=darwin&arch=arm64` returns download_url
|
|
|
|
**Version check flow:**
|
|
1. Bridge connects → calls GET /version?os={os}&arch={arch}
|
|
2. Server returns latest_bridge_version + download_url
|
|
3. Bridge compares versions (semver, not string)
|
|
4. If outdated: blocks all tool calls, returns curl command with exact path
|
|
5. User runs command via Desktop Commander, restarts Claude Desktop
|
|
|
|
**Key implementation details:**
|
|
- VERSION in Makefile controls all builds via ldflags
|
|
- Bridge knows platform (runtime.GOOS/GOARCH) and its own path (os.Executable)
|
|
- Server maps darwin→mac for URL paths
|
|
- Only blocks `tools/call` method, not initialization
|
|
- Returns success (not error) so Claude sees the message
|
|
|
|
**Files modified:**
|
|
- `/Volumes/dev/inou/mcp-client/main.go` - semver, auto-update blocking
|
|
- `/home/johan/dev/inou/mcp/main.go` - /version endpoint with download_url
|
|
- `/Volumes/dev/inou/portal/main.go` - installation portal
|
|
|
|
**Binary filenames standardized:**
|
|
- Windows: `inou_bridge_win_{amd64,arm64,386}.exe`
|
|
- Mac: `inou_bridge_darwin_{arm64,amd64}`
|
|
|
|
---
|
|
|
|
### 2025-12-11 - Multi-tenant & Session Persistence
|
|
|
|
**What was built:**
|
|
- Multi-frame DICOM support with per-frame position extraction
|
|
- Account/profile authentication system (accounts, account_profiles tables)
|
|
- Session persistence to SQLite (survives server restarts)
|
|
- Rich fetch_image metadata (patient, study, series, position, TR/TE)
|
|
- Walter Scott III patient added with full-body MRI (35 series, 3,371 slices)
|
|
|
|
**Files modified:**
|
|
- `/home/johan/dev/inou/mcp/main.go` - session persistence, account auth
|
|
- `/Volumes/dev/inou/convert/main.go` - multi-frame DICOM support
|
|
|
|
---
|
|
|
|
### 2025-12-07 - Zoom/Pan Implementation
|
|
|
|
**What was built:**
|
|
- Zoom feature with 5 levels (1x, 1.5x, 2x, 3x, 4x)
|
|
- Zoom to cursor position using Shift+scroll
|
|
- +/- keys for zoom in/out on hovered panel
|
|
- Pan with Shift+drag (only effective when zoomed)
|
|
- Double-click to reset zoom/pan
|
|
- Zoom/pan syncs by orientation type (all AX panels share state, etc.)
|
|
- Help modal (?) button showing all controls
|
|
- Request logging now includes IP address
|
|
|
|
**Key implementation details:**
|
|
- `zoomState` object tracks {level, panX, panY} per orientation (AX, SAG, COR)
|
|
- Transform: `translate() scale()` with origin at top-left
|
|
- Crosshairs and rectangles adjusted for zoom (divide out zoom from getBoundingClientRect)
|
|
- CSS transition disabled during pan for smooth movement
|
|
- Shift modifier used for both zoom and pan to avoid conflicts
|
|
|
|
**Files modified:**
|
|
- ~/dev/inou/viewer/main.go - zoom/pan state, event handlers, help modal, IP logging
|
|
|
|
---
|
|
|
|
### 2025-12-06 - 3D Crosshair View & API Improvements
|
|
Transcript: `2025-12-06-08-25-09-dicom-3d-crosshair-api-text-format.txt`
|
|
|
|
**What was built:**
|
|
- 3D crosshair view at /3d endpoint with SAG|AX|COR synchronized panels
|
|
- Vector-based crosshair positioning using ImageOrientationPatient math
|
|
- Fixed wheel scroll to work on any hovered panel
|
|
- API documentation at /api endpoint
|
|
- &format=text parameter returning HTML tables for AI model compatibility
|
|
- Request logging with timestamps
|
|
- Pixel spacing added to MCP fetch_image output
|
|
|
|
**Key learnings:**
|
|
- Crosshairs need to use slice CENTER (corner + half-dimensions along orientation vectors), not corner position
|
|
- Project 3D target onto 2D panel using dot product with row/col vectors
|
|
- Gemini's "browsing" = Google Search index, can't reach private servers
|
|
- Grok makes real HTTP requests but hallucinates results
|
|
|
|
**Files modified:**
|
|
- ~/dev/inou/viewer/main.go - 3D view, API endpoints, HTML format
|
|
- ~/dev/inou/mcp/main.go - Added pixel spacing to fetch_image output
|
|
|
|
---
|
|
|
|
### Earlier Sessions (various dates)
|
|
- Initial DICOM converter and viewer
|
|
- Rectangle coordinate system for pointing at findings
|
|
- Deep linking with URL parameters
|
|
- MCP server implementation
|
|
- X-ray pixel data offset fix
|
|
- Study import workflow
|
|
|
|
|
|
---
|
|
|
|
### 2025-12-17 - Phase 2: Bridge REST Migration & Schema Fixes
|
|
|
|
**Transcript:** 2025-12-17-09-45-12-phase2-bridge-rest-migration-complete.txt
|
|
|
|
**What was built:**
|
|
|
|
1. **Bridge migrated from SSE/MCP to pure REST API**
|
|
- Removed SSE connection, now makes direct HTTPS calls to viewer API
|
|
- All 8 tools working: list_profiles, list_studies, list_series, list_slices, fetch_image, query_anatomy, list_lab_tests, get_lab_results, get_version
|
|
- Uses --account=GUID parameter (account can have multiple profiles)
|
|
- Connects via https://inou.com/api/ (port 443, hospital-friendly)
|
|
|
|
2. **Account schema fixed**
|
|
- accounts.id is now GUID (was email hash)
|
|
- accounts.email_hash added for portal login lookup
|
|
- account_profiles.account_id references account GUID
|
|
- Portal login flow updated to use new schema
|
|
|
|
3. **Portal routing fixed**
|
|
- GET /api/profiles now proxies to viewer (was POST-only for creating profiles)
|
|
- All /api/* routes properly forwarded to viewer backend
|
|
|
|
4. **Convert improvements**
|
|
- insertSlice() now takes instanceNumber directly (was computing incorrectly)
|
|
- Passes frameCounter (sequential across series) instead of frameIdx (per-file)
|
|
- isLocalizer() enhanced to detect orientation mismatches:
|
|
- AX series: filters slices where rowX < 0.8 (should be ~1)
|
|
- SAG series: filters slices where rowX > 0.5 (should be ~0)
|
|
- Fixes instance_number always being 1
|
|
- Filters scout/localizer images automatically
|
|
|
|
5. **Database reset for re-import**
|
|
- Dropped studies, series, slices tables
|
|
- Cleaned /tank/inou/objects/
|
|
- Ready for fresh convert with fixed instance numbers
|
|
|
|
**Services architecture:**
|
|
```
|
|
Claude Desktop -> inou_bridge (stdio/REST) -> https://inou.com:443/api/*
|
|
| (portal proxy)
|
|
viewer:8765/api/*
|
|
```
|
|
|
|
**Files modified:**
|
|
- ~/dev/inou/mcp-client/main.go - Complete rewrite to REST client
|
|
- ~/dev/inou/portal/main.go - Schema fixes, GET /api/profiles routing
|
|
- ~/dev/inou/viewer/main.go - handleProfiles query fix
|
|
- ~/dev/inou/convert/main.go - instanceNumber fix, isLocalizer enhancement
|
|
|
|
**Binaries rebuilt:**
|
|
- /tank/inou/bin/convert
|
|
- /tank/inou/bin/inou_bridge_darwin_arm64
|
|
- /tank/inou/bin/inou-portal
|
|
- /tank/inou/bin/inou-viewer
|
|
|
|
**Still TODO:**
|
|
- Date formatting with locale awareness (bridge should detect OS locale)
|
|
- Add slice_index to API response
|
|
- Return viewer URL with fetch_image
|
|
- Re-run convert to populate database with correct instance numbers
|
|
|
|
**Command to run convert:**
|
|
```bash
|
|
cd /tank/inou && ./bin/convert
|
|
```
|
|
|
|
---
|
|
|
|
### 2025-12-18 - Verification & Image URL Enhancement
|
|
|
|
**What was done:**
|
|
|
|
1. **Verified fresh convert worked**
|
|
- 3167 slices imported successfully
|
|
- instance_number now sequential (1-25 for AX T2, etc.)
|
|
- Scout/localizer filtering working
|
|
|
|
2. **Tested all MCP tools with fresh data**
|
|
- list_profiles ✓
|
|
- list_studies ✓ (15 studies)
|
|
- list_series ✓ (MRI Brain: 10 series including T1, T2, FLAIR, SWAN, DTI)
|
|
- list_slices ✓ (returns full metadata)
|
|
- fetch_image ✓ (returns base64 PNG)
|
|
- query_anatomy ✓ (pons/medulla position ranges working)
|
|
- get_version ✓
|
|
|
|
3. **Added image_url to list_slices response**
|
|
- Each slice now includes: "image_url": "https://inou.com/image/{slice_guid}"
|
|
- Allows Claude to provide direct clickable links to images
|
|
- Change in viewer/main.go handleSlices()
|
|
|
|
4. **Reviewed and closed TODO items**
|
|
- Date format (YYYYMMDD): non-issue, Claude understands it fine
|
|
- slice_index: obsolete, instance_number now works correctly
|
|
- image_url: ✓ implemented
|
|
|
|
**Files modified:**
|
|
- ~/dev/inou/viewer/main.go - Added image_url field to handleSlices()
|
|
|
|
**Binaries rebuilt:**
|
|
- /tank/inou/bin/inou-viewer
|
|
|
|
|
|
## 2025-12-19: Design Reference - andrewmccalip.com/space-datacenters
|
|
|
|
Inspiration for future UI patterns:
|
|
|
|
**Horizontal bar charts**
|
|
- Label left, bar middle, value right
|
|
- Different colors per category (blue vs amber)
|
|
- Could use for: lab result ranges, storage usage, progress indicators
|
|
|
|
**Sliders with labeled ranges**
|
|
- Clean min/max labels below
|
|
- Marker dots at key positions
|
|
- Could use for: date range selection, threshold settings
|
|
|
|
**Label-value pairs**
|
|
|
|
- Muted left label, bold right value
|
|
- Great for metadata display
|
|
|
|
**Colored left borders on cards**
|
|
- Blue = one category, amber = another
|
|
- Section headers: (small caps, letter-spacing)
|
|
|
|
**Two-column comparison layout**
|
|
- Side by side for A vs B comparisons
|
|
|
|
## 2025-12-19: Design Reference - andrewmccalip.com/space-datacenters
|
|
|
|
Inspiration for future UI patterns:
|
|
|
|
**Horizontal bar charts**
|
|
- Label left, bar middle, value right
|
|
- Different colors per category (blue vs amber)
|
|
- Could use for: lab result ranges, storage usage, progress indicators
|
|
|
|
**Sliders with labeled ranges**
|
|
- Clean min/max labels below
|
|
- Marker dots at key positions
|
|
- Could use for: date range selection, threshold settings
|
|
|
|
**Label-value pairs**
|
|
- Muted left label, bold right value
|
|
- Example: "Cost per Watt" (grey) ... "$51.10/W" (bold)
|
|
- Great for metadata display
|
|
|
|
**Colored left borders on cards**
|
|
- Blue = one category, amber = another
|
|
- Section headers: small caps with letter-spacing and dot separator
|
|
|
|
**Two-column comparison layout**
|
|
- Side by side for A vs B comparisons
|
|
|
|
## 2025-12-19: AI Instructions (OUTDATED)
|
|
|
|
~~DO NOT USE `sed` for editing files.~~
|
|
|
|
**Update 2026-01-10:** This was written when running Claude on Mac via SSH to Linux, causing quote escaping issues. Now running Claude natively on Linux — `sed` works fine again.
|
|
|
|
## Mobile App - Input Parsing (Dec 21, 2024)
|
|
|
|
### Goal
|
|
Parse natural language input into structured health/wellness observations. The journal captures the *whole story* of a person's life, not just medical symptoms.
|
|
|
|
### Why
|
|
The pattern matters for healthcare:
|
|
- Dec 15: mother hospitalized
|
|
- Dec 16: can't sleep
|
|
- Dec 17: headache, took Tylenol
|
|
- Dec 18: BP 145/92
|
|
|
|
A doctor seeing just "BP 145/92" misses the context. The comprehensive journal shows the story.
|
|
|
|
### Categories to extract
|
|
- **symptom** - physical complaints
|
|
- **medication** - drugs, supplements
|
|
- **activity** - exercise, yard work, physical activity
|
|
- **vital** - measurable (BP, weight, temp)
|
|
- **bodily** - digestion, sleep, menstruation
|
|
- **mood** - emotional state
|
|
- **life_event** - stress, family, work, relationships
|
|
- **medical_event** - doctor visits, procedures, diagnoses
|
|
|
|
### Accept vs Reject
|
|
|
|
**Accept** (interpret through user's lens):
|
|
- "I worked in the yard" → activity
|
|
- "I got fired" → life_event (stress)
|
|
- "my wife wants to leave" → life_event (stress)
|
|
- "my mother is injured" → life_event (user's stress/worry, NOT medical record for mother)
|
|
|
|
**Reject** (not about the person's life):
|
|
- "what is the capital of Denmark"
|
|
- "write me a poem"
|
|
- trivia, requests to create things
|
|
|
|
### Dossier assignment
|
|
Only create structured records for people with dossiers. Everything else is context about the user's own state.
|
|
|
|
## TODO
|
|
- [ ] Improve genetic import progress communication
|