|
|
@@ -1,11 +1,11 @@
|
|
|
# ==============================================================================
|
|
|
# lf_mri_platform -- Start services and GUI
|
|
|
# Usage:
|
|
|
-# .\start.ps1 -- plug mode: Docker + GUI
|
|
|
-# .\start.ps1 -Mode real -- real mode: Docker + spectrometer + GUI
|
|
|
-# .\start.ps1 -GuiOnly -- GUI only (services already running)
|
|
|
-# .\start.ps1 -ServicesOnly -- Docker + spectrometer, no GUI
|
|
|
-# .\start.ps1 -SkipInstall -- skip venv check
|
|
|
+# .\start.ps1 -- plug mode: Docker + GUI
|
|
|
+# .\start.ps1 -Mode real -- real mode: Docker + spectrometer + GUI
|
|
|
+# .\start.ps1 -GuiOnly -- GUI only (services already running)
|
|
|
+# .\start.ps1 -ServicesOnly -- Docker + spectrometer, no GUI
|
|
|
+# .\start.ps1 -SkipInstall -- skip venv check
|
|
|
# .\start.ps1 -SkipSpectrometer -- skip native spectrometer even in real mode
|
|
|
# ==============================================================================
|
|
|
param(
|
|
|
@@ -35,13 +35,14 @@ function Write-Fail($msg) {
|
|
|
exit 1
|
|
|
}
|
|
|
|
|
|
-# Catch any unhandled terminating error — keep window open so user can read it
|
|
|
+# Keep window open on any unhandled error
|
|
|
trap {
|
|
|
Write-Host "`n[ERROR] $_" -ForegroundColor Red
|
|
|
Write-Host "`n Press Enter to close..." -ForegroundColor DarkGray
|
|
|
$null = Read-Host
|
|
|
exit 1
|
|
|
}
|
|
|
+
|
|
|
function Get-EnvPort($key, $default) {
|
|
|
if (Test-Path $EnvFile) {
|
|
|
$line = Get-Content $EnvFile | Select-String "^$key=(\d+)"
|
|
|
@@ -88,7 +89,8 @@ if (-not $GuiOnly) {
|
|
|
|
|
|
$waited = 0
|
|
|
while ($waited -lt 60) {
|
|
|
- Start-Sleep 5; $waited += 5
|
|
|
+ Start-Sleep 5
|
|
|
+ $waited += 5
|
|
|
try { & docker info *>$null; $dockerOk = $true; break } catch {}
|
|
|
Write-Host " ... $waited/60 s" -ForegroundColor DarkGray
|
|
|
}
|
|
|
@@ -98,8 +100,12 @@ if (-not $GuiOnly) {
|
|
|
|
|
|
# -- 3. .env ---------------------------------------------------------------
|
|
|
if (-not (Test-Path $EnvFile)) {
|
|
|
- if (Test-Path $EnvExample) { Copy-Item $EnvExample $EnvFile; Write-Warn ".env created from .env.example" }
|
|
|
- else { Write-Warn ".env missing -- using Compose defaults" }
|
|
|
+ if (Test-Path $EnvExample) {
|
|
|
+ Copy-Item $EnvExample $EnvFile
|
|
|
+ Write-Warn ".env created from .env.example"
|
|
|
+ } else {
|
|
|
+ Write-Warn ".env missing -- using Compose defaults"
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
# -- 4. Start containers ---------------------------------------------------
|
|
|
@@ -117,11 +123,9 @@ if (-not $GuiOnly) {
|
|
|
$SpecVenv = Join-Path $SpecDir "mvenv\Scripts\python.exe"
|
|
|
$PicoExe = Join-Path $SpecDir "bin\pico-tcp.exe"
|
|
|
|
|
|
- # Kill stale pico-tcp
|
|
|
$oldPico = Get-Process -Name "pico-tcp" -ErrorAction SilentlyContinue
|
|
|
if ($oldPico) { $oldPico | Stop-Process -Force; Write-Warn "Killed stale pico-tcp.exe" }
|
|
|
|
|
|
- # Create venv on first run
|
|
|
if (-not (Test-Path $SpecVenv)) {
|
|
|
Write-Warn "Spectrometer venv not found -- creating..."
|
|
|
Push-Location $SpecDir
|
|
|
@@ -136,24 +140,27 @@ if (-not $GuiOnly) {
|
|
|
Write-OK "Spectrometer venv found"
|
|
|
}
|
|
|
|
|
|
- # Migrations
|
|
|
Push-Location $SpecDir
|
|
|
& $SpecVenv manage.py migrate --noinput 2>&1 | Out-Null
|
|
|
Pop-Location
|
|
|
Write-OK "Migrations applied"
|
|
|
|
|
|
- # pico-tcp.exe
|
|
|
- if (Test-Path $PicoExe) { Start-Process $PicoExe -WindowStyle Hidden; Write-OK "pico-tcp.exe started" }
|
|
|
- else { Write-Warn "bin\pico-tcp.exe not found -- ADC proxy not started" }
|
|
|
+ if (Test-Path $PicoExe) {
|
|
|
+ Start-Process $PicoExe -WindowStyle Hidden
|
|
|
+ Write-OK "pico-tcp.exe started"
|
|
|
+ } else {
|
|
|
+ Write-Warn "bin\pico-tcp.exe not found -- ADC proxy not started"
|
|
|
+ }
|
|
|
|
|
|
- # Django runserver
|
|
|
$running = Get-Process -Name python* -ErrorAction SilentlyContinue |
|
|
|
Where-Object { $_.CommandLine -like "*manage.py*runserver*" }
|
|
|
if ($running) {
|
|
|
Write-OK "Spectrometer already running (PID $($running.Id))"
|
|
|
} else {
|
|
|
- Start-Process $SpecVenv -ArgumentList "manage.py runserver 0.0.0.0:8000" `
|
|
|
- -WorkingDirectory $SpecDir -WindowStyle Normal
|
|
|
+ Start-Process $SpecVenv `
|
|
|
+ -ArgumentList "manage.py runserver 0.0.0.0:8000" `
|
|
|
+ -WorkingDirectory $SpecDir `
|
|
|
+ -WindowStyle Normal
|
|
|
Write-OK "Spectrometer started in new window"
|
|
|
}
|
|
|
}
|
|
|
@@ -162,31 +169,46 @@ if (-not $GuiOnly) {
|
|
|
Write-Step "Waiting for services to become healthy"
|
|
|
$checkSpec = ($Mode -eq "real") -and (-not $SkipSpectrometer)
|
|
|
$services = @(
|
|
|
- @{ Name = "Orchestrator"; Url = "http://localhost:$(Get-EnvPort 'ORCHESTRATOR_PORT' '1717')/health"; Required = $true },
|
|
|
- @{ Name = "Seq-Interp"; Url = "http://localhost:$(Get-EnvPort 'SEQ_INTERP_PORT' '7475')/health"; Required = $true },
|
|
|
- @{ Name = "Reconstructor"; Url = "http://localhost:$(Get-EnvPort 'RECONSTRUCTOR_PORT' '8081')/health"; Required = $true },
|
|
|
- @{ Name = "Spectroscopy"; Url = "http://localhost:$(Get-EnvPort 'SPECTROSCOPY_PORT' '8002')/health"; Required = $true },
|
|
|
- @{ Name = "Spectrometer*"; Url = "http://localhost:$(Get-EnvPort 'SPECTROMETER_PORT' '8000')/api/"; Required = $checkSpec }
|
|
|
+ @{ Name = "Orchestrator"; Url = "http://localhost:$(Get-EnvPort 'ORCHESTRATOR_PORT' '1717')/health"; Required = $true },
|
|
|
+ @{ Name = "Seq-Interp"; Url = "http://localhost:$(Get-EnvPort 'SEQ_INTERP_PORT' '7475')/health"; Required = $true },
|
|
|
+ @{ Name = "Reconstructor"; Url = "http://localhost:$(Get-EnvPort 'RECONSTRUCTOR_PORT' '8081')/health"; Required = $true },
|
|
|
+ @{ Name = "Spectroscopy"; Url = "http://localhost:$(Get-EnvPort 'SPECTROSCOPY_PORT' '8002')/health"; Required = $true },
|
|
|
+ @{ Name = "Spectrometer"; Url = "http://localhost:$(Get-EnvPort 'SPECTROMETER_PORT' '8000')/api/"; Required = $checkSpec }
|
|
|
)
|
|
|
|
|
|
$maxWait = 120; $interval = 3; $elapsed = 0
|
|
|
while ($elapsed -lt $maxWait) {
|
|
|
- $pending = $services | Where-Object { $_.Required } | Where-Object {
|
|
|
- try { (Invoke-WebRequest $_.Url -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop).StatusCode -ge 400 }
|
|
|
- catch { $true }
|
|
|
+ $pending = @()
|
|
|
+ foreach ($svc in $services) {
|
|
|
+ if (-not $svc.Required) { continue }
|
|
|
+ $up = $false
|
|
|
+ try {
|
|
|
+ $r = Invoke-WebRequest $svc.Url -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
|
|
|
+ $up = ($r.StatusCode -lt 400)
|
|
|
+ } catch {}
|
|
|
+ if (-not $up) { $pending += $svc.Name }
|
|
|
}
|
|
|
- if (-not $pending) { Write-OK "All required services healthy"; break }
|
|
|
- Write-Host (" ... {0}/{1} s waiting: {2}" -f $elapsed, $maxWait, ($pending.Name -join ", ")) -ForegroundColor DarkGray
|
|
|
- Start-Sleep $interval; $elapsed += $interval
|
|
|
+ if ($pending.Count -eq 0) { Write-OK "All required 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 in time -- continuing anyway" }
|
|
|
|
|
|
Write-Host ""
|
|
|
foreach ($svc in $services) {
|
|
|
- $ok = try { (Invoke-WebRequest $svc.Url -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop).StatusCode -lt 400 } catch { $false }
|
|
|
- $icon = if ($ok) { "[OK]" } else { "[--]" }
|
|
|
- $color = if ($ok) { "Green" } elseif ($svc.Required) { "Yellow" } else { "DarkGray" }
|
|
|
- $suffix = if (-not $svc.Required -and -not $ok) { " (native — start manually if needed)" } else { "" }
|
|
|
+ $ok = $false
|
|
|
+ try {
|
|
|
+ $r = Invoke-WebRequest $svc.Url -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
|
|
|
+ $ok = ($r.StatusCode -lt 400)
|
|
|
+ } catch {}
|
|
|
+ $icon = if ($ok) { "[OK]" } else { "[--]" }
|
|
|
+ $color = if ($ok) { "Green" } elseif ($svc.Required) { "Yellow" } else { "DarkGray" }
|
|
|
+ if (-not $svc.Required -and -not $ok) {
|
|
|
+ $suffix = " (native -- start manually)"
|
|
|
+ } else {
|
|
|
+ $suffix = ""
|
|
|
+ }
|
|
|
Write-Host (" {0,-6} {1,-16} {2}{3}" -f $icon, $svc.Name, $svc.Url, $suffix) -ForegroundColor $color
|
|
|
}
|
|
|
|
|
|
@@ -196,7 +218,7 @@ if (-not $GuiOnly) {
|
|
|
$seqPort = Get-EnvPort "SEQ_INTERP_PORT" "7475"
|
|
|
$spectPort = Get-EnvPort "SPECTROSCOPY_PORT" "8002"
|
|
|
$cfgPath = Join-Path $Root "apps\gui\cfg\server_config.json"
|
|
|
- @{
|
|
|
+ $cfgObj = @{
|
|
|
srv_name = "srv_interp"
|
|
|
log_dir = "log"
|
|
|
upload_dir = "data/input"
|
|
|
@@ -207,8 +229,9 @@ if (-not $GuiOnly) {
|
|
|
seq_interp_url = "http://localhost:$seqPort"
|
|
|
spectroscopy_url = "http://localhost:$spectPort"
|
|
|
mode = $Mode
|
|
|
- } | ConvertTo-Json -Depth 3 | Set-Content $cfgPath -Encoding utf8
|
|
|
- Write-OK "server_config.json updated (mode=$Mode, ports: orch=$orchPort seq=$seqPort spectro=$spectPort)"
|
|
|
+ }
|
|
|
+ $cfgObj | ConvertTo-Json -Depth 3 | Set-Content $cfgPath -Encoding utf8
|
|
|
+ Write-OK "server_config.json updated (mode=$Mode orch=:$orchPort seq=:$seqPort spectro=:$spectPort)"
|
|
|
}
|
|
|
|
|
|
# -- 8. Launch GUI -------------------------------------------------------------
|