def plotTile_patches(lonc, latc, lonv, latv, data): """ plot the tile using matplotlib patcheCollection """ from matplotlib.patches import Polygon from matplotlib.collections import PatchCollection # need to flip the raster upside down data = np.flipud(data) ## delta for calculating cell vertices from cell center dlon = lonc[0] - lonc[1] / 2. dlat = latc[0] - latc[1] / 2. #lonp = np.zeros([len(lon), 4]) #latp = np.zeros([len(lat), 4]) patches = [] for i, llon in enumerate(lonc): for j, llat in enumerate(latc): lon_w = llon - dlon lon_e = llon + dlon lat_n = llat + dlat lat_s = llat - dlat ## counter-clockwise vertices for each cell xp = np.asarray([lon_w, lon_e, lon_e, lon_w]) yp = np.asarray([lat_s, lat_n, lat_n, lat_s]) patches.append(Polygon(np.vstack([xp, yp]).T)) pdb.set_trace() cmap = 'viridis' pc = PatchCollection(patches, cmap=cmap) pc.set_array(data.flatten()) pc.set_lw(0.1) plt.rcParams.update({'font.size': 18}) fig = plt.figure(figsize=(12, 6)) ax = fig.add_subplot(111) ax.add_collection(pc) ax.set_xlim([lonv.min(), lonv.max()]) ax.set_ylim([latv.min(), latv.max()]) ax.set_aspect('equal') plt.show()
def plot_poly(colors, cells, nvertices, x, y, xc=None, yc=None, xperiod=None, yperiod=None, colorbar=True, cmap='viridis'): """ from https://gist.github.com/pwolfram/2745eaccaf33f222fed6""" patches = [] for ii, (ac, nv) in enumerate(zip(cells, nvertices)): ac = np.asarray(ac[:nv], dtype='int') xp = x[ac] yp = y[ac] if xc is not None: xp = fix_periodicity(xp, xc[ii], xperiod) if yc is not None: yp = fix_periodicity(yp, yc[ii], yperiod) patches.append(Polygon(zip(xp, yp))) pc = PatchCollection(patches, cmap=cmap, alpha=1.0) pc.set_array(colors) pc.set_edgecolor('face') pc.set_lw(0.1) plt.figure() ax = plt.gca() ax.add_collection(pc) ax.set_aspect('equal') ax.autoscale_view() if colorbar: plt.colorbar(pc) return pc
def plot_target(data_temp, var_temp, start_indices_temp, end_indices_temp, out_dir_temp): #Set some strings if var_temp == 'rad_continuum_o2': var_string = 'o2_radiance' var_cbar_string = 'Radiance [Ph s' + r'$^{-1}$' + ' m' + r'$^{-2}$' + ' sr' + r'$^{-1}$' + r'$\mu$' + 'm' + r'$^{-1}$' + ']' var_title_string = "O" + r'$_2$' + ' A-Band Radiance' var_cbar = plt.cm.Purples_r elif var_temp == 'xco2': var_string = 'xco2' var_cbar_string = r'$X_{CO_2}$' + ' [ppm]' var_title_string = r'$X_{CO_2}$' var_cbar = plt.cm.viridis elif var_temp == 'dp': var_string = 'dp' var_cbar_string = 'dp [hPa]' var_title_string = 'dp' var_cbar = plt.cm.RdBu_r elif var_temp == 'aod_total': var_string = 'aod' var_cbar_string = 'AOD' var_title_string = 'AOD' var_cbar = plt.cm.magma else: print("Please select an appropriate variable...") ############################################ #Plot all the individual TG/AMs! for i in range(len(start_indices_temp)): print( "---------------------------------------------------------------") print("Plotting TG/AM ", str(i + 1), " of ", len(start_indices_temp)) data_temp2 = data_temp[start_indices_temp[i]:end_indices_temp[i]] print(data_temp2['target_id'][0], int(data_temp2['orbit'][0]), data_temp2['sounding_id'][0]) #Remove weird outliers that are far from the actual TG/AM cluster_input = np.array( [data_temp2['longitude'], data_temp2['latitude']]).T try: clusters = hcluster.fclusterdata(cluster_input, 1., criterion='distance') print("Cluster #s = ", np.bincount(clusters)) #Grab the largest cluster, or any/all clusters greater than 30 soundings cluster_mask = (clusters == np.argmax( np.bincount(clusters))) | np.isin( clusters, np.where(np.bincount(clusters) > 30)[0]) except: #If there's exactly one sounding, fclusterdata doesn't work cluster_mask = np.ones(len(data_temp2), dtype=bool) #Determine plotting box N,S,E,W = np.round(max(data_temp2['target_lat'][cluster_mask][0],data_temp2['latitude'][cluster_mask].max())+.25,1),\ np.round(min(data_temp2['target_lat'][cluster_mask][0],data_temp2['latitude'][cluster_mask].min())-.25,1),\ np.round(max(data_temp2['target_lon'][cluster_mask][0],data_temp2['longitude'][cluster_mask].max())+(.25/np.cos(np.deg2rad(max(data_temp2['target_lat'][cluster_mask][0],data_temp2['latitude'][cluster_mask].max())))),1),\ np.round(min(data_temp2['target_lon'][cluster_mask][0],data_temp2['longitude'][cluster_mask].min())-(.25/np.cos(np.deg2rad(min(data_temp2['target_lat'][cluster_mask][0],data_temp2['latitude'][cluster_mask].min())))),1) #And keep anything within the plotting box data_temp2 = data_temp2[(data_temp2['latitude'] < N) & (data_temp2['latitude'] > S) & (data_temp2['longitude'] < E) & (data_temp2['longitude'] > W)] #Get some datetime info from the sounding_id month_str = calendar.month_abbr[int( data_temp2['sounding_id'][0].astype(str)[4:6].lstrip("0"))] day_str, year_str = data_temp2['sounding_id'][0].astype( str)[6:8].lstrip("0"), data_temp2['sounding_id'][0].astype( str)[:4].lstrip("0") hour_str, minute_str = data_temp2['sounding_id'][0].astype( str)[8:10], data_temp2['sounding_id'][0].astype(str)[10:12] #Check if the .png exists already. If not, make it! if os.path.isfile(out_dir_temp + '/' + data_temp2['production_string'][0].astype(str) + '/' + var_string + '/OCO3_' + data_temp2['production_string'][0].astype(str) + "_" + var_string + '_' + str(data_temp2['sounding_id'][0])[:8] + '_' + str(int(data_temp2['orbit'][0])) + "_" + data_temp2['target_id'][0].astype(str) + '.png'): print(out_dir_temp + '/' + data_temp2['production_string'][0].astype(str) + '/' + var_string + '/OCO3_' + data_temp2['production_string'][0].astype(str) + "_" + var_string + '_' + str(data_temp2['sounding_id'][0])[:8] + '_' + str(int(data_temp2['orbit'][0])) + "_" + data_temp2['target_id'][0].astype(str) + '.png already exists!') else: fig, ax1 = plt.subplots(figsize=[20, 20]) m1 = Basemap(llcrnrlon=W, llcrnrlat=S, urcrnrlon=E, urcrnrlat=N, epsg=3857, resolution='h') try: m1.arcgisimage(service='World_Imagery', xpixels=2000, verbose=True) except: #Sometimes this fails randomly, so try again time.sleep(20) m1.arcgisimage(service='World_Imagery', xpixels=2000, verbose=True) m1.drawmeridians(np.linspace(W, E, 6)[1:-1], labels=[0, 0, 0, 1], size=24, color='0.75') m1.drawparallels(np.linspace(N, S, 6)[1:-1], labels=[1, 0, 0, 0], size=24, color='0.75') m1.drawcoastlines() #Map Scale. Have to hack because the Basemap drawmapscale function is broken, but this should work. Cartopy doesn't even have a map scale function. lat0 = S + (N - S) * 0.04 + 0.02 #0.04 lon0 = W + (E - W) * 0.04 distance = 40. / np.cos(lat0 * np.pi / 180.) corner_buffered_m1 = m1(lon0, lat0) corner_buffered_lon, corner_buffered_lat = m1( corner_buffered_m1[0] + (distance / 2 * 1000), corner_buffered_m1[1], inverse=True) scale = m1.drawmapscale(corner_buffered_lon, corner_buffered_lat, corner_buffered_lon, corner_buffered_lat, distance, units='km', fontcolor='w', fontsize=16, yoffset=2000) scale[3].set_text(40) #Plot footprints x1, y1 = m1(data_temp2['vertex_longitude_1'], data_temp2['vertex_latitude_1']) x2, y2 = m1(data_temp2['vertex_longitude_2'], data_temp2['vertex_latitude_2']) x3, y3 = m1(data_temp2['vertex_longitude_3'], data_temp2['vertex_latitude_3']) x4, y4 = m1(data_temp2['vertex_longitude_4'], data_temp2['vertex_latitude_4']) patches = [] for i in range(len(x1)): if (x1[i] == 0.0) | (x2[i] == 0.0) | (x3[i] == 0.0) | (x4[i] == 0.0): print("Bad vertex...") else: patches += [ Polygon([(x1[i], y1[i]), (x2[i], y2[i]), (x3[i], y3[i]), (x4[i], y4[i])]) ] p = PatchCollection(patches, alpha=1.) p.set_array(data_temp2[var_temp]) if var_temp == 'dp': p.set_clim( -1 * max(np.abs(np.percentile(data_temp2[var_temp], 10)), np.abs(np.percentile(data_temp2[var_temp], 90))), max(np.abs(np.percentile(data_temp2[var_temp], 10)), np.abs(np.percentile(data_temp2[var_temp], 90)))) elif var_temp == 'aod_total': p.set_clim(0, max(0.3, np.percentile(data_temp2[var_temp], 90))) else: p.set_clim(np.percentile(data_temp2[var_temp], 10), np.percentile(data_temp2[var_temp], 90)) p.set_lw(1.0) p.set_cmap(var_cbar) ax1.add_collection(p) #Colorbar divider = make_axes_locatable(ax1) cax = divider.append_axes("right", size=0.4, pad=0.25) if var_temp == 'aod_total': cbar = fig.colorbar(p, extend='max', cax=cax) else: cbar = fig.colorbar(p, extend='both', cax=cax) cbar.set_label(var_cbar_string, size=28, rotation=270, labelpad=35) cbar.ax.tick_params(labelsize=22) cbar.ax.yaxis.get_offset_text().set_fontsize(22) #Title title = ax1.set_title( 'OCO-3 ' + var_title_string + '\n' + data_temp2['sounding_operation_mode_string'][0].astype(str) + ' Mode (' + data_temp2['sounding_pcs_data_source_string'][0].astype(str) + '), ' + data_temp2['target_id'][0].astype(str) + ', "' + data_temp2['target_name'][0].astype(str) + '"\n' + data_temp2['production_string'][0].astype(str) + '\n' + hour_str + ':' + minute_str + ' UTC ' + day_str + ' ' + month_str + ' ' + year_str + ', Orbit ' + str(int(data_temp2['orbit'][0])), size=30, y=1.01) #Time stamp plt.text(0.99, 0.01, "Created " + str(datetime.datetime.now().day) + ' ' + calendar.month_abbr[datetime.datetime.now().month] + ' ' + str(datetime.datetime.now().year) + "\nCourtesy NASA/JPL-Caltech (R. R. Nelson)", ha='right', va='bottom', transform=ax1.transAxes, color='1.0', size=18) #Preliminary data stamp plt.text(0.01, 0.99, "PRELIMINARY (vEarly)", ha='left', va='top', transform=ax1.transAxes, color='r', size=18) #Globe inset ax2 = inset_axes(ax1, width=2., height=2.) m2 = Basemap(projection='ortho', lat_0=((N + S) / 2.), lon_0=((E + W) / 2.), resolution='l') m2.bluemarble() x1_globe, y1_globe = m2(((W + E) / 2.), ((N + S) / 2.)) m2.scatter(x1_globe, y1_globe, c='r', s=100, marker='*') #Mark the target x1_target, y1_target = m1(data_temp2['target_lon'][0], data_temp2['target_lat'][0]) ax1.scatter(x1_target, y1_target, c='r', marker="*", s=600) #Create save directory if it doesn't exist if not os.path.exists( out_dir_temp + '/' + data_temp2['production_string'][0].astype(str) + '/' + var_string): os.makedirs(out_dir_temp + '/' + data_temp2['production_string'][0].astype(str) + '/' + var_string) #Save figure print("Saving as " + out_dir_temp + '/' + data_temp2['production_string'][0].astype(str) + '/' + var_string + '/OCO3_' + data_temp2['production_string'][0].astype(str) + "_" + var_string + '_' + str(data_temp2['sounding_id'][0])[:8] + '_' + str(int(data_temp2['orbit'][0])) + "_" + data_temp2['target_id'][0].astype(str) + '.png')
def plotSparseMatrix(matrix, chrom, vmin, vmax, RF_dict, output_filepath): "Plots HIFI sparse matrix using Python's Matplotlib module" plt.ioff() #prevent view window from openning over ssh connection fig, ax = plt.subplots(figsize=(8, 8)) #create heat map using 'PatchCollection' rectangles and associated coordinates x = 0.0 patches, colours = [], [] y = sum(RF_dict["y"]["sizes"]) for i, row_height in enumerate(RF_dict["y"]["sizes"]): y -= row_height for j, col_width in enumerate(RF_dict["x"]["sizes"]): colours.append(matrix[i][j]) patch = Rectangle((x, y), col_width, row_height) patches.append(patch) x += col_width x = 0.0 #plot 'PatchCollection' of rectangles pc = PatchCollection(patches, cmap=cmap) pc.set_clim([vmin, vmax]) pc.set_array(np.array(colours)) pc.set_edgecolor("face") pc.set_lw(0.1) ax.add_collection(pc) #remove outline from color bar cbar = plt.colorbar(pc, fraction=0.04575, pad=0.04) cbar.outline.set_visible(False) cbar.ax.tick_params(labelsize=16, length=4, width=0.5, color="grey") ax.tick_params(axis="x", which="both", bottom=False, top=False, direction="out", length=4, width=0.5, pad=10, color="grey", labelsize=16) ax.xaxis.set_label_position("top") ax.set_xlabel(RF_dict["x"]["label"], fontsize=16, labelpad=8.25) ax.xaxis.tick_top() ax.tick_params(axis="y", which="both", left=False, right=False, direction="out", length=4, width=0.5, color="grey", labelsize=16) ax.set_ylabel(RF_dict["y"]["label"], fontsize=16, labelpad=None) ax.grid(False) # remove x and y ticks plt.xticks([], []) plt.yticks([], []) # remove axis edges for axis in ["bottom", "top", "left", "right"]: plt.gca().spines[axis].set_visible(False) ax.set_aspect("equal") plt.tight_layout() plt.savefig(output_filepath + ".png", format="png", dpi=600, transparent=False, bbox_inches="tight") plt.savefig(output_filepath + ".pdf", format="pdf", transparent=False, bbox_inches="tight") plt.close() #save matrix np.savetxt(output_filepath + ".csv", matrix, delimiter=",")