I am trying to plot a raster with rasterio but somehow that data is being resampled, I think.
The map created does not show the detail in the data. See here:
python plot
...compared to the original data (plotted with GIS):
topo data
Any idea how to stop rasterio from interpolating/resampling the data?
Here is my code:
import rasterio
from rasterio.plot import show
import matplotlib.pyplot as plt
topo = rasterio.open('../topo_raster/nz100dem2ihs21.tif')
nz_mask_file = '../gis_data/NZ_mask.shp'
nzmask = gpd.read_file(nz_mask_file)
fig= plt.figure(dpi=300. )
ax = plt.axes( projection=ccrs.epsg(27200))
show(topo.read(1,masked=True), ax=ax,transform=topo.transform,interpolation='none',zorder=1,cmap='gist_gray')
nzmask.plot(ax=ax,facecolor="white", edgecolor='black', lw=linewidths_rr,zorder=0.5)
plt.savefig('../newzealand.png')
plt.clf()
Related
Currently I'm doing some data visualization using python, matplotlib and mplcursor that requires to show different parameters and values at the same time in a certain time period.
Sample CSV data that was extracted from a system:
https://i.stack.imgur.com/fjd1d.png
My expected output would look like this:
https://i.stack.imgur.com/zXGXA.png
Found the same case but they were using numpy functions: Add the vertical line to the hoverbox (see pictures)
Hoping someone will suggest what is the best approach of my problem.
Code below:
import matplotlib.pyplot as plt
import numpy as np
import mplcursors
import pandas as pd
fig, ax=plt.subplots()
y1=ax.twinx()
y2=ax.twinx()
y2.spines.right.set_position(("axes", 1.05))
df=pd.read_csv(r"C:\Users\OneDrive\Desktop\sample.csv")
time=df['Time']
yd1=df['Real Power']
yd2=df['Frequency']
yd3=df['SOC']
l1=ax.plot(time,yd1,color='black', label='Real Power')
l2=y1.plot(time,yd2, color='blue', label='Frequency')
l3=y2.plot(time,yd3, color='orange', label='SOC')
df=pd.DataFrame(df)
arr=df.to_numpy()
print(arr)
def show_annotation(sel):
x=sel.target[0]
annotation_str = df['Real Power'][sel.index]
#sel.annotation.set_text(annotation_str)
fig.autofmt_xdate()
cursor=mplcursors.cursor(hover=True)
cursor.connect('add', show_annotation)
plt.show()```
I've been working to make a visual for a poster regarding the physical domain that I am studying. I'm working with a nested domain, so I have 1 smaller domain inside a larger outer domain. I'm trying to create a cartopy plot that shows both the outer domain and inner domain. Ideally, the result would look something like this:
I'm really struggling with trying to get my smaller domain inscribed onto my map. I've attempted to make a Shapely LinearRing to show the inner domain, but it is not working. Here's the code I have created so far:
# Imports
import numpy as np
import sys, os
import matplotlib.pyplot as plt
%matplotlib inline
import netCDF4
from netCDF4 import Dataset
from matplotlib.cm import get_cmap
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.feature import NaturalEarthFeature, COLORS
import metpy as mp
import metpy.calc as mpcalc
from metpy.calc import divergence, smooth_gaussian
from metpy.units import units
import xarray as xr
from wrf import getvar, interplevel, to_np, latlon_coords, get_cartopy, cartopy_xlim, cartopy_ylim, ALL_TIMES
from shapely.geometry.polygon import LinearRing
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
from shapely import geometry
# Get 1km lats/lons
lats1km = getvar(ds1, 'lat')
lons1km = getvar(ds1, 'lon')
lat1km_max = to_np(np.max(lats1km))
lat1km_min = to_np(np.min(lats1km))
lon1km_max = to_np(np.max(lons1km))
lon1km_min = to_np(np.min(lons1km))
# Get 3km lats/lons
lats3km = getvar(ds3, 'lat')
lons3km = getvar(ds3, 'lon')
lat3km_max = to_np(np.max(lats3km))
lat3km_min = to_np(np.min(lats3km))
lon3km_max = to_np(np.max(lons3km))
lon3km_min = to_np(np.min(lons3km))
domain = [lon3km_min, lat3km_min, lon3km_max, lat3km_max]
lons = [lat1km_min, lat1km_min, lat1km_max, lat1km_max]
lats = [lon1km_min, lon1km_max, lon1km_max, lon1km_min]
ring = LinearRing(list(zip(lons, lats)))
geom = geometry.box(minx=lon1km_min, miny=lat1km_min, maxx=lon1km_max, maxy=lat1km_max)
# Grab CRS
crs = get_cartopy(wrfin=ds1)
# Create figure and axes
fig = plt.figure(figsize=(20,10))
ax0 = fig.add_subplot(1, 1, 1, projection=crs)
ax0.set_extent([lon3km_min, lon3km_max, lat3km_min, lat3km_max])
ax0.add_geometries([ring], crs=crs, facecolor='blue', edgecolor='black')
ax0.add_geometries([geom], crs=crs, alpha=0.3)
plot_background(ax0)
This yields my outer domain, but not my inner domain:
What am I doing wrong, and what can I do to get my inner domain shown on the map? Thank you for the help! I really appreciate it!
NOTE: I have already attempted the solution in this link. I am still unable to visualize my polygon.
Have a look at EOmaps ! (I'm the dev) it provides simple functions to add static (or interactive) indicators such as projected rectangles or ellipses to cartopy plots in 1 line!
from eomaps import Maps
m = Maps()
m.add_coastlines()
props = dict(xy=(10, 45), xy_crs=4326, radius_crs=4326, shape="rectangles")
m.add_marker(**props, radius=3, fc=(0,1,0,.5), ec="r", lw=2)
m.add_marker(**props, radius=5, fc="none", ec="k")
m.add_marker(**props, radius=(15, 10), fc="none", ec="m", ls="--", lw=2)
m.figure.ax.set_extent((-15., 65., -5., 75.))
I have a netcdf file ('test.nc'). The variables of the netcdf file are the following:
variables(dimensions): float64 lon(lon), float64 lat(lat), int32 crs(), int16 Band1(lat,lon)
I am interested in the ´Band1´ variable.
Using cartopy, I could plot the data using the following code:
import numpy as np
import pandas as pd
import gzip
from netCDF4 import Dataset,num2date
import time
import matplotlib.pyplot as plt
import os
import matplotlib as mplt
#mplt.use('Agg')
import cartopy.crs as ccrs
import cartopy.feature as cfea
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
projection=ccrs.PlateCarree()
bbox=[-180,180,-60,85];creg='glob'
mplt.rc('xtick', labelsize=9)
mplt.rc('ytick', labelsize=9)
nc = Dataset('test.nc','r')
lat = nc.variables['lat'][:]
lon = nc.variables['lon'][:]
kopi= (nc.variables['Band1'][:,:])
nc.close()
fig=plt.figure(figsize=(11,5))
ax=fig.add_subplot(1,1,1,projection=projection)
ax.set_extent(bbox,projection)
ax.add_feature(cfea.COASTLINE,lw=.5)
ax.add_feature(cfea.RIVERS,lw=.5)
ax.add_feature(cfea.BORDERS, linewidth=0.6, edgecolor='dimgray')
ax.background_patch.set_facecolor('.9')
levels=[1,4,8,11,14,17,21,25,29]
cmap=plt.cm.BrBG
norm=mplt.colors.BoundaryNorm(levels,cmap.N)
ddlalo=.25
pc=ax.contourf(lon,lat,kopi,levels=levels,transform=projection,cmap=cmap,norm=norm,extend='both')
divider = make_axes_locatable(ax)
ax_cb = divider.new_horizontal(size="3%", pad=0.1, axes_class=plt.Axes)
fig.colorbar(pc,extend='both', cax=ax_cb)
fig.add_axes(ax_cb)
fig.colorbar(pc,extend='both', cax=ax_cb)
ttitle='Jony'
ax.set_title(ttitle,loc='left',fontsize=9)
plt.show()
However, I would like just to plot a selection of values inside the variable ´Band1´. I thought I could use the following code:
kopi= (nc.variables['Band1'][:,:])<=3
However it does not work and instead of plotting the area corresponding to the value selection it selected the all map.
How could I select and plot a desired range of values inside the variables ´Band1´?
Just mask the values with np.nan
kopi[kopi <=3] = np.nan
This should yield to white pixels in your plot.
Please provide test data in the future.
I am posting this question after three days searching the net but no success. Hope can get the answer here. Please do NOT delete the post as I did not find an answer for it here also. Thanks.
I have 2 files:
A raster image file (i.e., Air temperature 2020-01-01.tif)
World countries boundary shapefile ((i.e., World_Countries_base_map.shp)
Goal: I want to plot the shapefile on top of raster file, and then save the plot in a Jpeg file format to get something like this eventually:
I am quite new in Python, and used Spyder to prepare this simple code to do so:
# Import needed packages
import os
import rasterio
import matplotlib.pyplot as plt
import geopandas as gpd
import earthpy as et
from matplotlib import pyplot
## list all raster images in tiff format in the folder:
list_files = [f for f in
os.listdir('C:/Users/Desktop/Question/Raster_Air_temp')
if '.tif' in f]
print(list_files[1]) # checking the 1st file in the list
## reading the first tiff file:
raster_image = rasterio.open(list_files[1])
## plot it
draft_output = pyplot.imshow(raster_image.read(1), cmap='jet')
## importing world shapefile
World_map = gpd.read_file('C:/Users/Desktop/Question/World_shapefile/World_Countries_base_map.shp')
# plot World shapefile
fig, ax = plt.subplots(figsize = (30,30)) # image size and quality can be controled by figsize
ax.set_title('The Glob Map', fontsize=50);
World_map.plot(ax=ax, color='white', edgecolor='black') # colors note at https://matplotlib.org/tutorials/colors/colormaps.html
plt.show()
## Plot both World shapefile and raster image in one graph:
????
However, this code just produces 2 separated plots in the console for me as can be seen above.
Question: How can I type a proper code in ???? section of the code to get to my Goal (mentioned above)?
Thanks to all comments and helps.
Here, I share the two files in order to make it easier for those who want help.
Download the files from my Dropbox
.
since i have no access to your data I am showing the principle with some sample data from geopandas and a random numpy ndarray as a tiff surrogate.
the key point is to show the tiff with rasterios rasterplot and don't forget to set the extent of your DEM!
import rasterio
import numpy as np
from rasterio import plot as rasterplot
import geopandas as gpd
from matplotlib import pyplot as plt
# this is how you'd open the raster dataset if you have one
#tiff = rasterio.open('example.tif')
#tiff_extent = [tiff.bounds[0], tiff.bounds[2], tiff.bounds[1], tiff.bounds[3]]
# i am making this array up
tiff_band_1 = np.random.randint(0, 10, size=(65, 64))
tiff_extent = [4159200.0, 4808100.0, 2828000.0, 3482600.0]
shapefile = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
shapefile = shapefile.to_crs('epsg:3035')
shapefile = shapefile[shapefile.name == 'Germany']
f, ax = plt.subplots()
# plot DEM
rasterplot.show(
tiff_band_1, # use tiff.read(1) with your data
extent=tiff_extent,
ax=ax,
)
# plot shapefiles
shapefile.plot(ax=ax, facecolor='w', edgecolor='k')
plt.savefig('test.jpg')
plt.show()
I am trying to plot the Pumps.shp data on top of the OSMap.tif file from this website on the same figure.
I tried using rasterio.plot() and geopandas.plot() methods, with matplotlibs subplots.
The problem is that the plots don't match, the raster file gets plotted in the range(0,1000) for both axis and the shp gets plotted in the actual coordinates range(around 50000 on the x axis and around).
The crs are equal in both objects and the coordinates are in the same range. Why is this? What am I doing wrong?
Here is my code
import rasterio as rast
import rasterio.plot as rsplot
import geopandas as gpd
src=rast.open("OSMap.tif")
data=gpd.read_file("Pumps.shp")
fig,ax=plt.subplots()
rsplot.show(src,ax=ax)
data.plot(ax=ax)
plt.show()
This is the result of calling src.bounds:
BoundingBox(left=528765.0, bottom=180466.0, right=529934.0, top=181519.0)
This is the result of data.bounds
(528765.0, 180466.0, 529934.0, 181519.0)
This is crs of both:
CRS({'lon_0': -2, 'y_0': -100000, 'k': 0.9996012717, 'lat_0': 49, 'proj': 'tmerc', 'wktext': True, 'datum': 'OSGB36', 'no_defs': True, 'x_0': 400000, 'units': 'm'})
I had the same problem with rasterio 0.36.0. I first tried to translate and scale the raster but than prefered to translate the shapefile.
My code looks like:
import geopandas as gpd
import matplotlib.pyplot as plt
import rasterio
image = rasterio.open('input.tif') # with tgw world file
shapefile = gpd.read_file('input.shp')
# coordinates and scaling factors
scale_x = image.transform[1]
scale_y = image.transform[5]
x0 = image.transform[0]
y0 = image.transform[3]
# translates back shapefile
shapefile.geometry = shapefile.translate(-x0, -y0)
shapefile.geometry = shapefile.scale(-1.0/scale_x, -1.0/scale_y, origin=(0, 0, 0))
# plots both elements
fig, ax = plt.subplots()
ax = rasterio.plot.show(image.read(), with_bounds=True, ax=ax)
shapefile.plot(ax=ax)
Use matplotlib imshow instead of rasterio show. Pass the bounds of raster as "extent" parameter of imshow.