I have a 2D array and it's contents will display correctly as an image when I simply use
img = plt.imshow(full2DArray)
but my problem is that the axes just naively show the number of rows and columns. For example if my 2D array is 53x53 then the axes will count 0-53 on the y-axis and 0-53 on the x-axis.
I need to show the exact same image but have the axes display a linear scale from -130 to +130 instead.
I have a similar answer to this question here but to explain for your case, we can take an array data = np.random.rand(53,53) filled with random values, and plot it with imshow. You simply need to adjust the extent=[<xmin>,<xmax>,<ymin>,<ymax>] parameter, so in the example code:
import numpy as np
import matplotlib.pyplot as plt
data = np.random.rand(53,53)
print(data.shape) # Displays (53,53)
plt.figure()
plt.xlabel("x")
plt.ylabel("y")
plt.imshow(data, origin='lower', aspect='auto',
extent = [-130,130,-130,130], cmap=plt.cm.jet)
plt.colorbar()
plt.show()
We get the following plot with your desired bounds:
If I understand it correctly, you need predifined axis, instead of pyplot infering these from the image.
Setting xlim before calling imshow will do the job.
plt.xlim([-130, 130])
Similarly, you can call ylim for the y axis.
Related
An advantage of plt.pcolormesh over plt.imshow is the possibility to have unequal axis spacing.
On the other hand, plt.imshow's advantage over plt.pcolormesh is that it can display RGB-triplets.
Now, the predicament I am in is that I need to plot RGB-triplets with uneven axis spacing....
Below is a MWE:
import numpy as np
import matplotlib.pyplot as plt
from colorsys import hsv_to_rgb
square_x_axis = np.linspace(0,1,100)**2
cube_y_axis = np.linspace(0,1,200)**3
X,Y = np.meshgrid(cube_y_axis,square_x_axis); print(f'meshgrid has shape: {X.shape}')
rgb_array = np.zeros((square_x_axis.size, cube_y_axis.size,3)); print(f'rgb_array has shape: {rgb_array.shape}')
""" Now we populate the rgb array (initially in hsv color space for clarity)"""
for i,row in enumerate(rgb_array):
for j,col in enumerate(row):
rgb_array[i,j,:] = np.array(hsv_to_rgb(0,square_x_axis[i],cube_y_axis[j]))
fig = plt.figure(figsize=(15,10))
imshow_ax = plt.subplot(1,2,1)
imshow_ax.imshow(rgb_array, aspect='auto', extent=[0,1,0,1])
pcolor_R_ax = plt.subplot(3,2,2)
pcolor_R_ax.pcolormesh(X,Y,rgb_array[:,:,0], cmap='Reds')
pcolor_G_ax = plt.subplot(3,2,4)
pcolor_G_ax.pcolormesh(X,Y,rgb_array[:,:,1], cmap='Greens')
pcolor_B_ax = plt.subplot(3,2,6)
pcolor_B_ax.pcolormesh(X,Y,rgb_array[:,:,2], cmap='Blues')
Which produces the following figure:
The problem becomes immediately obvious: imshow (on the left) is capable of representing the 3D array, but its axis are scaled wrong, leading to a distorted representation. pcolormesh (on the right), on the other hand, can not represent the 3D array (hence why I plot all three channels separately), but is capable of applying the axis correctly, leading to no distortion.
How can I combine these properties?
I found another answer here that seems to work on your example, with a small tweak for some new pcolorbesh behaviour (the shading='auto' bit). Try this plot on your data:
fig = plt.figure(figsize=(15,10))
placeholder = rgb_array[..., 0]
colors = rgb_array.reshape(-1, 3)
mesh = plt.pcolormesh(X, Y, placeholder, facecolors=colors, shading='auto')
mesh.set_array(None)
It produces:
#kwinkunks answer is the method that solved my problem:
The original data, using imshow, looked like this, where both the x- and y-axis of the data plot and the colorbar are wrong. Of all 4 axes, only the data y-axis is linear, the 3 other axes are non-linear, and so using imshows's extent option is no good:
Now... taking #kwinkunks answer directly produced the following plot:
...where the axes tickmarks are now as they should be! Amazing!
I have a code to plot a figure.
When I run this code without adding plt.colorbar(), I can get a figure which looks more like a rectangle. However, if I add colorbar, the shape change to look like a square.
How can I add colorbar and maintain the original shape of the figure? Thanks!!!
#%%
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
x = np.random.rand(10000)
y = np.random.rand(10000)
plt.scatter(x,y,c=y)
#plt.colorbar()
plt.show()
Following this documentation, you need to add some settings to axes. Your script works for me in a right ways if I insert these rows after creation of fig:
ax = plt.gca()
ax.set_aspect('equal', 'box')
I am trying to produce RGB polar plots in Python and I was expecting matplotlib.pyplot.imshow to be able to do it. However, whenever I try plotting data using this method I obtain a blank output.
import matplotlib.pyplot as plt
import numpy as np
data = np.array([[[0,0,1],[0,1,0],[1,0,0]],[[0,0,0.5],[0,0.5,0],[0.5,0,0]]])
# Sample, any N,M,3 data should work
ax = plt.subplot(111,polar=True)
ax.imshow(data,extent=[0,2*np.pi,0,1]) # Produces a white circle
Is there a good way to accomplish this using the aforementioned method or another ?
Thanks.
EDIT: I managed to make a single quadrant by using extent=[0,np.pi/2,0,1] but its use is clearly bugged for polar plots. since anything but a full quadrant doesn't produce the expected outcome.
Using imshow on a polar plot is unfortunately not possible, because the imshow grid is necessarily quadratic in its pixels. You may however use pcolormesh and apply a trick (similar to this one), namely to provide the colors as color argument to pcolormesh, as it would usually just take 2D input.
import matplotlib.pyplot as plt
import numpy as np
data = np.array([[[0,0,1],[0,1,0],[1,0,0]],
[[0,0,0.5],[0,0.5,0],[0.5,0,0]]])
ax = plt.subplot(111, polar=True)
#get coordinates:
phi = np.linspace(0,2*np.pi,data.shape[1]+1)
r = np.linspace(0,1,data.shape[0]+1)
Phi,R = np.meshgrid(phi, r)
# get color
color = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
# plot colormesh with Phi, R as coordinates,
# and some 2D array of the same shape as the image, except the last dimension
# provide colors as `color` argument
m = plt.pcolormesh(Phi,R,data[:,:,0], color=color, linewidth=0)
# This is necessary to let the `color` argument determine the color
m.set_array(None)
plt.show()
The result is not a circle because you do not have enough points. Repeating the data, data = np.repeat(data, 25, axis=1) would then allow to get a circle.
I'm trying to create a histogram of a data column and plot it logarithmically (y-axis) and I'm not sure why the following code does not work:
import numpy as np
import matplotlib.pyplot as plt
data = np.loadtxt('foo.bar')
fig = plt.figure()
ax = fig.add_subplot(111)
plt.hist(data, bins=(23.0, 23.5,24.0,24.5,25.0,25.5,26.0,26.5,27.0,27.5,28.0))
ax.set_xlim(23.5, 28)
ax.set_ylim(0, 30)
ax.grid(True)
plt.yscale('log')
plt.show()
I've also tried instead of plt.yscale('log') adding Log=true in the plt.hist line and also I tried ax.set_yscale('log'), but nothing seems to work. I either get an empty plot, either the y-axis is indeed logarithmic (with the code as shown above), but there is no data plotted (no bins).
try
plt.yscale('log', nonposy='clip')
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.yscale
The issue is with the bottom of bars being at y=0 and the default is to mask out in-valid points (log(0) -> undefined) when doing the log transformation (there was discussion of changing this, but I don't remember which way it went) so when it tries to draw the rectangles for you bar plot, the bottom edge is masked out -> no rectangles.
The hist constructor accepts the log parameter.
You can do this:
plt.hist(data, bins=bins, log=True)
np.logspace returns bins in [1-10], logarithmically spaced - in my case xx is a npvector >0 so the following code does the trick
logbins=np.max(xx)*(np.logspace(0, 1, num=1000) - 1)/9
hh,ee=np.histogram(xx, density=True, bins=logbins)
I have two questions regarding usage of the contourf plotting function. I have been searching for answers but haven't found them.
In the contourf function, there is a variable named cmap. What is this used for and what is its meaning? And what is cmap=cm.jet mean?
When one puts x,y,z into contourf and then creates a colorbar, how do we get the minimum and maximum values by which to set the colorbar limits? I am doing it manually now, but is there no way to get the min and max directly from a contourf handle?
The cmap kwarg is the colormap that should be used to display the contour plot. If you do not specify one, the jet colormap (cm.jet) is used. You can change this to any other colormap that you want though (i.e. cm.gray). matplotlib has a large number of colormaps to choose from.
Here is a quick demo showing two contour plots with different colormaps selected.
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
data = np.random.rand(10,10)
plt.subplot(1,2,1)
con = plt.contourf(data, cmap=cm.jet)
plt.title('Jet')
plt.colorbar()
hax = plt.subplot(1,2,2)
con = plt.contourf(data, cmap=cm.gray)
plt.title('Gray')
plt.colorbar()
As far as getting the upper/lower bounds on the colorbar programmatically, you can do this by getting the clim value of the contourf plot object.
con = plt.contourf(data);
limits = con.get_clim()
(0.00, 1.05)
This returns a tuple containing the (lower, upper) bounds of the colorbar.