def test_get_radolan_grid_equality(self): # create radolan projection osr object scale = (1. + np.sin(np.radians(60.))) / (1. + np.sin(np.radians(90.))) dwd_string = ('+proj=stere +lat_0=90 +lat_ts=90 +lon_0=10 ' '+k={0:10.8f} +x_0=0 +y_0=0 +a=6370040 +b=6370040 ' '+to_meter=1000 +no_defs'.format(scale)) proj_stereo = georef.proj4_to_osr(dwd_string) # create wgs84 projection osr object proj_wgs = osr.SpatialReference() proj_wgs.ImportFromEPSG(4326) # transform radolan polar stereographic projection to wgs84 and wgs84 # to polar stereographic # using osr transformation routines radolan_grid_ll = georef.reproject(self.radolan_grid_xy, projection_source=proj_stereo, projection_target=proj_wgs) radolan_grid_xy = georef.reproject(self.radolan_grid_ll, projection_source=proj_wgs, projection_target=proj_stereo) # check source and target arrays for equality self.assertTrue(np.allclose(radolan_grid_ll, self.radolan_grid_ll)) self.assertTrue(np.allclose(radolan_grid_xy, self.radolan_grid_xy))
def test_get_radolan_grid_equality(self): # create radolan projection osr object scale = (1. + np.sin(np.radians(60.))) / (1. + np.sin(np.radians(90.))) dwd_string = ('+proj=stere +lat_0=90 +lat_ts=90 +lon_0=10 ' '+k={0:10.8f} +x_0=0 +y_0=0 +a=6370040 +b=6370040 ' '+to_meter=1000 +no_defs'.format(scale)) proj_stereo = georef.proj4_to_osr(dwd_string) # create wgs84 projection osr object proj_wgs = osr.SpatialReference() proj_wgs.ImportFromEPSG(4326) # transform radolan polar stereographic projection to wgs84 and wgs84 # to polar stereographic # using osr transformation routines radolan_grid_ll = georef.reproject(self.radolan_grid_xy, projection_source=proj_stereo, projection_target=proj_wgs) radolan_grid_xy = georef.reproject(self.radolan_grid_ll, projection_source=proj_wgs, projection_target=proj_stereo) # check source and target arrays for equality self.assertTrue(np.allclose(radolan_grid_ll, self.radolan_grid_ll)) self.assertTrue(np.allclose(radolan_grid_xy, self.radolan_grid_xy)) radolan_grid_xy = georef.get_radolan_grid(900, 900) radolan_grid_ll = georef.get_radolan_grid(900, 900, wgs84=True) # check source and target arrays for equality self.assertTrue(np.allclose(radolan_grid_ll, self.radolan_grid_ll)) self.assertTrue(np.allclose(radolan_grid_xy, self.radolan_grid_xy))
def test_reproject(self): proj_gk = osr.SpatialReference() proj_gk.ImportFromEPSG(31466) proj_wgs84 = osr.SpatialReference() proj_wgs84.ImportFromEPSG(4326) x, y = georef.reproject(7., 53., projection_source=proj_wgs84, projection_target=proj_gk) lon, lat = georef.reproject(x, y, projection_source=proj_gk, projection_target=proj_wgs84) self.assertAlmostEqual(lon, 7.0) self.assertAlmostEqual(lat, 53.0)
def test_geoid_to_ellipsoid(self): coords = np.array([[5.0, 50.0, 300.0], [2, 54, 300], [50, 5, 300]]) geoid = georef.get_earth_projection("geoid") ellipsoid = georef.get_earth_projection("ellipsoid") newcoords = georef.reproject( coords, projection_source=geoid, projection_target=ellipsoid ) assert np.any(np.not_equal(coords[..., 2], newcoords[..., 2])) newcoords = georef.reproject( newcoords, projection_source=ellipsoid, projection_target=geoid ) np.testing.assert_allclose(coords, newcoords)
def ex_coord(): pvol = io.read_OPERA_hdf5(os.path.dirname(__file__) + '/' + 'data/20130429043000.rad.bewid.pvol.dbzh.scan1.hdf') # Count the number of dataset ntilt = 1 for i in range(100): try: pvol["dataset%d/what" % ntilt] ntilt += 1 except Exception: ntilt -= 1 break nrays = int(pvol["dataset1/where"]["nrays"]) nbins = int(pvol["dataset1/where"]["nbins"]) rscale = int(pvol["dataset1/where"]["rscale"]) coord = np.empty((ntilt, nrays, nbins, 3)) for t in range(ntilt): elangle = pvol["dataset%d/where" % (t + 1)]["elangle"] coord[t, ...] = georef.sweep_centroids(nrays, rscale, nbins, elangle) ascale = math.pi / nrays sitecoords = (pvol["where"]["lon"], pvol["where"]["lat"], pvol["where"]["height"]) proj_radar = georef.create_osr("aeqd", lat_0=pvol["where"]["lat"], lon_0=pvol["where"]["lon"]) radius = georef.get_earth_radius(pvol["where"]["lat"], proj_radar) lon, lat, height = georef.polar2lonlatalt_n(coord[..., 0], np.degrees(coord[..., 1]), coord[..., 2], sitecoords, re=radius, ke=4. / 3.) x, y = georef.reproject(lon, lat, projection_target=proj_radar) test = x[0, 90, 0:960:60] print(test)
def make_3d_grid(sitecoords, proj, maxrange, maxalt, horiz_res, vert_res, minalt=0.): """Generate Cartesian coordinates for a regular 3-D grid based on \ radar specs. Parameters ---------- sitecoords : tuple Radar location coordinates in lon, lat proj : object GDAL OSR Spatial Reference Object describing projection maxrange : float maximum radar range (same unit as SRS defined by ``proj``, typically meters) maxalt : float maximum altitude to which the 3-d grid should extent (meters) horiz_res : float horizontal resolution of the 3-d grid (same unit as SRS defined by ``proj``, typically meters) vert_res : float vertical resolution of the 3-d grid (meters) Keyword Arguments ----------------- minalt : float minimum altitude to which the 3-d grid should extent (meters) Returns ------- output : :class:`numpy:numpy.ndarray`, tuple float array of shape (num grid points, 3), a tuple of 3 representing the grid shape """ center = georef.reproject(sitecoords[0], sitecoords[1], projection_target=proj) # minz = sitecoords[2] llx = center[0] - maxrange lly = center[1] - maxrange x = np.arange(llx, llx + 2 * maxrange + horiz_res, horiz_res) y = np.arange(lly, lly + 2 * maxrange + horiz_res, horiz_res) z = np.arange(minalt, maxalt + vert_res, vert_res) xyz = util.gridaspoints(z, y, x) shape = (len(z), len(y), len(x)) return xyz, shape
def test_reproject(self): proj_gk = osr.SpatialReference() proj_gk.ImportFromEPSG(31466) proj_wgs84 = osr.SpatialReference() proj_wgs84.ImportFromEPSG(4326) x, y, z = georef.reproject(7., 53., 0., projection_source=proj_wgs84, projection_target=proj_gk) lon, lat = georef.reproject(x, y, projection_source=proj_gk, projection_target=proj_wgs84) self.assertAlmostEqual(lon, 7.0) self.assertAlmostEqual(lat, 53.0) lonlat = georef.reproject(np.stack((x, y), axis=-1), projection_source=proj_gk, projection_target=proj_wgs84) self.assertAlmostEqual(lonlat[0], 7.0) self.assertAlmostEqual(lonlat[1], 53.0) self.assertRaises( TypeError, lambda: georef.reproject(np.stack( (x, y, x, y), axis=-1))) lon, lat, alt = georef.reproject(x, y, z, projection_source=proj_gk, projection_target=proj_wgs84) self.assertAlmostEqual(lon, 7., places=5) self.assertAlmostEqual(lat, 53., places=3) self.assertAlmostEqual(alt, 0., places=3) self.assertRaises(TypeError, lambda: georef.reproject(x, y, x, y)) self.assertRaises( TypeError, lambda: georef.reproject([np.arange(10)], [np.arange(11)])) self.assertRaises( TypeError, lambda: georef.reproject([np.arange( 10)], [np.arange(10)], [np.arange(11)]))
def setUp(self): f = 'gpm/2A-CS-151E24S154E30S.GPM.Ku.V7-20170308.20141206-S095002-E095137.004383.V05A.HDF5' # noqa gpm_file = util.get_wradlib_data_file(f) pr_data = read_generic_hdf5(gpm_file) pr_lon = pr_data['NS/Longitude']['data'] pr_lat = pr_data['NS/Latitude']['data'] zenith = pr_data['NS/PRE/localZenithAngle']['data'] wgs84 = georef.get_default_projection() a = wgs84.GetSemiMajor() b = wgs84.GetSemiMinor() rad = georef.proj4_to_osr( ('+proj=aeqd +lon_0={lon:f} ' + '+lat_0={lat:f} +a={a:f} +b={b:f}' + '').format(lon=pr_lon[68, 0], lat=pr_lat[68, 0], a=a, b=b)) pr_x, pr_y = georef.reproject(pr_lon, pr_lat, projection_source=wgs84, projection_target=rad) self.re = georef.get_earth_radius(pr_lat[68, 0], wgs84) * 4. / 3. self.pr_xy = np.dstack((pr_x, pr_y)) self.alpha = zenith self.zt = 407000. self.dr = 125. self.bw_pr = 0.71 self.nbin = 176 self.nray = pr_lon.shape[1] self.pr_out = np.array([[[[-58533.78453556, 124660.60390174], [-58501.33048429, 124677.58873852]], [[-53702.13393133, 127251.83656509], [-53670.98686161, 127268.11882882]]], [[[-56444.00788528, 120205.5374491], [-56411.55421163, 120222.52300741]], [[-51612.2360682, 122796.78620764], [-51581.08938314, 122813.06920719]]]]) self.r_out = np.array( [0., 125., 250., 375., 500., 625., 750., 875., 1000., 1125.]) self.z_out = np.array([ 0., 119.51255112, 239.02510224, 358.53765337, 478.05020449, 597.56275561, 717.07530673, 836.58785786, 956.10040898, 1075.6129601 ])
def ex_georef(): # -------------------------------------------------------------------------- # EXAMPLE 1: Full workflow for georeferencing radar data # 1st step: generate the centroid coordinates of the radar bins # define the polar coordinates and the site coordinates in lat/lon r = np.arange(1, 129) * 1000 az = np.linspace(0, 360, 361)[0:-1] # drs: 51.12527778 ; fbg: 47.87444444 ; tur: 48.58611111 ; muc: 48.3372222 # drs: 13.76972222 ; fbg: 8.005 ; tur: 9.783888889 ; muc: 11.61277778 sitecoords = (9.7839, 48.5861) # these are the polgon vertices of the radar bins polygons = georef.polar2polyvert(r, az, sitecoords) # these are the corresponding centroids cent_lon, cent_lat = georef.polar2centroids(r, az, sitecoords) # plot the vertices and the centroids in one plot fig = pl.figure(figsize=(8, 8)) ax = fig.add_subplot(111) polycoll = mpl.collections.PolyCollection(polygons, closed=True, facecolors='None') ax.add_collection(polycoll, autolim=True) ax.plot(cent_lon, cent_lat, 'r+') ax.axis('tight') pl.title('Zoom in to compare polygons and centroids.') pl.show() # 2nd step: reproject the centroid coordinates to Gauss-Krueger Zone 3 # by using the EPSG-Number 31467 # use it for projecting the centroids to Gauss-Krueger 3 proj_gk3 = georef.epsg_to_osr(31467) x, y = georef.reproject(cent_lon, cent_lat, projection_targe=proj_gk3) # export the projected centroid coordinates # f = open('centroids.tab', 'w') f = 'centroids.tab' # f.write('x\ty\n') np.savetxt(f, np.hstack((x.reshape((-1, 1)), y.reshape((-1, 1)))), fmt='%.2f', header='x\ty', delimiter='\t') # f.close() print('Exit.')
def setUp(self): f = 'gpm/2A-CS-151E24S154E30S.GPM.Ku.V7-20170308.20141206-S095002-E095137.004383.V05A.HDF5' # noqa gpm_file = util.get_wradlib_data_file(f) pr_data = read_generic_hdf5(gpm_file) pr_lon = pr_data['NS/Longitude']['data'] pr_lat = pr_data['NS/Latitude']['data'] zenith = pr_data['NS/PRE/localZenithAngle']['data'] wgs84 = georef.get_default_projection() a = wgs84.GetSemiMajor() b = wgs84.GetSemiMinor() rad = georef.proj4_to_osr(('+proj=aeqd +lon_0={lon:f} ' + '+lat_0={lat:f} +a={a:f} +b={b:f}' + '').format(lon=pr_lon[68, 0], lat=pr_lat[68, 0], a=a, b=b)) pr_x, pr_y = georef.reproject(pr_lon, pr_lat, projection_source=wgs84, projection_target=rad) self.re = georef.get_earth_radius(pr_lat[68, 0], wgs84) * 4. / 3. self.pr_xy = np.dstack((pr_x, pr_y)) self.alpha = zenith self.zt = 407000. self.dr = 125. self.bw_pr = 0.71 self.nbin = 176 self.nray = pr_lon.shape[1] self.pr_out = np.array([[[[-58533.78453556, 124660.60390174], [-58501.33048429, 124677.58873852]], [[-53702.13393133, 127251.83656509], [-53670.98686161, 127268.11882882]]], [[[-56444.00788528, 120205.5374491], [-56411.55421163, 120222.52300741]], [[-51612.2360682, 122796.78620764], [-51581.08938314, 122813.06920719]]]]) self.r_out = np.array([0., 125., 250., 375., 500., 625., 750., 875., 1000., 1125.]) self.z_out = np.array([0., 119.51255112, 239.02510224, 358.53765337, 478.05020449, 597.56275561, 717.07530673, 836.58785786, 956.10040898, 1075.6129601])
def test_reproject(self): proj_gk = osr.SpatialReference() proj_gk.ImportFromEPSG(31466) proj_wgs84 = osr.SpatialReference() proj_wgs84.ImportFromEPSG(4326) x, y, z = georef.reproject(7., 53., 0., projection_source=proj_wgs84, projection_target=proj_gk) lon, lat = georef.reproject(x, y, projection_source=proj_gk, projection_target=proj_wgs84) self.assertAlmostEqual(lon, 7.0) self.assertAlmostEqual(lat, 53.0) lonlat = georef.reproject(np.stack((x, y), axis=-1), projection_source=proj_gk, projection_target=proj_wgs84) self.assertAlmostEqual(lonlat[0], 7.0) self.assertAlmostEqual(lonlat[1], 53.0) self.assertRaises(TypeError, lambda: georef.reproject(np.stack((x, y, x, y), axis=-1))) lon, lat, alt = georef.reproject(x, y, z, projection_source=proj_gk, projection_target=proj_wgs84) self.assertAlmostEqual(lon, 7., places=5) self.assertAlmostEqual(lat, 53., places=3) self.assertAlmostEqual(alt, 0., places=3) self.assertRaises(TypeError, lambda: georef.reproject(x, y, x, y)) self.assertRaises(TypeError, lambda: georef.reproject([np.arange(10)], [np.arange(11)])) self.assertRaises(TypeError, lambda: georef.reproject([np.arange(10)], [np.arange(10)], [np.arange(11)]))
def get_raster_extent(dataset, geo=False, window=True): """Get the coordinates of the 4 corners of the raster dataset Parameters ---------- dataset : gdal.Dataset raster image with georeferencing (GeoTransform at least) geo : bool True to get geographical coordinates window : bool True to get the window containing the corners Returns ------- extent : :class:`numpy:numpy.ndarray` corner coordinates [ul,ll,lr,ur] or window extent [xmin, xmax, ymin, ymax] """ x_size = dataset.RasterXSize y_size = dataset.RasterYSize geotrans = dataset.GetGeoTransform() xmin = geotrans[0] ymax = geotrans[3] xmax = geotrans[0] + geotrans[1] * x_size ymin = geotrans[3] + geotrans[5] * y_size extent = np.array([[xmin, ymax], [xmin, ymin], [xmax, ymin], [xmax, ymax]]) if geo: projection = read_gdal_projection(dataset) extent = georef.reproject(extent, projection_source=projection) if window: x = extent[:, 0] y = extent[:, 1] extent = np.array([x.min(), x.max(), y.min(), y.max()]) return extent
def setUp(self): # read the radar volume scan filename = 'hdf5/20130429043000.rad.bewid.pvol.dbzh.scan1.hdf' filename = util.get_wradlib_data_file(filename) pvol = io.read_opera_hdf5(filename) nrays = int(pvol["dataset1/where"]["nrays"]) nbins = int(pvol["dataset1/where"]["nbins"]) val = pvol["dataset%d/data1/data" % (1)] gain = float(pvol["dataset1/data1/what"]["gain"]) offset = float(pvol["dataset1/data1/what"]["offset"]) self.val = val * gain + offset self.rscale = int(pvol["dataset1/where"]["rscale"]) elangle = pvol["dataset%d/where" % (1)]["elangle"] coord = georef.sweep_centroids(nrays, self.rscale, nbins, elangle) sitecoords = (pvol["where"]["lon"], pvol["where"]["lat"], pvol["where"]["height"]) coord, proj_radar = georef.spherical_to_xyz(coord[..., 0], coord[..., 1], coord[..., 2], sitecoords, re=6370040., ke=4. / 3.) filename = 'hdf5/SAFNWC_MSG3_CT___201304290415_BEL_________.h5' filename = util.get_wradlib_data_file(filename) sat_gdal = io.read_safnwc(filename) val_sat = georef.read_gdal_values(sat_gdal) coord_sat = georef.read_gdal_coordinates(sat_gdal) proj_sat = georef.read_gdal_projection(sat_gdal) coord_sat = georef.reproject(coord_sat, projection_source=proj_sat, projection_target=proj_radar) coord_radar = coord interp = ipol.Nearest(coord_sat[..., 0:2].reshape(-1, 2), coord_radar[..., 0:2].reshape(-1, 2)) self.val_sat = interp(val_sat.ravel()).reshape(val.shape) timelag = 9 * 60 wind = 10 self.error = np.absolute(timelag) * wind
def setUp(self): global skip # setup test grid and catchment lon = 7.071664 lat = 50.730521 r = np.array(range(50, 100 * 1000 + 50, 100)) a = np.array(range(0, 360, 1)) rays = a.shape[0] bins = r.shape[0] # create polar grid polygon vertices in lat,lon radar_ll = georef.polar2polyvert(r, a, (lon, lat)) # create polar grid centroids in lat,lon rlon, rlat = georef.polar2centroids(r, a, (lon, lat)) radar_llc = np.dstack((rlon, rlat)) # setup OSR objects self.proj_gk = osr.SpatialReference() self.proj_gk.ImportFromEPSG(31466) self.proj_ll = osr.SpatialReference() self.proj_ll.ImportFromEPSG(4326) # project ll grids to GK2 self.radar_gk = georef.reproject(radar_ll, projection_source=self.proj_ll, projection_target=self.proj_gk) self.radar_gkc = georef.reproject(radar_llc, projection_source=self.proj_ll, projection_target=self.proj_gk) # reshape self.radar_gk.shape = (rays, bins, 5, 2) self.radar_gkc.shape = (rays, bins, 2) self.box0 = np.array([[2600000., 5630000.], [2600000., 5630100.], [2600100., 5630100.], [2600100., 5630000.], [2600000., 5630000.]]) self.box1 = np.array([[2600100., 5630000.], [2600100., 5630100.], [2600200., 5630100.], [2600200., 5630000.], [2600100., 5630000.]]) self.data = np.array([self.box0, self.box1]) # create catchment bounding box buffer = 5000. bbox = zonalstats.get_bbox(self.data[..., 0], self.data[..., 1]) bbox = dict(left=bbox['left'] - buffer, right=bbox['right'] + buffer, bottom=bbox['bottom'] - buffer, top=bbox['top'] + buffer) mask, shape = zonalstats.mask_from_bbox(self.radar_gkc[..., 0], self.radar_gkc[..., 1], bbox, polar=True) self.radar_gkc = self.radar_gkc[mask, :] self.radar_gk = self.radar_gk[mask] self.zdpoly = zonalstats.ZonalDataPoly(self.radar_gk, self.data, srs=self.proj_gk) # self.zdpoly.dump_vector('test_zdpoly') self.zdpoint = zonalstats.ZonalDataPoint(self.radar_gkc, self.data, srs=self.proj_gk) # self.zdpoint.dump_vector('test_zdpoint') isec_poly0 = np.array([ np.array([[2600000., 5630000.], [2600000., 5630057.83273596], [2600018.65014816, 5630000.], [2600000., 5630000.]]), np.array([[2600000., 5630057.83273596], [2600000., 5630100.], [2600091.80406488, 5630100.], [2600100., 5630074.58501104], [2600100., 5630000.], [2600018.65014816, 5630000.], [2600000., 5630057.83273596]]), np.array([[2600091.80406488, 5630100.], [2600100., 5630100.], [2600100., 5630074.58501104], [2600091.80406488, 5630100.]]) ]) isec_poly1 = np.array([ np.array([[2600100., 5630000.], [2600100., 5630074.58501104], [2600124.05249566, 5630000.], [2600100., 5630000.]]), np.array([[2600100., 5630074.58501104], [2600100., 5630100.], [2600197.20644071, 5630100.], [2600200., 5630091.33737992], [2600200., 5630000.], [2600124.05249566, 5630000.], [2600100., 5630074.58501104]]), np.array([[2600197.20644071, 5630100.], [2600200., 5630100.], [2600200., 5630091.33737992], [2600197.20644071, 5630100.]]) ]) isec_point0 = np.array([[2600062.31245173, 5630031.20266055]]) isec_point1 = np.array([[2600157.8352244, 5630061.85098382]]) self.isec_poly = np.array([isec_poly0, isec_poly1]) self.isec_point = np.array([isec_point0, isec_point1])
def setUp(self): global skip # setup test grid and catchment lon = 7.071664 lat = 50.730521 r = np.array(range(50, 100 * 1000 + 50, 100)) a = np.array(range(0, 360, 1)) rays = a.shape[0] bins = r.shape[0] # setup OSR objects self.proj_gk = osr.SpatialReference() self.proj_gk.ImportFromEPSG(31466) self.proj_ll = osr.SpatialReference() self.proj_ll.ImportFromEPSG(4326) # create polar grid polygon vertices in lat,lon radar_ll = georef.spherical_to_polyvert(r, a, 0, (lon, lat), proj=self.proj_ll)[..., 0:2] # create polar grid centroids in lat,lon coords = georef.spherical_to_centroids(r, a, 0, (lon, lat), proj=self.proj_ll) radar_llc = coords[..., 0:2] # project ll grids to GK2 self.radar_gk = georef.reproject(radar_ll, projection_source=self.proj_ll, projection_target=self.proj_gk) self.radar_gkc = georef.reproject(radar_llc, projection_source=self.proj_ll, projection_target=self.proj_gk) # reshape self.radar_gk.shape = (rays, bins, 5, 2) self.radar_gkc.shape = (rays, bins, 2) self.box0 = np.array([[2600000., 5630000.], [2600000., 5630100.], [2600100., 5630100.], [2600100., 5630000.], [2600000., 5630000.]]) self.box1 = np.array([[2600100., 5630000.], [2600100., 5630100.], [2600200., 5630100.], [2600200., 5630000.], [2600100., 5630000.]]) self.data = np.array([self.box0, self.box1]) # create catchment bounding box buffer = 5000. bbox = zonalstats.get_bbox(self.data[..., 0], self.data[..., 1]) bbox = dict(left=bbox['left'] - buffer, right=bbox['right'] + buffer, bottom=bbox['bottom'] - buffer, top=bbox['top'] + buffer) mask, shape = zonalstats.mask_from_bbox(self.radar_gkc[..., 0], self.radar_gkc[..., 1], bbox, polar=True) self.radar_gkc = self.radar_gkc[mask, :] self.radar_gk = self.radar_gk[mask] self.zdpoly = zonalstats.ZonalDataPoly(self.radar_gk, self.data, srs=self.proj_gk) # self.zdpoly.dump_vector('test_zdpoly') self.zdpoint = zonalstats.ZonalDataPoint(self.radar_gkc, self.data, srs=self.proj_gk) # self.zdpoint.dump_vector('test_zdpoint') isec_poly0 = np.array([np.array([[2600000., 5630000.], [2600000., 5630100.], [2600009.61157242, 5630100.], [2600041.77844048, 5630000.], [2600000., 5630000.]]), np.array([[2600009.61157242, 5630100.], [2600100., 5630100.], [2600100., 5630000.], [2600041.77844048, 5630000.], [2600009.61157242, 5630100.]]), np.array([[2600091.80406488, 5630100.], [2600100., 5630100.], [2600100., 5630074.58501104], [2600091.80406488, 5630100.]])]) isec_poly1 = np.array([np.array([[2600100., 5630000.], [2600100., 5630100.], [2600114.66582085, 5630100.], [2600146.83254704, 5630000.], [2600100., 5630000.]]), np.array([[2600114.66582085, 5630100.], [2600200., 5630100.], [2600200., 5630000.], [2600146.83254704, 5630000.], [2600114.66582085, 5630100.]]), np.array([[2600197.20644071, 5630100.], [2600200., 5630100.], [2600200., 5630091.33737992], [2600197.20644071, 5630100.]])]) isec_point0 = np.array([[2600077.2899581, 5630056.0874306]]) isec_point1 = np.array([[2600172.498418, 5630086.7127034]]) self.isec_poly = np.array([isec_poly0, isec_poly1]) self.isec_point = np.array([isec_point0, isec_point1])
def setUp(self): global skip # setup test grid and catchment lon = 7.071664 lat = 50.730521 r = np.array(range(50, 100 * 1000 + 50, 100)) a = np.array(range(0, 360, 1)) rays = a.shape[0] bins = r.shape[0] # setup OSR objects self.proj_gk = osr.SpatialReference() self.proj_gk.ImportFromEPSG(31466) self.proj_ll = osr.SpatialReference() self.proj_ll.ImportFromEPSG(4326) # create polar grid polygon vertices in lat,lon radar_ll = georef.spherical_to_polyvert(r, a, 0, (lon, lat), proj=self.proj_ll)[..., 0:2] # create polar grid centroids in lat,lon coords = georef.spherical_to_centroids(r, a, 0, (lon, lat), proj=self.proj_ll) radar_llc = coords[..., 0:2] # project ll grids to GK2 self.radar_gk = georef.reproject(radar_ll, projection_source=self.proj_ll, projection_target=self.proj_gk) self.radar_gkc = georef.reproject(radar_llc, projection_source=self.proj_ll, projection_target=self.proj_gk) # reshape self.radar_gk.shape = (rays, bins, 5, 2) self.radar_gkc.shape = (rays, bins, 2) self.box0 = np.array([[2600000., 5630000.], [2600000., 5630100.], [2600100., 5630100.], [2600100., 5630000.], [2600000., 5630000.]]) self.box1 = np.array([[2600100., 5630000.], [2600100., 5630100.], [2600200., 5630100.], [2600200., 5630000.], [2600100., 5630000.]]) self.data = np.array([self.box0, self.box1]) # create catchment bounding box buffer = 5000. bbox = zonalstats.get_bbox(self.data[..., 0], self.data[..., 1]) bbox = dict(left=bbox['left'] - buffer, right=bbox['right'] + buffer, bottom=bbox['bottom'] - buffer, top=bbox['top'] + buffer) mask, shape = zonalstats.mask_from_bbox(self.radar_gkc[..., 0], self.radar_gkc[..., 1], bbox, polar=True) self.radar_gkc = self.radar_gkc[mask, :] self.radar_gk = self.radar_gk[mask] self.zdpoly = zonalstats.ZonalDataPoly(self.radar_gk, self.data, srs=self.proj_gk) # self.zdpoly.dump_vector('test_zdpoly') self.zdpoint = zonalstats.ZonalDataPoint(self.radar_gkc, self.data, srs=self.proj_gk) # self.zdpoint.dump_vector('test_zdpoint') isec_poly0 = np.array([ np.array([[2600000., 5630000.], [2600000., 5630100.], [2600009.61157242, 5630100.], [2600041.77844048, 5630000.], [2600000., 5630000.]]), np.array([[2600009.61157242, 5630100.], [2600100., 5630100.], [2600100., 5630000.], [2600041.77844048, 5630000.], [2600009.61157242, 5630100.]]), np.array([[2600091.80406488, 5630100.], [2600100., 5630100.], [2600100., 5630074.58501104], [2600091.80406488, 5630100.]]) ]) isec_poly1 = np.array([ np.array([[2600100., 5630000.], [2600100., 5630100.], [2600114.66582085, 5630100.], [2600146.83254704, 5630000.], [2600100., 5630000.]]), np.array([[2600114.66582085, 5630100.], [2600200., 5630100.], [2600200., 5630000.], [2600146.83254704, 5630000.], [2600114.66582085, 5630100.]]), np.array([[2600197.20644071, 5630100.], [2600200., 5630100.], [2600200., 5630091.33737992], [2600197.20644071, 5630100.]]) ]) isec_point0 = np.array([[2600077.2899581, 5630056.0874306]]) isec_point1 = np.array([[2600172.498418, 5630086.7127034]]) self.isec_poly = np.array([isec_poly0, isec_poly1]) self.isec_point = np.array([isec_point0, isec_point1])
class TestFilterCloudtype: if has_data: # read the radar volume scan filename = "hdf5/20130429043000.rad.bewid.pvol.dbzh.scan1.hdf" filename = util.get_wradlib_data_file(filename) pvol = io.read_opera_hdf5(filename) nrays = int(pvol["dataset1/where"]["nrays"]) nbins = int(pvol["dataset1/where"]["nbins"]) val = pvol["dataset%d/data1/data" % (1)] gain = float(pvol["dataset1/data1/what"]["gain"]) offset = float(pvol["dataset1/data1/what"]["offset"]) val = val * gain + offset rscale = int(pvol["dataset1/where"]["rscale"]) elangle = pvol["dataset%d/where" % (1)]["elangle"] coord = georef.sweep_centroids(nrays, rscale, nbins, elangle) sitecoords = ( pvol["where"]["lon"], pvol["where"]["lat"], pvol["where"]["height"], ) coord, proj_radar = georef.spherical_to_xyz( coord[..., 0], coord[..., 1], coord[..., 2], sitecoords, re=6370040.0, ke=4.0 / 3.0, ) filename = "hdf5/SAFNWC_MSG3_CT___201304290415_BEL_________.h5" filename = util.get_wradlib_data_file(filename) sat_gdal = io.read_safnwc(filename) val_sat = georef.read_gdal_values(sat_gdal) coord_sat = georef.read_gdal_coordinates(sat_gdal) proj_sat = georef.read_gdal_projection(sat_gdal) coord_sat = georef.reproject(coord_sat, projection_source=proj_sat, projection_target=proj_radar) coord_radar = coord interp = ipol.Nearest(coord_sat[..., 0:2].reshape(-1, 2), coord_radar[..., 0:2].reshape(-1, 2)) val_sat = interp(val_sat.ravel()).reshape(val.shape) timelag = 9 * 60 wind = 10 error = np.absolute(timelag) * wind @requires_data def test_filter_cloudtype(self): nonmet = clutter.filter_cloudtype(self.val, self.val_sat, scale=self.rscale, smoothing=self.error) nclutter = np.sum(nonmet) assert nclutter == 8141 nonmet = clutter.filter_cloudtype(self.val, self.val_sat, scale=self.rscale, smoothing=self.error, low=True) nclutter = np.sum(nonmet) assert nclutter == 17856
class TestZonalData: global skip # setup test grid and catchment lon = 7.071664 lat = 50.730521 r = np.array(range(50, 100 * 1000 + 50, 100)) a = np.array(range(0, 360, 1)) rays = a.shape[0] bins = r.shape[0] # setup OSR objects proj_gk = osr.SpatialReference() proj_gk.ImportFromEPSG(31466) proj_ll = osr.SpatialReference() proj_ll.ImportFromEPSG(4326) # create polar grid polygon vertices in lat,lon radar_ll = georef.spherical_to_polyvert(r, a, 0, (lon, lat), proj=proj_ll)[..., 0:2] # create polar grid centroids in lat,lon coords = georef.spherical_to_centroids(r, a, 0, (lon, lat), proj=proj_ll) radar_llc = coords[..., 0:2] # project ll grids to GK2 radar_gk = georef.reproject(radar_ll, projection_source=proj_ll, projection_target=proj_gk) radar_gkc = georef.reproject(radar_llc, projection_source=proj_ll, projection_target=proj_gk) # reshape radar_gk.shape = (rays, bins, 5, 2) radar_gkc.shape = (rays, bins, 2) box0 = np.array([ [2600000.0, 5630000.0], [2600000.0, 5630100.0], [2600100.0, 5630100.0], [2600100.0, 5630000.0], [2600000.0, 5630000.0], ]) box1 = np.array([ [2600100.0, 5630000.0], [2600100.0, 5630100.0], [2600200.0, 5630100.0], [2600200.0, 5630000.0], [2600100.0, 5630000.0], ]) data = np.array([box0, box1]) # create catchment bounding box buffer = 5000.0 bbox = zonalstats.get_bbox(data[..., 0], data[..., 1]) bbox = dict( left=bbox["left"] - buffer, right=bbox["right"] + buffer, bottom=bbox["bottom"] - buffer, top=bbox["top"] + buffer, ) mask, shape = zonalstats.mask_from_bbox(radar_gkc[..., 0], radar_gkc[..., 1], bbox, polar=True) radar_gkc = radar_gkc[mask, :] radar_gk = radar_gk[mask] zdpoly = zonalstats.ZonalDataPoly(radar_gk, data, srs=proj_gk) # zdpoly.dump_vector('test_zdpoly') zdpoint = zonalstats.ZonalDataPoint(radar_gkc, data, srs=proj_gk) # zdpoint.dump_vector('test_zdpoint') isec_poly0 = np.array( [ np.array([ [2600000.0, 5630000.0], [2600000.0, 5630100.0], [2600009.61157242, 5630100.0], [2600041.77844048, 5630000.0], [2600000.0, 5630000.0], ]), np.array([ [2600009.61157242, 5630100.0], [2600100.0, 5630100.0], [2600100.0, 5630000.0], [2600041.77844048, 5630000.0], [2600009.61157242, 5630100.0], ]), np.array([ [2600091.80406488, 5630100.0], [2600100.0, 5630100.0], [2600100.0, 5630074.58501104], [2600091.80406488, 5630100.0], ]), ], dtype=object, ) isec_poly1 = np.array( [ np.array([ [2600100.0, 5630000.0], [2600100.0, 5630100.0], [2600114.66582085, 5630100.0], [2600146.83254704, 5630000.0], [2600100.0, 5630000.0], ]), np.array([ [2600114.66582085, 5630100.0], [2600200.0, 5630100.0], [2600200.0, 5630000.0], [2600146.83254704, 5630000.0], [2600114.66582085, 5630100.0], ]), np.array([ [2600197.20644071, 5630100.0], [2600200.0, 5630100.0], [2600200.0, 5630091.33737992], [2600197.20644071, 5630100.0], ]), ], dtype=object, ) isec_point0 = np.array([[2600077.2899581, 5630056.0874306]]) isec_point1 = np.array([[2600172.498418, 5630086.7127034]]) isec_poly = np.array([isec_poly0, isec_poly1]) isec_point = np.array([isec_point0, isec_point1]) def test_srs(self): assert self.zdpoly.srs == self.proj_gk assert self.zdpoint.srs == self.proj_gk def test_isecs(self): # need to iterate over nested array for correct testing for i, ival in enumerate(self.zdpoly.isecs): for k, kval in enumerate(ival): np.testing.assert_allclose(kval.astype(float), self.isec_poly[i, k], rtol=1e-6) np.testing.assert_allclose(self.zdpoint.isecs.astype(float), self.isec_point, rtol=1e-6) def test_get_isec(self): for i in [0, 1]: for k, arr in enumerate(self.zdpoly.get_isec(i)): np.testing.assert_allclose(arr.astype(float), self.isec_poly[i, k], rtol=1e-6) np.testing.assert_allclose(self.zdpoint.get_isec(i).astype(float), self.isec_point[i], rtol=1e-6) def test_get_source_index(self): np.testing.assert_array_equal(self.zdpoly.get_source_index(0), np.array([2254, 2255])) np.testing.assert_array_equal(self.zdpoly.get_source_index(1), np.array([2255, 2256])) np.testing.assert_array_equal(self.zdpoint.get_source_index(0), np.array([2255])) np.testing.assert_array_equal(self.zdpoint.get_source_index(1), np.array([2256]))
def ex_clutter_cloud(): # read the radar volume scan path = os.path.dirname(__file__) + '/' pvol = io.read_OPERA_hdf5( path + 'data/20130429043000.rad.bewid.pvol.dbzh.scan1.hdf') # Count the number of dataset ntilt = 1 for i in range(100): try: pvol["dataset%d/what" % ntilt] ntilt += 1 except Exception: ntilt -= 1 break # Construct radar values nrays = int(pvol["dataset1/where"]["nrays"]) nbins = int(pvol["dataset1/where"]["nbins"]) val = np.empty((ntilt, nrays, nbins)) for t in range(ntilt): val[t, ...] = pvol["dataset%d/data1/data" % (t + 1)] gain = float(pvol["dataset1/data1/what"]["gain"]) offset = float(pvol["dataset1/data1/what"]["offset"]) val = val * gain + offset # Construct radar coordinates rscale = int(pvol["dataset1/where"]["rscale"]) coord = np.empty((ntilt, nrays, nbins, 3)) for t in range(ntilt): elangle = pvol["dataset%d/where" % (t + 1)]["elangle"] coord[t, ...] = georef.sweep_centroids(nrays, rscale, nbins, elangle) ascale = math.pi / nrays sitecoords = (pvol["where"]["lon"], pvol["where"]["lat"], pvol["where"]["height"]) proj_radar = georef.create_osr("aeqd", lat_0=pvol["where"]["lat"], lon_0=pvol["where"]["lon"]) coord[..., 0], coord[..., 1], coord[..., 2] = georef.polar2lonlatalt_n( coord[..., 0], np.degrees(coord[..., 1]), coord[..., 2], sitecoords, re=6370040., ke=4. / 3.) coord = georef.reproject(coord, projection_target=proj_radar) # Construct collocated satellite data sat_gdal = io.read_safnwc( path + 'data/SAFNWC_MSG3_CT___201304290415_BEL_________.h5') val_sat = georef.read_gdal_values(sat_gdal) coord_sat = georef.read_gdal_coordinates(sat_gdal) proj_sat = georef.read_gdal_projection(sat_gdal) coord_sat = georef.reproject(coord_sat, projection_source=proj_sat, projection_target=proj_radar) coord_radar = coord interp = ipol.Nearest(coord_sat[..., 0:2].reshape(-1, 2), coord_radar[..., 0:2].reshape(-1, 2)) val_sat = interp(val_sat.ravel()).reshape(val.shape) # Estimate localisation errors timelag = 9 * 60 wind = 10 error = np.absolute(timelag) * wind # Identify clutter based on collocated cloudtype clutter = cl.filter_cloudtype(val[0, ...], val_sat[0, ...], scale=rscale, smoothing=error) # visualize the result plt.figure() vis.plot_ppi(clutter) plt.suptitle('clutter') plt.savefig('clutter_cloud_example_1.png') plt.figure() vis.plot_ppi(val_sat[0, ...]) plt.suptitle('satellite') plt.savefig('clutter_cloud_example_2.png') plt.show()
def setUp(self): global skip # setup test grid and catchment lon = 7.071664 lat = 50.730521 r = np.array(range(50, 100 * 1000 + 50, 100)) a = np.array(range(0, 360, 1)) rays = a.shape[0] bins = r.shape[0] # create polar grid polygon vertices in lat,lon radar_ll = georef.polar2polyvert(r, a, (lon, lat)) # create polar grid centroids in lat,lon rlon, rlat = georef.polar2centroids(r, a, (lon, lat)) radar_llc = np.dstack((rlon, rlat)) # setup OSR objects self.proj_gk = osr.SpatialReference() self.proj_gk.ImportFromEPSG(31466) self.proj_ll = osr.SpatialReference() self.proj_ll.ImportFromEPSG(4326) # project ll grids to GK2 self.radar_gk = georef.reproject(radar_ll, projection_source=self.proj_ll, projection_target=self.proj_gk) self.radar_gkc = georef.reproject(radar_llc, projection_source=self.proj_ll, projection_target=self.proj_gk) # reshape self.radar_gk.shape = (rays, bins, 5, 2) self.radar_gkc.shape = (rays, bins, 2) self.box0 = np.array([[2600000., 5630000.], [2600000., 5630100.], [2600100., 5630100.], [2600100., 5630000.], [2600000., 5630000.]]) self.box1 = np.array([[2600100., 5630000.], [2600100., 5630100.], [2600200., 5630100.], [2600200., 5630000.], [2600100., 5630000.]]) self.data = np.array([self.box0, self.box1]) # create catchment bounding box buffer = 5000. bbox = zonalstats.get_bbox(self.data[..., 0], self.data[..., 1]) bbox = dict(left=bbox['left'] - buffer, right=bbox['right'] + buffer, bottom=bbox['bottom'] - buffer, top=bbox['top'] + buffer) mask, shape = zonalstats.mask_from_bbox(self.radar_gkc[..., 0], self.radar_gkc[..., 1], bbox, polar=True) self.radar_gkc = self.radar_gkc[mask, :] self.radar_gk = self.radar_gk[mask] self.zdpoly = zonalstats.ZonalDataPoly(self.radar_gk, self.data, srs=self.proj_gk) # self.zdpoly.dump_vector('test_zdpoly') self.zdpoint = zonalstats.ZonalDataPoint(self.radar_gkc, self.data, srs=self.proj_gk) # self.zdpoint.dump_vector('test_zdpoint') isec_poly0 = np.array([np.array([[2600000., 5630000.], [2600000., 5630057.83273596], [2600018.65014816, 5630000.], [2600000., 5630000.]]), np.array([[2600000., 5630057.83273596], [2600000., 5630100.], [2600091.80406488, 5630100.], [2600100., 5630074.58501104], [2600100., 5630000.], [2600018.65014816, 5630000.], [2600000., 5630057.83273596]]), np.array([[2600091.80406488, 5630100.], [2600100., 5630100.], [2600100., 5630074.58501104], [2600091.80406488, 5630100.]])]) isec_poly1 = np.array([np.array([[2600100., 5630000.], [2600100., 5630074.58501104], [2600124.05249566, 5630000.], [2600100., 5630000.]]), np.array([[2600100., 5630074.58501104], [2600100., 5630100.], [2600197.20644071, 5630100.], [2600200., 5630091.33737992], [2600200., 5630000.], [2600124.05249566, 5630000.], [2600100., 5630074.58501104]]), np.array([[2600197.20644071, 5630100.], [2600200., 5630100.], [2600200., 5630091.33737992], [2600197.20644071, 5630100.]])]) isec_point0 = np.array([[2600062.31245173, 5630031.20266055]]) isec_point1 = np.array([[2600157.8352244, 5630061.85098382]]) self.isec_poly = np.array([isec_poly0, isec_poly1]) self.isec_point = np.array([isec_point0, isec_point1])
def test_reproject(self): proj_gk = osr.SpatialReference() proj_gk.ImportFromEPSG(31466) proj_wgs84 = osr.SpatialReference() proj_wgs84.ImportFromEPSG(4326) x, y, z = georef.reproject( 7.0, 53.0, 0.0, projection_source=proj_wgs84, projection_target=proj_gk ) lon, lat = georef.reproject( x, y, projection_source=proj_gk, projection_target=proj_wgs84 ) assert pytest.approx(lon) == 7.0 assert pytest.approx(lat) == 53.0 lonlat = georef.reproject( np.stack((x, y), axis=-1), projection_source=proj_gk, projection_target=proj_wgs84, ) assert pytest.approx(lonlat[0]) == 7.0 assert pytest.approx(lonlat[1]) == 53.0 with pytest.raises(TypeError): georef.reproject(np.stack((x, y, x, y), axis=-1)) lon, lat, alt = georef.reproject( x, y, z, projection_source=proj_gk, projection_target=proj_wgs84 ) assert pytest.approx(lon, abs=1e-5) == 7.0 assert pytest.approx(lat, abs=1e-3) == 53.0 assert pytest.approx(alt, abs=1e-3) == 0.0 with pytest.raises(TypeError): georef.reproject(x, y, x, y) with pytest.raises(TypeError): georef.reproject([np.arange(10)], [np.arange(11)]) with pytest.raises(TypeError): georef.reproject([np.arange(10)], [np.arange(10)], [np.arange(11)])
class TestSatellite: f = "gpm/2A-CS-151E24S154E30S.GPM.Ku.V7-20170308.20141206-S095002-E095137.004383.V05A.HDF5" # noqa gpm_file = util.get_wradlib_data_file(f) pr_data = wradlib.io.read_generic_hdf5(gpm_file) pr_lon = pr_data["NS/Longitude"]["data"] pr_lat = pr_data["NS/Latitude"]["data"] zenith = pr_data["NS/PRE/localZenithAngle"]["data"] wgs84 = georef.get_default_projection() a = wgs84.GetSemiMajor() b = wgs84.GetSemiMinor() rad = georef.proj4_to_osr( ("+proj=aeqd +lon_0={lon:f} " + "+lat_0={lat:f} +a={a:f} +b={b:f}" + "").format( lon=pr_lon[68, 0], lat=pr_lat[68, 0], a=a, b=b ) ) pr_x, pr_y = georef.reproject( pr_lon, pr_lat, projection_source=wgs84, projection_target=rad ) re = georef.get_earth_radius(pr_lat[68, 0], wgs84) * 4.0 / 3.0 pr_xy = np.dstack((pr_x, pr_y)) alpha = zenith zt = 407000.0 dr = 125.0 bw_pr = 0.71 nbin = 176 nray = pr_lon.shape[1] pr_out = np.array( [ [ [ [-58533.78453556, 124660.60390174], [-58501.33048429, 124677.58873852], ], [ [-53702.13393133, 127251.83656509], [-53670.98686161, 127268.11882882], ], ], [ [ [-56444.00788528, 120205.5374491], [-56411.55421163, 120222.52300741], ], [ [-51612.2360682, 122796.78620764], [-51581.08938314, 122813.06920719], ], ], ] ) r_out = np.array( [0.0, 125.0, 250.0, 375.0, 500.0, 625.0, 750.0, 875.0, 1000.0, 1125.0] ) z_out = np.array( [ 0.0, 119.51255112, 239.02510224, 358.53765337, 478.05020449, 597.56275561, 717.07530673, 836.58785786, 956.10040898, 1075.6129601, ] ) def test_correct_parallax(self): xy, r, z = georef.correct_parallax(self.pr_xy, self.nbin, self.dr, self.alpha) pr_out = np.array( [ [ [ [-16582.50734831, 35678.47219358], [-16547.94607589, 35696.40777009], ], [ [-11742.02016667, 38252.32622057], [-11708.84553319, 38269.52268457], ], ], [ [ [-14508.62005182, 31215.98689653], [-14474.05905935, 31233.92329553], ], [ [-9667.99183645, 33789.86576047], [-9634.81750708, 33807.06305397], ], ], ] ) r_out = np.array( [0.0, 125.0, 250.0, 375.0, 500.0, 625.0, 750.0, 875.0, 1000.0, 1125.0] ) z_out = np.array( [ 0.0, 118.78164113, 237.56328225, 356.34492338, 475.1265645, 593.90820563, 712.68984675, 831.47148788, 950.25312901, 1069.03477013, ] ) np.testing.assert_allclose(xy[60:62, 0:2, 0:2, :], pr_out, rtol=1e-12) np.testing.assert_allclose(r[0:10], r_out, rtol=1e-12) np.testing.assert_allclose(z[0, 0, 0:10], z_out, rtol=1e-10) def test_dist_from_orbit(self): beta = abs(-17.04 + np.arange(self.nray) * self.bw_pr) xy, r, z = georef.correct_parallax(self.pr_xy, self.nbin, self.dr, self.alpha) dists = georef.dist_from_orbit(self.zt, self.alpha, beta, r, re=self.re) bd = np.array( [ 426553.58667772, 426553.50342119, 426553.49658156, 426553.51025979, 426553.43461609, 426553.42515894, 426553.46559985, 426553.37020786, 426553.44407286, 426553.42173696, ] ) sd = np.array( [ 426553.58667772, 424895.63462839, 423322.25176564, 421825.47714885, 420405.9414294, 419062.44208923, 417796.86827302, 416606.91482435, 415490.82582636, 414444.11587979, ] ) np.testing.assert_allclose(dists[0:10, 0, 0], bd, rtol=1e-12) np.testing.assert_allclose(dists[0, 0:10, 0], sd, rtol=1e-12)
def plot_scan_strategy( ranges, elevs, sitecoords, beamwidth=1.0, vert_res=500.0, maxalt=10000.0, range_res=None, maxrange=None, units="m", terrain=None, az=0.0, cg=False, ax=111, cmap="tab10", ): """Plot the vertical scanning strategy. Parameters ---------- ranges : sequence of floats array of ranges elevs : sequence of floats elevation angles sitecoords : sequence of floats radar site coordinates (longitude, latitude, altitude) beamwidth : float 3dB width of the radar beam, defaults to 1.0 deg. vert_res : float Vertical resolution in [m]. maxalt : float Maximum altitude in [m]. range_res : float Horizontal resolution in [m]. maxrange : float Maximum range in [m]. units : str Units to plot in, can be 'm' or 'km'. Defaults to 'm'. terrain : bool | :class:`numpy:numpy.ndarray` If True, downloads srtm data and add orography for given `az`. az : float Used to specify azimuth for terrain plots. cg : bool If True, plot in curvelinear grid, defaults to False (cartesian grid). ax : :class:`matplotlib:matplotlib.axes.Axes` | matplotlib grid definition If matplotlib Axes object is given, the scan strategy will be plotted into this axes object. If matplotlib grid definition is given (nrows/ncols/plotnumber), axis are created in the specified place. Defaults to '111', only one subplot/axis. cmap : str matplotlib colormap string. Returns ------- ax : :class:`matplotlib:matplotlib.axes.Axes` | matplotlib toolkit axisartist Axes object matplotlib Axes or curvelinear Axes (r-theta-grid) depending on keyword argument `cg`. """ if units == "m": scale = 1.0 elif units == "km": scale = 1000.0 else: raise ValueError( f"wradlib: unknown value for keyword argument units={units}") az = np.array([az]) if maxrange is None: maxrange = ranges.max() xyz, rad = georef.spherical_to_xyz(ranges, az, elevs, sitecoords, squeeze=True) add_title = "" if terrain is True: add_title += f" - Azimuth {az[0]}°" ll = georef.reproject(xyz, projection_source=rad) # (down-)load srtm data ds = io.get_srtm( [ ll[..., 0].min(), ll[..., 0].max(), ll[..., 1].min(), ll[..., 1].max() ], download={}, ) rastervalues, rastercoords, proj = georef.extract_raster_dataset( ds, nodata=-32768.0) # map rastervalues to polar grid points terrain = ipol.cart_to_irregular_spline(rastercoords, rastervalues, ll[-1, ..., :2], order=3, prefilter=False) if ax == 111: fig = pl.figure(figsize=(16, 8)) else: fig = pl.gcf() legend2 = {} if cg is True: ax, caax, paax = create_cg(fig=fig, subplot=ax, rot=0, scale=1) # for nice plotting we assume earth_radius = 6370000 m er = 6370000 # calculate beam_height and arc_distance for ke=1 # means line of sight ade = georef.bin_distance(ranges, 0, sitecoords[2], re=er, ke=1.0) nn0 = np.zeros_like(ranges) ecp = nn0 + er # theta (arc_distance sector angle) thetap = -np.degrees(ade / er) + 90.0 # zero degree elevation with standard refraction (bes, ) = paax.plot(thetap, ecp, "-k", linewidth=3, label="_MSL", zorder=3) legend2["MSL"] = bes if terrain is not None: paax.fill_between(thetap, ecp.min() - 2500, ecp + terrain, color="0.75", zorder=2) # axes layout ax.set_xlim(0, np.max(ade)) ax.set_ylim([ecp.min() - maxalt / 5, ecp.max() + maxalt]) caax.grid(True, axis="x") ax.grid(True, axis="y") ax.axis["top"].toggle(all=False) gh = ax.get_grid_helper() yrange = maxalt + maxalt / 5 nbins = ((yrange // vert_res) * 2 + 1) // np.sqrt(2) gh.grid_finder.grid_locator2._nbins = nbins else: ax = fig.add_subplot(ax) paax = ax caax = ax if terrain is not None: paax.fill_between(ranges, 0, terrain, color="0.75", zorder=2) ax.set_xlim(0.0, maxrange) ax.set_ylim(0.0, maxalt) ax.grid() # axes ticks and formatting if range_res is not None: xloc = range_res caax.xaxis.set_major_locator(MultipleLocator(xloc)) else: caax.xaxis.set_major_locator(MaxNLocator()) yloc = vert_res caax.yaxis.set_major_locator(MultipleLocator(yloc)) import functools hform = functools.partial(_height_formatter, cg=cg, scale=scale) rform = functools.partial(_range_formatter, scale=scale) caax.yaxis.set_major_formatter(FuncFormatter(hform)) caax.xaxis.set_major_formatter(FuncFormatter(rform)) # color management from cycler import cycler NUM_COLORS = len(elevs) cmap = pl.get_cmap(cmap) if cmap.N >= 256: colors = [cmap(1.0 * i / NUM_COLORS) for i in range(NUM_COLORS)] else: colors = cmap.colors cycle = cycler(color=colors) paax.set_prop_cycle(cycle) # plot beams for i, el in enumerate(elevs): alt = xyz[i, ..., 2] groundrange = np.sqrt(xyz[i, ..., 0]**2 + xyz[i, ..., 1]**2) if cg: plrange = thetap plalt = ecp + alt beamradius = util.half_power_radius(ranges, beamwidth) else: plrange = np.insert(groundrange, 0, 0) plalt = np.insert(alt, 0, sitecoords[2]) beamradius = util.half_power_radius(plrange, beamwidth) _, center, edge = _plot_beam(plrange, plalt, beamradius, label=f"{el:4.1f}°", ax=paax) # legend 1 handles, labels = ax.get_legend_handles_labels() leg1 = ax.legend( handles, labels, prop={"family": "monospace"}, loc="upper left", bbox_to_anchor=(1.04, 1), borderaxespad=0, ) # legend 2 legend2["Center"] = center[0] legend2["3 dB"] = edge[0] ax.legend( legend2.values(), legend2.keys(), prop={"family": "monospace"}, loc="lower left", bbox_to_anchor=(1.04, 0), borderaxespad=0, ) # add legend 1 ax.add_artist(leg1) # set axes labels ax.set_title(f"Radar Scan Strategy - {sitecoords}" + add_title) caax.set_xlabel(f"Range ({units})") caax.set_ylabel(f"Altitude ({units})") return ax
def reproject_raster_dataset(src_ds, **kwargs): """Reproject/Resample given dataset according to keyword arguments Parameters ---------- src_ds : gdal.Dataset raster image with georeferencing (GeoTransform at least) Keyword Arguments ----------------- spacing : float float or tuple of two floats pixel spacing of destination dataset, same unit as pixel coordinates size : int tuple of two ints X/YRasterSize of destination dataset resample : GDALResampleAlg defaults to GRA_Bilinear GRA_NearestNeighbour = 0, GRA_Bilinear = 1, GRA_Cubic = 2, GRA_CubicSpline = 3, GRA_Lanczos = 4, GRA_Average = 5, GRA_Mode = 6, GRA_Max = 8, GRA_Min = 9, GRA_Med = 10, GRA_Q1 = 11, GRA_Q3 = 12 projection_target : osr object destination dataset projection, defaults to None align : bool or Point If False, there is no destination grid aligment. If True, aligns the destination grid to the next integer multiple of destination grid. If Point (tuple, list of upper-left x,y-coordinate), the destination grid is aligned to this point. Returns ------- dst_ds : gdal.Dataset reprojected/resampled raster dataset """ # checking kwargs spacing = kwargs.pop('spacing', None) size = kwargs.pop('size', None) resample = kwargs.pop('resample', gdal.GRA_Bilinear) src_srs = kwargs.pop('projection_source', None) dst_srs = kwargs.pop('projection_target', None) align = kwargs.pop('align', False) # Get the GeoTransform vector src_geo = src_ds.GetGeoTransform() x_size = src_ds.RasterXSize y_size = src_ds.RasterYSize # get extent ulx = src_geo[0] uly = src_geo[3] lrx = src_geo[0] + src_geo[1] * x_size lry = src_geo[3] + src_geo[5] * y_size extent = np.array([[[ulx, uly], [lrx, uly]], [[ulx, lry], [lrx, lry]]]) if dst_srs: src_srs = osr.SpatialReference() src_srs.ImportFromWkt(src_ds.GetProjection()) # Transformation extent = georef.reproject(extent, projection_source=src_srs, projection_target=dst_srs) # wkt needed src_srs = src_srs.ExportToWkt() dst_srs = dst_srs.ExportToWkt() (ulx, uly, urx, ury, llx, lly, lrx, lry) = tuple(list(extent.flatten().tolist())) # align grid to destination raster or UL-corner point if align: try: ulx, uly = align except TypeError: pass ulx = int(max(np.floor(ulx), np.floor(llx))) uly = int(min(np.ceil(uly), np.ceil(ury))) lrx = int(min(np.ceil(lrx), np.ceil(urx))) lry = int(max(np.floor(lry), np.floor(lly))) # calculate cols/rows or xspacing/yspacing if spacing: try: x_ps, y_ps = spacing except TypeError: x_ps = spacing y_ps = spacing cols = int(abs(lrx - ulx) / x_ps) rows = int(abs(uly - lry) / y_ps) elif size: cols, rows = size x_ps = x_size * src_geo[1] / cols y_ps = y_size * abs(src_geo[5]) / rows else: raise NameError("Whether keyword 'spacing' or 'size' must be given") # create destination in-memory raster mem_drv = gdal.GetDriverByName('MEM') # and set RasterSize according ro cols/rows dst_ds = mem_drv.Create('', cols, rows, 1, gdal.GDT_Float32) # Create the destination GeoTransform with changed x/y spacing dst_geo = (ulx, x_ps, src_geo[2], uly, src_geo[4], -y_ps) # apply GeoTransform to destination dataset dst_ds.SetGeoTransform(dst_geo) # apply Projection to destination dataset if dst_srs is not None: dst_ds.SetProjection(dst_srs) # nodata handling, need to initialize dst_ds with nodata src_band = src_ds.GetRasterBand(1) nodata = src_band.GetNoDataValue() dst_band = dst_ds.GetRasterBand(1) if nodata is not None: dst_band.SetNoDataValue(nodata) dst_band.WriteArray(np.ones((rows, cols)) * nodata) dst_band.FlushCache() # resample and reproject dataset gdal.ReprojectImage(src_ds, dst_ds, src_srs, dst_srs, resample) return dst_ds
def plot_ppi_crosshair(site, ranges, angles=None, proj=None, elev=0., ax=None, **kwargs): """Plots a Crosshair for a Plan Position Indicator (PPI). Parameters ---------- site : tuple Tuple of coordinates of the radar site. If `proj` is not used, this simply becomes the offset for the origin of the coordinate system. If `proj` is used, values must be given as (longitude, latitude, altitude) tuple of geographical coordinates. ranges : list List of ranges, for which range circles should be drawn. If ``proj`` is None arbitrary units may be used (such that they fit with the underlying PPI plot. Otherwise the ranges must be given in meters. angles : list List of angles (in degrees) for which straight lines should be drawn. These lines will be drawn starting from the center and until the largest range. proj : osr spatial reference object GDAL OSR Spatial Reference Object describing projection The function will calculate lines and circles according to georeferenced coordinates taking beam propagation, earth's curvature and scale effects due to projection into account. Depending on the projection, crosshair lines might not be straight and range circles might appear elliptical (also check if the aspect of the axes might not also be responsible for this). elev : float or array of same shape as az Elevation angle of the scan or individual azimuths. May improve georeferencing coordinates for larger elevation angles. ax : :class:`matplotlib:matplotlib.axes.Axes` If given, the crosshair will be plotted into this axes object. If None matplotlib's current axes (function gca()) concept will be used to determine the axes. Keyword Arguments ----------------- line : dict dictionary, which will be passed to the crosshair line objects using the standard keyword inheritance mechanism. If not given defaults will be used. circle : dict dictionary, which will be passed to the range circle line objects using the standard keyword inheritance mechanism. If not given defaults will be used. See also -------- :func:`~wradlib.vis.plot_ppi` - plotting a PPI in cartesian coordinates Returns ------- ax : :class:`matplotlib:matplotlib.axes.Axes` The axes object into which the PPI was plotted Examples -------- See :ref:`/notebooks/visualisation/wradlib_plot_ppi_example.ipynb`. """ # check coordinate tuple if site and len(site) < 3: raise ValueError("WRADLIB: `site` need to be a tuple of coordinates " "(longitude, latitude, altitude).") # if we didn't get an axes object, find the current one if ax is None: ax = pl.gca() if angles is None: angles = [0, 90, 180, 270] # set default line keywords linekw = dict(color='gray', linestyle='dashed') # update with user settings linekw.update(kwargs.get('line', {})) # set default circle keywords circkw = dict(edgecolor='gray', linestyle='dashed', facecolor='none') # update with user settings circkw.update(kwargs.get('circle', {})) # determine coordinates for 'straight' lines if proj: # projected # reproject the site coordinates psite = georef.reproject(*site, projection_target=proj) # these lines might not be straigt so we approximate them with 10 # segments. Produce polar coordinates rr, az = np.meshgrid(np.linspace(0, ranges[-1], 10), angles) # convert from spherical to projection coords = georef.spherical_to_proj(rr, az, elev, site, proj=proj) nsewx = coords[..., 0] nsewy = coords[..., 1] else: # no projection psite = site rr, az = np.meshgrid(np.linspace(0, ranges[-1], 2), angles) # use simple trigonometry to calculate coordinates nsewx, nsewy = (psite[0] + rr * np.cos(np.radians(90 - az)), psite[1] + rr * np.sin(np.radians(90 - az))) # mark the site, just in case nothing else would be drawn ax.plot(*psite[:2], marker='+', **linekw) # draw the lines for i in range(len(angles)): ax.add_line(lines.Line2D(nsewx[i, :], nsewy[i, :], **linekw)) # draw the range circles if proj: # produce an approximation of the circle x, y = np.meshgrid(ranges, np.arange(360)) poly = georef.spherical_to_proj(ranges, np.arange(360), elev, site, proj=proj)[..., :2] poly = np.swapaxes(poly, 0, 1) for p in poly: ax.add_patch(patches.Polygon(p, **circkw)) else: # in the unprojected case, we may use 'true' circles. for r in ranges: ax.add_patch(patches.Circle(psite, r, **circkw)) # there should be not much wrong, setting the axes aspect to equal # by default ax.set_aspect('equal') # return the axes object for later use return ax
def ex_clutter_cloud(): # read the radar volume scan path = os.path.dirname(__file__) + '/' pvol = io.read_OPERA_hdf5(path + 'data/20130429043000.rad.bewid.pvol.dbzh.scan1.hdf') # Count the number of dataset ntilt = 1 for i in range(100): try: pvol["dataset%d/what" % ntilt] ntilt += 1 except Exception: ntilt -= 1 break # Construct radar values nrays = int(pvol["dataset1/where"]["nrays"]) nbins = int(pvol["dataset1/where"]["nbins"]) val = np.empty((ntilt, nrays, nbins)) for t in range(ntilt): val[t, ...] = pvol["dataset%d/data1/data" % (t + 1)] gain = float(pvol["dataset1/data1/what"]["gain"]) offset = float(pvol["dataset1/data1/what"]["offset"]) val = val * gain + offset # Construct radar coordinates rscale = int(pvol["dataset1/where"]["rscale"]) coord = np.empty((ntilt, nrays, nbins, 3)) for t in range(ntilt): elangle = pvol["dataset%d/where" % (t + 1)]["elangle"] coord[t, ...] = georef.sweep_centroids(nrays, rscale, nbins, elangle) ascale = math.pi / nrays sitecoords = (pvol["where"]["lon"], pvol["where"]["lat"], pvol["where"]["height"]) proj_radar = georef.create_osr("aeqd", lat_0=pvol["where"]["lat"], lon_0=pvol["where"]["lon"]) coord[..., 0], coord[..., 1], coord[..., 2] = georef.polar2lonlatalt_n(coord[..., 0], np.degrees(coord[..., 1]), coord[..., 2], sitecoords, re=6370040., ke=4. / 3.) coord = georef.reproject(coord, projection_target=proj_radar) # Construct collocated satellite data sat_gdal = io.read_safnwc(path + 'data/SAFNWC_MSG3_CT___201304290415_BEL_________.h5') val_sat = georef.read_gdal_values(sat_gdal) coord_sat = georef.read_gdal_coordinates(sat_gdal) proj_sat = georef.read_gdal_projection(sat_gdal) coord_sat = georef.reproject(coord_sat, projection_source=proj_sat, projection_target=proj_radar) coord_radar = coord interp = ipol.Nearest(coord_sat[..., 0:2].reshape(-1, 2), coord_radar[..., 0:2].reshape(-1, 2)) val_sat = interp(val_sat.ravel()).reshape(val.shape) # Estimate localisation errors timelag = 9 * 60 wind = 10 error = np.absolute(timelag) * wind # Identify clutter based on collocated cloudtype clutter = cl.filter_cloudtype(val[0, ...], val_sat[0, ...], scale=rscale, smoothing=error) # visualize the result plt.figure() vis.plot_ppi(clutter) plt.suptitle('clutter') plt.savefig('clutter_cloud_example_1.png') plt.figure() vis.plot_ppi(val_sat[0, ...]) plt.suptitle('satellite') plt.savefig('clutter_cloud_example_2.png') plt.show()