Source code for towerpy.georad.georef_rdata

"""Towerpy: an open-source toolbox for processing polarimetric radar data."""

import numpy as np


[docs] def cart2pol(x, y): """ Transform Cartesian coordinates to Polar. Parameters ---------- x, y : array Cartesian coordinates Returns ------- rho : array Radial coordinate, rho is the distance from the origin to a point in the x-y plane. theta : array Angular coordinates is the counterclockwise angle in the x-y plane measured in radians from the positive x-axis. The value of the angle is in the range [-pi, pi]. """ rho = np.hypot(x, y) theta = np.arctan2(y, x) return rho, theta
[docs] def pol2cart(rho, theta): """ Transform polar coordinates to Cartesian. Parameters ---------- rho : array Radial coordinate, rho is the distance from the origin to a point in the x-y plane. theta : array Angular coordinates is the counterclockwise angle in the x-y plane measured in radians from the positive x-axis. The value of the angle is in the range [-pi, pi]. Returns ------- x, y : array Cartesian coordinates. """ x = rho * np.cos(theta) y = rho * np.sin(theta) return x, y
[docs] def height_beamc(elev_angle, rad_range, e_rad=6378, std_refr=4/3): r""" Calculate the height of the centre of the radar beam above Earth's surface. Parameters ---------- elev_angle : float Radar elevation angle in degrees. rad_range : array Range from the radar in kilometres. e_rad : float, optional Effective Earth's radius. The default is 6378. std_refr : float, optional Standard refraction coefficient. The default is 4/3. Returns ------- h : array Height of the centre of the radar beam in kilometres. Notes ----- The beam height above sea level or radar level for a standard atmosphere is calculated by adapting equation (2.28b) in [1]_: :math:`h = \sqrt{r^2+(\frac{4}{3} E_r)^2+2r(\frac{4}{3} E_r)\sin\Theta}-\frac{4}{3} E_r` Where: h : height of the centre of the radar beam above Earth's surface r : radar range to the targets in kilometres. :math:`\Theta` : elevation angle of beam in degree :math:`E_r` : effective Earth's radius [approximately 6378 km] References ---------- .. [1] Doviak, R., & Zrnic, D. S. (1993). Electromagnetic Waves and Propagation in Doppler Radar and Weather Observations (pp. 10-29). San Diego: Academic Press, Second Edition. https://doi.org/10.1016/B978-0-12-221422-6.50007-3 """ h = (np.sqrt((rad_range**2)+((std_refr*e_rad)**2) + (2*rad_range*(std_refr*e_rad) * np.sin(np.deg2rad(elev_angle)))) - (std_refr*e_rad)) return h
[docs] def cartesian_distance(elev_angle, rad_range, hbeam, e_rad=6378, std_refr=4/3): r""" Compute the distance (arc length) from the radar to the bins. Parameters ---------- elev_angle : float Radar elevation angle in degrees. rad_range : array Range from the radar in kilometres. hbeam : float Height of the centre of the radar beam in kilometres. e_rad : float, optional Effective Earth's radius. The default is 6378. std_refr : float, optional Standard refraction coefficient. The default is 4/3. Returns ------- s: array Distance (arc length) from the radar to the bins in kilometres. Notes ----- The distance in Cartesian coordinates is calculated by adapting equations (2.28b and 2.28c) in [1]_: :math:`h = \sqrt{r^2+(\frac{4}{3} E_r)^2+2r(\frac{4}{3} E_r)\sin\Theta}-\frac{4}{3} E_r` :math:`s = \frac{4}{3} E_r * arcsin(\frac{r*cos(\Theta)}{\frac{4}{3} E_r+h})` References ---------- .. [1] Doviak, R., & Zrnic, D. S. (1993). Electromagnetic Waves and Propagation in Doppler Radar and Weather Observations (pp. 10-29). San Diego: Academic Press, Second Edition. https://doi.org/10.1016/B978-0-12-221422-6.50007-3 """ s = (std_refr*e_rad) * np.arcsin(rad_range * np.cos(np.deg2rad(elev_angle)) / (std_refr*e_rad+hbeam)) return s
[docs] def ppi_georef(rparams, georef=None, polarc_exist=True, elev=0.5, gate0=0, gateres=250): """ Create georeferenced grid for PPI radar scans. Parameters ---------- rparams : dict Radar parameters dictionary. Must contain: - 'nrays' : int, number of rays - 'ngates' : int, number of range gates - 'beamwidth [deg]' : float, beamwidth in degrees georef : dict, optional Existing georeference dictionary with keys 'azim [rad]', 'elev [rad]', 'range [m]'. Required if `polarc_exist=True`. polarc_exist : bool If True, polar coordinates (range, azimuth, elevation) are read directly from the georef attribute. If False, synthesise elevation, azimuth, and range. The default is True elev : float Elevation angle in degrees (used if `polarc_exist=False`). The default is 0.5 gate0 : float Starting range gate in metres (used if `polarc_exist=False`). The default is 0 gateres : float Gate resolution in metres (used if `polarc_exist=False`). The default is 250 Returns ------- geogrid : dict Dictionary containing georeferenced arrays: - 'grid_rectx', 'grid_recty' : Cartesian grid coordinates in kilometres - 'beam_height [km]' : beam centre heights in kilometres - 'beambottom_height [km]' : beam bottom heights in kilometres - 'beamtop_height [km]' : beam top heights in kilometres base : dict Dictionary with base polar coordinates (always in radians/metres): - 'azim [rad]' : azimuth angles in radians - 'elev [rad]' : elevation angles in radians - 'range [m]' : range values in metres Notes ----- 1. The rectangular grid is returned in kilometres to match convention. """ # Elevation, azimuth, range setup if polarc_exist and georef is not None: elev = georef['elev [rad]'] azim = georef['azim [rad]'] rng = georef['range [m]'] else: elev = np.deg2rad(np.full(rparams['nrays'], elev)) azim = np.deg2rad(np.linspace(0, 360, rparams['nrays'], endpoint=False)) rng = gate0 + np.arange(rparams['ngates'], dtype=float) * gateres elev_deg = np.rad2deg(elev) bw = rparams['beamwidth [deg]'] rng_km = rng / 1000.0 # convert to km for height_beamc # Beam heights bhkm = np.array([height_beamc(ray, rng_km) for ray in elev_deg]) bbhkm = np.array([height_beamc(ray - bw/2, rng_km) for ray in elev_deg]) bthkm = np.array([height_beamc(ray + bw/2, rng_km) for ray in elev_deg]) # Cartesian conversion s = np.array([cartesian_distance(ray, rng_km, bhkm[i]) for i, ray in enumerate(elev_deg)]) a = [pol2cart(arcl, azim) for arcl in s.T] xgrid = np.array([i[1] for i in a]).T ygrid = np.array([i[0] for i in a]).T # Build georef dict geogrid = { 'grid_rectx': xgrid, 'grid_recty': ygrid, 'beam_height [km]': bhkm, 'beambottom_height [km]': bbhkm, 'beamtop_height [km]': bthkm, } base = {'azim [rad]': azim, 'elev [rad]': elev, 'range [m]': rng} return geogrid, base