Plotting climate data with NetCdf files for a specific region - plot

I can plot temperature distribution figures with global NetCdf files with these codes.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from netCDF4 import Dataset as dt
import numpy as np
import matplotlib.pyplot as plt
filestr='E:/VIC/Forcing Data from princeton/from 48 to 2016/01.tmax/tmax_daily_2000-2000.nc'
ncfile=dt(filestr, 'r')
lats = ncfile.variables['lat'][:]
lons = ncfile.variables['lon'][:]
time = np.array(ncfile.variables['time'][:], dtype=np.float64)
data = ncfile.variables['tmax'][300,:,:]
data -=273
# Set font name
plt.rcParams["font.family"] = "cambria"
# Add Title
plt.suptitle('sub title', fontsize=12, fontweight='bold') #<---------
plt.title('title' , fontsize=12) #<---------
# Add basemap
map = Basemap(projection='merc',llcrnrlon=30,llcrnrlat=24,urcrnrlon=53,urcrnrlat=43,resolution='i', epsg = 4269)
# projection, lat/lon extents and resolution of polygons to draw
# resolutions: c - crude, l - low, i - intermediate, h - high, f - full
#map.drawmapscale()
map.arcgisimage(service='World_Physical_Map', xpixels = 5000, verbose= False)
map.drawcoastlines(linewidth=0.3, color='xkcd:darkblue')
#map.drawstates(linewidth=0.8)
#map.drawcountries(color ='r')
#map.drawlsmask(land_color='Linen', ocean_color='#CCFFFF') # can use HTML names or codes for colors
#map.drawcounties() # you can even add counties (and other shapefiles!)
parallels = np.arange(24.125,42.125,25.) # make latitude lines ever 5 degrees from 30N-50N #<---------
meridians = np.arange(32.125,52.375,25.) # make longitude lines every 5 degrees from 95W to 70W #<---------
map.drawparallels(parallels,linewidth=0.3,labels=[1,0,0,0],fontsize=10, color='white')
map.drawmeridians(meridians,linewidth=0.3,labels=[0,0,0,1],fontsize=10, color='white')
map.readshapefile('C:/Users/fyunu/OneDrive/Masaüstü/ETB STUDY/Shape File Area of the ETB basin/Aqueduct_river_basins_TIGRIS & EUPHRATES', \
name='Aqueduct_river_basins_TIGRIS & EUPHRATES', drawbounds=True, linewidth=0.6) #<---------
lon,lat= np.meshgrid(lons,lats) #(lons-360.,lats) # for this dataset, longitude is 0 through 360, so you need to subtract 180 to properly display on map
xi,yi = map(lon,lat) #<---------
levels = [i for i in range(-20, 70, 5)]
#levels = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.1, 1.5, 2.]
#levels = [-1., 0.6, 0.80, 0.85, 0.90, 0.95, 1, 1.05, 1.1, 1.15, 1.2, 1.4, 5]
#cs = map.pcolor(xi,yi,var,cmap='jet',vmin=min_value, vmax=max_value) #'RdBu_r')
map.contour(xi, yi, data, levels, linewidths=0.1, colors='k', linestyles='solid')
cs = map.contourf(xi, yi, data, levels, cmap=plt.get_cmap('jet'))#cmap=plt.cm.jet) #colors=colors_range) #,vmin=min_value, vmax=max_value) #<---------
# Add Colorbar
cbar = map.colorbar(cs, location='right', size='5%',pad="1%")
cbar.set_label('unit') #('Percent’) #<---------
plt.show()
#plt.savefig(path + 'mapPlot_' + plotInfo.variable + '_' + title + '_' + plotInfo.legend + '.png',transparent=True, dpi=300) #<---------
plt.close()
But I want to select only coordinates of the specific region. I have those coordinates in a csv file. Csv file has one column as 'lons' and one column as 'lats'. I want to read these columns and plot the data distribution according to these coordinates.
I tried
inpExcelFile = 'C:/Users/fyunu/OneDrive/Masaüstü/gridCellCoordinates6 seperately.csv' #lat, lon
df1 = pd.read_csv(inpExcelFile)
lats = float(df1.columns['lats'][:])
lons = float(df1.columns['lons'][:])
But I got OSError: Initializing from file failed.

Related

Add Spearman Correlation Coefficient and RMSE in a plot, and change the plot size

I've got the following dataset:
structure(list(Count = 1:14, GW = c(0.08, 0.04, 0.35, 0.54, 0.39,
0.94, 0.51, 0.01, 0.44, 0.63, 0.14, 0.79, 0.43, 0.73), Pz1 = c(-2.459826614,
-2.905007821, -2.241113224, -1.549264338, -1.761962438, -1.282612221,
-0.428828702, 1.659042479, 2.63518648, 3.076022461, 1.886216859,
0.124473561, -1.025720789, -1.969461882), Pz2 = c(-2.916090168,
-3.262459435, -2.455396094, -1.488106654, -0.417171756, -1.781014095,
-0.605012986, 1.037062685, 1.977265974, 2.587846362, 2.499228916,
1.0852274, -0.503736287, -1.829562138), Pz3 = c(-2.507944967,
-3.718722989, -2.812847708, -1.702389524, -0.356014073, -0.436223413,
-1.10341486, 0.860878402, 1.355286181, 1.929925855, 2.011052817,
1.698239458, 0.457017552, -1.307577636), Pz4 = c(-2.526729696,
-3.310577787, -3.269111262, -2.059841138, -0.570296943, -0.375065729,
0.241375822, 0.362476528, 1.179101897, 1.307946062, 1.35313231,
1.210063358, 1.07002961, -0.346823797), Pz5 = c(-3.284551238,
-3.329362517, -2.86096606, -2.516104692, -0.927748557, -0.5893486,
0.302533506, 1.70726721, 0.680700023, 1.131761778, 0.731152517,
0.552142851, 0.58185351, 0.266188261), Pz6 = c(-4.011896321,
-4.087184059, -2.87975079, -2.107959491, -1.38401211, -0.946800213,
0.088250636, 1.768424893, 2.025490705, 0.633359905, 0.554968233,
-0.069836942, -0.076066996, -0.221987839), Pz7 = c(-4.769878994,
-4.814529142, -3.637572331, -2.12674422, -0.975866909, -1.403063767,
-0.269200978, 1.554142023, 2.086648388, 1.978150587, 0.05656636,
-0.246021225, -0.698046789, -0.879908346)), class = "data.frame", row.names = c(NA,
-14L))
And I am running this code to automatically save the plots in a folder:
library(tidyverse)
library(ggplot2)
#~~~ step 1: transform the data from 'wide' format to 'long' format ~~~
my_data %>%
pivot_longer(names_to = 'key', values_to = 'value',-c(Count, GW)) %>%
{. ->> my_data_long}
#~~~ step 2: write a function to plot the data and save the plot ~~~
saveplot_function <- function(i){
my_plot <- my_data_long %>%
filter(
key == i
) %>%
ggplot(aes(x=Count)) +
geom_line(aes(y = scale(GW)), color = "blue") +
geom_line(aes(y = scale(value)), color="red") +
ylab(i)
ggsave(paste0('my_location/my_folder/', i, '.png'))
}
#~~~ step 3: loop through all the values of 'key' (column names in the wide format data) ~~~
for(i in unique(my_data_long$key)){
saveplot_function(i)
}
This code does the job, but I'd need to add a box (or just the text) showing the Spearman Correlation Coefficient and the RMSE for each plot (or better say for the two time series displayed within each plot).
Also, the plots are saved in a squared shape, and I would like them to be rectangular instead.
Something like this would be great:
Could you kindly help me to rewrite the code accordingly? I am not an R expert at all and this code has been modified from an old code that someone kindly wrote for me ( and it took me ages to make it work for the purpose I am using it for), so I would very much appreciate it if you could rewrite it (sorry!).
Additionally, as you can see from the code above, I used scale(). What I am trying to do is to standardise the plotted data using Z-Scores (i.e., Z = (x - mean(x)) / Standard_Deviation(x) ). Can you kindly confirm (or reject) that scale() standardises the time series using Z-Scores?
I am a little unclear about some parts of your question, but hopefully this will help. According to the documentation, scale() does the z-score transformation with numeric data because the center value is the mean and the scale value is the standard deviation.
Adding text to the plot can be done with annotate() and providing text and coordinates. I used two separate annotations, one for correlation that also used bquote() to get the Greek letter rho and the other for RMSE. I used the max values of GW, Value, and Count to anchor the text. This might need to be refined. I also computed the RMSE and correlation of the unscaled series.
A sample plot are provided below. I would check to make sure that things are being calculated the way you expect.
my_data = structure(list(Count = 1:14, GW = c(0.08, 0.04, 0.35, 0.54, 0.39,
0.94, 0.51, 0.01, 0.44, 0.63, 0.14, 0.79, 0.43, 0.73),
Pz1 = c(-2.459826614, -2.905007821, -2.241113224, -1.549264338, -1.761962438, -1.282612221,
-0.428828702, 1.659042479, 2.63518648, 3.076022461, 1.886216859,0.124473561, -1.025720789, -1.969461882),
Pz2 = c(-2.916090168,-3.262459435, -2.455396094, -1.488106654, -0.417171756, -1.781014095,
-0.605012986, 1.037062685, 1.977265974, 2.587846362, 2.499228916,1.0852274, -0.503736287, -1.829562138),
Pz3 = c(-2.507944967,-3.718722989, -2.812847708, -1.702389524, -0.356014073, -0.436223413,
-1.10341486, 0.860878402, 1.355286181, 1.929925855, 2.011052817,1.698239458, 0.457017552, -1.307577636),
Pz4 = c(-2.526729696,-3.310577787, -3.269111262, -2.059841138, -0.570296943, -0.375065729,
0.241375822, 0.362476528, 1.179101897, 1.307946062, 1.35313231,1.210063358, 1.07002961, -0.346823797),
Pz5 = c(-3.284551238,-3.329362517, -2.86096606, -2.516104692, -0.927748557, -0.5893486,
0.302533506, 1.70726721, 0.680700023, 1.131761778, 0.731152517,0.552142851, 0.58185351, 0.266188261),
Pz6 = c(-4.011896321,-4.087184059, -2.87975079, -2.107959491, -1.38401211, -0.946800213,
0.088250636, 1.768424893, 2.025490705, 0.633359905, 0.554968233,-0.069836942, -0.076066996, -0.221987839),
Pz7 = c(-4.769878994,-4.814529142, -3.637572331, -2.12674422, -0.975866909, -1.403063767,
-0.269200978, 1.554142023, 2.086648388, 1.978150587, 0.05656636,-0.246021225, -0.698046789, -0.879908346)),
class = "data.frame",
row.names = c(NA,-14L))
library(tidyverse)
library(ggplot2)
#~~~ step 1: transform the data from 'wide' format to 'long' format ~~~
my_data %>%
pivot_longer(names_to = 'key', values_to = 'value',-c(Count, GW)) %>%
{. ->> my_data_long}
#~~~ step 2: write a function to plot the data and save the plot ~~~
saveplot_function <- function(i){
# get data for key i
df_temp <- my_data_long %>%
filter(
key == i
)
# calculate RMSE and correlation
# adjust calculation as needed
rmse <- round(mean((df_temp$GW-df_temp$value)^2),3)
correl <- round(cor(df_temp$GW,df_temp$value),3)
my_plot <- my_data_long %>%
filter(
key == i
) %>%
ggplot(aes(x=Count)) +
geom_line(aes(y = scale(GW)), color = "blue") +
geom_line(aes(y = scale(value)), color="red") +
ylab(i)+
annotate(geom="text", x=max(df_temp$Count)-2,
y=max(df_temp$value,df_temp$GW),
label=bquote(paste(," rho (",rho,") =",.(correl),sep="")),#expression(paste("rho (", rho, ") = ",as.character(correl),sep='')),
color="black")+
annotate(geom="text", x=max(df_temp$Count)-2,
y=max(df_temp$value,df_temp$GW)-0.5,
label=paste('RMSE = ',rmse,sep=''),
color="black")
ggsave(paste0("my_location/my_folder/", i, '.png'),
width=6,
height=4,
units='in')
}
#~~~ step 3: loop through all the values of 'key' (column names in the wide format data) ~~~
for(i in unique(my_data_long$key)){
saveplot_function(i)
}

Outputting a list of the intersecting genes/Values when making a VennDiagram in R with the VennDiagram package

I made a VennDiagram with five intersecting vectors, each containing a set of gene names.
Does anyone know whether I can somehow export the list of genes, which overlap in the different intersections?
I know I can do that with several online tools, such as Venny or InteractiVenn, but it would be much more convenient in R.
This is the code I use:
venn.diagram(
x = list(set1, set2, set3, set4, set5),
category.names = c("set1", "set2", "set3", "set4", "set5"),
filename= "my_path/venn.png",
output=NULL,
# # Output features
imagetype="png" ,
height = 2000 ,
width = 2000 ,
units = "px",
na = 'stop',
resolution = 300,
compression = "lzw",
lwd = 2,
col = c("#1ABC9C", "#85C1E9", "#CD6155", "#5B2C6F", "#F8C471"),
cat.col = c("#1ABC9C", "#85C1E9", "#CD6155", "#5B2C6F", "#F8C471"),
fill = c(alpha("#1ABC9C",0.3), alpha("#85C1E9",0.3), alpha("#CD6155",0.3), alpha("#5B2C6F",0.3), alpha("#F8C471",0.3)),
cex = 1.5,
fontfamily = "sans",
cat.cex = 1.15,
cat.default.pos = "text",
cat.fontfamily = "sans",
cat.dist= c(0.055),
cat.pos= c(1)
)
Thanks!
I suspect the OP has moved on, but I had the same question.
Here's what I came up with for a five set example- NB this uses a different package:
require(nVennR)
require(dplyr)
# wrangle input
Venn <- plotVenn(list("set1"=set1, "set2"=set2, "set3"=set3, "set4"=set4,
"set5"=set5), outFile = "DataSourceVenn.svg") # produces associated diagram
# generate lists of each intersect
intersects <- listVennRegions(Venn)
# pull lists together
intersects <- plyr::ldply(intersects, cbind)
# insert own appropriate col name for V1
colnames(intersects)<-c('Intersect','V1')
# transpose data into columns for each intersect
intersects <- dcast(setDT(intersects), rowid(Intersect) ~ Intersect, value.var =
"V1")[,Intersect:=NULL]

How to update the data source for networkx graph with bokeh?

I would like to change the data source for bokeh network graph. However the from_network function does not allow me to input source = new_source for example. However do I change the data source for the network graph to be updated if click a button?
#PLOT GRAPH WITH BOKEH SERVER
def update_plot_layout(layout_name, range, source_bar):
plot_degree = figure(title='Knowledge Graph', x_range=range, y_range=range,
tools=['box_select,pan,wheel_zoom,box_zoom,reset'],
toolbar_location="right",
toolbar_sticky=False)
plot_degree.grid.grid_line_color = None
graph = from_networkx(g, layout_name , scale=2, center=(0,0))
# graph.node_renderer.data_source = source
#
graph.node_renderer.glyph = Circle(size=20,
fill_color= 'crimson',
fill_alpha = 0.8, line_color = 'black')
# graph.node_renderer.glyph = Circle(size='node_size',
# fill_color= 'crimson',
# fill_alpha = 0.8, line_color = 'black')
#
graph.edge_renderer.glyph = MultiLine(line_color='gray', line_width=1.5, line_alpha = 0.5)
# plot_degree.add_tools(HoverTool(line_policy='interp', tooltips=[('ID', '#index'),
# ('Degree Centrallity', '#degree_centrality')]))
plot_degree.renderers.append(graph)

Circular plot with related temperature

Hello guys and thanks in advance for your time.
I'm trying to create a circular plot with a color map that should be related with different temperature values acquired on a disk in order to verify the homogeneity of the heating, but despite my numerous trial and efforts it just wont work as i'd like it to be (i'm a newbie in programming).
Any ideas?
Thanks for your attention and have a nice day!
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
x = np.arange(-2, 2, 0.01)
y = np.arange(-2, 2, 0.01)
X, Y = np.meshgrid(x, y)
Z = X**2 + Y**2 + 1 #np.sin(X) * np.cos(Y) * 2
R = 4
Z[Z>R] = 0
colors = [(1,1,1), (0.99, 0.90, 0.68), (1, 0.87, 0.58), (0.93, 0.79, 0.53), (0.97, 0.71, 0.35), (0.84, 0.71, 0.27), (0.74, 0.48, 0.23),
(0.65, 0.44, 0.24), (0.56, 0.39, 0.23), (0.48, 0.32, 0.23),( 0.84, 0.53, 0.20), (0.21, 0.2, 0.17)] # R -> G -> B
n_bins = [100]
cmap_name = 'my_list'
fig, axs = plt.subplots(2, figsize=(6, 9))
fig.subplots_adjust(left=0.02, bottom=0.06, right=0.95, top=0.94, wspace=0.05)
for n_bin, ax in zip(n_bins, axs.ravel()):
cm = LinearSegmentedColormap.from_list(
cmap_name, colors, N=n_bin)
im = ax.imshow(Z, interpolation='nearest', origin='lower', cmap=cm)
ax.set_title("N bins: %s" % n_bin)
fig.colorbar(im, ax=ax)
This is a code that i'm trying to modify in order fit my purpose (temperature values correlation is still missing, i know...).

RGoogleMaps axes

I can't find any documentation of the following problem I'm having with the axis labels in RGoogleMaps:
library(RgoogleMaps)
datas <- structure(list(LAT = c(37.875, 37.925, 37.775, 37.875, 37.875),
LON = c(-122.225, -122.225, -122.075, -122.075, -122.025)),
.Names = c("LAT", "LON"), class = "data.frame",
row.names = c(1L, 2L, 3L, 4L, 5L))
# Get bounding box.
boxt <- qbbox(lat = datas$LAT, lon = datas$LON)
MyMap <- GetMap.bbox(boxt$lonR, boxt$latR, destfile = "Arvin12Map.png",
maptype = "mobile")
PlotOnStaticMap(MyMap, lat = datas$LAT, lon = datas$LON,
axes = TRUE, mar = rep(4, 4))
When I run this on my computer the horizontal axis ranges from 300W to 60E, but the ticks in between aren't linearly spaced (300W, 200W, 100W, 0, 100E, 160W, 60W).
Also, the vertical axis moves linearly from 300S to 300N. It seems that no matter what data I supply for datas, the axes are always labeled this way.
My question is:
1. Does this problem occur on other machines using this code?
2. Does anyone have an explanation for it?
and
3. Can anybody suggest a way to get the correct axes labels (assuming these are "incorrect", but maybe i'm somehow misinterpreting the plot!)?
Thank you for your time.
Yes
As #Andrie suggested, this appears to be a bug. When axes = TRUE, the degAxis() function called by PlotOnStaticMap() extracts the x and y plot coordinates of the pretty tickmarks found by axTicks(). degAxis() expects these coords to be in the coordinate system of the map, but rGoogleMaps returns them as pixel coordinates, calculated from a central origin. With a plot size of 640 x 640, the pretty tickmarks are assigned to -300, -200, -100, 0,100, 200, 300 in both E-W and N-S directions. You end up with 300W, 200W, 100W, 0, 100E, 160W, 60W, because the degreeLabelsEW() function called by degAxis() assumes that, given longitudes must fall within [-180, 180], any longitudes higher than 180 are in fact in the western hemisphere (e.g. 200E is 20 degrees eastward into the western hemisphere, i.e. 160W). Not sure why it doesn't perform similarly with nonsensical N, S and W coordinates.
A quick workaround, continuing with your MyMap object:
PlotOnStaticMap(MyMap, lat = datas$LAT, lon = datas$LON,
axes = FALSE, mar = rep(4.5, 4))
# x-axis
xrange <- MyMap$BBOX$ur[2] - MyMap$BBOX$ll[2]
xticklength <- xrange / (length(axTicks(1)) - 1)
xticklabs <- seq(MyMap$BBOX$ll[2], MyMap$BBOX$ur[2], xticklength)
xticklabs <- parse(text = paste(sprintf('%.2f', abs(xticklabs)),
ifelse(xticklabs < 0, '*degree*W', '*degree*E'), sep=''))
axis(1, at=axTicks(1), xticklabs, cex.axis=0.8)
# y-axis
yrange <- MyMap$BBOX$ur[1] - MyMap$BBOX$ll[1]
yticklength <- yrange / (length(axTicks(2)) - 1)
yticklabs <- seq(MyMap$BBOX$ll[1], MyMap$BBOX$ur[1], yticklength)
yticklabs <- parse(text = paste(sprintf('%.2f', abs(yticklabs)),
ifelse(yticklabs < 0, '*degree*S', '*degree*N'), sep=''))
axis(2, at=axTicks(2), yticklabs, cex.axis=0.8, las=1)

Resources