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

colour-science / colour / 12452776384

22 Dec 2024 08:43AM UTC coverage: 97.524% (-1.7%) from 99.255%
12452776384

push

github

KelSolaar
Code formatting.

41247 of 42294 relevant lines covered (97.52%)

0.98 hits per line

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

98.21
/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
1✔
14

15
import typing
1✔
16

17
import numpy as np
1✔
18

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

22
from matplotlib.collections import LineCollection
1✔
23

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

27
from matplotlib.patches import Polygon
1✔
28

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

38
if typing.TYPE_CHECKING:
1✔
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
1✔
51
from colour.models import (
1✔
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
1✔
58
from colour.plotting import (
1✔
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 (
1✔
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
1✔
81

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

89
__all__ = [
1✔
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(
1✔
98
    {"+x": (1, 2), "+y": (0, 2), "+z": (0, 1)}
99
)
100
MAPPING_AXIS_TO_PLANE.__doc__ = """Axis to plane mapping."""
1✔
101

102

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

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

145
    Other Parameters
146
    ----------------
147
    kwargs
148
        {:func:`colour.plotting.artist`,
149
        :func:`colour.plotting.render`},
150
        See the documentation of the previously listed definitions.
151

152
    Returns
153
    -------
154
    :class:`tuple`
155
        Current figure and axes.
156

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

171
    .. image:: ../_static/Plotting_Plot_Hull_Section_Colours.png
172
        :align: center
173
        :alt: plot_hull_section_colours
174
    """
175

176
    axis = validate_method(
1✔
177
        axis,
178
        ("+z", "+x", "+y"),
179
        '"{0}" axis is invalid, it must be one of {1}!',
180
    )
181

182
    hull = hull.copy()
1✔
183

184
    settings: Dict[str, Any] = {"uniform": True}
1✔
185
    settings.update(kwargs)
1✔
186

187
    _figure, axes = artist(**settings)
1✔
188

189
    section_colours = optional(
1✔
190
        section_colours, HEX_to_RGB(CONSTANTS_COLOUR_STYLE.colour.average)
191
    )
192

193
    convert_kwargs = optional(convert_kwargs, {})
1✔
194

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

203
    hull.vertices = ijk_vertices
1✔
204

205
    if axis == "+x":
1✔
206
        index_origin = 0
1✔
207
    elif axis == "+y":
1✔
208
        index_origin = 1
1✔
209
    elif axis == "+z":
1✔
210
        index_origin = 2
1✔
211
    plane = MAPPING_AXIS_TO_PLANE[axis]
1✔
212

213
    section = hull_section(hull, axis, origin, normalise)
1✔
214

215
    padding = 0.1 * np.mean(COLOURSPACE_MODELS_DOMAIN_RANGE_SCALE_1_TO_REFERENCE[model])
1✔
216
    min_x = np.min(ijk_vertices[..., plane[0]]) - padding
1✔
217
    max_x = np.max(ijk_vertices[..., plane[0]]) + padding
1✔
218
    min_y = np.min(ijk_vertices[..., plane[1]]) - padding
1✔
219
    max_y = np.max(ijk_vertices[..., plane[1]]) + padding
1✔
220
    extent = (min_x, max_x, min_y, max_y)
1✔
221

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

245
    facecolor = "none" if use_RGB_section_colours else section_colours
1✔
246
    polygon = Polygon(
1✔
247
        section[..., plane],
248
        facecolor=facecolor,
249
        edgecolor="none",
250
        zorder=CONSTANTS_COLOUR_STYLE.zorder.background_polygon,
251
    )
252
    axes.add_patch(polygon)
1✔
253

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

265
    settings = {
1✔
266
        "axes": axes,
267
        "bounding_box": extent,
268
    }
269
    settings.update(kwargs)
1✔
270

271
    return render(**settings)
1✔
272

273

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

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

313
    Other Parameters
314
    ----------------
315
    kwargs
316
        {:func:`colour.plotting.artist`,
317
        :func:`colour.plotting.render`},
318
        See the documentation of the previously listed definitions.
319

320
    Returns
321
    -------
322
    :class:`tuple`
323
        Current figure and axes.
324

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

339
    .. image:: ../_static/Plotting_Plot_Hull_Section_Contour.png
340
        :align: center
341
        :alt: plot_hull_section_contour
342
    """
343

344
    hull = hull.copy()
1✔
345

346
    contour_colours = optional(contour_colours, CONSTANTS_COLOUR_STYLE.colour.dark)
1✔
347

348
    settings: Dict[str, Any] = {"uniform": True}
1✔
349
    settings.update(kwargs)
1✔
350

351
    _figure, axes = artist(**settings)
1✔
352

353
    convert_kwargs = optional(convert_kwargs, {})
1✔
354

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

363
    hull.vertices = ijk_vertices
1✔
364

365
    plane = MAPPING_AXIS_TO_PLANE[axis]
1✔
366

367
    padding = 0.1 * np.mean(COLOURSPACE_MODELS_DOMAIN_RANGE_SCALE_1_TO_REFERENCE[model])
1✔
368
    min_x = np.min(ijk_vertices[..., plane[0]]) - padding
1✔
369
    max_x = np.max(ijk_vertices[..., plane[0]]) + padding
1✔
370
    min_y = np.min(ijk_vertices[..., plane[1]]) - padding
1✔
371
    max_y = np.max(ijk_vertices[..., plane[1]]) + padding
1✔
372
    extent = (min_x, max_x, min_y, max_y)
1✔
373

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

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

397
    settings = {
1✔
398
        "axes": axes,
399
        "bounding_box": extent,
400
    }
401
    settings.update(kwargs)
1✔
402

403
    return render(**settings)
1✔
404

405

406
@required("trimesh")
1✔
407
@override_style()
1✔
408
def plot_visible_spectrum_section(
1✔
409
    cmfs: (
410
        MultiSpectralDistributions | str | Sequence[MultiSpectralDistributions | str]
411
    ) = "CIE 1931 2 Degree Standard Observer",
412
    illuminant: SpectralDistribution | str = "D65",
413
    model: LiteralColourspaceModel | str = "CIE xyY",
414
    axis: Literal["+z", "+x", "+y"] | str = "+z",
415
    origin: float = 0.5,
416
    normalise: bool = True,
417
    show_section_colours: bool = True,
418
    show_section_contour: bool = True,
419
    **kwargs: Any,
420
) -> Tuple[Figure, Axes]:
421
    """
422
    Plot the visible spectrum volume, i.e., *Rösch-MacAdam* colour solid,
423
    section colours along given axis and origin.
424

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

450
    Other Parameters
451
    ----------------
452
    kwargs
453
        {:func:`colour.plotting.artist`,
454
        :func:`colour.plotting.render`,
455
        :func:`colour.plotting.section.plot_hull_section_colours`
456
        :func:`colour.plotting.section.plot_hull_section_contour`},
457
        See the documentation of the previously listed definitions.
458

459
    Returns
460
    -------
461
    :class:`tuple`
462
        Current figure and axes.
463

464
    Examples
465
    --------
466
    >>> from colour.utilities import is_trimesh_installed
467
    >>> if is_trimesh_installed:
468
    ...     plot_visible_spectrum_section(section_colours="RGB", section_opacity=0.15)
469
    ...     # doctest: +ELLIPSIS
470
    (<Figure size ... with 1 Axes>, <...Axes...>)
471

472
    .. image:: ../_static/Plotting_Plot_Visible_Spectrum_Section.png
473
        :align: center
474
        :alt: plot_visible_spectrum_section
475
    """
476

477
    import trimesh.convex
1✔
478
    from trimesh import Trimesh
1✔
479

480
    settings: Dict[str, Any] = {"uniform": True}
1✔
481
    settings.update(kwargs)
1✔
482

483
    _figure, axes = artist(**settings)
1✔
484

485
    cmfs = cast(
1✔
486
        MultiSpectralDistributions,
487
        reshape_msds(
488
            first_item(filter_cmfs(cmfs).values()),
489
            SpectralShape(360, 780, 1),
490
            copy=False,
491
        ),
492
    )
493
    illuminant = cast(
1✔
494
        SpectralDistribution,
495
        first_item(filter_illuminants(illuminant).values()),
496
    )
497

498
    vertices = solid_RoschMacAdam(
1✔
499
        cmfs,
500
        illuminant,
501
        point_order="Pulse Wave Width",
502
        filter_jagged_points=True,
503
    )
504
    mesh = Trimesh(vertices)
1✔
505
    hull = trimesh.convex.convex_hull(mesh)
1✔
506

507
    if show_section_colours:
1✔
508
        settings = {"axes": axes}
1✔
509
        settings.update(kwargs)
1✔
510
        settings["show"] = False
1✔
511

512
        plot_hull_section_colours(hull, model, axis, origin, normalise, **settings)
1✔
513

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

519
        plot_hull_section_contour(hull, model, axis, origin, normalise, **settings)
1✔
520

521
    title = (
1✔
522
        f"Visible Spectrum Section - "
523
        f"{f'{origin * 100}%' if normalise else origin} - "
524
        f"{model} - "
525
        f"{cmfs.display_name}"
526
    )
527

528
    plane = MAPPING_AXIS_TO_PLANE[axis]
1✔
529

530
    labels = np.array(COLOURSPACE_MODELS_AXIS_LABELS[model])[
1✔
531
        as_int_array(colourspace_model_axis_reorder([0, 1, 2], model))
532
    ]
533
    x_label, y_label = labels[plane[0]], labels[plane[1]]
1✔
534

535
    settings.update(
1✔
536
        {
537
            "axes": axes,
538
            "show": True,
539
            "title": title,
540
            "x_label": x_label,
541
            "y_label": y_label,
542
        }
543
    )
544
    settings.update(kwargs)
1✔
545

546
    return render(**settings)
1✔
547

548

549
@required("trimesh")
1✔
550
@override_style()
1✔
551
def plot_RGB_colourspace_section(
1✔
552
    colourspace: (
553
        RGB_Colourspace
554
        | LiteralRGBColourspace
555
        | str
556
        | Sequence[RGB_Colourspace | LiteralRGBColourspace | str]
557
    ),
558
    model: LiteralColourspaceModel | str = "CIE xyY",
559
    axis: Literal["+z", "+x", "+y"] | str = "+z",
560
    origin: float = 0.5,
561
    normalise: bool = True,
562
    size: float = 1.0,
563
    show_section_colours: bool = True,
564
    show_section_contour: bool = True,
565
    segments: int = 64,
566
    **kwargs: Any,
567
) -> Tuple[Figure, Axes]:
568
    """
569
    Plot given *RGB* colourspace section colours along given axis and origin.
570

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

596
    Other Parameters
597
    ----------------
598
    kwargs
599
        {:func:`colour.plotting.artist`,
600
        :func:`colour.plotting.render`,
601
        :func:`colour.plotting.section.plot_hull_section_colours`
602
        :func:`colour.plotting.section.plot_hull_section_contour`},
603
        See the documentation of the previously listed definitions.
604

605
    Returns
606
    -------
607
    :class:`tuple`
608
        Current figure and axes.
609

610
    Examples
611
    --------
612
    >>> from colour.utilities import is_trimesh_installed
613
    >>> if is_trimesh_installed:
614
    ...     plot_RGB_colourspace_section(
615
    ...         "sRGB", section_colours="RGB", section_opacity=0.15
616
    ...     )
617
    ...     # doctest: +ELLIPSIS
618
    (<Figure size ... with 1 Axes>, <...Axes...>)
619

620
    .. image:: ../_static/Plotting_Plot_RGB_Colourspace_Section.png
621
        :align: center
622
        :alt: plot_RGB_colourspace_section
623
    """
624

625
    from trimesh import Trimesh
1✔
626

627
    settings: Dict[str, Any] = {"uniform": True}
1✔
628
    settings.update(kwargs)
1✔
629

630
    _figure, axes = artist(**settings)
1✔
631

632
    colourspace = cast(
1✔
633
        RGB_Colourspace,
634
        first_item(filter_RGB_colourspaces(colourspace).values()),
635
    )
636

637
    vertices, faces, _outline = primitive_cube(1, 1, 1, segments, segments, segments)
1✔
638
    XYZ_vertices = RGB_to_XYZ((vertices["position"] + 0.5) * size, colourspace)
1✔
639
    hull = Trimesh(XYZ_vertices, faces, process=False)
1✔
640

641
    if show_section_colours:
1✔
642
        settings = {"axes": axes}
1✔
643
        settings.update(kwargs)
1✔
644
        settings["show"] = False
1✔
645

646
        plot_hull_section_colours(hull, model, axis, origin, normalise, **settings)
1✔
647

648
    if show_section_contour:
1✔
649
        settings = {"axes": axes}
1✔
650
        settings.update(kwargs)
1✔
651
        settings["show"] = False
1✔
652

653
        plot_hull_section_contour(hull, model, axis, origin, normalise, **settings)
1✔
654

655
    title = (
1✔
656
        f"{colourspace.name} Section - "
657
        f"{f'{origin * 100}%' if normalise else origin} - "
658
        f"{model}"
659
    )
660

661
    plane = MAPPING_AXIS_TO_PLANE[axis]
1✔
662

663
    labels = np.array(COLOURSPACE_MODELS_AXIS_LABELS[model])[
1✔
664
        as_int_array(colourspace_model_axis_reorder([0, 1, 2], model))
665
    ]
666
    x_label, y_label = labels[plane[0]], labels[plane[1]]
1✔
667

668
    settings.update(
1✔
669
        {
670
            "axes": axes,
671
            "show": True,
672
            "title": title,
673
            "x_label": x_label,
674
            "y_label": y_label,
675
        }
676
    )
677
    settings.update(kwargs)
1✔
678

679
    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