Coverage for graph/common.py: 55%

29 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-16 22:49 +1300

1""" 

2Graph Common Utilities 

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

4 

5Defines various common utilities for the graph module. 

6""" 

7 

8from __future__ import annotations 

9 

10import typing 

11 

12import numpy as np 

13 

14from colour.graph.conversion import conversion_path 

15from colour.utilities import as_float_array, get_domain_range_scale_metadata 

16 

17if typing.TYPE_CHECKING: 

18 from colour.hints import ArrayLike, NDArrayFloat 

19 

20__author__ = "Colour Developers" 

21__copyright__ = "Copyright 2013 Colour Developers" 

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

23__maintainer__ = "Colour Developers" 

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

25__status__ = "Production" 

26 

27__all__ = [ 

28 "colourspace_model_to_reference", 

29] 

30 

31 

32def colourspace_model_to_reference( 

33 a: ArrayLike, 

34 model: str, 

35) -> NDArrayFloat: 

36 """ 

37 Scale given colourspace model array from normalized [0, 1] to the model's 

38 reference scale by extracting scale metadata from the conversion function. 

39 

40 This function multiplies the input array by the model's reference scale 

41 (e.g., [0, 100] for CIE Lab) extracted from the XYZ_to_model conversion 

42 function's range annotation. 

43 

44 Parameters 

45 ---------- 

46 a 

47 Colourspace model array in normalized [0, 1] scale. 

48 model 

49 Colourspace model name (e.g., "CIE Lab", "CIE XYZ"). 

50 

51 Returns 

52 ------- 

53 :class:`numpy.ndarray` 

54 Colourspace model array scaled to reference scale. 

55 

56 Examples 

57 -------- 

58 >>> import numpy as np 

59 >>> Lab = np.array([0.41527875, 0.52638583, 0.26923179]) 

60 >>> colourspace_model_to_reference(Lab, "CIE Lab") # doctest: +ELLIPSIS 

61 array([ 41.527875..., 52.638583..., 26.923179...]) 

62 """ 

63 

64 import networkx as nx # noqa: PLC0415 

65 

66 a = as_float_array(a) 

67 

68 try: 

69 # Get conversion path from XYZ to model (lowercase for graph) 

70 path_functions = conversion_path("cie xyz", model.lower()) 

71 

72 # Get the last function in the path (final conversion to target model) 

73 if path_functions: 

74 last_function = path_functions[-1] 

75 metadata = get_domain_range_scale_metadata(last_function) 

76 range_scale = metadata.get("range") 

77 

78 if range_scale is not None: 

79 # Handle tuple scales (e.g., (100, 100, 360)) 

80 if isinstance(range_scale, tuple): 

81 scale_factor = np.array(range_scale) 

82 else: 

83 # Scalar scale applied uniformly 

84 scale_factor = range_scale 

85 

86 return a * scale_factor 

87 except (nx.NodeNotFound, nx.NetworkXNoPath): 

88 # Model not in graph or no conversion path exists 

89 pass 

90 

91 # Fallback: return unchanged if no scale metadata found 

92 return a