Source code for bhf_smarthealth.validate.gps_schema
"""This module contains pydantic validation models for the raw GPS data ingested into the Smart Health pipeline"""
import logging
from datetime import datetime
from pydantic import BaseModel, RootModel, ConfigDict, model_validator
from typing_extensions import Self
logger = logging.getLogger(__name__)
[docs]
class GPSDataPoint(BaseModel):
"""
Represents a measurement for a single GPS timepoint.
"""
# Raise ValidationError if any unexpected additional data fields are present
model_config = ConfigDict(extra="forbid")
# From raw data
d: datetime
long: float
lat: float
# Extracted from file metadata
sheffield_id: str
[docs]
class GPSDataList(RootModel):
"""
Validation model for a full list of GPS timepoints.
Will filter out timepoints with invlaid GPS coordinates after initial validation.
"""
root: list[GPSDataPoint]
# filter out invalid GPSDataPoints after initial validation
# prevents entire .json being rejected for a few bad points.
[docs]
@model_validator(mode="after")
def filter_invalid_gps_points(self) -> Self:
valid_points = []
for gps_point in self.root:
is_lat_valid = -90.0 <= gps_point.lat <= 90.0
is_long_valid = -180.0 <= gps_point.long <= 180.0
if is_lat_valid and is_long_valid:
valid_points.append(gps_point)
if len(valid_points) != len(self.root):
logger.warning(
f"Removed {len(self.root) - len(valid_points)} invalid GPS points"
)
# Replace the original list with the filtered list
self.root = valid_points
return self