plotting contours from a three column array - python

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)

Related

To plot graph non linear function

I want to plot graph of this function:
y = 2[1-e^(-x+1)]^2-2
When I plot a linear function, I used this code :
import matplotlib.pyplot as plt
import numpy as np
x = np.array(...)
y = np.array(...)
z = np.polyfit(x, y, 2)
p = np.poly1d(z)
xp = np.linspace(...)
_ = plt.plot(x, y, '.', xp, p(xp), '-')
plt.ylim(0, 200)
plt.show()
When the function is non-linear, it does not works
becasue it hard to find each x,y value.
How can I plot a non-linear function?
I hate to be the one to break this news to you, but polynomials of order greater than one are technically nonlinear too.
When you plot in matplotlib, you're really supplying discreet x and y values at a resolution sufficient to be visually pleasing. In this case, you've chosen xp to determine the points you plot for the parabola. You then call p(xp) to generate an array of y-values at those locations.
There nothing stopping you from generating y-values for your formula of interest using simple numpy functions:
y = 2 * (1 - np.exp(1 - xp))**2 - 2

In python - How can I plot 2D figure (x,y) and add 3rd axis by variation of the colour for each (x,y)-coordinate?

I want to add a 3rd axis data by adding a colour for each point on my 2D-plot.
I have measured the electric potential in an area, the X,Y is the lattitude and the longtitude. so each point on the 2D plot is a coordinate. Now I want to make each point a colour corresponding to the electrical potential measured (the z data). If the values are near each other they should be almost the same colour and a different if they are far apart.
I plotted it as 2D like this:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as pl
pl.plot(x,y, '*')
pl.xlabel('Latitude')
pl.ylabel('Longitude')
And then I tried to make a contourplot, with the data from the z-axis, but the plot turns out weird. If I try to plot the z-data directly, it gives an error saying "TypeError: Input z must be a 2D array.".
x = lat
y = lon
z = EP
X, Y = np.meshgrid(x, y)
print (X.shape, Y.shape)
# (2, 7) (2, 7) Both have same shape
#Z = z.reshape(X.shape) # Use either X or Y to define shape
Z=np.tile(z,(211,1))
print(Z.shape)
#print(z)
fig = plt.figure()
ax1 = plt.contour(X,Y,Z)
plt.colorbar(ax1)
plt.show()
I would like the plot to look a bit like this, where the dots have different colours depending on their value. Our x,y and z arrays are all arrays of one column and 211 rows, so they have the same size.
You could try using pl.scatter
%matplotlib inline
import numpy as np
import matplotlib.pyplot as pl
graph = pl.scatter(x, y, c=z)
pl.xlabel('Latitude')
pl.ylabel('Longitude')
pl.colorbar(graph)

Heatmap in Python using matplotlib from 3 independent arrays

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)

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.

Categories

Resources