How to use griddata from scipy.interpolate - python

I have a three-column (x-pixel, y-pixel, z-value) data with one million lines. The data is from an image and there are duplicated z-values. Now I need to make a surface plot. This image is a perfect example. But now the output image is null. Could someone check the code please?
import numpy as np
from enthought.mayavi import mlab
from scipy.interpolate import griddata
x,y,z = np.loadtxt('test.csv',delimiter=',',usecols=(0,1,2),unpack=True)
xi,yi = np.mgrid[0:3000:3000j, 0:3000:3000j]
zi = griddata((x, y), z, (xi, yi),method='linear')
mlab.surf(xi,yi,zi)
mlab.show()

I can't check the code without having the data, but I suspect that the problem is that you are using the default fill_value=nan as a griddata argument, so if you have gridded points that extend beyond the space of the (x,y) points, there are NaNs in the grid, which mlab may not be able to handle (matplotlib doesn't easily). Try setting fill_value=0 or another suitable real number.

Related

Python contour plot in traditional 3D data?

I've been using Python/NumPy for a lot of things for a while now, but I am still confused about creating 3D plots.
In a "traditional" data analysis program (Origin, SigmaPlot, Excel...), if you want to make a 3D plot or a contour plot, you usually have your data in (X,Y,Z) format, that is, for each pair of X and Y you have one value of Z.
As opposed to this, all Python plotting guides I find use numpy.meshgrid for plotting -and I don't fully understand the connection to the traditional plotting software.
Let's say I have the following code:
axes_range = np.linspace(-5, 5, num=25)
alphas = []
for xcoord in axes_range:
for ycoord in axes_range:
alphas.append(f(xcoord,ycoord))
What's the best way of making a plot of (xcoord, ycoord, alphas)?
With matplotlib you simply need
import matplotlib.pylab as plt
import numpy as np
from matplotlib import cm
X, Y = np.meshgrid(xcoord, ycoord)
plt.contourf(X, Y, alphas.T, levels=20, cmap=cm.jet)
plt.show()
I think you need to transpose alphas as I do here.

How to extract marker data points from a line plotted with markevery argument?

I am trying to get the data coordinates of line markers drawn with a help of markevery option. My attempt at the code below shows that the retrieved (x,y) data contains all original data values and the argument is ignored:
import numpy as np
from matplotlib import pyplot as plt
line, = plt.plot(np.arange(100)**2, marker='o', markevery=(0, 0.1))
x, y = line.get_data()
assert len(x) != 100
Note the value of markevery argument—advanced indexing on the data in this case is not applicable as an alternative.
Of course, I can successfully use private utility method lines._mark_every_path() to solve the problem I deal with. But is there any more, let's say, "correct" way to do that?
The markevery option allows to subsample the marked datapoints on a line. Which points are marked or not is only determined at the moment the line is drawn. There is hence no attribute of the line that would store the data of the shown points, because they might change all the time, depending on the size and limits of the plot.
The solution is indeed to replicate the drawing behaviour of the line to access the coordinates of the marked points, using _mark_every_path.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import lines
line, = plt.plot(np.arange(100)**2, marker='o', markevery=(0, 0.1))
tpath, affine = line._get_transformed_path().get_transformed_points_and_affine()
p = lines._mark_every_path(line.get_markevery(),
tpath, affine, line.axes.transAxes)
print(len(p.vertices)) # prints 10
print(p.vertices) # print array of points, shape (10,2)
plt.show()

2D Map in matplotlib with discrete values

I'm currently trying to plot with matplotlib a 2d map recorded with an instrument. The instrument is moving 2 motors (it makes a raster) and records the associated intensity value.
I'm currently able to plot the data and to associate the values I want to the axes, but I would like to digitize (make discrete) these values in order to obtain at each pixel of the image the corresponding values for the motors.
I'm currently using the following code (in the example I'll use x and y to define the motor positions):
import pylab as pl
pl.imshow(intensity, extent=(x_min, x_max, y_min, y_max),
interpolation='none')
The code works quite well but if I select one of the pixel on my plot with the cursor, it returns continuous values with many digits (like in figure).
Would it be possible to obtain directly the values of the motors (which I have stored for each point/pixel) by positioning the cursor on them?
Thanks for the help,
Fabio
You can do it by modifying the coordinate formatter like in this example on the matplotlib documentation. A simple adaptation to your request is:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
X = 10*np.random.rand(5, 3)
fig, ax = plt.subplots()
ax.imshow(X, cmap=cm.jet, interpolation='nearest')
def format_coord(x, y):
return 'x=%i, y=%i' % (x+1, y+1)
ax.format_coord = format_coord
plt.show()
, which will result in this:
Also you might want to check out mpldatacursor for something more pretty. For this option take a look at this question here in SO.

2D color plot with irregularly spaced samples (matplotlib.mlab.griddata)

cI previously posted this over at code review, but moved it over here as I was told it is more fitting.
Basically, I want to create a colorplot of some irregularly sampled data. I've had some success with the interpolation using matplotlib.mlab.griddata. When I plot the interpolated data (using matplotlib.pyplot.imshow) however, the edges of the domain appear to be left blank. This gets better if I increase the grid density (increase N in the code) but doesn't solve the problem.
I've attached my code and would like to upload an image of the plot I can generate, but am still lacking the reputation to post an image ;)
edit: That has changed now, uploaded the plot after the changes proposed by Ajean:
. Can someone help me out as to what is going wrong?
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.mlab import griddata
# Generate Data
X=np.random.random(100)
Y=2*np.random.random(100)-1
Z=X*Y
# Interpolation
N=100j
extent=(0,1,-1,1)
xs,ys = np.mgrid[extent[0]:extent[1]:N, extent[2]:extent[3]:N]
resampled=griddata(X,Y,Z,xs,ys,interp='nn')
#Plot
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlabel('X')
ax.set_ylabel('Y')
cplot=ax.imshow(resampled.T,extent=extent)
ticks=np.linspace(-1,1,11)
cbar=fig.colorbar(magplot,ticks=ticks,orientation='vertical')
cbar.set_label('Value', labelpad=20,rotation=270,size=16)
ax.scatter(X,Y,c='r')
It is because your calls to random don't provide you with any values at the boundary corners, therefore there is nothing to interpolate with. If you change X and Y definitions to
# Just include the four corners
X=np.concatenate([np.random.random(100),[0,0,1,1]])
Y=np.concatenate([2*np.random.random(100)-1,[-1,1,1,-1]])
You'll fill in the whole thing.

Matplotlib : quiver and imshow superimposed, how can I set two colorbars?

I have a figure that consists of an image displayed by imshow(), a contour and a vector field set by quiver(). I have colored the vector field based on another scalar quantity. On the right of my figure, I have made a colorbar(). This colorbar() represents the values displayed by imshow() (which can be positive and negative in my case). I'd like to know how I could setup another colorbar which would be based on the values of the scalar quantity upon which the color of the vectors is based. Does anyone know how to do that?
Here is an example of the image I've been able to make. Notice that the colors of the vectors go from blue to red. According to the current colorbar, blue means negative. However I know that the quantity represented by the color of the vector is always positive.
Simply call colorbar twice, right after each plotting call. Pylab will create a new colorbar matching to the latest plot. Note that, as in your example, the quiver values range from 0,1 while the imshow takes negative values. For clarity (not shown in this example), I would use different colormaps to distinguish the two types of plots.
import numpy as np
import pylab as plt
# Create some sample data
dx = np.linspace(0,1,20)
X,Y = np.meshgrid(dx,dx)
Z = X**2 - Y
Z2 = X
plt.imshow(Z)
plt.colorbar()
plt.quiver(X,Y,Z2,width=.01,linewidth=1)
plt.colorbar()
plt.show()
Running quiver doesn't necessarily return the type of mappable object that colorbar() requires. I think it might be because I explicitly "have colored the vector field based on another scalar quantity" like Heimdall says they did. Therefore, Hooked's answer didn't work for me.
I had to create my own mappable for the color bar to read. I did this by using Normalize from matplotlib.colors on the data that I wanted to use to color my quiver vectors (which I'll call C, which is an array of the same shape as X, Y, U, and V.)
My quiver call looks like this:
import matplotlib.pyplot as pl
import matplotlib.cm as cm
import matplotlib.colors as mcolors
import matplotlib.colorbar as mcolorbar
pl.figure()
nz = mcolors.Normalize()
nz.autoscale(C)
pl.quiver(X, Y, U, V, color=cm.jet(nz(C)))
cax,_ = mcolorbar.make_axes(pl.gca())
cb = mcolorbar.ColorbarBase(cax, cmap=cm.jet, norm=nz)
cb.set_label('color data meaning')
Giving any other arguments to the colorbar function gave me a variety of errors.

Categories

Resources