added covarage
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
from astropy import units as u
|
||||
from pycraf import pathprof
|
||||
from pyproj import Geod
|
||||
|
||||
from app.config import get_settings
|
||||
from app.core.dem import elevations_along
|
||||
from app.core.geo import GeoPoint, haversine, sample_path
|
||||
|
||||
_GEOD = Geod(ellps="WGS84")
|
||||
|
||||
|
||||
def _clutter_zone(environment: str) -> pathprof.CLUTTER:
|
||||
mapping = {
|
||||
"urban": pathprof.CLUTTER.URBAN,
|
||||
"suburban": pathprof.CLUTTER.SUBURBAN,
|
||||
"rural": pathprof.CLUTTER.SPARSE,
|
||||
}
|
||||
return mapping.get(environment, pathprof.CLUTTER.SPARSE)
|
||||
|
||||
|
||||
def _height_profile(
|
||||
tx: GeoPoint,
|
||||
rx: GeoPoint,
|
||||
*,
|
||||
dem_path: str | None = None,
|
||||
samples: int = 64,
|
||||
) -> tuple[np.ndarray, np.ndarray, float, float]:
|
||||
points = sample_path(tx, rx, samples)
|
||||
try:
|
||||
heights = elevations_along(points, dem_path=dem_path or get_settings().dem_path)
|
||||
except Exception:
|
||||
heights = np.zeros(len(points), dtype=float)
|
||||
dists = np.array([point.distance_m for point in points], dtype=float) * u.m
|
||||
return dists, heights * u.m, points[0].lon, points[0].lat
|
||||
|
||||
|
||||
def p452_path_loss(
|
||||
tx: GeoPoint,
|
||||
rx: GeoPoint,
|
||||
*,
|
||||
tx_height_agl: float,
|
||||
rx_height_agl: float,
|
||||
freq_mhz: float,
|
||||
environment: str = "rural",
|
||||
elevation_profile_m: list[float] | None = None,
|
||||
dem_path: str | None = None,
|
||||
) -> float:
|
||||
distance_km = haversine(tx, rx) / 1000.0
|
||||
if elevation_profile_m is not None:
|
||||
count = len(elevation_profile_m)
|
||||
dists = np.linspace(0, distance_km * 1000, count) * u.m
|
||||
heights = np.array(elevation_profile_m, dtype=float) * u.m
|
||||
bearing, _, _ = _GEOD.inv(tx.lon, tx.lat, rx.lon, rx.lat)
|
||||
backbearing = (bearing + 180) % 360
|
||||
else:
|
||||
dists, heights, _, _ = _height_profile(tx, rx, dem_path=dem_path)
|
||||
bearing, _, _ = _GEOD.inv(tx.lon, tx.lat, rx.lon, rx.lat)
|
||||
backbearing = (bearing + 180) % 360
|
||||
|
||||
pathprop = pathprof.PathProp(
|
||||
freq_mhz * u.MHz,
|
||||
293 * u.K,
|
||||
1013 * u.hPa,
|
||||
tx.lon * u.deg,
|
||||
tx.lat * u.deg,
|
||||
rx.lon * u.deg,
|
||||
rx.lat * u.deg,
|
||||
tx_height_agl * u.m,
|
||||
rx_height_agl * u.m,
|
||||
max(100.0, distance_km * 10) * u.m,
|
||||
50 * u.percent,
|
||||
zone_t=_clutter_zone(environment),
|
||||
zone_r=_clutter_zone(environment),
|
||||
hprof_dists=dists,
|
||||
hprof_heights=heights,
|
||||
hprof_bearing=bearing * u.deg,
|
||||
hprof_backbearing=backbearing * u.deg,
|
||||
)
|
||||
losses = pathprof.loss_complete(pathprop)
|
||||
total = losses[0]
|
||||
return float(total.value)
|
||||
Reference in New Issue
Block a user