# lf_mri_platform

Umbrella microservice platform for the LF-MRI system.
Brings up the entire backend stack with a single command; the GUI runs on the host.

---

## Deployment architecture

```
┌─── Host (Windows) ──────────────────────────────────────────────────────────┐
│                                                                              │
│   lf_mri_gui.exe  (or  python app.py)                                       │
│   ┌──────────────┬──────────────┬──────────────┐                            │
│   │ Sequence tab │ Scanner tab  │   FID tab    │                            │
│   │ REST or local│ REST only    │  local only  │                            │
│   └──────┬───────┴──────┬───────┴──────────────┘                            │
│          │               │                                                   │
│          │ HTTP:7475     │ HTTP:1717                                         │
│          │               │                                                   │
└──────────┼───────────────┼─────────────────────────────────────────────────┘
           │               │
┌──────────▼───────────────▼──── Docker (lf_mri_platform) ───────────────────┐
│                                                                              │
│  ┌─────────────────┐    ┌─────────────────────────────────────────────┐     │
│  │  seq-interp     │    │  orchestrator                               │     │
│  │  :7475          │    │  :1717                                      │     │
│  │                 │    │  MODE=plug → stub tasks (no hardware)       │     │
│  │  POST /interpret│    │  MODE=real → calls spectrometer+reconstructor│    │
│  │  GET  /result   │    └──────────┬─────────────────────┬───────────┘     │
│  └─────────────────┘               │                     │                 │
│                                    │ HTTP:8000            │ HTTP:8081       │
│  ┌─────────────────┐  ┌────────────▼──────┐  ┌──────────▼──────────┐      │
│  │  spectroscopy   │  │  spectrometer     │  │  reconstructor      │      │
│  │  :8002          │  │  :8000 (DRF)      │  │  :8081 (FastAPI)    │      │
│  └─────────────────┘  └───────────────────┘  └─────────────────────┘      │
└──────────────────────────────────────────────────────────────────────────────┘
```

---

## Services

| Service | Port | Purpose | Docker-ready |
|---------|------|---------|-------------|
| orchestrator | 1717 | Workflow engine | yes (dockerfile_inline) |
| seq-interp | 7475 | .seq interpreter → XML/waveforms | yes (Dockerfile) |
| spectrometer | 8000 | Hardware acquisition (DRF) | yes (dockerfile_inline) |
| reconstructor | 8081 | MRI image reconstruction | yes (dockerfile_inline) |
| spectroscopy | 8002 | Signal processor | yes (Dockerfile) |

---

## Quick start

### Prerequisites
- Windows 10/11
- [Docker Desktop](https://www.docker.com/products/docker-desktop/) ≥ 4.x
- Python 3.10+ (for GUI)

### First time
```powershell
cd D:\Projects\lf_mri_platform

# Install GUI dependencies + create shortcuts
.\install.ps1
```

### Daily use
```powershell
# Start services (Docker) + GUI (host Python) — stub mode
.\start.ps1

# Start in real hardware mode
.\start.ps1 -Mode real

# Start services only (no GUI)
.\start.ps1 -ServicesOnly

# Start GUI only (without Docker services)
.\start.ps1 -GuiOnly

# Stop services
.\stop.ps1

# Full reset (remove volumes/data)
.\stop.ps1 -Clean
```

### With Make (WSL/Git Bash)
```bash
make plug      # start in stub mode
make real      # start in real mode
make health    # check all endpoints
make logs      # tail all logs
make down      # stop
```

---

## Modes

| Mode | Switch | Description |
|------|--------|-------------|
| **plug** | default | Stub tasks — instant mock responses, no hardware needed |
| **real** | `-Mode real` | Live tasks — orchestrator calls real spectrometer + reconstructor |

---

## GUI communication

The GUI is currently **hybrid** — not a pure thin client:

| Tab | How it communicates |
|-----|---------------------|
| Sequence | REST → seq-interp:7475 **if online**, otherwise local Python |
| Scanner | REST → orchestrator:1717 (always) |
| FID | Local Python + file I/O only |

---

## Build standalone .exe (optional)

```powershell
cd D:\Projects\lf_mri\MRI-testing\lf_mri_gui
.venv\Scripts\activate
build_exe.bat
# Output: dist\lf_mri_gui\lf_mri_gui.exe
```

---

## Docker compatibility status

All services are now buildable as Docker containers.

| Service | Previously broken | Fix applied |
|---------|-------------------|-------------|
| reconstructor | Windows `\\` in paths (`reco.py`) | `os.path.join()` — fixed |
| reconstructor | `matplotlib` without Agg backend | `matplotlib.use('Agg')` + `MPLBACKEND=Agg` in dockerfile — fixed |
| spectroscopy | Missing `/health` endpoint (healthcheck failed) | Added `GET /health` to `main.py` — fixed |
| spectroscopy | `matplotlib` without explicit Agg backend | `matplotlib.use('Agg')` in `main.py` — fixed |
| spectroscopy | `host="127.0.0.1"` in `run_py.py` | Not used by Docker (CMD calls uvicorn directly) — N/A |
| spectroscopy | `plt.show()` in `ESSSST.py` | No-op with Agg backend — N/A |
| seq-interp | PySide6/pyqtgraph pulled in via `-r ../requirements.txt` | `seq_interp/requirements.docker.txt` without GUI libs — fixed  |

---

## Source layout

```
D:\Projects\
├── lf_mri_platform\              ← this repo (infrastructure)
│   ├── docker-compose.yml
│   ├── .env.example
│   ├── install.ps1
│   ├── start.ps1 / start.bat
│   ├── stop.ps1
│   └── Makefile
├── lf_orchestration\             ← orchestrator source
├── lf_mri\
│   ├── MRI-testing\
│   │   ├── seq_interp\           ← seq-interp source
│   │   └── lf_mri_gui\          ← GUI source
│   │       ├── lf_mri_gui.spec  ← PyInstaller spec
│   │       └── build_exe.bat
│   └── fast-api-spectroscopy\   ← spectroscopy source
├── fast-api-reconstruction\
│   └── serv\                    ← reconstructor source
└── lowfield_mri_programs\
    └── spectrometer_service\
        └── mserv00\             ← spectrometer (DRF) source
```
