I am trying to write a function which makes a contour plot from a text data file (or a numpy array) formatted as "x, y, z". However, when I try to use griddata to interpolate the data, I get a "type" error:
if not len(x)==len(y)==len(z):
TypeError: object of type 'numpy.float64' has no len()
This is my function:
def ContourPlot(datafile,columns=[0,1,2], nXvals=100, nYvals=100, title='', xlab='', ylab='', colormap='rainbow', contours=10):
if type(datafile)==type(str()):
try:
x, y, z = np.loadtxt(datafile, dtype='float', unpack=True, usecols=columns)
except:
print "Can't open the input file!"
exit
elif type(datafile)==np.ndarray:
x = datafile[0]
y = datafile[1]
z = datafile[2]
else:
print "ERROR: You tried to pass data to the ContourPlot() function in a format it cannot read"
exit
print type(x)
xi = np.linspace(np.amin(x), np.amax(x), nXvals)
yi = np.linspace(np.amin(y), np.amax(y), nYvals)
zi = griddata(x, y, z, xi, yi)
norm = colors.Normalize(vmin = np.min(z), vmax = np.max(z), clip = False)
pl.figure()
pl.contourf(xi, yi, zi, 30, cmap = pl.get_cmap(colormap), norm =norm)
CS = pl.contour(xi, yi, zi, colors = 'k',lw = 3, levels= contours)
pl.clabel(CS, inline=1, fontsize=10)
pl.tick_params(axis='x', labelsize=20)
pl.tick_params(axis='y', labelsize=20)
pl.title(title, fontsize=17)
pl.xlabel(xlab, fontsize=20)
pl.ylabel(ylab, fontsize=20)
pl.show()
I tried converting x, y, z to regular Python lists with the tolist() method, but it didn't work.
Any help would be greatly appreciated!
I suppose you are using an older version of matplotlib? Where are you importing your griddata from? Have a look at the griddate function in your matplotlib/mlab.py file and look whether there is a line similar to
if not len(x)==len(y)==len(z):
raise TypeError("inputs x,y,z must all be 1D arrays of the same length")
The current version at https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/mlab.py does not have this line any more but now checksthis way:
# Check input arguments.
x = np.asanyarray(x, dtype=np.float64)
y = np.asanyarray(y, dtype=np.float64)
z = np.asanyarray(z, dtype=np.float64)
if x.shape != y.shape or x.shape != z.shape or x.ndim != 1:
raise ValueError("x, y and z must be equal-length 1-D arrays")
So an update to a more recent version might already solve your problem. In any case currently at least one of your x, y, z inputs is of type numpy.float64 and for some reason has no len().
Related
I do have a script, which creates a dict with XYZ-values. Following dict includes values at x from -2 to 2, with y from 0 to 2.
my_dict = {
-2:{0:1,1:1,2:0},
-1:{0:3,1:1,2:0},
0:{0:6,1:1,2:9},
1:{0:-2,1:1,2:2},
2:{0:1,1:1,2:6}}
Now, I don't now how to create a 3D plot out of this. I am aware of the matplotlib library,but I am not sure how to generate my Z-Data. I tried to write a function, to get my Z-data in a mesh, but it doesn't work. This is what I got so far:
x = np.arange(-2, 2, 1)
y = np.arange(0, 2, 1)
X, Y = np.meshgrid(x, y)
Z = f(X,Y) #HERE, the function f is what I am searching for.
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.contour3D(X, Y, Z, 50, cmap='binary')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
Is there any numpy or pythonic way to do this?
Is this what you're looking for?
my_dict = {
-2:{0:1,1:1,2:0},
-1:{0:3,1:1,2:0},
0:{0:6,1:1,2:9},
1:{0:-2,1:1,2:2},
2:{0:1,1:1,2:6}}
x = np.arange(-2, 3, 1)
y = np.arange(0, 3, 1)
X, Y = np.meshgrid(x, y)
def f(x, y):
z = np.zeros(X.reshape(-1).shape) # Create an "empty" tensor that matches the "flattened" meshgrid
c = 0 # To index over our "z"
for i in y:
for j in x:
z[c] = my_dict[j][i] # Fill the empty tensor with its corresponding values from the dictionary (depending on x and y)
c += 1
z = z.reshape(X.shape) # Reshape it back to match meshgrid's shape
return z
Z = f(x, y)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.contour3D(X, Y, Z, 50, cmap='binary')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
plt.show()
I believe you can get away with accessing the correct value in your dict via:
Z = mydict[x][y]
I am a new Python user and need help with plotting a heatmap in Python using matplotlib
I have three vectors [x, y, z], each having 7700 elements. I got the code for plotting the heatmap from google search (see below), but ended up with an error
Some pointers
In array "x", all the items are different
In array "y", not all the values are different
In array "z", not all the values are different
x = mdf_merged.get('Signal_x').samples # define the x array
y = mdf_merged.get('Signal_y').samples # define the y array
z = mdf_merged.get('Signal_z').samples # define the z array
x=np.unique(x)
x = np.unique(x)
y1, yind = np.unique(y, return_index=True)
X,Y = np.meshgrid(x,y[sorted(yind)])
Z=z.reshape(len(y1),len(x), order='F')
plt.pcolormesh(X,Y,Z)
plt.colorbar()
plt.xlabel("X-values")
plt.ylabel("Y-values")
I end up with this error
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: cannot reshape array of size 7700 into shape (6447,7700)
So my questions are
a) What could be the cause and possible solution to this ?
b) Why can't it directly take x, y, and z. Why do I have to do meshgrip and reshape ?
I am a newbie to Python so it could be nice with a little more detailed reply
So, with the help from the community, I have been able to reach closer to the solution. The thing that I did was
import numpy as np
from scipy.interpolate import griddata
import matplotlib.pyplot as plt
x = mdf_merged.get('VariableX').samples
y = mdf_merged.get('VariableY').samples
z = mdf_merged.get('VariableZ').samples
###
xi = np.linspace(min(x),max(x),10)
yi = np.linspace(min(y),max(y),20)
zi = griddata((x, y), z, (xi[None,:], yi[:,None]), method='linear')
plt.pcolormesh(xi, yi, zi)
I have zero background in programming. I am trying to code something for my class and it is giving me an error "not enough values to unpack (expected 2, got 1)". What might be wrong with my codes?
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import shapefile as shp
#Read x, y, z file
data = pd.read_excel('RegionV.xlsx', header = None)
# Get X, Y, Z values from file
data = np.array(data)
data = data.astype(np.float)
x = data[:,0]
y = data[:,1]
z = data[:,2]
#Mask negative values of z (bathemetry)
zz = np.ma.masked_where(z <= 0, z)
#Create a map using basemap
fig = plt.figure(figsize=(10,10))
map = Basemap(projection='mill',llcrnrlat=11,urcrnrlat=15,\
llcrnrlon=122,urcrnrlon=125,resolution='h')
lon = np.linspace(min(x), max(x))
lat = np.linspace(min(y), max(y))
xs, ys = np.meshgrid(lon, lat)
x, y = map(xs, ys)
map.drawparallels(np.arange(12.,14.,0.5), labels=[0,0,0,1])
map.drawmeridians(np.arange(123.,126.,0.5), labels=[1,0,0,0])
#Plot
cmap = plt.cm.jet
cmap.set_bad(color='white')
m.pcolormesh(x, y, zz, cmap=cmap, vmax=1300, vmin=0)
m.colorbar(location='right', label='meters')
map.drawmapboundary()
map.drawcoastlines()
the first part of the error message says:
ValueError Traceback (most recent call last)
<ipython-input-50-3d7531011dc2> in <module>
44 cmap = plt.cm.jet
45 cmap.set_bad(color='white')
---> 46 m.pcolormesh(xs, ys, zz, cmap=cmap, vmax=1300, vmin=0)
47 m.colorbar(location='right', label='meters')
then, at the end,
ValueError: not enough values to unpack (expected 2, got 1)
Stackoverflow is not allowing me to post the entire error message. Hope everyone who see my post understands what I mean.
I think that the problem is with line x, y = map(xs, ys). Look at this page for the documentation of the Basemap() function and the example usage (search for ".basemap" keyword). It says that the example usage is:
# create Basemap instance for Robinson projection.
m = Basemap(projection='robin',lon_0=0.5*(lons[0]+lons[-1]))
# compute map projection coordinates for lat/lon grid.
x, y = m(*np.meshgrid(lons,lats))
You try to get x,y from Basemap() instance, which is only one object. That's why it says that it expected 2 values (x, y), but got only one (Basemap()).
I'm trying to plot a matrix in python using pcolor. This is my code but it's not working. can you show me how to plot the matrix?!
Matrix = np.zeros((NumX, NumY))
for i in range(NumX):
for j in range(NumY):
Matrix[i][j] = Data[i*NumY+j+1]
# Set up a regular grid of interpolation points
xi = np.arange(0, NumX*1.5, 1.5)
yi = np.arange(0, NumY*1.5, 1.5)
X, Y = np.meshgrid(xi, yi)
intensity = np.array(Matrix)
plt.pcolormesh(X, Y, Matrix)
plt.colorbar()
plt.show()
this is the error :
TypeError: Dimensions of C (22, 30) are incompatible with X (22)
and/or Y (30); see help(pcolormesh)
You need to mind the indexing rules for arrays. X is the second dimension, Y is the first dimension.
import numpy as np; np.random.seed(1)
import matplotlib.pyplot as plt
NumX, NumY = 5,7
Data = np.random.randint(1,9,size=NumX*NumY+1)
Matrix = np.zeros((NumY, NumX))
for i in range(NumY):
for j in range(NumX):
Matrix[i,j] = Data[i*NumX+j+1]
print(Matrix)
xi = np.arange(0, NumX)
yi = np.arange(0, NumY)
X, Y = np.meshgrid(xi, yi)
plt.pcolormesh(X, Y, Matrix)
for i in range(NumY-1):
for j in range(NumX-1):
plt.text(j,i, Matrix[i,j], color="w")
plt.colorbar()
plt.show()
Trying to do a 3d plot with matplotlib, but for some reason my code fails when i try to set xi,yi and keep getting the following message:
xi = np.linspace(min(x_mtx), max(x_mtx))
File "C:\Python27\lib\site-packages\numpy\core\function_base.py", line 80, in linspace
step = (stop-start)/float((num-1))
TypeError: unsupported operand type(s) for -: 'list' and 'list'
Code:
def plot_3D(self,x_mtx,y_mtx,z_mtx,title,xlabel,ylabel):
fig = plt.figure()
ax = fig.gca(projection='3d')
x = x_mtx
y = y_mtx
z = z_mtx
xi = np.linspace(min(x_mtx), max(x_mtx))
yi = np.linspace(min(y_mtx), max(y_mtx))
X, Y = np.meshgrid(xi, yi)
Z = griddata(x, y, z, xi, yi)
Z = np.nan_to_num(Z)
surf = ax.plot_surface(X, Y, Z, rstride=3, cstride=1, cmap=cm.jet,
linewidth=0, antialiased=True)
ax.set_zlim3d(np.min(Z), np.max(Z))
fig.colorbar(surf)
plt.xlabel(xlabel)
plt.ylabel(ylabel)
plt.title(title)
plt.show()
I am using the following data set:
x =[[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9],...,[[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]]
y =[[1,2,3,4],...,[1,2,3,4]
z =[[1604.18997105,1537.61273892,1475.55679943,1372.35580231,1338.5212552,1205.65768444,1123.58398781,1011.84290322,859.696324611],[1032.18731228,996.573332541,948.61368911,912.983432776,881.29239958,798.381328007,750.773525511,679.725673182,586.014048166],[727.489743398,674.426010669,660.796225936,636.607836391,603.244223602,559.648437086,513.633091109,473.594466259,417.134921259],[511.067337872,482.096743673,471.899423715,448.898733469,436.745110773,392.610890968,362.940790577,330.484896223,290.875981749]]
This is because (presumably) x_mtx is a matrix, and so the in-built max returns a list containing the largest element in each row of x_mtx.
If you want to get the min/max values in x_mtx globally, use numpy's min/max instead, which returns the scalar minimum over the entire matrix, not just each row:
xi = np.linspace(np.min(x_mtx), np.max(x_mtx))