Upgrade async GPU analysis and workbench UX
This commit is contained in:
@@ -2,9 +2,14 @@ from __future__ import annotations
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from fastapi import APIRouter, Depends, Query, Request
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.guest_scope import (
|
||||
assert_guest_project_scope,
|
||||
guest_project_scope,
|
||||
guest_scoped_project_filter,
|
||||
)
|
||||
from app.db.session import get_db
|
||||
from app.schemas import (
|
||||
AnalysisQaResponse,
|
||||
@@ -21,6 +26,7 @@ from app.schemas import (
|
||||
SegmentationRunResponse,
|
||||
)
|
||||
from app.services.model_registry_service import ModelRegistryService
|
||||
from app.services.dataset_service import DatasetService
|
||||
from app.services.detection_service import DetectionService
|
||||
from app.services.segmentation_service import SegmentationService
|
||||
from app.utils.response import envelope
|
||||
@@ -34,7 +40,12 @@ def list_segmentation_models() -> dict:
|
||||
|
||||
|
||||
@router.post("/run", response_model=Envelope[SegmentationRunResponse])
|
||||
def run_segmentation(payload: SegmentationRunRequest, db: Session = Depends(get_db)) -> dict:
|
||||
def run_segmentation(
|
||||
payload: SegmentationRunRequest,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
assert_guest_project_scope(request, payload.project_id)
|
||||
result = SegmentationService.run_segmentation(
|
||||
db=db,
|
||||
project_id=payload.project_id,
|
||||
@@ -49,13 +60,18 @@ def run_segmentation(payload: SegmentationRunRequest, db: Session = Depends(get_
|
||||
|
||||
|
||||
@router.post("/run-async", response_model=Envelope[JobRead])
|
||||
def queue_segmentation(payload: SegmentationRunRequest, db: Session = Depends(get_db)) -> dict:
|
||||
def queue_segmentation(
|
||||
payload: SegmentationRunRequest,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
"""Queue a segmentation run for the background worker.
|
||||
|
||||
Configured segmentation walks the same tile manifest as detection and is
|
||||
just as unsuited to running inside the request. Poll ``GET /jobs/{id}``.
|
||||
"""
|
||||
|
||||
assert_guest_project_scope(request, payload.project_id)
|
||||
job = SegmentationService.enqueue_segmentation(
|
||||
db=db,
|
||||
project_id=payload.project_id,
|
||||
@@ -71,12 +87,14 @@ def queue_segmentation(payload: SegmentationRunRequest, db: Session = Depends(ge
|
||||
|
||||
@router.get("/runs", response_model=Envelope[SegmentationRunListResponse])
|
||||
def list_segmentation_runs(
|
||||
request: Request,
|
||||
project_id: UUID | None = None,
|
||||
dataset_id: UUID | None = None,
|
||||
limit: int = Query(default=DetectionService.DEFAULT_RUN_LIST_LIMIT, ge=0, le=5_000),
|
||||
offset: int = Query(default=0, ge=0),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
project_id = guest_scoped_project_filter(request, project_id)
|
||||
return envelope(
|
||||
SegmentationService.list_runs(
|
||||
db, project_id=project_id, dataset_id=dataset_id, limit=limit, offset=offset
|
||||
@@ -85,8 +103,14 @@ def list_segmentation_runs(
|
||||
|
||||
|
||||
@router.get("/runs/{analysis_run_id}", response_model=Envelope[SegmentationRunRead])
|
||||
def get_segmentation_run(analysis_run_id: UUID, db: Session = Depends(get_db)) -> dict:
|
||||
return envelope(SegmentationService.get_run(db, analysis_run_id).model_dump())
|
||||
def get_segmentation_run(
|
||||
analysis_run_id: UUID,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
run = SegmentationService.get_run(db, analysis_run_id)
|
||||
assert_guest_project_scope(request, run.project_id)
|
||||
return envelope(run.model_dump())
|
||||
|
||||
|
||||
@router.get(
|
||||
@@ -95,6 +119,7 @@ def get_segmentation_run(analysis_run_id: UUID, db: Session = Depends(get_db)) -
|
||||
)
|
||||
def list_segmentation_run_outputs(
|
||||
analysis_run_id: UUID,
|
||||
request: Request,
|
||||
dataset_id: UUID | None = None,
|
||||
class_name: str | None = None,
|
||||
min_confidence: float | None = None,
|
||||
@@ -107,6 +132,9 @@ def list_segmentation_run_outputs(
|
||||
offset: int = Query(default=0, ge=0),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
if guest_project_scope(request) is not None:
|
||||
run = SegmentationService.get_run(db, analysis_run_id)
|
||||
assert_guest_project_scope(request, run.project_id)
|
||||
return envelope(
|
||||
SegmentationService.list_segmentations(
|
||||
db,
|
||||
@@ -126,6 +154,7 @@ def list_segmentation_run_outputs(
|
||||
)
|
||||
def list_dataset_segmentations(
|
||||
dataset_id: UUID,
|
||||
request: Request,
|
||||
analysis_run_id: UUID | None = None,
|
||||
class_name: str | None = None,
|
||||
min_confidence: float | None = None,
|
||||
@@ -138,6 +167,9 @@ def list_dataset_segmentations(
|
||||
offset: int = Query(default=0, ge=0),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
if guest_project_scope(request) is not None:
|
||||
dataset = DatasetService.get_dataset(db, dataset_id)
|
||||
assert_guest_project_scope(request, dataset.project_id)
|
||||
return envelope(
|
||||
SegmentationService.list_segmentations(
|
||||
db,
|
||||
@@ -152,8 +184,14 @@ def list_dataset_segmentations(
|
||||
|
||||
|
||||
@router.get("/segmentations/{segmentation_id}", response_model=Envelope[SegmentationRead])
|
||||
def get_segmentation(segmentation_id: UUID, db: Session = Depends(get_db)) -> dict:
|
||||
return envelope(SegmentationService.get_segmentation(db, segmentation_id).model_dump())
|
||||
def get_segmentation(
|
||||
segmentation_id: UUID,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
segmentation = SegmentationService.get_segmentation(db, segmentation_id)
|
||||
assert_guest_project_scope(request, segmentation.project_id)
|
||||
return envelope(segmentation.model_dump())
|
||||
|
||||
|
||||
@router.get(
|
||||
@@ -162,6 +200,7 @@ def get_segmentation(segmentation_id: UUID, db: Session = Depends(get_db)) -> di
|
||||
)
|
||||
def get_segmentation_run_geojson(
|
||||
analysis_run_id: UUID,
|
||||
request: Request,
|
||||
class_name: str | None = None,
|
||||
min_confidence: float | None = None,
|
||||
limit: int = Query(
|
||||
@@ -172,6 +211,9 @@ def get_segmentation_run_geojson(
|
||||
),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
if guest_project_scope(request) is not None:
|
||||
run = SegmentationService.get_run(db, analysis_run_id)
|
||||
assert_guest_project_scope(request, run.project_id)
|
||||
return envelope(
|
||||
SegmentationService.segmentations_to_geojson(
|
||||
db,
|
||||
@@ -189,6 +231,7 @@ def get_segmentation_run_geojson(
|
||||
)
|
||||
def get_dataset_segmentation_geojson(
|
||||
dataset_id: UUID,
|
||||
request: Request,
|
||||
analysis_run_id: UUID | None = None,
|
||||
class_name: str | None = None,
|
||||
min_confidence: float | None = None,
|
||||
@@ -200,6 +243,9 @@ def get_dataset_segmentation_geojson(
|
||||
),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
if guest_project_scope(request) is not None:
|
||||
dataset = DatasetService.get_dataset(db, dataset_id)
|
||||
assert_guest_project_scope(request, dataset.project_id)
|
||||
return envelope(
|
||||
SegmentationService.segmentations_to_geojson(
|
||||
db,
|
||||
@@ -219,8 +265,12 @@ def get_dataset_segmentation_geojson(
|
||||
def compare_segmentation_run_with_reference(
|
||||
analysis_run_id: UUID,
|
||||
payload: SegmentationQaRequest,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
if guest_project_scope(request) is not None:
|
||||
run = SegmentationService.get_run(db, analysis_run_id)
|
||||
assert_guest_project_scope(request, run.project_id)
|
||||
return envelope(
|
||||
SegmentationService.compare_segmentations_with_reference(
|
||||
db=db,
|
||||
|
||||
Reference in New Issue
Block a user