Source code for pyBADA.magnetic

# -*- coding: utf-8 -*-
"""
pyBADA
Magnetic declination module
Developped @EUROCONTROL (EIH)
2024
"""

import json
import bisect
from pyBADA import configuration


[docs] class Grid: """This class provides methods to calculate the magnetic declination at a given latitude and longitude using pre-loaded grid data. The grid data is loaded from a JSON file, and the closest grid point is used to determine the magnetic declination. """ def __init__(self, inputJSON=None): """Initializes the grid with magnetic declination data. :param inputJSON: Path to the JSON file containing grid data. Defaults to a pre-configured path. :type inputJSON: str, optional """ if inputJSON is None: inputJSON = ( configuration.getDataPath() + "/magneticDeclinationGridData.json" ) f = open(inputJSON) grid = json.load(f) self.gridData = {} latitudeList = [] longitudeList = [] magneticDeclinationList = [] for result in grid["result"]: latitudeList.append(result["latitude"]) longitudeList.append(result["longitude"]) magneticDeclinationList.append(result["declination"]) self.gridData["LAT"] = latitudeList self.gridData["LON"] = longitudeList self.gridData["declination"] = magneticDeclinationList
[docs] def getClosestLatitude(self, LAT_target): """Finds the closest latitude in the grid to the target latitude. :param LAT_target: Target latitude to search for. :type LAT_target: float :return: The closest latitude from the grid or None if the target is out of bounds. :rtype: float or None """ latitudeList = sorted(self.gridData["LAT"]) if LAT_target < latitudeList[0] or LAT_target > latitudeList[-1]: return None index = bisect.bisect_left(latitudeList, LAT_target) if index == 0: closest = latitudeList[0] elif index == len(latitudeList): closest = latitudeList[-1] else: before = latitudeList[index - 1] after = latitudeList[index] closest = ( before if after - LAT_target > LAT_target - before else after ) return closest
[docs] def getClosestLongitude(self, LON_target): """Finds the closest longitude in the grid to the target longitude. :param LON_target: Target longitude to search for. :type LON_target: float :return: The closest longitude from the grid or None if the target is out of bounds. :rtype: float or None """ longitudeList = sorted(self.gridData["LON"]) if LON_target < longitudeList[0] or LON_target > longitudeList[-1]: return None index = bisect.bisect_left(longitudeList, LON_target) if index == 0: closest = longitudeList[0] elif index == len(longitudeList): closest = longitudeList[-1] else: before = longitudeList[index - 1] after = longitudeList[index] closest = ( before if after - LON_target > LON_target - before else after ) return closest
[docs] def getClosestIdx(self, LAT_target, LON_target): """Finds the index of the closest grid point for a given latitude and longitude. :param LAT_target: Target latitude. :param LON_target: Target longitude. :type LAT_target: float :type LON_target: float :return: Index of the closest point in the grid or None if no point is found. :rtype: int or None """ closestLAT = self.getClosestLatitude(LAT_target=LAT_target) closestLON = self.getClosestLongitude(LON_target=LON_target) indicesLAT = [ i for i in range(len(self.gridData["LAT"])) if self.gridData["LAT"][i] == closestLAT ] indicesLON = [ i for i in range(len(self.gridData["LON"])) if self.gridData["LON"][i] == closestLON ] for idx in indicesLAT: if idx in indicesLON: return idx return None
[docs] def getMagneticDeclination(self, LAT_target, LON_target): """Returns the magnetic declination for the closest grid point to the target coordinates. :param LAT_target: Target latitude. :param LON_target: Target longitude. :type LAT_target: float :type LON_target: float :return: Magnetic declination at the closest grid point or None if no point is found. :rtype: float or None """ idx = self.getClosestIdx(LAT_target=LAT_target, LON_target=LON_target) if idx is None: return None else: magneticDeclination = self.gridData["declination"][idx] return magneticDeclination