• 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

78.4
/colour/plotting/section.py
1
"""
2
Gamut Section Plotting
3
======================
4

5
Define the gamut section plotting objects.
6

7
-   :func:`colour.plotting.section.plot_hull_section_colours`
8
-   :func:`colour.plotting.section.plot_hull_section_contour`
9
-   :func:`colour.plotting.plot_visible_spectrum_section`
10
-   :func:`colour.plotting.plot_RGB_colourspace_section`
11
"""
12

13
from __future__ import annotations
×
14

15
import typing
×
16

17
import numpy as np
×
18

19
if typing.TYPE_CHECKING:
20
    from matplotlib.axes import Axes
21

22
from matplotlib.collections import LineCollection
×
23

24
if typing.TYPE_CHECKING:
25
    from matplotlib.figure import Figure
26

27
from matplotlib.patches import Polygon
×
28

29
from colour.colorimetry import (
×
30
    MultiSpectralDistributions,
31
    SpectralDistribution,
32
    SpectralShape,
33
    reshape_msds,
34
)
35
from colour.geometry import hull_section, primitive_cube
×
36
from colour.graph import convert
×
37

38
if typing.TYPE_CHECKING:
39
    from colour.hints import (
40
        Any,
41
        ArrayLike,
42
        Dict,
43
        Literal,
44
        LiteralColourspaceModel,
45
        LiteralRGBColourspace,
46
        Sequence,
47
        Tuple,
48
    )
49

50
from colour.hints import Real, cast
×
51
from colour.models import (
×
52
    COLOURSPACE_MODELS_AXIS_LABELS,
53
    COLOURSPACE_MODELS_DOMAIN_RANGE_SCALE_1_TO_REFERENCE,
54
    RGB_Colourspace,
55
    RGB_to_XYZ,
56
)
57
from colour.notation import HEX_to_RGB
×
58
from colour.plotting import (
×
59
    CONSTANTS_COLOUR_STYLE,
60
    XYZ_to_plotting_colourspace,
61
    artist,
62
    colourspace_model_axis_reorder,
63
    filter_cmfs,
64
    filter_illuminants,
65
    filter_RGB_colourspaces,
66
    override_style,
67
    render,
68
)
69
from colour.utilities import (
×
70
    CanonicalMapping,
71
    as_int_array,
72
    first_item,
73
    full,
74
    optional,
75
    required,
76
    suppress_warnings,
77
    tstack,
78
    validate_method,
79
)
80
from colour.volume import solid_RoschMacAdam
×
81

82
__author__ = "Colour Developers"
×
83
__copyright__ = "Copyright 2013 Colour Developers"
×
84
__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
×
85
__maintainer__ = "Colour Developers"
×
86
__email__ = "colour-developers@colour-science.org"
×
87
__status__ = "Production"
×
88

89
__all__ = [
×
90
    "MAPPING_AXIS_TO_PLANE",
91
    "plot_hull_section_colours",
92
    "plot_hull_section_contour",
93
    "plot_visible_spectrum_section",
94
    "plot_RGB_colourspace_section",
95
]
96

97
MAPPING_AXIS_TO_PLANE: CanonicalMapping = CanonicalMapping(
×
98
    {"+x": (1, 2), "+y": (0, 2), "+z": (0, 1)}
99
)
100
MAPPING_AXIS_TO_PLANE.__doc__ = """
×
101
Mapping from axes to their orthogonal planes.
102

103
Maps each positive axis ('+x', '+y', '+z') to the indices of the two
104
dimensions that form the perpendicular plane in 3D space.
105
"""
106

107

108
@required("trimesh")
×
109
@override_style()
×
110
def plot_hull_section_colours(
×
111
    hull: trimesh.Trimesh,  # pyright: ignore  # noqa: F821
112
    model: LiteralColourspaceModel | str = "CIE xyY",
113
    axis: Literal["+z", "+x", "+y"] | str = "+z",
114
    origin: float = 0.5,
115
    normalise: bool = True,
116
    section_colours: ArrayLike | str | None = None,
117
    section_opacity: float = 1,
118
    convert_kwargs: dict | None = None,
119
    samples: int = 256,
120
    **kwargs: Any,
121
) -> Tuple[Figure, Axes]:
122
    """
123
    Plot the section colours of the specified *trimesh* hull along the
124
    specified axis and origin.
125

126
    Parameters
127
    ----------
128
    hull
129
        *Trimesh* hull.
130
    model
131
        Colourspace model, see :attr:`colour.COLOURSPACE_MODELS` attribute
132
        for the list of supported colourspace models.
133
    axis
134
        Axis the hull section will be normal to.
135
    origin
136
        Coordinate along ``axis`` at which to plot the hull section.
137
    normalise
138
        Whether to normalise ``axis`` to the extent of the hull along it.
139
    section_colours
140
        Colours of the hull section, if ``section_colours`` is set to *RGB*,
141
        the colours will be computed using the corresponding coordinates.
142
    section_opacity
143
        Opacity of the hull section colours.
144
    convert_kwargs
145
        Keyword arguments for the :func:`colour.convert` definition.
146
    samples
147
        Sample count on one axis when computing the hull section colours.
148

149
    Other Parameters
150
    ----------------
151
    kwargs
152
        {:func:`colour.plotting.artist`,
153
        :func:`colour.plotting.render`},
154
        See the documentation of the previously listed definitions.
155

156
    Returns
157
    -------
158
    :class:`tuple`
159
        Current figure and axes.
160

161
    Examples
162
    --------
163
    >>> from colour.models import RGB_COLOURSPACE_sRGB
164
    >>> from colour.utilities import is_trimesh_installed
165
    >>> vertices, faces, _outline = primitive_cube(1, 1, 1, 64, 64, 64)
166
    >>> XYZ_vertices = RGB_to_XYZ(vertices["position"] + 0.5, RGB_COLOURSPACE_sRGB)
167
    >>> if is_trimesh_installed:
168
    ...     from trimesh import Trimesh
169
    ...
170
    ...     hull = Trimesh(XYZ_vertices, faces, process=False)
171
    ...     plot_hull_section_colours(hull, section_colours="RGB")
172
    ...     # doctest: +ELLIPSIS
173
    (<Figure size ... with 1 Axes>, <...Axes...>)
174

175
    .. image:: ../_static/Plotting_Plot_Hull_Section_Colours.png
176
        :align: center
177
        :alt: plot_hull_section_colours
178
    """
179

180
    axis = validate_method(
1✔
181
        axis,
182
        ("+z", "+x", "+y"),
183
        '"{0}" axis is invalid, it must be one of {1}!',
184
    )
185

186
    hull = hull.copy()
1✔
187

188
    settings: Dict[str, Any] = {"uniform": True}
1✔
189
    settings.update(kwargs)
1✔
190

191
    _figure, axes = artist(**settings)
1✔
192

193
    section_colours = optional(
1✔
194
        section_colours, HEX_to_RGB(CONSTANTS_COLOUR_STYLE.colour.average)
195
    )
196

197
    convert_kwargs = optional(convert_kwargs, {})
1✔
198

199
    # Luminance / Lightness reordered along "z" axis.
200
    with suppress_warnings(python_warnings=True):
1✔
201
        ijk_vertices = colourspace_model_axis_reorder(
1✔
202
            convert(hull.vertices, "CIE XYZ", model, **convert_kwargs), model
203
        )
204
        ijk_vertices = np.nan_to_num(ijk_vertices)
1✔
205
        ijk_vertices *= COLOURSPACE_MODELS_DOMAIN_RANGE_SCALE_1_TO_REFERENCE[model]
1✔
206

207
    hull.vertices = ijk_vertices
1✔
208

209
    if axis == "+x":
1✔
210
        index_origin = 0
1✔
211
    elif axis == "+y":
1✔
212
        index_origin = 1
1✔
213
    elif axis == "+z":
1✔
214
        index_origin = 2
1✔
215
    plane = MAPPING_AXIS_TO_PLANE[axis]
1✔
216

217
    section = hull_section(hull, axis, origin, normalise)
1✔
218

219
    padding = 0.1 * np.mean(COLOURSPACE_MODELS_DOMAIN_RANGE_SCALE_1_TO_REFERENCE[model])
1✔
220
    min_x = np.min(ijk_vertices[..., plane[0]]) - padding
1✔
221
    max_x = np.max(ijk_vertices[..., plane[0]]) + padding
1✔
222
    min_y = np.min(ijk_vertices[..., plane[1]]) - padding
1✔
223
    max_y = np.max(ijk_vertices[..., plane[1]]) + padding
1✔
224
    extent = (min_x, max_x, min_y, max_y)
1✔
225

226
    use_RGB_section_colours = str(section_colours).upper() == "RGB"
1✔
227
    if use_RGB_section_colours:
1✔
228
        ii, jj = np.meshgrid(
1✔
229
            np.linspace(min_x, max_x, samples),
230
            np.linspace(max_y, min_y, samples),
231
        )
232
        ij = tstack([ii, jj])
1✔
233
        ijk_section = full(
1✔
234
            (samples, samples, 3),
235
            cast("Real", np.median(section[..., index_origin])),
236
        )
237
        ijk_section[..., plane] = ij
1✔
238
        ijk_section /= COLOURSPACE_MODELS_DOMAIN_RANGE_SCALE_1_TO_REFERENCE[model]
1✔
239
        XYZ_section = convert(
1✔
240
            colourspace_model_axis_reorder(ijk_section, model, "Inverse"),
241
            model,
242
            "CIE XYZ",
243
            **convert_kwargs,
244
        )
245
        RGB_section = XYZ_to_plotting_colourspace(XYZ_section)
1✔
246
    else:
247
        section_colours = np.hstack([section_colours, section_opacity])
1✔
248

249
    facecolor = "none" if use_RGB_section_colours else section_colours
1✔
250
    polygon = Polygon(
1✔
251
        section[..., plane],
252
        facecolor=facecolor,
253
        edgecolor="none",
254
        zorder=CONSTANTS_COLOUR_STYLE.zorder.background_polygon,
255
    )
256
    axes.add_patch(polygon)
1✔
257

258
    if use_RGB_section_colours:
1✔
259
        image = axes.imshow(
1✔
260
            np.clip(RGB_section, 0, 1),
261
            interpolation="bilinear",
262
            extent=extent,
263
            clip_path=None,
264
            alpha=section_opacity,
265
            zorder=CONSTANTS_COLOUR_STYLE.zorder.background_polygon,
266
        )
267
        image.set_clip_path(polygon)
1✔
268

269
    settings = {
1✔
270
        "axes": axes,
271
        "bounding_box": extent,
272
    }
273
    settings.update(kwargs)
1✔
274

275
    return render(**settings)
1✔
276

277

278
@required("trimesh")
×
279
@override_style()
×
280
def plot_hull_section_contour(
×
281
    hull: trimesh.Trimesh,  # pyright: ignore  # noqa: F821
282
    model: LiteralColourspaceModel | str = "CIE xyY",
283
    axis: Literal["+z", "+x", "+y"] | str = "+z",
284
    origin: float = 0.5,
285
    normalise: bool = True,
286
    contour_colours: ArrayLike | str | None = None,
287
    contour_opacity: float = 1,
288
    convert_kwargs: dict | None = None,
289
    **kwargs: Any,
290
) -> Tuple[Figure, Axes]:
291
    """
292
    Plot the section contour of the specified *trimesh* hull along the
293
    specified axis and origin.
294

295
    Parameters
296
    ----------
297
    hull
298
        *Trimesh* hull.
299
    model
300
        Colourspace model, see :attr:`colour.COLOURSPACE_MODELS` attribute
301
        for the list of supported colourspace models.
302
    axis
303
        Axis the hull section will be normal to.
304
    origin
305
        Coordinate along ``axis`` at which to plot the hull section.
306
    normalise
307
        Whether to normalise ``axis`` to the extent of the hull along it.
308
    contour_colours
309
        Colours of the hull section contour, if ``contour_colours`` is set
310
        to *RGB*, the colours will be computed using the corresponding
311
        coordinates.
312
    contour_opacity
313
        Opacity of the hull section contour.
314
    convert_kwargs
315
        Keyword arguments for the :func:`colour.convert` definition.
316

317
    Other Parameters
318
    ----------------
319
    kwargs
320
        {:func:`colour.plotting.artist`,
321
        :func:`colour.plotting.render`},
322
        See the documentation of the previously listed definitions.
323

324
    Returns
325
    -------
326
    :class:`tuple`
327
        Current figure and axes.
328

329
    Examples
330
    --------
331
    >>> from colour.models import RGB_COLOURSPACE_sRGB
332
    >>> from colour.utilities import is_trimesh_installed
333
    >>> vertices, faces, _outline = primitive_cube(1, 1, 1, 64, 64, 64)
334
    >>> XYZ_vertices = RGB_to_XYZ(vertices["position"] + 0.5, RGB_COLOURSPACE_sRGB)
335
    >>> if is_trimesh_installed:
336
    ...     from trimesh import Trimesh
337
    ...
338
    ...     hull = Trimesh(XYZ_vertices, faces, process=False)
339
    ...     plot_hull_section_contour(hull, contour_colours="RGB")
340
    ...     # doctest: +ELLIPSIS
341
    (<Figure size ... with 1 Axes>, <...Axes...>)
342

343
    .. image:: ../_static/Plotting_Plot_Hull_Section_Contour.png
344
        :align: center
345
        :alt: plot_hull_section_contour
346
    """
347

348
    hull = hull.copy()
1✔
349

350
    contour_colours = optional(contour_colours, CONSTANTS_COLOUR_STYLE.colour.dark)
1✔
351

352
    settings: Dict[str, Any] = {"uniform": True}
1✔
353
    settings.update(kwargs)
1✔
354

355
    _figure, axes = artist(**settings)
1✔
356

357
    convert_kwargs = optional(convert_kwargs, {})
1✔
358

359
    # Luminance / Lightness is re-ordered along "z-up" axis.
360
    with suppress_warnings(python_warnings=True):
1✔
361
        ijk_vertices = colourspace_model_axis_reorder(
1✔
362
            convert(hull.vertices, "CIE XYZ", model, **convert_kwargs), model
363
        )
364
        ijk_vertices = np.nan_to_num(ijk_vertices)
1✔
365
        ijk_vertices *= COLOURSPACE_MODELS_DOMAIN_RANGE_SCALE_1_TO_REFERENCE[model]
1✔
366

367
    hull.vertices = ijk_vertices
1✔
368

369
    plane = MAPPING_AXIS_TO_PLANE[axis]
1✔
370

371
    padding = 0.1 * np.mean(COLOURSPACE_MODELS_DOMAIN_RANGE_SCALE_1_TO_REFERENCE[model])
1✔
372
    min_x = np.min(ijk_vertices[..., plane[0]]) - padding
1✔
373
    max_x = np.max(ijk_vertices[..., plane[0]]) + padding
1✔
374
    min_y = np.min(ijk_vertices[..., plane[1]]) - padding
1✔
375
    max_y = np.max(ijk_vertices[..., plane[1]]) + padding
1✔
376
    extent = (min_x, max_x, min_y, max_y)
1✔
377

378
    use_RGB_contour_colours = str(contour_colours).upper() == "RGB"
1✔
379
    section = hull_section(hull, axis, origin, normalise)
1✔
380
    if use_RGB_contour_colours:
1✔
381
        ijk_section = (
1✔
382
            section / (COLOURSPACE_MODELS_DOMAIN_RANGE_SCALE_1_TO_REFERENCE[model])
383
        )
384
        XYZ_section = convert(
1✔
385
            colourspace_model_axis_reorder(ijk_section, model, "Inverse"),
386
            model,
387
            "CIE XYZ",
388
            **convert_kwargs,
389
        )
390
        contour_colours = np.clip(XYZ_to_plotting_colourspace(XYZ_section), 0, 1)
1✔
391

392
    section = np.reshape(section[..., plane], (-1, 1, 2))
1✔
393
    line_collection = LineCollection(
1✔
394
        np.concatenate([section[:-1], section[1:]], axis=1),  # pyright: ignore
395
        colors=contour_colours,
396
        alpha=contour_opacity,
397
        zorder=CONSTANTS_COLOUR_STYLE.zorder.background_line,
398
    )
399
    axes.add_collection(line_collection)
1✔
400

401
    settings = {
1✔
402
        "axes": axes,
403
        "bounding_box": extent,
404
    }
405
    settings.update(kwargs)
1✔
406

407
    return render(**settings)
1✔
408

409

410
@required("trimesh")
×
411
@override_style()
×
412
def plot_visible_spectrum_section(
×
413
    cmfs: (
414
        MultiSpectralDistributions | str | Sequence[MultiSpectralDistributions | str]
415
    ) = "CIE 1931 2 Degree Standard Observer",
416
    illuminant: SpectralDistribution | str = "D65",
417
    model: LiteralColourspaceModel | str = "CIE xyY",
418
    axis: Literal["+z", "+x", "+y"] | str = "+z",
419
    origin: float = 0.5,
420
    normalise: bool = True,
421
    show_section_colours: bool = True,
422
    show_section_contour: bool = True,
423
    **kwargs: Any,
424
) -> Tuple[Figure, Axes]:
425
    """
426
    Plot the visible spectrum volume section colours along the specified axis
427
    and origin.
428

429
    The visible spectrum volume represents the *Rösch-MacAdam* colour solid.
430

431
    Parameters
432
    ----------
433
    cmfs
434
        Standard observer colour matching functions, default to the
435
        *CIE 1931 2 Degree Standard Observer*.  ``cmfs`` can be of any type
436
        or form supported by the :func:`colour.plotting.common.filter_cmfs`
437
        definition.
438
    illuminant
439
        Illuminant spectral distribution, default to *CIE Illuminant D65*.
440
        ``illuminant`` can be of any type or form supported by the
441
        :func:`colour.plotting.common.filter_illuminants` definition.
442
    model
443
        Colourspace model, see :attr:`colour.COLOURSPACE_MODELS` attribute
444
        for the list of supported colourspace models.
445
    axis
446
        Axis the hull section will be normal to.
447
    origin
448
        Coordinate along ``axis`` at which to plot the hull section.
449
    normalise
450
        Whether to normalise ``axis`` to the extent of the hull along it.
451
    show_section_colours
452
        Whether to show the hull section colours.
453
    show_section_contour
454
        Whether to show the hull section contour.
455

456
    Other Parameters
457
    ----------------
458
    kwargs
459
        {:func:`colour.plotting.artist`,
460
        :func:`colour.plotting.render`,
461
        :func:`colour.plotting.section.plot_hull_section_colours`
462
        :func:`colour.plotting.section.plot_hull_section_contour`},
463
        See the documentation of the previously listed definitions.
464

465
    Returns
466
    -------
467
    :class:`tuple`
468
        Current figure and axes.
469

470
    Examples
471
    --------
472
    >>> from colour.utilities import is_trimesh_installed
473
    >>> if is_trimesh_installed:
474
    ...     plot_visible_spectrum_section(section_colours="RGB", section_opacity=0.15)
475
    ...     # doctest: +ELLIPSIS
476
    (<Figure size ... with 1 Axes>, <...Axes...>)
477

478
    .. image:: ../_static/Plotting_Plot_Visible_Spectrum_Section.png
479
        :align: center
480
        :alt: plot_visible_spectrum_section
481
    """
482

483
    import trimesh.convex  # noqa: PLC0415
1✔
484
    from trimesh import Trimesh  # noqa: PLC0415
1✔
485

486
    settings: Dict[str, Any] = {"uniform": True}
1✔
487
    settings.update(kwargs)
1✔
488

489
    _figure, axes = artist(**settings)
1✔
490

491
    cmfs = cast(
1✔
492
        "MultiSpectralDistributions",
493
        reshape_msds(
494
            first_item(filter_cmfs(cmfs).values()),
495
            SpectralShape(360, 780, 1),
496
            copy=False,
497
        ),
498
    )
499
    illuminant = cast(
1✔
500
        "SpectralDistribution",
501
        first_item(filter_illuminants(illuminant).values()),
502
    )
503

504
    vertices = solid_RoschMacAdam(
1✔
505
        cmfs,
506
        illuminant,
507
        point_order="Pulse Wave Width",
508
        filter_jagged_points=True,
509
    )
510
    mesh = Trimesh(vertices)
1✔
511
    hull = trimesh.convex.convex_hull(mesh)
1✔
512

513
    if show_section_colours:
1✔
514
        settings = {"axes": axes}
1✔
515
        settings.update(kwargs)
1✔
516
        settings["show"] = False
1✔
517

518
        plot_hull_section_colours(hull, model, axis, origin, normalise, **settings)
1✔
519

520
    if show_section_contour:
1✔
521
        settings = {"axes": axes}
1✔
522
        settings.update(kwargs)
1✔
523
        settings["show"] = False
1✔
524

525
        plot_hull_section_contour(hull, model, axis, origin, normalise, **settings)
1✔
526

527
    title = (
1✔
528
        f"Visible Spectrum Section - "
529
        f"{f'{origin * 100}%' if normalise else origin} - "
530
        f"{model} - "
531
        f"{cmfs.display_name}"
532
    )
533

534
    plane = MAPPING_AXIS_TO_PLANE[axis]
1✔
535

536
    labels = np.array(COLOURSPACE_MODELS_AXIS_LABELS[model])[
1✔
537
        as_int_array(colourspace_model_axis_reorder([0, 1, 2], model))
538
    ]
539
    x_label, y_label = labels[plane[0]], labels[plane[1]]
1✔
540

541
    settings.update(
1✔
542
        {
543
            "axes": axes,
544
            "show": True,
545
            "title": title,
546
            "x_label": x_label,
547
            "y_label": y_label,
548
        }
549
    )
550
    settings.update(kwargs)
1✔
551

552
    return render(**settings)
1✔
553

554

555
@required("trimesh")
×
556
@override_style()
×
557
def plot_RGB_colourspace_section(
×
558
    colourspace: (
559
        RGB_Colourspace
560
        | LiteralRGBColourspace
561
        | str
562
        | Sequence[RGB_Colourspace | LiteralRGBColourspace | str]
563
    ),
564
    model: LiteralColourspaceModel | str = "CIE xyY",
565
    axis: Literal["+z", "+x", "+y"] | str = "+z",
566
    origin: float = 0.5,
567
    normalise: bool = True,
568
    size: float = 1.0,
569
    show_section_colours: bool = True,
570
    show_section_contour: bool = True,
571
    segments: int = 64,
572
    **kwargs: Any,
573
) -> Tuple[Figure, Axes]:
574
    """
575
    Plot the specified *RGB* colourspace section colours along the
576
    specified axis and origin.
577

578
    Parameters
579
    ----------
580
    colourspace
581
        *RGB* colourspace of the *RGB* array. ``colourspace`` can be of
582
        any type or form supported by the
583
        :func:`colour.plotting.common.filter_RGB_colourspaces`
584
        definition.
585
    model
586
        Colourspace model, see :attr:`colour.COLOURSPACE_MODELS`
587
        attribute for the list of supported colourspace models.
588
    axis
589
        Axis the hull section will be normal to.
590
    origin
591
        Coordinate along ``axis`` at which to plot the hull section.
592
    normalise
593
        Whether to normalise ``axis`` to the extent of the hull along
594
        it.
595
    size:
596
        Size of the underlying *RGB* colourspace cube; used for plotting
597
        HDR related sections.
598
    show_section_colours
599
        Whether to show the hull section colours.
600
    show_section_contour
601
        Whether to show the hull section contour.
602
    segments
603
        Edge segments count for the *RGB* colourspace cube.
604

605
    Other Parameters
606
    ----------------
607
    kwargs
608
        {:func:`colour.plotting.artist`,
609
        :func:`colour.plotting.render`,
610
        :func:`colour.plotting.section.plot_hull_section_colours`
611
        :func:`colour.plotting.section.plot_hull_section_contour`},
612
        See the documentation of the previously listed definitions.
613

614
    Returns
615
    -------
616
    :class:`tuple`
617
        Current figure and axes.
618

619
    Examples
620
    --------
621
    >>> from colour.utilities import is_trimesh_installed
622
    >>> if is_trimesh_installed:
623
    ...     plot_RGB_colourspace_section(
624
    ...         "sRGB", section_colours="RGB", section_opacity=0.15
625
    ...     )
626
    ...     # doctest: +ELLIPSIS
627
    (<Figure size ... with 1 Axes>, <...Axes...>)
628

629
    .. image:: ../_static/Plotting_Plot_RGB_Colourspace_Section.png
630
        :align: center
631
        :alt: plot_RGB_colourspace_section
632
    """
633

634
    from trimesh import Trimesh  # noqa: PLC0415
1✔
635

636
    settings: Dict[str, Any] = {"uniform": True}
1✔
637
    settings.update(kwargs)
1✔
638

639
    _figure, axes = artist(**settings)
1✔
640

641
    colourspace = cast(
1✔
642
        "RGB_Colourspace",
643
        first_item(filter_RGB_colourspaces(colourspace).values()),
644
    )
645

646
    vertices, faces, _outline = primitive_cube(1, 1, 1, segments, segments, segments)
1✔
647
    XYZ_vertices = RGB_to_XYZ((vertices["position"] + 0.5) * size, colourspace)
1✔
648
    hull = Trimesh(XYZ_vertices, faces, process=False)
1✔
649

650
    if show_section_colours:
1✔
651
        settings = {"axes": axes}
1✔
652
        settings.update(kwargs)
1✔
653
        settings["show"] = False
1✔
654

655
        plot_hull_section_colours(hull, model, axis, origin, normalise, **settings)
1✔
656

657
    if show_section_contour:
1✔
658
        settings = {"axes": axes}
1✔
659
        settings.update(kwargs)
1✔
660
        settings["show"] = False
1✔
661

662
        plot_hull_section_contour(hull, model, axis, origin, normalise, **settings)
1✔
663

664
    title = (
1✔
665
        f"{colourspace.name} Section - "
666
        f"{f'{origin * 100}%' if normalise else origin} - "
667
        f"{model}"
668
    )
669

670
    plane = MAPPING_AXIS_TO_PLANE[axis]
1✔
671

672
    labels = np.array(COLOURSPACE_MODELS_AXIS_LABELS[model])[
1✔
673
        as_int_array(colourspace_model_axis_reorder([0, 1, 2], model))
674
    ]
675
    x_label, y_label = labels[plane[0]], labels[plane[1]]
1✔
676

677
    settings.update(
1✔
678
        {
679
            "axes": axes,
680
            "show": True,
681
            "title": title,
682
            "x_label": x_label,
683
            "y_label": y_label,
684
        }
685
    )
686
    settings.update(kwargs)
1✔
687

688
    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