The ColorManager#
The ColorManager can take care of setting up a colormap, a corresponding normalization, and assists in drawing colorbars.
Its aim is to make the matplotlib.colors module accessible via the configuration.
For instance, specifying a colormap, norm and vmin/vmax can be done like this:
cmap:
name: magma
under: grey
over: white
bad: red
norm:
name: LogNorm
vmin: 1
vmax: 10
In the corresponding output plot, data points that go beyond vmax are shown in white, and those that cannot be represented with the custom LogNorm are shown as “bad” values in red:
Integration#
In order to make full use of the ColorManager’s capabilities, it needs to be integrated in the following way:
Depending on your use case, divert the
cmap,norm,vmin,vmaxand colorbar label arguments to initialize aColorManager.Where you would typically use the
cmapandnormarguments passed through, use the corresponding propertiesColorManager.cmapandColorManager.norminstead.Instead of creating the colorbar yourself, use the
ColorManager.create_cbar()method, which knows about the custom colorbar labels.
This may look as follows:
from dantro.plot import ColorManager
def my_scatter_func(
x,
y,
*,
c,
ax,
cmap=None,
norm=None,
vmin: float = None,
vmax: float = None,
cbar_labels: Union[list, dict] = None,
cbar_kwargs: dict = {},
**scatter_kwargs,
):
"""This plot function illustrates ColorManager integration"""
# Set up the ColorManager
cm = ColorManager(
cmap=cmap, norm=norm, vmin=vmin, vmax=vmax, labels=cbar_labels
)
# Now plot, passing the corresponding cmap and norm arguments ...
scatter = ax.scatter(
x,
y,
c=c,
cmap=cm.cmap,
norm=cm.norm,
**scatter_kwargs,
)
# ... and let the ColorManager create the colorbar
cbar = cm.create_cbar(
scatter,
**cbar_kwargs,
)
return scatter, cbar
Note
If you are not in control of the colorbar — or are not using one — you can also use parse_cmap_and_norm_kwargs(), which will extract the relevant arguments to initialize a ColorManager and return the resolved colormap and norm object.
In that case, the labels argument will not have any effect.
Examples#
The following examples use a YAML representation for the parameters.
Specifying colormap and vmin/vmax#
Directly specifying a colormap by name and the boundaries for the norm (falling back to the default Normalize):
cmap:
name: viridis
# ... can have more arguments here
vmin: 0
vmax: 10
Extreme values#
Can also specify colormap extreme values and a custom norm:
cmap:
name: magma
under: grey
over: white
bad: red
norm:
name: LogNorm
vmin: 1
vmax: 10
Note how the “bad” values are shown in red while values that go beyond vmax are shown in white.
The extend argument for ColorManager.create_cbar() can be used to control whether these colors are shown at the top or bottom of the colorbar.
By default, the method inspects whether extreme values are set in the colormap and shows them and selects the fitting visualization automatically.
Custom norm#
The norm argument can be used to select a custom Normalize-derived normalization class.
Arguments can simply be passed through.
Available norms are specified in NORMS.
cmap:
name: coolwarm
over: red
under: blue
norm:
name: TwoSlopeNorm
vcenter: 0
vmin: -5
vmax: 10
Segmented colormaps#
It is easy to specify a ListedColormap using the cmap.from_values argument; the keys of that dictionary specify the positions of the segments.
The segments can either be centered around the values specified as keys or be given explicitly as the left and right edges of the respective segments.
Inferred edges#
When using scalar keys (0, 1, 4 here), the bin edges are inferred automatically:
cmap:
from_values:
0: r
1: g
4: b
bad: w
over: w
under: w
labels:
0: foo
1: bar
4: baz
Note
If using irregular distances between bins (as done above), the label position will not appear centered.
However, the label position can be adjusted separately via the keys of labels.
Custom bin edges#
A segmented colormap with custom bin edges, achieved by passing the boundaries via 2-tuple-like keys:
cmap:
from_values:
[-.5, 0.5]: r
[0.5, 1.5]: ~ # None → will use placeholder color
[1.5, 4.5]: b
placeholder_color: w # default: white
Note
If passing labels here as well, they would still need scalar keys for their position.
Labels and colors (shorthand syntax)#
There is a shorthand syntax for specifying labels and the corresponding colors via a single mapping (see the cmap argument labels_and_colors below).
Here, the corresponding values are inferred from the size of the mapping and vmin and/or vmax.
There
Implicit syntax#
cmap:
first: green
second: blue
third: red
fourth: orange
# can also specify extremes here
under: k
over: w
Explicit syntax#
To avoid name clashes between labels and valid colormap arguments (those specified in ColorManager._POSSIBLE_CMAP_KWARGS), a more explicit syntax can be used:
cmap:
labels_and_colors:
# can use restricted labels here
name: green
colors: blue
reversed: red
gamma: orange
under: k
over: w
Custom vmin/vmax#
In cases where the inferred integer range of the labels should not start at zero, simply define vmin and/or vmax.
cmap:
first: green
second: blue
third: red
fourth: orange
under: k
over: w
vmin: 2
vmax: ~
Skipping values#
If some values should not be associated with a color, they can be skipped:
cmap:
first: green
second: blue
" ": ~
fourth: orange
" ": ~
under: k
over: w
Note
In order for the labels to not be shown at all, use spaces as the key of the labels_and_colors mapping.
Take care to use unique mapping keys, e.g. by using different numbers of spaces.
Continuous colormaps#
A continous colormap with linearly interpolated colors (LinearSegmentedColormap) can also easily be specified:
cmap:
continuous: true
from_values:
0: '#EC7070'
0.5: '#EC9F7E'
1: black
under: grey
over: white
vmin: 0
vmax: 10
With boundaries#
This can still be combined with the matplotlib.colors.BoundaryNorm:
cmap:
continuous: true
from_values:
0: "#EC7070"
0.5: "#EC9F7E"
1: black
under: grey
over: white
bad: red
norm:
name: BoundaryNorm
ncolors: 256
boundaries: [-2, 2, 6, 8, 9, 10]
Note
The matplotlib.colors.BoundaryNorm does not include the upper boundary.
Alpha values for extremes#
Specifying color and alpha for the extremes is also possible:
cmap:
name: viridis
under:
color: blue
alpha: 0.5
over:
color: red
alpha: 0.5
bad: darkred
Seaborn color maps#
It is also possible to use seaborn colormaps, which opens up many new possibilities to define colormaps. These fall into three categories:
Named colormaps like
icefirethat are available after seaborn was imported (which it is when theColorManageris invoked).Color palettes defined via
seaborn.color_palette().Divering colormaps constructed via
seaborn.diverging_palette().
The latter two use a prefix syntax for the name argument: To use those modes, use a name argument that starts with color_palette:: or diverging::, respectively, followed by the corresponding arguments.
More information and examples below.
Color palettes#
cmap:
name: color_palette::light:#69d
vmin: 0
vmax: 10
More examples:
color_palette::YlOrBr
color_palette::icefire
color_palette::icefire_r # reversed
color_palette::light:b # white -> blue
color_palette::dark:b # black -> blue
color_palette::light:#69d # custom color
color_palette::light:#69d_r # custom color reversed
color_palette::dark:salmon_r # named colormap reversed
color_palette::ch:s=-.2,r=.6 # cubehelix with parameters
Hint
You may have to put these prefixed strings into quotes to avoid YAML interpreting them as mappings.
Diverging palettes#
By default, seaborn.diverging_palette() does not offer the expanded string-based syntax that seaborn.color_palette() supports.
However, the ColorManager has that functionality.
cmap:
name: diverging::250, 30, l=65, center=dark
under: w
over: w
vmin: -5
vmax: +5
More examples:
diverging::220,20
diverging::145,300,s=60
diverging::250, 30, l=65, center=dark
API Reference#
Below, an excerpt from the ColorManager API is shown.
ColorManager.__init__#
- ColorManager.__init__(*, cmap: str | dict | list | Colormap | None = None, norm: str | dict | Normalize | None = None, labels: List[str] | Dict[float, str] | None = None, vmin: float | None = None, vmax: float | None = None, discretized: bool | None = None)[source]
Initializes a
ColorManagerby building the colormap, the norm, and the colorbar labels.Refer to the dedicated documentation page for examples and integration instructions.
- Parameters:
cmap (Union[str, dict, list, Colormap], optional) –
The colormap specification. If this is not already a
matplotlib.colors.Colormapinstance, it will be parsed into a dict-like specification, which has the options as shown below.If
cmapis a string, it is turned intodict(name=cmap).If
cmapis a list (or tuple), it will be converted todict(from_values=cmap), creating a segmented colormap. See below for more information.
In dict form, the following arguments are available:
name(str, optional):Name of a registered matplotlib colormap or None to use a default. For available colormap names, see here.
Also supports seaborn colormaps. If the name starts with the
_SNS_COLOR_PALETTE_PREFIXstring,seaborn.color_palette()is used to generate the colormap. If starting with_SNS_DIVERGING_PALETTE_PREFIX,seaborn.diverging_palette()is invoked, using argument specified as part of thename.This opens many possibilities, as shown in the seaborn documentation. For example:
color_palette::YlOrBr color_palette::icefire color_palette::icefire_r # reversed color_palette::light:b # white -> blue color_palette::dark:b # black -> blue color_palette::light:#69d # custom color color_palette::light:#69d_r # ... reversed color_palette::dark:salmon_r # named, reversed color_palette::ch:s=-.2,r=.6 # cubehelix diverging::220,20 diverging::145,300,s=60 diverging::250, 30, l=65, center=dark
Here, the
ch:<key>=<val>,<key>=<val>syntax is used to create aseaborn.cubehelix_palette(). The same<arg>,<arg>,<key>=<val>,<key>=<val>syntax is used for the diverging palette.Note
When specifying these via YAML, make sure to put the string into single or double quotes to avoid it being interpreted as a YAML mapping.
from_values(Union[dict, list], optional):Dict of colors keyed by bin-specifier. If given,
nameis ignored and a discrete colormap is created from the list of specified colors. Thenormis then set tomatplotlib.colors.BoundaryNorm.The bins can be specified either by bin-centers (Scalar) or by bin-intervals (2-tuples). For the former, the deduced bin-edges are assumed halfway between the bin-centers. For the latter, the given intervals must be pairwise connected. In both cases, the bins must monotonically increase.
If a list of colors is passed they are automatically assigned to the bin-centers
[0, 1, 2, ...], potentially shifted depending onvminandvmax. Inferring these values is done in_infer_pos_map().Alternatively, a continuous, linearly interpolated colormap can be generated by setting the
continuousflag, see below. This will construct aLinearSegmentedColormap. In such a case, keys infrom_valuescan only be scalar, bin intervals cannot be specified.continuous(bool, optional):If True, will interpret the
from_valuesdata as specifying points between which a linear interpolation is carried out. Will create aLinearSegmentedColormap.under(Union[str, dict], optional):Passed on to
set_under()over(Union[str, dict], optional):Passed on to
set_over()bad(Union[str, dict], optional):Passed on to
set_bad()placeholder_color(str, optional):Nonevalues infrom_valuesare replaced with this color (default: white).reversed(bool, optional):If True, will reverse the colormap.
labels_and_colors(dict, optional):This is a shorthand syntax for specifying colorbar labels and colors at the same time. Keys refer to labels, values to colors. The label positions and bounds are inferred using
_infer_pos_map()and are affected byvminandvmax. These may also be given implicitly via**kwargs(see below), but not at the same time!Effectively, the mapping is unpacked into two parts: The keys are used to specify the values of the
labelsdict (on the top-level); the values are used to specify the values of thecmap.from_valuesdict (see above). The keys are inferred from the length of the sequence andvminandvmax, expecting to map to an integer data positions.Example:
cmap: empty: darkkhaki # -> 0 susceptible: forestgreen # -> 1 exposed: darkorange # ... infected: firebrick recovered: slategray deceased: black source: maroon inert: moccasin # -> 7 # can still set extremes here (should not appear) under: red over: red
**kwargs(optional):Depending on the argument names, these are either passed to colormap instantiation or are used to specify the
labels_and_colorsmapping. For the latter, labels may not be named after arguments that are relevant for colormap initialization (_POSSIBLE_CMAP_KWARGS).
norm (Union[str, dict, Normalize], optional) – The norm that is applied for the color-mapping. If it is a string, the matching norm in
matplotlib.colorsis created with default values. If it is a dict, thenameentry specifies the norm and all further entries are passed to its constructor. Overwritten if a discrete colormap is specified viacmap.from_values.labels (Union[List[str], Dict[float, str]], optional) – Colorbar tick-labels keyed by tick position. If a list of labels is passed they are automatically assigned to the positions
[0, 1, 2, ...](if novminandvmaxare given) or[vmin, vmin + 1, ..., vmax]otherwise.vmin (float, optional) – The lower bound of the color-mapping. Not passed to
matplotlib.colors.BoundaryNorm, which does not support it. If given, this argument in combination withvmaxneeds to define an integer range that has the same number of values as needed for a colormap constructed fromfrom_valuesor via thelabel -> colormapping. Ifdiscretizedis set, this value will be set toceil(vmin) - 0.5.vmax (float, optional) – The upper bound of the color-mapping. Not passed to
matplotlib.colors.BoundaryNorm, which does not support it. If given, this argument in combination withvminneeds to define an integer range that has the same number of values as needed for a colormap constructed fromfrom_valuesor via thelabel -> colormapping. Ifdiscretizedis set, this value will be set tofloor(vmax) + 0.5.discretized (bool, optional) – If True, assumes that the data this colormap is to represent only has integer values and makes a number of changes to improve the overall visualization. For instance, if
True, thevminandvmaxvalues will be set to the appropriate half-integer such that tick positions are centered within the corresponding range. IfNone(default), will do this automatically if a colormap is constructed viafrom_valuesor vialabel -> colormapping.
ColorManager.create_cbar#
- ColorManager.create_cbar(mappable: _ScalarMappable, *, fig: Figure | None = None, ax: Axes | None = None, label: str | None = None, label_kwargs: dict | None = None, tick_params: dict | None = None, extend: str = 'auto', **cbar_kwargs) Colorbar[source]
Creates a colorbar of a given mappable
- Parameters:
mappable (ScalarMappable) – The mappable that is to be described by the colorbar.
fig (Figure, optional) – The figure; if not given, will use the current figure as determined by
gcf().ax (Axes, optional) – The axes; if not given, will use the one given by
matplotlib.figure.Figure.gca().label (str, optional) – A label for the colorbar
label_kwargs (dict, optional) – Additional parameters passed to
matplotlib.colorbar.Colorbar.set_label()tick_params (dict, optional) – Set colorbar tick parameters via the
matplotlib.axes.Axes.tick_params()method of thematplotlib.colorbar.Colorbaraxes.extend (str, optional) – Whether to extend the colorbar axis to show the
underandovervalues. Ifauto(default), will inspect whether the colormap has these values set and decide accordingly. Can also be set manually, possible values beingneither,min,max, andboth.**cbar_kwargs – Passed on to
matplotlib.figure.Figure.colorbar()
- Returns:
The created colorbar object
- Return type:
parse_cmap_and_norm_kwargs#
- parse_cmap_and_norm_kwargs(*, _key_map: dict | None = None, use_color_manager: bool = True, **kws) dict[source]
A function that parses colormap-related keyword arguments and passes them through the
ColorManager, making its functionality available in places that would otherwise not be able to use the expanded syntax of the color manager.Note
The resulting dict will only have the
cmapandcbarkwargs (or their mapped equivalents) set from the color manager, all other arguments are simply passed through.In particular, this means that the
labelsfeature of the color manager is not supported, because this function has no ability to set the colorbar.- Parameters:
_key_map (dict, optional) – If custom keyword argument keys are expected as output, e.g.
hue_cmapinstead ofcmap, set the values to these custom names:{"cmap": "hue_cmap"}. Expected keys arecmap,norm,vmin,vmax. If not set or partially not set, will use defaults.use_color_manager (bool, optional) – If false, will simply pass through
**kws – Keyword arguments to parse
- Returns:
The updated keyword arguments with
cmapandnorm(or equivalent keys according to_key_map).- Return type: