feat: add Gamma SBAS workflow and coverage design
This commit is contained in:
@@ -308,6 +308,25 @@ class Settings(BaseSettings):
|
||||
PYINT_GAMMA_ENV_SCRIPT: str = ""
|
||||
PYINT_DEFAULT_TIMEOUT_SECONDS: int = 43200
|
||||
PYINT_SMOKE_TEST_ENABLED: bool = False
|
||||
|
||||
GAMMA_SBAS_ENABLED: bool = True
|
||||
GAMMA_SBAS_RUNTIME_ID: str = ""
|
||||
GAMMA_SBAS_WSL_DISTRO: str = ""
|
||||
GAMMA_SBAS_PYTHON: str = ""
|
||||
GAMMA_SBAS_ENV_SCRIPT: str = ""
|
||||
GAMMA_SBAS_WORK_ROOT: str = ""
|
||||
GAMMA_SBAS_PRODUCT_ROOT: str = ""
|
||||
GAMMA_SBAS_SCRIPT_TEMPLATE_ROOT: str = ""
|
||||
GAMMA_SBAS_SOURCE_ROOTS: str = ""
|
||||
GAMMA_SBAS_ORBIT_ROOTS: str = ""
|
||||
GAMMA_SBAS_DEFAULT_RLKS: int = 8
|
||||
GAMMA_SBAS_DEFAULT_AZLKS: int = 8
|
||||
GAMMA_SBAS_DEFAULT_MB_MODE: int = 0
|
||||
GAMMA_SBAS_DEFAULT_REFERENCE_WINDOW: int = 16
|
||||
GAMMA_SBAS_AUTO_APPROVE_ITAB: bool = True
|
||||
GAMMA_SBAS_STEP_TIMEOUT_SECONDS: int = 43200
|
||||
GAMMA_SBAS_WORKFLOW_TIMEOUT_SECONDS: int = 172800
|
||||
|
||||
JOB_WORKER_HEALTH_TIMEOUT: int = 60
|
||||
JOB_WORKER_JOB_HEARTBEAT_INTERVAL: float = 5.0
|
||||
JOB_WORKER_STALE_RECOVER_INTERVAL: float = 15.0
|
||||
@@ -623,6 +642,79 @@ class Settings(BaseSettings):
|
||||
)
|
||||
if not self.PYINT_ORBIT_POOL_TXT:
|
||||
object.__setattr__(self, "PYINT_ORBIT_POOL_TXT", self.ORBIT_POOL_ENVI)
|
||||
if not self.GAMMA_SBAS_RUNTIME_ID:
|
||||
object.__setattr__(self, "GAMMA_SBAS_RUNTIME_ID", "gamma_sbas_runtime_v1")
|
||||
if not self.GAMMA_SBAS_WSL_DISTRO:
|
||||
object.__setattr__(
|
||||
self,
|
||||
"GAMMA_SBAS_WSL_DISTRO",
|
||||
self.WSL_DISTRO or self.PYINT_WSL_DISTRO or self.ISCE2_WSL_DISTRO,
|
||||
)
|
||||
if not self.GAMMA_SBAS_PYTHON:
|
||||
object.__setattr__(
|
||||
self,
|
||||
"GAMMA_SBAS_PYTHON",
|
||||
self.WSL_SHARED_PYTHON or self.PYINT_WSL_PYTHON or self.ISCE2_PYTHON,
|
||||
)
|
||||
if not self.GAMMA_SBAS_ENV_SCRIPT:
|
||||
object.__setattr__(self, "GAMMA_SBAS_ENV_SCRIPT", self.PYINT_GAMMA_ENV_SCRIPT)
|
||||
if not self.GAMMA_SBAS_WORK_ROOT:
|
||||
object.__setattr__(
|
||||
self,
|
||||
"GAMMA_SBAS_WORK_ROOT",
|
||||
os.path.join(backend_dir, "runtime", "sbas_insar_production"),
|
||||
)
|
||||
if not self.GAMMA_SBAS_PRODUCT_ROOT:
|
||||
object.__setattr__(
|
||||
self,
|
||||
"GAMMA_SBAS_PRODUCT_ROOT",
|
||||
os.path.join(self.TIMESERIES_PRODUCT_DIR, "sbas"),
|
||||
)
|
||||
if not self.GAMMA_SBAS_SCRIPT_TEMPLATE_ROOT:
|
||||
object.__setattr__(
|
||||
self,
|
||||
"GAMMA_SBAS_SCRIPT_TEMPLATE_ROOT",
|
||||
os.path.join(backend_dir, "templates", "gamma_sbas"),
|
||||
)
|
||||
if not self.GAMMA_SBAS_SOURCE_ROOTS:
|
||||
def _local_split_paths(raw: str | None) -> list[str]:
|
||||
items: list[str] = []
|
||||
for part in str(raw or "").replace(";", ",").split(","):
|
||||
text = part.strip().strip('"').strip("'")
|
||||
if text:
|
||||
items.append(text)
|
||||
return items
|
||||
lt1_roots = [
|
||||
item
|
||||
for value in (self.SOURCE_PRODUCT_DIRS, self.MONITOR_RADAR_DIRS, self.INSAR_STORAGE_DIRS)
|
||||
for item in _local_split_paths(value)
|
||||
if "lutan" in item.lower() or "lt1" in item.lower()
|
||||
]
|
||||
lt1_roots = list(dict.fromkeys(lt1_roots))
|
||||
object.__setattr__(self, "GAMMA_SBAS_SOURCE_ROOTS", ";".join(lt1_roots) or r"D:\LuTan1_Image_Pool")
|
||||
if not self.GAMMA_SBAS_ORBIT_ROOTS:
|
||||
object.__setattr__(self, "GAMMA_SBAS_ORBIT_ROOTS", self.PYINT_ORBIT_POOL_TXT or self.ORBIT_POOL_ENVI)
|
||||
object.__setattr__(self, "GAMMA_SBAS_DEFAULT_RLKS", max(1, int(self.GAMMA_SBAS_DEFAULT_RLKS or 8)))
|
||||
object.__setattr__(self, "GAMMA_SBAS_DEFAULT_AZLKS", max(1, int(self.GAMMA_SBAS_DEFAULT_AZLKS or 8)))
|
||||
gamma_sbas_mb_mode = int(self.GAMMA_SBAS_DEFAULT_MB_MODE or 0)
|
||||
if gamma_sbas_mb_mode not in {0, 1, 2}:
|
||||
gamma_sbas_mb_mode = 0
|
||||
object.__setattr__(self, "GAMMA_SBAS_DEFAULT_MB_MODE", gamma_sbas_mb_mode)
|
||||
object.__setattr__(
|
||||
self,
|
||||
"GAMMA_SBAS_DEFAULT_REFERENCE_WINDOW",
|
||||
max(1, int(self.GAMMA_SBAS_DEFAULT_REFERENCE_WINDOW or 16)),
|
||||
)
|
||||
object.__setattr__(
|
||||
self,
|
||||
"GAMMA_SBAS_STEP_TIMEOUT_SECONDS",
|
||||
max(60, int(self.GAMMA_SBAS_STEP_TIMEOUT_SECONDS or 43200)),
|
||||
)
|
||||
object.__setattr__(
|
||||
self,
|
||||
"GAMMA_SBAS_WORKFLOW_TIMEOUT_SECONDS",
|
||||
max(self.GAMMA_SBAS_STEP_TIMEOUT_SECONDS, int(self.GAMMA_SBAS_WORKFLOW_TIMEOUT_SECONDS or 172800)),
|
||||
)
|
||||
if self.TIMESERIES_ENABLED:
|
||||
if not self.TIMESERIES_WSL_DISTRO:
|
||||
object.__setattr__(self, "TIMESERIES_WSL_DISTRO", self.WSL_DISTRO or self.ISCE2_WSL_DISTRO)
|
||||
@@ -755,6 +847,10 @@ class Settings(BaseSettings):
|
||||
os.makedirs(settings.PYINT_WORK_ROOT, exist_ok=True)
|
||||
os.makedirs(settings.PYINT_OUTPUT_ROOT, exist_ok=True)
|
||||
os.makedirs(settings.PYINT_DEM_ROOT, exist_ok=True)
|
||||
if settings.GAMMA_SBAS_ENABLED:
|
||||
os.makedirs(settings.GAMMA_SBAS_WORK_ROOT, exist_ok=True)
|
||||
os.makedirs(settings.GAMMA_SBAS_PRODUCT_ROOT, exist_ok=True)
|
||||
os.makedirs(settings.GAMMA_SBAS_SCRIPT_TEMPLATE_ROOT, exist_ok=True)
|
||||
if settings.TIMESERIES_ENABLED and settings.TIMESERIES_WORK_ROOT:
|
||||
os.makedirs(settings.TIMESERIES_WORK_ROOT, exist_ok=True)
|
||||
|
||||
@@ -1033,6 +1129,42 @@ def validate_runtime_config() -> dict[str, Any]:
|
||||
expect_file=True,
|
||||
)
|
||||
|
||||
if settings.GAMMA_SBAS_ENABLED:
|
||||
if not settings.GAMMA_SBAS_RUNTIME_ID:
|
||||
errors.append("GAMMA_SBAS_ENABLED=true but GAMMA_SBAS_RUNTIME_ID is not configured.")
|
||||
if not settings.GAMMA_SBAS_WSL_DISTRO:
|
||||
errors.append("GAMMA_SBAS_ENABLED=true but GAMMA_SBAS_WSL_DISTRO is not configured.")
|
||||
if not settings.GAMMA_SBAS_PYTHON:
|
||||
errors.append("GAMMA_SBAS_ENABLED=true but GAMMA_SBAS_PYTHON is not configured.")
|
||||
_check_path(
|
||||
label="GAMMA_SBAS_ENV_SCRIPT",
|
||||
value=settings.GAMMA_SBAS_ENV_SCRIPT,
|
||||
errors=errors,
|
||||
warnings=warnings,
|
||||
expect_file=True,
|
||||
)
|
||||
_check_path(
|
||||
label="GAMMA_SBAS_WORK_ROOT",
|
||||
value=settings.GAMMA_SBAS_WORK_ROOT,
|
||||
errors=errors,
|
||||
warnings=warnings,
|
||||
expect_file=False,
|
||||
)
|
||||
_check_path(
|
||||
label="GAMMA_SBAS_PRODUCT_ROOT",
|
||||
value=settings.GAMMA_SBAS_PRODUCT_ROOT,
|
||||
errors=errors,
|
||||
warnings=warnings,
|
||||
expect_file=False,
|
||||
)
|
||||
_check_path(
|
||||
label="GAMMA_SBAS_SCRIPT_TEMPLATE_ROOT",
|
||||
value=settings.GAMMA_SBAS_SCRIPT_TEMPLATE_ROOT,
|
||||
errors=errors,
|
||||
warnings=warnings,
|
||||
expect_file=False,
|
||||
)
|
||||
|
||||
if settings.ISCE2_ENABLED or settings.PYINT_ENABLED:
|
||||
info.append(
|
||||
"WSL shared runtime: "
|
||||
|
||||
@@ -190,6 +190,16 @@ async def lifespan(app: FastAPI):
|
||||
)
|
||||
if pairing_bootstrap.get("error"):
|
||||
print(f">>> [Pairing] Startup bootstrap failed: {pairing_bootstrap['error']}")
|
||||
print(
|
||||
">>> [Gamma SBAS] enabled={0} runtime={1} distro={2} python={3} work_root={4} product_root={5}".format(
|
||||
"YES" if settings.GAMMA_SBAS_ENABLED else "NO",
|
||||
settings.GAMMA_SBAS_RUNTIME_ID or "?",
|
||||
settings.GAMMA_SBAS_WSL_DISTRO or "?",
|
||||
settings.GAMMA_SBAS_PYTHON or "?",
|
||||
settings.GAMMA_SBAS_WORK_ROOT or "?",
|
||||
settings.GAMMA_SBAS_PRODUCT_ROOT or "?",
|
||||
)
|
||||
)
|
||||
|
||||
# 当前项目默认 Manual-only 扫描模式,保留调度器关闭状态。
|
||||
# scheduler_manager.start()
|
||||
|
||||
@@ -88,6 +88,59 @@ class SbasCoregistrationJobRequest(BaseModel):
|
||||
timeout_seconds: int = Field(default=43200, ge=60, le=172800)
|
||||
|
||||
|
||||
class SbasRdcDemRequest(BaseModel):
|
||||
execute: bool = False
|
||||
rlks: int = Field(default=8, ge=1, le=64)
|
||||
|
||||
|
||||
class SbasRdcDemJobRequest(BaseModel):
|
||||
rlks: int = Field(default=8, ge=1, le=64)
|
||||
timeout_seconds: int = Field(default=43200, ge=60, le=172800)
|
||||
|
||||
|
||||
class SbasInterferogramsRequest(BaseModel):
|
||||
execute: bool = False
|
||||
rlks: int = Field(default=8, ge=1, le=64)
|
||||
azlks: int = Field(default=8, ge=1, le=64)
|
||||
unwrap_threshold: float = Field(default=0.20, ge=0.01, le=0.95)
|
||||
|
||||
|
||||
class SbasInterferogramsJobRequest(BaseModel):
|
||||
rlks: int = Field(default=8, ge=1, le=64)
|
||||
azlks: int = Field(default=8, ge=1, le=64)
|
||||
unwrap_threshold: float = Field(default=0.20, ge=0.01, le=0.95)
|
||||
timeout_seconds: int = Field(default=43200, ge=60, le=172800)
|
||||
|
||||
|
||||
class SbasIptaTimeseriesRequest(BaseModel):
|
||||
execute: bool = False
|
||||
rlks: int = Field(default=8, ge=1, le=64)
|
||||
reference_window: int = Field(default=16, ge=1, le=256)
|
||||
mb_mode: int = Field(default=0, ge=0, le=2)
|
||||
|
||||
|
||||
class SbasIptaTimeseriesJobRequest(BaseModel):
|
||||
rlks: int = Field(default=8, ge=1, le=64)
|
||||
reference_window: int = Field(default=16, ge=1, le=256)
|
||||
mb_mode: int = Field(default=0, ge=0, le=2)
|
||||
timeout_seconds: int = Field(default=43200, ge=60, le=172800)
|
||||
|
||||
|
||||
class SbasWorkflowPrepareRequest(BaseModel):
|
||||
force: bool = False
|
||||
rlks: int = Field(default=8, ge=1, le=64)
|
||||
azlks: int = Field(default=8, ge=1, le=64)
|
||||
reference_window: int = Field(default=16, ge=1, le=256)
|
||||
mb_mode: int = Field(default=0, ge=0, le=2)
|
||||
|
||||
|
||||
class SbasWorkflowJobRequest(SbasWorkflowPrepareRequest):
|
||||
from_step: str | None = Field(default=None, max_length=64)
|
||||
to_step: str | None = Field(default=None, max_length=64)
|
||||
only_steps: list[str] | None = None
|
||||
timeout_seconds: int = Field(default=172800, ge=60, le=604800)
|
||||
|
||||
|
||||
@router.get("/capabilities")
|
||||
async def get_sbas_insar_capabilities():
|
||||
return sbas_insar_production_service.get_capabilities()
|
||||
@@ -168,6 +221,76 @@ async def get_sbas_insar_run(run_id: str):
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
|
||||
|
||||
@router.post("/runs/{run_id}/workflow", status_code=202)
|
||||
async def prepare_sbas_insar_workflow(run_id: str, request: SbasWorkflowPrepareRequest):
|
||||
try:
|
||||
return await asyncio.to_thread(
|
||||
sbas_insar_production_service.prepare_workflow,
|
||||
run_id,
|
||||
force=request.force,
|
||||
rlks=request.rlks,
|
||||
azlks=request.azlks,
|
||||
reference_window=request.reference_window,
|
||||
mb_mode=request.mb_mode,
|
||||
)
|
||||
except FileNotFoundError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
|
||||
|
||||
@router.post("/runs/{run_id}/workflow/jobs", status_code=202)
|
||||
async def submit_sbas_insar_workflow_job(run_id: str, request: SbasWorkflowJobRequest):
|
||||
try:
|
||||
await asyncio.to_thread(
|
||||
sbas_insar_production_service.prepare_workflow,
|
||||
run_id,
|
||||
force=request.force,
|
||||
rlks=request.rlks,
|
||||
azlks=request.azlks,
|
||||
reference_window=request.reference_window,
|
||||
mb_mode=request.mb_mode,
|
||||
)
|
||||
from ..services.job_handlers import JOB_TYPE_SBAS_GAMMA_WORKFLOW
|
||||
|
||||
payload = {
|
||||
"run_id": run_id,
|
||||
"force": request.force,
|
||||
"rlks": request.rlks,
|
||||
"azlks": request.azlks,
|
||||
"reference_window": request.reference_window,
|
||||
"mb_mode": request.mb_mode,
|
||||
"from_step": request.from_step,
|
||||
"to_step": request.to_step,
|
||||
"only_steps": request.only_steps or [],
|
||||
"timeout_seconds": request.timeout_seconds,
|
||||
}
|
||||
task_id = await task_service.create_task(
|
||||
task_type=JOB_TYPE_SBAS_GAMMA_WORKFLOW,
|
||||
task_name=f"Gamma SBAS Workflow {run_id}",
|
||||
params=payload,
|
||||
)
|
||||
job_id = await job_queue_service.create_job(
|
||||
job_type=JOB_TYPE_SBAS_GAMMA_WORKFLOW,
|
||||
payload=payload,
|
||||
task_id=task_id,
|
||||
max_attempts=1,
|
||||
)
|
||||
return {
|
||||
"message": "Gamma SBAS workflow job queued.",
|
||||
"run_id": run_id,
|
||||
"task_id": task_id,
|
||||
"job_id": job_id,
|
||||
"job_type": JOB_TYPE_SBAS_GAMMA_WORKFLOW,
|
||||
}
|
||||
except FileNotFoundError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except ValueError as exc:
|
||||
message = str(exc)
|
||||
status_code = 409 if "already running" in message.lower() or "conflict" in message.lower() else 400
|
||||
raise HTTPException(status_code=status_code, detail=message) from exc
|
||||
|
||||
|
||||
@router.post("/runs/{run_id}/baseline-audit", status_code=202)
|
||||
async def run_sbas_insar_baseline_audit(run_id: str, request: SbasBaselineAuditRequest):
|
||||
try:
|
||||
@@ -274,6 +397,219 @@ async def submit_sbas_insar_coregistration_job(run_id: str, request: SbasCoregis
|
||||
raise HTTPException(status_code=status_code, detail=message) from exc
|
||||
|
||||
|
||||
@router.post("/runs/{run_id}/rdc-dem", status_code=202)
|
||||
async def prepare_sbas_insar_rdc_dem(run_id: str, request: SbasRdcDemRequest):
|
||||
try:
|
||||
return await asyncio.to_thread(
|
||||
sbas_insar_production_service.prepare_rdc_dem,
|
||||
run_id,
|
||||
execute=request.execute,
|
||||
rlks=request.rlks,
|
||||
)
|
||||
except FileNotFoundError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
|
||||
|
||||
@router.post("/runs/{run_id}/rdc-dem/jobs", status_code=202)
|
||||
async def submit_sbas_insar_rdc_dem_job(run_id: str, request: SbasRdcDemJobRequest):
|
||||
try:
|
||||
run_detail = await asyncio.to_thread(sbas_insar_production_service.get_run_detail, run_id)
|
||||
status = str((run_detail.get("run") or {}).get("status") or "").strip()
|
||||
if status in {"COREGISTRATION_READY", "RDC_DEM_FAILED"}:
|
||||
await asyncio.to_thread(
|
||||
sbas_insar_production_service.prepare_rdc_dem,
|
||||
run_id,
|
||||
execute=False,
|
||||
rlks=request.rlks,
|
||||
)
|
||||
run_detail = await asyncio.to_thread(sbas_insar_production_service.get_run_detail, run_id)
|
||||
status = str((run_detail.get("run") or {}).get("status") or "").strip()
|
||||
if status not in {"RDC_DEM_SCRIPT_READY", "RDC_DEM_RUNNING"}:
|
||||
raise ValueError(f"run status does not allow RDC DEM job submission: {status}")
|
||||
if status == "RDC_DEM_RUNNING":
|
||||
raise ValueError("RDC DEM is already running for this run")
|
||||
|
||||
from ..services.job_handlers import JOB_TYPE_SBAS_RDC_DEM
|
||||
|
||||
payload = {
|
||||
"run_id": run_id,
|
||||
"rlks": request.rlks,
|
||||
"timeout_seconds": request.timeout_seconds,
|
||||
}
|
||||
task_id = await task_service.create_task(
|
||||
task_type=JOB_TYPE_SBAS_RDC_DEM,
|
||||
task_name=f"SBAS-InSAR RDC DEM {run_id}",
|
||||
params=payload,
|
||||
)
|
||||
job_id = await job_queue_service.create_job(
|
||||
job_type=JOB_TYPE_SBAS_RDC_DEM,
|
||||
payload=payload,
|
||||
task_id=task_id,
|
||||
max_attempts=1,
|
||||
)
|
||||
return {
|
||||
"message": "SBAS-InSAR RDC DEM job queued.",
|
||||
"run_id": run_id,
|
||||
"task_id": task_id,
|
||||
"job_id": job_id,
|
||||
"job_type": JOB_TYPE_SBAS_RDC_DEM,
|
||||
}
|
||||
except FileNotFoundError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except ValueError as exc:
|
||||
message = str(exc)
|
||||
status_code = 409 if "already running" in message.lower() or "conflict" in message.lower() else 400
|
||||
raise HTTPException(status_code=status_code, detail=message) from exc
|
||||
|
||||
|
||||
@router.post("/runs/{run_id}/interferograms", status_code=202)
|
||||
async def prepare_sbas_insar_interferograms(run_id: str, request: SbasInterferogramsRequest):
|
||||
try:
|
||||
return await asyncio.to_thread(
|
||||
sbas_insar_production_service.prepare_interferograms,
|
||||
run_id,
|
||||
execute=request.execute,
|
||||
rlks=request.rlks,
|
||||
azlks=request.azlks,
|
||||
unwrap_threshold=request.unwrap_threshold,
|
||||
)
|
||||
except FileNotFoundError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
|
||||
|
||||
@router.post("/runs/{run_id}/interferograms/jobs", status_code=202)
|
||||
async def submit_sbas_insar_interferograms_job(run_id: str, request: SbasInterferogramsJobRequest):
|
||||
try:
|
||||
run_detail = await asyncio.to_thread(sbas_insar_production_service.get_run_detail, run_id)
|
||||
status = str((run_detail.get("run") or {}).get("status") or "").strip()
|
||||
if status in {"RDC_DEM_READY", "INTERFEROGRAMS_FAILED"}:
|
||||
await asyncio.to_thread(
|
||||
sbas_insar_production_service.prepare_interferograms,
|
||||
run_id,
|
||||
execute=False,
|
||||
rlks=request.rlks,
|
||||
azlks=request.azlks,
|
||||
unwrap_threshold=request.unwrap_threshold,
|
||||
)
|
||||
run_detail = await asyncio.to_thread(sbas_insar_production_service.get_run_detail, run_id)
|
||||
status = str((run_detail.get("run") or {}).get("status") or "").strip()
|
||||
if status not in {"INTERFEROGRAMS_SCRIPT_READY", "INTERFEROGRAMS_RUNNING"}:
|
||||
raise ValueError(f"run status does not allow interferogram job submission: {status}")
|
||||
if status == "INTERFEROGRAMS_RUNNING":
|
||||
raise ValueError("interferograms are already running for this run")
|
||||
|
||||
from ..services.job_handlers import JOB_TYPE_SBAS_INTERFEROGRAMS
|
||||
|
||||
payload = {
|
||||
"run_id": run_id,
|
||||
"rlks": request.rlks,
|
||||
"azlks": request.azlks,
|
||||
"unwrap_threshold": request.unwrap_threshold,
|
||||
"timeout_seconds": request.timeout_seconds,
|
||||
}
|
||||
task_id = await task_service.create_task(
|
||||
task_type=JOB_TYPE_SBAS_INTERFEROGRAMS,
|
||||
task_name=f"SBAS-InSAR Interferograms {run_id}",
|
||||
params=payload,
|
||||
)
|
||||
job_id = await job_queue_service.create_job(
|
||||
job_type=JOB_TYPE_SBAS_INTERFEROGRAMS,
|
||||
payload=payload,
|
||||
task_id=task_id,
|
||||
max_attempts=1,
|
||||
)
|
||||
return {
|
||||
"message": "SBAS-InSAR interferogram job queued.",
|
||||
"run_id": run_id,
|
||||
"task_id": task_id,
|
||||
"job_id": job_id,
|
||||
"job_type": JOB_TYPE_SBAS_INTERFEROGRAMS,
|
||||
}
|
||||
except FileNotFoundError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except ValueError as exc:
|
||||
message = str(exc)
|
||||
status_code = 409 if "already running" in message.lower() or "conflict" in message.lower() else 400
|
||||
raise HTTPException(status_code=status_code, detail=message) from exc
|
||||
|
||||
|
||||
@router.post("/runs/{run_id}/ipta-timeseries", status_code=202)
|
||||
async def prepare_sbas_insar_ipta_timeseries(run_id: str, request: SbasIptaTimeseriesRequest):
|
||||
try:
|
||||
return await asyncio.to_thread(
|
||||
sbas_insar_production_service.prepare_ipta_timeseries,
|
||||
run_id,
|
||||
execute=request.execute,
|
||||
rlks=request.rlks,
|
||||
reference_window=request.reference_window,
|
||||
mb_mode=request.mb_mode,
|
||||
)
|
||||
except FileNotFoundError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
|
||||
|
||||
@router.post("/runs/{run_id}/ipta-timeseries/jobs", status_code=202)
|
||||
async def submit_sbas_insar_ipta_timeseries_job(run_id: str, request: SbasIptaTimeseriesJobRequest):
|
||||
try:
|
||||
run_detail = await asyncio.to_thread(sbas_insar_production_service.get_run_detail, run_id)
|
||||
status = str((run_detail.get("run") or {}).get("status") or "").strip()
|
||||
if status in {"INTERFEROGRAMS_READY", "IPTA_TIMESERIES_FAILED"}:
|
||||
await asyncio.to_thread(
|
||||
sbas_insar_production_service.prepare_ipta_timeseries,
|
||||
run_id,
|
||||
execute=False,
|
||||
rlks=request.rlks,
|
||||
reference_window=request.reference_window,
|
||||
mb_mode=request.mb_mode,
|
||||
)
|
||||
run_detail = await asyncio.to_thread(sbas_insar_production_service.get_run_detail, run_id)
|
||||
status = str((run_detail.get("run") or {}).get("status") or "").strip()
|
||||
if status not in {"IPTA_TIMESERIES_SCRIPT_READY", "IPTA_TIMESERIES_RUNNING"}:
|
||||
raise ValueError(f"run status does not allow IPTA time-series job submission: {status}")
|
||||
if status == "IPTA_TIMESERIES_RUNNING":
|
||||
raise ValueError("IPTA time-series is already running for this run")
|
||||
|
||||
from ..services.job_handlers import JOB_TYPE_SBAS_IPTA_TIMESERIES
|
||||
|
||||
payload = {
|
||||
"run_id": run_id,
|
||||
"rlks": request.rlks,
|
||||
"reference_window": request.reference_window,
|
||||
"mb_mode": request.mb_mode,
|
||||
"timeout_seconds": request.timeout_seconds,
|
||||
}
|
||||
task_id = await task_service.create_task(
|
||||
task_type=JOB_TYPE_SBAS_IPTA_TIMESERIES,
|
||||
task_name=f"SBAS-InSAR IPTA Timeseries {run_id}",
|
||||
params=payload,
|
||||
)
|
||||
job_id = await job_queue_service.create_job(
|
||||
job_type=JOB_TYPE_SBAS_IPTA_TIMESERIES,
|
||||
payload=payload,
|
||||
task_id=task_id,
|
||||
max_attempts=1,
|
||||
)
|
||||
return {
|
||||
"message": "SBAS-InSAR IPTA time-series job queued.",
|
||||
"run_id": run_id,
|
||||
"task_id": task_id,
|
||||
"job_id": job_id,
|
||||
"job_type": JOB_TYPE_SBAS_IPTA_TIMESERIES,
|
||||
}
|
||||
except FileNotFoundError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except ValueError as exc:
|
||||
message = str(exc)
|
||||
status_code = 409 if "already running" in message.lower() or "conflict" in message.lower() else 400
|
||||
raise HTTPException(status_code=status_code, detail=message) from exc
|
||||
|
||||
|
||||
@router.get("/runs/{run_id}/artifacts/{relative_path:path}")
|
||||
async def get_sbas_insar_run_artifact(run_id: str, relative_path: str):
|
||||
try:
|
||||
|
||||
@@ -1272,6 +1272,7 @@ async def _check_wsl_runtime() -> Dict[str, Any]:
|
||||
required_by_engine = {
|
||||
"isce2": bool(settings.ISCE2_ENABLED or settings.TIMESERIES_ENABLED),
|
||||
"pyint": bool(settings.PYINT_ENABLED),
|
||||
"gamma": bool(settings.GAMMA_SBAS_ENABLED),
|
||||
}
|
||||
for runtime in wsl_runtime_registry.runtimes.values():
|
||||
required = bool(required_by_engine.get(runtime.engine_code, False))
|
||||
@@ -1285,6 +1286,9 @@ async def _check_wsl_runtime() -> Dict[str, Any]:
|
||||
distro_matches_shared = str(runtime.distro or "").strip() == str(
|
||||
wsl_runtime_registry.shared_distro or ""
|
||||
).strip()
|
||||
if runtime.engine_code == "gamma":
|
||||
python_matches_shared = bool(str(runtime.python_path or "").strip())
|
||||
distro_matches_shared = bool(str(runtime.distro or "").strip())
|
||||
runtime_ok = runner_exists and python_matches_shared and distro_matches_shared
|
||||
if env_profile_exists is False and required:
|
||||
runtime_ok = False
|
||||
|
||||
@@ -92,6 +92,10 @@ JOB_TYPE_REBUILD_DINSAR_CATALOG = "REBUILD_DINSAR_CATALOG"
|
||||
JOB_TYPE_REBUILD_PSINSAR_CATALOG = "REBUILD_PSINSAR_CATALOG"
|
||||
JOB_TYPE_SCAN_ASSET_INVENTORY = "SCAN_ASSET_INVENTORY"
|
||||
JOB_TYPE_SBAS_COREGISTRATION = "SBAS_COREGISTRATION"
|
||||
JOB_TYPE_SBAS_RDC_DEM = "SBAS_RDC_DEM"
|
||||
JOB_TYPE_SBAS_INTERFEROGRAMS = "SBAS_INTERFEROGRAMS"
|
||||
JOB_TYPE_SBAS_IPTA_TIMESERIES = "SBAS_IPTA_TIMESERIES"
|
||||
JOB_TYPE_SBAS_GAMMA_WORKFLOW = "SBAS_GAMMA_WORKFLOW"
|
||||
|
||||
COPY_ALLOWED_STATUSES = {"PENDING", "IN_PROGRESS", "COMPLETED", "FAILED"}
|
||||
|
||||
@@ -4263,6 +4267,346 @@ async def _handle_sbas_coregistration(job: SystemJobORM) -> None:
|
||||
)
|
||||
|
||||
|
||||
async def _handle_sbas_rdc_dem(job: SystemJobORM) -> None:
|
||||
if not job.task_id:
|
||||
raise ValueError("SBAS_RDC_DEM requires task_id for progress tracking.")
|
||||
payload = job.payload or {}
|
||||
run_id = str(payload.get("run_id") or "").strip()
|
||||
if not run_id:
|
||||
raise ValueError("SBAS_RDC_DEM requires run_id payload.")
|
||||
|
||||
rlks = _normalize_positive_int(payload.get("rlks")) or 8
|
||||
timeout_seconds = _normalize_positive_int(payload.get("timeout_seconds")) or 43200
|
||||
|
||||
await task_service.start_task(job.task_id, message="正在执行 SBAS-InSAR Gamma RDC DEM...")
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
progress=5,
|
||||
message=f"准备运行 Gamma gc_map1/gc_map_fine: run_id={run_id}",
|
||||
)
|
||||
await task_service.add_log(
|
||||
job.task_id,
|
||||
"INFO",
|
||||
f"SBAS RDC DEM queued: run_id={run_id}, rlks={rlks}, timeout={timeout_seconds}s",
|
||||
)
|
||||
|
||||
from .sbas_insar_production_service import sbas_insar_production_service
|
||||
|
||||
async def _task_keepalive() -> None:
|
||||
progress = 12
|
||||
while True:
|
||||
await asyncio.sleep(60)
|
||||
progress = min(88, progress + 2)
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
progress=progress,
|
||||
message=f"Gamma RDC DEM 仍在运行: run_id={run_id}",
|
||||
)
|
||||
|
||||
runner_task = asyncio.create_task(
|
||||
asyncio.to_thread(
|
||||
sbas_insar_production_service.execute_rdc_dem,
|
||||
run_id,
|
||||
rlks=rlks,
|
||||
timeout_seconds=timeout_seconds,
|
||||
)
|
||||
)
|
||||
keepalive_task = asyncio.create_task(_task_keepalive())
|
||||
try:
|
||||
result = await runner_task
|
||||
finally:
|
||||
keepalive_task.cancel()
|
||||
try:
|
||||
await keepalive_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
manifest = result.get("manifest") or {}
|
||||
run = result.get("run") or {}
|
||||
summary = (manifest.get("rdc_dem") or {}).get("summary") or {}
|
||||
status = str(run.get("status") or manifest.get("status") or "").strip()
|
||||
if status != "RDC_DEM_READY":
|
||||
raise RuntimeError(
|
||||
"SBAS RDC DEM failed: "
|
||||
f"status={status or 'UNKNOWN'}, "
|
||||
f"missing_outputs={summary.get('missing_outputs') or []}"
|
||||
)
|
||||
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
status="COMPLETED",
|
||||
progress=100,
|
||||
message=(
|
||||
"SBAS-InSAR RDC DEM 完成: "
|
||||
f"rdc_dem={((summary.get('outputs') or {}).get('rdc_dem') or {}).get('path') or '-'}"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def _handle_sbas_interferograms(job: SystemJobORM) -> None:
|
||||
if not job.task_id:
|
||||
raise ValueError("SBAS_INTERFEROGRAMS requires task_id for progress tracking.")
|
||||
payload = job.payload or {}
|
||||
run_id = str(payload.get("run_id") or "").strip()
|
||||
if not run_id:
|
||||
raise ValueError("SBAS_INTERFEROGRAMS requires run_id payload.")
|
||||
|
||||
rlks = _normalize_positive_int(payload.get("rlks")) or 8
|
||||
azlks = _normalize_positive_int(payload.get("azlks")) or 8
|
||||
timeout_seconds = _normalize_positive_int(payload.get("timeout_seconds")) or 43200
|
||||
try:
|
||||
unwrap_threshold = float(payload.get("unwrap_threshold") or 0.20)
|
||||
except (TypeError, ValueError):
|
||||
unwrap_threshold = 0.20
|
||||
|
||||
await task_service.start_task(job.task_id, message="正在执行 SBAS-InSAR Gamma 差分干涉图...")
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
progress=5,
|
||||
message=f"准备运行 Gamma phase_sim_orb/SLC_diff_intf/mcf: run_id={run_id}",
|
||||
)
|
||||
await task_service.add_log(
|
||||
job.task_id,
|
||||
"INFO",
|
||||
(
|
||||
f"SBAS interferograms queued: run_id={run_id}, rlks={rlks}, azlks={azlks}, "
|
||||
f"unwrap_threshold={unwrap_threshold}, timeout={timeout_seconds}s"
|
||||
),
|
||||
)
|
||||
|
||||
from .sbas_insar_production_service import sbas_insar_production_service
|
||||
|
||||
async def _task_keepalive() -> None:
|
||||
progress = 12
|
||||
while True:
|
||||
await asyncio.sleep(60)
|
||||
progress = min(88, progress + 2)
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
progress=progress,
|
||||
message=f"Gamma 差分干涉图仍在运行: run_id={run_id}",
|
||||
)
|
||||
|
||||
runner_task = asyncio.create_task(
|
||||
asyncio.to_thread(
|
||||
sbas_insar_production_service.execute_interferograms,
|
||||
run_id,
|
||||
rlks=rlks,
|
||||
azlks=azlks,
|
||||
unwrap_threshold=unwrap_threshold,
|
||||
timeout_seconds=timeout_seconds,
|
||||
)
|
||||
)
|
||||
keepalive_task = asyncio.create_task(_task_keepalive())
|
||||
try:
|
||||
result = await runner_task
|
||||
finally:
|
||||
keepalive_task.cancel()
|
||||
try:
|
||||
await keepalive_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
manifest = result.get("manifest") or {}
|
||||
run = result.get("run") or {}
|
||||
summary = (manifest.get("interferograms") or {}).get("summary") or {}
|
||||
status = str(run.get("status") or manifest.get("status") or "").strip()
|
||||
if status != "INTERFEROGRAMS_READY":
|
||||
raise RuntimeError(
|
||||
"SBAS interferograms failed: "
|
||||
f"status={status or 'UNKNOWN'}, "
|
||||
f"missing_pairs={summary.get('missing_pairs') or []}, "
|
||||
f"missing_tabs={summary.get('missing_tabs') or []}"
|
||||
)
|
||||
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
status="COMPLETED",
|
||||
progress=100,
|
||||
message=(
|
||||
"SBAS-InSAR 差分干涉图完成: "
|
||||
f"{summary.get('ready_pair_count', 0)}/{summary.get('pair_count', 0)} pairs ready"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def _handle_sbas_ipta_timeseries(job: SystemJobORM) -> None:
|
||||
if not job.task_id:
|
||||
raise ValueError("SBAS_IPTA_TIMESERIES requires task_id for progress tracking.")
|
||||
payload = job.payload or {}
|
||||
run_id = str(payload.get("run_id") or "").strip()
|
||||
if not run_id:
|
||||
raise ValueError("SBAS_IPTA_TIMESERIES requires run_id payload.")
|
||||
|
||||
rlks = _normalize_positive_int(payload.get("rlks")) or 8
|
||||
reference_window = _normalize_positive_int(payload.get("reference_window")) or 16
|
||||
try:
|
||||
mb_mode = int(payload.get("mb_mode") or 0)
|
||||
except (TypeError, ValueError):
|
||||
mb_mode = 0
|
||||
if mb_mode not in {0, 1, 2}:
|
||||
mb_mode = 0
|
||||
timeout_seconds = _normalize_positive_int(payload.get("timeout_seconds")) or 43200
|
||||
|
||||
await task_service.start_task(job.task_id, message="Running SBAS-InSAR Gamma IPTA time-series inversion...")
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
progress=5,
|
||||
message=f"Preparing Gamma mb/ts_rate: run_id={run_id}",
|
||||
)
|
||||
await task_service.add_log(
|
||||
job.task_id,
|
||||
"INFO",
|
||||
(
|
||||
f"SBAS IPTA time-series queued: run_id={run_id}, rlks={rlks}, "
|
||||
f"reference_window={reference_window}, mb_mode={mb_mode}, "
|
||||
f"timeout={timeout_seconds}s"
|
||||
),
|
||||
)
|
||||
|
||||
from .sbas_insar_production_service import sbas_insar_production_service
|
||||
|
||||
async def _task_keepalive() -> None:
|
||||
progress = 12
|
||||
while True:
|
||||
await asyncio.sleep(60)
|
||||
progress = min(88, progress + 2)
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
progress=progress,
|
||||
message=f"Gamma IPTA mb/ts_rate still running: run_id={run_id}",
|
||||
)
|
||||
|
||||
runner_task = asyncio.create_task(
|
||||
asyncio.to_thread(
|
||||
sbas_insar_production_service.execute_ipta_timeseries,
|
||||
run_id,
|
||||
rlks=rlks,
|
||||
reference_window=reference_window,
|
||||
mb_mode=mb_mode,
|
||||
timeout_seconds=timeout_seconds,
|
||||
)
|
||||
)
|
||||
keepalive_task = asyncio.create_task(_task_keepalive())
|
||||
try:
|
||||
result = await runner_task
|
||||
finally:
|
||||
keepalive_task.cancel()
|
||||
try:
|
||||
await keepalive_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
manifest = result.get("manifest") or {}
|
||||
run = result.get("run") or {}
|
||||
summary = (manifest.get("ipta_timeseries") or {}).get("summary") or {}
|
||||
status = str(run.get("status") or manifest.get("status") or "").strip()
|
||||
if status != "IPTA_TIMESERIES_READY":
|
||||
raise RuntimeError(
|
||||
"SBAS IPTA time-series failed: "
|
||||
f"status={status or 'UNKNOWN'}, "
|
||||
f"missing_outputs={summary.get('missing_outputs') or []}"
|
||||
)
|
||||
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
status="COMPLETED",
|
||||
progress=100,
|
||||
message=(
|
||||
"SBAS-InSAR IPTA time-series complete: "
|
||||
f"ts_rate={((summary.get('outputs') or {}).get('ts_rate') or {}).get('path') or '-'}"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def _handle_sbas_gamma_workflow(job: SystemJobORM) -> None:
|
||||
if not job.task_id:
|
||||
raise ValueError("SBAS_GAMMA_WORKFLOW requires task_id for progress tracking.")
|
||||
payload = job.payload or {}
|
||||
run_id = str(payload.get("run_id") or "").strip()
|
||||
if not run_id:
|
||||
raise ValueError("SBAS_GAMMA_WORKFLOW requires run_id payload.")
|
||||
|
||||
from_step = str(payload.get("from_step") or "").strip() or None
|
||||
to_step = str(payload.get("to_step") or "").strip() or None
|
||||
only_steps_raw = payload.get("only_steps") or []
|
||||
only_steps = [str(item).strip() for item in only_steps_raw if str(item).strip()] if isinstance(only_steps_raw, list) else []
|
||||
force = bool(payload.get("force", False))
|
||||
timeout_seconds = _normalize_positive_int(payload.get("timeout_seconds")) or int(settings.GAMMA_SBAS_WORKFLOW_TIMEOUT_SECONDS)
|
||||
|
||||
await task_service.start_task(job.task_id, message="Running Gamma SBAS expert workflow...")
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
progress=5,
|
||||
message=f"Preparing Gamma SBAS manifest runner: run_id={run_id}",
|
||||
)
|
||||
await task_service.add_log(
|
||||
job.task_id,
|
||||
"INFO",
|
||||
(
|
||||
f"SBAS Gamma workflow queued: run_id={run_id}, from={from_step or '-'}, "
|
||||
f"to={to_step or '-'}, only={only_steps or '-'}, force={force}, timeout={timeout_seconds}s"
|
||||
),
|
||||
)
|
||||
|
||||
from .sbas_insar_production_service import sbas_insar_production_service
|
||||
|
||||
async def _task_keepalive() -> None:
|
||||
progress = 10
|
||||
while True:
|
||||
await asyncio.sleep(60)
|
||||
progress = min(92, progress + 2)
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
progress=progress,
|
||||
message="Gamma SBAS workflow is still running...",
|
||||
)
|
||||
|
||||
runner_task = asyncio.create_task(
|
||||
asyncio.to_thread(
|
||||
sbas_insar_production_service.execute_workflow,
|
||||
run_id,
|
||||
from_step=from_step,
|
||||
to_step=to_step,
|
||||
only_steps=only_steps,
|
||||
force=force,
|
||||
timeout_seconds=timeout_seconds,
|
||||
)
|
||||
)
|
||||
keepalive_task = asyncio.create_task(_task_keepalive())
|
||||
try:
|
||||
result = await runner_task
|
||||
finally:
|
||||
keepalive_task.cancel()
|
||||
try:
|
||||
await keepalive_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
run = result.get("run") or {}
|
||||
manifest = result.get("manifest") or {}
|
||||
workflow = manifest.get("workflow") or {}
|
||||
summary = workflow.get("summary") or {}
|
||||
status = str(run.get("status") or manifest.get("status") or "").strip()
|
||||
if status not in {"WORKFLOW_COMPLETED", "WORKFLOW_PARTIAL"}:
|
||||
raise RuntimeError(
|
||||
"SBAS Gamma workflow failed: "
|
||||
f"status={status or 'UNKNOWN'}, failed_steps={summary.get('failed_count') or 0}"
|
||||
)
|
||||
|
||||
await task_service.update_task(
|
||||
job.task_id,
|
||||
status="COMPLETED",
|
||||
progress=100,
|
||||
message=(
|
||||
f"Gamma SBAS expert workflow {status.lower()}: "
|
||||
f"completed={summary.get('completed_count', 0)}, "
|
||||
f"skipped={summary.get('skipped_count', 0)}, "
|
||||
f"planned={summary.get('planned_count', 0)}"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
_HANDLERS = {
|
||||
JOB_TYPE_SCAN_DATA: _handle_scan_data,
|
||||
JOB_TYPE_SCAN_ASSET_INVENTORY: _handle_scan_asset_inventory,
|
||||
@@ -4301,6 +4645,10 @@ _HANDLERS = {
|
||||
JOB_TYPE_GF3_UNPACK: _handle_gf3_unpack,
|
||||
JOB_TYPE_GF3_BATCH_PROCESS: _handle_gf3_batch_process,
|
||||
JOB_TYPE_SBAS_COREGISTRATION: _handle_sbas_coregistration,
|
||||
JOB_TYPE_SBAS_RDC_DEM: _handle_sbas_rdc_dem,
|
||||
JOB_TYPE_SBAS_INTERFEROGRAMS: _handle_sbas_interferograms,
|
||||
JOB_TYPE_SBAS_IPTA_TIMESERIES: _handle_sbas_ipta_timeseries,
|
||||
JOB_TYPE_SBAS_GAMMA_WORKFLOW: _handle_sbas_gamma_workflow,
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -112,6 +112,7 @@ def build_wsl_runtime_registry() -> WslRuntimeRegistry:
|
||||
|
||||
isce2_runner_windows = _project_file_windows("deploy", "wsl", "runners", "isce2_runner.py")
|
||||
gamma_runner_windows = _project_file_windows("deploy", "wsl", "runners", "gamma_pyint_runner.py")
|
||||
gamma_sbas_runner_windows = _project_file_windows("deploy", "wsl", "runners", "gamma_sbas_runner.py")
|
||||
gamma_profile_windows = _project_file_windows("deploy", "wsl", "profiles", "gamma_env.sh")
|
||||
|
||||
runtimes = {
|
||||
@@ -151,6 +152,33 @@ def build_wsl_runtime_registry() -> WslRuntimeRegistry:
|
||||
"legacy_profile_env_var": "PYINT_GAMMA_ENV_SCRIPT",
|
||||
},
|
||||
),
|
||||
settings.GAMMA_SBAS_RUNTIME_ID: WslRuntimeDefinition(
|
||||
runtime_id=settings.GAMMA_SBAS_RUNTIME_ID,
|
||||
engine_code="gamma",
|
||||
display_name="Gamma SBAS Runtime V1",
|
||||
distro=str(settings.GAMMA_SBAS_WSL_DISTRO or shared_distro).strip() or shared_distro,
|
||||
conda_env_name=shared_conda_env,
|
||||
python_path=str(settings.GAMMA_SBAS_PYTHON or shared_python_path).strip() or shared_python_path,
|
||||
runner_path_windows=gamma_sbas_runner_windows,
|
||||
runner_path_wsl=_windows_path_to_wsl_mount(gamma_sbas_runner_windows),
|
||||
allowed_operations=("lt1_gamma_sbas_workflow", "lt1_gamma_sbas_step"),
|
||||
env_profile_path_windows=str(settings.GAMMA_SBAS_ENV_SCRIPT or gamma_profile_windows).strip(),
|
||||
env_profile_path_wsl=_windows_path_to_wsl_mount(
|
||||
str(settings.GAMMA_SBAS_ENV_SCRIPT or gamma_profile_windows).strip()
|
||||
),
|
||||
metadata_json={
|
||||
"shared_runtime": True,
|
||||
"workflow_code": "sbas_insar",
|
||||
"processor_code": "gamma_ipta_sbas",
|
||||
"env_vars": {
|
||||
"runtime_id": "GAMMA_SBAS_RUNTIME_ID",
|
||||
"python": "GAMMA_SBAS_PYTHON",
|
||||
"env_profile": "GAMMA_SBAS_ENV_SCRIPT",
|
||||
"work_root": "GAMMA_SBAS_WORK_ROOT",
|
||||
"product_root": "GAMMA_SBAS_PRODUCT_ROOT",
|
||||
},
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
return WslRuntimeRegistry(
|
||||
|
||||
Reference in New Issue
Block a user