import csv import re import shapely from nexrad.db import DatabaseTable from nexrad.coord import COORD_SYSTEM """ Implements a parser and wrapper class for the WSR-88D radar list available at the following location (accessed 10 Feb 2025): https://apollo.nvu.vsc.edu/classes/remote/lecture_notes/radar/88d/88D_locations.html The input TSV file is created by copying and pasting the tabular data from a web browser into a text file. """ RE_PARSE = re.compile(r'^\s*(\d+)([NS]*)\s+/\s+(\d+)([EW]*)\s*$') def parse_int(text: str): size = len(text) degree = int(text[0:size-4]) minute = int(text[size-4:size-2]) second = int(text[size-2:]) return degree + (minute / 60) + (second / 3600) def parse(text: str): match = RE_PARSE.match(text) if match is None: raise Exception("Invalid coordinates '%s'" % text) sign_lon = 1 if match[4] == 'E' else -1 sign_lat = -1 if match[2] == 'S' else 1 lon = parse_int(match[3]) lat = parse_int(match[1]) return shapely.Point(sign_lon * lon, sign_lat * lat) RADAR_RANGE = 230000 class Radar(DatabaseTable): __slots__ = ( 'call', 'wban', 'name', 'coord', 'site_elevation', 'tower_height', ) __table__ = 'nexrad_radar' __key__ = 'call' __columns__ = ( 'call', 'wban', 'name', 'coord', 'site_elevation', 'tower_height' ) __columns_read__ = { 'coord': 'ST_AsText(coord) as coord' } __values_read__ = { 'coord': shapely.from_wkt } __columns_write__ = { 'coord': 'MakePoint(:coord_lon, :coord_lat, {crs})'.format(crs=COORD_SYSTEM) } __values_write__ = { 'coord': lambda v: {'coord_lon': v.x, 'coord_lat': v.y} } call: str wban: int name: str coord: shapely.Point site_elevation: float tower_height: float @staticmethod def from_tsv_row(row: list): radar = Radar() radar.call = row[1] radar.wban = int(row[0]) if row[0] != 'PENDING' else None radar.name = row[2] radar.coord = parse(row[3]) radar.site_elevation = 0.3048 * float(row[4]) radar.tower_height = float(row[5]) return radar @staticmethod def each_from_tsv(file: str): with open(file) as fh: reader = csv.reader(fh, delimiter='\t') for row in reader: for i in range(0, len(row)): row[i] = row[i].rstrip() yield Radar.from_tsv_row(row)