|
|
@@ -0,0 +1,145 @@
|
|
|
+# ==============================================================================
|
|
|
+# lf_mri_platform — One-time installation script
|
|
|
+# Run as: .\install.ps1
|
|
|
+# Requires: Windows 10/11, PowerShell 5.1+, internet access
|
|
|
+# ==============================================================================
|
|
|
+param(
|
|
|
+ [string]$PythonExe = "python",
|
|
|
+ [string]$GuiDir = "..\lf_mri\MRI-testing\lf_mri_gui",
|
|
|
+ [string]$RepoRoot = "..\lf_mri\MRI-testing"
|
|
|
+)
|
|
|
+
|
|
|
+$ErrorActionPreference = "Stop"
|
|
|
+
|
|
|
+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 " [FAIL] $msg" -ForegroundColor Red; exit 1 }
|
|
|
+
|
|
|
+# ── 1. Check prerequisites ────────────────────────────────────────────────────
|
|
|
+Write-Step "Checking prerequisites"
|
|
|
+
|
|
|
+# Python
|
|
|
+try {
|
|
|
+ $pyVer = & $PythonExe --version 2>&1
|
|
|
+ if ($pyVer -match "3\.(1[0-9]|[0-9]+)") {
|
|
|
+ Write-OK "Python: $pyVer"
|
|
|
+ } else {
|
|
|
+ Write-Fail "Python 3.10+ required, found: $pyVer"
|
|
|
+ }
|
|
|
+} catch {
|
|
|
+ Write-Fail "Python not found. Install from https://python.org (add to PATH)"
|
|
|
+}
|
|
|
+
|
|
|
+# Docker
|
|
|
+try {
|
|
|
+ $dockerVer = & docker --version 2>&1
|
|
|
+ Write-OK "Docker: $dockerVer"
|
|
|
+} catch {
|
|
|
+ Write-Warn "Docker not found — services (orchestrator, seq_interp, etc.) won't start."
|
|
|
+ Write-Warn "Install Docker Desktop: https://www.docker.com/products/docker-desktop/"
|
|
|
+}
|
|
|
+
|
|
|
+# Docker Compose
|
|
|
+try {
|
|
|
+ $composeVer = & docker compose version 2>&1
|
|
|
+ Write-OK "Docker Compose: $composeVer"
|
|
|
+} catch {
|
|
|
+ Write-Warn "Docker Compose not found (included in Docker Desktop >= 3.0)"
|
|
|
+}
|
|
|
+
|
|
|
+# ── 2. Create Python virtual environment for the GUI ─────────────────────────
|
|
|
+Write-Step "Creating Python virtual environment"
|
|
|
+
|
|
|
+$venvPath = Join-Path $GuiDir ".venv"
|
|
|
+$absGuiDir = Resolve-Path $GuiDir -ErrorAction SilentlyContinue
|
|
|
+if (-not $absGuiDir) { Write-Fail "GUI directory not found: $GuiDir" }
|
|
|
+
|
|
|
+if (Test-Path $venvPath) {
|
|
|
+ Write-Warn "Venv already exists at $venvPath — skipping creation"
|
|
|
+} else {
|
|
|
+ & $PythonExe -m venv $venvPath
|
|
|
+ Write-OK "Created venv at $venvPath"
|
|
|
+}
|
|
|
+
|
|
|
+$pip = Join-Path $venvPath "Scripts\pip.exe"
|
|
|
+
|
|
|
+# ── 3. Install GUI dependencies ───────────────────────────────────────────────
|
|
|
+Write-Step "Installing GUI dependencies"
|
|
|
+
|
|
|
+# Install root requirements first (numpy, scipy, etc.)
|
|
|
+$rootReqs = Join-Path $RepoRoot "requirements.txt"
|
|
|
+if (Test-Path $rootReqs) {
|
|
|
+ & $pip install -r $rootReqs --quiet
|
|
|
+ Write-OK "Root requirements installed"
|
|
|
+}
|
|
|
+
|
|
|
+# Install GUI-specific requirements
|
|
|
+$guiReqs = Join-Path $GuiDir "requirements.txt"
|
|
|
+if (Test-Path $guiReqs) {
|
|
|
+ & $pip install -r $guiReqs --quiet
|
|
|
+ Write-OK "GUI requirements installed"
|
|
|
+}
|
|
|
+
|
|
|
+# Install LF_scanner as editable package
|
|
|
+$lfScannerSetup = Join-Path $RepoRoot "LF_scanner\setup.py"
|
|
|
+if (Test-Path $lfScannerSetup) {
|
|
|
+ & $pip install -e (Join-Path $RepoRoot "LF_scanner") --quiet
|
|
|
+ Write-OK "LF_scanner installed (editable)"
|
|
|
+} else {
|
|
|
+ Write-Warn "LF_scanner/setup.py not found — skipping"
|
|
|
+}
|
|
|
+
|
|
|
+# ── 4. Copy .env for Docker services ─────────────────────────────────────────
|
|
|
+Write-Step "Setting up Docker environment config"
|
|
|
+
|
|
|
+$envFile = Join-Path $PSScriptRoot ".env"
|
|
|
+$envExample = Join-Path $PSScriptRoot ".env.example"
|
|
|
+
|
|
|
+if (-not (Test-Path $envFile)) {
|
|
|
+ Copy-Item $envExample $envFile
|
|
|
+ Write-OK ".env created from .env.example"
|
|
|
+} else {
|
|
|
+ Write-Warn ".env already exists — not overwriting"
|
|
|
+}
|
|
|
+
|
|
|
+# ── 5. Create desktop shortcut ────────────────────────────────────────────────
|
|
|
+Write-Step "Creating desktop shortcuts"
|
|
|
+
|
|
|
+$desktopPath = [Environment]::GetFolderPath("Desktop")
|
|
|
+$pythonExePath = Join-Path $venvPath "Scripts\python.exe"
|
|
|
+$appScript = Resolve-Path (Join-Path $GuiDir "app.py")
|
|
|
+
|
|
|
+# Shortcut: Start GUI only
|
|
|
+$wsh = New-Object -ComObject WScript.Shell
|
|
|
+$sc = $wsh.CreateShortcut("$desktopPath\LF-MRI GUI.lnk")
|
|
|
+$sc.TargetPath = $pythonExePath
|
|
|
+$sc.Arguments = "`"$appScript`""
|
|
|
+$sc.WorkingDirectory = (Resolve-Path $RepoRoot).Path
|
|
|
+$sc.Description = "LF-MRI System GUI"
|
|
|
+$sc.Save()
|
|
|
+Write-OK "Shortcut: 'LF-MRI GUI.lnk' on Desktop"
|
|
|
+
|
|
|
+# Shortcut: Start all (services + GUI)
|
|
|
+$startAll = Resolve-Path (Join-Path $PSScriptRoot "start.ps1")
|
|
|
+$scAll = $wsh.CreateShortcut("$desktopPath\LF-MRI Start All.lnk")
|
|
|
+$scAll.TargetPath = "powershell.exe"
|
|
|
+$scAll.Arguments = "-ExecutionPolicy Bypass -File `"$startAll`""
|
|
|
+$scAll.WorkingDirectory = $PSScriptRoot
|
|
|
+$scAll.Description = "Start LF-MRI services + GUI"
|
|
|
+$scAll.Save()
|
|
|
+Write-OK "Shortcut: 'LF-MRI Start All.lnk' on Desktop"
|
|
|
+
|
|
|
+# ── 6. Summary ────────────────────────────────────────────────────────────────
|
|
|
+Write-Host ""
|
|
|
+Write-Host "============================================================" -ForegroundColor Green
|
|
|
+Write-Host " Installation complete!" -ForegroundColor Green
|
|
|
+Write-Host "============================================================" -ForegroundColor Green
|
|
|
+Write-Host ""
|
|
|
+Write-Host " Next steps:"
|
|
|
+Write-Host " 1. Start all services + GUI: .\start.ps1"
|
|
|
+Write-Host " 2. GUI only (no services): .\start.ps1 -GuiOnly"
|
|
|
+Write-Host " 3. Stop services: .\stop.ps1"
|
|
|
+Write-Host ""
|
|
|
+Write-Host " Config: edit .env to change ports or switch mode (plug/real)"
|
|
|
+Write-Host ""
|