bluer-objects 6.104.1__py3-none-any.whl → 6.464.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.
- bluer_objects/.abcli/abcli.sh +6 -0
- bluer_objects/.abcli/alias.sh +13 -6
- bluer_objects/.abcli/assets/cd.sh +20 -0
- bluer_objects/.abcli/assets/mv.sh +34 -0
- bluer_objects/.abcli/assets/publish.sh +40 -0
- bluer_objects/.abcli/assets.sh +15 -0
- bluer_objects/.abcli/create_test_asset.sh +10 -0
- bluer_objects/.abcli/download.sh +3 -1
- bluer_objects/.abcli/file.sh +15 -4
- bluer_objects/.abcli/gif.sh +18 -0
- bluer_objects/.abcli/host.sh +23 -7
- bluer_objects/.abcli/ls.sh +19 -8
- bluer_objects/.abcli/metadata/download.sh +9 -0
- bluer_objects/.abcli/metadata/edit.sh +15 -0
- bluer_objects/.abcli/metadata/upload.sh +9 -0
- bluer_objects/.abcli/mlflow/browse.sh +2 -0
- bluer_objects/.abcli/mlflow/deploy.sh +21 -5
- bluer_objects/.abcli/mlflow/lock/lock.sh +11 -0
- bluer_objects/.abcli/mlflow/lock/unlock.sh +12 -0
- bluer_objects/.abcli/mlflow/lock.sh +15 -0
- bluer_objects/.abcli/mlflow/tags/search.sh +1 -5
- bluer_objects/.abcli/mlflow.sh +0 -2
- bluer_objects/.abcli/pdf/convert.sh +92 -0
- bluer_objects/.abcli/pdf.sh +15 -0
- bluer_objects/.abcli/storage/clear.sh +2 -0
- bluer_objects/.abcli/tests/clone.sh +2 -3
- bluer_objects/.abcli/tests/create_test_asset.sh +16 -0
- bluer_objects/.abcli/tests/file.sh +64 -0
- bluer_objects/.abcli/tests/gif.sh +3 -3
- bluer_objects/.abcli/tests/help.sh +23 -7
- bluer_objects/.abcli/tests/ls.sh +11 -4
- bluer_objects/.abcli/tests/metadata.sh +35 -0
- bluer_objects/.abcli/tests/mlflow_lock.sh +30 -0
- bluer_objects/.abcli/tests/mlflow_tags.sh +1 -1
- bluer_objects/.abcli/tests/open.sh +11 -0
- bluer_objects/.abcli/tests/open_gif_open.sh +14 -0
- bluer_objects/.abcli/tests/pdf.sh +39 -0
- bluer_objects/.abcli/tests/storage_clear.sh +11 -0
- bluer_objects/.abcli/tests/storage_public_upload.sh +25 -0
- bluer_objects/.abcli/tests/storage_status.sh +12 -0
- bluer_objects/.abcli/tests/{storage.sh → storage_upload_download.sh} +26 -8
- bluer_objects/.abcli/upload.sh +26 -2
- bluer_objects/README/__init__.py +7 -22
- bluer_objects/README/alias.py +67 -0
- bluer_objects/README/build/__init__.py +0 -0
- bluer_objects/README/build/aliases.py +23 -0
- bluer_objects/README/build/docs.py +23 -0
- bluer_objects/README/build/modules.py +9 -0
- bluer_objects/README/consts.py +44 -0
- bluer_objects/README/functions.py +154 -204
- bluer_objects/README/items.py +78 -6
- bluer_objects/README/process/__init__.py +0 -0
- bluer_objects/README/process/assets.py +36 -0
- bluer_objects/README/process/details.py +20 -0
- bluer_objects/README/process/envs.py +23 -0
- bluer_objects/README/process/help.py +27 -0
- bluer_objects/README/process/include.py +40 -0
- bluer_objects/README/process/legacy.py +21 -0
- bluer_objects/README/process/mermaid.py +20 -0
- bluer_objects/README/process/national_internet.py +55 -0
- bluer_objects/README/process/objects.py +32 -0
- bluer_objects/README/process/signature.py +35 -0
- bluer_objects/README/process/title.py +44 -0
- bluer_objects/README/process/variables.py +12 -0
- bluer_objects/__init__.py +1 -1
- bluer_objects/assets/__init__.py +0 -0
- bluer_objects/assets/__main__.py +57 -0
- bluer_objects/assets/functions.py +62 -0
- bluer_objects/config.env +13 -1
- bluer_objects/env.py +27 -1
- bluer_objects/file/__main__.py +52 -7
- bluer_objects/file/functions.py +21 -4
- bluer_objects/file/load.py +2 -9
- bluer_objects/file/save.py +17 -24
- bluer_objects/graphics/__main__.py +7 -0
- bluer_objects/graphics/gif.py +11 -7
- bluer_objects/graphics/screen.py +9 -8
- bluer_objects/help/assets.py +93 -0
- bluer_objects/help/create_test_asset.py +22 -0
- bluer_objects/help/download.py +17 -3
- bluer_objects/help/file.py +59 -0
- bluer_objects/help/functions.py +9 -1
- bluer_objects/help/gif.py +25 -0
- bluer_objects/help/host.py +6 -4
- bluer_objects/help/ls.py +26 -3
- bluer_objects/help/metadata.py +51 -0
- bluer_objects/help/mlflow/__init__.py +23 -2
- bluer_objects/help/mlflow/cache.py +2 -4
- bluer_objects/help/mlflow/lock.py +52 -0
- bluer_objects/help/mlflow/tags.py +34 -23
- bluer_objects/help/pdf.py +67 -0
- bluer_objects/help/upload.py +10 -3
- bluer_objects/host/functions.py +4 -1
- bluer_objects/logger/confusion_matrix.py +76 -0
- bluer_objects/logger/image.py +110 -0
- bluer_objects/logger/stitch.py +107 -0
- bluer_objects/markdown.py +8 -6
- bluer_objects/metadata/__init__.py +1 -0
- bluer_objects/metadata/flatten.py +27 -0
- bluer_objects/mlflow/__init__.py +1 -1
- bluer_objects/mlflow/__main__.py +49 -31
- bluer_objects/mlflow/lock/__init__.py +1 -0
- bluer_objects/mlflow/lock/__main__.py +58 -0
- bluer_objects/mlflow/lock/functions.py +121 -0
- bluer_objects/mlflow/logging.py +53 -41
- bluer_objects/mlflow/models.py +7 -0
- bluer_objects/mlflow/objects.py +7 -0
- bluer_objects/mlflow/runs.py +10 -1
- bluer_objects/mlflow/serverless/__init__.py +3 -0
- bluer_objects/mlflow/serverless/api.py +88 -0
- bluer_objects/mlflow/serverless/read.py +19 -0
- bluer_objects/mlflow/serverless/search.py +35 -0
- bluer_objects/mlflow/serverless/write.py +42 -0
- bluer_objects/mlflow/tags.py +59 -9
- bluer_objects/objects.py +3 -1
- bluer_objects/pdf/__init__.py +1 -0
- bluer_objects/pdf/__main__.py +78 -0
- bluer_objects/pdf/convert/__init__.py +0 -0
- bluer_objects/pdf/convert/batch.py +54 -0
- bluer_objects/pdf/convert/combination.py +32 -0
- bluer_objects/pdf/convert/convert.py +110 -0
- bluer_objects/pdf/convert/image.py +53 -0
- bluer_objects/pdf/convert/md.py +97 -0
- bluer_objects/pdf/convert/missing.py +96 -0
- bluer_objects/pdf/convert/pdf.py +37 -0
- bluer_objects/sample.env +6 -0
- bluer_objects/storage/WebDAV.py +11 -7
- bluer_objects/storage/WebDAVrequest.py +360 -0
- bluer_objects/storage/WebDAVzip.py +26 -29
- bluer_objects/storage/__init__.py +28 -1
- bluer_objects/storage/__main__.py +40 -6
- bluer_objects/storage/base.py +84 -5
- bluer_objects/storage/policies.py +7 -0
- bluer_objects/storage/s3.py +367 -0
- bluer_objects/testing/__main__.py +6 -0
- bluer_objects/tests/test_README_consts.py +71 -0
- bluer_objects/tests/test_README_items.py +128 -0
- bluer_objects/tests/test_alias.py +33 -0
- bluer_objects/tests/test_env.py +42 -7
- bluer_objects/tests/test_file_download.py +30 -0
- bluer_objects/tests/test_file_load_save.py +1 -2
- bluer_objects/tests/test_file_load_save_text.py +46 -0
- bluer_objects/tests/test_graphics_gif.py +2 -0
- bluer_objects/tests/test_log_image_grid.py +29 -0
- bluer_objects/tests/test_logger_confusion_matrix.py +18 -0
- bluer_objects/tests/test_logger_matrix.py +2 -2
- bluer_objects/tests/test_logger_stitch_images.py +47 -0
- bluer_objects/tests/test_metadata.py +12 -6
- bluer_objects/tests/test_metadata_flatten.py +109 -0
- bluer_objects/tests/test_mlflow.py +114 -5
- bluer_objects/tests/test_mlflow_lock.py +26 -0
- bluer_objects/tests/test_objects.py +2 -0
- bluer_objects/tests/test_shell.py +34 -0
- bluer_objects/tests/test_storage.py +8 -21
- bluer_objects/tests/test_storage_base.py +39 -0
- bluer_objects/tests/test_storage_s3.py +67 -0
- bluer_objects/tests/test_storage_webdav_request.py +75 -0
- bluer_objects/tests/test_storage_webdav_zip.py +42 -0
- bluer_objects/tests/test_web_is_accessible.py +11 -0
- {bluer_objects-6.104.1.dist-info → bluer_objects-6.464.1.dist-info}/METADATA +20 -11
- bluer_objects-6.464.1.dist-info/RECORD +228 -0
- {bluer_objects-6.104.1.dist-info → bluer_objects-6.464.1.dist-info}/WHEEL +1 -1
- bluer_objects/.abcli/storage/download_file.sh +0 -9
- bluer_objects/.abcli/storage/exists.sh +0 -8
- bluer_objects/.abcli/storage/list.sh +0 -8
- bluer_objects/.abcli/storage/rm.sh +0 -11
- bluer_objects/.abcli/tests/mlflow_test.sh +0 -7
- bluer_objects-6.104.1.dist-info/RECORD +0 -143
- {bluer_objects-6.104.1.dist-info → bluer_objects-6.464.1.dist-info}/licenses/LICENSE +0 -0
- {bluer_objects-6.104.1.dist-info → bluer_objects-6.464.1.dist-info}/top_level.txt +0 -0
|
@@ -9,8 +9,7 @@ def help_read(
|
|
|
9
9
|
) -> str:
|
|
10
10
|
return show_usage(
|
|
11
11
|
[
|
|
12
|
-
"@
|
|
13
|
-
"cache",
|
|
12
|
+
"@cache",
|
|
14
13
|
"read",
|
|
15
14
|
"<keyword>",
|
|
16
15
|
],
|
|
@@ -25,8 +24,7 @@ def help_write(
|
|
|
25
24
|
) -> str:
|
|
26
25
|
return show_usage(
|
|
27
26
|
[
|
|
28
|
-
"@
|
|
29
|
-
"cache",
|
|
27
|
+
"@cache",
|
|
30
28
|
"write",
|
|
31
29
|
"<keyword>",
|
|
32
30
|
"<value>",
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from bluer_options.terminal import show_usage, xtra
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def help_lock(
|
|
7
|
+
tokens: List[str],
|
|
8
|
+
mono: bool,
|
|
9
|
+
) -> str:
|
|
10
|
+
args = [
|
|
11
|
+
"[--lock <lock-name>]",
|
|
12
|
+
"[--timeout <10>]",
|
|
13
|
+
"[--verbose 0]",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
return show_usage(
|
|
17
|
+
[
|
|
18
|
+
"@lock",
|
|
19
|
+
"lock",
|
|
20
|
+
"[.|<object-name>]",
|
|
21
|
+
]
|
|
22
|
+
+ args,
|
|
23
|
+
"lock <object-name>.",
|
|
24
|
+
mono=mono,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def help_unlock(
|
|
29
|
+
tokens: List[str],
|
|
30
|
+
mono: bool,
|
|
31
|
+
) -> str:
|
|
32
|
+
args = [
|
|
33
|
+
"[--lock <lock-name>]",
|
|
34
|
+
"[--verbose 0]",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
return show_usage(
|
|
38
|
+
[
|
|
39
|
+
"@lock",
|
|
40
|
+
"unlock",
|
|
41
|
+
"[.|<object-name>]",
|
|
42
|
+
]
|
|
43
|
+
+ args,
|
|
44
|
+
"unlock <object-name>.",
|
|
45
|
+
mono=mono,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
help_functions = {
|
|
50
|
+
"lock": help_lock,
|
|
51
|
+
"unlock": help_unlock,
|
|
52
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from typing import List
|
|
2
2
|
|
|
3
|
-
from bluer_options.terminal import show_usage
|
|
3
|
+
from bluer_options.terminal import show_usage
|
|
4
|
+
|
|
5
|
+
from bluer_objects import env
|
|
4
6
|
|
|
5
7
|
search_args = [
|
|
6
8
|
"[--count <-1>]",
|
|
@@ -16,8 +18,7 @@ def help_clone(
|
|
|
16
18
|
) -> str:
|
|
17
19
|
return show_usage(
|
|
18
20
|
[
|
|
19
|
-
"@
|
|
20
|
-
"tags",
|
|
21
|
+
"@tags",
|
|
21
22
|
"clone",
|
|
22
23
|
"[..|<object-1>]",
|
|
23
24
|
"[.|<object-2>]",
|
|
@@ -35,8 +36,7 @@ def help_get(
|
|
|
35
36
|
|
|
36
37
|
return show_usage(
|
|
37
38
|
[
|
|
38
|
-
"@
|
|
39
|
-
"tags",
|
|
39
|
+
"@tags",
|
|
40
40
|
"get",
|
|
41
41
|
"[.|<object-name>]",
|
|
42
42
|
]
|
|
@@ -50,40 +50,47 @@ def help_search(
|
|
|
50
50
|
tokens: List[str],
|
|
51
51
|
mono: bool,
|
|
52
52
|
) -> str:
|
|
53
|
-
options = "
|
|
53
|
+
options = "<keyword-1>=<value-1>,<keyword-2>,~<keyword-3>"
|
|
54
54
|
|
|
55
55
|
usage_1 = show_usage(
|
|
56
56
|
[
|
|
57
|
-
"@
|
|
58
|
-
"tags",
|
|
57
|
+
"@tags",
|
|
59
58
|
"search",
|
|
60
59
|
f"[{options}]",
|
|
61
60
|
]
|
|
62
|
-
+ search_args
|
|
63
|
-
|
|
64
|
-
"search mlflow for <filter-string>",
|
|
65
|
-
{
|
|
66
|
-
"<finter-string>: https://www.mlflow.org/docs/latest/search-experiments.html": ""
|
|
67
|
-
},
|
|
61
|
+
+ search_args,
|
|
62
|
+
"search mlflow.",
|
|
68
63
|
mono=mono,
|
|
69
64
|
)
|
|
70
65
|
|
|
66
|
+
if env.MLFLOW_IS_SERVERLESS:
|
|
67
|
+
return usage_1
|
|
68
|
+
|
|
71
69
|
# ---
|
|
72
70
|
|
|
73
|
-
|
|
71
|
+
args = sorted(
|
|
72
|
+
[
|
|
73
|
+
"[--server_style 1]",
|
|
74
|
+
"[--filter_string <filter-string>]",
|
|
75
|
+
]
|
|
76
|
+
+ search_args
|
|
77
|
+
)
|
|
74
78
|
|
|
75
79
|
usage_2 = show_usage(
|
|
76
80
|
[
|
|
77
|
-
"@
|
|
78
|
-
"tags",
|
|
81
|
+
"@tags",
|
|
79
82
|
"search",
|
|
80
|
-
f"[{options}]",
|
|
81
83
|
]
|
|
82
|
-
+
|
|
83
|
-
"search mlflow
|
|
84
|
+
+ args,
|
|
85
|
+
"search mlflow server for <filter-string>.",
|
|
86
|
+
{
|
|
87
|
+
"<filter-string>: https://www.mlflow.org/docs/latest/search-experiments.html": ""
|
|
88
|
+
},
|
|
84
89
|
mono=mono,
|
|
85
90
|
)
|
|
86
91
|
|
|
92
|
+
# ---
|
|
93
|
+
|
|
87
94
|
return "\n".join(
|
|
88
95
|
[
|
|
89
96
|
usage_1,
|
|
@@ -98,14 +105,18 @@ def help_set(
|
|
|
98
105
|
) -> str:
|
|
99
106
|
options = "<keyword-1>=<value>,<keyword-2>,~<keyword-3>"
|
|
100
107
|
|
|
108
|
+
args = [
|
|
109
|
+
"[--verbose 1]",
|
|
110
|
+
]
|
|
111
|
+
|
|
101
112
|
return show_usage(
|
|
102
113
|
[
|
|
103
|
-
"@
|
|
104
|
-
"tags",
|
|
114
|
+
"@tags",
|
|
105
115
|
"set",
|
|
106
116
|
"[.|<object-name>]",
|
|
107
117
|
f"[{options}]",
|
|
108
|
-
]
|
|
118
|
+
]
|
|
119
|
+
+ args,
|
|
109
120
|
"set tags in mlflow.",
|
|
110
121
|
mono=mono,
|
|
111
122
|
)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from bluer_options.terminal import show_usage, xtra
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def help_convert(
|
|
7
|
+
tokens: List[str],
|
|
8
|
+
mono: bool,
|
|
9
|
+
) -> str:
|
|
10
|
+
options = "".join(
|
|
11
|
+
[
|
|
12
|
+
"combine",
|
|
13
|
+
xtra(",~compress,filename=<release.pdf>,install,", mono=mono),
|
|
14
|
+
"upload",
|
|
15
|
+
]
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
args = [
|
|
19
|
+
"[--count <2>]",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
# ---
|
|
23
|
+
|
|
24
|
+
usage_1 = show_usage(
|
|
25
|
+
[
|
|
26
|
+
"@pdf",
|
|
27
|
+
"convert",
|
|
28
|
+
"[{}]".format(f"inline,{options}"),
|
|
29
|
+
"<module-name>",
|
|
30
|
+
"<.,this,this/that.md,this/that.jpg,this/that.pdf>",
|
|
31
|
+
"[-|<object-name>]",
|
|
32
|
+
]
|
|
33
|
+
+ args,
|
|
34
|
+
"md -> pdf.",
|
|
35
|
+
mono=mono,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# ---
|
|
39
|
+
|
|
40
|
+
usage_2 = show_usage(
|
|
41
|
+
[
|
|
42
|
+
"@pdf",
|
|
43
|
+
"convert",
|
|
44
|
+
f"[{options}]",
|
|
45
|
+
"[.|<object-name>]",
|
|
46
|
+
]
|
|
47
|
+
+ args
|
|
48
|
+
+ [
|
|
49
|
+
"[--list_missing 0]",
|
|
50
|
+
],
|
|
51
|
+
"md -> pdf.",
|
|
52
|
+
mono=mono,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# ---
|
|
56
|
+
|
|
57
|
+
return "\n".join(
|
|
58
|
+
[
|
|
59
|
+
usage_1,
|
|
60
|
+
usage_2,
|
|
61
|
+
]
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
help_functions = {
|
|
66
|
+
"convert": help_convert,
|
|
67
|
+
}
|
bluer_objects/help/upload.py
CHANGED
|
@@ -3,16 +3,23 @@ from typing import List
|
|
|
3
3
|
from bluer_options.terminal import show_usage, xtra
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
def options(mono: bool) -> str:
|
|
7
|
+
return "".join(
|
|
8
|
+
[
|
|
9
|
+
"filename=<filename>",
|
|
10
|
+
xtra(",public,zip", mono=mono),
|
|
11
|
+
]
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
6
15
|
def help_upload(
|
|
7
16
|
tokens: List[str],
|
|
8
17
|
mono: bool,
|
|
9
18
|
) -> str:
|
|
10
|
-
options = "filename=<filename>"
|
|
11
|
-
|
|
12
19
|
return show_usage(
|
|
13
20
|
[
|
|
14
21
|
"@upload",
|
|
15
|
-
f"[{options}]",
|
|
22
|
+
f"[{options(mono=mono)}]",
|
|
16
23
|
"[.|<object-name>]",
|
|
17
24
|
],
|
|
18
25
|
"upload <object-name>.",
|
bluer_objects/host/functions.py
CHANGED
|
@@ -11,7 +11,7 @@ NAME = module.name(__file__, NAME)
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def shell(
|
|
14
|
-
command: str,
|
|
14
|
+
command: Union[str, List[str]],
|
|
15
15
|
clean_after: bool = False,
|
|
16
16
|
return_output: bool = False,
|
|
17
17
|
work_dir: str = ".",
|
|
@@ -20,6 +20,9 @@ def shell(
|
|
|
20
20
|
bool,
|
|
21
21
|
Tuple[bool, List[str]],
|
|
22
22
|
]:
|
|
23
|
+
if isinstance(command, list):
|
|
24
|
+
command = " ".join(command)
|
|
25
|
+
|
|
23
26
|
if log:
|
|
24
27
|
logger.info(f"{NAME}.shell({command})")
|
|
25
28
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import matplotlib.pyplot as plt
|
|
2
|
+
import numpy as np
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
from bluer_objects.graphics.signature import justify_text
|
|
6
|
+
from bluer_objects import file
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def log_confusion_matrix(
|
|
10
|
+
confusion_matrix: np.ndarray,
|
|
11
|
+
filename: str,
|
|
12
|
+
header: List[str] = [],
|
|
13
|
+
footer: List[str] = [],
|
|
14
|
+
x_classes: List[str] = [],
|
|
15
|
+
y_classes: List[str] = [],
|
|
16
|
+
x_name: str = "prediction",
|
|
17
|
+
y_name: str = "label",
|
|
18
|
+
line_width: int = 80,
|
|
19
|
+
log: bool = True,
|
|
20
|
+
figsize: tuple = (10, 10),
|
|
21
|
+
) -> bool:
|
|
22
|
+
fig, ax = plt.subplots(figsize=figsize)
|
|
23
|
+
cax = ax.imshow(
|
|
24
|
+
confusion_matrix,
|
|
25
|
+
interpolation="nearest",
|
|
26
|
+
cmap=plt.cm.Blues,
|
|
27
|
+
)
|
|
28
|
+
fig.colorbar(cax)
|
|
29
|
+
ax.set_title(
|
|
30
|
+
justify_text(
|
|
31
|
+
" | ".join(header),
|
|
32
|
+
line_width=line_width,
|
|
33
|
+
return_str=True,
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
ax.set_xlabel(
|
|
37
|
+
justify_text(
|
|
38
|
+
" | ".join([x_name] + footer),
|
|
39
|
+
line_width=line_width,
|
|
40
|
+
return_str=True,
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
ax.set_ylabel(y_name)
|
|
44
|
+
|
|
45
|
+
if not x_classes:
|
|
46
|
+
x_classes = [f"class #{index}" for index in range(confusion_matrix.shape[1])]
|
|
47
|
+
if not y_classes:
|
|
48
|
+
y_classes = [f"class #{index}" for index in range(confusion_matrix.shape[0])]
|
|
49
|
+
|
|
50
|
+
ax.set_xticks(np.arange(confusion_matrix.shape[1]))
|
|
51
|
+
ax.set_yticks(np.arange(confusion_matrix.shape[0]))
|
|
52
|
+
ax.set_xticklabels(
|
|
53
|
+
x_classes,
|
|
54
|
+
rotation=45,
|
|
55
|
+
ha="right",
|
|
56
|
+
)
|
|
57
|
+
ax.set_yticklabels(y_classes)
|
|
58
|
+
|
|
59
|
+
threshold = confusion_matrix.max() / 2.0
|
|
60
|
+
for i in range(confusion_matrix.shape[0]):
|
|
61
|
+
for j in range(confusion_matrix.shape[1]):
|
|
62
|
+
ax.text(
|
|
63
|
+
j,
|
|
64
|
+
i,
|
|
65
|
+
f"{100*confusion_matrix[i, j]:.1f}%",
|
|
66
|
+
ha="center",
|
|
67
|
+
va="center",
|
|
68
|
+
color="white" if confusion_matrix[i, j] > threshold else "black",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
plt.tight_layout()
|
|
72
|
+
|
|
73
|
+
return file.save_fig(
|
|
74
|
+
filename,
|
|
75
|
+
log=log,
|
|
76
|
+
)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import matplotlib.pyplot as plt
|
|
2
|
+
from typing import Dict, Any, Union, List
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import random
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from bluer_options import string
|
|
8
|
+
|
|
9
|
+
from bluer_objects import file, objects, path
|
|
10
|
+
from bluer_objects.graphics.signature import sign_filename
|
|
11
|
+
|
|
12
|
+
LOG_IMAGE_GRID_COLS = 5
|
|
13
|
+
LOG_IMAGE_GRID_ROWS = 3
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def log_image_grid(
|
|
17
|
+
items: Union[
|
|
18
|
+
List[Dict[str, Any]],
|
|
19
|
+
pd.DataFrame,
|
|
20
|
+
],
|
|
21
|
+
filename: str,
|
|
22
|
+
rows: int = LOG_IMAGE_GRID_ROWS,
|
|
23
|
+
cols: int = LOG_IMAGE_GRID_COLS,
|
|
24
|
+
log: bool = True,
|
|
25
|
+
verbose: bool = False,
|
|
26
|
+
scale: int = 2,
|
|
27
|
+
shuffle: bool = False,
|
|
28
|
+
header: List[str] = [],
|
|
29
|
+
footer: List[str] = [],
|
|
30
|
+
relative_path: bool = False,
|
|
31
|
+
) -> bool:
|
|
32
|
+
if isinstance(items, pd.DataFrame):
|
|
33
|
+
items = items.to_dict("records")
|
|
34
|
+
|
|
35
|
+
while len(items) < rows * cols:
|
|
36
|
+
items += [{"pass": True}]
|
|
37
|
+
if shuffle:
|
|
38
|
+
random.shuffle(items)
|
|
39
|
+
|
|
40
|
+
items = items[: rows * cols]
|
|
41
|
+
|
|
42
|
+
if relative_path:
|
|
43
|
+
root_path = file.path(filename)
|
|
44
|
+
for item in items:
|
|
45
|
+
if item.get("filename", ""):
|
|
46
|
+
item["filename"] = os.path.join(
|
|
47
|
+
root_path,
|
|
48
|
+
item["filename"],
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
_, axes = plt.subplots(
|
|
52
|
+
rows,
|
|
53
|
+
cols,
|
|
54
|
+
figsize=(
|
|
55
|
+
scale * cols,
|
|
56
|
+
scale * rows,
|
|
57
|
+
),
|
|
58
|
+
)
|
|
59
|
+
axes = axes.flatten()
|
|
60
|
+
|
|
61
|
+
image_shape = ""
|
|
62
|
+
for i, item in enumerate(items):
|
|
63
|
+
if item.get("pass", False):
|
|
64
|
+
axes[i].axis("off")
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
if item.get("filename", ""):
|
|
68
|
+
success, item["image"] = file.load_image(
|
|
69
|
+
item.get("filename", ""),
|
|
70
|
+
log=verbose,
|
|
71
|
+
)
|
|
72
|
+
if not success:
|
|
73
|
+
return False
|
|
74
|
+
|
|
75
|
+
ax = axes[i]
|
|
76
|
+
image = item["image"]
|
|
77
|
+
image_shape = string.pretty_shape_of_matrix(image)
|
|
78
|
+
ax.imshow(
|
|
79
|
+
image,
|
|
80
|
+
cmap="gray" if image.ndim == 2 else None,
|
|
81
|
+
)
|
|
82
|
+
ax.set_title(
|
|
83
|
+
item.get("title", f"#{i}"),
|
|
84
|
+
color=item.get("color", "black"),
|
|
85
|
+
fontsize=10,
|
|
86
|
+
)
|
|
87
|
+
ax.axis("off")
|
|
88
|
+
|
|
89
|
+
plt.tight_layout()
|
|
90
|
+
|
|
91
|
+
if not file.save_fig(
|
|
92
|
+
filename,
|
|
93
|
+
log=verbose,
|
|
94
|
+
):
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
return sign_filename(
|
|
98
|
+
filename,
|
|
99
|
+
[
|
|
100
|
+
" | ".join(
|
|
101
|
+
objects.signature(
|
|
102
|
+
info=file.name_and_extension(filename),
|
|
103
|
+
object_name=path.name(file.path(filename)),
|
|
104
|
+
)
|
|
105
|
+
+ [image_shape]
|
|
106
|
+
+ header
|
|
107
|
+
)
|
|
108
|
+
],
|
|
109
|
+
[" | ".join(footer)],
|
|
110
|
+
)
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from blueness import module
|
|
5
|
+
from bluer_options import string
|
|
6
|
+
|
|
7
|
+
from bluer_objects import NAME
|
|
8
|
+
from bluer_objects.logger import logger
|
|
9
|
+
|
|
10
|
+
NAME = module.name(__file__, NAME)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def stitch_images(
|
|
14
|
+
list_of_images: List[np.ndarray],
|
|
15
|
+
cols: int = -1,
|
|
16
|
+
rows: int = -1,
|
|
17
|
+
log: bool = False,
|
|
18
|
+
) -> np.ndarray:
|
|
19
|
+
if not list_of_images:
|
|
20
|
+
return np.zeros((1, 1, 3), dtype=np.uint8)
|
|
21
|
+
|
|
22
|
+
list_of_images = list_of_images.copy()
|
|
23
|
+
|
|
24
|
+
if rows == -1:
|
|
25
|
+
rows = int(np.floor(np.sqrt(len(list_of_images))))
|
|
26
|
+
cols = -1
|
|
27
|
+
|
|
28
|
+
if cols == -1:
|
|
29
|
+
cols = int(np.ceil(len(list_of_images) / rows))
|
|
30
|
+
|
|
31
|
+
if log:
|
|
32
|
+
logger.info(
|
|
33
|
+
"{}.stitch_images[{}x{}]({}): {}".format(
|
|
34
|
+
NAME,
|
|
35
|
+
rows,
|
|
36
|
+
cols,
|
|
37
|
+
len(list_of_images),
|
|
38
|
+
", ".join(
|
|
39
|
+
[string.pretty_shape_of_matrix(image) for image in list_of_images]
|
|
40
|
+
),
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
for image in list_of_images:
|
|
45
|
+
if len(image.shape) == 2:
|
|
46
|
+
image = np.stack([image, image, image], axis=2)
|
|
47
|
+
|
|
48
|
+
if rows == 1:
|
|
49
|
+
output = np.zeros(
|
|
50
|
+
(
|
|
51
|
+
max([image.shape[0] for image in list_of_images]),
|
|
52
|
+
sum([image.shape[1] for image in list_of_images]),
|
|
53
|
+
3,
|
|
54
|
+
),
|
|
55
|
+
dtype=np.uint8,
|
|
56
|
+
)
|
|
57
|
+
x: int = 0
|
|
58
|
+
for image in list_of_images:
|
|
59
|
+
x_new = x + image.shape[1]
|
|
60
|
+
|
|
61
|
+
output[
|
|
62
|
+
: image.shape[0],
|
|
63
|
+
x:x_new,
|
|
64
|
+
:,
|
|
65
|
+
] = image
|
|
66
|
+
|
|
67
|
+
x = x_new
|
|
68
|
+
|
|
69
|
+
return output
|
|
70
|
+
|
|
71
|
+
if cols == 1:
|
|
72
|
+
output = np.zeros(
|
|
73
|
+
(
|
|
74
|
+
sum([image.shape[0] for image in list_of_images]),
|
|
75
|
+
max([image.shape[1] for image in list_of_images]),
|
|
76
|
+
3,
|
|
77
|
+
),
|
|
78
|
+
dtype=np.uint8,
|
|
79
|
+
)
|
|
80
|
+
y: int = 0
|
|
81
|
+
for image in list_of_images:
|
|
82
|
+
y_new = y + image.shape[0]
|
|
83
|
+
|
|
84
|
+
output[
|
|
85
|
+
y:y_new,
|
|
86
|
+
: image.shape[1],
|
|
87
|
+
:,
|
|
88
|
+
] = image
|
|
89
|
+
|
|
90
|
+
y = y_new
|
|
91
|
+
|
|
92
|
+
return output
|
|
93
|
+
|
|
94
|
+
return stitch_images(
|
|
95
|
+
list_of_images=[
|
|
96
|
+
stitch_images(
|
|
97
|
+
list_of_images[row * cols : (row + 1) * cols],
|
|
98
|
+
cols=cols,
|
|
99
|
+
rows=1,
|
|
100
|
+
log=log,
|
|
101
|
+
)
|
|
102
|
+
for row in range(rows)
|
|
103
|
+
],
|
|
104
|
+
cols=1,
|
|
105
|
+
rows=rows,
|
|
106
|
+
log=log,
|
|
107
|
+
)
|
bluer_objects/markdown.py
CHANGED
|
@@ -12,6 +12,7 @@ NAME = module.name(__file__, NAME)
|
|
|
12
12
|
def generate_table(
|
|
13
13
|
items: List[str],
|
|
14
14
|
cols: int = 3,
|
|
15
|
+
log: bool = True,
|
|
15
16
|
) -> List[str]:
|
|
16
17
|
if not items:
|
|
17
18
|
return []
|
|
@@ -22,13 +23,14 @@ def generate_table(
|
|
|
22
23
|
|
|
23
24
|
row_count = int(math.ceil(len(items) / cols))
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
if log:
|
|
27
|
+
logger.info(
|
|
28
|
+
"{}.generate_table(): {} item(s), {} row(s)".format(
|
|
29
|
+
NAME,
|
|
30
|
+
len(items),
|
|
31
|
+
row_count,
|
|
32
|
+
)
|
|
30
33
|
)
|
|
31
|
-
)
|
|
32
34
|
|
|
33
35
|
return [
|
|
34
36
|
"| {} |".format(" | ".join(cols * [" "])),
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def flatten(obj: Any) -> Any:
|
|
6
|
+
if isinstance(obj, dict):
|
|
7
|
+
return {k: flatten(v) for k, v in obj.items()}
|
|
8
|
+
|
|
9
|
+
if isinstance(obj, list):
|
|
10
|
+
return [flatten(x) for x in obj]
|
|
11
|
+
|
|
12
|
+
if isinstance(obj, tuple):
|
|
13
|
+
return tuple(flatten(x) for x in obj)
|
|
14
|
+
|
|
15
|
+
if isinstance(obj, np.ndarray):
|
|
16
|
+
return obj.tolist()
|
|
17
|
+
|
|
18
|
+
if hasattr(obj, "__dict__"):
|
|
19
|
+
return flatten(vars(obj))
|
|
20
|
+
|
|
21
|
+
if isinstance(obj, (int, float, str)):
|
|
22
|
+
return obj
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
return str(obj)
|
|
26
|
+
except:
|
|
27
|
+
return obj.__class__.__name__
|