def test_ellipsoid_polar_transform(self): # USGS Professional Paper 1395, pp 338--339 globe = ccrs.Globe(ellipse=None, semimajor_axis=6378388.0, flattening=1 - np.sqrt(1 - 0.00672267)) aeqd = ccrs.AzimuthalEquidistant(central_latitude=90.0, central_longitude=-100.0, globe=globe) geodetic = aeqd.as_geodetic() other_args = { 'a=6378388.0', 'f=0.003367003355798981', 'lon_0=-100.0', 'lat_0=90.0', 'x_0=0.0', 'y_0=0.0' } check_proj_params('aeqd', aeqd, other_args) assert_almost_equal(np.array(aeqd.x_limits), [-20038296.88254529, 20038296.88254529], decimal=6) assert_almost_equal( np.array(aeqd.y_limits), # TODO: This is wrong. Globe.semiminor_axis does # not account for flattening. # [-19970827.86969727, 19970827.86969727] [-20038296.88254529, 20038296.88254529], decimal=6) result = aeqd.transform_point(5.0, 80.0, geodetic) assert_array_almost_equal(result, [1078828.3, 289071.2], decimal=1)
def two_side_plot(self): """ analyze branch phenomenon plot dispersion curve from both side of station pairs in different color :return: None """ fig = plt.figure(figsize=(10, 5)) ax1 = fig.add_subplot( 1, 2, 1, projection=ccrs.AzimuthalEquidistant(*self.latlon1[::-1])) ax2 = fig.add_subplot(1, 2, 2) ax1.set_global() ax1.stock_img() ax1.coastlines() colors = ['red', 'blue'] stla = (self.latlon1[0] + self.latlon2[0]) / 2.0 for i in range(len(self.evts)): evla = self.evts[i].getlatlon()[0] marker = 0 if stla > evla else 1 plotdispax(self.disp[i], np.arange(*self.PRANGE), ax2, color=colors[marker]) ax1.plot(*self.evts[i].getlatlon()[::-1], marker='*', markersize=5, transform=ccrs.Geodetic(), color=colors[marker]) plt.show()
def coverage(evla,evlo,stla,stlo,stat): """ Creates a map showing the locations of a seismic station and the associated events using a AzimuthalEquidistant projection centered on the Station evla - event longitude(s) [deg] can be 1 or more evlo - event latitude(s) [deg] can be 1 or more stla - station latitude [deg] stlo - station longitude [deg] stat - Station Code (string) """ # We can either do and AzimuthalEquidistant projection centered on the staiton or a nice, Pacific-centered one # proj = cart.PlateCarree(central_longitude=180) proj = cart.AzimuthalEquidistant(central_longitude=stlo,central_latitude=stla) ax = plt.axes(projection=proj) ax.set_global() #This sets the axes extent to its maximum possible setting, so we can find these darn events ax.coastlines(resolution = '110m') # Coastline data is downloaded by Cartopy from Natural Earth (http://www.naturalearthdata.com) #Resolution options are 100m,50m and 10m ax.add_feature(cartopy.feature.OCEAN, zorder=0) ax.add_feature(cartopy.feature.LAND, zorder=0, edgecolor='black') # Now add observed events ax.plot(evlo,evla,'ro',markersize = 5,transform = cart.Geodetic(),label='Event Location') # ax.set_xticks([-130,-125,-120,-115,-110,-105,-100], crs=proj) # ax.set_yticks([30,35,40,45,50,55,60], crs=proj) stat = 'NEW' ax.plot(stlo,stla,'kv',transform=cart.Geodetic(),markersize=10,label='Station Loction') ax.set_title('Coverage for Station {}'.format(stat)) ax.legend() plt.show()
def test_ellipsoid_guam_transform(self): # USGS Professional Paper 1395, pp 339--340 globe = ccrs.Globe(ellipse=None, semimajor_axis=6378206.4, flattening=1 - np.sqrt(1 - 0.00676866)) lat_0 = 13 + (28 + 20.87887 / 60) / 60 lon_0 = 144 + (44 + 55.50254 / 60) / 60 aeqd = ccrs.AzimuthalEquidistant(central_latitude=lat_0, central_longitude=lon_0, false_easting=50000.0, false_northing=50000.0, globe=globe) geodetic = aeqd.as_geodetic() other_args = {'a=6378206.4', 'f=0.003390076308689371', 'lon_0=144.7487507055556', 'lat_0=13.47246635277778', 'x_0=50000.0', 'y_0=50000.0'} check_proj_params('aeqd', aeqd, other_args) assert_almost_equal(np.array(aeqd.x_limits), [-19987726.36931940, 20087726.36931940], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), [-19919796.94787477, 20019796.94787477], decimal=6) pt_lat = 13 + (20 + 20.53846 / 60) / 60 pt_lon = 144 + (38 + 7.19265 / 60) / 60 result = aeqd.transform_point(pt_lon, pt_lat, geodetic) # The paper uses an approximation, so we cannot match it exactly, # hence, decimal=1, not 2. assert_array_almost_equal(result, [37712.48, 35242.00], decimal=1)
def base_map(projection='local', center_lat=0, center_lon=0, extent=None, **kwargs): """ Function to plot a basic map which can be used to add data later. :param projection: Cartopy projection string :param center_lat: Latitude to center map :param center_lon: Longitude to center map :param extent: List of coordinates for map boundaries """ plt.figure() if projection == 'global': ax = plt.axes(projection=ccrs.Mollweide(central_longitude=center_lon)) elif projection == 'local': ax = plt.axes(projection=ccrs.AlbersEqualArea( central_latitude=center_lat, central_longitude=center_lon)) if extent: ax.set_extent(extent) elif projection == 'AzimuthalEquidistant': ax = plt.axes(projection=ccrs.AzimuthalEquidistant( central_longitude=center_lon, central_latitude=center_lat)) else: print('Projection not supported') ax.coastlines() ax.add_feature(cfeature.LAND) ax.add_feature(cfeature.BORDERS, linestyle='-') return ax
def test_ellipsoid_micronesia_transform(self): # USGS Professional Paper 1395, pp 340--341 globe = ccrs.Globe(ellipse=None, semimajor_axis=6378206.4, flattening=1 - np.sqrt(1 - 0.00676866)) lat_0 = 15 + (11 + 5.6830 / 60) / 60 lon_0 = 145 + (44 + 29.9720 / 60) / 60 aeqd = ccrs.AzimuthalEquidistant(central_latitude=lat_0, central_longitude=lon_0, false_easting=28657.52, false_northing=67199.99, globe=globe) geodetic = aeqd.as_geodetic() expected = ('+a=6378206.4 +f=0.003390076308689371 +proj=aeqd ' '+lon_0=145.7416588888889 +lat_0=15.18491194444444 ' '+x_0=28657.52 +y_0=67199.99000000001 +no_defs') assert_equal(aeqd.proj4_init, expected) assert_almost_equal(np.array(aeqd.x_limits), [-20009068.84931940, 20066383.88931940], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), # TODO: This is wrong. Globe.semiminor_axis does # not account for flattening. # [-19902596.95787477, 20036996.93787477] [-19970526.37931940, 20104926.35931940], decimal=6) pt_lat = 15 + (14 + 47.4930 / 60) / 60 pt_lon = 145 + (47 + 34.9080 / 60) / 60 result = aeqd.transform_point(pt_lon, pt_lat, geodetic) assert_array_almost_equal(result, [34176.20, 74017.88], decimal=2)
def plotGeographic(self, map_widget=None): """ Creates a geographic representation of the catalogue. Parameters ---------- map_widget : Axes object, optional The axes object on which to plot the map. One is generated if not provided """ network_centre = self.network.centre lons = self.src_df.lon.values lats = self.src_df.lat.values sids = self.src_df.sourceid.values proj = ccrs.AzimuthalEquidistant(central_longitude=network_centre[0], central_latitude=network_centre[1]) if not map_widget: return else: ax = map_widget.canvas.mapPlot(proj) minr = compute_radius(proj, self.minrad, network_centre) ax.add_patch( Circle(xy=network_centre, radius=minr, edgecolor="red", linewidth=4.0, fill=False, alpha=0.3, transform=proj, zorder=15)) if float(self.maxrad) >= 150.: pass else: maxr = compute_radius(proj, self.maxrad, network_centre) ax.add_patch( Circle(xy=network_centre, radius=maxr, edgecolor="red", linewidth=4.0, fill=False, alpha=0.3, transform=proj, zorder=15)) tolerance = 10 for i in range(len(lons)): ax.scatter(lons[i], lats[i], 18, marker='o', color='k', picker=tolerance, zorder=20, label="SOURCE: {}".format(sids[i]), transform=ccrs.Geodetic())
def test_ellipsoid_micronesia_transform(self): # USGS Professional Paper 1395, pp 340--341 globe = ccrs.Globe(ellipse=None, semimajor_axis=6378206.4, flattening=1 - np.sqrt(1 - 0.00676866)) lat_0 = 15 + (11 + 5.6830 / 60) / 60 lon_0 = 145 + (44 + 29.9720 / 60) / 60 aeqd = ccrs.AzimuthalEquidistant(central_latitude=lat_0, central_longitude=lon_0, false_easting=28657.52, false_northing=67199.99, globe=globe) geodetic = aeqd.as_geodetic() other_args = {'a=6378206.4', 'f=0.003390076308689371', 'lon_0=145.7416588888889', 'lat_0=15.18491194444444', 'x_0=28657.52', 'y_0=67199.99000000001'} check_proj_params('aeqd', aeqd, other_args) assert_almost_equal(np.array(aeqd.x_limits), [-20009068.84931940, 20066383.88931940], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), [-19902596.95787477, 20036996.93787477], decimal=6) pt_lat = 15 + (14 + 47.4930 / 60) / 60 pt_lon = 145 + (47 + 34.9080 / 60) / 60 result = aeqd.transform_point(pt_lon, pt_lat, geodetic) assert_array_almost_equal(result, [34176.20, 74017.88], decimal=2)
def _plot(self, **kwargs): dtype = self.data.dtype lon, lat, var = self.data.lon, self.data.lat, self.data.data if (self.settings["extent"] == None ): # 增加判断,城市名称绘制在选择区域内,否则自动绘制在data.lon和data.lat范围内 self.settings["extent"] = [ lon.min(), lon.max(), lat.min(), lat.max() ] # When plot single radar, azimuthal equidistant projection is used. # The data which has code like 'Z9XXX' is considered as single radar. code = self.data.code if isinstance(self.data, Radial) or (code.startswith("Z") and code[1:].isnumeric()): proj = ccrs.AzimuthalEquidistant( central_longitude=self.data.stp["lon"], central_latitude=self.data.stp["lat"], ) else: proj = ccrs.PlateCarree() self.geoax: GeoAxes = create_geoaxes(self.fig, proj, extent=self.settings["extent"]) if self.data.dtype in ["VEL", "SW"] and self.data.include_rf: rf = var[1] var = var[0] self._plot_ctx["var"] = var self._plot_ctx["dtype"] = dtype pnorm, cnorm, clabel = self._norm() pcmap, ccmap = self._cmap() self.geoax.pcolormesh(lon, lat, var, norm=pnorm, cmap=pcmap, transform=self.data_crs, **kwargs) if self.data.dtype in ["VEL", "SW"] and self.data.include_rf: self.geoax.pcolormesh(lon, lat, rf, norm=norm_plot["RF"], cmap=cmap_plot["RF"], transform=self.data_crs, **kwargs) self._autoscale() add_shp( self.geoax, proj, coastline=self.settings["coastline"], style=self.settings["style"], extent=self.geoax.get_extent(self.data_crs), ) if self.settings["highlight"]: draw_highlight_area(self.settings["highlight"]) if self.settings["add_city_names"]: self._add_city_names() if self.settings["slice"]: self.plot_cross_section(self.settings["slice"])
def plot_range_rings(range_rings_km, location, radar, ax): ''' plot range rings at specified intervals range_rings_km - list of rings to plot (in km) location - defines position of labels (0-360 degrees, 0 = top) ''' loc_r = np.radians(location) transform = ccrs.AzimuthalEquidistant(central_longitude=radar.longitude['data'][0], central_latitude=radar.latitude['data'][0]) for ring in range_rings_km: angle = np.linspace(0., 2.0 * np.pi, 360) mask_angle = 22/ring #calculate angle needed for same length 'cut out' on each range ring (= arc length/r) for i in range(len(angle)): if loc_r-(mask_angle/2) <= angle[i] <= loc_r+(mask_angle/2): angle[i] =np.nan #nan values to exclude from plot where label will go label = (str(ring) + ' km') xpts = ring * 1000. * np.sin(angle) ypts = ring * 1000. * np.cos(angle) rot = 360 - location ax.plot(xpts, ypts, linestyle='--', c = 'gray', linewidth = 0.25, transform = transform, zorder = 10) txt = ax.text(ring*1000*np.sin(loc_r),ring*1000*np.cos(loc_r),label, va = 'center', ha = 'center', fontsize = 3, alpha = 0.7, color = 'gray', clip_on = True, transform = transform, rotation = rot) txt.clipbox = ax.bbox
def test_ellipsoid_guam_transform(self): # USGS Professional Paper 1395, pp 339--340 globe = ccrs.Globe(ellipse=None, semimajor_axis=6378206.4, flattening=1 - np.sqrt(1 - 0.00676866)) lat_0 = 13 + (28 + 20.87887 / 60) / 60 lon_0 = 144 + (44 + 55.50254 / 60) / 60 aeqd = ccrs.AzimuthalEquidistant(central_latitude=lat_0, central_longitude=lon_0, false_easting=50000.0, false_northing=50000.0, globe=globe) geodetic = aeqd.as_geodetic() expected = ('+a=6378206.4 +f=0.003390076308689371 +proj=aeqd ' '+lon_0=144.7487507055556 +lat_0=13.47246635277778 ' '+x_0=50000.0 +y_0=50000.0 +no_defs') assert_equal(aeqd.proj4_init, expected) assert_almost_equal(np.array(aeqd.x_limits), [-19987726.36931940, 20087726.36931940], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), # TODO: This is wrong. Globe.semiminor_axis does # not account for flattening. # [-19919796.94787477, 20019796.94787477] [-19987726.36931940, 20087726.36931940], decimal=6) pt_lat = 13 + (20 + 20.53846 / 60) / 60 pt_lon = 144 + (38 + 7.19265 / 60) / 60 result = aeqd.transform_point(pt_lon, pt_lat, geodetic) # The paper uses an approximation, so we cannot match it exactly, # hence, decimal=1, not 2. assert_array_almost_equal(result, [37712.48, 35242.00], decimal=1)
def _plot(self, **kwargs): lon = self.data["longitude"].values lat = self.data["latitude"].values var = self.data[self.dtype].values if not self.settings["extent"]: # 增加判断,城市名称绘制在选择区域内,否则自动绘制在data.lon和data.lat范围内 self.settings["extent"] = [ lon.min(), lon.max(), lat.min(), lat.max() ] # When plot single radar, azimuthal equidistant projection is used. # The data which has code like 'Z9XXX' is considered as single radar. code = self.data.site_code if is_radial(self.data) and (code.startswith("Z") and code[1:].isnumeric()): proj = ccrs.AzimuthalEquidistant( central_longitude=self.data.site_longitude, central_latitude=self.data.site_latitude, ) else: proj = ccrs.PlateCarree() self.geoax: GeoAxes = create_geoaxes(self.fig, proj, extent=self.settings["extent"]) self._plot_ctx["var"] = var pnorm, cnorm, clabel = self._norm() pcmap, ccmap = self._cmap() self.geoax.pcolormesh(lon, lat, var, norm=pnorm, cmap=pcmap, transform=self.data_crs, **kwargs) if self.rf_flag: rf = self.data["RF"].values self.geoax.pcolormesh(lon, lat, rf, norm=norm_plot["RF"], cmap=cmap_plot["RF"], transform=self.data_crs, **kwargs) self._autoscale() add_shp( self.geoax, proj, coastline=self.settings["coastline"], style=self.settings["style"], extent=self.geoax.get_extent(self.data_crs), ) if self.settings["highlight"]: draw_highlight_area(self.settings["highlight"]) if self.settings["add_city_names"]: self._add_city_names() if self.settings["slice"]: self.plot_cross_section(self.settings["slice"]) self._fig_init = True
def select_tracks(tracks, station, radius, cpa): """ Select tracks passing close to some interest point. Parameters ---------- tracks : GeoSerie Tracks from which the selection must be done. station : Obspy Station Station of interest. radius : float Tracks are intersected in with a disk with radius is given but that value (in metres). cpa : float Tracks passing farther than this are rejected (in metres). Returns ------- df : GeoDataFrame The selected tracks in the local azimuthal equidistant projection as a GeoDataFrame containing tracks and related statistics. """ # insure that original data is preserved tracks = tracks.copy() # trim data before and after station operating time t_start = station.start_date.timestamp t_end = station.end_date.timestamp tracks = tracks.apply(lambda track: trim_track(track, t_start, t_end)) tracks = tracks[~tracks.isna()] # project in a local CRS crs = ccrs.AzimuthalEquidistant(station.longitude, station.latitude) tracks = tracks.apply(lambda track: LineString( crs.transform_points(ccrs.PlateCarree(), *np.array(track.coords).T))) # remove tracks which CPA is too far centre = Point(0, 0) cpa_mask = tracks.apply(centre.distance) <= cpa tracks = tracks[cpa_mask] # intersect tracks with the interest area area = centre.buffer(radius) tracks = tracks.apply(area.intersection) # if tracks empty return None if len(tracks) == 0: return None # separate eventual MultiLineString in separate LineStrings tracks = ( tracks.apply(pd.Series) # split MultiLineStrings into LineStrings .stack() # stack them so that each row as a unique LineString # only keep the original index which will be use to retrieve MMSI .reset_index(level=1, drop=True).apply(lambda track: LineString( sorted(track.coords, key=lambda point: point[-1])))) # verify that tracks do not have too far CPA cpa_mask = tracks.apply(centre.distance) <= cpa tracks = tracks[cpa_mask] return tracks
def test_default(self): aeqd = ccrs.AzimuthalEquidistant() expected = ('+ellps=WGS84 +proj=aeqd +lon_0=0.0 ' '+lat_0=0.0 +x_0=0.0 +y_0=0.0 +no_defs') assert_equal(aeqd.proj4_init, expected) assert_almost_equal(np.array(aeqd.x_limits), [-20037508.34278924, 20037508.34278924], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), [-20037508.34278924, 20037508.34278924], decimal=6)
def test_default(self): aeqd = ccrs.AzimuthalEquidistant() other_args = {'ellps=WGS84', 'lon_0=0.0', 'lat_0=0.0', 'x_0=0.0', 'y_0=0.0'} check_proj_params('aeqd', aeqd, other_args) assert_almost_equal(np.array(aeqd.x_limits), [-20037508.34278924, 20037508.34278924], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), [-19970326.371123, 19970326.371123], decimal=6)
def projector(projec,east,west,north,south): """ Provide extent details based on projection type. Parameters ---------- All defined on main.py Returns ------- 'new_extent' under given projection and object for projection ('proj') """ # defining extents based on projection if projec == 'Robinson': proj = ccrs.Robinson() new_extent = 'filler' elif projec == 'AzimuthalEquidistant': radius=6371228 ex = 9024309 adj = 4000000 cornerx=ex+adj newcornerx=cornerx/2. newcornery=newcornerx globe = ccrs.Globe(ellipse=None, semimajor_axis=radius, semiminor_axis=radius) proj = ccrs.AzimuthalEquidistant(central_latitude=90, central_longitude=-30, globe=globe) new_extent = [-newcornerx*1.25,newcornerx*1.25,-newcornery,newcornery] elif projec == 'LambertConformal': canada_east = east canada_west = west canada_north = north canada_south = south standard_parallels = (49, 77) central_longitude = -(91 + 52 / 60) proj = ccrs.LambertConformal(central_longitude=central_longitude, standard_parallels=standard_parallels) new_extent = [canada_west,canada_east,canada_south,canada_north] elif projec == 'PlateCarree': africa_east = east africa_west = west africa_north = north africa_south = south proj = ccrs.PlateCarree() new_extent = [africa_west,africa_east,africa_south,africa_north] return proj,new_extent
def test_eastings(self): aeqd_offset = ccrs.AzimuthalEquidistant(false_easting=1234, false_northing=-4321) expected = ('+ellps=WGS84 +proj=aeqd +lon_0=0.0 +lat_0=0.0 ' '+x_0=1234 +y_0=-4321 +no_defs') assert_equal(aeqd_offset.proj4_init, expected) assert_almost_equal(np.array(aeqd_offset.x_limits), [-20036274.34278924, 20038742.34278924], decimal=6) assert_almost_equal(np.array(aeqd_offset.y_limits), [-20041829.34278924, 20033187.34278924], decimal=6)
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) aeqd = ccrs.AzimuthalEquidistant(globe=globe) expected = ('+a=1000 +b=500 +proj=aeqd +lon_0=0.0 +lat_0=0.0 ' '+x_0=0.0 +y_0=0.0 +no_defs') assert_equal(aeqd.proj4_init, expected) assert_almost_equal(np.array(aeqd.x_limits), [-3141.59265359, 3141.59265359], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), [-1570.796326795, 1570.796326795], decimal=6)
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) aeqd = ccrs.AzimuthalEquidistant(globe=globe) other_args = {'a=1000', 'b=500', 'lon_0=0.0', 'lat_0=0.0', 'x_0=0.0', 'y_0=0.0'} check_proj_params('aeqd', aeqd, other_args) assert_almost_equal(np.array(aeqd.x_limits), [-3141.59265359, 3141.59265359], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), [-1570.796326795, 1570.796326795], decimal=6)
def test_eastings(self): aeqd_offset = ccrs.AzimuthalEquidistant(false_easting=1234, false_northing=-4321) other_args = {'ellps=WGS84', 'lon_0=0.0', 'lat_0=0.0', 'x_0=1234', 'y_0=-4321'} check_proj_params('aeqd', aeqd_offset, other_args) assert_almost_equal(np.array(aeqd_offset.x_limits), [-20036274.34278924, 20038742.34278924], decimal=6) assert_almost_equal(np.array(aeqd_offset.y_limits), [-19974647.371123, 19966005.371123], decimal=6)
def __init__(self, metric_name, date, decorations=True, basemaps=True, alpha=0.35, centered=None): self.metric_name = metric_name self.date = date self.decorations = decorations self.basemaps = basemaps self.plotalpha = alpha if centered is None: self.proj = ccrs.PlateCarree() figsize=(16,24) else: self.proj = ccrs.AzimuthalEquidistant(centered[0], centered[1]) figsize=(12,12) self.fig = plt.figure(figsize=figsize) self.ax = plt.axes( projection=self.proj, frame_on=self.decorations, facecolor='white', ) self.ax.spines['geo'].set_edgecolor('#666') self.ax.set_global() if self.decorations: if centered is None: self.ax.grid(True, visible=True, linewidth=.5, color='black', alpha=0.25, linestyle='--') self.ax.set_xticks([-180, -160, -140, -120,-100, -80, -60,-40,-20, 0, 20, 40, 60,80,100, 120,140, 160,180], crs=ccrs.PlateCarree()) self.ax.set_yticks([-80, -60,-40,-20, 0, 20, 40, 60,80], crs=ccrs.PlateCarree()) else: self.ax.gridlines( linewidth=.5, color='black', alpha=0.25, linestyle='--', xlocs=[-180, -160, -140, -120,-100, -80, -60,-40,-20, 0, 20, 40, 60,80,100, 120,140, 160,180], ylocs=[-80, -60,-40,-20, 0, 20, 40, 60,80], ) else: self.ax.axis(False) self.ax.outline_patch.set_visible(False) self.ax.background_patch.set_visible(False) self.ax.set_xmargin(0) self.ax.set_ymargin(0) if basemaps: self.ax.add_feature(cartopy.feature.NaturalEarthFeature('physical', 'land', '110m', edgecolor='face', facecolor=np.array((0xdd,0xdd,0xcc))/256., zorder=-1 ) ) self.ax.add_feature(Nightshade(self.date, alpha=0.08))
def _plot(self, **kwargs): from cinrad.constants import plot_kw dtype = self.data.dtype lon, lat, var = _prepare(self.data, dtype) if self.settings['extent'] == None: #增加判断,城市名称绘制在选择区域内,否则自动绘制在data.lon和data.lat范围内 self.settings['extent'] = [lon.min(), lon.max(), lat.min(), lat.max()] # When plot single radar, azimuthal equidistant projection is used. # The data which has code like 'Z9XXX' is considered as single radar. code = self.data.code if isinstance(self.data, Radial) or (code.startswith('Z') and code[1:].isnumeric()): proj = ccrs.AzimuthalEquidistant(central_longitude=self.data.stp['lon'], central_latitude=self.data.stp['lat']) else: proj = ccrs.PlateCarree() self.geoax = set_geoaxes(self.fig, proj, extent=self.settings['extent']) if self.data.dtype in ['VEL', 'SW'] and self.data.include_rf: rf = var[1] var = var[0] popnan = var[np.logical_not(np.isnan(var))] pnorm, cnorm, clabel = self._norm() pcmap, ccmap = self._cmap() self.geoax.pcolormesh(lon, lat, var, norm=pnorm, cmap=pcmap, transform=self.data_crs, **kwargs) if self.data.dtype in ['VEL', 'SW'] and self.data.include_rf: self.geoax.pcolormesh(lon, lat, rf, norm=norm_plot['RF'], cmap=cmap_plot['RF'], transform=self.data_crs, **kwargs) add_shp(self.geoax, proj, coastline=self.settings['coastline'], style=self.settings['style'], extent=self.settings['extent']) if self.settings['highlight']: draw_highlight_area(self.settings['highlight']) if self.settings['add_city_names']: self._add_city_names() # axes used for text which has the same x-position as # the colorbar axes (for matplotlib 3 compatibility) ax2 = self.fig.add_axes([0.92, 0.06, 0.01, 0.35]) for sp in ax2.spines.values(): sp.set_visible(False) ax, cbar = setup_axes(self.fig, ccmap, cnorm) if not isinstance(clabel, type(None)): change_cbar_text(cbar, np.linspace(cnorm.vmin, cnorm.vmax, len(clabel)), clabel) ax2.yaxis.set_visible(False) ax2.xaxis.set_visible(False) if self.settings['plot_labels']: # Make VCP21 the default scanning strategy task = self.data.scan_info.pop('task', 'VCP21') text(ax2, self.data.drange, self.data.reso, self.data.scantime, self.data.name, task, self.data.elev) ax2.text(0, 2.36, ' ' * 35) # Ensure consistent figure size ax2.text(0, 2.36, prodname[dtype], **plot_kw) ax2.text(0, 1.96, 'Max: {:.1f}{}'.format(np.max(popnan), unit[dtype]), **plot_kw) if self.data.dtype == 'VEL': ax2.text(0, 1.91, 'Min: {:.1f}{}'.format(np.min(popnan), unit[dtype]), **plot_kw) if self.settings['slice']: self.plot_cross_section(self.settings['slice'])
def _find_box(latlon, boxes, crs=None): """Return the box which encloses the coordinates.""" import cartopy.crs as ccrs from shapely.geometry import Point if crs is None: latlons = [boxes[len(boxes) // 2]['latlon']] latlon0 = np.median(latlons, axis=0) crs = ccrs.AzimuthalEquidistant(*latlon0[::-1]) pc = ccrs.PlateCarree() p = crs.project_geometry(Point(*latlon[::-1]), pc) for box in boxes: poly = crs.project_geometry(box['poly'], pc) if p.within(poly): return box
def PlotField( ds, output = "", field="zg", #name of field500 matrix, may vary from file to file mapcrs = ccrs.AzimuthalEquidistant(central_latitude = 90), datacrs = ccrs.PlateCarree(), extent =[-180,180,20,70], box_vertices = [[0,0],[0,0],[0,0],[0,0]], subplot_grid = 11, subplot_idx = 1, plot_title=""): lons,lats,dat1 = check_field(ds,field) #multiple plots for having both contours and heatmap ax = plt.subplot(int(str(subplot_grid)+str(subplot_idx)), projection=mapcrs, aspect = 1.0) ax.set_extent(extent, datacrs) ax.coastlines() gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1, color='gray', alpha=0.5, linestyle='--') #define colorbar cs_range,ticks,cb_label,cmap = bp_colorbar(field) #plot contour cs = ax.contourf(lons, lats,dat1, cs_range,cmap=cmap, transform=datacrs) #first ploot (float) cs_b = ax.contour(lons, lats,dat1, cs_range,colors="gray",linewidths = 0.1 ,transform=datacrs)#second plot for contours #plt.clabel(cs_b, colors ="black", fontsize = 5, inline ="false") #plot box if needed if box_vertices[0] != box_vertices[1]: polygon = plt.Polygon(box_vertices,fill = False,color="Green",transform=datacrs) ax.add_patch(polygon) ax.patch.set_alpha(1) # Make some nice titles for the plot plt.title(plot_title,fontsize = 12, loc='left') plt.colorbar(cs, orientation='horizontal',ticks=ticks,pad=0.08, label = cb_label , aspect=40) #Export image if subplot_grid != 11: return ax try: plt.savefig(output,bbox_inches='tight',dpi=250) return 0 except: print("Error code 1: no output file was given or something went wrong with matplotlib") return 1
def SKKS_plot(stat,phase): """ Creates a 3 panel plot showing measured fast direction and lag time vs back azimuth at a given station along with the coverage of the events stat - station Code [STRING] phase - phase to plot [STRING] """ data = load(stat,phase) fig = plt.figure(figsize = [20,20]) axs = [] gs = gridspec.GridSpec(2,3) proj = cart.AzimuthalEquidistant(central_longitude=data.STLO[0],central_latitude=data.STLA[0]) ax1 = plt.subplot(gs[0,0]) ax2 = plt.subplot(gs[1,0]) ax3 = fig.add_subplot(gs[:,1:],projection = proj) ax1.errorbar(data.BAZ,data.TLAG,yerr = data.DTLAG,fmt='kx',elinewidth=0.5) ax1.set_ylim([0,4]) ax1.set_ylabel('Lag (s)') ax1.set_xlabel('Back Azimuth (deg)') # _lag(ax1,data.BAZ,data.TLAG,data.DTLAG,'kx') # _fast(ax2,data.BAZ,data.FAST,data.DFAST,'kx') # coverage(ax3,data.EVLA,data.EVLO,data.STLA[0],data.STLO[0],stat) # plt.show() ax2.errorbar(data.BAZ,data.FAST,yerr=data.DFAST,fmt='kx',elinewidth=0.5) ax2.set_ylim([-90,90]) ax2.set_ylabel('Fast Direction (s)') ax2.set_xlabel('Back Azimuth (deg)') ### Plot Coverage on third axis object ax3.set_global() #This sets the axes extent to its maximum possible setting, so we can find these darn events ax3.coastlines(resolution = '110m') # Coastline data is downloaded by Cartopy from Natural Earth (http://www.naturalearthdata.com) #Resolution options are 100m,50m and 10m ax3.add_feature(cartopy.feature.OCEAN, zorder=0) ax3.add_feature(cartopy.feature.LAND, zorder=0, edgecolor='black') # Now add observed events ax3.plot(data.EVLO,data.EVLA,'ro',markersize = 5,transform = cart.Geodetic(),label='Event Location') # ax.set_xticks([-130,-125,-120,-115,-110,-105,-100], crs=proj) # ax.set_yticks([30,35,40,45,50,55,60], crs=proj) ax3.plot(data.STLO,data.STLA,'kv',transform=cart.Geodetic(),markersize=10,label='Station Loction') ax3.set_title('{} coverage for Station {}'.format(phase,stat)) ax3.legend() plt.show()
def plotlocation(self): fig = plt.figure(figsize=(10, 5)) ax = fig.add_subplot( 1, 1, 1, projection=ccrs.AzimuthalEquidistant(*self.latlon1[::-1])) ax.set_global() ax.stock_img() ax.coastlines() ax.plot(*self.latlon1[::-1], marker='^', markersize=10, transform=ccrs.Geodetic()) for evt in self.evts: ax.plot(*evt.getlatlon()[::-1], marker='*', color='red', markersize=5, transform=ccrs.Geodetic()) plt.show()
def plotMap(self, index = 0, view = "geo" ): import matplotlib.pyplot as plt import cartopy.crs as ccrs if view.lower().startswith("geo"): ax = plt.axes( projection=ccrs.PlateCarree() ) elif view.lower().startswith("polar"): ax = plt.axes( projection=ccrs.NorthPolarStereo( ) ) elif view.lower().startswith("epolar"): ax = plt.axes(projection=ccrs.AzimuthalEquidistant( -80, 90 ) ) elif view.lower().startswith("mol"): ax = plt.axes(projection=ccrs.Mollweide()) elif view.lower().startswith("rob"): ax = plt.axes(projection=ccrs.Robinson()) else: raise Exception( "Unrecognized map view: " + view ) self.xarrays[index].plot.contourf( ax=ax, levels=8, cmap='jet', robust=True, transform=ccrs.PlateCarree() ) ax.coastlines() plt.show()
def run(self): for index in self.indices: for pos, lat in enumerate(self.lat): if not self.ok: break print('Computing at (longitude, latitude) = (%s, %s)' % (self.long[index], lat)) # Generate new figure if self.size[0] == self.size[1]: figsize = (1, 1) dpi = self.size[0] elif self.size[0] > self.size[1]: figsize = (self.size[0] / self.size[1], 1) dpi = self.size[1] else: figsize = (self.size[0], self.size[1] / self.size[0]) dpi = self.size[0] plt.figure(figsize=[i * 1.3 for i in figsize], dpi=dpi, frameon=False) plt.axes(projection=ccrs.AzimuthalEquidistant( central_latitude=lat, central_longitude=self.long[index])) plt.imshow(self.data, transform=ccrs.PlateCarree()) # Use the indices rather than the values to name the files plt.savefig(opath.join( self.directory, self.name + '_%d,%d' % (index, pos) + '.jpg'), format='jpg', transparent=True, bbox_inches='tight', pad_inches=0) if not self.ok: break return
def test_sphere_transform(self): # USGS Professional Paper 1395, pg 337 globe = ccrs.Globe(ellipse=None, semimajor_axis=3.0, semiminor_axis=3.0) aeqd = ccrs.AzimuthalEquidistant(central_latitude=40.0, central_longitude=-100.0, globe=globe) geodetic = aeqd.as_geodetic() expected = ('+a=3.0 +b=3.0 +proj=aeqd +lon_0=-100.0 +lat_0=40.0 ' '+x_0=0.0 +y_0=0.0 +no_defs') assert_equal(aeqd.proj4_init, expected) assert_almost_equal(np.array(aeqd.x_limits), [-9.42477796, 9.42477796], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), [-9.42477796, 9.42477796], decimal=6) result = aeqd.transform_point(100.0, -20.0, geodetic) assert_array_almost_equal(result, [-5.8311398, 5.5444634])
def test_sphere_transform(self): # USGS Professional Paper 1395, pg 337 globe = ccrs.Globe(ellipse=None, semimajor_axis=3.0, semiminor_axis=3.0) aeqd = ccrs.AzimuthalEquidistant(central_latitude=40.0, central_longitude=-100.0, globe=globe) geodetic = aeqd.as_geodetic() other_args = {'a=3.0', 'b=3.0', 'lon_0=-100.0', 'lat_0=40.0', 'x_0=0.0', 'y_0=0.0'} check_proj_params('aeqd', aeqd, other_args) assert_almost_equal(np.array(aeqd.x_limits), [-9.42477796, 9.42477796], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), [-9.42477796, 9.42477796], decimal=6) result = aeqd.transform_point(100.0, -20.0, geodetic) assert_array_almost_equal(result, [-5.8311398, 5.5444634])