def test_plot_tmerc(self): filename = tests.get_data_path(('NetCDF', 'transverse_mercator', 'tmean_1910_1910.nc')) self.cube = iris.load_cube(filename) iplt.pcolormesh(self.cube[0]) plt.gca().coastlines() self.check_graphic()
def test_yaxis_labels_with_axes(self): import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) ax.set_ylim(0, 3) iplt.pcolormesh(self.cube, axes=ax, coords=('bar', 'str_coord')) plt.close(fig) self.assertPointsTickLabels('yaxis', ax)
def test_different_coord_systems(self): cube = self.bounded_cube lat = cube.coord('latitude') lon = cube.coord('longitude') lat.coord_system = iris.coord_systems.GeogCS(7000000) lon.coord_system = iris.coord_systems.GeogCS(7000001) with self.assertRaises(ValueError): iplt.pcolormesh(cube, coords=['longitude', 'latitude'])
def test_dateline(self): dpath = tests.get_data_path(['PP', 'nzgust.pp']) cube = iris.load_cube(dpath) pcolormesh(cube) # Ensure that the limited area expected for NZ is set. # This is set in longitudes with the datum set to the # International Date Line. self.assertTrue(-10 < plt.gca().get_xlim()[0] < -5 and 5 < plt.gca().get_xlim()[1] < 10)
def test_boundmode_multidim(self): # Test exception translation. # We can't get contiguous bounded grids from multi-d coords. cube = self.bounded_cube cube.remove_coord("latitude") cube.add_aux_coord(coords.AuxCoord(points=cube.data, standard_name='latitude', units='degrees'), [0, 1]) with self.assertRaises(ValueError): iplt.pcolormesh(cube, coords=['longitude', 'latitude'])
def test_boundmode_4bounds(self): # Test exception translation. # We can only get contiguous bounded grids with 2 bounds per point. cube = self.bounded_cube lat = coords.AuxCoord.from_coord(cube.coord("latitude")) lat.bounds = np.array([lat.points, lat.points + 1, lat.points + 2, lat.points + 3]).transpose() cube.remove_coord("latitude") cube.add_aux_coord(lat, 0) with self.assertRaises(ValueError): iplt.pcolormesh(cube, coords=['longitude', 'latitude'])
def main(): fname = iris.sample_data_path('rotated_pole.nc') temperature = iris.load_strict(fname) # Calculate the lat lon range and buffer it by 10 degrees lat_range, lon_range = iris.analysis.cartography.lat_lon_range(temperature) lat_range = lat_range[0] - 10, lat_range[1] + 10 lon_range = lon_range[0] - 10, lon_range[1] + 10 # Plot #1: Point plot showing data values & a colorbar plt.figure() iplt.map_setup(temperature, lat_range=lat_range, lon_range=lon_range) points = qplt.points(temperature, c=temperature.data) cb = plt.colorbar(points, orientation='horizontal') cb.set_label(temperature.units) iplt.gcm().drawcoastlines() plt.show() # Plot #2: Contourf of the point based data plt.figure() iplt.map_setup(temperature, lat_range=lat_range, lon_range=lon_range) qplt.contourf(temperature, 15) iplt.gcm().drawcoastlines() plt.show() # Plot #3: Contourf overlayed by coloured point data plt.figure() iplt.map_setup(temperature, lat_range=lat_range, lon_range=lon_range) qplt.contourf(temperature) iplt.points(temperature, c=temperature.data) iplt.gcm().drawcoastlines() plt.show() # For the purposes of this example, add some bounds to the latitude and longitude temperature.coord('grid_latitude').guess_bounds() temperature.coord('grid_longitude').guess_bounds() # Plot #4: Block plot plt.figure() iplt.map_setup(temperature, lat_range=lat_range, lon_range=lon_range) iplt.pcolormesh(temperature) iplt.gcm().bluemarble() iplt.gcm().drawcoastlines() plt.show()
def draw(geoaxes): import iris import iris.plot as iplt # Add some high-resolution coastlines so we can produce nice results # even when zoomed a long way in. geoaxes.coastlines('10m') fname = iris.sample_data_path('rotated_pole.nc') temperature = iris.load_cube(fname) iplt.pcolormesh(temperature) # Do the initial draw so that the coastlines are projected # (the slow part). plt.draw()
def main(): # Load the data with iris.FUTURE.context(netcdf_promote=True): cube1 = iris.load_cube(iris.sample_data_path('ostia_monthly.nc')) # Slice into cube to retrieve data for the inset map showing the # data region region = cube1[-1, :, :] # Average over latitude to reduce cube to 1 dimension plot_line = region.collapsed('latitude', iris.analysis.MEAN) # Open a window for plotting fig = plt.figure() # Add a single subplot (axes). Could also use "ax_main = plt.subplot()" ax_main = fig.add_subplot(1, 1, 1) # Produce a quick plot of the 1D cube qplt.plot(plot_line) # Set x limits to match the data ax_main.set_xlim(0, plot_line.coord('longitude').points.max()) # Adjust the y limits so that the inset map won't clash with main plot ax_main.set_ylim(294, 310) ax_main.set_title('Meridional Mean Temperature') # Add grid lines ax_main.grid() # Add a second set of axes specifying the fractional coordinates within # the figure with bottom left corner at x=0.55, y=0.58 with width # 0.3 and height 0.25. # Also specify the projection ax_sub = fig.add_axes([0.55, 0.58, 0.3, 0.25], projection=ccrs.Mollweide(central_longitude=180)) # Use iris.plot (iplt) here so colour bar properties can be specified # Also use a sequential colour scheme to reduce confusion for those with # colour-blindness iplt.pcolormesh(region, cmap='Blues') # Manually set the orientation and tick marks on your colour bar ticklist = np.linspace(np.min(region.data), np.max(region.data), 4) plt.colorbar(orientation='horizontal', ticks=ticklist) ax_sub.set_title('Data Region') # Add coastlines ax_sub.coastlines() # request to show entire map, using the colour mesh on the data region only ax_sub.set_global() qplt.show()
def main(): # Start with arrays for latitudes and longitudes, with a given number of # coordinates in the arrays. coordinate_points = 200 longitudes = np.linspace(-180.0, 180.0, coordinate_points) latitudes = np.linspace(-90.0, 90.0, coordinate_points) lon2d, lat2d = np.meshgrid(longitudes, latitudes) # Omega is the Earth's rotation rate, expressed in radians per second omega = 7.29e-5 # The data for our cube is the Coriolis frequency, # `f = 2 * omega * sin(phi)`, which is computed for each grid point over # the globe from the 2-dimensional latitude array. data = 2. * omega * np.sin(np.deg2rad(lat2d)) # We now need to define a coordinate system for the plot. # Here we'll use GeogCS; 6371229 is the radius of the Earth in metres. cs = GeogCS(6371229) # The Iris coords module turns the latitude list into a coordinate array. # Coords then applies an appropriate standard name and unit to it. lat_coord = iris.coords.DimCoord(latitudes, standard_name='latitude', units='degrees', coord_system=cs) # The above process is repeated for the longitude coordinates. lon_coord = iris.coords.DimCoord(longitudes, standard_name='longitude', units='degrees', coord_system=cs) # Now we add bounds to our latitude and longitude coordinates. # We want simple, contiguous bounds for our regularly-spaced coordinate # points so we use the guess_bounds() method of the coordinate. For more # complex coordinates, we could derive and set the bounds manually. lat_coord.guess_bounds() lon_coord.guess_bounds() # Now we input our data array into the cube. new_cube = iris.cube.Cube(data, standard_name='coriolis_parameter', units='s-1', dim_coords_and_dims=[(lat_coord, 0), (lon_coord, 1)]) # Now let's plot our cube, along with coastlines, a title and an # appropriately-labelled colour bar: ax = plt.axes(projection=ccrs.Orthographic()) ax.coastlines(resolution='10m') mesh = iplt.pcolormesh(new_cube, cmap='seismic') tick_levels = [-0.00012, -0.00006, 0.0, 0.00006, 0.00012] plt.colorbar(mesh, orientation='horizontal', label='s-1', ticks=tick_levels, format='%.1e') plt.title('Coriolis frequency') plt.show()
def draw(self, cube): for name in self.coords: if not isinstance(name, int): coord = cube.coord(name) if not coord.has_bounds(): coord.guess_bounds() self.element = iplt.pcolormesh(cube, axes=self.axes, coords=self.coords, **self.kwargs) return self.element
def main(): # Enable a future option, to ensure that the netcdf load works the same way # as in future Iris versions. iris.FUTURE.netcdf_promote = True # Load some test data. fname = iris.sample_data_path('rotated_pole.nc') air_pressure = iris.load_cube(fname) # Plot #1: Point plot showing data values & a colorbar plt.figure() points = qplt.points(air_pressure, c=air_pressure.data) cb = plt.colorbar(points, orientation='horizontal') cb.set_label(air_pressure.units) plt.gca().coastlines() iplt.show() # Plot #2: Contourf of the point based data plt.figure() qplt.contourf(air_pressure, 15) plt.gca().coastlines() iplt.show() # Plot #3: Contourf overlayed by coloured point data plt.figure() qplt.contourf(air_pressure) iplt.points(air_pressure, c=air_pressure.data) plt.gca().coastlines() iplt.show() # For the purposes of this example, add some bounds to the latitude # and longitude air_pressure.coord('grid_latitude').guess_bounds() air_pressure.coord('grid_longitude').guess_bounds() # Plot #4: Block plot plt.figure() plt.axes(projection=ccrs.PlateCarree()) iplt.pcolormesh(air_pressure) plt.gca().stock_img() plt.gca().coastlines() iplt.show()
def pcolormesh(cube, *args, **kwargs): """ Draws a labelled pseudocolour plot based on the given Cube. See :func:`iris.plot.pcolormesh` for details of valid keyword arguments. """ coords = kwargs.get('coords') result = iplt.pcolormesh(cube, *args, **kwargs) _label_with_bounds(cube, result, coords=coords) return result
def main(): fname = iris.sample_data_path('rotated_pole.nc') temperature = iris.load_cube(fname) # Plot #1: Point plot showing data values & a colorbar plt.figure() points = qplt.points(temperature, c=temperature.data) cb = plt.colorbar(points, orientation='horizontal') cb.set_label(temperature.units) plt.gca().coastlines() plt.show() # Plot #2: Contourf of the point based data plt.figure() qplt.contourf(temperature, 15) plt.gca().coastlines() plt.show() # Plot #3: Contourf overlayed by coloured point data plt.figure() qplt.contourf(temperature) iplt.points(temperature, c=temperature.data) plt.gca().coastlines() plt.show() # For the purposes of this example, add some bounds to the latitude and longitude temperature.coord('grid_latitude').guess_bounds() temperature.coord('grid_longitude').guess_bounds() # Plot #4: Block plot plt.figure() ax = plt.axes(projection=ccrs.PlateCarree()) iplt.pcolormesh(temperature) plt.gca().stock_img() plt.gca().coastlines() plt.show()
def test_grid(self): iplt.pcolormesh(self.cube, facecolors="none", edgecolors="blue") # the result is a graphic which has coloured edges. This is a mpl bug, # see https://github.com/matplotlib/matplotlib/issues/1302 self.check_graphic()
def plotOneModel(gpmdict, modelcubes, model2plot, timeagg, plotdomain, odir): # Plot GPM against all lead times from one model try: m = [i for i, x in enumerate(modelcubes[model2plot]) if x][0] myu = modelcubes[model2plot][m].coord('time').units daterange = [ x.strftime('%Y%m%dT%H%MZ') for x in myu.num2date( modelcubes[model2plot][m].coord('time').bounds[0]) ] except: pdb.set_trace() return if not os.path.isdir(odir): os.makedirs(odir) #pdb.set_trace() if len(modelcubes[model2plot]) < 10: diff = 10 - len(modelcubes[model2plot]) # pdb.set_trace() modelcubes[model2plot] = np.repeat( None, diff).tolist() + modelcubes[model2plot] postage = { 1: gpmdict['gpm_prod_data'] if gpmdict['gpm_prod_data'] is not None else gpmdict['gpm_late_data'], 2: gpmdict['gpm_prod_qual'] if gpmdict['gpm_prod_qual'] is not None else gpmdict['gpm_late_qual'], # TODO : Replace the next 2 lines with different observations either from satellite or radar 3: gpmdict['gpm_late_data'] if gpmdict['gpm_prod_data'] is not None else gpmdict['gpm_early_data'], 4: gpmdict['gpm_late_qual'] if gpmdict['gpm_prod_qual'] is not None else gpmdict['gpm_early_qual'], 5: modelcubes[model2plot][9], 6: modelcubes[model2plot][8], 7: modelcubes[model2plot][7], 8: modelcubes[model2plot][6], 9: modelcubes[model2plot][5], 10: modelcubes[model2plot][4], 11: modelcubes[model2plot][3], 12: modelcubes[model2plot][2], 13: modelcubes[model2plot][1], 14: modelcubes[model2plot][0], 15: None, 16: None } contour_levels = { '30mins': [0.0, 0.1, 0.25, 0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 1000.0], '3hr': [0.0, 0.3, 0.75, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 1000.0], '6hr': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '12hr': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '24hr': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0] } my_rgb = [ '#ffffff', '#87bbeb', '#6a9bde', '#2a6eb3', '#30ca28', '#e2d942', '#f49d1b', '#e2361d', '#f565f5', '#ffffff' ] # contour_levels = {'30mins': [1,2,4,8,16,32,64,128], # # '3hr' : [1,2,4,8,16,32,64,128], # '3hr' : [0,0.3,0.75,1.5,3.0,6.0,12.0,24.0,48.0,96.0], # '6hr' : [1,2,4,8,16,32,64,128], # '12hr' : [1,2,4,8,16,32,64,128,256], # '24hr' : [1,2,4,8,16,32,64,128,256]} # TODO: Change thresholds especially for 12 & 24hr # my_rgb = ['#ffffff', '#87bbeb', '#5b98d6', '#276abc', '#1fc91a', '#fded39', '#f59800', '#eb2f1a', '#fe5cfc', '#ffffff'] # light blue '#6a9bde', mid blue bounds = contour_levels[str(timeagg) + 'hr'] norm = colors.BoundaryNorm(boundaries=bounds, ncolors=len(my_rgb)) my_cmap = colors.ListedColormap(my_rgb) qbounds = np.arange(1, 101) qnorm = colors.BoundaryNorm(boundaries=qbounds, ncolors=len(qbounds) - 1) # Create a wider than normal figure to support our many plots #fig = plt.figure(figsize=(8, 12), dpi=100) fig = plt.figure(figsize=(12, 13), dpi=100) # Also manually adjust the spacings which are used when creating subplots plt.gcf().subplots_adjust(hspace=0.07, wspace=0.05, top=0.92, bottom=0.05, left=0.075, right=0.925) # iterate over all possible latitude longitude slices for i in range(1, 17): #print(i) # plot the data in a 4 row x 4 col grid # pdb.set_trace() if postage[i] is not None: ax = plt.subplot(4, 4, i) # timebnds = postage[i].coord('time').bounds[0] # timediff = int(round(timebnds[1] - timebnds[0])) # plotthis = True if timediff == timeagg else False # if plotthis: if not (postage[i].coord('longitude').has_bounds() or postage[i].coord('latitude').has_bounds()): postage[i].coord('longitude').guess_bounds() postage[i].coord('latitude').guess_bounds() if 'Quality Flag' in postage[i].attributes['title']: qcm = iplt.pcolormesh( postage[i], vmin=0, vmax=100, cmap='cubehelix_r') #cmap='cubehelix_r') norm=qnorm, else: pcm = iplt.pcolormesh(postage[i], norm=norm, cmap=my_cmap) #cmap='cubehelix_r') # add coastlines ax = plt.gca() x0, y0, x1, y1 = plotdomain ax.set_extent([x0, x1, y0, y1]) if i > 4: fclt = postage[i].coord('forecast_period').bounds[0] plt.title('T+' + str(int(fclt[0])) + ' to ' + 'T+' + str(int(fclt[1]))) else: plt.title(postage[i].attributes['title']) borderlines = cfeature.NaturalEarthFeature( category='cultural', name='admin_0_boundary_lines_land', scale='50m', facecolor='none') ax.add_feature(borderlines, edgecolor='black', alpha=0.5) ax.coastlines(resolution='50m', color='black') ax.gridlines(color="gray", alpha=0.2) #plt.gca().coastlines() # make an axes to put the shared colorbar in colorbar_axes = plt.gcf().add_axes([0.54, 0.1, 0.35, 0.025]) # left, bottom, width, height colorbar = plt.colorbar(pcm, colorbar_axes, orientation='horizontal', extend='neither') try: # colorbar.set_label('%s' % postage[i-2].units) colorbar.set_label('Precipitation amount (mm)') except: while postage[i - 2] is None: i -= 1 # Make another axis for the quality flag colour bar qcolorbar_axes = plt.gcf().add_axes([0.54, 0.2, 0.35, 0.025]) # left, bottom, width, height qcolorbar = plt.colorbar(qcm, qcolorbar_axes, orientation='horizontal') qcolorbar.set_label('Quality Flag') # limit the colorbar to 8 tick marks #import matplotlib.ticker #colorbar.locator = matplotlib.ticker.MaxNLocator(8) #colorbar.update_ticks() # get the time for the entire plot #time_coord = last_timestep.coord('time') #time = time_coord.units.num2date(time_coord.bounds[0, 0]) # set a global title for the postage stamps with the date formated by # The following lines get around the problem of some missing data j = 0 while modelcubes[model2plot][j] is None: j += 1 newu = modelcubes[model2plot][j].coord('time').units key4p4 = [ x for x in modelcubes.keys() if 'km4p4' in x ][0] # This just gets the key for the 4.4km model (it changes depending on version) # pdb.set_trace() k = [i for i, x in enumerate(modelcubes[key4p4]) if x][0] daterng = [ x.strftime('%Y%m%dT%H%MZ') for x in newu.num2date(modelcubes[key4p4][k + 1].coord('time').bounds[0]) ] ofile = odir + 'plotOneModel_' + model2plot + '_' + daterng[ 0] + '-' + daterng[1] + '_timeagg' + str(timeagg) + 'hrs.png' # pdb.set_trace() plt.suptitle('Precipitation: GPM compared to %s for\n%s to %s' % (model2plot, daterng[0], daterng[1]), fontsize=18) fig.savefig(ofile, bbox_inches='tight') plt.close(fig) return ofile
def test_pcolormesh(self): # pcolormesh can only be drawn in native coordinates (or more # specifically, in coordinates that don't wrap). plt.axes(projection=ccrs.PlateCarree(central_longitude=180)) iplt.pcolormesh(self.cube) self.check_graphic()
def plot_cartmap(ship_data, cube): import iris.plot as iplt import iris.quickplot as qplt import iris.analysis.cartography import cartopy.crs as ccrs import cartopy # from matplotlib.patches import Polygon ################################### ## PLOT MAP ################################### print ('******') print ('') print ('Plotting cartopy map:') print ('') ################################################## ################################################## #### CARTOPY ################################################## ################################################## SMALL_SIZE = 12 MED_SIZE = 14 LARGE_SIZE = 16 plt.rc('font',size=MED_SIZE) plt.rc('axes',titlesize=MED_SIZE) plt.rc('axes',labelsize=MED_SIZE) plt.rc('xtick',labelsize=SMALL_SIZE) plt.rc('ytick',labelsize=SMALL_SIZE) plt.rc('legend',fontsize=SMALL_SIZE) # plt.rc('figure',titlesize=LARGE_SIZE) ################################################################# ## create figure and axes instances ################################################################# plt.figure(figsize=(5,4)) # ax = plt.axes(projection=ccrs.Orthographic(0, 90)) # NP Stereo ax = plt.axes(projection=ccrs.NorthPolarStereo(central_longitude=0)) ax.set_extent([-180, 190, 80, 90], crs=ccrs.PlateCarree()) ### DON'T USE PLATECARREE, NORTHPOLARSTEREO (on it's own), LAMBERT ################################################################# ## add geographic features/guides for reference ################################################################# ax.add_feature(cartopy.feature.OCEAN, zorder=0) ax.add_feature(cartopy.feature.LAND, zorder=0, edgecolor='black') # ax.set_global() ax.gridlines() ################################################################# ## plot UM data ################################################################# if np.size(cube.shape) == 3: iplt.pcolormesh(cube[9,:,:]) elif np.size(cube.shape) == 2: iplt.pcolormesh(cube[:,:]) if cube.units in locals(): plt.title(cube.standard_name + ', ' + str(cube.units)) else: plt.title(cube.standard_name) plt.colorbar() ################################################################# ## plot UM nest ################################################################# ### draw outline of grid # qplt.outline(cube[0,380:500,230:285]) ################################################################# ## plot ship track ################################################################# ### DEFINE DRIFT + IN_ICE PERIODS drift_index = iceDrift(ship_data) inIce_index = inIce(ship_data) ### Plot tracks as line plot # plt.plot(ship_data.values[:,6], ship_data.values[:,7], # color = 'yellow', linewidth = 2, # transform = ccrs.PlateCarree(), label = 'Whole', # ) plt.plot(ship_data.values[inIce_index,6], ship_data.values[inIce_index,7], color = 'darkorange', linewidth = 3, transform = ccrs.PlateCarree(), label = 'In Ice', ) plt.plot(ship_data.values[inIce_index[0],6], ship_data.values[inIce_index[0],7], 'k^', markerfacecolor = 'darkorange', linewidth = 3, transform = ccrs.PlateCarree(), ) plt.plot(ship_data.values[inIce_index[-1],6], ship_data.values[inIce_index[-1],7], 'kv', markerfacecolor = 'darkorange', linewidth = 3, transform = ccrs.PlateCarree(), ) plt.plot(ship_data.values[drift_index,6], ship_data.values[drift_index,7], color = 'red', linewidth = 4, transform = ccrs.PlateCarree(), label = 'Drift', ) plt.legend() print ('******') print ('') print ('Finished plotting cartopy map! :)') print ('') # plt.savefig('FIGS/Test_AirPressure_t0_wShipTrack.png', dpi=200) plt.show()
import iris import iris.analysis import iris.plot as iplt import matplotlib.pyplot as plt global_air_temp = iris.load_cube(iris.sample_data_path("air_temp.pp")) rotated_psl = iris.load_cube(iris.sample_data_path("rotated_pole.nc")) rotated_air_temp = global_air_temp.regrid(rotated_psl, iris.analysis.Linear()) plt.figure(figsize=(4, 3)) iplt.pcolormesh(rotated_air_temp, norm=plt.Normalize(260, 300)) plt.title("Air temperature\n" "on a limited area rotated pole grid") ax = plt.gca() ax.coastlines(resolution="50m") ax.gridlines() plt.show()
ax = plt.subplot(2, 2, i + 1, projection=ccrs.PlateCarree()) # ax = plt.subplot(2, 2, i + 1, projection=ccrs.Mercator()) ax.coastlines('10m') ax.set_ylim(55, 70) ax.set_xlim(-30, 0) ax.gridlines(draw_labels=True) # This allows you to mask data less than the specified threshold DataField = np.ma.masked_less(cubes.data, threshold) cubes.data = DataField # Plot Using contourf #mappable = iplt.contourf(cubes, levels=contours, colors=colorscale) mappable = iplt.pcolormesh(cubes, cmap='jet', norm=normDosage, edgecolors='none') # Add a title plt.title('mid-point ' + str(Level) + ' m asl\n') # Setting up the Colour Bar cbaxes = fig.add_axes([0.15, 0.05, 0.6, 0.02]) cbartext = 'Air Concentration (g m$^{-3}$)' cb = plt.colorbar(mappable, cax=cbaxes, orientation='horizontal', format='%.1e') cb.ax.set_xlabel(cbartext, fontsize=12) cl = plt.getp(cb.ax, 'xmajorticklabels') plt.setp(cl, fontsize=12)
def plotPostageOneModel(gpmdict, modelcubes, model2plot, timeagg, plotdomain, ofile): # Plot GPM against all lead times from one model try: m = [ i for i, x in enumerate(modelcubes) if x and i > 0 ][0] # i>0 because sometimes the first record doesn't have the correct time span myu = modelcubes[m].coord('time').units daterange = [ x.strftime('%Y%m%dT%H%MZ') for x in myu.num2date(modelcubes[m].coord('time').bounds[0]) ] except: return None odir = os.path.dirname(ofile) if not os.path.isdir(odir): os.makedirs(odir) if len(modelcubes) < 10: diff = 10 - len(modelcubes) # pdb.set_trace() modelcubes = np.repeat(None, diff).tolist() + modelcubes postage = { 1: gpmdict['gpm_prod_data'] if gpmdict['gpm_prod_data'] is not None else gpmdict['gpm_late_data'], 2: gpmdict['gpm_prod_qual'] if gpmdict['gpm_prod_qual'] is not None else gpmdict['gpm_late_qual'], # TODO : Replace the next 2 lines with different observations either from satellite or radar 3: gpmdict['gpm_late_data'] if gpmdict['gpm_prod_data'] is not None else gpmdict['gpm_early_data'], 4: gpmdict['gpm_late_qual'] if gpmdict['gpm_prod_qual'] is not None else gpmdict['gpm_early_qual'], 5: modelcubes[9], 6: modelcubes[8], 7: modelcubes[7], 8: modelcubes[6], 9: modelcubes[5], 10: modelcubes[4], 11: modelcubes[3], 12: modelcubes[2], 13: modelcubes[1], 14: modelcubes[0], 15: None, 16: None } contour_levels = { '3-hrs': [0.0, 0.3, 0.75, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 1000.0], '6-hrs': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '12-hrs': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '24-hrs': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '48-hrs': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '72-hrs': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '96-hrs': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0] } my_rgb = [ '#ffffff', '#87bbeb', '#6a9bde', '#2a6eb3', '#30ca28', '#e2d942', '#f49d1b', '#e2361d', '#f565f5', '#ffffff' ] bounds = contour_levels[str(timeagg) + '-hrs'] norm = colors.BoundaryNorm(boundaries=bounds, ncolors=len(my_rgb)) my_cmap = colors.ListedColormap(my_rgb) qbounds = np.arange(1, 101) # qnorm = colors.BoundaryNorm(boundaries=qbounds, ncolors=len(qbounds) - 1) # Create a wider than normal figure to support our many plots # fig = plt.figure(figsize=(8, 12), dpi=100) fig = plt.figure(figsize=(12, 13), dpi=100) # Also manually adjust the spacings which are used when creating subplots plt.gcf().subplots_adjust(hspace=0.07, wspace=0.05, top=0.92, bottom=0.05, left=0.075, right=0.925) # iterate over all possible latitude longitude slices for i in range(1, 17): # plot the data in a 4 row x 4 col grid if postage[i] is not None: ax = plt.subplot(4, 4, i) if not (postage[i].coord('longitude').has_bounds() or postage[i].coord('latitude').has_bounds()): postage[i].coord('longitude').guess_bounds() postage[i].coord('latitude').guess_bounds() if 'Quality Flag' in postage[i].attributes['title']: qcm = iplt.pcolormesh(postage[i], vmin=0, vmax=100, cmap='cubehelix_r') else: pcm = iplt.pcolormesh(postage[i], norm=norm, cmap=my_cmap) # add coastlines ax = plt.gca() x0, y0, x1, y1 = plotdomain ax.set_extent([x0, x1, y0, y1]) if i > 4: fclt = postage[i].coord('forecast_period').bounds[0] plt.title('T+' + str(int(fclt[0])) + ' to ' + 'T+' + str(int(fclt[1]))) else: plt.title(postage[i].attributes['title']) lakelines = cfeature.NaturalEarthFeature( category='physical', name='lakes', scale='10m', edgecolor=cfeature.COLORS['water'], facecolor='none') ax.add_feature(lakelines) borderlines = cfeature.NaturalEarthFeature( category='cultural', name='admin_0_boundary_lines_land', scale='50m', facecolor='none') ax.add_feature(borderlines, edgecolor='black', alpha=0.5) ax.coastlines(resolution='50m', color='black') ax.gridlines(color="gray", alpha=0.2) # make an axes to put the shared colorbar in colorbar_axes = plt.gcf().add_axes([0.54, 0.1, 0.35, 0.025]) # left, bottom, width, height colorbar = plt.colorbar(pcm, colorbar_axes, orientation='horizontal', extend='neither') try: # colorbar.set_label('%s' % postage[i-2].units) colorbar.set_label('Precipitation amount (mm)') except: while postage[i - 2] is None: i -= 1 # Make another axis for the quality flag colour bar qcolorbar_axes = plt.gcf().add_axes([0.54, 0.2, 0.35, 0.025]) # left, bottom, width, height try: # NB: If there is no quality flag information available, we won't be able to plot the legend qcolorbar = plt.colorbar(qcm, qcolorbar_axes, orientation='horizontal') qcolorbar.set_label('Quality Flag') except: print('No quality flag data available') # Use daterange in the title ... plt.suptitle('Precipitation: GPM compared to %s for\n%s to %s' % (model2plot, daterange[0], daterange[1]), fontsize=18) fig.savefig(ofile, bbox_inches='tight') plt.close(fig) return ofile
def __make_plots__(cube_list, save_filepath, figsize=(16, 9), terrain=cimgt.StamenTerrain(), logscaled=True, vmin=None, vmax=None, colourmap='viridis', colourbarticks=None, colourbarticklabels=None, colourbar_label=None, markerpoint=None, markercolor='#B9DC0C', timestamp=None, time_box_position=None, plottitle=None, box_colour='#FFFFFF', textcolour='#000000', coastlines=False, scheduler_address=None): cubenumber, cube = cube_list if type(figsize) == tuple: fig, ax = plt.subplots(figsize=figsize) Terrain = terrain fig = plt.axes(projection=Terrain.crs) fig.add_image(terrain, 4) if logscaled == True and vmin == None and vmax == None and colourmap == 'viridis': data = iplt.pcolormesh(cube, alpha=1, norm=colors.LogNorm(), cmap='viridis') if logscaled == True and type(vmin) == float and type( vmax) == float and colourmap == 'viridis': data = iplt.pcolormesh(cube, alpha=1, norm=colors.LogNorm(vmin=vmin, vmax=vmax), cmap='viridis') if logscaled == True and vmin == None and vmax == None and type( colourmap) == str: data = iplt.pcolormesh(cube, alpha=1, norm=colors.LogNorm(), cmap=colourmap) if logscaled == True and type(vmin) == float and type( vmax) == float and type(colourmap) == str: data = iplt.pcolormesh(cube, alpha=1, norm=colors.LogNorm(vmin=vmin, vmax=vmax), cmap=colourmap) if logscaled == False and vmin == None and vmax == None and colourmap == 'viridis': data = iplt.pcolormesh(cube, alpha=1, norm=colors.LogNorm(), cmap='viridis') if logscaled == False and type(vmin) == float and type( vmax) == float and colourmap == 'viridis': data = iplt.pcolormesh(cube, alpha=1, vmin=vmin, vmax=vmax, cmap='viridis') if logscaled == False and vmin == None and vmax == None and type( colourmap) == str: data = iplt.pcolormesh(cube, alpha=1, cmap=colourmap) if logscaled == False and type(vmin) == float and type( vmax) == float and type(colourmap) == str: data = iplt.pcolormesh(cube, alpha=1, vmin=vmin, vmax=vmax, cmap=colourmap) if coastlines == True: plt.gca().coastlines('50m') cbaxes = plt.axes([0.2, 0.25, 0.65, 0.03]) colorbar = plt.colorbar(data, cax=cbaxes, orientation='horizontal') colorbar.set_ticks(colourbarticks) colorbar.set_ticklabels(colourbarticklabels) if colourbar_label is not None: colorbar.set_label(colourbar_label, fontproperties='FT2Font', color=box_colour, fontsize=8, bbox=dict(facecolor=box_colour, edgecolor='#2A2A2A', boxstyle='square')) if markerpoint is not None and markercolor is not None: longitude, latitude, name_of_place = markerpoint fig.plot(longitude, latitude, marker='^', color=markercolor, markersize=12, transform=ccrs.Geodetic()) geodetic_transform = ccrs.Geodetic()._as_mpl_transform(fig) text_transform = offset_copy(geodetic_transform, units='dots', y=+75) fig.text(longitude, latitude, u + name_of_place, fontproperties='FT2Font', alpha=1, fontsize=8, verticalalignment='center', horizontalalignment='right', transform=text_transform, bbox=dict(facecolor=markercolor, edgecolor='#2A2A2A', boxstyle='round')) if timestamp is not None: attributedict = subset.attributes datetime = attributedict.get(timestamp) timetransform = offset_copy(geodetic_transform, units='dots', y=0) longitude_of_time_box, latitude_of_time_box = time_box_position fig.text(longitude_of_time_box, latitude_of_time_box, "Time, date: " + datetime, fontproperties='FT2Font', alpha=0.7, fontsize=8, transform=timetransform, bbox=dict(facecolor=markercolor, edgecolor='#2A2A2A', boxstyle='round')) if plottitle is not None: titleaxes = plt.axes([0.2, 0.8, 0.65, 0.04], facecolor=box_colour) titleaxes.text(0.5, 0.25, plottitle, horizontalalignment='center', fontproperties='FT2Font', fontsize=10, weight=600, color=textcolour) titleaxes.set_yticks([]) titleaxes.set_xticks([]) picturename = save_filepath + "%04i.png" % cubenumber plt.savefig(picturename, dpi=200, bbox_inches="tight")
def plot_map( dcube_input, fig=None, ax=None, cont=False, vrange=[-1, 1], vstep=0.2, vmid=None, cpal="RdBu_r", bar_tick_spacing=1, bar_orientation="horizontal", bar_position=None, extendcolbar="both", badcol=(1, 1, 1, 0), undercol="magenta", overcol="yellow", cmsize=[23, 18], dpi=DPI_SAVING, dpi_display=DPI_DISPLAY, fsize=12, fontfam="Arial", proj=ccrs.PlateCarree(), marlft=0.03, marrgt=0.97, martop=0.96, marbot=0.06, marwsp=0, marhsp=0, contlines=None, contlinew=1.0, contlinecol="yellow", contlinealpha=1, countrylw=1, countrylcol="grey", regionlw=1, regionlcol=None, riverslw=1, riverslcol=None, coastlw=1, coastlcol="black", gridlw=0.5, gridlcol="grey", gridlsty=":", barlabel="Unknown", preferred_unit=None, xlims=None, ylims=None, showglobal=False, xlims_for_grid=None, ylims_for_grid=None, dxgrid=20, dygrid=20, xgridax=[True, False], ygridax=[True, False], mask_sea=False, mask_land=False, lsm_cube=None, axbackgroundcol=None, figbackgroundcol=None, outfnames=["x11"], ): """ All the gubbins required to make a nice map. Most arguments are the same as components of a stds.StandardMap object; see there for further documentation. dcube is a single 2-D cube holding the data to plot. outfnames is a list of strings; If any end in 'x11', the plot will be displayed onscreen; otherwise, it attempts to write it to a file. To NOT plot to file or screen, set outfnames=None; you can then add other things to the plot as the Axes object is returned. """ # FIRST THING is to convert the unit of the data cube, if required. # (if not, just point dcube to the input cube without a copy) if preferred_unit is not None: if dcube_input.units != preferred_unit: LOG.debug( "NOTE: converting cube units (in a copy) from %s to %s", dcube_input.units.name, preferred_unit.name, ) dcube = dcube_input.copy() # Got a function to do all this now: rectify_units(dcube, target_unit=preferred_unit) else: # Already in the right units dcube = dcube_input else: # No preferred unit, leave as it is: dcube = dcube_input # Show the value range, and the units: LOG.debug( "Input cube value range: %s-%s %s", dcube.data.min(), dcube.data.max(), dcube.units.title(""), ) # Next, add a mask to the cube covering the sea/land as selected. # We go by the assumption that, in the land-sea mask (LSM) file, # 1 ==> land, 0 ==> sea. # So to mask out the sea, we mask where LSM < 0.5, # and to mask out the land, we mask where LSM > 0.5. if mask_sea or mask_land: if lsm_cube is None: LOG.warning( "No land--sea mask specified, but mask requested " "(sea:%s; land:%s,)", mask_sea, mask_land, ) raise UserWarning("Land--sea mask cube required in plot_map().") # LOG.debug("Applying LSM:") # Note we let the user mask either the land or sea or both (!). # More fool them. if mask_sea: dcube_masked = add_mask(dcube, lsm_cube, comparator="<", threshold=0.5) if mask_land: dcube_masked = add_mask(dcube, lsm_cube, comparator=">", threshold=0.5) else: # Leave as it is: dcube_masked = dcube # Set up the Figure object, if required: if fig is None: newfig = True # Set up the Figure object # (including setting the font family and size) fig, oldfont_family, oldfont_size = start_figure( cmsize, dpi_display, fontfam, fsize, figbackgroundcol) else: # Figure object already exists. newfig = False LOG.debug("Figure object already exists, ") LOG.debug("Not using plot_map() arguments: ") LOG.debug(" cmsize,dpi_display, fsize,fontfam,") LOG.debug(" marlft,marrgt,martop,marbot,marwsp,marhsp") # Set up the Axes object: if ax is None: # Set up the Axes object as a cartopy GeoAxes object, # i.e. one that is spatial-aware, so we can add coastlines etc later.) # (just doing the iplt.contourf will also do this, # but we'd have to grab the gca() afterwards then) ax = plt.axes(projection=proj) else: # Already got an Axes object: LOG.debug("Axes object already exists,") LOG.debug("Not using plot_map() argument: proj") # Set the Axes background colour: # The user can specify the alpha by using an rgba tuple, # e.g. (1,0,1,0.5) would be semitransparent magenta. if axbackgroundcol is not None: ax.patch.set_facecolor(axbackgroundcol) # ax.patch.set_alpha(1.0) # Set up colour bar: # http://matplotlib.org/examples/color/colormaps_reference.html # levels = np.arange(vrange[0], vrange[1] + vstep, vstep) # np.arange can give inconsistent results # https://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html # Allow for not labelling every colour in the colourbar: levels_labelled = np.arange(vrange[0], vrange[1] + vstep * bar_tick_spacing, vstep * bar_tick_spacing) # Set up the colourmap: cmap = _setup_colourmap(cpal, vrange, vstep, vmid=vmid) # Add values for bad/over/under: # Note we're not hardcoding an alpha value. # The user can specify it through badcol by using an rgba tuple, # e.g. (1,0,1,0.5) would be semitransparent magenta. if badcol is not None: cmap.set_bad(color=badcol) # Require the user to have specified overcol and undercol: cmap.set_over(color=overcol) cmap.set_under(color=undercol) # Set plot limits. # For some projections (Robinson!), # it only makes sense to use them globally, # but setting global extents seems to confuse it. # So we have an override option: if showglobal: ax.set_global() else: # A previous version prevented specifying Axes extents # if we used the ccrs.OSGB() projection; # now we have a better projection, # I've removed that special case, letting it get confused # if anyone uses it... # Get the x/y limits from the data if they're not specified: if not xlims: xlims = [ dcube_masked.coord("longitude").points.min(), dcube_masked.coord("longitude").points.max(), ] if not ylims: ylims = [ dcube_masked.coord("latitude").points.min(), dcube_masked.coord("latitude").points.max(), ] ax.set_extent(xlims + ylims, crs=proj) # Only label the axes if we're in the Plate Carrée projection: if proj == ccrs.PlateCarree(): ax.set_xlabel(r"Longitude") ax.set_ylabel(r"Latitude") # Plot the data! if cont: # Filled contours # (always discrete colours, unless you cheat and have many colours) cf = iplt.contourf(dcube_masked, levels, cmap=cmap, extend=extendcolbar) else: # Shaded gridcells # (discrete colours if the number is given when setting up cmap, # otherwise continuous colours) cf = iplt.pcolormesh(dcube_masked, cmap=cmap, vmin=vrange[0], vmax=vrange[1]) # Add extra annotations! # e.g. http://www.naturalearthdata.com/downloads/50m-cultural-vectors/ # Extra contour lines, if requested: if contlines is not None: # Set the negative linestyle to be solid, like positive. # (the default is 'dashed'; 'dotted' doesn't work) matplotlib.rcParams["contour.negative_linestyle"] = "solid" # The original pbskill_maps.py routine # had a bit here for outlining [lat--lon-defined] subregions. # I've cut this from here, # as regional maps should probably be done elsewhere... # Add gridlines if the grid linewidth > 0 # (and label them on the axes, IF we're in PlateCarree) if gridlcol is not None: gridlabels = proj == ccrs.PlateCarree() gl = ax.gridlines( crs=ccrs.PlateCarree(), draw_labels=gridlabels, linewidth=gridlw, linestyle=gridlsty, color=gridlcol, ) if gridlabels: # Options to switch on/off individual axes labels: gl.xlabels_bottom = xgridax[0] gl.xlabels_top = xgridax[1] gl.ylabels_left = ygridax[0] gl.ylabels_right = ygridax[1] # Set limits for the grid separate to the plot's xlims/ylims: if showglobal: xlims_for_grid = [-180, 180] ylims_for_grid = [-90, 90] else: if xlims_for_grid is None: xlims_for_grid = (xlims if xlims is not None else [ dcube_masked.coord("longitude").points.min(), dcube_masked.coord("longitude").points.max(), ]) if ylims_for_grid is None: ylims_for_grid = (ylims if ylims is not None else [ dcube_masked.coord("latitude").points.min(), dcube_masked.coord("latitude").points.max(), ]) xgridrange = [ float(dxgrid) * np.round(float(val) / float(dxgrid)) for val in xlims_for_grid ] ygridrange = [ float(dygrid) * np.round(float(val) / float(dygrid)) for val in ylims_for_grid ] xgridpts = np.arange(xgridrange[0], xgridrange[1] + dxgrid, dxgrid) ygridpts = np.arange(ygridrange[0], ygridrange[1] + dygrid, dygrid) # Filter in case the rounding meant we went off-grid! xgridpts = [ xgridpt for xgridpt in xgridpts if (xgridpt >= -180 and xgridpt <= 360) ] ygridpts = [ ygridpt for ygridpt in ygridpts if (ygridpt >= -90 and ygridpt <= 90) ] gl.xlocator = mticker.FixedLocator(xgridpts) gl.ylocator = mticker.FixedLocator(ygridpts) if gridlabels: gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER # Adjust the margins: if newfig: # We could legally do this even if this wasn't a new figure, # (we've got the figure object using gcf() above), # but in practice we'll be designing the multipanel figure # elsewhere, and that is where the margins should be set. if marlft is None and marrgt is None and martop is None and marbot is None: plt.tight_layout() else: fig.subplots_adjust( left=marlft, bottom=marbot, right=marrgt, top=martop, wspace=marwsp, hspace=marhsp, ) # (note that we have a wrapper, plotgeneral.set_standard_margins(), # which does this for a StandardMap object) # Colour bar: if bar_orientation.lower() == "none": LOG.debug("Skipping colour bar") else: make_colourbar( fig, bar_orientation, extendcolbar, levels_labelled, barlabel, colmappable=cf, bar_pos=bar_position, ) # Finally, make the plot, if we've provided any filenames: if outfnames is not None: # This saves to any filenames if specified, and/or displays to screen, # closes the plot and resets the font family & size. end_figure(outfnames, dpi=dpi, oldfont_family=oldfont_family, oldfont_size=oldfont_size) else: LOG.debug("No outfnames provided, continue plotting using Axes ax") LOG.debug("All done in plot_map, returning") return (ax, cf)
data_save = '/data/users/sburgan/CP4A/processed_data/Southern_Africa/' if __name__ == '__main__': ################# read in data ##################### cp4 = iris.load_cube(data_dir + 'Southern Africa_CP4A_daily_precip_*') # for CP4 to convert kg/ms/s to mm/day #cp4.data = cp4.data*86400.0 cp4 = cp4 * 86400.0 # test plot to check the right area crs_latlon = ccrs.PlateCarree() ax = plt.axes(projection=crs_latlon) iplt.pcolormesh(cp4[0, :, :]) ax.set_extent((60, -50, 50, -50), crs=crs_latlon) ax.gridlines(crs=crs_latlon, linestyle=':') ax.add_feature(cfeature.BORDERS, linestyle='-') ax.add_feature(cfeature.COASTLINE, linestyle='-') plt.plot(39.27, -6.80, marker='o', markersize=4.0, markerfacecolor='red', transform=crs_latlon) iplt.show() ################# generate timeseries ##################### # this section could probably be done better as a loop!
color='gray', alpha=0.5, linestyle='--') gl.xlabels_top = False gl.xlabel_style = {'size': 11, 'color': 'gray'} #gl.xlines = False #gl.set_xticks() #gl.set_yticks() gl.xformatter = LONGITUDE_FORMATTER gl.ylabel_style = {'size': 11, 'color': 'gray'} #ax.ylabels_left = False gl.yformatter = LATITUDE_FORMATTER # plot with Iris quickplot pcolormesh #cs = iplt.pcolormesh(cube_ORAS4_atlantic_regrid,cmap='coolwarm',vmin=0,vmax=1) cs = iplt.pcolormesh(cube_ORAS4_atlantic_regrid, cmap='RdYlBu', vmin=0, vmax=1) cbar = fig1.colorbar(cs, extend='both', orientation='horizontal', shrink=0.8, pad=0.05) cbar.set_label('sea-land') # show and save plot iplt.show() fig1.savefig(output_path + os.sep + 'atlantic_mask_ORAS4.jpg', dpi=500) print '======================== GLORYS2V3 ========================' # define the cube for the use of iris package latitude_GLORYS2V3 = iris.coords.AuxCoord(lat_GLORYS2V3, standard_name='latitude',
cube_copy.data[i][j] = 1.0 else: cube_copy.data[i][j] = 0.0 N+=1 # now sum the binary value site cubes to create 'hotspot' cube to show extent of overlap between site plumes if N == 1: sites_cube = cube_copy else: sites_cube = iris.analysis.maths.add(sites_cube,cube_copy, dim=None, ignore=True, in_place=True) # plot plt.figure(figsize=(10,5)) ax = iplt.plt.axes(projection=iplt.ccrs.PlateCarree()) plot = iplt.pcolormesh(sites_cube,cmap='YlGnBu', vmin=0, vmax=len(rundirs)+2) ax.coastlines(resolution='50m', color='black', linewidth=1) ax.add_feature(iplt.cartopy.feature.BORDERS) ax.gridlines() ax.set_xlim(lon_min,lon_max) ax.set_ylim(lat_min,lat_max) sl_plot = plt.scatter(source_locations_x, source_locations_y, c='r', marker=(5, 1),s=50,linewidth=0.5) plt.gca().coastlines() cbar = plt.colorbar(plot, ticks = np.arange(len(rundirs)+2)) cbar.set_label('Plume overlap (number of sites)') plt.title('Plume overlap between '+str(N)+' sites') plt.savefig('Plot_plume_overlap_between_'+str(N)+'_sites_for_sandpit.png') plt.close()
def make_plot(projection_name, projection_crs): # Create a matplotlib Figure. plt.figure() # Add a matplotlib Axes, specifying the required display projection. # NOTE: specifying 'projection' (a "cartopy.crs.Projection") makes the # resulting Axes a "cartopy.mpl.geoaxes.GeoAxes", which supports plotting # in different coordinate systems. ax = plt.axes(projection=projection_crs) # Set display limits to include a set region of latitude * longitude. # (Note: Cartopy-specific). ax.set_extent((-80.0, 20.0, 10.0, 80.0), crs=crs_latlon) # Add coastlines and meridians/parallels (Cartopy-specific). ax.coastlines(linewidth=0.75, color='navy') ax.gridlines(crs=crs_latlon, linestyle='-') # Plot the first dataset as a pseudocolour filled plot. maindata_filepath = iris.sample_data_path('rotated_pole.nc') main_data = iris.load_cube(maindata_filepath) # NOTE: iplt.pcolormesh calls "pyplot.pcolormesh", passing in a coordinate # system with the 'transform' keyword: This enables the Axes (a cartopy # GeoAxes) to reproject the plot into the display projection. iplt.pcolormesh(main_data, cmap='RdBu_r') # Overplot the other dataset (which has a different grid), as contours. overlay_filepath = iris.sample_data_path('space_weather.nc') overlay_data = iris.load_cube(overlay_filepath, 'total electron content') # NOTE: as above, "iris.plot.contour" calls "pyplot.contour" with a # 'transform' keyword, enabling Cartopy reprojection. iplt.contour(overlay_data, 20, linewidths=2.0, colors='darkgreen', linestyles='-') # Draw a margin line, some way in from the border of the 'main' data... # First calculate rectangle corners, 7% in from each corner of the data. x_coord, y_coord = main_data.coord(axis='x'), main_data.coord(axis='y') x_start, x_end = np.min(x_coord.points), np.max(x_coord.points) y_start, y_end = np.min(y_coord.points), np.max(y_coord.points) margin = 0.07 margin_fractions = np.array([margin, 1.0 - margin]) x_lower, x_upper = x_start + (x_end - x_start) * margin_fractions y_lower, y_upper = y_start + (y_end - y_start) * margin_fractions box_x_points = x_lower + (x_upper - x_lower) * np.array([0, 1, 1, 0, 0]) box_y_points = y_lower + (y_upper - y_lower) * np.array([0, 0, 1, 1, 0]) # Get the Iris coordinate sytem of the X coordinate (Y should be the same). cs_data1 = x_coord.coord_system # Construct an equivalent Cartopy coordinate reference system ("crs"). crs_data1 = cs_data1.as_cartopy_crs() # Draw the rectangle in this crs, with matplotlib "pyplot.plot". # NOTE: the 'transform' keyword specifies a non-display coordinate system # for the plot points (as used by the "iris.plot" functions). plt.plot(box_x_points, box_y_points, transform=crs_data1, linewidth=2.0, color='white', linestyle='--') # Mark some particular places with a small circle and a name label... # Define some test points with latitude and longitude coordinates. city_data = [('London', 51.5072, 0.1275), ('Halifax, NS', 44.67, -63.61), ('Reykjavik', 64.1333, -21.9333)] # Place a single marker point and a text annotation at each place. for name, lat, lon in city_data: plt.plot(lon, lat, marker='o', markersize=7.0, markeredgewidth=2.5, markerfacecolor='black', markeredgecolor='white', transform=crs_latlon) # NOTE: the "plt.annotate call" does not have a "transform=" keyword, # so for this one we transform the coordinates with a Cartopy call. at_x, at_y = ax.projection.transform_point(lon, lat, src_crs=crs_latlon) plt.annotate( name, xy=(at_x, at_y), xytext=(30, 20), textcoords='offset points', color='black', backgroundcolor='white', size='large', arrowprops=dict(arrowstyle='->', color='white', linewidth=2.5)) # Add a title, and display. plt.title('A pseudocolour plot on the {} projection,\n' 'with overlaid contours.'.format(projection_name)) iplt.show()
def plotGPM(cube_dom, outdir, domain, overwrite, accum='12hr'): print(accum + ' Accumulation') this_title = accum + ' Accumulation (mm)' ofilelist = [] # print(np.nanmin(cube_dom.data)) if accum == '24hr': # Aggregate by day_of_year. # NB: Data is in mm/hr for each half hour timestep, so divide by 2 cube_dom_acc = cube_dom.aggregated_by('day_of_year', iris.analysis.SUM) / 2. these_units = 'Accumulated rainfall (mm/24hrs)' if accum == '12hr': # Aggregate by am or pm ... # NB: Data is in mm/hr for each half hour timestep, so divide by 2 cube_dom_acc = cube_dom.aggregated_by(['day_of_year', 'am_or_pm'], iris.analysis.SUM) / 2. these_units = 'Accumulated rainfall (mm/12hrs)' if accum == '6hr': # Aggregate by 6hr period # NB: Data is in mm/hr for each half hour timestep, so divide by 2 cube_dom_acc = cube_dom.aggregated_by(['day_of_year', '6hourly'], iris.analysis.SUM) / 2. these_units = 'Accumulated rainfall (mm/6hrs)' if accum == '3hr': # Aggregate by 3hr period # NB: Data is in mm/hr for each half hour timestep, so divide by 2 cube_dom_acc = cube_dom.aggregated_by(['day_of_year', '3hourly'], iris.analysis.SUM) / 2. these_units = 'Accumulated rainfall (mm/3hrs)' if accum == '30mins': # Don't aggregate! # NB: Data is in mm/hr for each half hour timestep, so divide by 2 cube_dom_acc = cube_dom.copy() this_title = 'Rate (mm/hr) for 30-min Intervals' these_units = 'Accumulated rainfall (mm/hr)' contour_levels = { '30mins': [0.0, 0.1, 0.25, 0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 1000.0], '3hr': [0.0, 0.3, 0.75, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 1000.0], '6hr': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '12hr': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '24hr': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0] } my_rgb = [ '#ffffff', '#87bbeb', '#6a9bde', '#2a6eb3', '#30ca28', '#e2d942', '#f49d1b', '#e2361d', '#f565f5', '#ffffff' ] # Plot the cube. for i in range(0, cube_dom_acc.shape[0]): print('Plotting ' + accum + ': ' + str(i + 1) + ' / ' + str(cube_dom_acc.shape[0])) # Prepare time coords tcoord = cube_dom_acc[i].coord('time') tu = tcoord.units tpt = tu.num2date(tcoord.bounds[0][1]) + timedelta( seconds=1) # Get the upper bound and nudge it the hour # Define the correct output dir and filename thisyr = tpt.strftime('%Y') thismon = tpt.strftime('%m') thisday = tpt.strftime('%d') timestamp = tpt.strftime('%Y%m%dT%H%MZ') ofile = outdir + thisyr + '/' + thismon + '/' + thisday + '/gpm-precip_' + accum + '_' + timestamp + '.png' print('Plotting ' + accum + ': ' + timestamp + ' (' + str(i) + ' / ' + str(cube_dom_acc.shape[0] - 1) + ')') if not os.path.isfile(ofile) or overwrite: this_localdir = os.path.dirname(ofile) if not os.path.isdir(this_localdir): os.makedirs(this_localdir) # Now do the plotting fig = plt.figure(figsize=getFigSize(domain), dpi=96) bounds = contour_levels[accum] norm = colors.BoundaryNorm(boundaries=bounds, ncolors=len(my_rgb)) my_cmap = matplotlib.colors.ListedColormap(my_rgb) pcm = iplt.pcolormesh(cube_dom_acc[i], norm=norm, cmap=my_cmap) plt.title('GPM Precipitation ' + this_title + ' at\n' + tpt.strftime('%Y-%m-%d %H:%M')) plt.xlabel('longitude / degrees') plt.ylabel('latitude / degrees') var_plt_ax = plt.gca() var_plt_ax.set_extent(domain) # var_plt_ax.coastlines(resolution='50m') borderlines = cfeature.NaturalEarthFeature( category='cultural', name='admin_0_boundary_lines_land', scale='50m', facecolor='none') var_plt_ax.add_feature(borderlines, edgecolor='black', alpha=0.5) var_plt_ax.coastlines(resolution='50m', color='black') gl = var_plt_ax.gridlines(color="gray", alpha=0.2, draw_labels=True) gl.xlabels_top = False gl.ylabels_left = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.xlabel_style = {'size': 8} gl.ylabel_style = {'size': 8} vleft, vbottom, vwidth, vheight = var_plt_ax.get_position().bounds plt.gcf().subplots_adjust(top=vbottom + vheight, bottom=vbottom + 0.04, left=vleft, right=vleft + vwidth) cbar_axes = fig.add_axes([vleft, vbottom - 0.02, vwidth, 0.02]) cbar = plt.colorbar(pcm, norm=norm, boundaries=bounds, cax=cbar_axes, orientation='horizontal', extend='both') cbar.set_label(these_units) cbar.ax.tick_params(length=0) fig.savefig(ofile, bbox_inches='tight') plt.close(fig) if os.path.isfile(ofile): # Add it to the list of files ofilelist = ofilelist + [ofile] # Make sure everyone can read it os.chmod(ofile, 0o777) return (ofilelist)
def test_xaxis_labels(self): iplt.pcolormesh(self.cube, coords=('str_coord', 'bar')) self.assertBoundsTickLabels('xaxis')
regional_ash = iris.load_cube(iris.sample_data_path('NAME_output.txt')) regional_ash = regional_ash.collapsed('flight_level', iris.analysis.SUM) # Mask values so low that they are anomalous. regional_ash.data = np.ma.masked_less(regional_ash.data, 5e-6) norm = matplotlib.colors.LogNorm(5e-6, 0.0175) global_air_temp.coord('longitude').guess_bounds() global_air_temp.coord('latitude').guess_bounds() fig = plt.figure(figsize=(8, 4.5)) plt.subplot(2, 2, 1) iplt.pcolormesh(regional_ash, norm=norm) plt.title('Volcanic ash total\nconcentration not regridded', size='medium') for subplot_num, mdtol in zip([2, 3, 4], [0, 0.5, 1]): plt.subplot(2, 2, subplot_num) scheme = iris.analysis.AreaWeighted(mdtol=mdtol) global_ash = regional_ash.regrid(global_air_temp, scheme) iplt.pcolormesh(global_ash, norm=norm) plt.title('Volcanic ash total concentration\n' 'regridded with AreaWeighted(mdtol={})'.format(mdtol), size='medium') plt.subplots_adjust(hspace=0, wspace=0.05, left=0.001, right=0.999,
lat, lon = mask.dim_coords nlat, nlon = mask.shape cyclic = lon.points[0] == 0 and abs(lon.points[-1] + lon.points[1] - 360.) < 1e-4 if mask.data.min() < 0: # Plots better when flipped mask.data = -1*mask.data cmap = matplotlib.colors.ListedColormap(((0.7,0.7,1),(0,0.5,0))) changed = False if cyclic: ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180)) global PM PM = iplt.pcolormesh(mask,cmap=cmap) if args.mapres == 'l': plt.gca().coastlines(resolution='110m') elif args.mapres == 'h': plt.gca().coastlines(resolution='10m') else: plt.gca().coastlines(resolution='50m') # Make a copy so can see what's changed later # (PM.set_array alters mask.data for LAMs) origmask = np.array(mask.data[:]) # From the image_zcoord example def format_coord(x, y):
def make_pv_plot(pv, **kwargs): im = iplt.pcolormesh(pv, **kwargs) iplt.contour(pv, [2], colors='k', linewidths=2) add_map() return im
def plot_map(df, data_type='AOD', lat=(-90, 90), lon=(-180, 180), plot_type='pcolormesh', show=True, grid_size=0.5, vmin=None, vmax=None, show_limits=True): ''' For a (list of) DataFrame(s) this function will plot the average of the total or dust AOD onto a map. For a (list of) MatchFrame(s) several different values can be plotted on a map. These are the average difference in AOD or time (data_set[1] - data_set[0]), the local RMS values, or the number of matched-up data points. If AERONET data is included then the individual sites will be plotted, otherwise it will be plotted on a grid. Parameters ---------- df : AeroCT DataFrame / MatchFrame, or list of DataFrames / MatchFrames data_type : str, optional (Default: 'AOD') This describes which type of data to plot. If df is a DataFrame(s) then it describes the type of AOD data to plot. It can take any one of the values 'AOD', 'dust AOD', or 'total AOD'. If 'AOD' is chosen then the total AOD will be plotted, unless the data frame has only dust AOD in which case that will be plotted. If df is a MatchFrame(s) then it can take the any of the values: 'AOD' - Plot the mean AOD bias between the two data sets for each location. 'RMS' - Plot the local RMS values. 'time diff' - Plot the average time difference between the two data sets. 'heatmap' - Plot the number of matched-up data points within each location. lat : tuple, optional (Default: (-90, 90)) A tuple of the latitude bounds of the plot in degrees. lon : tuple, optional (Default: (-180, 180)) A tuple of the longitude bounds of the plot in degrees. plot_type : str, optional (Default: 'pcolormesh') The type of plot to produce if it does not contain AERONET data. 'scatter' to plot a scatter grid of all AOD data, and 'pcolormesh' or 'contourf' for griddded plots. The grid cell values for gridded plots are found by using a cubic interpolation scheme with scipy.interpolate.griddata(). show : bool, optional (Default: True) If True the figure is shown, otherwise it is returned grid_size : float, optional (Default: 0.5) The size of the grid squares in degrees if not using indivdual sites vmin, vmax : scalar, optional (Default: None) vmin and vmax are used to set limits for the color map. If either is None, it is autoscaled to the respective min or max of the plotted data. show_limits : bool, optional (Default: True) If True, the minimum and maximum of the data is shown under the plot. ''' # Convert a list of match frames to a single match frame that may be plotted if isinstance(df, list): df = aeroct.concatenate_data_frames(df) date = '{0} to {1}'.format(df.date[0].date(), df.date[-1].date()) elif isinstance(df.date, list): date = '{0} to {1}'.format(df.date[0].date(), df.date[-1].date()) else: date = df.date.date() fig = plt.figure(figsize=(8, 6)) ax = plt.axes(projection=ccrs.PlateCarree()) plt.xlim(lon) plt.ylim(lat) mon_cmap = cm.get_cmap('inferno_r') div_cmap = cm.get_cmap('RdYlBu_r') # USE IRIS PLOT IF THERE IS A CUBE IN THE DATA FRAME if df.cube is not None: # Suppress warnings and plot with warnings.catch_warnings(): warnings.simplefilter("ignore", category=UserWarning) day_avg_cube = df.cube.collapsed('time', analysis.MEAN) if df.__class__.__name__ == 'DataFrame': plt.title('{0}: Dust AOD Mean For {1}'.format(df.name, date)) cmap = mon_cmap data = day_avg_cube.aod else: plt.title('Dust AOD Difference (Mean) ({0} - {1}) for {2}'\ .format(df.names[1], df.names[0], date)) cmap = shiftedColorMap(div_cmap, day_avg_cube.data, vmin, vmax) data = day_avg_cube.data if plot_type == 'pcolormesh': iplt.pcolormesh(day_avg_cube, cmap=cmap, vmin=vmin, vmax=vmax) elif plot_type == 'contourf': iplt.contourf(day_avg_cube, cmap=cmap, vmin=vmin, vmax=vmax) elif df.__class__.__name__ == 'DataFrame': # Select the total or dust AOD data which is in the given bounds if data_type == 'AOD': aod, lons, lats = df.get_data(None)[:3] aod_type = df.get_data(None, return_type=True)[-1] elif data_type in ['total', 'total AOD']: aod, lons, lats = df.get_data('total')[:3] aod_type = 'total' elif data_type in ['dust', 'dust AOD']: aod, lons, lats = df.get_data('dust')[:3] aod_type = 'dust' plt.title('{0}: {1} AOD Mean For {2}'.format(df.name, aod_type.title(), date)) cmap = mon_cmap in_bounds = (lon[0] < lons) & (lons < lon[1]) & (lat[0] < lats) & ( lats < lat[1]) data = aod[in_bounds] lons = lons[in_bounds] lats = lats[in_bounds] # PLOT AOD AT AERONET SITES AS A SCATTER PLOT if df.data_set == 'aeronet': # Get the list of data points at each location site_lons, i_site = np.unique(lons, return_index=True) site_lats = lats[i_site] in_sites = site_lons[:, np.newaxis] == lons # Average the AOD at each site and take std data = np.mean(data * in_sites, axis=1) # aod_site_std = np.sqrt(np.mean(data**2 * in_sites, axis=1) - aod_site_avg**2) plt.scatter(site_lons, site_lats, c=data, cmap=cmap, edgecolors='k', linewidths=0.2, s=100, vmin=vmin, vmax=vmax) # PLOT THE AOD AT EVERY DATA POINT elif plot_type == 'scatter': plt.scatter(lons, lats, c=data, marker='o', s=(50. / fig.dpi)**2, vmin=vmin, vmax=vmax) # OTHERWISE PLOT A GRID else: # Using scipy.interpolate.griddata # First get the axes grid = np.mgrid[(lon[0] + grid_size / 2):lon[1]:grid_size, (lat[0] + grid_size / 2):lat[1]:grid_size] ll = zip(lons, lats) data = griddata(ll, data, tuple(grid), method='linear') # Mask grid data where there are no nearby points. Firstly create kd-tree THRESHOLD = 2 * grid_size # Maximum distance to look for nearby points tree = cKDTree(ll) xi = _ndim_coords_from_arrays(tuple(grid)) dists = tree.query(xi)[0] # Copy original result but mask missing values with NaNs data[dists > THRESHOLD] = np.nan if plot_type == 'pcolormesh': plt.pcolormesh(grid[0], grid[1], data, cmap=cmap, vmin=vmin, vmax=vmax) elif plot_type == 'contourf': plt.contourf(grid[0], grid[1], data, cmap=cmap, vmin=vmin, vmax=vmax) elif df.__class__.__name__ == 'MatchFrame': # Find the data within the given longitude and latitude bounds in_bounds = (df.longitudes > lon[0]) & (df.longitudes < lon[1]) & \ (df.latitudes > lat[0]) & (df.latitudes < lat[1]) lons = df.longitudes[in_bounds] lats = df.latitudes[in_bounds] # Get the data for which to find the area average and the title if data_type == 'time diff': data = df.time_diff[in_bounds] plt.title('Mean Time Difference ({0} - {1})\n for {2}'\ .format(df.names[1], df.names[0], date)) elif data_type == 'RMS': data = (df.data[1, in_bounds] - df.data[0, in_bounds])**2 plt.title('Root Mean Square ({0}, {1})\n for {2}'\ .format(df.names[0], df.names[1], date)) elif data_type == 'heatmap': data = np.ones_like(df.data[1, in_bounds]) plt.title('Number Of Matched Data Points ({0}, {1})\n for {2}'\ .format(df.names[0], df.names[1], date)) else: data = df.data[1, in_bounds] - df.data[0, in_bounds] plt.title('Mean AOD Difference ({0} - {1})\n for {2}'\ .format(df.names[1], df.names[0], date)) # If AERONET is included plot the sites on a map if np.any([df.data_sets[i] == 'aeronet' for i in [0, 1]]): # Get the list of data points at each location site_lons, i_site = np.unique(lons, return_index=True) site_lats = lats[i_site] in_sites = site_lons[:, np.newaxis] == lons # Average the AOD at each site and take std data = np.mean(data * in_sites, axis=1) if data_type == 'RMS': data = np.sqrt(data) cmap = mon_cmap elif data_type == 'heatmap': data = np.sum(in_sites, axis=1) cmap = mon_cmap else: # Shift colour map to have a midpoint of zero cmap = shiftedColorMap(div_cmap, data, vmin, vmax) plt.scatter(site_lons, site_lats, c=data, s=(500 / fig.dpi)**2, edgecolors='k', linewidths=0.2, cmap=cmap, vmin=vmin, vmax=vmax) # OTHERWISE PLOT A GRID else: # Using scipy.interpolate.griddata # First get the axes grid = np.mgrid[(lon[0] + grid_size / 2):lon[1]:grid_size, (lat[0] + grid_size / 2):lat[1]:grid_size] ll = zip(lons, lats) if data_type == 'heatmap': lon_edges = np.arange(lon[0], lon[1] + 1e-5, grid_size) lat_edges = np.arange(lat[0], lat[1] + 1e-5, grid_size) data = np.histogram2d(lons, lats, [lon_edges, lat_edges])[0] else: data = griddata(ll, data, tuple(grid), method='cubic') # Mask grid data where there are no nearby points. Firstly create kd-tree THRESHOLD = grid_size # Maximum distance to look for nearby points tree = cKDTree(ll) xi = _ndim_coords_from_arrays(tuple(grid)) dists = tree.query(xi)[0] # Copy original result but mask missing values with NaNs data[dists > THRESHOLD] = np.nan if data_type == 'RMS': data = np.sqrt(data) if data_type in ['RMS', 'heatmap']: cmap = mon_cmap else: # Shift colour map to have a midpoint of zero cmap = shiftedColorMap(div_cmap, data, vmin, vmax) if plot_type == 'pcolormesh': plt.pcolormesh(grid[0], grid[1], data, cmap=cmap, vmin=vmin, vmax=vmax) elif plot_type == 'contourf': plt.contourf(grid[0], grid[1], data, cmap=cmap, vmin=vmin, vmax=vmax) if show_limits: limits = (np.nanmin(data), np.nanmax(data)) fig.text(0.5, 0.22, 'Min: {0:.04f} Max: {1:.04f}'.format(limits[0], limits[1]), horizontalalignment='center', verticalalignment='center', fontsize=12) ax.coastlines() plt.colorbar(orientation='horizontal') fig.tight_layout() if show == True: plt.show() return else: return fig
def plotmaps(data, verbose = False, filter ="WORLD", var="od550aer", plotdir="./"): """plot aerocom standard maps Will plot every supplied time step""" if not isinstance(data, GriddedData): raise TypeError("Need pyaerocom.GriddedData as input") #define color bar; #will be moved somewhere else and variable specific at some point colorbar_levels = [0., 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] colorbar_ticks = [0., 0.02, 0.04, 0.06, 0.08, 0.1, 0.3, 0.5, 0.7, 0.9] aod_data = { 'red': ((0., 0, 0), (0.07, 0, 0), (0.1, 0.678, 0.678,), (0.26, 1, 1), (0.85, 1, 1), (1, 0.545, 0.545)), 'green': ((0., 0, 0), (0.07, 1, 1), (0.24, 1, 1), (0.91, 0, 0), (1, 0, 0)), 'blue': ((0., 1, 1), (0.07, 1, 1), (0.1, 0.133, 0.133), (0.25, 0, 0), (1, 0, 0))} colormap = LinearSegmentedColormap('aod_jet', aod_data) plt.register_cmap(cmap = colormap) TIME_VAR_NAME = 'time' PlotDailyFlag = False PlotMonthlyFlag = True for model in data: #assume that we have single cube for the moment #iterate over the time dimension cube = data[model].data #model = 'AATSR_ORAC_v4.01' cube.coord('latitude').guess_bounds() cube.coord('longitude').guess_bounds() #plot daily data if PlotDailyFlag: for time_sub_cube in cube.slices_over(TIME_VAR_NAME): pre_grid_areas = iris.analysis.cartography.area_weights(time_sub_cube) #pdb.set_trace() #print(time_sub_cube) # Perform the area-weighted mean for each of the datasets using the # computed grid-box areas. weighted_mean = time_sub_cube.collapsed(['latitude', 'longitude'], iris.analysis.MEAN, weights = pre_grid_areas) time = (unit.num2date(time_sub_cube.coord(TIME_VAR_NAME).points, time_sub_cube.coord(TIME_VAR_NAME).units.name, time_sub_cube.coord(TIME_VAR_NAME).units.calendar)) date = str(time[0]).split(' ')[0].replace('-','') Year = date[0:4] TsStr = 'm'+date PlotType = 'MAP' title = " ".join([var, date, 'mean: {:6.3f}'.format(float(weighted_mean.data))]) #ABS550_AER_an2012_mALLYEAR_WORLD_ZONALOBS_AERONETSky.ps.png #OD550_AER_an2017_d20171125_WORLD_MAP.ps.png plotfilename = os.path.join(plotdir, '_'.join([var, "an" + Year, TsStr, filter, PlotType]) + ".png") if verbose: print(plotfilename) plot = iplt.pcolormesh(time_sub_cube[:, :], cmap = colormap, vmin=0., vmax=max(colorbar_levels)) # pdb.set_trace() plot.axes.set_aspect(1.8) LatsToPlot = time_sub_cube.coord(axis='X').points LonsToPlot = time_sub_cube.coord(axis='Y').points axis = plt.axis([LatsToPlot.min(), LatsToPlot.max(), LonsToPlot.min(), LonsToPlot.max()]) ax = plot.axes ax.annotate('source: AEROCOM', xy=(0.88, 0.04), xycoords='figure fraction', horizontalalignment='right', fontsize=10, bbox=dict(boxstyle='square', facecolor='none', edgecolor='black')) ax.annotate(model, xy=(-174., -83.), xycoords='data', horizontalalignment='left', fontsize=13, color='black', bbox=dict(boxstyle='square', facecolor='white', edgecolor='none', alpha=0.7)) # plt.ylabel(_title(plot_defn.coords[0], with_units=True)) # plot_defn = iplt._get_plot_defn(cube, mode, ndims) plt.colorbar(spacing='uniform', ticks=colorbar_ticks, boundaries=colorbar_levels, extend='max') ax.coastlines() ax.set_xticks([-180., -120., -60., 0., 60, 120, 180], crs=ccrs.PlateCarree()) ax.set_yticks([-90., -60, -30, 0., 30, 60, 90], crs=ccrs.PlateCarree()) lon_formatter = LongitudeFormatter(number_format='.1f', degree_symbol='') lat_formatter = LatitudeFormatter(number_format='.1f', degree_symbol='') ax.xaxis.set_major_formatter(lon_formatter) ax.yaxis.set_major_formatter(lat_formatter) plt.xlabel = 'longitude' plt.ylabel = 'latitude' plt.title(title) plt.savefig(plotfilename, dpi=300) plt.close() #pdb.set_trace() elif PlotMonthlyFlag: #calculate monthly data iris.coord_categorisation.add_month(cube, TIME_VAR_NAME, name='month_number') iris.coord_categorisation.add_year(cube, TIME_VAR_NAME, name='month_year') cube_monthly = cube.aggregated_by(['month_number', 'month_year'], iris.analysis.MEAN) for time_sub_cube in cube_monthly.slices_over(TIME_VAR_NAME): pre_grid_areas = iris.analysis.cartography.area_weights(time_sub_cube) # pdb.set_trace() # print(time_sub_cube) # Perform the area-weighted mean for each of the datasets using the # computed grid-box areas. weighted_mean = time_sub_cube.collapsed(['latitude', 'longitude'], iris.analysis.MEAN, weights=pre_grid_areas) time = (unit.num2date(time_sub_cube.coord(TIME_VAR_NAME).points, time_sub_cube.coord(TIME_VAR_NAME).units.name, time_sub_cube.coord(TIME_VAR_NAME).units.calendar)) date = str(time[0]).split(' ')[0].replace('-', ' ')[0:7] Year = date[0:4] TsStr = 'm' + date[-2:] PlotType = 'MAP' title = " ".join([var, date, 'mean: {:6.3f}'.format(float(weighted_mean.data))]) # ABS550_AER_an2012_mALLYEAR_WORLD_ZONALOBS_AERONETSky.ps.png # OD550_AER_an2017_d20171125_WORLD_MAP.ps.png plotfilename = os.path.join(plotdir, '_'.join([var, "an" + Year, TsStr, filter, PlotType]) + ".png") if verbose: print(plotfilename) LatsToPlot = time_sub_cube.coord(axis='X').points LonsToPlot = time_sub_cube.coord(axis='Y').points xticks = [-180., -120., -60., 0., 60, 120, 180] yticks = [-90., -60, -30, 0., 30, 60, 90] plot_ts_map(time_sub_cube, title, plotfilename, LatsToPlot, LonsToPlot, colorbar_ticks, colorbar_levels, colormap, model, xticks, yticks)
def main(): cube = iris.load( '~/code/develop/vipc/datasets/t2m_mon.era20cr_1950-2010.nc')[0] iris.coord_categorisation.add_year(cube, 'time', name='year') yearly = cube.aggregated_by('year', iris.analysis.MEAN) clim = cube.collapsed('time', iris.analysis.MEAN) anomaly = yearly - clim anom_detr = detrend(anomaly) window = 11 # appends(cube, cmap, title, vn, vx) # ---------------------------------------- # # ---------------1 OUTPUT----------------- # SDtot = anom_detr.collapsed('time', iris.analysis.STD_DEV) # paint # appends(SDtot, plt.cm.Reds, 'SDtot', 0, 2.25) TRd = trend(anomaly) # paint -negative values # appends(TRd, plt.cm.RdBu_r, 'TRd', -0.9, 0.9) TRd_SDtot = TRd / SDtot # paint -negative values # appends(TRd_SDtot, plt.cm.RdBu_r, 'TRd/SDtot', -0.8, 0.8) # ---------------1 OUTPUT----------------- # # ---------------------------------------- # # ---------------------------------------- # # ---------------2 OUTPUT----------------- # anom_detr.remove_coord('year') corr_5y_lag = lagged_correlation(anom_detr, 5) corr_3y_lag = lagged_correlation(anom_detr, 3) corr_1y_lag = lagged_correlation(anom_detr, 1) appends(corr_5y_lag, plt.cm.RdBu_r, '5-year lagged correlation', -0.7, 0.7, lc=True) appends(corr_3y_lag, plt.cm.RdBu_r, '3-year lagged correlation', -0.7, 0.7, lc=True) appends(corr_1y_lag, plt.cm.RdBu_r, '1-year lagged correlation', -0.7, 0.7, lc=True) # ---------------2 OUTPUT----------------- # # ---------------------------------------- # # ---------------------------------------- # # ---------------3 OUTPUT----------------- # # Construct 2-year (24-month) and 7-year (84-month) low pass filters # for the SOI data which is monthly. wgts5 = low_pass_weights(window, 1. / 5.) wgts10 = low_pass_weights(window, 1. / 10.) soi5 = anom_detr.rolling_window('time', iris.analysis.MEAN, len(wgts5), weights=wgts5) soi10 = anom_detr.rolling_window('time', iris.analysis.MEAN, len(wgts10), weights=wgts10) # SD SD5 = soi5.collapsed('time', iris.analysis.STD_DEV) # paint SD10 = soi10.collapsed('time', iris.analysis.STD_DEV) # paint SD5p2_SDtotp2 = SD5**2 / SDtot**2 # paint SD10p2_SDtotp2 = SD10**2 / SDtot**2 # paint # appends(SD5, plt.cm.Reds, 'SD5', 0, 1.9) # appends(SD10, plt.cm.Reds, 'SD10', 0, 1.9) # appends(SD5p2_SDtotp2, plt.cm.Reds, 'SD$5^2$/SDtot$^2$', 0, 1) # appends(SD10p2_SDtotp2, plt.cm.Reds, 'SD$10^2$/SDtot$^2$', 0, 1) # ---------------3 OUTPUT----------------- # # ---------------------------------------- # # LOS LOLES corr_10y_lag_f = lagged_correlation(soi5, 10) corr_5y_lag_f = lagged_correlation(soi5, 5) corr_3y_lag_f = lagged_correlation(soi5, 3) appends(corr_10y_lag_f, plt.cm.RdBu_r, '10-year, 5y-filt, lagged correlation', -1, 1, lc=True) appends(corr_5y_lag_f, plt.cm.RdBu_r, '5-year, 5y-filt, lagged correlation', -1, 1, lc=True) appends(corr_3y_lag_f, plt.cm.RdBu_r, '3-year, 5y-filt, lagged correlation', -1, 1, lc=True) # ---------------------------------------- # # -----------------PLOT------------------- # proj = ccrs.PlateCarree(central_longitude=180) for i, (cube, cmp, t, vn, vx, lc) in enumerate(zip(map, color_map, titles, vmin, vmax, lcs)): plt.figure(figsize=(10, 5)) ax = plt.axes(projection=proj) ax.set_aspect('auto') contour = iplt.pcolormesh(cube, vmin=vn, vmax=vx, coords=('longitude', 'latitude'), cmap=cmp) # contour = iplt.pcolormesh(cube, coords=('longitude', 'latitude'), cmap=cmp) plt.title(t + ', (1950-2010)') ax.coastlines('50m', linewidth=0.8) cb = plt.colorbar(contour, ax=ax, orientation="vertical") if lc: iplt.contour(cube, [-0.275], colors='k') iplt.contour(cube, [0.275], colors='k') cb.set_label('Correlation', size=15) else: cb.set_label('Temp. / ' + str(cube.units), size=15) plt.tight_layout(h_pad=1) plt.savefig('/Users/Pep/code/develop/vipc/plots_e2/' + str(i) + '.eps')
def make_plot(projection_name, projection_crs): # Create a matplotlib Figure. fig = plt.figure() # Add a matplotlib Axes, specifying the required display projection. # NOTE: specifying 'projection' (a "cartopy.crs.Projection") makes the # resulting Axes a "cartopy.mpl.geoaxes.GeoAxes", which supports plotting # in different coordinate systems. ax = plt.axes(projection=projection_crs) # Set display limits to include a set region of latitude * longitude. # (Note: Cartopy-specific). ax.set_extent((-80.0, 20.0, 10.0, 80.0), crs=crs_latlon) # Add coastlines and meridians/parallels (Cartopy-specific). ax.coastlines(linewidth=0.75, color='navy') ax.gridlines(crs=crs_latlon, linestyle='-') # Plot the first dataset as a pseudocolour filled plot. maindata_filepath = iris.sample_data_path('rotated_pole.nc') main_data = iris.load_cube(maindata_filepath) # NOTE: iplt.pcolormesh calls "pyplot.pcolormesh", passing in a coordinate # system with the 'transform' keyword: This enables the Axes (a cartopy # GeoAxes) to reproject the plot into the display projection. iplt.pcolormesh(main_data, cmap='RdBu_r') # Overplot the other dataset (which has a different grid), as contours. overlay_filepath = iris.sample_data_path('space_weather.nc') overlay_data = iris.load_cube(overlay_filepath, 'total electron content') # NOTE: as above, "iris.plot.contour" calls "pyplot.contour" with a # 'transform' keyword, enabling Cartopy reprojection. iplt.contour(overlay_data, 20, linewidths=2.0, colors='darkgreen', linestyles='-') # Draw a margin line, some way in from the border of the 'main' data... # First calculate rectangle corners, 7% in from each corner of the data. x_coord, y_coord = main_data.coord(axis='x'), main_data.coord(axis='y') x_start, x_end = np.min(x_coord.points), np.max(x_coord.points) y_start, y_end = np.min(y_coord.points), np.max(y_coord.points) margin = 0.07 margin_fractions = np.array([margin, 1.0 - margin]) x_lower, x_upper = x_start + (x_end - x_start) * margin_fractions y_lower, y_upper = y_start + (y_end - y_start) * margin_fractions box_x_points = x_lower + (x_upper - x_lower) * np.array([0, 1, 1, 0, 0]) box_y_points = y_lower + (y_upper - y_lower) * np.array([0, 0, 1, 1, 0]) # Get the Iris coordinate sytem of the X coordinate (Y should be the same). cs_data1 = x_coord.coord_system # Construct an equivalent Cartopy coordinate reference system ("crs"). crs_data1 = cs_data1.as_cartopy_crs() # Draw the rectangle in this crs, with matplotlib "pyplot.plot". # NOTE: the 'transform' keyword specifies a non-display coordinate system # for the plot points (as used by the "iris.plot" functions). plt.plot(box_x_points, box_y_points, transform=crs_data1, linewidth=2.0, color='white', linestyle='--') # Mark some particular places with a small circle and a name label... # Define some test points with latitude and longitude coordinates. city_data = [('London', 51.5072, 0.1275), ('Halifax, NS', 44.67, -63.61), ('Reykjavik', 64.1333, -21.9333)] # Place a single marker point and a text annotation at each place. for name, lat, lon in city_data: plt.plot(lon, lat, marker='o', markersize=7.0, markeredgewidth=2.5, markerfacecolor='black', markeredgecolor='white', transform=crs_latlon) # NOTE: the "plt.annotate call" does not have a "transform=" keyword, # so for this one we transform the coordinates with a Cartopy call. at_x, at_y = ax.projection.transform_point(lon, lat, src_crs=crs_latlon) plt.annotate(name, xy=(at_x, at_y), xytext=(30, 20), textcoords='offset points', color='black', backgroundcolor='white', size='large', arrowprops=dict(arrowstyle='->', color='white', linewidth=2.5)) # Add a title, and display. plt.title('A pseudocolour plot on the {} projection,\n' 'with overlaid contours.'.format(projection_name)) plt.show()
gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1, color='gray', alpha=0.5, linestyle='--') gl.xlabels_top = False # use of formatter (fixed), only after this the style setup will work gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER # specify label styles gl.xlabel_style = {'size': 9, 'color': 'gray'} gl.ylabel_style = {'size': 9, 'color': 'gray'} # Load a Cynthia Brewer palette. #brewer_cmap = mpl_cm.get_cmap('brewer_RdYlBu_11') cs = iplt.pcolormesh(cube_ERAI, cmap='coolwarm', vmin=-0.50, vmax=0.50) cbar = fig4.colorbar(cs, extend='both', orientation='horizontal', shrink=0.8, pad=0.1, format="%.2f") cbar.set_ticks([-0.50, -0.25, 0, 0.25, 0.50]) cbar.set_clim(-0.50, 0.50) cbar.ax.tick_params(labelsize=9) cbar.set_label('Correlation coefficient', size=12) # locate the indices of p_value matrix where error p<0.005 (99.5% confident) ii, jj = np.where(p_value_ERAI_fields <= 0.005) # get the coordinate on the map (lon,lat) and plot scatter dots ax.scatter(longitude_ERAI_fields[jj], latitude_ERAI_fields[ii],
def main(): # Load a sample air temperatures sequence. file_path = iris.sample_data_path("E1_north_america.nc") temperatures = iris.load_cube(file_path) # Create a year-number coordinate from the time information. iris.coord_categorisation.add_year(temperatures, "time") # Create a sample anomaly field for one chosen year, by extracting that # year and subtracting the time mean. sample_year = 1982 year_temperature = temperatures.extract(iris.Constraint(year=sample_year)) time_mean = temperatures.collapsed("time", iris.analysis.MEAN) anomaly = year_temperature - time_mean # Construct a plot title string explaining which years are involved. years = temperatures.coord("year").points plot_title = "Temperature anomaly" plot_title += "\n{} differences from {}-{} average.".format( sample_year, years[0], years[-1]) # Define scaling levels for the logarithmic colouring. minimum_log_level = 0.1 maximum_scale_level = 3.0 # Use a standard colour map which varies blue-white-red. # For suitable options, see the 'Diverging colormaps' section in: # http://matplotlib.org/stable/gallery/color/colormap_reference.html anom_cmap = "bwr" # Create a 'logarithmic' data normalization. anom_norm = mcols.SymLogNorm( linthresh=minimum_log_level, linscale=1, vmin=-maximum_scale_level, vmax=maximum_scale_level, ) # Setting "linthresh=minimum_log_level" makes its non-logarithmic # data range equal to our 'zero band'. # Setting "linscale=1" maps the whole zero band to the middle colour value # (i.e., 0.5), which is the neutral point of a "diverging" style colormap. # Create an Axes, specifying the map projection. plt.axes(projection=ccrs.LambertConformal()) # Make a pseudocolour plot using this colour scheme. mesh = iplt.pcolormesh(anomaly, cmap=anom_cmap, norm=anom_norm) # Add a colourbar, with extensions to show handling of out-of-range values. bar = plt.colorbar(mesh, orientation="horizontal", extend="both") # Set some suitable fixed "logarithmic" colourbar tick positions. tick_levels = [-3, -1, -0.3, 0.0, 0.3, 1, 3] bar.set_ticks(tick_levels) # Modify the tick labels so that the centre one shows "+/-<minumum-level>". tick_levels[3] = r"$\pm${:g}".format(minimum_log_level) bar.set_ticklabels(tick_levels) # Label the colourbar to show the units. bar.set_label("[{}, log scale]".format(anomaly.units)) # Add coastlines and a title. plt.gca().coastlines() plt.title(plot_title) # Display the result. iplt.show()
def plot_2d_cube(cube, vmin=None, vmax=None, mask_less=1e-8, vaac_colours=False, limits=None): """ Draw a map of a two dimensional cube. Cube should have two spatial dimensions (e.g. latitude, longitude). All other dimensions (time, altitude) should be scalar dimensions. The figure and title are returned to allow user to save if required. :param cube: iris Cube :param vmin: Optional minimum value for scale :param vmax: Optional maximum value for scale :param mask_less: float, values beneath this are masked out :param vaac_colours: bool, use cyan, grey, red aviation zones :param limits: tuple (xmin, ymin, xmax, ymax), bounding box for plot :return fig: handle to Matplotlib figure :return title: str; title of plot generated from cube attributes """ # Mask out data below threshold cube.data = np.ma.masked_less(cube.data, mask_less) # Prepare colormap if vaac_colours and _vaac_compatible(cube): colors = ['#80ffff', '#939598'] levels = [0.0002, 0.002, 0.004] cmap = matplotlib.colors.ListedColormap(colors) cmap.set_over('#e00404') norm = matplotlib.colors.BoundaryNorm(levels, cmap.N, clip=False) elif vaac_colours and not _vaac_compatible(cube): # Raise a warning but continue with default colour scheme warnings.warn("The VAAC colour scheme option (vaac_colours=True)" " is only compatible with air concentration data." " Falling back to use the default colour scheme...") cmap = "viridis" norm = None else: cmap = "viridis" norm = None # Plot data fig = plt.figure() mesh_plot = iplt.pcolormesh(cube, vmin=vmin, vmax=vmax, cmap=cmap, norm=norm) ax = plt.gca() ax.coastlines(resolution='50m', color='grey') colorbar = fig.colorbar(mesh_plot, orientation='horizontal', extend='max', extendfrac='auto') colorbar.set_label(f'{cube.units}') # Set axis limits if limits: xmin, ymin, xmax, ymax = limits ax.set_xlim(xmin, xmax) ax.set_ylim(ymin, ymax) # Add tick marks ax.set_xticks(ax.get_xticks(), crs=ccrs.PlateCarree()) ax.set_yticks(ax.get_yticks(), crs=ccrs.PlateCarree()) lon_formatter = LongitudeFormatter(zero_direction_label=True) lat_formatter = LatitudeFormatter() ax.xaxis.set_major_formatter(lon_formatter) ax.yaxis.set_major_formatter(lat_formatter) ax.grid(linewidth=0.5, color='grey', alpha=0.25, linestyle='--') # Get title attributes zlevel = _format_zlevel_string(cube) timestamp = _format_timestamp_string(cube) # Get and apply title, filter removes NoneType # elements before joining. title = '_'.join( filter(None, (cube.attributes.get('model_run_title').replace( ' ', '_'), cube.attributes.get('quantity').replace( ' ', '_'), str(zlevel), str(timestamp)))) ax.set_title(title) return fig, title
def init_artists(self, ax, plot_args, plot_kwargs): return {'artist': iplt.pcolormesh(*plot_args, axes=ax, **plot_kwargs)}
def test_pcolormesh(self): iplt.pcolormesh(self.cube) self.check_graphic()
def main(): first_of_year = datetime.date(2011, 01, 01) first_ordinal = first_of_year.toordinal() diagnostic = '4203' pickle_name = ('pickle_instant_rain_largescale_mean*_%s.p' % diagnostic) flist = glob.glob ('/home/pwille/python_scripts/*/%s' % pickle_name) for i in flist: fname = str(i) experiment_id = fname.split('/')[4] full_cube = pickle.load( open( fname, "rb" ) ) #experiment_id = fname.split('/')[6] #map_quest_aerial = cimgt.MapQuestOpenAerial() for sub_cube in full_cube.slices(['grid_latitude', 'grid_longitude']): #Get date in iso fromat, if needed, for title #day=sub_cube_daily.coord('dayyear') #day_number = day.points[0] #day_number_ordinal=first_ordinal-1 + day_number #date_print = datetime.date.fromordinal(day_number_ordinal) #date_iso = str(date_print.isoformat()) #sub_cube_daily.units = 'hPa' #sub_cube_daily /= 100 # Load a Cynthia Brewer palette. brewer_cmap = mpl_cm.get_cmap('gist_rainbow') #contour = qplt.contour(sub_cube_daily, brewer_cmap.N, cmap=brewer_cmap) #sub_cube.coord('grid_latitude').guess_bounds() #sub_cube.coord('grid_longitude').guess_bounds() # turn the iris Cube data structure into numpy arrays #gridlons = sub_cube.coord('grid_longitude').contiguous_bounds() #gridlats = sub_cube.coord('grid_latitude').contiguous_bounds() #sub_grid = sub_cube.data plt.axes(projection=ccrs.PlateCarree() ) #rotated_pole = ccrs.RotatedPole(pole_longitude = 263, pole_latitude = 76) iplt.pcolormesh(sub_cube, cmap=brewer_cmap) plt.title('Large scale rainfall rate mean: kg/m2/s: %s model run.' % (experiment_id), fontsize=10) #plt.title('Large scale rainfall rate mean: kg/m2/s: %s model run. %s' % (experiment_id, date_iso), fontsize=18) #plt.gridlines() #plt.gca().xlabel('longitude / degrees') #plt.ylabel('latitude / degrees') dx, dy = 10, 10 # plt.clabel(contour, fmt='%d') #plt.gca().stock_img() plt.gca().coastlines(resolution='110m', color='black') gl = plt.gca().gridlines(draw_labels=True,linewidth=1, color='gray', alpha=0.5, linestyle='--') gl.xlabels_top = False gl.ylabels_right = False #gl.xlines = False gl.xlocator = mticker.FixedLocator(range(60,105+dx,dx)) gl.ylocator = mticker.FixedLocator(range(-10,30+dy,dx)) gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER iplt.pcolormesh(sub_cube, cmap=brewer_cmap) #gl.xlabel_style = {'size': 15, 'color': 'gray'} #gl.xlabel_style = {'color': 'red', 'weight': 'bold'} #plt.savefig('/home/pwille/python_scripts/pngs/%s/msl_daily_mean_%s_%s.png' % (experiment_id, experiment_id, date_iso)) #plt.savefig('/home/pwille/python_scripts/pngs/%s/%s_daily_mean_%s_%s.png' % (experiment_id, diagnostic, experiment_id, date_iso)) #plt.close() plt.show()
from __future__ import (absolute_import, division, print_function) from six.moves import (filter, input, map, range, zip) # noqa import iris import iris.analysis import iris.plot as iplt import matplotlib.pyplot as plt global_air_temp = iris.load_cube(iris.sample_data_path('air_temp.pp')) rotated_psl = iris.load_cube(iris.sample_data_path('rotated_pole.nc')) rotated_air_temp = global_air_temp.regrid(rotated_psl, iris.analysis.Linear()) plt.figure(figsize=(4, 3)) iplt.pcolormesh(rotated_air_temp, norm=plt.Normalize(260, 300)) plt.title('Air temperature\n' 'on a limited area rotated pole grid') ax = plt.gca() ax.coastlines(resolution='50m') ax.gridlines() plt.show()
def plotGPM(cube, region_name, location_name, bbox, bbox_name, overwrite=False, accum='12-hrs'): ''' Plots GPM IMERG data for the given location and accumulation period :param cube: :param region_name: :param location_name: :param bbox: :param overwrite: :param accum: :return: ''' print(accum + ' Accumulation') this_title = accum + ' Accumulation (mm)' ofilelist = [] if accum == '24-hrs': # Aggregate by day_of_year. # NB: Data is in mm/hr for each half hour timestep, so divide by 2 cube_dom_acc = cube.aggregated_by('day_of_year', iris.analysis.SUM) / 2. these_units = 'Accumulated rainfall (mm/24hrs)' elif accum == '12-hrs': # Aggregate by am or pm ... # NB: Data is in mm/hr for each half hour timestep, so divide by 2 cube_dom_acc = cube.aggregated_by(['day_of_year', 'am_or_pm'], iris.analysis.SUM) / 2. these_units = 'Accumulated rainfall (mm/12hrs)' elif accum == '6-hrs': # Aggregate by 6hr period # NB: Data is in mm/hr for each half hour timestep, so divide by 2 cube_dom_acc = cube.aggregated_by(['day_of_year', '6hourly'], iris.analysis.SUM) / 2. these_units = 'Accumulated rainfall (mm/6hrs)' elif accum == '3-hrs': # Aggregate by 3hr period # NB: Data is in mm/hr for each half hour timestep, so divide by 2 cube_dom_acc = cube.aggregated_by(['day_of_year', '3hourly'], iris.analysis.SUM) / 2. these_units = 'Accumulated rainfall (mm/3hrs)' elif accum == '1-hr': # Aggregate by 3hr period # NB: Data is in mm/hr for each half hour timestep, so divide by 2 cube_dom_acc = cube.aggregated_by(['day_of_year', 'hour'], iris.analysis.SUM) / 2. these_units = 'Accumulated rainfall (mm/hr)' elif accum == '30-mins': # Don't aggregate! # NB: Data is in mm/hr for each half hour timestep, so divide by 2 cube_dom_acc = cube.copy() this_title = 'Rate (mm/hr) for 30-min Intervals' these_units = 'Accumulated rainfall (mm/hr)' else: print( 'Please specify a different accumulation time. Choose from: 30-mins, 1-hr, 3-hrs, 6-hrs, 12-hrs, 24-hrs' ) return cube_dom_acc.coord('latitude').guess_bounds() cube_dom_acc.coord('longitude').guess_bounds() contour_levels = { '30-mins': [0.0, 0.1, 0.25, 0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 1000.0], '1-hr': [0.0, 0.1, 0.25, 0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 1000.0], '3-hrs': [0.0, 0.3, 0.75, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 1000.0], '6-hrs': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '12-hrs': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '24-hrs': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '48-hrs': [0.0, 0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0] } my_rgb = [ '#ffffff', '#87bbeb', '#6a9bde', '#2a6eb3', '#30ca28', '#e2d942', '#f49d1b', '#e2361d', '#f565f5', '#ffffff' ] # Plot the cube. for i in range(0, cube_dom_acc.shape[0]): # Prepare time coords tcoord = cube_dom_acc[i].coord('time') tu = tcoord.units tpt = tu.num2date(tcoord.bounds[0][1]) + dt.timedelta( seconds=1) # Get the upper bound and nudge it the hour # Define the correct output dir and filename timestamp = tpt.strftime('%Y%m%dT%H%MZ') # Make Output filename ofile = sf.make_outputplot_filename(region_name, location_name, tpt, 'GPM-IMERG', bbox_name, accum, 'Precipitation', 'Observed-Timeseries', 'T+0') print('Plotting ' + accum + ': ' + timestamp + ' (' + str(i + 1) + ' / ' + str(cube_dom_acc.shape[0]) + ')') if not os.path.isfile(ofile) or overwrite: this_localdir = os.path.dirname(ofile) if not os.path.isdir(this_localdir): os.makedirs(this_localdir) # Now do the plotting fig = plt.figure(figsize=getFigSize(bbox), dpi=300) bounds = contour_levels[accum] norm = colors.BoundaryNorm(boundaries=bounds, ncolors=len(my_rgb)) my_cmap = matplotlib.colors.ListedColormap(my_rgb) pcm = iplt.pcolormesh(cube_dom_acc[i], norm=norm, cmap=my_cmap) plt.title('GPM Precipitation ' + this_title + ' at\n' + tpt.strftime('%Y-%m-%d %H:%M')) plt.xlabel('longitude (degrees)') plt.ylabel('latitude (degrees)') var_plt_ax = plt.gca() var_plt_ax.set_extent([bbox[0], bbox[2], bbox[1], bbox[3]]) lakelines = cfeature.NaturalEarthFeature(category='physical', name='lakes', scale='10m', edgecolor='black', alpha=0.5, facecolor='none') var_plt_ax.add_feature(lakelines) borderlines = cfeature.NaturalEarthFeature( category='cultural', name='admin_0_boundary_lines_land', scale='50m', linewidth=1, linestyle=(0, (3, 1, 1, 1, 1, 1)), edgecolor='black', facecolor='none') var_plt_ax.add_feature(borderlines) var_plt_ax.coastlines(resolution='50m', color='black') gl = var_plt_ax.gridlines(color="gray", alpha=0.2, draw_labels=True) gl.top_labels = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.xlabel_style = {'size': 8} gl.ylabel_style = {'size': 8} vleft, vbottom, vwidth, vheight = var_plt_ax.get_position().bounds plt.gcf().subplots_adjust(top=vbottom + vheight, bottom=vbottom + 0.04, left=vleft, right=vleft + vwidth) cbar_axes = fig.add_axes([vleft, vbottom - 0.02, vwidth, 0.02]) cbar = plt.colorbar(pcm, boundaries=bounds, cax=cbar_axes, orientation='horizontal', extend='both') # norm=norm, cbar.set_label(these_units) cbar.ax.tick_params(length=0) fig.savefig(ofile, bbox_inches='tight') plt.close(fig) if os.path.isfile(ofile): # Add it to the list of files ofilelist.append(ofile) # Make sure everyone can read it os.chmod(ofile, 0o777) return ofilelist
import matplotlib.pyplot as plt import cartopy.crs as ccrs from cartopy.io.img_tiles import MapQuestOpenAerial import iris import iris.plot as iplt fname = '../data/ukVpmslont_first_field.pp' cube = iris.load_cube(fname) # Decimate the cube ... cube = cube[::20, ::20] fig = plt.figure(figsize=(16, 12)) map_quest_aerial = MapQuestOpenAerial() #ax = plt.axes(projection=ccrs.Mercator()) ax = plt.axes(projection=map_quest_aerial.crs) iplt.pcolormesh(cube, edgecolor='grey', linewidth=1) ax.add_image(map_quest_aerial, 8) ax.coastlines(resolution='10m') ax.outline_patch.set_edgecolor('none') #ax.set_extent((-16.91, 8.05, 46.29, 61.35), crs=ccrs.PlateCarree()) ax.set_extent((-29, 19, 37, 66), crs=ccrs.PlateCarree()) #plt.savefig('ukv.png', transparent=True, dpi=200) plt.show()
regional_ash = iris.load_cube(iris.sample_data_path('NAME_output.txt')) regional_ash = regional_ash.collapsed('flight_level', iris.analysis.SUM) # Mask values so low that they are anomalous. regional_ash.data = np.ma.masked_less(regional_ash.data, 5e-6) norm = matplotlib.colors.LogNorm(5e-6, 0.0175) global_air_temp.coord('longitude').guess_bounds() global_air_temp.coord('latitude').guess_bounds() fig = plt.figure(figsize=(8, 4.5)) plt.subplot(2, 2, 1) iplt.pcolormesh(regional_ash, norm=norm) plt.title('Volcanic ash total\nconcentration not regridded', size='medium') for subplot_num, mdtol in zip([2, 3, 4], [0, 0.5, 1]): plt.subplot(2, 2, subplot_num) scheme = iris.analysis.AreaWeighted(mdtol=mdtol) global_ash = regional_ash.regrid(global_air_temp, scheme) iplt.pcolormesh(global_ash, norm=norm) plt.title('Volcanic ash total concentration\n' 'regridded with AreaWeighted(mdtol={})'.format(mdtol), size='medium') plt.subplots_adjust(hspace=0, wspace=0.05, left=0.001, right=0.999, bottom=0, top=0.955)
def plotRegionalPrecipWind(analysis_data, gpm_data, region_bbox, region_bbox_name, settings, pstart, pend, time_tups, ofiles): ''' :param analysis_data: :param gpm_data: :param region_bbox: :param settings: :param pstart: :param pend: :param time_tups: :param ofiles: :return: ''' try: cubex850_alltime = analysis_data['Uwind-levels'].extract( iris.Constraint(pressure=850.)) cubey850_alltime = analysis_data['Vwind-levels'].extract( iris.Constraint(pressure=850.)) except: return ofiles # First, make sure that we have data for the last of the 4 plots last_start, last_end = time_tups[-1] diff_hrs = (last_end - last_start).total_seconds() // 3600 # Get the length of all the input data gpmdata_ss = sf.periodConstraint(gpm_data, last_start, last_end) cubex850 = sf.periodConstraint(cubex850_alltime, last_start, last_end) cubey850 = sf.periodConstraint(cubey850_alltime, last_start, last_end) try: gpm_len_hrs = np.round( gpmdata_ss.coord('time').bounds[-1][1] - gpmdata_ss.coord('time').bounds[0][0]) cubex_len_hrs = cubex850.coord('time').bounds[-1][1] - cubex850.coord( 'time').bounds[0][0] cubey_len_hrs = cubey850.coord('time').bounds[-1][1] - cubey850.coord( 'time').bounds[0][0] except: return ofiles if (diff_hrs != gpm_len_hrs) or (diff_hrs != cubex_len_hrs) or ( diff_hrs != cubey_len_hrs): return ofiles # Create a figure contour_levels = { '3-hrs': [0.3, 0.75, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 1000.0], '6-hrs': [0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '12-hrs': [0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '24-hrs': [0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '48-hrs': [0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '72-hrs': [0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0], '96-hrs': [0.6, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 96.0, 192.0, 1000.0] } my_rgb = [ '#87bbeb', '#6a9bde', '#2a6eb3', '#30ca28', '#e2d942', '#f49d1b', '#e2361d', '#f565f5', '#ffffff' ] diff = time_tups[0][1] - time_tups[0][0] timeagg = int(diff.seconds / (60 * 60)) bounds = contour_levels[str(timeagg) + '-hrs'] norm = colors.BoundaryNorm(boundaries=bounds, ncolors=len(my_rgb)) my_cmap = colors.ListedColormap(my_rgb) # Temporarily build a data2plot dictionary so that we can get contour levels data2plot = {} myu = cubex850_alltime.coord('time').units for tpt in myu.num2date(cubex850_alltime.coord('time').points): data2plot[tpt] = { 'analysis': { 'Uwind': cubex850_alltime.extract( iris.Constraint(time=lambda t: t.point == tpt)), 'Vwind': cubey850_alltime.extract( iris.Constraint(time=lambda t: t.point == tpt)) } } wspdcontour_levels = sf.get_contour_levels(data2plot, 'wind', extend='both', level_num=4) # Create a wider than normal figure to support our many plots (width, height) # fig = plt.figure(figsize=(8, 12), dpi=100) fig = plt.figure(figsize=(15, 12), dpi=100) # Also manually adjust the spacings which are used when creating subplots plt.gcf().subplots_adjust(hspace=0.07, wspace=0.05, top=0.91, bottom=0.075, left=0.075, right=0.8) # Set the map projection crs_latlon = ccrs.PlateCarree() # Loop through time_tups for tt in time_tups: i = time_tups.index(tt) + 1 # Subset the GPM data try: gpmdata_ss = sf.periodConstraint(gpm_data, tt[0], tt[1]) gpmdata_ss = gpmdata_ss.collapsed('time', iris.analysis.SUM) gpmdata_ss.data = gpmdata_ss.data / 2. gpmdata_ss.coord('latitude').guess_bounds() gpmdata_ss.coord('longitude').guess_bounds() except: print('Error getting GPM data') continue # Get the wind speed and line width cubex850 = sf.periodConstraint(cubex850_alltime, tt[0], tt[1]) cubey850 = sf.periodConstraint(cubey850_alltime, tt[0], tt[1]) if (not cubex850) or (not cubey850): print('Error getting analysis data') continue plt.subplot(2, 2, i) pcm = iplt.pcolormesh(gpmdata_ss, norm=norm, cmap=my_cmap, zorder=2) # Set the plot extent ax = plt.gca() x0, y0, x1, y1 = region_bbox ax.set_extent([x0, x1, y0, y1], crs=crs_latlon) # Add a subplot title plt.title(tt[1].strftime('%Y%m%d %H:%M')) # Add Coastlines, Borders and Gridlines lakefill = cfeature.NaturalEarthFeature(category='physical', name='lakes', scale='50m', edgecolor='none', facecolor='lightgrey') ax.add_feature(lakefill, zorder=1) oceanfill = cfeature.NaturalEarthFeature(category='physical', name='ocean', scale='50m', edgecolor='none', facecolor='lightgrey') ax.add_feature(oceanfill, zorder=1) lakelines = cfeature.NaturalEarthFeature(category='physical', name='lakes', scale='50m', edgecolor='black', facecolor='none') ax.add_feature(lakelines, zorder=3) borderlines = cfeature.NaturalEarthFeature( category='cultural', name='admin_0_boundary_lines_land', scale='50m', linewidth=1, linestyle=(0, (3, 1, 1, 1, 1, 1)), edgecolor='black', facecolor='none') ax.add_feature(borderlines, zorder=4) ax.coastlines(resolution='50m', color='black') gl = ax.gridlines(color="gray", alpha=0.2, draw_labels=True) gl.top_labels = False if i == 1: gl.bottom_labels = False gl.right_labels = False elif i == 2: gl.bottom_labels = False gl.left_labels = False elif i == 3: gl.right_labels = False else: gl.left_labels = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.xlabel_style = {'size': 8} gl.ylabel_style = {'size': 8} # Overlay wind field Y, X, U, V, spd, dir, lw = sf.compute_allwind( cubex850, cubey850, spd_levels=wspdcontour_levels) ax.streamplot(X, Y, U, V, density=1.5, color='k', linewidth=lw, zorder=5) # make an axes to put the shared colorbar in # colorbar_axes = plt.gcf().add_axes([0.175, 0.1, 0.65, 0.022]) # left, bottom, width, height colorbar_axes = plt.gcf().add_axes([0.85, 0.2, 0.022, 0.45]) # left, bottom, width, height colorbar = plt.colorbar(pcm, colorbar_axes, orientation='vertical', extend='max') colorbar.set_label('6-hr Precipitation Total (mm)') # make an axes to put the streamlines legend in strax = plt.gcf().add_axes([0.85, 0.7, 0.022, 0.15]) # left, bottom, width, height # colorbar = plt.colorbar(pcm, colorbar_axes, orientation='horizontal', extend='max') # colorbar.set_label('6-hr Precipitation Total (mm)') sf.makeStreamLegend(strax, wspdcontour_levels) # Use daterange in the title ... plt.suptitle( 'UM Analysis 850hPa winds and GPM IMERG Precipitation\n%s to %s' % (pstart.strftime('%Y%m%d %H:%M'), pend.strftime('%Y%m%d %H:%M')), fontsize=18) region_name, location_name = [ settings['region_name'], settings['location_name'] ] ofile = sf.make_outputplot_filename(region_name, location_name, pend, 'analysis', region_bbox_name, str(timeagg) + '-hrs', 'Precipitation', 'Regional-850winds', 'T+0') fig.savefig(ofile, bbox_inches='tight') plt.close(fig) if os.path.isfile(ofile): ofiles.append(ofile) return ofiles
def main(): # Start with arrays for latitudes and longitudes, with a given number of # coordinates in the arrays. coordinate_points = 200 longitudes = np.linspace(-180.0, 180.0, coordinate_points) latitudes = np.linspace(-90.0, 90.0, coordinate_points) lon2d, lat2d = np.meshgrid(longitudes, latitudes) # Omega is the Earth's rotation rate, expressed in radians per second omega = 7.29e-5 # The data for our cube is the Coriolis frequency, # `f = 2 * omega * sin(phi)`, which is computed for each grid point over # the globe from the 2-dimensional latitude array. data = 2.0 * omega * np.sin(np.deg2rad(lat2d)) # We now need to define a coordinate system for the plot. # Here we'll use GeogCS; 6371229 is the radius of the Earth in metres. cs = GeogCS(6371229) # The Iris coords module turns the latitude list into a coordinate array. # Coords then applies an appropriate standard name and unit to it. lat_coord = iris.coords.DimCoord( latitudes, standard_name="latitude", units="degrees", coord_system=cs ) # The above process is repeated for the longitude coordinates. lon_coord = iris.coords.DimCoord( longitudes, standard_name="longitude", units="degrees", coord_system=cs ) # Now we add bounds to our latitude and longitude coordinates. # We want simple, contiguous bounds for our regularly-spaced coordinate # points so we use the guess_bounds() method of the coordinate. For more # complex coordinates, we could derive and set the bounds manually. lat_coord.guess_bounds() lon_coord.guess_bounds() # Now we input our data array into the cube. new_cube = iris.cube.Cube( data, standard_name="coriolis_parameter", units="s-1", dim_coords_and_dims=[(lat_coord, 0), (lon_coord, 1)], ) # Now let's plot our cube, along with coastlines, a title and an # appropriately-labelled colour bar: ax = plt.axes(projection=ccrs.Orthographic()) ax.coastlines(resolution="10m") mesh = iplt.pcolormesh(new_cube, cmap="seismic") tick_levels = [-0.00012, -0.00006, 0.0, 0.00006, 0.00012] plt.colorbar( mesh, orientation="horizontal", label="s-1", ticks=tick_levels, format="%.1e", ) plt.title("Coriolis frequency") plt.show()
axes_class=(GeoAxes, dict(map_projection=ccrs.PlateCarree())), nrows_ncols=(1, 2), axes_pad=0.05, cbar_location='bottom', cbar_mode='single', cbar_pad=0.2, cbar_size='1%', label_mode='') # note the empty label_mode levels = np.arange(20, 65, 5) gustcmap = plt.get_cmap('YlOrRd') gustcmap.set_under('lightgrey', 1.0) gustcmap.set_over('black', 1.0) norm = BoundaryNorm(boundaries=levels, ncolors=gustcmap.N) cf = iplt.pcolormesh(q95, axes=axgr[0], cmap=gustcmap, norm=norm) iplt.pcolormesh(q99, axes=axgr[1], cmap=gustcmap, norm=norm) # Plot Level 1 regions # Plot place labels for ax in axgr: ax.plot(pop['LONGITUDE'].values, pop['LATITUDE'].values, marker='o', fillstyle='none', markersize=5, linestyle='none', color='black', path_effects=[ path_effects.Stroke(linewidth=2, foreground='white'),
def plot_increment_map(self, cube, rows=0, columns=0, loc=0, model_level=1, fixed=False, timescale=DEFAULT_TIMESCALE, cb_orientation='horizontal', cb_units=False): ''' Plot increment on given model level ''' # Extract model level and create time mean pcube = cube.extract(iris.Constraint(model_level_number=model_level)) if pcube.coords('time', dim_coords=True): pcube = pcube.collapsed('time', iris.analysis.MEAN) # Determine prognostic and physics scheme (_, prognostic, scheme) = self.split_cf_stdname(cube.name()) proginfo = PROGNOSTICS[prognostic] if scheme in OTHER_DIAGS: physinfo = OTHER_DIAGS[scheme] else: physinfo = PHYSICS[scheme] # Modify plot units if 'punits' in proginfo: pcube.convert_units(proginfo['punits']) self.scale_time_unit(pcube, timescale) # Create plot axes if loc < 1: loc = physinfo['loc'] axes = plt.subplot(rows, columns, loc, projection=ccrs.PlateCarree()) # Plot cube with fixed levels or self-determined cmap = mpl_cm.get_cmap('RdBu_r') if fixed: scale_levels = physinfo.get('scale_levels', 1.0) levels = scale_levels * proginfo['levels'] # if self.difference: # levels *= 0.1 norm = mpl_col.BoundaryNorm(levels, cmap.N, clip=True) ctf = iplt.pcolormesh(pcube, axes=axes, cmap=cmap, norm=norm) else: ctf = iplt.pcolormesh(pcube, axes=axes, cmap=cmap) # Add colorbar cbar = plt.colorbar(ctf, orientation=cb_orientation, extend='both', spacing='uniform') if cb_units: cbar.set_label(rf'${{unit_latex(pcube.units)}}$') # Set plot niceties plot_title = f'd{proginfo["label"]} {physinfo["label"]}' axes.set_title(plot_title) axes.coastlines() gl = axes.gridlines(draw_labels=True, linestyle='dotted', alpha=0.5) gl.xlabels_top = False gl.ylabels_right = False gl.xformatter = cmgridl.LONGITUDE_FORMATTER gl.yformatter = cmgridl.LATITUDE_FORMATTER # If all values are zero then plaster a big "= 0" on plot if not cube.data.any(): axes.text(0.5, 0.5, 'ZERO', ha='center', va='center', transform=axes.transAxes, fontsize='xx-large', bbox=dict(edgecolor='black', facecolor='yellow'))
import iris import iris.analysis import iris.plot as iplt import matplotlib.pyplot as plt global_air_temp = iris.load_cube(iris.sample_data_path("air_temp.pp")) rotated_psl = iris.load_cube(iris.sample_data_path("rotated_pole.nc")) scheme = iris.analysis.Linear(extrapolation_mode="mask") global_psl = rotated_psl.regrid(global_air_temp, scheme) plt.figure(figsize=(4, 3)) iplt.pcolormesh(global_psl) plt.title("Air pressure\n" "on a global longitude latitude grid") ax = plt.gca() ax.coastlines() ax.gridlines() ax.set_extent([-90, 70, 10, 80]) plt.show()
def main(): # Enable a future option, to ensure that the netcdf load works the same way # as in future Iris versions. iris.FUTURE.netcdf_promote = True # Load a sample air temperatures sequence. file_path = iris.sample_data_path('E1_north_america.nc') temperatures = iris.load_cube(file_path) # Create a year-number coordinate from the time information. iris.coord_categorisation.add_year(temperatures, 'time') # Create a sample anomaly field for one chosen year, by extracting that # year and subtracting the time mean. sample_year = 1982 year_temperature = temperatures.extract(iris.Constraint(year=sample_year)) time_mean = temperatures.collapsed('time', iris.analysis.MEAN) anomaly = year_temperature - time_mean # Construct a plot title string explaining which years are involved. years = temperatures.coord('year').points plot_title = 'Temperature anomaly' plot_title += '\n{} differences from {}-{} average.'.format( sample_year, years[0], years[-1]) # Define scaling levels for the logarithmic colouring. minimum_log_level = 0.1 maximum_scale_level = 3.0 # Use a standard colour map which varies blue-white-red. # For suitable options, see the 'Diverging colormaps' section in: # http://matplotlib.org/examples/color/colormaps_reference.html anom_cmap = 'bwr' # Create a 'logarithmic' data normalization. anom_norm = mcols.SymLogNorm(linthresh=minimum_log_level, linscale=0, vmin=-maximum_scale_level, vmax=maximum_scale_level) # Setting "linthresh=minimum_log_level" makes its non-logarithmic # data range equal to our 'zero band'. # Setting "linscale=0" maps the whole zero band to the middle colour value # (i.e. 0.5), which is the neutral point of a "diverging" style colormap. # Create an Axes, specifying the map projection. plt.axes(projection=ccrs.LambertConformal()) # Make a pseudocolour plot using this colour scheme. mesh = iplt.pcolormesh(anomaly, cmap=anom_cmap, norm=anom_norm) # Add a colourbar, with extensions to show handling of out-of-range values. bar = plt.colorbar(mesh, orientation='horizontal', extend='both') # Set some suitable fixed "logarithmic" colourbar tick positions. tick_levels = [-3, -1, -0.3, 0.0, 0.3, 1, 3] bar.set_ticks(tick_levels) # Modify the tick labels so that the centre one shows "+/-<minumum-level>". tick_levels[3] = r'$\pm${:g}'.format(minimum_log_level) bar.set_ticklabels(tick_levels) # Label the colourbar to show the units. bar.set_label('[{}, log scale]'.format(anomaly.units)) # Add coastlines and a title. plt.gca().coastlines() plt.title(plot_title) # Display the result. iplt.show()
def test_grid(self): iplt.pcolormesh(self.cube, facecolor='none', edgecolors='#888888') self.check_graphic()
def test_grid(self): iplt.pcolormesh(self.cube, facecolors='none', edgecolors='blue') # the result is a graphic which has coloured edges. This is a mpl bug, # see https://github.com/matplotlib/matplotlib/issues/1302 self.check_graphic()