contour plot - 2D shape of X and Y values [duplicate] - python

This question already has answers here:
Why does pyplot.contour() require Z to be a 2D array?
(5 answers)
Closed 5 years ago.
I plot a contour plot which indicates the seperating hyperplane of a SVC estimator in a 2D axes using the following code.
X,y= make_circles(n_samples=50,factor=.1,noise=.1)
x_fit=np.linspace(-1.5,1.5,10)
y_fit=np.linspace(-1.5,1.5,10)
Y,XX=np.meshgrid(x_fit,y_fit)
xy=np.vstack([XX.ravel(),Y.ravel()]).T
P=clf.decision_function(xy).reshape(XX.shape)
plt.contour(XX,Y,P,colors="k",levels=[-1,0,1],alpha=0.5,linestyles=["--","-","--"])
Question
Based on this question and the answer of Ilya V. Schurov there is still one issue for me. I understand, that X and Y provides the x and y values and Z provides the "depth" for each xy coordiante and thus has to be 2 dimensional. Further, the X and Y values of the plt.contour() function can be either 1D or 2D (if 1D the meshgrid gets computed internally).
BUT what is the benefit/ reason for X and Y to be 2D?
Because actually the "second dimension" of X and Y can not be plotted on a 2D axes. So has it some "algorithmic performance" reasons for X and Y to be 2D or what is the reason?

Contour plot is not designed for just plotting hyperplanes for classfier. It represents a 3-D surface with a 2-D format; or it plots elevations of a 2-D area. Therefore, plt.contour() has to somehow understand/know elevations covering the whole area. One way, or the current way, is to provide a set of elevations for a set of points covering the 2-D area. And the more you provide, the better/finer the final contour plot is. When providing a 1-D x and y, it represents a line rather than an area, which cannot be used to interpolated a 2-D area.
Another way to plot hyperplanes is to calculate the exact planes yourself. Then you can plot hyperplanes with a 1-D linespace. But I don't think this will be easier than using plt.contour() since plt.contour() did the hard calculation by simulating with interpolation for you.
Edit: How Z works with X and Y in plt.contour()?
It takes some assumption for Z works with X and Y.
If X and Y is 2-D, a value in Z is the depth for a point specified by corresponding (same location by index) values in X and Y.
If X and Y is 1-D, it will be convert to a meshgrid first, as you can see in the source code. Then the rest will work the same way as explained above.
So for your case specifically, using x_fit and y_fit can give you the same result because plt.contour() makes the meshgrid for you. As long as you understand the mechanism, either way is fine. The only thing I would say is if you end up making the meshgrid for calculating P anyway, why not using the meshgrid to avoid assumption/ambiguity?

Related

Visualising 2D and 1D matrices on a one plot

I have two matrices: m x m and m x 1.
The 2D matrix's data is dependent on the 1D matrix, so I want to show this case in a one plot.
Earlier, to visualize the 2D matrix I used a heatmap and also now I think about using it.
Both matrices have the same label ticks, so I got an idea to double the 1D matrix and place them next to the 2D matrix's labels to let them share the same label ticks:
Is it possible to achieve such a plot^ in Python, especially in seaborn or matplotlib?
Or maybe there is another, better way to visualize such a data?
For now, I see here one issue - a lack of a legend for 1D matrices, but I have no idea where and how it should be placed.

How to convert back points in 2d to 3d with known orthogonal (camera) projection matrix?

I have a numpy array with 2d points that I convert from 3d to 2d via the following equation:
https://wikimedia.org/api/rest_v1/media/math/render/svg/198f15da062c7ce00598d7a2f9bd8169d7042ed3
How can I convert the point back to 3D?
I used the top down view matrix that is in the image above. Found in Wikiperia: https://en.wikipedia.org/wiki/Orthographic_projection
#To 2D from 3d:
points2D = np.array([np.matmul(camera_pos, point) for point in points3D])[:,:2]
You cannot convert it back using just the projected points. Note that your projection basically is just looking at the (x,y) values and discarding the z value so there is no way to know what z was after doing this.
For instance, consider the points u = [1,2,3] and v=[1,2,-3]. These both project to [1,2,0], so there is no way to know if we should make [1,2,0] into u or v when we try to invert (undo) the projection.
In terms of the matrix operation, this is because the projection matrices are not invertible (except the identity matrix).
You will need more information than just the projected points to be able to recover the original points.

Redefining indexing in N-dimensional arrays

So I have a N-dimensional array of values, let's call it A. Now, I can plot this in a contour map, with coordinate axes X and Y, using
plt.contourf(X,Y,A)
Now, I have to carry out a mapping of these points to another plane, so, basically another set of coordinates. Let the transformation be
X - X1
Y - X1
Now, each point with magnitude "I" in matrix A at (X,Y) is at (X- X1, Y - Y1). I can plot this using
plt.contourf(X-X1, Y-Y1,A)
My question is, how do I index the array A such that I obtain an array B where the indexing corresponds to X-X1 and Y-Y1 instead of X and Y so that I can plot it directly using the following
plt.contourf(X,Y,B)
Thanks!

python function to interpolate the value at a point in a 2D field

I have a 2D pressure field and I would like to interpolate the value at
particular set of singular points or locations. I'm suspect downscaling is a solution but before I try and write the functions for python, I was wondering if there is a way/code already in existence. Perhaps scipy has a function but I'm unaware and cannot find any.
Any help is appreciated
Scipy has a 2-dimensional interpolation function:
scipy.interpolate.interp2d
Information on how to use this function can be found on http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.interpolate.interp2d.html
scipy.interpolate.interp2d(x, y, z)
in which x and y are 1-dimensional arrays of coordinates corresponding to the two dimensional array z which is your pressurefield.
x corresponds to the second axis of the z-matrix.
y corresponds to the first axis of the z-matrix

numpy 3D meshgrid only as a view

I have a cubic grid defined by the spacing xi,yi,zi:
xi,yi,zi = [linspace(ox,ox+s*d,s) for ox,s,d in zip(origin,size,delta)]
I also have set of scalar values W onto that grid. W.shape() == size. I'd like to use scipy's linear interpolation, which requires as input:
class scipy.interpolate.LinearNDInterpolator(points, values):
Parameters :
points : ndarray of floats, shape (npoints, ndims) Data point coordinates.
values : ndarray of float or complex, shape (npoints, ...) Data values.
How do I create a fake set of points (via magical broadcasting) from xi,yi,zi? Right now I'm creating an intermediate array to feed to the interpolation function - is there a better way?
Related Question: Numpy meshgrid in 3D. The answers in this post actually create the grid - I only want to simulate it as input to another function (pure numpy solution preferred).
>>> xi, yi, zi = [np.arange(3) for i in range(3)]
>>> xx, yy, zz = np.broadcast_arrays(xi,yi[:,np.newaxis],zi[:,np.newaxis,np.newaxis])
>>> xx.shape
(3, 3, 3)
>>> xx.strides
(0, 0, 8)
You can see it didn't create new copies since the strides are 0 in the first two dimensions.
I wrote a n dimensional version of this also:
def ndmesh(*args):
args = map(np.asarray,args)
return np.broadcast_arrays(*[x[(slice(None),)+(None,)*i] for i, x in enumerate(args)])
You can construct the necessary points array in a similar way as explained in the other answers:
xx, yy, zz = np.broadcast_arrays(xi[:,None,None], yi[None,:,None], zi[None,None,:])
points = (xx.ravel(), yy.ravel(), zz.ravel())
ip = LinearNDInterpolator(points, data.ravel())
However, if you have a regular grid, then using LinearNDInterpolator is most likely not the best choice, since it is designed for scattered data interpolation. It constructs a Delaunay triangulation of the data points, but in this case the original data has already a very regular structure that would be more efficient to make use of.
Since your grid is rectangular, you can build up the interpolation as a tensor product of three 1-D interpolations. Scipy doesn't have this built-in (so far), but it's fairly easy to do, see this thread: http://mail.scipy.org/pipermail/scipy-user/2012-June/032314.html
(use e.g. interp1d instead of pchip to get 1-D interpolation)
I do not believe there is any way you can pass something to LinearNDInterpolator short of a full copy (as there are no functions for regular grids in three dimensions too). So the only place to avoid creating full arrays would be during creation of this points array, I do not know how you do it right now, so maybe it is already efficient in this regard, but I guess its likely not worth the trouble to avoid this.
Other then np.mgrid+reshape maybe something like this might be an option (not to hard to write for n-dimensions too):
# Create broadcastest versions of xi, yi and zi
# np.broadcast_arrays does not allocate the full arrays
xi, yi, zi = np.broadcast_arrays(xi[:,None,None], yi[:,None,None], zi[:,None,None])
# then you could use .flat to fill a point array:
points = np.empty((xi.size, 3), dtype=xi.dtype)
points[:,0] = xi.flat
points[:,1] = yi.flat
points[:,2] = zi.flat
Opposed to the .repeat function, the temporary arrays created here are not larger then the original xi, etc. arrays.

Categories