How do I plot 2D map like this image in Python - python

I am trying to create a plot like the image using the data attached here, however when I try to plot the grid data I am having a memory error.
I can only plot the the file using scatter option from matplotlib like my following example:
%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from scipy.interpolate import griddata
dffold = pd.read_csv('foldmap.toc', delimiter='\t',encoding='latin1',usecols=['Inline','Crossline','X','Y','Fold'])
x1 = np.array(dffold.X)
y1 = np.array(dffold.Y)
zf = np.array(dffold.Fold)
xi = np.linspace(min(x1), max(x1))
yi = np.linspace(min(y1), max(y1))
A, B = np.meshgrid(xi, yi, copy=False)
zi = griddata((x1, y1), zf , (xi, yi), method='nearest')
plt.scatter(x1,y1,zf)
plt.show()

Related

Regridding and plotting netcdf file with irregular grid

I am trying to regrid my .nc data with irregular grid with the following code:
from mpl_toolkits.basemap import Basemap
from netCDF4 import Dataset as NetCDFFile
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import griddata
nc = NetCDFFile('test.nc')
lat = nc.variables['latitude'][:]
lon = nc.variables['longitude'][:]
time = nc.variables['time'][:]
ssi = nc.variables['solar_irradiation'][:]
XI = np.arange(46.025, 56.525, 0.05)
YI = np.arange(5.025, 15.525, 0.05)
lat_new, lon_new = np.meshgrid(XI, YI)
new_grid = griddata((lat, lon), ssi, (lat_new, lon_new), method='linear')
It works fine, there are NaN values at lat/lon boxes which are not in the original file.
Then I want to plot it using Basemap:
map = Basemap(projection='merc', llcrnrlon=-5., llcrnrlat=35., urcrnrlon=30., urcrnrlat=60.,
resolution='i')
map.drawcountries()
map.drawcoastlines()
x, y = map(XI, YI)
rad = map.contourf(x, y, new_grid)
cb = map.colorbar(rad, "bottom", size="10%", pad="10%")
I am receiving following error: IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed. I know that this means, but I have no clue how to change to code so that it worked the same way. Thank you for every help!

2D Density Plot with X Y Z data

I am trying to plot 2d terrain map with x,y and z (elevation). I followed the steps from the following link but I am getting very weird plot.
Python : 2d contour plot from 3 lists : x, y and rho?
I spent almost half day searching but got nowhere.
import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate
# import data:
import xlrd
loc = "~/Desktop/Book4.xlsx"
wb = xlrd.open_workbook(loc)
sheet = wb.sheet_by_index(0)
sample=500
# Generate array:
x=np.array(sheet.col_values(0))[0:sample]
y=np.array(sheet.col_values(1))[0:sample]
z=np.hamming(sample)[0:sample][:,None]
# Set up a regular grid of interpolation points
xi, yi = np.meshgrid(x, y)
# Interpolate
rbf = scipy.interpolate.Rbf(x, y, z, function='cubic')
zi = rbf(xi, yi)
# Plot
plt.imshow(zi, vmin=z.min(), vmax=z.max(), origin='lower',
extent=[x.min(), x.max(), y.min(), y.max()])
plt.colorbar()
plt.show()
The first of the following fig is what I am getting and the last one is how it should look like.
Any help shall be appreciated
Link to data file
I think the problem is that the data you're giving it is not smooth enough to interpolate with the default parameters. Here's one approach, using mgrid instead of meshgrid:
import numpy as np
import pandas as pd
from scipy.interpolate import Rbf
# fname is your data, but as a CSV file.
data = pd.read_csv(fname).values
x, y = data.T
x_min, x_max = np.amin(x), np.amax(x)
y_min, y_max = np.amin(y), np.amax(y)
# Make a grid with spacing 0.002.
grid_x, grid_y = np.mgrid[x_min:x_max:0.002, y_min:y_max:0.002]
# Make up a Z.
z = np.hamming(x.size)
# Make an n-dimensional interpolator.
rbfi = Rbf(x, y, z, smooth=2)
# Predict on the regular grid.
di = rbfi(grid_x, grid_y)
Then you can look at the result:
import matplotlib.pyplot as plt
plt.imshow(di)
I get:
I wrote a Jupyter Notebook on this topic recently, check it out for a few other interpolation methods, like kriging and spline fitting.

Problems with unpacking Matplotlib hist2d outputs

I'm using Matplotlib's function hist2d() and I want to unpack the output in order to further use it. Here's what I do: I simply load with numpy a 2-column file containing my data and use the following code
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np
traj = np.loadtxt('trajectory.txt')
x = traj[:,0]
y = traj[:,1]
M, xe, ye, img = plt.hist2d(x, y, bins = 80, norm = LogNorm())
plt.imshow(M)
plt.show()
The result I get is the following:
Instead, if I try to directly plot the hist2d results without unpacking them:
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np
traj = np.loadtxt('trajectory.txt')
x = traj[:,0]
y = traj[:,1]
plt.hist2d(x, y, bins = 80, norm = LogNorm())
plt.show()
I get the whole plot without the strange blue box. What am I doing wrong?
You can create a histogram plot directly with plt.hist2d. This calculates the histogram and plots it to the current axes. There is no need to show it yet another time using imshow.
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np; np.random.seed(9)
x = np.random.rayleigh(size=9900)
y = np.random.rayleigh(size=9900)
M, xe, ye, img = plt.hist2d(x, y, bins = 80, norm = LogNorm())
plt.show()
Or, you may first calculate the histogram and afterwards plot the result as an image to the current axes. Note that the histogram produced by numpy is transposed, see Matplotlib 2D histogram seems transposed, making it necessary to call imshow(M.T). Also note that in order to obtain the correct axes labeling, you need to set the imshow's extent to the extremal values of the xe and ye edge arrays.
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np; np.random.seed(9)
x = np.random.rayleigh(size=9900)
y = np.random.rayleigh(size=9900)
M, xe, ye = np.histogram2d(x, y, bins = 80)
extent = [xe[0], xe[-1], ye[0], ye[-1]]
plt.imshow(M.T, extent=extent, norm = LogNorm(), origin="lower")
plt.show()

Plotting 3D image form a data in NumPy-array

I have a data file in NumPy array, I would like to view the 3D-image. I am sharing an example, where I can view 2D image of size (100, 100), this is a slice in xy-plane at z = 0.
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
X, Y, Z = np.mgrid[-10:10:100j, -10:10:100j, -10:10:100j]
T = np.sin(X*Y*Z)/(X*Y*Z)
T=T[:,:,0]
im = plt.imshow(T, cmap='hot')
plt.colorbar(im, orientation='vertical')
plt.show()
How can I view a 3D image of the data T of shape (100, 100, 100)?
I think the main problem is, that you do have 4 informations for each point, so you are actually interessted in a 4-dimensional object. Plotting this is always difficult (maybe even impossible). I suggest one of the following solutions:
You change the question to: I'm not interessted in all combinations of x,y,z, but only the ones, where z = f(x,y)
You change the accuracy of you plot a bit, saying that you don't need 100 levels of z, but only maybe 5, then you simply make 5 of the plots you already have.
In case you want to use the first method, then there are several submethods:
A. Plot the 2-dim surface f(x,y)=z and color it with T
B. Use any technic that is used to plot complex functions, for more info see here.
The plot given by method 1.A (which I think is the best solution) with z=x^2+y^2 yields:
I used this programm:
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib as mpl
X, Y = np.mgrid[-10:10:100j, -10:10:100j]
Z = (X**2+Y**2)/10 #definition of f
T = np.sin(X*Y*Z)
norm = mpl.colors.Normalize(vmin=np.amin(T), vmax=np.amax(T))
T = mpl.cm.hot(T) #change T to colors
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, facecolors=T, linewidth=0,
cstride = 1, rstride = 1)
plt.show()
The second method gives something like:
With the code:
norm = mpl.colors.Normalize(vmin=-1, vmax=1)
X, Y= np.mgrid[-10:10:101j, -10:10:101j]
fig = plt.figure()
ax = fig.gca(projection='3d')
for i in np.linspace(-1,1,5):
Z = np.zeros(X.shape)+i
T = np.sin(X*Y*Z)
T = mpl.cm.hot(T)
ax.plot_surface(X, Y, Z, facecolors=T, linewidth=0, alpha = 0.5, cstride
= 10, rstride = 10)
plt.show()
Note: I changed the function to T = sin(X*Y*Z) because dividing by X*Y*Zmakes the functions behavior bad, as you divide two number very close to 0.
I have got a solution to my question. If we have the NumPy data, then we can convert them into TVTK ImageData and then visualization is possible with the help of mlab form Mayavi. The code and its 3D visualization are the following
from tvtk.api import tvtk
import numpy as np
from mayavi import mlab
X, Y, Z = np.mgrid[-10:10:100j, -10:10:100j, -10:10:100j]
data = np.sin(X*Y*Z)/(X*Y*Z)
i = tvtk.ImageData(spacing=(1, 1, 1), origin=(0, 0, 0))
i.point_data.scalars = data.ravel()
i.point_data.scalars.name = 'scalars'
i.dimensions = data.shape
mlab.pipeline.surface(i)
mlab.colorbar(orientation='vertical')
mlab.show()
For another randomly generated data
from numpy import random
data = random.random((20, 20, 20))
The visualization will be

pcolormesh shading='gouraud' not working

I am trying to smooth my color map using pcolormesh shading='gouraud' argument, but it failed, returned the follow error, which I do not understand.
"/usr/local/anaconda/lib/python2.7/site- packages/matplotlib/collections.py", line 1822, in draw
gc, triangles, colors, transform.frozen())
File "/usr/local/anaconda/lib/python2.7/site-packages/matplotlib/backends/backend_ps.py", line 876, in draw_gouraud_triangles
('colors', 'u1', (3,))])
TypeError: data type not understood File
I have my code as below:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams
from matplotlib.mlab import griddata
from matplotlib.ticker import AutoMinorLocator
from mpl_toolkits.axes_grid1 import make_axes_locatable
from mpl_toolkits.basemap import Basemap
x = np.loadtxt('data.txt',usecols=[0])
y = np.loadtxt('data.txt',usecols=[1])
s = np.loadtxt('data.txt',usecols=[2])
N = 36j
M = 18j
extent = (min(x), max(x), min(y), max(y))
xx,yy = np.mgrid[extent[0]:extent[1]:N, extent[2]:extent[3]:M]
ss = griddata(x, y, s, xx, yy, interp='linear')
fig, ax = plt.subplots()
#m = Basemap(projection='hammer',lon_0=0,resolution=None)
m = Basemap(projection='kav7',lon_0=0,resolution=None)
m.drawmapboundary(fill_color='0.75')
im = m.pcolormesh(xx,yy,ss,shading='gouraud',cmap=plt.cm.jet,latlon=True)
m.drawparallels(np.arange(-90.,99.,30.))
m.drawmeridians(np.arange(-180.,180.,60.))
cb = m.colorbar(im,"bottom", size="5%", pad="2%", ticks=[-2,-1,0,1,2,3,4,5])
plt.show()
When the shading argument is flat shading = 'flat', then this works very well, but the color is not smooth. Any one can offer me some idea how to approach this problem?

Categories

Resources