I am running into an error when using scipy.interpolate.griddata. My goal is to prepare data for contouring using matplotlib. I have read that the best way to perform this is to separate the x any y as 1D arrays using linspace before passing to griddata.
The min and max values of my x and y values are used to input into the linspace, so as to keep the co-ordinates the same for GIS mapping purposes (not sure if this is necessary to have the data points in the same xy area as the grid co-ordinates, but am doing so any way)
The file Watertable CSV is imported as a numpy array with x,y and z values. The z is supplied to griddata as a straight array column index.
I am running into the error "valueError: invalid shape for input data points"
I am sure it is something very simple and hopefully someone can shed light on my error.
[EDIT]
I have linked the csv file using pastebin as suggested:
http://pastebin.com/nj7THgMw
import numpy as np
from scipy.interpolate import griddata
from numpy import genfromtxt
my_data = genfromtxt('WaterTable.csv', delimiter=',')
x = my_data[1:,0:1]
y = my_data[1:,1:2]
z = my_data[1:,2:3]
xmax = max(x)
xmin = min(x)
ymax = max(y)
ymin = min(y)
xi = np.linspace(xmin, xmax, 2000)
yi = np.linspace(ymin, ymax, 2000)
zi = griddata((x, y), z, (xi, yi), method='cubic')
I script then exits with the following error:
Traceback (most recent call last):
File "C:/Users/Hp/PycharmProjects/GISdev/Irregular_Grid03.py", line 60, in <module>
zi = griddata((x, y), z, (xi, yi), method='cubic')
File "C:\Python27\lib\site-packages\scipy\interpolate\ndgriddata.py", line 212, in griddata
rescale=rescale)
File "scipy/interpolate/interpnd.pyx", line 840, in scipy.interpolate.interpnd.CloughTocher2DInterpolator.__init__ (scipy\interpolate\interpnd.c:9961)
File "scipy/interpolate/interpnd.pyx", line 78, in scipy.interpolate.interpnd.NDInterpolatorBase.__init__ (scipy\interpolate\interpnd.c:2356)
File "scipy/interpolate/interpnd.pyx", line 123, in scipy.interpolate.interpnd.NDInterpolatorBase._check_init_shape (scipy\interpolate\interpnd.c:3128)
ValueError: invalid shape for input data points
Your arrays x, y and z are two-dimensional, with shape (n, 1). griddata expects one-dimensional arrays (i.e. with shape (n,)).
To fix this, use a single index instead of a slice in the second index position when you pull the arrays out of my_data:
x = my_data[1:, 0]
y = my_data[1:, 1]
z = my_data[1:, 2]
Related
I have a dataframe df1 containing points which describe a 3D curve (x, y, z coordinates and the arc length).
In a second data frame df2 I have the arc length (with different steps than in df1) and a value g. I need to find the g associated coordinates x, y and z.
My idea was to use splprep and splev to create a b_spline representation and interpolate via a Parametrization. Unfortunately this does not quite work, can someone help me?
Edit: This is my Code so far. I don't get any Errors, but the calculated x,y,z coordinates are wrong.
# df1 with x, y, z values and arc length
x = df1['x'].values
y = df1['y'].values
z = df1['z'].values
s = df1['arc_length'].values
# df2 with arc length intervals and gamma values
s_int = df2['arc_length'].values
gamma = df2['g'].values
# Use splprep to create a smooth curve
spl = splprep([x, y, z], s=0, k=3)
# Get the x, y, and z coordinates for a given arc length value
target_arc_lengths = s_int
points = splev(target_arc_lengths, spl[0])
x_coordinates = points[0]
y_coordinates = points[1]
z_coordinates = points[2]
Edit2: When creating the minimal example I noticed that my data is incorrect, the script works fine
I have a numerical set X, Y, Z and I would like to reproduce a heatmap with these values. The size of the bin is 20 x 20 and the range of the X and Y axes are from -150 to 150 with Z being the color. Within that bin it should contain the average of the Z values in that range.
In Origin contains this tool to make a heatmap with the average of the values, but I would like to do it in MATLAB. The graph I made in Origin and that I would like to do in MATLAB can be seen in figure 1.
I've tried something like
load xyz.dat
x = xyz(:,1);
y = xyz(:,2);
z = xyz(:,3);
tbl = table(x,y,z);
h = heatmap(tbl,'x','y','ColorVariable','z','ColorMethod','mean');
But it printed this warning
Warning: Error updating HeatmapChart. Values in the source table variable 'x' are not grouped into discrete categories. Use the discretize function to group your values.
heatmap expects discrete x and y values. You goal is to bin your x and y's into 20 discrete bins and average the z values for each bin, but x and y themselves are continuous.
To achieve your goal take the advice of the warning message and use discretize to bin your x and y values.
% I used the following stand ins for your data:
% x = rand(540, 1);
% y = rand(540, 1);
n_bins = 20; % Number of grid cells
% If you want the width of the grid cell to be 20, use
% n_bins = (max(x) - min(x)) / 20;
x_discrete = discretize(x, n_bins);
y_discrete = discretize(y, n_bins);
tbl = table(X_discrete,y_discrete,z, 'VariableNames', {'x', 'y', 'z'});
h = heatmap(tbl,'x','y','ColorVariable','z','ColorMethod','mean');
Note: Why was this not a problem with the sample data?
Using your sample data,
x = [49.8, 14.5, -60.7, -21.6, -10.6];
y = [45.3, 7.9, 23.9, -58.5, -55.4];
z = [0.2 , -0.06, -0.35, -0.15, -0.08];
tbl = table(x',y',z', 'VariableNames', {'x', 'y', 'z'});
h = heatmap(tbl,'x','y','ColorVariable','z','ColorMethod','mean');
Does not throw an error because it treats each x and y value as a separate category. heatmap uses a call to categorical to transform the continuous values into categorical values.
Aside from not really providing the output you want (each point would be its own box instead of averaging grid cells), categorical seems to have a limit in how many categorical values it will create. I wasn't able to find any documentation about exactly what that limit is, but by experimentation, it tops out in the mid 200's. Since your vectors are 540 elements long, you get the warning about using discretize instead.
I want to interpolate an irregular 3-D grids using matlab command "interp3", what I
have is the coordinates of X,Y,Z and the values at each point. The dimension of x,y,z is 76*36*16 and the sampling positions stored in vectors x, y, and z are increasing.
x
y
z
the values at each point
the commands I use to interpolate the grids are as belows:
[x_out,y_out,z_out]=meshgrid(-310:5:310,-165:5:205,-70:5:5);
vel_grid=interp3(x_3d,y_3d,z_3d,vel,x_out,y_out,z_out);
and the error message:
your input grid is invalid Meshgrid.
I can't figure where is wrong about my input grids, the sampling positions stored in vectors x, y, and z are increasing. What conditions should my input grids still satisfy?
Since your 3-D grids are irregular you cannot use interp3 which supposes that your initial data is in a proper meshgrid order.
for example
x = rand(76,36,16);
y = rand(76,36,16);
z = rand(76,36,16);
v = rand(76,36,16);
slice(x,y,z,v,0,0,0);
will result in
Error using interp3 (line 147)
Input grid is not a valid MESHGRID.
Error in slice (line 104)
vi = interp3(x,y,z,v,xi,yi,zi,method);
However you can use scatteredInterpolant as such
F =scatteredInterpolant(x_3d(:),y_3d(:),z_3d(:),vel(:));
[x_out,y_out,z_out]=meshgrid(-310:5:310,-165:5:205,-70:5:5);
v_out = F(x_out,y_out,z_out);
xslice = [0];
yslice = [0];
zslice = [,0];
slice(x_out,y_out,z_out,vel(:),xslice,yslice,zslice)
I have a shapefile (example here) which I would like to convert to a binary region of interest (ROI) mask using MATLAB's poly2mask().
MATLAB's description is as follows:
BW = poly2mask(x, y, m, n)
BW = poly2mask(x, y, m, n) computes a binary region of interest (ROI)
mask, BW, from an ROI polygon, represented by the vectors x and y. The
size of BW is m-by-n. poly2mask sets pixels in BW that are inside the
polygon (X,Y) to 1 and sets pixels outside the polygon to 0.
poly2mask closes the polygon automatically if it isn't already closed.
This is the script I am using to convert my shapefile:
s = 'D:\path\to\studyArea.shp'
shp = shaperead(s)
x = [shp.X];
y = [shp.Y];
% use bounding box to define m and n
m = shp.BoundingBox(2) - shp.BoundingBox(1)
n = shp.BoundingBox(3) - shp.BoundingBox(1)
mask = poly2mask(x,y, m, n)
Results in the following error:
Error using poly2mask Expected input number 1, X, to be finite.
Error in poly2mask (line 49)
validateattributes(x,{'double'},{'real','vector','finite'},mfilename,'X',1);
Error in createMask (line 11) mask = poly2mask(x,y, m, n)
I suspect there may be an issue with UTM coordinates rather than Lat/Long, however, I could use some input from someone who has experience in this. Where am I going wrong here?
your x and y values have NaN's as the last coordinate.
poly2mask won't work if there are NaN's in the coordinates. (hence the error 'values must be finite').
If this is the case you can use a quick fix..
x = length(x)-1;
y = length(y)-1;
more info
http://www.mathworks.com/help/map/understanding-vector-geodata.html
-James
See the changes here -
s = 'studyArea.shp' %// Copy this file to working directory
shp = shaperead(s)
x = [shp.X];
y = [shp.Y];
%// Threw error before because there were NaNs there in x or y or both. So one assumption could be that you want to remove all x and y where any x or y is a NaN.
cond1 = isnan(x) | isnan(y);
x(cond1)=[];
y(cond1)=[];
% use bounding box to define m and n
m = shp.BoundingBox(2) - shp.BoundingBox(1)
n = shp.BoundingBox(3) - shp.BoundingBox(1)
%mask = poly2mask(x,y, m, n); %// Threw error
mask = poly2mask(x,y, round(m/20), round(n/20)); %//Worked fine for smaller 3rd and 4th arguments
I am trying to create a 2-D grid from a vector.
So, for example I have:
x = 1:1:10;
z = 2:2:20;
Now, I want to create a grid which has x on both side of the grid cell and z as grid cell value.
I tried doing it as :
[X,Y] = meshgrid(x, x);
newZ = griddata(x, x ,z, X, Y);
But this gives me error:
The underlying triangulation is empty - the points may be
collinear.
Need help solving this.
In a high level, griddata() takes a 2d surface with variable z-value at each point as the first part of the input, and the query points as the second part of the input. To be more specific, when we look into the definition of the function:
vq = griddata(x,y,v,xq,yq)
x and y specifies the range of x and y values, v is like z-value in a plane, and xq and yq together are query points. Here, v (in your case, z) is expected to be a 2d matrix, to be more specific, the size of v is [length(x), length(y)], whereas in your case, you put z as a vector. Matlab generates the warning since the size doesn't match.
For your reference: http://www.mathworks.com/help/matlab/ref/griddata.html?refresh=true