I was trying to make a Polar heatmap using the following code.
# Plotting the polar plot
from matplotlib.colorbar import ColorbarBase
from matplotlib.colors import LogNorm
import matplotlib.pyplot as plt
cmap = obspy_sequential
# Have defined the variables to be used for pointing to the coordinates
# baz is angular, slow is radial, abs_power is the value at every co-ordinate
# Choose number of fractions in plot (desirably 360 degree/N is an integer!)
N = 72
N2 = 30
abins = np.arange(N + 1) * 360. / N
sbins = np.linspace(0, 3, N2 + 1)
# Sum rel power in bins given by abins and sbins
hist, baz_edges, sl_edges = \
np.histogram2d(baz, slow, bins=[abins, sbins], weights=abs_power)
# Transform to radian
baz_edges = np.radians(baz_edges)
# Add polar and colorbar axes
fig = plt.figure(figsize=(8, 8))
cax = fig.add_axes([0.85, 0.2, 0.05, 0.5])
ax = fig.add_axes([0.10, 0.1, 0.70, 0.7], polar=True)
ax.set_theta_direction(-1)
ax.set_theta_zero_location("N")
dh = abs(sl_edges[1] - sl_edges[0])
dw = abs(baz_edges[1] - baz_edges[0])
# Circle through backazimuth
for i, row in enumerate(hist):
bars = ax.bar((i * dw) * np.ones(N2),
height=dh * np.ones(N2),
width=dw, bottom=dh * np.arange(N2),color=cmap(row / hist.max()))
ax.set_xticks(np.linspace(0, 2 * np.pi, 10, endpoint=False))
ax.set_yticklabels(velocity)
ax.set_ylim(0, 3)
[i.set_color('white') for i in ax.get_yticklabels()]
ColorbarBase(cax, cmap=cmap,
norm=LogNorm(vmin=hist.min(),vmax=hist.max()))
plt.show()
I am creating multiple plots like this and thus I need to extend the range of the colorbar beyond the maximum of the abs_power data range. I tried changing the vmax and vmin to the maximum-minimum target numbers I want, but it plots out the exact same plot every single time. The maximum value on the colorbar keeps changing but the plot does not change. Why is this happening? Here is how it looks,
Here the actual maximum power is way lesser than the maximum specified in the colorbar. Still a bright yellow spot is visible. PS : I get this same plot for any vmax,vmin values I provide.
Changing the colorbar doesn't have an effect on the main plot. You'd need to change the formula used in color=cmap(row / hist.max())
to change the barplot. The 'norm' is just meant for this task. The norm maps the range of numbers to the interval [0, 1]
. Every value that is mapped to a value higher than 1 (i.e. a value higher than hist.max()
in the example), gets assigned the highest color.
To have the colorbar reflect the correct information, you'd need the same cmap and same norm for both the plot and the colorbar:
my_norm = LogNorm(vmin=hist.min(),vmax=hist.max())
for i, row in enumerate(hist):
bars = ax.bar((i * dw) * np.ones(N2),
height=dh * np.ones(N2),
width=dw, bottom=dh * np.arange(N2),color=cmap(my_norm(row)))
and
ColorbarBase(cax, cmap=cmap, norm=my_norm)
On the other hand, if you don't want the yellow color to show up, you could try something like my_norm = LogNorm(vmin=hist.min(), vmax=hist.max()*100)
in the code above.
Instead of creating the colorbar via ColorbarBase
, it can help to use a standard plt.colorbar()
, but with a ScalarMappable
that indicates the color map and the norm used. In case of a LogNorm
this will show the ticks in log format.
from matplotlib.cm import ScalarMappable
plt.colorbar(ScalarMappable(cmap=cmap, norm=my_norm), ax=ax, cax=cax)