Beispiel #1
0
 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
Beispiel #2
0
 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
Beispiel #3
0
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
Beispiel #4
0
 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
Beispiel #5
0
 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
Beispiel #6
0
    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
Beispiel #7
0
 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
Beispiel #8
0
 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
Beispiel #9
0
    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
Beispiel #10
0
    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