Heatmap in Python using matplotlib from 3 independent arrays - python

I would like to do a heatmap plot using three independent vectors x, y and z. I have looked at examples over the internet and most of them show how to do heatmap plot for x, y and z represented as a 2D matrix
So, can someone please help me on how can I convert 3 independent vectors to a 2d matrix, which I can eventually use for doing heatmap plots
One thing that I thought was to create matrix by first discretizing and arranging in ascending order x and y, and finding z at the new "x" and "y" combinations. But, there could be cases in which "z" cannot be computed due to lack of data during interpolation
I am bit confused, and I would like to seek help in this regard

Have a look at pcolormesh. It does what you need: create a heat map of data that do not lie on a regular grid. You can specify how the data are interpolated (and extrapolated).
From the docs:
matplotlib.pyplot.pcolormesh(*args, alpha=None, norm=None, cmap=None, vmin=None, vmax=None, shading='flat', antialiased=False, data=None, **kwargs)
Create a pseudocolor plot with a non-regular rectangular grid.
Call signature:
pcolor([X, Y,] C, **kwargs)
X and Y can be used to specify the corners of the quadrilaterals.

Thank you group memebers. With your help, 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)

Related

plotting contours from a three column array

I have a three column array, contains two parameters which are the x and y axes, and the Chi-square of these two parameters. I should make a meshgrid of these two parameters and then plot 1-sigma, 2-sigma, and 3-sigma contours, considering the Chi-square values. How can I do it in matplotlib?
Here is my code:
x (which is the second column in the "1.txt" file) and y (which is the third column) should be arranged from min to max, in order to make x and y axes, I thought it can be done using meshgrid. And z (the first column in the "1.txt" file) is the Chi-square.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import griddata
x = np.genfromtxt('1.txt', usecols=(1))
y = np.genfromtxt('1.txt', usecols=(2))
z = np.genfromtxt('1.txt', usecols=(0))
plt.figure()
X, Y = np.meshgrid(x,y)
Z= griddata(x,y,z,X,Y)
contour=plt.contour(X,Y,Z)
plt.show()
this code confront with the error:
"RuntimeError: To use interp='nn' (Natural Neighbor interpolation) in griddata, natgrid must be installed. Either install it from http://github.com/matplotlib/natgrid or use interp='linear' instead."
When I use interp='linear', running the code would last a long time without any result. Is there any way to solve this problem?
It looks like you are creating a "grid" of all values in your columns. Instead you would want to create a regular grid of numbers in an increasing order. E.g. using 100 values between the minimum and maximum of the data
X = np.linspace(x.min(), x.max(), 100)
Y = np.linspace(y.min(), y.max(), 100)
Z = griddata(x, y, z, xi, yi, interp='linear')
contour=plt.contour(X, Y, Z)
Also see this example.
Note however that matplotlib.mlab.griddata has been removed in newer versions of matplotlib, but is available with from scipy.interpolate import griddata, as shown in the new example, which also has the a newer option with axes.tricontour.
Consider directly plotting a triangulated contour using your original values x,y,z,
plt.tricontour(x, y, z)

matplotlib 2d histrogram heatmap-- how do I use my dataset to make one?

I am new to python.
I have a dataset like
import numpy as np
from matplotlib import pyplot as plt
dats = np.array([r1,x1,y1],[r2,x2,y2],...])
I would like to plot color intensity associated with r1,r2,... at the position (x1,y1), (x2,y2), et cetera respectively.
How can I get this data set manipulated in a format which matplotlib can use in a 2D histogram?
Any help much appreciated. I'll help others in return once I've gained some skill : o
In order to make 2D histogram, your data set has to comprises two data values rather than one data value and two indices. Thus, you need two arrays: one containing the r1 values and one containing the r2 values. Your data does not have any r2 values, therefore, you cannot compute a bi-dimensional histogram.
Regarding your question, you do not even want a histogram. You just want to visualise your r1 values on a plane. This is easy. Say, your array dats has a length of 100, then:
rs = dats[:, 0] # retrieve r-values from dats
plt.imshow(rs.reshape(10, 10), cmap='Greys', interpolation='None')
plt.colorbar()
You can create interpolated data from a set of points using griddata, assuming x = [x1, x2, etc] and r = [r1, r2, etc] then,
#Setup a grid
xi = np.linspace(x.min(),x,max(),100)
yi = np.linspace(y.min(),y.max(),100)
zi = griddata(x, y, r, xi, yi, interp='linear')
#Plot the colormap
cm = plt.pcolormesh(xi,yi,zi)
plt.colorbar()
plt.show()
Other options include colouring scatter plots,
plt.scatter(x,y,c=r)
or there is a 2D histogram functions in scipy where you could set the weights based on r,
H, xedges, yedges = np.histogram2d(x, y, w_i = r)
I haven't used the last one personally.
I think what you are looking for is not a histogram but a contour plot (a histogram would count the number of occurrences of a coordinate (x,y) falling into a bin).
If your data is not on a grid, you can use tricontourf:
plt.tricontourf(dats[:,1],dats[:,2],dats[:,0],cmap='hot')
plt.colorbar()
plt.show()
There are more ways to plot this, such as scatter plots etc.

Adding a 4th variable to a 3D plot in Python

I have 3 different parameters X,Y and Z over a range of values, and for each combination of these a certain value of V. To make it clearer, the data would look something like this.
X Y Z V
1 1 2 10
1 2 3 15
etc...
I'd like to visualize the data with a surface/contour plot, using V as a colour to see its value at that point, but I do not see how to add my custom colouring scheme into the mix using Python. Any idea on how to do this (or is this visualization outright silly)?
Thanks a lot!
Matplotlib allows one to pass the facecolors as an argument to e.g.
ax.plot_surface.
That would imply then that you would have to perform 2D interpolation on your
current array of colors, because you currently only have the colors in the
corners of the rectangular faces (you did mention that you have a rectilinear
grid).
You could use
scipy.interpolate.interp2d
for that, but as you see from the documentation, it is suggested to use
scipy.interpolate.RectBivariateSpline.
To give you a simple example:
import numpy as np
y,x = np.mgrid[1:10:10j, 1:10:10j] # returns 2D arrays
# You have 1D arrays that would make a rectangular grid if properly reshaped.
y,x = y.ravel(), x.ravel() # so let's convert to 1D arrays
z = x*(x-y)
colors = np.cos(x**2) - np.sin(y)**2
Now I have a similar dataset as you (one-dimensional arrays for x, y, z and
colors). Remark that the colors are defined for
each point (x,y). But when you want to plot with plot_surface, you'll
generate rectangular patches, of which the corners are given by those points.
So, on to interpolation then:
from scipy.interpolate import RectBivariateSpline
# from scipy.interpolate import interp2d # could 've used this too, but docs suggest the faster RectBivariateSpline
# Define the points at the centers of the faces:
y_coords, x_coords = np.unique(y), np.unique(x)
y_centers, x_centers = [ arr[:-1] + np.diff(arr)/2 for arr in (y_coords, x_coords)]
# Convert back to a 2D grid, required for plot_surface:
Y = y.reshape(y_coords.size, -1)
X = x.reshape(-1, x_coords.size)
Z = z.reshape(X.shape)
C = colors.reshape(X.shape)
#Normalize the colors to fit in the range 0-1, ready for using in the colormap:
C -= C.min()
C /= C.max()
interp_func = RectBivariateSpline(x_coords, y_coords, C.T, kx=1, ky=1) # the kx, ky define the order of interpolation. Keep it simple, use linear interpolation.
In this last step, you could also have used interp2d (with kind='linear'
replacing the kx=1, ky=1). But since the docs suggest to use the faster
RectBivariateSpline...
Now you're ready to plot it:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.cm as cm
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
r = ax.plot_surface(X,Y,Z,
facecolors=cm.hot(interp_func(x_centers, y_centers).T),
rstride=1, cstride=1) # only added because of this very limited dataset
As you can see, the colors on the faces have nothing to do anymore with the height of the dataset.
Note that you could have thought simply passing the 2D array C to facecolors would work, and matplotlib would not have complained. However, the result isn't accurate then, because matplotlib will use only a subset of C for the facecolors (it seems to ignore the last column and last row of C). It is equivalent to using only the color defined by one coordinate (e.g. the top-left) over the entire patch.
An easier method would have been to let matplotlib do the interpolation and obtain the facecolors and then pass those in to the real plot:
r = ax.plot_surface(X,Y,C, cmap='hot') # first plot the 2nd dataset, i.e. the colors
fc = r.get_facecolors()
ax.clear()
ax.plot_surface(X, Y, Z, facecolors=fc)
However, that won't work in releases <= 1.4.1 due to this recently submitted bug.
It really depends on how you plan on plotting this data. I like to plot graphs with gnuplot: it's easy, free and intuitive. To plot your example with gnuplot you'd have to print those line into a file (with only those four columns) and plot using a code like the following
reset
set terminal png
set output "out.png"
splot "file.txt" using 1:2:3:4 with lines palette
Assuming that you save your data into the file file.txt. splot stands for surface plot. Of course, this is a minimum example.
Alternatively you can use matplotlib, but that is not, in my opinion, as intuitive. Although it has the advantage of centering all the processing in python.

Making a contour plot with solutions from systems of differential equations with pylab

So, I'm solving a system of differential equations numerically i have x,y,z each a solution. Each array is one dimensional and and for example x[0],y[0],z[0] goes with a point in space. i want to graph these in a contour like the usual x y z coordinates, it says i need z to be a 2d array, i know how to make a mesh from x and y, but how do i do this to z?
I have made a mesh out of the x,y, but for z i don't know what to do.
if someone could give me insight it would be much appreciated.
It is not enough to just mesh in x and y, you need to grid your data on a regular grid to be able to do a contour plot. To do this you should look into matplotlib.mlab.griddata (http://matplotlib.org/examples/pylab_examples/griddata_demo.html).
I'll paste the example code from the link below with some extra comments:
from numpy.random import uniform, seed
from matplotlib.mlab import griddata
import matplotlib.pyplot as plt
import numpy as np
# Here the code generates some x and y coordinates and some corresponding z values.
seed(0)
npts = 200
x = uniform(-2,2,npts)
y = uniform(-2,2,npts)
z = x*np.exp(-x**2-y**2)
# Here you define a grid (of arbitrary dimensions, but equal spacing) onto which your data will be mapped
xi = np.linspace(-2.1,2.1,100)
yi = np.linspace(-2.1,2.1,200)
# Map the data to the grid to get a 2D array of remapped z values
zi = griddata(x,y,z,xi,yi,interp='linear')
# contour the gridded data, plotting dots at the nonuniform data points.
CS = plt.contour(xi,yi,zi,15,linewidths=0.5,colors='k')
CS = plt.contourf(xi,yi,zi,15,cmap=plt.cm.rainbow,
vmax=abs(zi).max(), vmin=-abs(zi).max())
plt.colorbar() # draw colorbar
# Plot the original sampling
plt.scatter(x,y,marker='o',c='b',s=5,zorder=10)
plt.xlim(-2,2)
plt.ylim(-2,2)
plt.title('griddata test (%d points)' % npts)
plt.show()
It looks like you are looking for line or scatter plots instead of contour.

How to plot with mplot3d

I am trying to plot the solutions of a minimization problem,
'X, Y = meshgrid(gammas, psis)'
gammas and psis are my 2 axes,
'mplot3d(X, Y, x)'
x is the solution of my problem,
While executing my script : name 'mplot3d' is not defined......
import pylab
def scatterme(x, y, z):
pylab.figure()
imi = pylab.scatter(x, y, c = z, edgecolor = "none")
pylab.colorbar(imi)
pylab.show()
In this case, my x and y are what for you would be X.flatten() and Y.flatten() and the z would be your x.flatten(). This code also works if your data does not come from something square, so if you just want to see what something looks like, if you have a lot of x and y values, and for each one you have a z, this shows you what you want as well.
Note: this is not a 3D plot, but i (personnal opinion) feel that a scatterplot in which the z-dimension is your colorbar seems to show much more what you need to know, compared to a 3D plot that you have to rotate around all the time, to be able to see at the angle that might show you something you want to know
Edit:
for the full code, that you can just copypaste (put this after the first piece in my post)
import numpy
X,Y = meshgrid(gammas, psis)
scatterme(X.flatten(), Y.flatten(), x.flatten())

Categories

Resources