def projection(self, reso:float, h_offset:bool=False) -> tuple: r'''Calculate the geographic coordinates of the requested data range.''' theta = self.get_azimuth_angles(self.tilt) r = self.get_range(self.drange, reso) lonx, latx = get_coordinate(r, theta, self.elev, self.stationlon, self.stationlat, h_offset=h_offset) hght = height(r, self.elev, self.radarheight) * np.ones(theta.shape[0])[:, np.newaxis] return lonx, latx, hght, r, theta
def get_data(self): dist = np.arange(self.start_range + self.reso, self.end_range + self.reso, self.reso) lon, lat = get_coordinate(dist, self.azi, self.el, self.stationlon, self.stationlat) hgt = (height(dist, self.el, self.radarheight) * np.ones(self.azi.shape[0])[:, np.newaxis]) da = DataArray(self.data, coords=[self.azi, dist], dims=["azimuth", "distance"]) ds = Dataset( {self.dtype: da}, attrs={ "elevation": self.el, "range": self.end_range, "scan_time": self.scantime, "site_code": self.code, "site_name": self.name, "site_longitude": self.stationlon, "site_latitude": self.stationlat, "tangential_reso": self.reso, "task": self.task_name, }, ) ds["longitude"] = (["azimuth", "distance"], lon) ds["latitude"] = (["azimuth", "distance"], lat) ds["height"] = (["azimuth", "distance"], hgt) if self.dtype in ["VEL", "SW"]: ds["RF"] = (["azimuth", "distance"], self.data[1]) return ds
def echo_top(ref, distance, elev, radarheight, threshold=18.): r''' Calculate height of echo tops (ET) in one full scan Parameters ---------- ref: numpy.ndarray dim=3 (elevation angle, distance, azimuth) reflectivity data distance: numpy.ndarray dim=2 (distance, azimuth) distance from radar site elev: numpy.ndarray or list dim=1 elevation angles in degree radarheight: int or float height of radar drange: float or int range of data to be calculated threshold: float minimum value of reflectivity to be taken into calculation Returns ------- data: numpy.ndarray echo tops data ''' r = np.ma.array(ref, mask=(ref > threshold)) xshape, yshape = r[0].shape et = np.zeros((xshape, yshape)) h_ = list() for i in elev: h = height(distance, i, radarheight) h_.append(h) hght = np.concatenate(h_).reshape(r.shape) for i in range(xshape): for j in range(yshape): vert_h = hght[:, i, j] vert_r = ref[:, i, j] if vert_r.max( ) < threshold: # Vertical points don't satisfy threshold et[i][j] = 0 continue elif vert_r[ -1] >= threshold: # Point in highest scan exceeds threshold et[i][j] = vert_h[-1] continue else: position = np.where(vert_r >= threshold)[0] if position[-1] == 0: et[i][j] = vert_h[0] continue else: pos = position[-1] z1 = vert_r[pos] z2 = vert_r[pos + 1] h1 = vert_h[pos] h2 = vert_h[pos + 1] w1 = (z1 - threshold) / (z1 - z2) w2 = 1 - w1 et[i][j] = w1 * h2 + w2 * h1 return et
def projection(self, reso: float) -> tuple: r = np.arange(reso, self.drange + reso, reso) theta = np.array(self.aux[self.tilt]["azimuth"]) * deg2rad lonx, latx = get_coordinate(r, theta, self.elev, self.stationlon, self.stationlat) hght = (height(r, self.elev, self.radarheight) * np.ones(theta.shape[0])[:, np.newaxis]) return lonx, latx, hght, r, theta
def projection(self, reso): r = np.arange(reso, self.drange + reso, reso) theta = np.array(self.data[self.tilt]['azimuth']) * deg2rad lonx, latx = get_coordinate(r, theta, self.elev, self.stationlon, self.stationlat) hght = height(r, self.elev, self.radarheight) * np.ones( theta.shape[0])[:, np.newaxis] return lonx, latx, hght, r, theta
def get_data( self, tilt: int, drange: Number_T, dtype: str ) -> Union[Radial, Slice_]: r""" Get radar data Parameters ---------- tilt: int index of elevation angle drange: float radius of data dtype: str type of product (REF, VEL, etc.) Returns ------- r_obj: cinrad.datastruct.Radial """ reso = self.scan_config[tilt].dop_reso / 1000 ret = self.get_raw(tilt, drange, dtype) if self.scan_type == "PPI": shape = ret[0].shape[1] if isinstance(ret, tuple) else ret.shape[1] r_obj = Radial( ret, int(shape * reso), self.elev, reso, self.code, self.name, self.scantime, dtype, self.stationlon, self.stationlat, nyquist_velocity=self.scan_config[tilt].nyquist_spd, task=self.task_name, ) x, y, z, d, a = self.projection(reso) r_obj.add_geoc(x, y, z) r_obj.add_polarc(d, a) return r_obj else: # Manual projection shape = ret[0].shape[1] if isinstance(ret, tuple) else ret.shape[1] dist = np.linspace(reso, self.drange, ret.shape[1]) d, e = np.meshgrid(dist, self.aux[tilt]["elevation"]) h = height(d, e, 0) rhi = Slice_( ret, d, h, self.scantime, self.code, self.name, dtype, azimuth=self.aux[tilt]["azimuth"][0], ) return rhi
def projection(self, reso:float, h_offset:bool=False) -> tuple: header = self.f.sweeps[self.tilt][0][4][self.dtype][0] gatenum = header.num_gates firstgate = header.first_gate data_range = np.arange(gatenum) * reso + firstgate azi = np.array([ray[0].az_angle for ray in self.f.sweeps[self.tilt]]) * deg2rad datalength = int(self.drange / reso) lonx, latx = get_coordinate(data_range[:datalength], azi, self.elev, self.stationlon, self.stationlat, h_offset=h_offset) hght = height(data_range[:datalength], self.elev, 0) * np.ones(azi.shape[0])[:, np.newaxis] return lonx, latx, hght, data_range[:datalength], azi
def _geocoor(self): r_data = list() x_data = list() y_data = list() h_data = list() for i in self.rl: r, x, y = grid_2d(i.data, i.lon, i.lat) r_data.append(r) x_data.append(x) y_data.append(y) for radial, elev in zip(self.rl, self.el): hgh = height(radial.dist, elev, 0) hgh_radial = np.asarray(hgh.tolist() * radial.data.shape[0]).reshape(radial.data.shape) hgh_grid, x, y = grid_2d(hgh_radial, radial.lon, radial.lat) h_data.append(hgh_grid) return x_data, y_data, h_data, r_data
def get_data(self, tilt: int, drange: Number_T, dtype: str) -> xr.Dataset: r""" Get radar data with extra information Args: tilt (int): Index of elevation angle starting from zero. drange (float): Radius of data. dtype (str): Type of product (REF, VEL, etc.) Returns: xarray.Dataset: Data. """ reso = self.scan_config[tilt].dop_reso / 1000 ret = self.get_raw(tilt, drange, dtype) shape = ret[0].shape[1] if isinstance(ret, tuple) else ret.shape[1] if self.scan_type == "PPI": x, y, z, d, a = self.projection(reso) if dtype in ["VEL", "SW"]: da = xr.DataArray(ret[0], coords=[a, d], dims=["azimuth", "distance"]) else: da = xr.DataArray(ret, coords=[a, d], dims=["azimuth", "distance"]) ds = xr.Dataset( {dtype: da}, attrs={ "elevation": self.elev, "range": int(np.round(shape * reso)), "scan_time": self.scantime.strftime("%Y-%m-%d %H:%M:%S"), "site_code": self.code, "site_name": self.name, "site_longitude": self.stationlon, "site_latitude": self.stationlat, "tangential_reso": reso, "nyquist_vel": self.scan_config[tilt].nyquist_spd, "task": self.task_name, }, ) ds["longitude"] = (["azimuth", "distance"], x) ds["latitude"] = (["azimuth", "distance"], y) ds["height"] = (["azimuth", "distance"], z) if dtype in ["VEL", "SW"]: ds["RF"] = (["azimuth", "distance"], ret[1]) else: # Manual projection dist = np.linspace(reso, self.drange, ret.shape[1]) azimuth = self.aux[tilt]["azimuth"][0] elev = self.aux[tilt]["elevation"] d, e = np.meshgrid(dist, elev) h = height(d, e, self.radarheight) if dtype in ["VEL", "SW"]: da = xr.DataArray( ret[0], coords=[elev, dist], dims=["tilt", "distance"] ) else: da = xr.DataArray(ret, coords=[elev, dist], dims=["tilt", "distance"]) # Calculate the "start" and "end" of RHI scan # to facilitate tick labeling start_lon = self.stationlon start_lat = self.stationlat end_lon, end_lat = get_coordinate( drange, azimuth * deg2rad, 0, self.stationlon, self.stationlat ) ds = xr.Dataset( {dtype: da}, attrs={ "range": drange, "scan_time": self.scantime.strftime("%Y-%m-%d %H:%M:%S"), "site_code": self.code, "site_name": self.name, "site_longitude": self.stationlon, "site_latitude": self.stationlat, "tangential_reso": reso, "azimuth": azimuth, "start_lon": start_lon, "start_lat": start_lat, "end_lon": end_lon, "end_lat": end_lat, }, ) ds["x_cor"] = (["tilt", "distance"], d) ds["y_cor"] = (["tilt", "distance"], h) return ds
def get_data(self, tilt: int, drange: number_type, dtype: str) -> Radial: r''' Get radar raw data Parameters ---------- tilt: int index of elevation angle drange: float radius of data dtype: str type of product (REF, VEL, etc.) Returns ------- r_obj: cinrad.datastruct.Radial ''' self.tilt = tilt if self.scan_type == 'PPI' else 0 self.drange = drange if self.scan_type == 'RHI': max_range = self.scan_config[0].max_range1 / 1000 if drange > max_range: drange = max_range self.elev = self.el[tilt] try: raw = np.array(self.data[tilt][dtype]) except KeyError: raise RadarDecodeError('Invalid product name') if raw.size == 0: warnings.warn('Empty data', RuntimeWarning) data = np.ma.array(raw, mask=(raw <= 5)) reso = self.scan_config[tilt].dop_reso / 1000 cut = data[:, :int(drange / reso)] shape_diff = np.round(drange / reso) - cut.shape[1] append = np.zeros((cut.shape[0], int(shape_diff))) * np.ma.masked if dtype == 'VEL': rf = np.ma.array(cut.data, mask=(cut.data != 1)) rf = np.ma.hstack([rf, append]) cut = np.ma.hstack([cut, append]) scale, offset = self.aux[tilt][dtype] r = (cut - offset) / scale if dtype in ['VEL', 'SW']: ret = (r, rf) else: ret = r if self.scan_type == 'PPI': r_obj = Radial(ret, int(r.shape[1] * reso), self.elev, reso, self.code, self.name, self.scantime, dtype, self.stationlon, self.stationlat, nyquist_velocity=self.scan_config[tilt].nyquist_spd) x, y, z, d, a = self.projection(reso) r_obj.add_geoc(x, y, z) r_obj.add_polarc(d, a) return r_obj else: # Manual projection dist = np.linspace(reso, self.drange, cut.shape[1]) d, e = np.meshgrid(dist, self.aux[tilt]['elevation']) h = height(d, e, 0) rhi = Slice_(ret, d, h, self.scantime, self.code, self.name, dtype, azimuth=self.aux[tilt]['azimuth'][0]) return rhi