Coverage for plotting/tm3018/report.py: 71%

1"""

2 ANSI/IES TM-30-18 Colour Rendition Report

3=========================================

4

5 Define the *ANSI/IES TM-30-18 Colour Rendition Report* plotting objects:

6

7- :func:`colour.plotting.tm3018.plot_single_sd_colour_rendition_report_full`

8- :func:`colour.plotting.tm3018.plot_single_sd_colour_rendition_report_intermediate`

9- :func:`colour.plotting.tm3018.plot_single_sd_colour_rendition_report_simple`

10- :func:`colour.plotting.plot_single_sd_colour_rendition_report`

11"""

12

13 from __future__ import annotations

14

15 import typing

16

17 if typing.TYPE_CHECKING:

18 from matplotlib.figure import Figure

19 from matplotlib.axes import Axes

20

21 import matplotlib.pyplot as plt

22

23 from colour.colorimetry import SpectralDistribution, sd_to_XYZ

24

25 if typing.TYPE_CHECKING:

26 from colour.hints import Any, Dict, Literal, Tuple

27

28 from colour.io import SpectralDistribution_IESTM2714

29 from colour.models import Luv_to_uv, XYZ_to_Luv, XYZ_to_xy

30 from colour.plotting import CONSTANTS_COLOUR_STYLE, override_style, render

31 from colour.plotting.tm3018.components import (

32 plot_colour_fidelity_indexes,

33 plot_colour_vector_graphic,

34 plot_local_chroma_shifts,

35 plot_local_colour_fidelities,

36 plot_local_hue_shifts,

37 plot_spectra_ANSIIESTM3018,

38)

39 from colour.quality import (

40 colour_fidelity_index_ANSIIESTM3018,

41 colour_rendering_index,

42)

43 from colour.utilities import (

44 as_float_scalar,

45 describe_environment,

46 optional,

47 validate_method,

48)

49

50 __author__ = "Colour Developers"

51 __copyright__ = "Copyright 2013 Colour Developers"

52 __license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"

53 __maintainer__ = "Colour Developers"

54 __email__ = "colour-developers@colour-science.org"

55 __status__ = "Production"

56

57 __all__ = [

58 "CONSTANT_REPORT_SIZE_FULL",

59 "CONSTANT_REPORT_ROW_HEIGHT_RATIOS_FULL",

60 "CONSTANT_REPORT_PADDING_FULL",

61 "CONSTANT_REPORT_SIZE_INTERMEDIATE",

62 "CONSTANT_REPORT_ROW_HEIGHT_RATIOS_INTERMEDIATE",

63 "CONSTANT_REPORT_PADDING_INTERMEDIATE",

64 "CONSTANT_REPORT_SIZE_SIMPLE",

65 "CONSTANT_REPORT_ROW_HEIGHT_RATIOS_SIMPLE",

66 "CONSTANT_REPORT_PADDING_SIMPLE",

67 "CONSTANTS_REPORT_STYLE",

68 "CONTENT_REPORT_HEADER",

69 "CONTENT_REPORT_FOOTER",

70 "plot_single_sd_colour_rendition_report_full",

71 "plot_single_sd_colour_rendition_report_intermediate",

72 "plot_single_sd_colour_rendition_report_simple",

73 "plot_single_sd_colour_rendition_report",

74]

75

76# Full Report Size Constants

77 CONSTANT_REPORT_SIZE_FULL: tuple = (8.27, 11.69)

78"""Full report size, default to A4 paper size in inches."""

79

80 CONSTANT_REPORT_ROW_HEIGHT_RATIOS_FULL: tuple = (1, 2, 24, 3, 1)

81"""Full report size row height ratios."""

82

83 CONSTANT_REPORT_PADDING_FULL: dict = {

84 "w_pad": 20 / 100,

85 "h_pad": 10 / 100,

86 "hspace": 0,

87 "wspace": 0,

88}

89"""

90 Full report box padding, tries to define the padding around the figure and

91 in-between the axes.

92"""

93

94# Intermediate Report Size Constants

95 CONSTANT_REPORT_SIZE_INTERMEDIATE: tuple = (8.27, 11.69 / 2.35)

96"""Intermediate report size, a window into A4 paper size in inches."""

97

98 CONSTANT_REPORT_ROW_HEIGHT_RATIOS_INTERMEDIATE: tuple = (1, 8, 1)

99"""Intermediate report size row height ratios."""

100

101 CONSTANT_REPORT_PADDING_INTERMEDIATE: dict = {

102 "w_pad": 20 / 100,

103 "h_pad": 10 / 100,

104 "hspace": 0,

105 "wspace": 0,

106}

107"""

108 Intermediate report box padding, tries to define the padding around the figure

109 and in-between the axes.

110"""

111

112# Simple Report Size Constants

113 CONSTANT_REPORT_SIZE_SIMPLE: tuple = (8.27, 8.27)

114"""Simple report size, a window into A4 paper size in inches."""

115

116 CONSTANT_REPORT_ROW_HEIGHT_RATIOS_SIMPLE: tuple = (1, 8, 1)

117"""Simple report size row height ratios."""

118

119 CONSTANT_REPORT_PADDING_SIMPLE: dict = {

120 "w_pad": 20 / 100,

121 "h_pad": 10 / 100,

122 "hspace": 0,

123 "wspace": 0,

124}

125"""

126 Simple report box padding, tries to define the padding around the figure

127 and in-between the axes.

128"""

129

130 CONSTANTS_REPORT_STYLE: dict = {

131 "axes.grid": False,

132 "axes.labelpad": CONSTANTS_COLOUR_STYLE.geometry.short * 3,

133 "axes.labelsize": "x-small",

134 "axes.labelweight": "bold",

135 "legend.frameon": False,

136 "xtick.labelsize": "x-small",

137 "ytick.labelsize": "x-small",

138 "xtick.direction": "out",

139 "ytick.direction": "out",

140 "xtick.major.size": CONSTANTS_COLOUR_STYLE.geometry.long * 0.5,

141 "ytick.major.size": CONSTANTS_COLOUR_STYLE.geometry.long * 0.5,

142 "xtick.minor.size": CONSTANTS_COLOUR_STYLE.geometry.long * 0.25,

143 "ytick.minor.size": CONSTANTS_COLOUR_STYLE.geometry.long * 0.25,

144 "xtick.minor.visible": False,

145 "ytick.minor.visible": False,

146}

147"""Report style overrides."""

148

149 CONTENT_REPORT_HEADER: str = "IES TM-30-18 Colour Rendition Report"

150"""Report header content, i.e., the report title."""

151

152 CONTENT_REPORT_FOOTER: str = (

153 "Colours are for visual orientation purposes only. Created with Colour{0}"

154)

155"""Report footer content."""

156

157 _VALUE_NOT_APPLICABLE: str = "N/A"

158

159

160 def _plot_report_header(axes: Axes) -> Axes:

161 """

162 Plot the report header on the specified axes.

163

164 Parameters

165 ----------

166 axes

167 Axes to add the report header to.

168

169 Returns

170 -------

171 :class:`matplotlib.axes._axes.Axes`

172 Axes with the report header added.

173 """

174

175 axes.set_axis_off()

176 axes.text(

177 0.5,

178 0.5,

179 CONTENT_REPORT_HEADER,

180 ha="center",

181 va="center",

182 size="x-large",

183 weight="bold",

184 zorder=CONSTANTS_COLOUR_STYLE.zorder.foreground_label,

185 )

186

187 return axes

188

189

190 def _plot_report_footer(axes: Axes) -> Axes:

191 """

192 Plot the report footer on the specified axes.

193

194 Parameters

195 ----------

196 axes

197 Axes to add the report footer to.

198

199 Returns

200 -------

201 :class:`matplotlib.axes._axes.Axes`

202 Axes with the report footer added.

203 """

204

205 try:

206 describe = describe_environment(print_callable=lambda x: x)[

207 "colour-science.org"

208 ]["colour"]

209 version = f" {describe}."

210 except Exception: # pragma: no cover # noqa: BLE001

211 version = "."

212

213 axes.set_axis_off()

214 axes.text(

215 0.5,

216 0.5,

217 CONTENT_REPORT_FOOTER.format(version),

218 ha="center",

219 va="center",

220 size="small",

221 zorder=CONSTANTS_COLOUR_STYLE.zorder.foreground_label,

222 )

223

224 return axes

225

226

227@override_style(**CONSTANTS_REPORT_STYLE)

228 def plot_single_sd_colour_rendition_report_full(

229 sd: SpectralDistribution,

230 source: str | None = None,

231 date: str | None = None,

232 manufacturer: str | None = None,

233 model: str | None = None,

234 notes: str | None = None,

235 report_size: tuple[float, float] = CONSTANT_REPORT_SIZE_FULL,

236 report_row_height_ratios: tuple = CONSTANT_REPORT_ROW_HEIGHT_RATIOS_FULL,

237 report_box_padding: dict | None = None,

238 **kwargs: Any,

239) -> Tuple[Figure, Axes]:

240 """

241 Generate the full *ANSI/IES TM-30-18 Colour Rendition Report* for the

242 specified spectral distribution.

243

244 Parameters

245 ----------

246 sd

247 Spectral distribution of the emission source to generate the report

248 for.

249 source

250 Emission source name, defaults to the

251 `colour.SpectralDistribution_IESTM2714.header.description` or

252 `colour.SpectralDistribution_IESTM2714.name` property value.

253 date

254 Emission source measurement date, defaults to the

255 `colour.SpectralDistribution_IESTM2714.header.report_date` property

256 value.

257 manufacturer

258 Emission source manufacturer, defaults to the

259 `colour.SpectralDistribution_IESTM2714.header.manufacturer` property

260 value.

261 model

262 Emission source model, defaults to the

263 `colour.SpectralDistribution_IESTM2714.header.catalog_number`

264 property value.

265 notes

266 Notes pertaining to the emission source, defaults to the

267 `colour.SpectralDistribution_IESTM2714.header.comments` property

268 value.

269 report_size

270 Report size, defaults to A4 paper size in inches.

271 report_row_height_ratios

272 Report size row height ratios.

273 report_box_padding

274 Report box padding, defines the padding around the figure and

275 between the axes.

276

277 Other Parameters

278 ----------------

279 kwargs

280 {:func:`colour.plotting.artist`, :func:`colour.plotting.render`},

281 See the documentation of the previously listed definitions.

282

283 Returns

284 -------

285 :class:`tuple`

286 Current figure and axes.

287

288 Examples

289 --------

290 >>> from colour import SDS_ILLUMINANTS

291 >>> sd = SDS_ILLUMINANTS["FL2"]

292 >>> plot_single_sd_colour_rendition_report_full(sd)

293 ... # doctest: +ELLIPSIS

294 (<Figure size ... with ... Axes>, <...Axes...>)

295

296 .. image:: ../_static/Plotting_\

297 Plot_Single_SD_Colour_Rendition_Report_Full.png

298 :align: center

299 :alt: plot_single_sd_colour_rendition_report_full

300 """

301

302 report_box_padding = optional(report_box_padding, CONSTANT_REPORT_PADDING_FULL)

303

304 specification = colour_fidelity_index_ANSIIESTM3018(sd, True)

305

306 sd = (

307 SpectralDistribution_IESTM2714(data=sd, name=sd.name)

308 if not isinstance(sd, SpectralDistribution_IESTM2714)

309 else sd

310 )

311

312 NA = _VALUE_NOT_APPLICABLE

313

314 source = optional(optional(source, sd.header.description), sd.name)

315 date = optional(optional(date, sd.header.report_date), NA)

316 manufacturer = optional(optional(manufacturer, sd.header.manufacturer), NA)

317 model = optional(optional(model, sd.header.catalog_number), NA)

318 notes = optional(optional(notes, sd.header.comments), NA)

319

320 figure = plt.figure(figsize=report_size, constrained_layout=True)

321

322 settings: Dict[str, Any] = dict(kwargs)

323 settings["show"] = False

324 settings["tight_layout"] = False

325

326 gridspec_report = figure.add_gridspec(5, 1, height_ratios=report_row_height_ratios)

327

328 # Title Row

329 gridspec_title = gridspec_report[0].subgridspec(1, 1)

330 axes_title = figure.add_subplot(gridspec_title[0])

331 _plot_report_header(axes_title)

332

333 # Description Rows & Columns

334 gridspec_description = gridspec_report[1].subgridspec(1, 2)

335 # Source & Date Column

336 axes_source_date = figure.add_subplot(gridspec_description[0])

337 axes_source_date.set_axis_off()

338 axes_source_date.text(

339 0.25,

340 2 / 3,

341 "Source: ",

342 ha="right",

343 va="center",

344 size="medium",

345 weight="bold",

346 )

347 axes_source_date.text(0.25, 2 / 3, source, va="center", size="medium")

348

349 axes_source_date.text(

350 0.25,

351 1 / 3,

352 "Date: ",

353 ha="right",

354 va="center",

355 size="medium",

356 weight="bold",

357 )

358 axes_source_date.text(0.25, 1 / 3, date, va="center", size="medium")

359

360 # Manufacturer & Model Column

361 axes_manufacturer_model = figure.add_subplot(gridspec_description[1])

362 axes_manufacturer_model.set_axis_off()

363 axes_manufacturer_model.text(

364 0.25,

365 2 / 3,

366 "Manufacturer: ",

367 ha="right",

368 va="center",

369 size="medium",

370 weight="bold",

371 )

372 axes_manufacturer_model.text(0.25, 2 / 3, manufacturer, va="center", size="medium")

373

374 axes_manufacturer_model.text(

375 0.25,

376 1 / 3,

377 "Model: ",

378 ha="right",

379 va="center",

380 size="medium",

381 weight="bold",

382 )

383 axes_manufacturer_model.text(0.25, 1 / 3, model, va="center", size="medium")

384

385 # Main Figures Rows & Columns

386 gridspec_figures = gridspec_report[2].subgridspec(

387 4, 2, height_ratios=[1, 1, 1, 1.5]

388 )

389 axes_spectra = figure.add_subplot(gridspec_figures[0, 0])

390 plot_spectra_ANSIIESTM3018(specification, axes=axes_spectra, **settings)

391

392 axes_vector_graphics = figure.add_subplot(gridspec_figures[1:3, 0])

393 plot_colour_vector_graphic(specification, axes=axes_vector_graphics, **settings)

394

395 axes_chroma_shifts = figure.add_subplot(gridspec_figures[0, 1])

396 plot_local_chroma_shifts(specification, axes=axes_chroma_shifts, **settings)

397

398 axes_hue_shifts = figure.add_subplot(gridspec_figures[1, 1])

399 plot_local_hue_shifts(specification, axes=axes_hue_shifts, **settings)

400

401 axes_colour_fidelities = figure.add_subplot(gridspec_figures[2, 1])

402 plot_local_colour_fidelities(

403 specification, axes=axes_colour_fidelities, x_ticker=True, **settings

404 )

405

406 # Colour Fidelity Indexes Row

407 axes_colour_fidelity_indexes = figure.add_subplot(gridspec_figures[3, :])

408 plot_colour_fidelity_indexes(

409 specification, axes=axes_colour_fidelity_indexes, **settings

410 )

411

412 # Notes & Chromaticities / CRI Row and Columns

413 gridspec_notes_chromaticities_CRI = gridspec_report[3].subgridspec(1, 2)

414 axes_notes = figure.add_subplot(gridspec_notes_chromaticities_CRI[0])

415 axes_notes.set_axis_off()

416 axes_notes.text(

417 0.25,

418 1,

419 "Notes: ",

420 ha="right",

421 va="center",

422 size="medium",

423 weight="bold",

424 )

425 axes_notes.text(0.25, 1, notes, va="center", size="medium")

426 gridspec_chromaticities_CRI = gridspec_notes_chromaticities_CRI[1].subgridspec(1, 2)

427

428 XYZ = sd_to_XYZ(specification.sd_test)

429 xy = XYZ_to_xy(XYZ)

430 Luv = XYZ_to_Luv(XYZ, xy)

431 uv_p = Luv_to_uv(Luv, xy)

432

433 gridspec_chromaticities = gridspec_chromaticities_CRI[0].subgridspec(1, 1)

434 axes_chromaticities = figure.add_subplot(gridspec_chromaticities[0])

435 axes_chromaticities.set_axis_off()

436 axes_chromaticities.text(

437 0.5,

438 4 / 5,

439 f"$x$ {xy[0]:.4f}",

440 ha="center",

441 va="center",

442 size="medium",

443 weight="bold",

444 )

445

446 axes_chromaticities.text(

447 0.5,

448 3 / 5,

449 f"$y$ {xy[1]:.4f}",

450 ha="center",

451 va="center",

452 size="medium",

453 weight="bold",

454 )

455

456 axes_chromaticities.text(

457 0.5,

458 2 / 5,

459 f"$u'$ {uv_p[0]:.4f}",

460 ha="center",

461 va="center",

462 size="medium",

463 weight="bold",

464 )

465

466 axes_chromaticities.text(

467 0.5,

468 1 / 5,

469 f"$v'$ {uv_p[1]:.4f}",

470 ha="center",

471 va="center",

472 size="medium",

473 weight="bold",

474 )

475

476 gridspec_CRI = gridspec_chromaticities_CRI[1].subgridspec(1, 1)

477

478 CRI_spec = colour_rendering_index(specification.sd_test, additional_data=True)

479

480 axes_CRI = figure.add_subplot(gridspec_CRI[0])

481 axes_CRI.set_xticks([])

482 axes_CRI.set_yticks([])

483 axes_CRI.text(

484 0.5,

485 4 / 5,

486 "CIE 13.31-1995",

487 ha="center",

488 va="center",

489 size="medium",

490 weight="bold",

491 )

492

493 axes_CRI.text(

494 0.5,

495 3 / 5,

496 "(CRI)",

497 ha="center",

498 va="center",

499 size="medium",

500 weight="bold",

501 )

502

503 axes_CRI.text(

504 0.5,

505 2 / 5,

506 f"$R_a$ {as_float_scalar(CRI_spec.Q_a):.0f}",

507 ha="center",

508 va="center",

509 size="medium",

510 weight="bold",

511 )

512

513 axes_CRI.text(

514 0.5,

515 1 / 5,

516 f"$R_9$ {as_float_scalar(CRI_spec.Q_as[9].Q_a):.0f}",

517 ha="center",

518 va="center",

519 size="medium",

520 weight="bold",

521 )

522

523 gridspec_footer = gridspec_report[4].subgridspec(1, 1)

524 axes_footer = figure.add_subplot(gridspec_footer[0])

525 _plot_report_footer(axes_footer)

526

527 figure.get_layout_engine().set(**report_box_padding) # pyright: ignore

528

529 settings = dict(kwargs)

530 settings["tight_layout"] = False

531

532 return render(**settings)

533

534

535@override_style(**CONSTANTS_REPORT_STYLE)

536 def plot_single_sd_colour_rendition_report_intermediate(

537 sd: SpectralDistribution,

538 report_size: tuple[float, float] = CONSTANT_REPORT_SIZE_INTERMEDIATE,

539 report_row_height_ratios: tuple = (CONSTANT_REPORT_ROW_HEIGHT_RATIOS_INTERMEDIATE),

540 report_box_padding: dict | None = None,

541 **kwargs: Any,

542) -> Tuple[Figure, Axes]:

543 """

544 Generate the intermediate *ANSI/IES TM-30-18 Colour Rendition Report*

545 for the specified spectral distribution.

546

547 Parameters

548 ----------

549 sd

550 Spectral distribution of the emission source to generate the report

551 for.

552 report_size

553 Report size, defaults to A4 paper size in inches.

554 report_row_height_ratios

555 Report size row height ratios.

556 report_box_padding

557 Report box padding, defines the padding around the figure and

558 between the axes.

559

560 Other Parameters

561 ----------------

562 kwargs

563 {:func:`colour.plotting.artist`, :func:`colour.plotting.render`},

564 See the documentation of the previously listed definitions.

565

566 Returns

567 -------

568 :class:`tuple`

569 Current figure and axes.

570

571 Examples

572 --------

573 >>> from colour import SDS_ILLUMINANTS

574 >>> sd = SDS_ILLUMINANTS["FL2"]

575 >>> plot_single_sd_colour_rendition_report_intermediate(sd)

576 ... # doctest: +ELLIPSIS

577 (<Figure size ... with ... Axes>, <...Axes...>)

578

579 .. image:: ../_static/Plotting_\

580 Plot_Single_SD_Colour_Rendition_Report_Intermediate.png

581 :align: center

582 :alt: plot_single_sd_colour_rendition_report_intermediate

583 """

584

585 report_box_padding = optional(

586 report_box_padding, CONSTANT_REPORT_PADDING_INTERMEDIATE

587 )

588

589 specification = colour_fidelity_index_ANSIIESTM3018(sd, True)

590

591 figure = plt.figure(figsize=report_size, constrained_layout=True)

592

593 settings: Dict[str, Any] = dict(kwargs)

594 settings["show"] = False

595 settings["tight_layout"] = False

596

597 gridspec_report = figure.add_gridspec(3, 1, height_ratios=report_row_height_ratios)

598

599 # Title Row

600 gridspec_title = gridspec_report[0].subgridspec(1, 1)

601 axes_title = figure.add_subplot(gridspec_title[0])

602 _plot_report_header(axes_title)

603

604 # Main Figures Rows & Columns

605 gridspec_figures = gridspec_report[1].subgridspec(2, 2)

606

607 axes_vector_graphics = figure.add_subplot(gridspec_figures[0:2, 0])

608 plot_colour_vector_graphic(specification, axes=axes_vector_graphics, **settings)

609

610 axes_chroma_shifts = figure.add_subplot(gridspec_figures[0, 1])

611 plot_local_chroma_shifts(specification, axes=axes_chroma_shifts, **settings)

612

613 axes_hue_shifts = figure.add_subplot(gridspec_figures[1, 1])

614 plot_local_hue_shifts(

615 specification, axes=axes_hue_shifts, x_ticker=True, **settings

616 )

617

618 gridspec_footer = gridspec_report[2].subgridspec(1, 1)

619 axes_footer = figure.add_subplot(gridspec_footer[0])

620 _plot_report_footer(axes_footer)

621

622 figure.get_layout_engine().set(**report_box_padding) # pyright: ignore

623

624 settings = dict(kwargs)

625 settings["tight_layout"] = False

626

627 return render(**settings)

628

629

630 def plot_single_sd_colour_rendition_report_simple(

631 sd: SpectralDistribution,

632 report_size: tuple[float, float] = CONSTANT_REPORT_SIZE_SIMPLE,

633 report_row_height_ratios: tuple = CONSTANT_REPORT_ROW_HEIGHT_RATIOS_SIMPLE,

634 report_box_padding: dict | None = None,

635 **kwargs: Any,

636) -> Tuple[Figure, Axes]:

637 """

638 Generate the simple *ANSI/IES TM-30-18 Colour Rendition Report* for the

639 specified spectral distribution.

640

641 Parameters

642 ----------

643 sd

644 Spectral distribution of the emission source to generate the report

645 for.

646 report_size

647 Report size, defaults to A4 paper size in inches.

648 report_row_height_ratios

649 Report size row height ratios.

650 report_box_padding

651 Report box padding, defines the padding around the figure and

652 between the axes.

653

654 Other Parameters

655 ----------------

656 kwargs

657 {:func:`colour.plotting.artist`, :func:`colour.plotting.render`},

658 See the documentation of the previously listed definitions.

659

660 Returns

661 -------

662 :class:`tuple`

663 Current figure and axes.

664

665 Examples

666 --------

667 >>> from colour import SDS_ILLUMINANTS

668 >>> sd = SDS_ILLUMINANTS["FL2"]

669 >>> plot_single_sd_colour_rendition_report_simple(sd)

670 ... # doctest: +ELLIPSIS

671 (<Figure size ... with ... Axes>, <...Axes...>)

672

673 .. image:: ../_static/Plotting_\

674 Plot_Single_SD_Colour_Rendition_Report_Simple.png

675 :align: center

676 :alt: plot_single_sd_colour_rendition_report_simple

677 """

678

679 report_box_padding = optional(report_box_padding, CONSTANT_REPORT_PADDING_SIMPLE)

680

681 specification = colour_fidelity_index_ANSIIESTM3018(sd, True)

682

683 figure = plt.figure(figsize=report_size, constrained_layout=True)

684

685 settings: Dict[str, Any] = dict(kwargs)

686 settings["show"] = False

687 settings["tight_layout"] = False

688

689 gridspec_report = figure.add_gridspec(3, 1, height_ratios=report_row_height_ratios)

690

691 # Title Row

692 gridspec_title = gridspec_report[0].subgridspec(1, 1)

693 axes_title = figure.add_subplot(gridspec_title[0])

694 _plot_report_header(axes_title)

695

696 # Main Figures Rows & Columns

697 gridspec_figures = gridspec_report[1].subgridspec(1, 1)

698

699 axes_vector_graphics = figure.add_subplot(gridspec_figures[0, 0])

700 plot_colour_vector_graphic(specification, axes=axes_vector_graphics, **settings)

701

702 gridspec_footer = gridspec_report[2].subgridspec(1, 1)

703 axes_footer = figure.add_subplot(gridspec_footer[0])

704 _plot_report_footer(axes_footer)

705

706 figure.get_layout_engine().set(**report_box_padding) # pyright: ignore

707

708 settings = dict(kwargs)

709 settings["tight_layout"] = False

710

711 return render(**settings)

712

713

714 def plot_single_sd_colour_rendition_report(

715 sd: SpectralDistribution,

716 method: Literal["Full", "Intermediate", "Simple"] | str = "Full",

717 **kwargs: Any,

718) -> Tuple[Figure, Axes]:

719 """

720 Generate the *ANSI/IES TM-30-18 Colour Rendition Report* for the

721 specified spectral distribution using the specified method.

722

723 Parameters

724 ----------

725 sd

726 Spectral distribution of the emission source to generate the

727 report for.

728 method

729 Report plotting method.

730

731 Other Parameters

732 ----------------

733 kwargs

734 {:func:`colour.plotting.artist`, :func:`colour.plotting.render`,

735 :func:`colour.plotting.tm3018.\

736 plot_single_sd_colour_rendition_report_full`, :func:`colour.plotting.tm3018.\

737 plot_single_sd_colour_rendition_report_intermediate`, \

738:func:`colour.plotting.tm3018.plot_single_sd_colour_rendition_report_simple`}

739 See the documentation of the previously listed definitions.

740

741 Returns

742 -------

743 :class:`tuple`

744 Current figure and axes.

745

746 Examples

747 --------

748 >>> from colour import SDS_ILLUMINANTS

749 >>> sd = SDS_ILLUMINANTS["FL2"]

750 >>> plot_single_sd_colour_rendition_report(sd)

751 ... # doctest: +ELLIPSIS

752 (<Figure size ... with ... Axes>, <...Axes...>)

753

754 .. image:: ../_static/Plotting_\

755 Plot_Single_SD_Colour_Rendition_Report_Full.png

756 :align: center

757 :alt: plot_single_sd_colour_rendition_report_full

758

759 >>> plot_single_sd_colour_rendition_report(sd, "Intermediate")

760 ... # doctest: +ELLIPSIS

761 (<Figure size ... with ... Axes>, <...Axes...>)

762

763 .. image:: ../_static/Plotting_\

764 Plot_Single_SD_Colour_Rendition_Report_Intermediate.png

765 :align: center

766 :alt: plot_single_sd_colour_rendition_report_intermediate

767

768 >>> plot_single_sd_colour_rendition_report(sd, "Simple")

769 ... # doctest: +ELLIPSIS

770 (<Figure size ... with ... Axes>, <...Axes...>)

771

772 .. image:: ../_static/Plotting_\

773 Plot_Single_SD_Colour_Rendition_Report_Simple.png

774 :align: center

775 :alt: plot_single_sd_colour_rendition_report_simple

776 """

777

778 method = validate_method(method, ("Full", "Intermediate", "Simple"))

779

780 if method == "full":

781 return plot_single_sd_colour_rendition_report_full(sd, **kwargs)

782

783 if method == "intermediate":

784 return plot_single_sd_colour_rendition_report_intermediate(sd, **kwargs)

785

786 # method == 'simple'

787 return plot_single_sd_colour_rendition_report_simple(sd, **kwargs)