radnn 0.0.7.2__py3-none-any.whl → 0.0.8__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.
- radnn/__init__.py +7 -5
- radnn/core.py +44 -28
- radnn/data/__init__.py +8 -0
- radnn/data/data_feed.py +147 -0
- radnn/data/dataset_base.py +3 -5
- radnn/data/dataset_folder.py +55 -0
- radnn/data/image_dataset.py +0 -2
- radnn/data/image_dataset_files.py +175 -0
- radnn/data/preprocess/normalizer.py +7 -1
- radnn/data/preprocess/standardizer.py +9 -2
- radnn/data/sample_set.py +30 -17
- radnn/data/sequence_dataset.py +0 -2
- radnn/data/subset_type.py +45 -0
- radnn/data/tf_classification_data_feed.py +113 -0
- radnn/errors.py +29 -0
- radnn/evaluation/evaluate_classification.py +7 -3
- radnn/experiment/ml_experiment.py +29 -0
- radnn/experiment/ml_experiment_config.py +61 -32
- radnn/experiment/ml_experiment_env.py +6 -2
- radnn/experiment/ml_experiment_store.py +0 -1
- radnn/images/__init__.py +2 -0
- radnn/images/colors.py +28 -0
- radnn/images/image_processor.py +513 -0
- radnn/learn/learning_algorithm.py +4 -3
- radnn/ml_system.py +59 -18
- radnn/plots/plot_auto_multi_image.py +27 -17
- radnn/plots/plot_confusion_matrix.py +7 -4
- radnn/plots/plot_learning_curve.py +7 -3
- radnn/plots/plot_multi_scatter.py +7 -3
- radnn/plots/plot_roc.py +8 -4
- radnn/plots/plot_voronoi_2d.py +8 -5
- radnn/stats/__init__.py +1 -0
- radnn/stats/descriptive_stats.py +45 -0
- radnn/system/files/__init__.py +1 -0
- radnn/system/files/csvfile.py +8 -5
- radnn/system/files/filelist.py +40 -0
- radnn/system/files/fileobject.py +9 -4
- radnn/system/files/imgfile.py +8 -4
- radnn/system/files/jsonfile.py +8 -4
- radnn/system/files/picklefile.py +8 -4
- radnn/system/files/textfile.py +37 -7
- radnn/system/filestore.py +36 -18
- radnn/system/filesystem.py +8 -3
- radnn/system/hosts/colab_host.py +29 -0
- radnn/system/hosts/linux_host.py +29 -0
- radnn/system/hosts/windows_host.py +39 -1
- radnn/system/tee_logger.py +7 -3
- radnn/system/threads/__init__.py +5 -0
- radnn/system/threads/semaphore_lock.py +58 -0
- radnn/system/threads/thread_context.py +175 -0
- radnn/system/threads/thread_safe_queue.py +163 -0
- radnn/system/threads/thread_safe_string_collection.py +66 -0
- radnn/system/threads/thread_worker.py +68 -0
- radnn/utils.py +96 -2
- {radnn-0.0.7.2.dist-info → radnn-0.0.8.dist-info}/METADATA +1 -1
- radnn-0.0.8.dist-info/RECORD +70 -0
- radnn-0.0.7.2.dist-info/RECORD +0 -53
- {radnn-0.0.7.2.dist-info → radnn-0.0.8.dist-info}/LICENSE.txt +0 -0
- {radnn-0.0.7.2.dist-info → radnn-0.0.8.dist-info}/WHEEL +0 -0
- {radnn-0.0.7.2.dist-info → radnn-0.0.8.dist-info}/top_level.txt +0 -0
radnn/system/filesystem.py
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
# ======================================================================================
|
|
2
|
+
#
|
|
3
|
+
# Rapid Deep Neural Networks
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the MIT License
|
|
6
|
+
# ______________________________________________________________________________________
|
|
1
7
|
# ......................................................................................
|
|
2
|
-
# MIT License
|
|
3
8
|
|
|
4
9
|
# Copyright (c) 2018-2025 Pantelis I. Kaplanoglou
|
|
5
10
|
|
|
@@ -20,8 +25,8 @@
|
|
|
20
25
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
26
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
27
|
# SOFTWARE.
|
|
23
|
-
# ......................................................................................
|
|
24
28
|
|
|
29
|
+
# .......................................................................................
|
|
25
30
|
import os
|
|
26
31
|
from radnn.core import system_name
|
|
27
32
|
from radnn.system.filestore import FileStore
|
|
@@ -30,7 +35,7 @@ from radnn.system.files import JSONFile
|
|
|
30
35
|
# =======================================================================================================================
|
|
31
36
|
class FileSystem(object):
|
|
32
37
|
# --------------------------------------------------------------------------------------------------------
|
|
33
|
-
def __init__(self, config_folder="MLConfig", model_folder="MLModels", dataset_folder="MLData", must_exist=False, setup_filename="*auto*", is_custom_setup=
|
|
38
|
+
def __init__(self, config_folder="MLConfig", model_folder="MLModels", dataset_folder="MLData", must_exist=False, setup_filename="*auto*", is_custom_setup=True):
|
|
34
39
|
'''
|
|
35
40
|
Initializes the file system settings for an experiment
|
|
36
41
|
:param config_folder: The folder that contains the experiment hyperparameter files.
|
radnn/system/hosts/colab_host.py
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
# ======================================================================================
|
|
2
|
+
#
|
|
3
|
+
# Rapid Deep Neural Networks
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the MIT License
|
|
6
|
+
# ______________________________________________________________________________________
|
|
7
|
+
# ......................................................................................
|
|
8
|
+
|
|
9
|
+
# Copyright (c) 2019-2025 Pantelis I. Kaplanoglou
|
|
10
|
+
|
|
11
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
# in the Software without restriction, including without limitation the rights
|
|
14
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
# furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
# copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
# SOFTWARE.
|
|
28
|
+
|
|
29
|
+
# .......................................................................................
|
|
1
30
|
import os
|
|
2
31
|
from google.colab import drive
|
|
3
32
|
from google.colab import files
|
radnn/system/hosts/linux_host.py
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
# ======================================================================================
|
|
2
|
+
#
|
|
3
|
+
# Rapid Deep Neural Networks
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the MIT License
|
|
6
|
+
# ______________________________________________________________________________________
|
|
7
|
+
# ......................................................................................
|
|
8
|
+
|
|
9
|
+
# Copyright (c) 2024-2025 Pantelis I. Kaplanoglou
|
|
10
|
+
|
|
11
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
# in the Software without restriction, including without limitation the rights
|
|
14
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
# furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
# copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
# SOFTWARE.
|
|
28
|
+
|
|
29
|
+
# .......................................................................................
|
|
1
30
|
class LinuxHost(object):
|
|
2
31
|
def __init__(self):
|
|
3
32
|
pass
|
|
@@ -1,5 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
# ======================================================================================
|
|
2
|
+
#
|
|
3
|
+
# Rapid Deep Neural Networks
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the MIT License
|
|
6
|
+
# ______________________________________________________________________________________
|
|
7
|
+
# ......................................................................................
|
|
8
|
+
|
|
9
|
+
# Copyright (c) 2024-2025 Pantelis I. Kaplanoglou
|
|
10
|
+
|
|
11
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
# in the Software without restriction, including without limitation the rights
|
|
14
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
# furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
# copies or substantial portions of the Software.
|
|
2
20
|
|
|
21
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
# SOFTWARE.
|
|
28
|
+
|
|
29
|
+
# .......................................................................................
|
|
30
|
+
import win32api
|
|
31
|
+
import ctypes
|
|
3
32
|
class WindowsHost(object):
|
|
4
33
|
# --------------------------------------------------------------------------------------------------------------------
|
|
5
34
|
@classmethod
|
|
@@ -38,4 +67,13 @@ class WindowsHost(object):
|
|
|
38
67
|
str_info = u'\\StringFileInfo\\%04X%04X\\%s' % (sLanguageCode, sCodePage, sVersionString)
|
|
39
68
|
dInfo[sVersionString] = repr(win32api.GetFileVersionInfo(dll_filename, str_info))
|
|
40
69
|
return dInfo
|
|
70
|
+
# --------------------------------------------------------------------------------------------------------------------
|
|
71
|
+
@classmethod
|
|
72
|
+
def set_windows_sleep_resolution(cls, msecs=1):
|
|
73
|
+
"""
|
|
74
|
+
Requests a minimum resolution for periodic timers. This increases accuracy
|
|
75
|
+
for the waiting interval of the time.sleep function
|
|
76
|
+
"""
|
|
77
|
+
oWinMM = ctypes.WinDLL('oWinMM')
|
|
78
|
+
oWinMM.timeBeginPeriod(msecs)
|
|
41
79
|
# --------------------------------------------------------------------------------------------------------------------
|
radnn/system/tee_logger.py
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
# ======================================================================================
|
|
2
|
+
#
|
|
3
|
+
# Rapid Deep Neural Networks
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the MIT License
|
|
6
|
+
# ______________________________________________________________________________________
|
|
1
7
|
# ......................................................................................
|
|
2
|
-
# MIT License
|
|
3
8
|
|
|
4
9
|
# Copyright (c) 2024-2025 Pantelis I. Kaplanoglou
|
|
5
10
|
|
|
@@ -21,8 +26,7 @@
|
|
|
21
26
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
27
|
# SOFTWARE.
|
|
23
28
|
|
|
24
|
-
#
|
|
25
|
-
|
|
29
|
+
# .......................................................................................
|
|
26
30
|
import os
|
|
27
31
|
import sys
|
|
28
32
|
from datetime import datetime
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# ======================================================================================
|
|
2
|
+
#
|
|
3
|
+
# Rapid Deep Neural Networks
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the MIT License
|
|
6
|
+
# ______________________________________________________________________________________
|
|
7
|
+
# ......................................................................................
|
|
8
|
+
|
|
9
|
+
# Copyright (c) 2018-2025 Pantelis I. Kaplanoglou
|
|
10
|
+
|
|
11
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
# in the Software without restriction, including without limitation the rights
|
|
14
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
# furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
# copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
# SOFTWARE.
|
|
28
|
+
|
|
29
|
+
# .......................................................................................
|
|
30
|
+
from threading import BoundedSemaphore
|
|
31
|
+
|
|
32
|
+
#=======================================================================================================================
|
|
33
|
+
class SemaphoreLock(BoundedSemaphore):
|
|
34
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
35
|
+
def __init__(self, value=1):
|
|
36
|
+
super(SemaphoreLock, self).__init__(value)
|
|
37
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
38
|
+
def lock(self, blocking=True, timeout=None):
|
|
39
|
+
self.acquire(blocking, timeout)
|
|
40
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
41
|
+
def unlock(self):
|
|
42
|
+
self.release()
|
|
43
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
44
|
+
# //TODO: Not working, check if this can be fixed
|
|
45
|
+
'''
|
|
46
|
+
def __enter__(self):
|
|
47
|
+
self.Lock()
|
|
48
|
+
return self
|
|
49
|
+
|
|
50
|
+
def __exit__(self, exception_type, exception_val, trace):
|
|
51
|
+
try:
|
|
52
|
+
self.Unlock()
|
|
53
|
+
except:
|
|
54
|
+
print("Could not unlock semaphore")
|
|
55
|
+
return True
|
|
56
|
+
'''
|
|
57
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
58
|
+
#=======================================================================================================================
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# ======================================================================================
|
|
2
|
+
#
|
|
3
|
+
# Rapid Deep Neural Networks
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the MIT License
|
|
6
|
+
# ______________________________________________________________________________________
|
|
7
|
+
# ......................................................................................
|
|
8
|
+
|
|
9
|
+
# Copyright (c) 2018-2025 Pantelis I. Kaplanoglou
|
|
10
|
+
|
|
11
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
# in the Software without restriction, including without limitation the rights
|
|
14
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
# furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
# copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
# SOFTWARE.
|
|
28
|
+
|
|
29
|
+
# .......................................................................................
|
|
30
|
+
import time
|
|
31
|
+
from threading import Thread, Event, get_ident
|
|
32
|
+
from datetime import datetime
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
#=======================================================================================================================
|
|
36
|
+
class ThreadEx(Thread):
|
|
37
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
38
|
+
def __init__(self,target=None, name=None, args=(), kwargs=None):
|
|
39
|
+
#//TODO: delegate target, args and kwargs properly
|
|
40
|
+
super(ThreadEx, self).__init__(target=target, name=name, args=args, kwargs=kwargs)
|
|
41
|
+
self._stop_event = Event()
|
|
42
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
43
|
+
def stop(self):
|
|
44
|
+
self._stop_event.set()
|
|
45
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
46
|
+
@property
|
|
47
|
+
def is_stopped(self):
|
|
48
|
+
return self._stop_event.is_set()
|
|
49
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
50
|
+
#=======================================================================================================================
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
#=======================================================================================================================
|
|
61
|
+
class ThreadContext(object):
|
|
62
|
+
__NEXT_ID = 0
|
|
63
|
+
|
|
64
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
65
|
+
def __init__(self, name=None, is_daemon_thread=True, verbose_level=1):
|
|
66
|
+
#........................... | Instance Attributes | ...........................
|
|
67
|
+
type(self).__NEXT_ID += 1
|
|
68
|
+
if name is None:
|
|
69
|
+
self.name = str(type(self).__NEXT_ID)
|
|
70
|
+
else:
|
|
71
|
+
self.name = f"{name}{str(type(self).__NEXT_ID)}"
|
|
72
|
+
self.thread_id = None
|
|
73
|
+
self.verbose_level = verbose_level
|
|
74
|
+
|
|
75
|
+
#// Settings \\
|
|
76
|
+
self.is_daemon_thread = is_daemon_thread
|
|
77
|
+
self.join_timeout = 5 #secs
|
|
78
|
+
|
|
79
|
+
# // Control Variables \\
|
|
80
|
+
self.must_continue = False
|
|
81
|
+
self.has_finished = False
|
|
82
|
+
self.has_started = False
|
|
83
|
+
|
|
84
|
+
# // Agregated Objects \\
|
|
85
|
+
self.thread_handle = None
|
|
86
|
+
self.thread_args = None
|
|
87
|
+
self.on_after_finish_handler = None
|
|
88
|
+
self.run_once_func = None
|
|
89
|
+
#................................................................................
|
|
90
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
91
|
+
def sleep(self, interval_in_msecs):
|
|
92
|
+
time.sleep(interval_in_msecs / 1000.0)
|
|
93
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
94
|
+
def _thread_start(self, args):
|
|
95
|
+
self.thread_id = get_ident()
|
|
96
|
+
self.thread_args = args
|
|
97
|
+
self.has_started = True
|
|
98
|
+
|
|
99
|
+
if self.verbose_level > 0:
|
|
100
|
+
print(f"{self} is starting with arguments:", args)
|
|
101
|
+
|
|
102
|
+
self.has_finished = False
|
|
103
|
+
try:
|
|
104
|
+
if self.run_once_func is None:
|
|
105
|
+
self.loop()
|
|
106
|
+
else:
|
|
107
|
+
self.run_once_func(args)
|
|
108
|
+
finally:
|
|
109
|
+
self.has_finished = True
|
|
110
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
111
|
+
def _thread_finish(self):
|
|
112
|
+
while not self.has_finished:
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
# Callback after finishing
|
|
116
|
+
if self.on_after_finish_handler is not None:
|
|
117
|
+
self.on_after_finish_handler()
|
|
118
|
+
|
|
119
|
+
# Signal the thread to stop via the event
|
|
120
|
+
self.thread_handle.stop()
|
|
121
|
+
|
|
122
|
+
# Wait for the thread to finish
|
|
123
|
+
if self.verbose_level > 1:
|
|
124
|
+
print(f"{self} joining...")
|
|
125
|
+
|
|
126
|
+
self.thread_handle.join(self.join_timeout)
|
|
127
|
+
|
|
128
|
+
if self.verbose_level > 1:
|
|
129
|
+
nTimeDelta = datetime.now() - self._stop_action_start
|
|
130
|
+
print(f"{self} joined after {(nTimeDelta.microseconds / 1000):.3f} msecs")
|
|
131
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
132
|
+
def start(self, args=None):
|
|
133
|
+
self.must_continue = True
|
|
134
|
+
|
|
135
|
+
self.thread_handle = ThreadEx(target=self._thread_start, args=(), kwargs={"args": args})
|
|
136
|
+
self.thread_handle.setDaemon(True)
|
|
137
|
+
self.thread_handle.start()
|
|
138
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
139
|
+
def resume(self, args=None):
|
|
140
|
+
if not self.has_started:
|
|
141
|
+
self.start(args)
|
|
142
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
143
|
+
def stop(self):
|
|
144
|
+
self._stop_action_start = datetime.now()
|
|
145
|
+
if self.verbose_level > 0:
|
|
146
|
+
print(f"{self} is stopping ...")
|
|
147
|
+
# Break the loop and wait for the method to exit
|
|
148
|
+
self.must_continue = False
|
|
149
|
+
self._thread_finish()
|
|
150
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
151
|
+
def terminate(self):
|
|
152
|
+
self.stop()
|
|
153
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
154
|
+
def loop(self):
|
|
155
|
+
pass
|
|
156
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
157
|
+
def __str__(self):
|
|
158
|
+
return f"{self.name} ({self.thread_id})"
|
|
159
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
160
|
+
def __repr__(self):
|
|
161
|
+
return self.__str__()
|
|
162
|
+
# ------------------------------------------------------------------------------------------------------------------
|
|
163
|
+
#=======================================================================================================================
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# ======================================================================================
|
|
2
|
+
#
|
|
3
|
+
# Rapid Deep Neural Networks
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the MIT License
|
|
6
|
+
# ______________________________________________________________________________________
|
|
7
|
+
# ......................................................................................
|
|
8
|
+
|
|
9
|
+
# Copyright (c) 2018-2025 Pantelis I. Kaplanoglou
|
|
10
|
+
|
|
11
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
# in the Software without restriction, including without limitation the rights
|
|
14
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
# furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
# copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
# SOFTWARE.
|
|
28
|
+
|
|
29
|
+
# .......................................................................................
|
|
30
|
+
from .semaphore_lock import SemaphoreLock
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ThreadSafeQueue(object):
|
|
35
|
+
#-------------------------------------------------------------------------------------------------------------------
|
|
36
|
+
def __init__(self, name="Queue", max_queued_items=None):
|
|
37
|
+
#........................... | Instance Attributes | ...........................
|
|
38
|
+
self.name = name
|
|
39
|
+
self.queue=[]
|
|
40
|
+
|
|
41
|
+
# // Settings \\
|
|
42
|
+
self.max_queued_items = max_queued_items
|
|
43
|
+
self.can_delete = True
|
|
44
|
+
|
|
45
|
+
# // Control Params \\
|
|
46
|
+
self.is_queue_locked = False
|
|
47
|
+
|
|
48
|
+
# // Composites \\
|
|
49
|
+
self.update_lock = SemaphoreLock()
|
|
50
|
+
#................................................................................
|
|
51
|
+
|
|
52
|
+
# -------------------------------------------------------------------------------------------------------------------
|
|
53
|
+
@property
|
|
54
|
+
def count(self):
|
|
55
|
+
return len(self.queue)
|
|
56
|
+
|
|
57
|
+
# -------------------------------------------------------------------------------------------------------------------
|
|
58
|
+
@property
|
|
59
|
+
def is_empty(self):
|
|
60
|
+
bResult = (len(self.queue) == 0)
|
|
61
|
+
|
|
62
|
+
return bResult
|
|
63
|
+
#-------------------------------------------------------------------------------------------------------------------
|
|
64
|
+
def push(self, value):
|
|
65
|
+
self.update_lock.lock()
|
|
66
|
+
try:
|
|
67
|
+
if self.max_queued_items is None:
|
|
68
|
+
bCanAppend = True
|
|
69
|
+
else:
|
|
70
|
+
bCanAppend = len(self.queue) < self.max_queued_items
|
|
71
|
+
|
|
72
|
+
if bCanAppend:
|
|
73
|
+
self.queue.append(value)
|
|
74
|
+
finally:
|
|
75
|
+
self.update_lock.unlock()
|
|
76
|
+
#-------------------------------------------------------------------------------------------------------------------
|
|
77
|
+
def pop(self, index=0):
|
|
78
|
+
nValue = None
|
|
79
|
+
if self.can_delete:
|
|
80
|
+
self.update_lock.lock()
|
|
81
|
+
try:
|
|
82
|
+
bMustPop = len(self.queue) > 0
|
|
83
|
+
if bMustPop:
|
|
84
|
+
if index == -1:
|
|
85
|
+
index = len(self.queue) - 1
|
|
86
|
+
nValue = self.queue.pop(index)
|
|
87
|
+
finally:
|
|
88
|
+
self.update_lock.unlock()
|
|
89
|
+
|
|
90
|
+
return nValue
|
|
91
|
+
#-------------------------------------------------------------------------------------------------------------------
|
|
92
|
+
def clear(self):
|
|
93
|
+
self.update_lock.lock()
|
|
94
|
+
try:
|
|
95
|
+
self.queue = []
|
|
96
|
+
finally:
|
|
97
|
+
self.update_lock.unlock()
|
|
98
|
+
#-------------------------------------------------------------------------------------------------------------------
|
|
99
|
+
'''
|
|
100
|
+
def pop_ex(self, index=0):
|
|
101
|
+
nValue,nRemainingItemCount = [None,None]
|
|
102
|
+
if self.can_delete:
|
|
103
|
+
self.update_lock.Lock()
|
|
104
|
+
try:
|
|
105
|
+
nRemainingItemCount = len(self.queue)
|
|
106
|
+
bMustPop = nRemainingItemCount > 0
|
|
107
|
+
if bMustPop:
|
|
108
|
+
if index == -1:
|
|
109
|
+
index = len(self.queue) - 1
|
|
110
|
+
nValue = self.queue.pop(index)
|
|
111
|
+
nRemainingItemCount = len(self.queue)
|
|
112
|
+
finally:
|
|
113
|
+
self.update_lock.UnLock()
|
|
114
|
+
|
|
115
|
+
return nValue, nRemainingItemCount
|
|
116
|
+
'''
|
|
117
|
+
#-------------------------------------------------------------------------------------------------------------------
|
|
118
|
+
def push_ex(self, message):
|
|
119
|
+
while self.is_queue_locked:
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
if self.max_queued_items is None:
|
|
123
|
+
bCanAppend = True
|
|
124
|
+
else:
|
|
125
|
+
bCanAppend = len(self.queue) < self.max_queued_items
|
|
126
|
+
|
|
127
|
+
if not bCanAppend:
|
|
128
|
+
return
|
|
129
|
+
|
|
130
|
+
self.is_queue_locked = True
|
|
131
|
+
try:
|
|
132
|
+
self.queue.append(message)
|
|
133
|
+
finally:
|
|
134
|
+
self.is_queue_locked = False
|
|
135
|
+
#-------------------------------------------------------------------------------------------------------------------
|
|
136
|
+
def pop_ex(self):
|
|
137
|
+
sMessage = None
|
|
138
|
+
if self.can_delete:
|
|
139
|
+
while self.is_queue_locked:
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
self.is_queue_locked = True
|
|
143
|
+
try:
|
|
144
|
+
if len(self.queue) > 0:
|
|
145
|
+
sMessage = self.queue.pop(0)
|
|
146
|
+
finally:
|
|
147
|
+
self.is_queue_locked = False
|
|
148
|
+
|
|
149
|
+
return sMessage
|
|
150
|
+
#-------------------------------------------------------------------------------------------------------------------
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from .thread_safe_queue import ThreadSafeQueue
|
|
2
|
+
|
|
3
|
+
class StringCollectionThreadSafe(ThreadSafeQueue):
|
|
4
|
+
# -------------------------------------------------------------------------------------------------------------------
|
|
5
|
+
def __init__(self, filename=None, name="Text"):
|
|
6
|
+
super(StringCollectionThreadSafe, self).__init__(name)
|
|
7
|
+
|
|
8
|
+
self.filename = filename
|
|
9
|
+
self.__count = 0
|
|
10
|
+
self.__index = 0
|
|
11
|
+
# -------------------------------------------------------------------------------------------------------------------
|
|
12
|
+
def append(self, text):
|
|
13
|
+
self.push(text)
|
|
14
|
+
# -------------------------------------------------------------------------------------------------------------------
|
|
15
|
+
def print(self, text, *args):
|
|
16
|
+
if args is None:
|
|
17
|
+
self.push(text)
|
|
18
|
+
else:
|
|
19
|
+
self.push(text + " " + " ".join(map(str, args)))
|
|
20
|
+
# -------------------------------------------------------------------------------------------------------------------
|
|
21
|
+
def flush(self):
|
|
22
|
+
if self.CanDelete:
|
|
23
|
+
with open(self.filename, "a") as oFile:
|
|
24
|
+
for sLine in self.queue:
|
|
25
|
+
print(sLine, file=oFile)
|
|
26
|
+
self.clear()
|
|
27
|
+
# -------------------------------------------------------------------------------------------------------------------
|
|
28
|
+
def display_and_flush(self):
|
|
29
|
+
if self.CanDelete:
|
|
30
|
+
if self.filename is None:
|
|
31
|
+
for sLine in self.queue:
|
|
32
|
+
print(sLine)
|
|
33
|
+
else:
|
|
34
|
+
with open(self.filename, "a") as oFile:
|
|
35
|
+
for sLine in self.queue:
|
|
36
|
+
print(sLine, file=oFile)
|
|
37
|
+
self.clear()
|
|
38
|
+
# -------------------------------------------------------------------------------------------------------------------
|
|
39
|
+
def __iter__(self):
|
|
40
|
+
self.update_lock.Lock()
|
|
41
|
+
try:
|
|
42
|
+
self.__index = 0
|
|
43
|
+
self.__count = len(self.queue)
|
|
44
|
+
self.CanDelete = False
|
|
45
|
+
finally:
|
|
46
|
+
self.update_lock.UnLock()
|
|
47
|
+
|
|
48
|
+
return self
|
|
49
|
+
# -------------------------------------------------------------------------------------------------------------------
|
|
50
|
+
def __next__(self):
|
|
51
|
+
if self.__index < self.__count:
|
|
52
|
+
oResult = self.queue[self.__index]
|
|
53
|
+
self.__index += 1
|
|
54
|
+
return oResult
|
|
55
|
+
else:
|
|
56
|
+
self.CanDelete = True
|
|
57
|
+
raise StopIteration()
|
|
58
|
+
# -------------------------------------------------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|