Strange behavior of matplotlib's griddata - python

I have a .txt file with values
x1 y1 z1
x2 y2 z2
etc.
With my previous little experience I was trying to draw a contourf, with this code
import numpy as np
import matplotlib
from matplotlib import rc
import matplotlib.mlab as ml
from pylab import *
rc('font', family='serif')
rc('font', serif='Times New Roman')
rc('font', size='9')
rc('text', usetex=True)
from matplotlib.mlab import griddata
import matplotlib.pyplot as plt
import numpy.ma as ma
from numpy.random import uniform
from matplotlib.colors import LogNorm
matplotlib.use('pgf')
fig = plt.figure()
data = np.genfromtxt('Velocidad.txt')
matplotlib.rcParams['xtick.direction'] = 'out'
matplotlib.rcParams['ytick.direction'] = 'out'
rc('text', usetex=True)
rc('font', family='serif')
x = data[:,0]
y = data[:,1]
z = data[:,2]
xi = np.linspace(0,3000.0, 400)
yi = np.linspace(0,4.0, 200)
zi = griddata(x,y,z,xi,yi,interp='nn')
CS = plt.contourf(xi,yi,zi,200,cmap=plt.cm.jet,rasterized=True)
plt.colorbar()
plt.xlim(0,3000)
plt.ylim(0,4.0)
plt.ylabel(r'$t$')
plt.xlabel(r'$x$')
plt.title(r' Contour de $v(x,t)$')
plt.savefig("CampoVel.png", dpi=100)
plt.show()
the problem is the output:
When I see this picture and I look at the data (which is here, in this link) and I don't understand those discontinuities in x=750 and x=1875. And those strange vertical lines all over the plot. Looking at the data I would expect something smooth, at least in those positions, but the output obviously isn't. Is this a problem of griddata()? How can I solve it?
I have been told that as my data is regularly spaced on X and Y, I shouldn't use griddata(), but I have looked examples and I can't get the code to work.

If you simply reshape your data after loading it and skip the griddata thing, doing this:
data = data.reshape(81, 201, 3)
x = data[...,0]
y = data[...,1]
z = data[...,2]
CS = plt.contourf(x,y,z,200,cmap=plt.cm.jet,rasterized=True)
plt.colorbar()
plt.show()
You get this:

Related

strange plot surface of matplotlib

I'm trying to generate a 3D height figure, I have a regular grid, the height data collected by the sensor and data store in a file which name is "data.txt". data stored one data per line. the file link on github
import numpy as np
import matplotlib.pyplot as pit
from mpl_toolkits.mplot3d import Axes3D
from scipy.stats import multivariate_normal
from matplotlib import cm
x = np.linspace(0,350,18)
y = np.linspace(0,350,15)
z = np.loadtxt('data.txt')
xx,yy = np.meshgrid(x,y)
fig = pit.figure()
ax = fig.add_subplot(111,projection='3d')
ax.scatter(xx,yy,z)
use the code above, I got a scatter. It looks good! I found this , I want convert the figure to surface, than I add the code below, but it looks very strange
xa = np.reshape(xx, (18,15))
ya = np.reshape(yy, (18,15))
za = np.reshape(z, (18,15))
surf=ax.plot_surface(xa,ya,za,cmap="summer",linewidth=0,antialiased=False, alpha=0.5)
fig.colorbar(surf)
pit.show()
the image
i don't know what happened, it look too strange! Should i smooth it?
You need to use xx and yy defined earlier and reshape z to the same shape as xx:
za = z.reshape(xx.shape)
fig = pit.figure()
ax = fig.add_subplot(111,projection='3d')
surf=ax.plot_surface(xx,yy,za,cmap="summer",linewidth=0,antialiased=False, alpha=0.5)
fig.colorbar(surf)
pit.show()
Note that I have rotate the chart for better clarity.
I think you need scipy.griddata. Try this code:
from scipy.interpolate import griddata
za = griddata(x, y, z, (xx, yy), method='linear')
surf=ax.plot_surface(xx,yy,za,cmap="summer",linewidth=0,antialiased=False, alpha=0.5)
fig.colorbar(surf)
plt.show()

Basemap cannot set aspect on 3D axis

I am using Basemap with a 3D graph to display ray paths. I would like to implement one of basemap's topo, shaded relief or bluemarble layers but I am running into the same issue over and over again:
NotImplementedError: It is not currently possible to manually set the aspect on 3D axes
I have already implemented fixed_aspect=False into calling the basemap
and have also tried ax.set_aspect('equal') which gives me the same error
I am using matplotlib ==2.2.3
Here is my code:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.basemap import Basemap
import numpy as np
from io import StringIO
import re
f = open("best-working4D.ray_paths", 'r') #125 waves - 125 "lines"
data = f.read()
lines = data.split('\n ')
fig = plt.figure()
ax = plt.axes(projection='3d')
extent = [300, 360, 50, 75]
bm = Basemap(llcrnrlon=extent[0], llcrnrlat=extent[2],
urcrnrlon=extent[1], urcrnrlat=extent[3], resolution='l', fix_aspect= False)
bm.bluemarble()
for i in range(1, 119):
wave = lines[i]
j = wave.split('\n')
k = []
for i in j:
k.append(i.split())
x=[]
y=[]
z=[]
n= 0
for m in k[1:]:
x.append(m[0])
y.append(m[1])
z.append(m[2])
x= np.array(x).astype('float32')
y= np.array(y).astype('float32')
z= np.array(z).astype('float32')
ax.plot3D(x,y,z, color='red')
##Plotting Tropopause
T_hi = 20
xx, yy = np.meshgrid(range(300,360), range(50,75))
zz = yy*0 + T_hi
ax.plot_surface(xx, yy, zz, alpha=0.15)
ax.set_xlabel("Latitude [deg]")
ax.set_ylabel("Longitude [deg]")
ax.set_zlabel("Altitude [km]")
ax.add_collection3d(bm.drawcoastlines(linewidth=0.25))
plt.show()
The basemap IS working for the bm.drawcoastlines just nothing else.
IMAGELINK
I would greatly appreciate any ideas!

Animation Interpolation Python Matplotlib

I would like to make an animation of an interpolation.
This is my code for the moment :
import scipy.interpolate as itp
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
import matplotlib.animation as animation
def update(i,Z):
x = np.arange(0,Z.shape[0])
y = np.arange(0,Z.shape[0])
I = itp.interp2d(x, y, Z, kind='cubic')
xi = np.linspace(0, Z.shape[0]-1, Z.shape[0]+1)
yi = np.linspace(0, Z.shape[0]-1, Z.shape[0]+1)
Z = I(xi, yi)
return Z
Z = np.random.randint(10, size=(4, 4))
fig, ax = plt.subplots()
matrice = ax.matshow(Z)
plt.colorbar(matrice)
ani = animation.FuncAnimation(fig, update, frames=19, interval=500,fargs=(Z,))
fig.show()
So as you can see, I want to show the progress of the interpolation, but it doesn't work. Z matrix never changes.
Can you help me please.
Thank you in advance.
Thank you for you help. I managed to to solve my problem :
import scipy.interpolate as itp
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
import matplotlib.animation as animation
def update(i,Z,size_initial):
x = np.arange(0,size_initial)
y = np.arange(0,size_initial)
I = itp.interp2d(x, y, Z, kind='cubic')
xi = np.linspace(0, size_initial-1, i+size_initial)
yi = np.linspace(0, size_initial-1, i+size_initial)
Z = I(xi, yi)
matrice.set_data(Z)
return matrice,
size_initial = 4
Z = np.random.randint(100, size=(size_initial, size_initial))
fig, ax = plt.subplots()
matrice = ax.matshow(Z)
plt.colorbar(matrice)
ani = animation.FuncAnimation(fig, update, frames=50, interval=500,fargs=[Z,size_initial])
fig.show()

Plotly plot_trisurf isn't working with arange arrays

I've basically just copied the example code found on the Matplotlib website, but I replaced their radii and angles with simple arange arrays.
I've tried different array functions and I can't seem to figure out anything.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from Equation import Expression
x = np.arange(0,100,0.01)
y = np.arange(0,100,0.01)
x2 = np.append(0,x.flatten())
y2 = np.append(0,y.flatten())
z = x2 + y2
print(z)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_trisurf(x, y, z, linewidth=0.2, antialiased=True)
plt.show()
I'm just trying to make a graph of z = x + y but I'm getting a confusing error.
"RuntimeError: Error in qhull Delaunay triangulation calculation: singular input data (exitcode=2); use python verbose option (-v) to see original qhull error."
Edit: I've also tried it without calling flatten() but I get the same result though.
The error you are getting is because your z is not a surface but a line. You need to use at least 3 points that would define a plane. One option could be to use np.meshgrid to create your surface for plotting and then flatten everything to insert into the function. Try going back to some example code here. Note you may also want to change your resolution depending on the detail of your surface.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,100,1)
y = np.arange(0,100,1)
x2 = np.append(0,x.flatten())
y2 = np.append(0,y.flatten())
x2,y2 = np.meshgrid(x2,y2) #This is what you were missing
z = x2 + y2
fig = plt.figure(figsize=(12,12))
ax = fig.gca(projection='3d')
ax.plot_trisurf(x2.flatten(), y2.flatten(), z.flatten(), linewidth=0.2, antialiased=True) #flatten all the arrays here
plt.show()

Modify line / plot in IPython notebook "interact"

Is there a way to modify the plot inside IPython "interact" function rather than replotting it?
In case when the plot contains a lot of heavy graphics (or some parts require heavy calculations) it would be much faster than doing the plot from the scratch.
I'm trying the following code, but it does not work: after changing the slider the whole plot becomes blank.
%matplotlib inline
import matplotlib.pyplot as plt
from IPython.html.widgets import interact
import numpy as np
x = np.arange(0,11.)
y1 = x / 10.
y2 = np.random.rand(len(x))
plt.plot(x,y1)
plt.plot(x,y2)
plt.ylim([0,1])
ax = plt.gca()
def replot_it(a):
ax.lines.pop(1)
y = (x/10.)**a
ax.plot(x,y)
interact(replot_it, a=(0.,5.))
I would appreciate any suggestions.
If you have IPython > 3.0 and mpl > 1.4: run this is one cell:
%matplotlib notebook
import matplotlib.pyplot as plt
from IPython.html.widgets import interact
import numpy as np
x = np.arange(0,11.)
y1 = x / 10.
y2 = np.random.rand(len(x))
fig, ax = plt.subplots()
ln1, = ax.plot(x,y1)
ln2, = ax.plot(x,y2)
ax.set_ylim([0,1])
def replot_it(a):
y = (x/10.)**a
ln2.set_ydata(y)
ax.figure.canvas.draw()
and
interact(replot_it, a=(0.,5.))
in the cell below it.

Categories