@mytec: 1.4iter ready for testing
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import time
|
||||
|
||||
from fastapi import APIRouter, HTTPException, BackgroundTasks
|
||||
from typing import List, Optional
|
||||
from pydantic import BaseModel
|
||||
@@ -5,7 +7,9 @@ from app.services.coverage_service import (
|
||||
coverage_service,
|
||||
CoverageSettings,
|
||||
SiteParams,
|
||||
CoveragePoint
|
||||
CoveragePoint,
|
||||
apply_preset,
|
||||
PRESETS,
|
||||
)
|
||||
|
||||
router = APIRouter()
|
||||
@@ -23,6 +27,8 @@ class CoverageResponse(BaseModel):
|
||||
count: int
|
||||
settings: CoverageSettings
|
||||
stats: dict
|
||||
computation_time: float # seconds
|
||||
models_used: List[str] # which models were active
|
||||
|
||||
|
||||
@router.post("/calculate")
|
||||
@@ -30,7 +36,8 @@ async def calculate_coverage(request: CoverageRequest) -> CoverageResponse:
|
||||
"""
|
||||
Calculate RF coverage for one or more sites
|
||||
|
||||
Returns grid of RSRP values with terrain and building effects
|
||||
Returns grid of RSRP values with terrain and building effects.
|
||||
Supports propagation model presets: fast, standard, detailed, full.
|
||||
"""
|
||||
if not request.sites:
|
||||
raise HTTPException(400, "At least one site required")
|
||||
@@ -45,6 +52,13 @@ async def calculate_coverage(request: CoverageRequest) -> CoverageResponse:
|
||||
if request.settings.resolution < 50:
|
||||
raise HTTPException(400, "Minimum resolution 50m")
|
||||
|
||||
# Apply preset and determine active models
|
||||
effective_settings = apply_preset(request.settings.model_copy())
|
||||
models_used = _get_active_models(effective_settings)
|
||||
|
||||
# Time the calculation
|
||||
start_time = time.time()
|
||||
|
||||
# Calculate
|
||||
if len(request.sites) == 1:
|
||||
points = await coverage_service.calculate_coverage(
|
||||
@@ -57,6 +71,8 @@ async def calculate_coverage(request: CoverageRequest) -> CoverageResponse:
|
||||
request.settings
|
||||
)
|
||||
|
||||
computation_time = time.time() - start_time
|
||||
|
||||
# Calculate stats
|
||||
rsrp_values = [p.rsrp for p in points]
|
||||
los_count = sum(1 for p in points if p.has_los)
|
||||
@@ -68,16 +84,48 @@ async def calculate_coverage(request: CoverageRequest) -> CoverageResponse:
|
||||
"los_percentage": (los_count / len(points) * 100) if points else 0,
|
||||
"points_with_buildings": sum(1 for p in points if p.building_loss > 0),
|
||||
"points_with_terrain_loss": sum(1 for p in points if p.terrain_loss > 0),
|
||||
"points_with_reflection_gain": sum(1 for p in points if p.reflection_gain > 0),
|
||||
}
|
||||
|
||||
return CoverageResponse(
|
||||
points=points,
|
||||
count=len(points),
|
||||
settings=request.settings,
|
||||
stats=stats
|
||||
settings=effective_settings,
|
||||
stats=stats,
|
||||
computation_time=round(computation_time, 2),
|
||||
models_used=models_used
|
||||
)
|
||||
|
||||
|
||||
@router.get("/presets")
|
||||
async def get_presets():
|
||||
"""Get available propagation model presets"""
|
||||
return {
|
||||
"presets": {
|
||||
"fast": {
|
||||
"description": "Quick calculation - terrain only",
|
||||
**PRESETS["fast"],
|
||||
"estimated_speed": "~5 seconds for 5km radius"
|
||||
},
|
||||
"standard": {
|
||||
"description": "Balanced - terrain + buildings with materials",
|
||||
**PRESETS["standard"],
|
||||
"estimated_speed": "~30 seconds for 5km radius"
|
||||
},
|
||||
"detailed": {
|
||||
"description": "Accurate - adds dominant path analysis",
|
||||
**PRESETS["detailed"],
|
||||
"estimated_speed": "~2 minutes for 5km radius"
|
||||
},
|
||||
"full": {
|
||||
"description": "Maximum realism - all models enabled",
|
||||
**PRESETS["full"],
|
||||
"estimated_speed": "~5 minutes for 5km radius"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@router.get("/buildings")
|
||||
async def get_buildings(
|
||||
min_lat: float,
|
||||
@@ -102,3 +150,23 @@ async def get_buildings(
|
||||
"count": len(buildings),
|
||||
"buildings": [b.model_dump() for b in buildings]
|
||||
}
|
||||
|
||||
|
||||
def _get_active_models(settings: CoverageSettings) -> List[str]:
|
||||
"""Determine which propagation models are active"""
|
||||
models = ["okumura_hata"] # Always active as base model
|
||||
|
||||
if settings.use_terrain:
|
||||
models.append("terrain_los")
|
||||
if settings.use_buildings:
|
||||
models.append("buildings")
|
||||
if settings.use_materials:
|
||||
models.append("materials")
|
||||
if settings.use_dominant_path:
|
||||
models.append("dominant_path")
|
||||
if settings.use_street_canyon:
|
||||
models.append("street_canyon")
|
||||
if settings.use_reflections:
|
||||
models.append("reflections")
|
||||
|
||||
return models
|
||||
|
||||
Reference in New Issue
Block a user