bluer-objects 6.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of bluer-objects might be problematic. Click here for more details.

Files changed (149) hide show
  1. bluer_objects/.abcli/abcli.sh +9 -0
  2. bluer_objects/.abcli/actions.sh +11 -0
  3. bluer_objects/.abcli/aka.sh +3 -0
  4. bluer_objects/.abcli/alias.sh +36 -0
  5. bluer_objects/.abcli/blue_objects.sh +11 -0
  6. bluer_objects/.abcli/cache.sh +5 -0
  7. bluer_objects/.abcli/clone.sh +94 -0
  8. bluer_objects/.abcli/download.sh +53 -0
  9. bluer_objects/.abcli/file.sh +8 -0
  10. bluer_objects/.abcli/gif.sh +27 -0
  11. bluer_objects/.abcli/host.sh +29 -0
  12. bluer_objects/.abcli/ls.sh +24 -0
  13. bluer_objects/.abcli/metadata/get.sh +24 -0
  14. bluer_objects/.abcli/metadata/post.sh +22 -0
  15. bluer_objects/.abcli/metadata.sh +16 -0
  16. bluer_objects/.abcli/mlflow/browse.sh +36 -0
  17. bluer_objects/.abcli/mlflow/cache.sh +31 -0
  18. bluer_objects/.abcli/mlflow/list_registered_models.sh +9 -0
  19. bluer_objects/.abcli/mlflow/log_artifacts.sh +10 -0
  20. bluer_objects/.abcli/mlflow/log_run.sh +10 -0
  21. bluer_objects/.abcli/mlflow/run.sh +11 -0
  22. bluer_objects/.abcli/mlflow/tags/clone.sh +15 -0
  23. bluer_objects/.abcli/mlflow/tags/get.sh +10 -0
  24. bluer_objects/.abcli/mlflow/tags/search.sh +12 -0
  25. bluer_objects/.abcli/mlflow/tags/set.sh +13 -0
  26. bluer_objects/.abcli/mlflow/tags.sh +16 -0
  27. bluer_objects/.abcli/mlflow/test.sh +11 -0
  28. bluer_objects/.abcli/mlflow/transition.sh +20 -0
  29. bluer_objects/.abcli/mlflow.sh +29 -0
  30. bluer_objects/.abcli/mysql/cache.sh +65 -0
  31. bluer_objects/.abcli/mysql/relations.sh +83 -0
  32. bluer_objects/.abcli/mysql/tags.sh +85 -0
  33. bluer_objects/.abcli/mysql.sh +16 -0
  34. bluer_objects/.abcli/object.sh +54 -0
  35. bluer_objects/.abcli/publish.sh +58 -0
  36. bluer_objects/.abcli/select.sh +34 -0
  37. bluer_objects/.abcli/storage/clear.sh +45 -0
  38. bluer_objects/.abcli/storage/download_file.sh +9 -0
  39. bluer_objects/.abcli/storage/exists.sh +8 -0
  40. bluer_objects/.abcli/storage/list.sh +8 -0
  41. bluer_objects/.abcli/storage/rm.sh +11 -0
  42. bluer_objects/.abcli/storage/status.sh +11 -0
  43. bluer_objects/.abcli/storage.sh +15 -0
  44. bluer_objects/.abcli/tags.sh +5 -0
  45. bluer_objects/.abcli/tests/README.sh +8 -0
  46. bluer_objects/.abcli/tests/clone.sh +32 -0
  47. bluer_objects/.abcli/tests/help.sh +85 -0
  48. bluer_objects/.abcli/tests/host.sh +7 -0
  49. bluer_objects/.abcli/tests/ls.sh +13 -0
  50. bluer_objects/.abcli/tests/metadata.sh +53 -0
  51. bluer_objects/.abcli/tests/mlflow_cache.sh +14 -0
  52. bluer_objects/.abcli/tests/mlflow_logging.sh +12 -0
  53. bluer_objects/.abcli/tests/mlflow_tags.sh +29 -0
  54. bluer_objects/.abcli/tests/mlflow_test.sh +7 -0
  55. bluer_objects/.abcli/tests/mysql_cache.sh +15 -0
  56. bluer_objects/.abcli/tests/mysql_relations.sh +20 -0
  57. bluer_objects/.abcli/tests/mysql_tags.sh +16 -0
  58. bluer_objects/.abcli/tests/test_gif.sh +13 -0
  59. bluer_objects/.abcli/tests/version.sh +10 -0
  60. bluer_objects/.abcli/upload.sh +73 -0
  61. bluer_objects/README/__init__.py +29 -0
  62. bluer_objects/README/functions.py +285 -0
  63. bluer_objects/README/items.py +30 -0
  64. bluer_objects/__init__.py +19 -0
  65. bluer_objects/__main__.py +16 -0
  66. bluer_objects/config.env +22 -0
  67. bluer_objects/env.py +72 -0
  68. bluer_objects/file/__init__.py +41 -0
  69. bluer_objects/file/__main__.py +51 -0
  70. bluer_objects/file/classes.py +38 -0
  71. bluer_objects/file/functions.py +290 -0
  72. bluer_objects/file/load.py +219 -0
  73. bluer_objects/file/save.py +280 -0
  74. bluer_objects/graphics/__init__.py +4 -0
  75. bluer_objects/graphics/__main__.py +84 -0
  76. bluer_objects/graphics/frame.py +15 -0
  77. bluer_objects/graphics/gif.py +86 -0
  78. bluer_objects/graphics/screen.py +63 -0
  79. bluer_objects/graphics/signature.py +97 -0
  80. bluer_objects/graphics/text.py +165 -0
  81. bluer_objects/help/__init__.py +0 -0
  82. bluer_objects/help/__main__.py +10 -0
  83. bluer_objects/help/functions.py +5 -0
  84. bluer_objects/host/__init__.py +1 -0
  85. bluer_objects/host/__main__.py +84 -0
  86. bluer_objects/host/functions.py +66 -0
  87. bluer_objects/logger/__init__.py +4 -0
  88. bluer_objects/logger/matrix.py +209 -0
  89. bluer_objects/markdown.py +43 -0
  90. bluer_objects/metadata/__init__.py +8 -0
  91. bluer_objects/metadata/__main__.py +110 -0
  92. bluer_objects/metadata/enums.py +29 -0
  93. bluer_objects/metadata/get.py +89 -0
  94. bluer_objects/metadata/post.py +101 -0
  95. bluer_objects/mlflow/__init__.py +28 -0
  96. bluer_objects/mlflow/__main__.py +271 -0
  97. bluer_objects/mlflow/cache.py +13 -0
  98. bluer_objects/mlflow/logging.py +81 -0
  99. bluer_objects/mlflow/models.py +57 -0
  100. bluer_objects/mlflow/objects.py +76 -0
  101. bluer_objects/mlflow/runs.py +100 -0
  102. bluer_objects/mlflow/tags.py +90 -0
  103. bluer_objects/mlflow/testing.py +39 -0
  104. bluer_objects/mysql/cache/__init__.py +8 -0
  105. bluer_objects/mysql/cache/__main__.py +91 -0
  106. bluer_objects/mysql/cache/functions.py +181 -0
  107. bluer_objects/mysql/relations/__init__.py +9 -0
  108. bluer_objects/mysql/relations/__main__.py +138 -0
  109. bluer_objects/mysql/relations/functions.py +180 -0
  110. bluer_objects/mysql/table.py +144 -0
  111. bluer_objects/mysql/tags/__init__.py +1 -0
  112. bluer_objects/mysql/tags/__main__.py +130 -0
  113. bluer_objects/mysql/tags/functions.py +203 -0
  114. bluer_objects/objects.py +167 -0
  115. bluer_objects/path.py +194 -0
  116. bluer_objects/sample.env +16 -0
  117. bluer_objects/storage/__init__.py +3 -0
  118. bluer_objects/storage/__main__.py +114 -0
  119. bluer_objects/storage/classes.py +237 -0
  120. bluer_objects/tests/__init__.py +0 -0
  121. bluer_objects/tests/test_README.py +5 -0
  122. bluer_objects/tests/test_env.py +27 -0
  123. bluer_objects/tests/test_file_load_save.py +105 -0
  124. bluer_objects/tests/test_fullname.py +5 -0
  125. bluer_objects/tests/test_graphics.py +28 -0
  126. bluer_objects/tests/test_graphics_frame.py +11 -0
  127. bluer_objects/tests/test_graphics_gif.py +29 -0
  128. bluer_objects/tests/test_graphics_screen.py +8 -0
  129. bluer_objects/tests/test_graphics_signature.py +80 -0
  130. bluer_objects/tests/test_graphics_text.py +14 -0
  131. bluer_objects/tests/test_logger.py +5 -0
  132. bluer_objects/tests/test_logger_matrix.py +73 -0
  133. bluer_objects/tests/test_markdown.py +10 -0
  134. bluer_objects/tests/test_metadata.py +204 -0
  135. bluer_objects/tests/test_mlflow.py +60 -0
  136. bluer_objects/tests/test_mysql_cache.py +14 -0
  137. bluer_objects/tests/test_mysql_relations.py +16 -0
  138. bluer_objects/tests/test_mysql_table.py +9 -0
  139. bluer_objects/tests/test_mysql_tags.py +13 -0
  140. bluer_objects/tests/test_objects.py +180 -0
  141. bluer_objects/tests/test_path.py +7 -0
  142. bluer_objects/tests/test_storage.py +7 -0
  143. bluer_objects/tests/test_version.py +5 -0
  144. bluer_objects/urls.py +3 -0
  145. bluer_objects-6.3.1.dist-info/METADATA +57 -0
  146. bluer_objects-6.3.1.dist-info/RECORD +149 -0
  147. bluer_objects-6.3.1.dist-info/WHEEL +5 -0
  148. bluer_objects-6.3.1.dist-info/licenses/LICENSE +121 -0
  149. bluer_objects-6.3.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,165 @@
1
+ from typing import Tuple, List, Union
2
+ import cv2
3
+ from functools import reduce
4
+ import numpy as np
5
+
6
+ from blueness import module
7
+
8
+ from bluer_objects import NAME
9
+ from bluer_objects.logger import logger
10
+
11
+ NAME = module.name(__file__, NAME)
12
+
13
+
14
+ def render_text(
15
+ text: List[str],
16
+ box: bool = False,
17
+ centered: bool = False,
18
+ color_depth: int = 3,
19
+ font_color: Union[Tuple, List, int] = 3 * (127,),
20
+ font_face: int = cv2.FONT_HERSHEY_SIMPLEX,
21
+ font_size: int = 2,
22
+ height: float = 1.0,
23
+ image: Union[None, np.array] = None,
24
+ image_width: Union[None, int] = None,
25
+ left: float = 0.0,
26
+ line_type: int = cv2.LINE_AA,
27
+ thickness: int = 1,
28
+ top: float = 0.0,
29
+ width: float = 1.0,
30
+ ) -> np.ndarray:
31
+ if image is None:
32
+ if image_width is None:
33
+ logger.error(f"-{NAME}: render_text(None): image_width is missing.")
34
+ return image
35
+ else:
36
+ if not image.shape or len(image.shape) < 2:
37
+ return image
38
+
39
+ if not isinstance(font_color, list) and not isinstance(font_color, tuple):
40
+ font_color = 3 * (font_color,)
41
+
42
+ if not isinstance(text, list):
43
+ text = [text]
44
+
45
+ # https://stackoverflow.com/a/51285918/10917551
46
+ # (label_width, label_height), baseline
47
+ text_line_size = [
48
+ cv2.getTextSize(
49
+ text=text_line,
50
+ fontFace=font_face,
51
+ fontScale=font_size,
52
+ thickness=thickness,
53
+ )
54
+ for text_line in text
55
+ ]
56
+
57
+ required_text_height = reduce(
58
+ lambda x, y: x + y,
59
+ [
60
+ text_line_size_[0][1] + text_line_size_[1] + 2
61
+ for text_line_size_ in text_line_size
62
+ ],
63
+ 0,
64
+ )
65
+ required_text_width = max(
66
+ [text_line_size_[0][0] for text_line_size_ in text_line_size]
67
+ )
68
+
69
+ if image is None:
70
+ text_width = int(image_width * width)
71
+
72
+ font_size *= text_width / required_text_width
73
+ else:
74
+ text_height = int(image.shape[0] * height)
75
+ text_width = int(image.shape[1] * width)
76
+
77
+ font_size *= min(
78
+ [text_width / required_text_width, text_height / required_text_height]
79
+ )
80
+
81
+ # (label_width, label_height), baseline
82
+ text_line_size = [
83
+ cv2.getTextSize(
84
+ text=text_line,
85
+ fontFace=font_face,
86
+ fontScale=font_size,
87
+ thickness=thickness,
88
+ )
89
+ for text_line in text
90
+ ]
91
+
92
+ required_text_height = reduce(
93
+ lambda x, y: x + y,
94
+ [
95
+ text_line_size_[0][1] + text_line_size_[1] + 2
96
+ for text_line_size_ in text_line_size
97
+ ],
98
+ 0,
99
+ )
100
+
101
+ if image is None:
102
+ image = np.zeros(
103
+ (required_text_height, image_width, color_depth),
104
+ dtype=np.uint8,
105
+ )
106
+
107
+ text_height = int(image.shape[0] * height)
108
+ text_width = int(image.shape[1] * width)
109
+
110
+ line_spacing = (text_height - required_text_height) / (1 + len(text))
111
+
112
+ text_left = int(image.shape[1] * left)
113
+ text_top = int(image.shape[0] * top)
114
+
115
+ x = text_left
116
+ y = text_top + line_spacing
117
+ for index, text_line in enumerate(text):
118
+ y += text_line_size[index][0][1] + 2
119
+
120
+ actual_x = int(
121
+ x + text_width / 2 - text_line_size[index][0][0] / 2 if centered else x
122
+ )
123
+
124
+ cv2.putText(
125
+ image,
126
+ text=text_line,
127
+ org=(
128
+ actual_x,
129
+ int(y),
130
+ ),
131
+ fontFace=font_face,
132
+ fontScale=font_size,
133
+ color=font_color,
134
+ lineType=line_type,
135
+ thickness=thickness,
136
+ )
137
+ if box:
138
+ cv2.rectangle(
139
+ image,
140
+ (
141
+ int(actual_x),
142
+ int(y - text_line_size[index][0][1]),
143
+ ),
144
+ (
145
+ int(actual_x + text_line_size[index][0][0]),
146
+ int(y + text_line_size[index][1]),
147
+ ),
148
+ color=font_color,
149
+ thickness=thickness // 2,
150
+ lineType=line_type,
151
+ )
152
+
153
+ y += line_spacing
154
+
155
+ if box:
156
+ cv2.rectangle(
157
+ image,
158
+ (text_left, text_top),
159
+ (text_left + text_width, text_top + text_height),
160
+ color=font_color,
161
+ thickness=thickness,
162
+ lineType=line_type,
163
+ )
164
+
165
+ return image
File without changes
@@ -0,0 +1,10 @@
1
+ from blueness import module
2
+ from blue_options.help.functions import help_main
3
+
4
+ from bluer_objects import NAME
5
+ from bluer_objects.help.functions import help_functions
6
+
7
+ NAME = module.name(__file__, NAME)
8
+
9
+
10
+ help_main(NAME, help_functions)
@@ -0,0 +1,5 @@
1
+ from abcli.help.generic import help_functions as generic_help_functions
2
+
3
+ from bluer_objects import ALIAS
4
+
5
+ help_functions = generic_help_functions(plugin_name=ALIAS)
@@ -0,0 +1 @@
1
+ from bluer_objects.host.functions import shell, unzip
@@ -0,0 +1,84 @@
1
+ import argparse
2
+
3
+ from blueness import module
4
+ from blueness.argparse.generic import sys_exit
5
+
6
+ from bluer_objects import NAME, file
7
+ from blue_options.host import signature as host_signature
8
+ from bluer_objects.graphics import add_signature
9
+ from bluer_objects.objects import signature as object_signature
10
+ from bluer_objects.logger import logger
11
+
12
+ NAME = module.name(__file__, NAME)
13
+
14
+ parser = argparse.ArgumentParser(NAME)
15
+ parser.add_argument(
16
+ "task",
17
+ type=str,
18
+ default="get",
19
+ help="add_signature",
20
+ )
21
+ parser.add_argument(
22
+ "--application",
23
+ type=str,
24
+ default="",
25
+ )
26
+ parser.add_argument(
27
+ "--header",
28
+ type=str,
29
+ default="",
30
+ help="this|that",
31
+ )
32
+ parser.add_argument(
33
+ "--filename",
34
+ type=str,
35
+ default="",
36
+ )
37
+ parser.add_argument(
38
+ "--footer",
39
+ type=str,
40
+ default="",
41
+ help="this|that",
42
+ )
43
+ parser.add_argument(
44
+ "--item_name",
45
+ default="tag",
46
+ type=str,
47
+ )
48
+ parser.add_argument(
49
+ "--log",
50
+ default=1,
51
+ type=int,
52
+ help="0|1",
53
+ )
54
+ parser.add_argument(
55
+ "--word_wrap",
56
+ default=0,
57
+ type=int,
58
+ help="0|1",
59
+ )
60
+ args = parser.parse_args()
61
+
62
+ success = False
63
+ if args.task == "add_signature":
64
+ success, image = file.load_image(args.filename)
65
+ if success:
66
+ success = file.save_image(
67
+ args.filename,
68
+ add_signature(
69
+ image,
70
+ [args.header] + [" | ".join(object_signature())],
71
+ [args.footer] + [" | ".join([args.application] + host_signature())],
72
+ word_wrap=args.word_wrap,
73
+ ),
74
+ )
75
+
76
+ if success:
77
+ logger.info(
78
+ f"{NAME}.add_signature({args.filename},{args.header},{args.footer})"
79
+ )
80
+ else:
81
+ success = None
82
+
83
+
84
+ sys_exit(logger, NAME, args.task, success, log=args.log)
@@ -0,0 +1,66 @@
1
+ import os
2
+ from typing import Union, Tuple, List
3
+
4
+ from blueness import module
5
+ from blue_options.logger import crash_report
6
+
7
+ from bluer_objects import NAME, file
8
+ from bluer_objects.logger import logger
9
+
10
+ NAME = module.name(__file__, NAME)
11
+
12
+
13
+ def shell(
14
+ command: str,
15
+ clean_after: bool = False,
16
+ return_output: bool = False,
17
+ work_dir: str = ".",
18
+ log: bool = False,
19
+ ) -> Union[
20
+ bool,
21
+ Tuple[bool, List[str]],
22
+ ]:
23
+ if log:
24
+ logger.info(f"{NAME}.shell({command})")
25
+
26
+ success = True
27
+ output = []
28
+
29
+ if return_output:
30
+ output_filename = file.auxiliary("shell", "txt")
31
+ command += f" > {output_filename}"
32
+
33
+ current_path = os.getcwd()
34
+ try:
35
+ os.chdir(work_dir)
36
+
37
+ try:
38
+ os.system(command)
39
+ except:
40
+ crash_report(f"host.shell({command}) failed")
41
+ success = False
42
+
43
+ finally:
44
+ os.chdir(current_path)
45
+
46
+ if success and return_output:
47
+ success, output = file.load_text(output_filename)
48
+
49
+ if clean_after:
50
+ file.delete(output_filename)
51
+
52
+ return (success, output) if return_output else success
53
+
54
+
55
+ def unzip(
56
+ zip_filename: str,
57
+ output_folder: str = "",
58
+ log: bool = False,
59
+ ) -> bool:
60
+ if not output_folder:
61
+ output_folder = file.path(zip_filename)
62
+
63
+ return shell(
64
+ command=f'unzip -q -o "{zip_filename}" -d "{output_folder}"',
65
+ log=log,
66
+ )
@@ -0,0 +1,4 @@
1
+ from blue_options.logger import get_logger
2
+ from bluer_objects import ICON
3
+
4
+ logger = get_logger(ICON)
@@ -0,0 +1,209 @@
1
+ from typing import List, Tuple
2
+ import numpy as np
3
+ import matplotlib.pyplot as plt
4
+ import math
5
+ import cv2
6
+
7
+ from blueness import module
8
+ from blue_options import string
9
+ from abcli.host import signature
10
+
11
+ from bluer_objects import NAME
12
+ from bluer_objects import file
13
+ from bluer_objects.graphics.signature import add_signature, justify_text
14
+ from bluer_objects.logger import logger
15
+
16
+ NAME = module.name(__file__, NAME)
17
+
18
+
19
+ def log_matrix(
20
+ matrix: np.ndarray,
21
+ header: List[str],
22
+ footer: List[str],
23
+ filename: str,
24
+ dynamic_range: Tuple[float] = (-100, 100),
25
+ line_width: int = 80,
26
+ min_width: int = 1200,
27
+ max_width: int = 2400,
28
+ colorbar_width: int = 20,
29
+ colormap: int = -1, # example: cv2.COLORMAP_JET
30
+ invert_color_map: bool = True,
31
+ invert_color_map_rgb: bool = True,
32
+ verbose: bool = False,
33
+ log: bool = True,
34
+ log_range: bool = False,
35
+ log_shape_of_matrix: bool = True,
36
+ suffix: List[np.ndarray] = [],
37
+ ) -> bool:
38
+ if log:
39
+ logger.info(
40
+ "{}.log_matrix({})".format(
41
+ NAME,
42
+ string.pretty_shape_of_matrix(matrix),
43
+ )
44
+ )
45
+
46
+ shape_of_matrix = string.pretty_shape_of_matrix(matrix)
47
+
48
+ range_signature: List[str] = (
49
+ [f"range: {string.pretty_range_of_matrix(matrix)}"] if log_range else []
50
+ )
51
+
52
+ scale = 1
53
+ if min_width != -1 and matrix.shape[1] < min_width and matrix.shape[1] > 0:
54
+ scale = int(math.ceil(min_width / matrix.shape[1]))
55
+ elif max_width != -1 and (
56
+ matrix.shape[0] > max_width or matrix.shape[1] > max_width
57
+ ):
58
+ scale = min([max_width / matrix.shape[index] for index in [0, 1]])
59
+
60
+ if scale != 1:
61
+ if verbose:
62
+ logger.info(f"scale: {scale}")
63
+
64
+ matrix = cv2.resize(
65
+ matrix,
66
+ (
67
+ int(scale * matrix.shape[1]),
68
+ int(scale * matrix.shape[0]),
69
+ ),
70
+ interpolation=cv2.INTER_NEAREST_EXACT,
71
+ )
72
+
73
+ if colormap != -1:
74
+ normalized_matrix = (matrix - dynamic_range[0]) / (
75
+ dynamic_range[1] - dynamic_range[0]
76
+ )
77
+ normalized_matrix[normalized_matrix < 0] = 0
78
+ normalized_matrix[normalized_matrix > 1] = 1
79
+
80
+ colored_matrix = cv2.applyColorMap(
81
+ (
82
+ (1 - normalized_matrix if invert_color_map else normalized_matrix) * 255
83
+ ).astype(np.uint8),
84
+ colormap,
85
+ )
86
+ if not invert_color_map_rgb:
87
+ colored_matrix = colored_matrix[:, :, [2, 1, 0]]
88
+
89
+ gradient = (
90
+ 255
91
+ * np.linspace(0, 1, colored_matrix.shape[0]).reshape(-1, 1)
92
+ * np.ones((1, colorbar_width))
93
+ ).astype(np.uint8)
94
+ colorbar = cv2.applyColorMap(gradient, colormap)
95
+ if not invert_color_map:
96
+ colorbar = np.flipud(colorbar)
97
+ if not invert_color_map_rgb:
98
+ colorbar = colorbar[:, :, [2, 1, 0]]
99
+
100
+ colored_matrix = np.hstack(
101
+ (
102
+ colored_matrix,
103
+ np.zeros(
104
+ (colored_matrix.shape[0], colorbar_width // 2, 3),
105
+ dtype=np.uint8,
106
+ ),
107
+ colorbar,
108
+ )
109
+ )
110
+
111
+ matrix = colored_matrix
112
+
113
+ if suffix:
114
+ if scale != 1:
115
+ suffix = [
116
+ cv2.resize(
117
+ matrix,
118
+ (
119
+ int(scale * matrix.shape[1]),
120
+ int(scale * matrix.shape[0]),
121
+ ),
122
+ interpolation=cv2.INTER_NEAREST_EXACT,
123
+ )
124
+ for matrix in suffix
125
+ ]
126
+
127
+ matrix = np.concatenate([matrix] + suffix, axis=1)
128
+
129
+ matrix = add_signature(
130
+ matrix,
131
+ header=[
132
+ " | ".join(
133
+ header
134
+ + ([shape_of_matrix] if log_shape_of_matrix else [])
135
+ + [
136
+ f"scale: {scale:.2f}X",
137
+ ]
138
+ + (
139
+ []
140
+ if colormap == -1
141
+ else [
142
+ "dynamic-range: ( {:.03f} , {:.03f} )".format(
143
+ dynamic_range[0],
144
+ dynamic_range[1],
145
+ ),
146
+ ]
147
+ )
148
+ + range_signature
149
+ )
150
+ ],
151
+ footer=[" | ".join(footer + signature())],
152
+ word_wrap=True,
153
+ line_width=line_width,
154
+ )
155
+
156
+ return file.save_image(filename, matrix, log=verbose)
157
+
158
+
159
+ def log_matrix_hist(
160
+ matrix: np.ndarray,
161
+ dynamic_range: Tuple[float],
162
+ filename: str,
163
+ header: List[str] = [],
164
+ footer: List[str] = [],
165
+ line_width: int = 80,
166
+ bins: int = 64,
167
+ ylabel: str = "frequency",
168
+ log: bool = True,
169
+ verbose: bool = False,
170
+ ) -> bool:
171
+ if log:
172
+ logger.info(
173
+ "{}.log_matrix_hist({})".format(
174
+ NAME,
175
+ string.pretty_shape_of_matrix(matrix),
176
+ )
177
+ )
178
+
179
+ plt.figure(figsize=(10, 6))
180
+ plt.hist(
181
+ matrix.ravel(),
182
+ bins=bins,
183
+ range=dynamic_range,
184
+ )
185
+ plt.title(
186
+ justify_text(
187
+ " | ".join(
188
+ header
189
+ + [
190
+ string.pretty_shape_of_matrix(matrix),
191
+ f"dynamic-range: {dynamic_range}",
192
+ f"bins: {bins}",
193
+ ]
194
+ ),
195
+ line_width=line_width,
196
+ return_str=True,
197
+ )
198
+ )
199
+ plt.xlabel(
200
+ justify_text(
201
+ " | ".join(footer + signature()),
202
+ line_width=line_width,
203
+ return_str=True,
204
+ )
205
+ )
206
+ plt.ylabel(ylabel)
207
+ plt.grid(True)
208
+
209
+ return file.save_fig(filename, log=verbose)
@@ -0,0 +1,43 @@
1
+ from typing import List
2
+ import math
3
+
4
+ from blueness import module
5
+
6
+ from bluer_objects import NAME
7
+ from bluer_objects.logger import logger
8
+
9
+ NAME = module.name(__file__, NAME)
10
+
11
+
12
+ def generate_table(
13
+ items: List[str],
14
+ cols: int = 3,
15
+ ) -> List[str]:
16
+ if not items:
17
+ return []
18
+
19
+ items_dict = {index: item for index, item in enumerate(items)}
20
+
21
+ cols = min(cols, len(items))
22
+
23
+ row_count = int(math.ceil(len(items) / cols))
24
+
25
+ logger.info(
26
+ "{}.generate_table(): {} item(s), {} row(s)".format(
27
+ NAME,
28
+ len(items),
29
+ row_count,
30
+ )
31
+ )
32
+
33
+ return [
34
+ "| {} |".format(" | ".join(cols * [" "])),
35
+ "| {} |".format(" | ".join(cols * ["---"])),
36
+ ] + [
37
+ "| {} |".format(
38
+ " | ".join(
39
+ [items_dict.get(cols * row_index + index, "") for index in range(cols)]
40
+ )
41
+ )
42
+ for row_index in range(row_count)
43
+ ]
@@ -0,0 +1,8 @@
1
+ from bluer_objects.metadata.enums import MetadataSourceType
2
+ from bluer_objects.metadata.get import (
3
+ get,
4
+ get_from_file,
5
+ get_from_object,
6
+ get_from_path,
7
+ )
8
+ from bluer_objects.metadata.post import post, post_to_file, post_to_object, post_to_path