Matplotlib: how to set cbar limits from a fig object? - python

I have a number of matplotlib.figure.Figure objects. Each of these contain a pcolormesh with an associated colorbar. I would like to change the color scale of these plots so they're all plotted on the same scale. Starting from the fig object, how do I reference the appropriate objects and change the color scale of the pcolormeshes?
I've tried a number of things along the lines of fig.axes[0].set(clim=[0, 10]) but keep running into errors like AttributeError: 'AxesSubplot' object has no property 'clim'

Related

Adding colorbar to scatter plot

I am currently working with some geospatial data and I want to add a colorbar next to the map. I used the following code to overlay a baseline map with a scatter plot. However, I cannot get the correct colorbar next to it. Can anyone find the reason for such behaviour?
cm = plt.cm.get_cmap('RdYlBu') # define a colormap
fig,ax = plt.subplots(figsize=(15, 15))
city_map = df.plot(alpha=0.2, ax=ax) # plot a city contour
ctx.add_basemap(city_map) # plot a city map
points = gdf_new.plot(c=gdf_new['Score'], cmap=cm, ax=ax) # scatter plot
fig.colorbar(ax.collections[1], ax=ax) # current solution
pandas column gdf_new['Score'] contains values from 0 to 1 used for points coloring.
If I replace the last line with below, I get:
for plt.colorbar() - RuntimeError: No mappable was found to use for colorbar creation. First define a mappable such as an image (with imshow) or a contour set (with contourf)
for plt.colorbar(point) - AttributeError: 'AxesSubplot' object has no attribute 'get_array'
My current solution is to add:
fig.colorbar(ax.collections[1], ax=ax) - it displays the correct color bar but with a wrong numbers' range of 0-200 instead 0-1.
How to fix it?

Limiting the axes on a mplot3d surface without the graph spilling from the figure?

I'm attempting to make a 3D surface plot of a spectrogram, but I want to limit the axes to a certain frequency and time range. I've tried the following:
fig = plt.figure(figsize=(1,1))
ax = mplot3d.axes3d.Axes3D(fig,rect=(0,0,20,5),azim=-90,elev=10)
plot = ax.plot_surface(x,y,z,norm=norm,vmin=vmin,vmax=vmax,cmap=cmap)
ax.axes.set_ylim3d(bottom=0, top=200)
ax.axes.set_xlim3d(left=-5, right=40)
fig.colorbar(plot)
plt.show()
as well as xlim()/ylim(), and set_ylim()/set_xlim(). For some reason, when I try to limit the axes, the graph spills over the edge like so.
The graph without axis limits for reference.
How do I avoid this?

matplotlib get colorbar mappable from an axis

I want to add a colorbar WITHOUT what is returned by the axis on plotting things.
Sometimes I draw things to an axis inside a function, which returns nothing.
Is there a way to get the mappable for a colorbar from an axis where a plotting has been done beforehand?
I believe there is enough information about colormap and color range bound to the axis itself.
I'd like tp do something like this:
def plot_something(ax):
ax.plot( np.random.random(10), np.random.random(10), c= np.random.random(10))
fig, axs = plt.subplots(2)
plot_something(axs[0])
plot_something(axs[1])
mappable = axs[0].get_mappable() # a hypothetical method I want to have.
fig.colorbar(mappable)
plt.show()
EDIT
The answer to the possible duplicate can partly solve my problem as is given in the code snippet. However, this question is more about retrieving a general mappable object from an axis, which seems to be impossible according to Diziet Asahi.
The way you could get your mappable would depend on what plotting function your are using in your plot_something() function.
for example:
plot() returns a Line2D object. A reference to that object is
stored in the list ax.lines of the Axes object. That being said, I don't think a Line2D can be used as a mappable for colorbar()
scatter() returns a PathCollection collection object. This object is stored in the ax.collections list of the Axes object.
On the other hand, imshow() returns an AxesImage object, which is stored in ax.images
You might have to try and look in those different list until you find an appropriate object to use.
def plot_something(ax):
x = np.random.random(size=(10,))
y = np.random.random(size=(10,))
c = np.random.random(size=(10,))
ax.scatter(x,y,c=c)
fig, ax = plt.subplots()
plot_something(ax)
mappable = ax.collections[0]
fig.colorbar(mappable=mappable)

Label objects not found

Setup a graph using matplotlib which is working properly (see image below), but when I try to add a legend I get the following error: UserWarning: No labeled objects found. Use label='...' kwarg on indivial plots.
Here's the code I'm using to define the lines that I want in the legend and draw the legend:
#Moving average labels
smaLabel1 = str(SMA1)+'d SMA'
smaLabel2 = str(SMA2)+'d SMA'
smaLabel3 = str(SMA3)+'d SMA'
#Add SMAs to chart
ax1.plot(ind, avg1, '#5998ff', label=smaLabel1, linewidth=1)
ax1.plot(ind, avg2, '#ffbb82', label=smaLabel2, linewidth=1)
ax1.plot(ind, avg3, '#d689c4', label=smaLabel3, linewidth=1)
""" End SMA additions """
#Add legend
plt.legend()
I've checked the smaLabel variables, and all hold the correct strings. Anyone know why the labels aren't registering?
You must have plot the candle plots and the volume before plotting the SMA. The candle plot doesn't have any labeled object, when you call the plt.legend(), it tries to plot a label for every plot on the current axes. Therefore, you get this UserWarning: No labeled objects found. Use label='...' kwarg on indivial plots.
To solve it, I hope it is clear at this point, simply requires you to plot the SMA's very first, before the candle plot, and call the legend() right after that before any other plots being generated.

Matplotlib: make x-axis longer

In Matplotlib I need to draw a graph with points on the x-axis on each integer between 1 and 5000 and on the y-axis only in a very limited range.
Matplotlib automatically compacts everything to let all the data fit on a (landscape) page. In my case I would like the x-axis to be as large as possible so that all points are clearly visible. Right now there's just a thick coloured line as opposed to scattered points.
How can I do this?
(I'm saving to pdf, if that helps)
You can always try to specify the dimensions (in inches) of the figure you are creating. Something along the following line might help:
fig = plt.figure(figsize=(20, 2))
ax = fig.add_subplot(111)
ax.plot(x, y)
The figsize takes a tuple of width, height in inches.

Categories