• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

colour-science / colour / 18370061804

09 Oct 2025 08:19AM UTC coverage: 76.753% (-22.6%) from 99.349%
18370061804

push

github

KelSolaar
Merge branch 'feature/v0.4.7' into develop

32663 of 42556 relevant lines covered (76.75%)

0.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.83
/colour/plotting/characterisation.py
1
"""
2
Characterisation Plotting
3
=========================
4

5
Define the characterisation plotting objects.
6

7
-   :func:`colour.plotting.plot_single_colour_checker`
8
-   :func:`colour.plotting.plot_multi_colour_checkers`
9
"""
10

11
from __future__ import annotations
×
12

13
import typing
×
14

15
if typing.TYPE_CHECKING:
16
    from matplotlib.figure import Figure
17
    from matplotlib.axes import Axes
18

19
import numpy as np
×
20

21
if typing.TYPE_CHECKING:
22
    from colour.characterisation import ColourChecker
23
    from colour.hints import Any, Dict, Sequence, Tuple
24

25
from colour.models import xyY_to_XYZ
×
26
from colour.plotting import (
×
27
    CONSTANTS_COLOUR_STYLE,
28
    ColourSwatch,
29
    XYZ_to_plotting_colourspace,
30
    artist,
31
    filter_colour_checkers,
32
    override_style,
33
    plot_multi_colour_swatches,
34
    render,
35
)
36
from colour.utilities import attest
×
37

38
__author__ = "Colour Developers"
×
39
__copyright__ = "Copyright 2013 Colour Developers"
×
40
__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
×
41
__maintainer__ = "Colour Developers"
×
42
__email__ = "colour-developers@colour-science.org"
×
43
__status__ = "Production"
×
44

45
__all__ = [
×
46
    "plot_single_colour_checker",
47
    "plot_multi_colour_checkers",
48
]
49

50

51
@override_style(
×
52
    **{
53
        "axes.grid": False,
54
        "xtick.bottom": False,
55
        "ytick.left": False,
56
        "xtick.labelbottom": False,
57
        "ytick.labelleft": False,
58
    }
59
)
60
def plot_single_colour_checker(
×
61
    colour_checker: (ColourChecker | str) = "ColorChecker24 - After November 2014",
62
    **kwargs: Any,
63
) -> Tuple[Figure, Axes]:
64
    """
65
    Plot the specified colour checker.
66

67
    Parameters
68
    ----------
69
    colour_checker
70
        Colour checker to plot. ``colour_checker`` can be of any type or
71
        form supported by the
72
        :func:`colour.plotting.common.filter_colour_checkers` definition.
73

74
    Other Parameters
75
    ----------------
76
    kwargs
77
        {:func:`colour.plotting.artist`,
78
        :func:`colour.plotting.plot_multi_colour_swatches`,
79
        :func:`colour.plotting.render`},
80
        See the documentation of the previously listed definitions.
81

82
    Returns
83
    -------
84
    :class:`tuple`
85
        Current figure and axes.
86

87
    Examples
88
    --------
89
    >>> plot_single_colour_checker("ColorChecker 2005")  # doctest: +ELLIPSIS
90
    (<Figure size ... with 1 Axes>, <...Axes...>)
91

92
    .. image:: ../_static/Plotting_Plot_Single_Colour_Checker.png
93
        :align: center
94
        :alt: plot_single_colour_checker
95
    """
96

97
    return plot_multi_colour_checkers([colour_checker], **kwargs)
1✔
98

99

100
@override_style(
×
101
    **{
102
        "axes.grid": False,
103
        "xtick.bottom": False,
104
        "ytick.left": False,
105
        "xtick.labelbottom": False,
106
        "ytick.labelleft": False,
107
    }
108
)
109
def plot_multi_colour_checkers(
×
110
    colour_checkers: ColourChecker | str | Sequence[ColourChecker | str],
111
    **kwargs: Any,
112
) -> Tuple[Figure, Axes]:
113
    """
114
    Plot and compare the specified colour checkers.
115

116
    Parameters
117
    ----------
118
    colour_checkers
119
        Colour checkers to plot, count must be less than or equal to 2.
120
        ``colour_checkers`` elements can be of any type or form supported
121
        by the :func:`colour.plotting.common.filter_colour_checkers`
122
        definition.
123

124
    Other Parameters
125
    ----------------
126
    kwargs
127
        {:func:`colour.plotting.artist`,
128
        :func:`colour.plotting.plot_multi_colour_swatches`,
129
        :func:`colour.plotting.render`},
130
        See the documentation of the previously listed definitions.
131

132
    Returns
133
    -------
134
    :class:`tuple`
135
        Current figure and axes.
136

137
    Examples
138
    --------
139
    >>> plot_multi_colour_checkers(["ColorChecker 1976", "ColorChecker 2005"])
140
    ... # doctest: +ELLIPSIS
141
    (<Figure size ... with 1 Axes>, <...Axes...>)
142

143
    .. image:: ../_static/Plotting_Plot_Multi_Colour_Checkers.png
144
        :align: center
145
        :alt: plot_multi_colour_checkers
146
    """
147

148
    filtered_colour_checkers = list(filter_colour_checkers(colour_checkers).values())
1✔
149

150
    attest(
1✔
151
        len(filtered_colour_checkers) <= 2,
152
        "Only two colour checkers can be compared at a time!",
153
    )
154

155
    _figure, axes = artist(**kwargs)
1✔
156

157
    compare_swatches = len(filtered_colour_checkers) == 2
1✔
158

159
    column_counts = []
1✔
160
    colour_swatches = []
1✔
161
    colour_checker_names = []
1✔
162
    for colour_checker in filtered_colour_checkers:
1✔
163
        colour_checker_names.append(colour_checker.name)
1✔
164
        column_counts.append(colour_checker.columns)
1✔
165
        for label, xyY in colour_checker.data.items():
1✔
166
            XYZ = xyY_to_XYZ(xyY)
1✔
167
            RGB = XYZ_to_plotting_colourspace(XYZ, colour_checker.illuminant)
1✔
168
            colour_swatches.append(
1✔
169
                ColourSwatch(np.clip(np.ravel(RGB), 0, 1), label.title())
170
            )
171

172
    columns = np.unique(column_counts)
1✔
173
    attest(len(columns) == 1)
1✔
174

175
    if compare_swatches:
1✔
176
        colour_swatches = [
1✔
177
            swatch
178
            for pairs in zip(
179
                colour_swatches[0 : len(colour_swatches) // 2],
180
                colour_swatches[len(colour_swatches) // 2 :],
181
                strict=True,
182
            )
183
            for swatch in pairs
184
        ]
185

186
    background_colour = "0.1"
1✔
187
    width = height = 1.0
1✔
188
    spacing = 0.25
1✔
189

190
    settings: Dict[str, Any] = {
1✔
191
        "axes": axes,
192
        "width": width,
193
        "height": height,
194
        "spacing": spacing,
195
        "columns": columns,
196
        "direction": "-y",
197
        "text_kwargs": {"size": 8},
198
        "background_colour": background_colour,
199
        "compare_swatches": "Stacked" if compare_swatches else None,
200
    }
201
    settings.update(kwargs)
1✔
202
    settings["show"] = False
1✔
203

204
    plot_multi_colour_swatches(colour_swatches, **settings)
1✔
205

206
    axes.text(
1✔
207
        0.5,
208
        0.005,
209
        (
210
            f"{', '.join(colour_checker_names)} - "
211
            f"{CONSTANTS_COLOUR_STYLE.colour.colourspace.name} - "
212
            f"Colour Rendition Chart"
213
        ),
214
        transform=axes.transAxes,
215
        color=CONSTANTS_COLOUR_STYLE.colour.bright,
216
        ha="center",
217
        va="bottom",
218
        zorder=CONSTANTS_COLOUR_STYLE.zorder.midground_label,
219
    )
220

221
    settings.update(
1✔
222
        {
223
            "axes": axes,
224
            "show": True,
225
            "title": ", ".join(colour_checker_names),
226
        }
227
    )
228
    settings.update(kwargs)
1✔
229

230
    return render(**settings)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc