Source code for pyart.retrieve.srv

"""
Calculation of storm-relative velocity from a radar object. Code written by
Edward C. Wolff. Modifications for single-sweep files suggested by Leanne
Blind.

"""

import math

import numpy as np

from ..config import get_field_name


[docs]def storm_relative_velocity( radar, direction=None, speed=None, field=None, u=None, v=None ): """ This function calculates storm-relative Doppler velocities. Parameters ---------- radar: Radar Radar object used. direction: float or string Direction of the storm motion vector (where north equals 0 degrees). Accepts a float or a string with the abbreviation of a cardinal or ordinal/intercardinal direction (for example: N, SE, etc.). If both speed/direction and u/v are specified, speed/direction will be used. speed: string Speed of the storm motion vector. Units should be identical to those in the provided radar object. If both speed/direction and u/v are specified, speed/direction will be used. field: string, optional Velocity field to use for storm-relative calculation. A value of None will use the default field name as defined in the Py-ART configuration file. u: float, optional U-component of the storm motion v: float, optional V-component of the storm motion Returns ------- sr_data : dict Field dictionary containing storm-relative Doppler velocities in the same units as original velocities and the specified storm speed. Array is stored under the 'data' key. """ # Parse the field parameter if field is None: field = get_field_name("velocity") # Obtain velocity data and copy the array sr_data = radar.fields[field]["data"].copy() # Specify cardinal directions that can be interpreted direction_dict = { "N": 0, "NE": 45, "E": 90, "SE": 135, "S": 180, "SW": 225, "W": 270, "NW": 315, } # Set the direction of the storm motion vector # When speed and direction are specified if direction is not None and speed is not None: if isinstance(direction, int) or isinstance(direction, float): alpha = direction elif isinstance(direction, str): if direction in direction_dict.keys(): alpha = direction_dict[direction] else: raise ValueError("Direction string must be cardinal/ordinal direction") else: raise ValueError("Direction must be an integer, float, or string") # When u and v are specified elif u is not None: if v is not None: speed = np.sqrt((u**2) + (v**2)) direction = 90 - np.rad2deg(math.atan2(v / speed, u / speed)) if direction < 0: direction = direction + 360 else: raise ValueError("Must specify both u and v components") else: raise ValueError("Must specify either speed and direction or u and v") # Calculates the storm relative velocities # If the radar file contains only one sweep (e.g. some research radars) if len(radar.sweep_number["data"]) == 1: sweep = 0 start, end = radar.get_start_end(sweep) angle_array = radar.get_azimuth(sweep=sweep) ray_array = np.arange(start, end, 1) for count, ray in enumerate(ray_array): correction = speed * np.cos(np.deg2rad(alpha - angle_array[count])) sr_data[ray] = radar.fields[field]["data"][ray] - correction # If the radar file contains several sweeps, one volume scan (e.g. NEXRAD) else: for sweep in radar.sweep_number["data"]: start, end = radar.get_start_end(sweep) angle_array = radar.get_azimuth(sweep=sweep) ray_array = np.arange(start, end + 1, 1) for count, ray in enumerate(ray_array): correction = speed * np.cos(np.deg2rad(alpha - angle_array[count])) sr_data[ray] = radar.fields[field]["data"][ray] - correction return sr_data