81 lines
3.3 KiB
Python
81 lines
3.3 KiB
Python
from __future__ import annotations
|
|
|
|
import uuid
|
|
|
|
from fastapi import APIRouter, Depends
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.db.session import get_db
|
|
from app.core.errors import AppError
|
|
from app.models import Dataset, Job
|
|
from app.schemas import QaProviderComparisonRequest
|
|
from app.services.qa_service import QaService
|
|
from app.services.job_service import JobService
|
|
from app.services.quality_service import QualityService
|
|
from app.utils.response import envelope
|
|
|
|
router = APIRouter(prefix="/qa", tags=["qa"])
|
|
|
|
|
|
@router.post("/detections-vs-reference")
|
|
def compare_candidate_with_reference(
|
|
payload: QaProviderComparisonRequest,
|
|
db: Session = Depends(get_db),
|
|
) -> dict:
|
|
candidate_dataset = db.get(Dataset, payload.candidate_dataset_id)
|
|
if not candidate_dataset:
|
|
raise AppError(code="DATASET_NOT_FOUND", message="Candidate dataset not found", status_code=404)
|
|
job = JobService.run_sync_job(
|
|
db=db,
|
|
project_id=candidate_dataset.project_id,
|
|
job_type="qa.compare-candidate-with-reference",
|
|
parameters=payload.model_dump(mode="json"),
|
|
input_dataset_id=candidate_dataset.id,
|
|
operation=lambda: QaService.compare_candidate_with_reference(
|
|
db=db,
|
|
project_id=candidate_dataset.project_id,
|
|
candidate_dataset_id=payload.candidate_dataset_id,
|
|
reference_dataset_id=payload.reference_dataset_id,
|
|
iou_threshold=payload.iou_threshold,
|
|
area_id=payload.area_id,
|
|
).model_dump(mode="json"),
|
|
)
|
|
result_json = job.get("result_json") if isinstance(job, dict) else None
|
|
if isinstance(result_json, dict) and job.get("status") == "success":
|
|
quality_check = QualityService.persist_quality_check(
|
|
db=db,
|
|
project_id=candidate_dataset.project_id,
|
|
job_id=uuid.UUID(str(job["id"])),
|
|
candidate_dataset_id=payload.candidate_dataset_id,
|
|
reference_dataset_id=payload.reference_dataset_id,
|
|
check_type="candidate_vs_reference",
|
|
status=str(result_json.get("status", "ok")),
|
|
score=result_json.get("f1_score"),
|
|
parameters=payload.model_dump(mode="json"),
|
|
findings={
|
|
"matches": result_json.get("matches"),
|
|
"false_positives": result_json.get("false_positives"),
|
|
"false_negatives": result_json.get("false_negatives"),
|
|
"warnings": result_json.get("warnings", []),
|
|
"unsupported_geometry": result_json.get("unsupported_geometry", False),
|
|
"unsupported_geometries": result_json.get("unsupported_geometries", []),
|
|
},
|
|
metrics={
|
|
"precision": result_json.get("precision"),
|
|
"recall": result_json.get("recall"),
|
|
"f1": result_json.get("f1_score"),
|
|
"mean_iou": result_json.get("mean_iou"),
|
|
"false_positive_count": result_json.get("false_positives"),
|
|
"false_negative_count": result_json.get("false_negatives"),
|
|
},
|
|
)
|
|
result_json["quality_check_id"] = str(quality_check.id)
|
|
|
|
job_record = db.get(Job, uuid.UUID(str(job["id"])))
|
|
if job_record:
|
|
job_record.result_json = result_json
|
|
db.add(job_record)
|
|
db.commit()
|
|
|
|
return envelope(job)
|