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.
- bluer_objects/.abcli/abcli.sh +9 -0
- bluer_objects/.abcli/actions.sh +11 -0
- bluer_objects/.abcli/aka.sh +3 -0
- bluer_objects/.abcli/alias.sh +36 -0
- bluer_objects/.abcli/blue_objects.sh +11 -0
- bluer_objects/.abcli/cache.sh +5 -0
- bluer_objects/.abcli/clone.sh +94 -0
- bluer_objects/.abcli/download.sh +53 -0
- bluer_objects/.abcli/file.sh +8 -0
- bluer_objects/.abcli/gif.sh +27 -0
- bluer_objects/.abcli/host.sh +29 -0
- bluer_objects/.abcli/ls.sh +24 -0
- bluer_objects/.abcli/metadata/get.sh +24 -0
- bluer_objects/.abcli/metadata/post.sh +22 -0
- bluer_objects/.abcli/metadata.sh +16 -0
- bluer_objects/.abcli/mlflow/browse.sh +36 -0
- bluer_objects/.abcli/mlflow/cache.sh +31 -0
- bluer_objects/.abcli/mlflow/list_registered_models.sh +9 -0
- bluer_objects/.abcli/mlflow/log_artifacts.sh +10 -0
- bluer_objects/.abcli/mlflow/log_run.sh +10 -0
- bluer_objects/.abcli/mlflow/run.sh +11 -0
- bluer_objects/.abcli/mlflow/tags/clone.sh +15 -0
- bluer_objects/.abcli/mlflow/tags/get.sh +10 -0
- bluer_objects/.abcli/mlflow/tags/search.sh +12 -0
- bluer_objects/.abcli/mlflow/tags/set.sh +13 -0
- bluer_objects/.abcli/mlflow/tags.sh +16 -0
- bluer_objects/.abcli/mlflow/test.sh +11 -0
- bluer_objects/.abcli/mlflow/transition.sh +20 -0
- bluer_objects/.abcli/mlflow.sh +29 -0
- bluer_objects/.abcli/mysql/cache.sh +65 -0
- bluer_objects/.abcli/mysql/relations.sh +83 -0
- bluer_objects/.abcli/mysql/tags.sh +85 -0
- bluer_objects/.abcli/mysql.sh +16 -0
- bluer_objects/.abcli/object.sh +54 -0
- bluer_objects/.abcli/publish.sh +58 -0
- bluer_objects/.abcli/select.sh +34 -0
- bluer_objects/.abcli/storage/clear.sh +45 -0
- bluer_objects/.abcli/storage/download_file.sh +9 -0
- bluer_objects/.abcli/storage/exists.sh +8 -0
- bluer_objects/.abcli/storage/list.sh +8 -0
- bluer_objects/.abcli/storage/rm.sh +11 -0
- bluer_objects/.abcli/storage/status.sh +11 -0
- bluer_objects/.abcli/storage.sh +15 -0
- bluer_objects/.abcli/tags.sh +5 -0
- bluer_objects/.abcli/tests/README.sh +8 -0
- bluer_objects/.abcli/tests/clone.sh +32 -0
- bluer_objects/.abcli/tests/help.sh +85 -0
- bluer_objects/.abcli/tests/host.sh +7 -0
- bluer_objects/.abcli/tests/ls.sh +13 -0
- bluer_objects/.abcli/tests/metadata.sh +53 -0
- bluer_objects/.abcli/tests/mlflow_cache.sh +14 -0
- bluer_objects/.abcli/tests/mlflow_logging.sh +12 -0
- bluer_objects/.abcli/tests/mlflow_tags.sh +29 -0
- bluer_objects/.abcli/tests/mlflow_test.sh +7 -0
- bluer_objects/.abcli/tests/mysql_cache.sh +15 -0
- bluer_objects/.abcli/tests/mysql_relations.sh +20 -0
- bluer_objects/.abcli/tests/mysql_tags.sh +16 -0
- bluer_objects/.abcli/tests/test_gif.sh +13 -0
- bluer_objects/.abcli/tests/version.sh +10 -0
- bluer_objects/.abcli/upload.sh +73 -0
- bluer_objects/README/__init__.py +29 -0
- bluer_objects/README/functions.py +285 -0
- bluer_objects/README/items.py +30 -0
- bluer_objects/__init__.py +19 -0
- bluer_objects/__main__.py +16 -0
- bluer_objects/config.env +22 -0
- bluer_objects/env.py +72 -0
- bluer_objects/file/__init__.py +41 -0
- bluer_objects/file/__main__.py +51 -0
- bluer_objects/file/classes.py +38 -0
- bluer_objects/file/functions.py +290 -0
- bluer_objects/file/load.py +219 -0
- bluer_objects/file/save.py +280 -0
- bluer_objects/graphics/__init__.py +4 -0
- bluer_objects/graphics/__main__.py +84 -0
- bluer_objects/graphics/frame.py +15 -0
- bluer_objects/graphics/gif.py +86 -0
- bluer_objects/graphics/screen.py +63 -0
- bluer_objects/graphics/signature.py +97 -0
- bluer_objects/graphics/text.py +165 -0
- bluer_objects/help/__init__.py +0 -0
- bluer_objects/help/__main__.py +10 -0
- bluer_objects/help/functions.py +5 -0
- bluer_objects/host/__init__.py +1 -0
- bluer_objects/host/__main__.py +84 -0
- bluer_objects/host/functions.py +66 -0
- bluer_objects/logger/__init__.py +4 -0
- bluer_objects/logger/matrix.py +209 -0
- bluer_objects/markdown.py +43 -0
- bluer_objects/metadata/__init__.py +8 -0
- bluer_objects/metadata/__main__.py +110 -0
- bluer_objects/metadata/enums.py +29 -0
- bluer_objects/metadata/get.py +89 -0
- bluer_objects/metadata/post.py +101 -0
- bluer_objects/mlflow/__init__.py +28 -0
- bluer_objects/mlflow/__main__.py +271 -0
- bluer_objects/mlflow/cache.py +13 -0
- bluer_objects/mlflow/logging.py +81 -0
- bluer_objects/mlflow/models.py +57 -0
- bluer_objects/mlflow/objects.py +76 -0
- bluer_objects/mlflow/runs.py +100 -0
- bluer_objects/mlflow/tags.py +90 -0
- bluer_objects/mlflow/testing.py +39 -0
- bluer_objects/mysql/cache/__init__.py +8 -0
- bluer_objects/mysql/cache/__main__.py +91 -0
- bluer_objects/mysql/cache/functions.py +181 -0
- bluer_objects/mysql/relations/__init__.py +9 -0
- bluer_objects/mysql/relations/__main__.py +138 -0
- bluer_objects/mysql/relations/functions.py +180 -0
- bluer_objects/mysql/table.py +144 -0
- bluer_objects/mysql/tags/__init__.py +1 -0
- bluer_objects/mysql/tags/__main__.py +130 -0
- bluer_objects/mysql/tags/functions.py +203 -0
- bluer_objects/objects.py +167 -0
- bluer_objects/path.py +194 -0
- bluer_objects/sample.env +16 -0
- bluer_objects/storage/__init__.py +3 -0
- bluer_objects/storage/__main__.py +114 -0
- bluer_objects/storage/classes.py +237 -0
- bluer_objects/tests/__init__.py +0 -0
- bluer_objects/tests/test_README.py +5 -0
- bluer_objects/tests/test_env.py +27 -0
- bluer_objects/tests/test_file_load_save.py +105 -0
- bluer_objects/tests/test_fullname.py +5 -0
- bluer_objects/tests/test_graphics.py +28 -0
- bluer_objects/tests/test_graphics_frame.py +11 -0
- bluer_objects/tests/test_graphics_gif.py +29 -0
- bluer_objects/tests/test_graphics_screen.py +8 -0
- bluer_objects/tests/test_graphics_signature.py +80 -0
- bluer_objects/tests/test_graphics_text.py +14 -0
- bluer_objects/tests/test_logger.py +5 -0
- bluer_objects/tests/test_logger_matrix.py +73 -0
- bluer_objects/tests/test_markdown.py +10 -0
- bluer_objects/tests/test_metadata.py +204 -0
- bluer_objects/tests/test_mlflow.py +60 -0
- bluer_objects/tests/test_mysql_cache.py +14 -0
- bluer_objects/tests/test_mysql_relations.py +16 -0
- bluer_objects/tests/test_mysql_table.py +9 -0
- bluer_objects/tests/test_mysql_tags.py +13 -0
- bluer_objects/tests/test_objects.py +180 -0
- bluer_objects/tests/test_path.py +7 -0
- bluer_objects/tests/test_storage.py +7 -0
- bluer_objects/tests/test_version.py +5 -0
- bluer_objects/urls.py +3 -0
- bluer_objects-6.3.1.dist-info/METADATA +57 -0
- bluer_objects-6.3.1.dist-info/RECORD +149 -0
- bluer_objects-6.3.1.dist-info/WHEEL +5 -0
- bluer_objects-6.3.1.dist-info/licenses/LICENSE +121 -0
- 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 @@
|
|
|
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,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
|
+
]
|