The ColorManager
Contents
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
,vmax
and colorbar label arguments to initialize aColorManager
.Where you would typically use the
cmap
andnorm
arguments passed through, use the corresponding propertiesColorManager.cmap
andColorManager.norm
instead.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
icefire
that are available after seaborn was imported (which it is when theColorManager
is 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: Optional[Union[str, dict, list, Colormap]] = None, norm: Optional[Union[str, dict, Normalize]] = None, labels: Optional[Union[List[str], Dict[float, str]]] = None, vmin: Optional[float] = None, vmax: Optional[float] = None, discretized: Optional[bool] = None)[source]
Initializes a
ColorManager
by 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.Colormap
instance, it will be parsed into a dict-like specification, which has the options as shown below.If
cmap
is a string, it is turned intodict(name=cmap)
.If
cmap
is 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_PREFIX
string,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,
name
is ignored and a discrete colormap is created from the list of specified colors. Thenorm
is 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 onvmin
andvmax
. Inferring these values is done in_infer_pos_map()
.Alternatively, a continuous, linearly interpolated colormap can be generated by setting the
continuous
flag, see below. This will construct aLinearSegmentedColormap
. In such a case, keys infrom_values
can only be scalar, bin intervals cannot be specified.continuous
(bool, optional):If True, will interpret the
from_values
data 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):None
values infrom_values
are 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 byvmin
andvmax
. 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
labels
dict (on the top-level); the values are used to specify the values of thecmap.from_values
dict (see above). The keys are inferred from the length of the sequence andvmin
andvmax
, 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_colors
mapping. 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.colors
is created with default values. If it is a dict, thename
entry 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 novmin
andvmax
are 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 withvmax
needs to define an integer range that has the same number of values as needed for a colormap constructed fromfrom_values
or via thelabel -> color
mapping. Ifdiscretized
is 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 withvmin
needs to define an integer range that has the same number of values as needed for a colormap constructed fromfrom_values
or via thelabel -> color
mapping. Ifdiscretized
is 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
, thevmin
andvmax
values 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_values
or vialabel -> color
mapping.
ColorManager.create_cbar
#
- ColorManager.create_cbar(mappable: ScalarMappable, *, fig: Optional[Figure] = None, ax: Optional[Axes] = None, label: Optional[str] = None, label_kwargs: Optional[dict] = None, tick_params: Optional[dict] = 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.Colorbar
axes.extend (str, optional) – Whether to extend the colorbar axis to show the
under
andover
values. 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: Optional[dict] = 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
cmap
andcbar
kwargs (or their mapped equivalents) set from the color manager, all other arguments are simply passed through.In particular, this means that the
labels
feature 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_cmap
instead 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
cmap
andnorm
(or equivalent keys according to_key_map
).- Return type