Coverage for colour/plotting/tm3018/report.py: 98%

185 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-15 19:01 +1300

1""" 

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

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

4 

5Define 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 

13from __future__ import annotations 

14 

15import typing 

16 

17if typing.TYPE_CHECKING: 

18 from matplotlib.figure import Figure 

19 from matplotlib.axes import Axes 

20 

21import matplotlib.pyplot as plt 

22 

23from colour.colorimetry import SpectralDistribution, sd_to_XYZ 

24 

25if typing.TYPE_CHECKING: 

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

27 

28from colour.io import SpectralDistribution_IESTM2714 

29from colour.models import Luv_to_uv, XYZ_to_Luv, XYZ_to_xy 

30from colour.plotting import CONSTANTS_COLOUR_STYLE, override_style, render 

31from 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) 

39from colour.quality import ( 

40 colour_fidelity_index_ANSIIESTM3018, 

41 colour_rendering_index, 

42) 

43from 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 

77CONSTANT_REPORT_SIZE_FULL: tuple = (8.27, 11.69) 

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

79 

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

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

82 

83CONSTANT_REPORT_PADDING_FULL: dict = { 

84 "w_pad": 20 / 100, 

85 "h_pad": 10 / 100, 

86 "hspace": 0, 

87 "wspace": 0, 

88} 

89""" 

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

91in-between the axes. 

92""" 

93 

94# Intermediate Report Size Constants 

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

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

97 

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

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

100 

101CONSTANT_REPORT_PADDING_INTERMEDIATE: dict = { 

102 "w_pad": 20 / 100, 

103 "h_pad": 10 / 100, 

104 "hspace": 0, 

105 "wspace": 0, 

106} 

107""" 

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

109and in-between the axes. 

110""" 

111 

112# Simple Report Size Constants 

113CONSTANT_REPORT_SIZE_SIMPLE: tuple = (8.27, 8.27) 

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

115 

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

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

118 

119CONSTANT_REPORT_PADDING_SIMPLE: dict = { 

120 "w_pad": 20 / 100, 

121 "h_pad": 10 / 100, 

122 "hspace": 0, 

123 "wspace": 0, 

124} 

125""" 

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

127and in-between the axes. 

128""" 

129 

130CONSTANTS_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 

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

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

151 

152CONTENT_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 

160def _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 

190def _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) 

228def 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_\ 

297Plot_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) 

536def 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_\ 

580Plot_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 

630def 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_\ 

674Plot_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 

714def 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.\ 

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

737plot_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_\ 

755Plot_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_\ 

764Plot_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_\ 

773Plot_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)