Browse Source

fix orchestrator up

spacexerq 2 weeks ago
parent
commit
9e796723e2
2 changed files with 211 additions and 0 deletions
  1. 13 0
      LF_scanner/__init__.py
  2. 198 0
      launch.ps1

+ 13 - 0
LF_scanner/__init__.py

@@ -0,0 +1,13 @@
+"""Compatibility package for vendored lf-scanner sources.
+
+The vendored pypulseq copy still contains absolute imports such as
+``LF_scanner.pypulseq``. Expose ``libs/lf-scanner`` as the package path so
+those imports continue to resolve while application code imports ``pypulseq``
+directly.
+"""
+
+from pathlib import Path
+
+_VENDORED_ROOT = Path(__file__).resolve().parent.parent / "libs" / "lf-scanner"
+
+__path__ = [str(_VENDORED_ROOT)]

+ 198 - 0
launch.ps1

@@ -0,0 +1,198 @@
+# ==============================================================================
+#  lf_mri_platform -- Full launch: install (if needed) -> containers -> GUI
+#  Usage:
+#    .\launch.ps1                -- install if needed, start services + GUI
+#    .\launch.ps1 -Mode real     -- hardware mode
+#    .\launch.ps1 -SkipInstall   -- skip dependency check
+#    .\launch.ps1 -ServicesOnly  -- do not open GUI
+# ==============================================================================
+param(
+    [ValidateSet("plug", "real")]
+    [string]$Mode = "plug",
+    [switch]$SkipInstall,
+    [switch]$ServicesOnly
+)
+
+$ErrorActionPreference = "Stop"
+$Root        = $PSScriptRoot
+$GuiDir      = Join-Path $Root "apps\gui"
+$LibsDir     = Join-Path $Root "libs\lf-scanner"
+$VenvPython  = Join-Path $GuiDir ".venv\Scripts\python.exe"
+$VenvPip     = Join-Path $GuiDir ".venv\Scripts\pip.exe"
+$AppScript   = Join-Path $GuiDir "app.py"
+$EnvFile     = Join-Path $Root ".env"
+$EnvExample  = Join-Path $Root ".env.example"
+
+function Write-Step($msg) { Write-Host "`n==> $msg" -ForegroundColor Cyan }
+function Write-OK($msg)   { Write-Host "    [OK] $msg" -ForegroundColor Green }
+function Write-Warn($msg) { Write-Host "    [!!] $msg" -ForegroundColor Yellow }
+function Write-Fail($msg) { Write-Host "`n[FAIL] $msg" -ForegroundColor Red; exit 1 }
+
+# -- 1. Install dependencies if venv is missing --------------------------------
+if (-not $SkipInstall) {
+    Write-Step "Checking GUI environment"
+
+    $needsInstall = $false
+
+    if (-not (Test-Path $VenvPython)) {
+        Write-Warn "Virtual environment not found -- running install"
+        $needsInstall = $true
+    } else {
+        # Check that key packages are present
+        $checkPkg = & $VenvPython -c "import PyQt6" 2>&1
+        if ($LASTEXITCODE -ne 0) {
+            Write-Warn "GUI packages missing -- running install"
+            $needsInstall = $true
+        } else {
+            Write-OK "Virtual environment ready"
+        }
+    }
+
+    if ($needsInstall) {
+        $installScript = Join-Path $Root "install.ps1"
+        if (-not (Test-Path $installScript)) {
+            Write-Fail "install.ps1 not found at $installScript"
+        }
+        & powershell.exe -ExecutionPolicy Bypass -File $installScript
+        if ($LASTEXITCODE -ne 0) { Write-Fail "install.ps1 failed" }
+    }
+}
+
+# -- 2. Ensure Docker is running -----------------------------------------------
+Write-Step "Checking Docker"
+
+$dockerOk = $false
+try { & docker info *>$null; $dockerOk = $true } catch {}
+
+if (-not $dockerOk) {
+    Write-Warn "Docker not responding -- attempting to start Docker Desktop..."
+    $dockerExe = "C:\Program Files\Docker\Docker\Docker Desktop.exe"
+    if (Test-Path $dockerExe) {
+        Start-Process $dockerExe
+    } else {
+        Write-Fail "Docker Desktop not found. Install it from https://www.docker.com/products/docker-desktop/"
+    }
+
+    Write-Host "    Waiting up to 60 s for Docker to start..." -ForegroundColor DarkGray
+    $waited = 0
+    while ($waited -lt 60) {
+        Start-Sleep 5
+        $waited += 5
+        try { & docker info *>$null; $dockerOk = $true; break } catch {}
+        Write-Host "    ... $waited/60 s" -ForegroundColor DarkGray
+    }
+    if (-not $dockerOk) { Write-Fail "Docker did not start in time. Start Docker Desktop manually and re-run." }
+}
+Write-OK "Docker is running"
+
+# -- 3. Prepare .env -----------------------------------------------------------
+if (-not (Test-Path $EnvFile)) {
+    if (Test-Path $EnvExample) {
+        Copy-Item $EnvExample $EnvFile
+        Write-Warn ".env not found -- created from .env.example"
+    } else {
+        Write-Warn ".env and .env.example both missing -- using Docker Compose defaults"
+    }
+}
+
+# -- 4. Build and start containers ---------------------------------------------
+Write-Step "Starting Docker services (mode: $Mode)"
+
+$env:ORCHESTRATOR_MODE = $Mode
+
+$envArgs = if (Test-Path $EnvFile) { @("--env-file", $EnvFile) } else { @() }
+& docker compose @envArgs up --build -d
+if ($LASTEXITCODE -ne 0) { Write-Fail "docker compose up failed" }
+Write-OK "Containers started"
+
+# -- 5. Wait for all services to become healthy --------------------------------
+Write-Step "Waiting for services to become healthy"
+
+# Read ports from .env if available; fall back to compose defaults
+function Get-EnvPort($key, $default) {
+    if (Test-Path $EnvFile) {
+        $line = Get-Content $EnvFile | Select-String "^$key=(\d+)"
+        if ($line) { return $line.Matches[0].Groups[1].Value }
+    }
+    return $default
+}
+
+$services = @(
+    @{ Name = "Orchestrator";  Url = "http://localhost:$(Get-EnvPort 'ORCHESTRATOR_PORT' '1717')/health" },
+    @{ Name = "Seq-Interp";    Url = "http://localhost:$(Get-EnvPort 'SEQ_INTERP_PORT'   '7475')/health" },
+    @{ Name = "Reconstructor"; Url = "http://localhost:$(Get-EnvPort 'RECONSTRUCTOR_PORT' '8081')/health" },
+    @{ Name = "Spectroscopy";  Url = "http://localhost:$(Get-EnvPort 'SPECTROSCOPY_PORT'  '8002')/health" },
+    @{ Name = "Spectrometer";  Url = "http://localhost:$(Get-EnvPort 'SPECTROMETER_PORT'  '8000')/api/" }
+)
+
+$maxWait  = 120
+$interval = 3
+$elapsed  = 0
+
+while ($elapsed -lt $maxWait) {
+    $pending = @()
+    foreach ($svc in $services) {
+        try {
+            $r = Invoke-WebRequest $svc.Url -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
+            if ($r.StatusCode -lt 400) { continue }
+        } catch {}
+        $pending += $svc.Name
+    }
+
+    if ($pending.Count -eq 0) {
+        Write-OK "All services healthy"
+        break
+    }
+
+    Write-Host ("    ... {0}/{1} s  waiting: {2}" -f $elapsed, $maxWait, ($pending -join ", ")) -ForegroundColor DarkGray
+    Start-Sleep $interval
+    $elapsed += $interval
+}
+
+if ($elapsed -ge $maxWait) {
+    Write-Warn "Some services did not respond within ${maxWait}s -- GUI will start anyway"
+
+    foreach ($svc in $services) {
+        try {
+            $r = Invoke-WebRequest $svc.Url -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
+            $icon = if ($r.StatusCode -lt 400) { "[OK]" } else { "[--]" }
+        } catch {
+            $icon = "[--]"
+        }
+        Write-Host ("    {0,-6} {1,-15} {2}" -f $icon, $svc.Name, $svc.Url) -ForegroundColor $(if ($icon -eq "[OK]") {"Green"} else {"Yellow"})
+    }
+}
+
+# -- 6. Launch GUI in a separate window ----------------------------------------
+if (-not $ServicesOnly) {
+    Write-Step "Launching GUI"
+
+    if (-not (Test-Path $VenvPython)) {
+        Write-Warn "Venv not found -- falling back to system Python"
+        $VenvPython = "python"
+    }
+    if (-not (Test-Path $AppScript)) {
+        Write-Fail "GUI entry point not found: $AppScript"
+    }
+
+    Start-Process $VenvPython `
+        -ArgumentList "`"$AppScript`"" `
+        -WorkingDirectory $Root `
+        -WindowStyle Normal
+
+    Write-OK "GUI launched"
+}
+
+# -- 7. Summary ----------------------------------------------------------------
+Write-Host ""
+Write-Host "============================================================" -ForegroundColor Green
+Write-Host "  LF-MRI platform is running" -ForegroundColor Green
+Write-Host "============================================================" -ForegroundColor Green
+Write-Host ""
+Write-Host "  Service endpoints:"
+foreach ($svc in $services) {
+    Write-Host ("    {0,-15} {1}" -f $svc.Name, $svc.Url)
+}
+Write-Host ""
+Write-Host "  Stop services:  .\stop.ps1"
+Write-Host ""