Extents in hist2d?

How do I place extents on the colorbar in a hist2d?

What I need is a fixed range for the colorbar, so that various plots are all comparable. How do I achieve this?

EDIT: adding code that shows the issue:

import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
from numpy.random import default_rng
import numpy as np

RG = default_rng()

NORMZ = LogNorm()

SIDE = 6
GRATIO = 1.5
FIG, AXES = plt.subplots(2, constrained_layout=True, figsize=(SIDE, SIDE))

SAMPLES_X1 = RG.lognormal(3.0, 5.0, 5000)
SAMPLES_Y1 = RG.lognormal(3.0, 5.0, 5000)

BIN_EDGES_X = np.histogram_bin_edges(np.log10(SAMPLES_X1), bins=100)
BIN_EDGES_X = np.power(10, BIN_EDGES_X)
BIN_EDGES_Y = np.histogram_bin_edges(np.log10(SAMPLES_Y1), bins=100)
BIN_EDGES_Y = np.power(10, BIN_EDGES_Y)

IM = AXES[0].hist2d(SAMPLES_X1, SAMPLES_Y1, [BIN_EDGES_X, BIN_EDGES_Y],
                    cmap='cool', density=True, norm=NORMZ)

print(np.min(IM[0][np.nonzero(IM[0])]), np.max(IM[0]))
print(IM[1][0], IM[1][-1])
print(IM[2][0], IM[2][-1])

FIG.colorbar(IM[3], ax=AXES)


SAMPLES_X2 = RG.lognormal(3.0, 7.0, 5000)
SAMPLES_Y2 = RG.lognormal(3.0, 7.0, 5000)

BIN_EDGES_X = np.histogram_bin_edges(np.log10(SAMPLES_X2), bins=100)
BIN_EDGES_X = np.power(10, BIN_EDGES_X)
BIN_EDGES_Y = np.histogram_bin_edges(np.log10(SAMPLES_Y2), bins=100)
BIN_EDGES_Y = np.power(10, BIN_EDGES_Y)

IM = AXES[1].hist2d(SAMPLES_X2, SAMPLES_Y2, [BIN_EDGES_X, BIN_EDGES_Y],
                    cmap='cool', density=True, norm=NORMZ)

print(np.min(IM[0][np.nonzero(IM[0])]), np.max(IM[0]))
print(IM[1][0], IM[1][-1])
print(IM[2][0], IM[2][-1])

#FIG.colorbar(IM[3], ax=AXES)

AXES[0].tick_params(length=9, labelsize=15)
AXES[0].set_yscale('log')
AXES[0].set_xscale('log')
AXES[1].tick_params(length=9, labelsize=15)
AXES[1].set_yscale('log')
AXES[1].set_xscale('log')
plt.show()

When you create your norm, set the min/max values you want

NORMZ = LogNorm(my_min, my_max)

and then pass that to all of your calls to hist2d. If you do not set the min/max the first time the norm is used it tries to infer the “right” limits based on the data it sees.

Yeah, so that is what I’m confused about. If I set a vmin and a vmax, won’t it just ‘rescale’ the colours? But that would then be wrong, would it not? Because the probability densities calculated by hist2d will now be changed.

Yeah, so that is what I’m confused about. If I set a vmin and a vmax, won’t it just ‘rescale’ the colours? But that would then be wrong, would it not? Because the probability densities calculated by hist2d will now be changed.

The data is not changed. Its just mapped into the colormap in a consistent way. In plot 1 if you have the value 10.1 and it is green, you want the same value to be green in plot 2, right? The way you do that is using the same norms across the plots. If you want the data to be mapped differently between the plots, create two norms and pass different vmin and vmax.

Ah, okay, I think I misunderstood what the Normalisation did. Thanks!

@physkets Can you take a look at https://github.com/matplotlib/matplotlib/pull/18487 and comment if that text would have helped you?

Ya, I think this part makes it bit more clear:

This allows us to fully independently pick what colors to use (by
selecting the colormap), what data range to show (via the vmin and vmax attributes on .Normalize, or via the .cm.ScalarMappable.set_clim method),