mosamatic2 2.0.1__py3-none-any.whl → 2.0.3__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 mosamatic2 might be problematic. Click here for more details.

Files changed (72) hide show
  1. mosamatic2/app.py +31 -1
  2. mosamatic2/cli.py +32 -0
  3. mosamatic2/commands/__init__.py +0 -0
  4. mosamatic2/commands/calculatescores.py +73 -0
  5. mosamatic2/commands/createpngsfromsegmentations.py +65 -0
  6. mosamatic2/commands/rescaledicomimages.py +54 -0
  7. mosamatic2/commands/segmentmusclefatl3tensorflow.py +55 -0
  8. mosamatic2/constants.py +27 -0
  9. mosamatic2/core/__init__.py +0 -0
  10. mosamatic2/core/data/__init__.py +5 -0
  11. mosamatic2/core/data/dicomimage.py +18 -0
  12. mosamatic2/core/data/dicomimageseries.py +26 -0
  13. mosamatic2/core/data/dixonseries.py +22 -0
  14. mosamatic2/core/data/filedata.py +26 -0
  15. mosamatic2/core/data/multidicomimage.py +30 -0
  16. mosamatic2/core/managers/__init__.py +0 -0
  17. mosamatic2/core/managers/logmanager.py +45 -0
  18. mosamatic2/core/managers/logmanagerlistener.py +3 -0
  19. mosamatic2/core/pipelines/__init__.py +1 -0
  20. mosamatic2/core/pipelines/defaultpipeline.py +79 -0
  21. mosamatic2/core/pipelines/pipeline.py +14 -0
  22. mosamatic2/core/singleton.py +9 -0
  23. mosamatic2/core/tasks/__init__.py +4 -0
  24. mosamatic2/core/tasks/calculatescorestask/__init__.py +0 -0
  25. mosamatic2/core/tasks/calculatescorestask/calculatescorestask.py +149 -0
  26. mosamatic2/core/tasks/createpngsfromsegmentationstask/__init__.py +0 -0
  27. mosamatic2/core/tasks/createpngsfromsegmentationstask/createpngsfromsegmentationstask.py +52 -0
  28. mosamatic2/core/tasks/rescaledicomimagestask/__init__.py +0 -0
  29. mosamatic2/core/tasks/rescaledicomimagestask/rescaledicomimagestask.py +64 -0
  30. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/__init__.py +0 -0
  31. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/paramloader.py +39 -0
  32. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/segmentmusclefatl3tensorflowtask.py +121 -0
  33. mosamatic2/core/tasks/task.py +49 -0
  34. mosamatic2/core/utils.py +316 -0
  35. mosamatic2/server.py +98 -0
  36. mosamatic2/ui/__init__.py +0 -0
  37. mosamatic2/ui/mainwindow.py +196 -0
  38. mosamatic2/ui/resources/VERSION +1 -0
  39. mosamatic2/ui/resources/icons/mosamatic2.icns +0 -0
  40. mosamatic2/ui/resources/icons/mosamatic2.ico +0 -0
  41. mosamatic2/ui/resources/icons/spinner.gif +0 -0
  42. mosamatic2/ui/resources/images/body-composition.jpg +0 -0
  43. mosamatic2/ui/settings.py +62 -0
  44. mosamatic2/ui/utils.py +36 -0
  45. mosamatic2/ui/widgets/__init__.py +0 -0
  46. mosamatic2/ui/widgets/dialogs/__init__.py +0 -0
  47. mosamatic2/ui/widgets/dialogs/dialog.py +16 -0
  48. mosamatic2/ui/widgets/dialogs/helpdialog.py +9 -0
  49. mosamatic2/ui/widgets/panels/__init__.py +0 -0
  50. mosamatic2/ui/widgets/panels/defaultpanel.py +31 -0
  51. mosamatic2/ui/widgets/panels/logpanel.py +65 -0
  52. mosamatic2/ui/widgets/panels/mainpanel.py +82 -0
  53. mosamatic2/ui/widgets/panels/pipelines/__init__.py +0 -0
  54. mosamatic2/ui/widgets/panels/pipelines/defaultpipelinepanel.py +299 -0
  55. mosamatic2/ui/widgets/panels/stackedpanel.py +22 -0
  56. mosamatic2/ui/widgets/panels/taskpanel.py +6 -0
  57. mosamatic2/ui/widgets/panels/tasks/__init__.py +0 -0
  58. mosamatic2/ui/widgets/panels/tasks/calculatescorestaskpanel.py +215 -0
  59. mosamatic2/ui/widgets/panels/tasks/createpngsfromsegmentationstaskpanel.py +186 -0
  60. mosamatic2/ui/widgets/panels/tasks/rescaledicomimagestaskpanel.py +184 -0
  61. mosamatic2/ui/widgets/panels/tasks/segmentmusclefatl3tensorflowtaskpanel.py +216 -0
  62. mosamatic2/ui/widgets/panels/tasks/selectslicefromscantaskpanel.py +184 -0
  63. mosamatic2/ui/widgets/splashscreen.py +101 -0
  64. mosamatic2/ui/worker.py +29 -0
  65. mosamatic2-2.0.3.dist-info/METADATA +34 -0
  66. mosamatic2-2.0.3.dist-info/RECORD +70 -0
  67. mosamatic2-2.0.3.dist-info/entry_points.txt +5 -0
  68. mosamatic2/api.py +0 -2
  69. mosamatic2-2.0.1.dist-info/METADATA +0 -12
  70. mosamatic2-2.0.1.dist-info/RECORD +0 -8
  71. mosamatic2-2.0.1.dist-info/entry_points.txt +0 -4
  72. {mosamatic2-2.0.1.dist-info → mosamatic2-2.0.3.dist-info}/WHEEL +0 -0
mosamatic2/ui/utils.py ADDED
@@ -0,0 +1,36 @@
1
+ import os
2
+ import sys
3
+ import mosamatic2.constants as constants
4
+ from PySide6.QtGui import (
5
+ QPixmap,
6
+ QPainter,
7
+ QColor
8
+ )
9
+
10
+
11
+ def resource_path(relative_path):
12
+ base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
13
+ return os.path.join(base_path, relative_path)
14
+
15
+
16
+ def version():
17
+ with open(resource_path(constants.MOSAMATIC2_VERSION_FILE), 'r') as f:
18
+ return f.readline().strip()
19
+
20
+
21
+ def is_macos():
22
+ return sys.platform.startswith('darwin')
23
+
24
+
25
+ def icon(parent, icon_type):
26
+ return parent.style().standardIcon(icon_type)
27
+
28
+
29
+ def set_opacity(pixmap, opacity):
30
+ result = QPixmap(pixmap.size())
31
+ result.fill(QColor(0, 0, 0, 0))
32
+ painter = QPainter(result)
33
+ painter.setOpacity(opacity)
34
+ painter.drawPixmap(0, 0, pixmap)
35
+ painter.end()
36
+ return result
File without changes
File without changes
@@ -0,0 +1,16 @@
1
+ from PySide6.QtWidgets import (
2
+ QDialog,
3
+ )
4
+
5
+
6
+ class Dialog(QDialog):
7
+ def __init__(self, parent=None):
8
+ super(Dialog, self).__init__(parent)
9
+ self.setFixedWidth(400)
10
+
11
+ def clear(self):
12
+ raise NotImplementedError()
13
+
14
+ def showEvent(self, arg__1):
15
+ self.clear()
16
+ return super().showEvent(arg__1)
@@ -0,0 +1,9 @@
1
+ from mosamatic2.ui.widgets.dialogs.dialog import Dialog
2
+
3
+
4
+ class HelpDialog(Dialog):
5
+ def clear(self):
6
+ pass
7
+
8
+ def set_text(self, text):
9
+ pass
File without changes
@@ -0,0 +1,31 @@
1
+ from PySide6.QtWidgets import QWidget, QPushButton
2
+
3
+ from mosamatic2.ui.widgets.dialogs.helpdialog import HelpDialog
4
+
5
+
6
+ class DefaultPanel(QWidget):
7
+ def __init__(self):
8
+ super(DefaultPanel, self).__init__()
9
+ self._title = None
10
+ self._help_dialog = None
11
+ self._show_help_button = None
12
+
13
+ def title(self):
14
+ return self._title
15
+
16
+ def set_title(self, title):
17
+ self._title = title
18
+
19
+ def help_dialog(self):
20
+ if not self._help_dialog:
21
+ self._help_dialog = HelpDialog()
22
+ return self._help_dialog
23
+
24
+ def show_help_button(self):
25
+ if not self._show_help_button:
26
+ self._show_help_button = QPushButton('Help')
27
+ self._show_help_button.clicked.connect(self.handle_show_help_button)
28
+ return self._show_help_button
29
+
30
+ def handle_show_help_button(self):
31
+ self.help_dialog().show()
@@ -0,0 +1,65 @@
1
+ from PySide6.QtWidgets import (
2
+ QWidget,
3
+ QDockWidget,
4
+ QTextEdit,
5
+ QPushButton,
6
+ QVBoxLayout,
7
+ QLabel,
8
+ )
9
+
10
+ from mosamatic2.core.managers.logmanagerlistener import LogManagerListener
11
+
12
+ PANEL_TITLE = 'Output log'
13
+ PANEL_NAME = 'logpanel'
14
+
15
+
16
+ class LogPanel(QDockWidget, LogManagerListener):
17
+ def __init__(self):
18
+ super(LogPanel, self).__init__()
19
+ self._title_label = None
20
+ self._text_edit = None
21
+ self.init_layout()
22
+
23
+ def title_label(self):
24
+ if not self._title_label:
25
+ self._title_label = QLabel(PANEL_TITLE)
26
+ return self._title_label
27
+
28
+ def text_edit(self):
29
+ if not self._text_edit:
30
+ self._text_edit = QTextEdit()
31
+ return self._text_edit
32
+
33
+ def init_layout(self):
34
+ clear_logs_button = QPushButton('Clear log')
35
+ clear_logs_button.clicked.connect(self.handle_clear_logs_button)
36
+ layout = QVBoxLayout()
37
+ # layout.addWidget(self.title_label())
38
+ layout.addWidget(self.text_edit())
39
+ layout.addWidget(clear_logs_button)
40
+ container = QWidget()
41
+ container.setLayout(layout)
42
+ self.setObjectName(PANEL_NAME)
43
+ self.setWindowTitle(self.title_label().text())
44
+ self.setWidget(container)
45
+
46
+ # HELPERS
47
+
48
+ def add_line(self, line):
49
+ self.text_edit().insertPlainText(line + '\n')
50
+ self.move_to_end()
51
+
52
+ def move_to_end(self):
53
+ cursor = self.text_edit().textCursor()
54
+ cursor.movePosition(cursor.MoveOperation.End)
55
+ self.text_edit().setTextCursor(cursor)
56
+ self.text_edit().ensureCursorVisible()
57
+
58
+ # EVENTS
59
+
60
+ def handle_clear_logs_button(self):
61
+ self.text_edit().clear()
62
+
63
+ # implements(LogManagerListener)
64
+ def new_message(self, message):
65
+ self.add_line(message)
@@ -0,0 +1,82 @@
1
+ import webbrowser
2
+
3
+ from PySide6.QtWidgets import (
4
+ QWidget,
5
+ QLabel,
6
+ QPushButton,
7
+ QVBoxLayout,
8
+ QDockWidget,
9
+ )
10
+
11
+ from mosamatic2.ui.settings import Settings
12
+ from mosamatic2.ui.widgets.panels.stackedpanel import StackedPanel
13
+ from mosamatic2.core.managers.logmanager import LogManager
14
+
15
+ LOG = LogManager()
16
+
17
+ PANEL_NAME = 'mainpanel'
18
+ DONATE_URL = 'https://rbeesoft.nl/wordpress/'
19
+
20
+
21
+ class MainPanel(QDockWidget):
22
+ def __init__(self, parent):
23
+ super(MainPanel, self).__init__(parent)
24
+ self._settings = None
25
+ self._title_label = None
26
+ self._donate_button = None
27
+ self._stacked_panel = None
28
+ self._panels = {}
29
+ self.init_layout()
30
+
31
+ def init_layout(self):
32
+ layout = QVBoxLayout()
33
+ layout.addWidget(self.title_label())
34
+ # layout.addWidget(self.donate_button())
35
+ layout.addWidget(self.stacked_panel())
36
+ container = QWidget()
37
+ container.setLayout(layout)
38
+ self.setObjectName(PANEL_NAME)
39
+ self.setWidget(container)
40
+
41
+ # GETTERS
42
+
43
+ def settings(self):
44
+ if not self._settings:
45
+ self._settings = Settings()
46
+ return self._settings
47
+
48
+ def title_label(self):
49
+ if not self._title_label:
50
+ self._title_label = QLabel('')
51
+ self._title_label.setStyleSheet('color: black; font-weight: bold; font-size: 14pt;')
52
+ return self._title_label
53
+
54
+ def donate_button(self):
55
+ if not self._donate_button:
56
+ self._donate_button = QPushButton('Donate')
57
+ self._donate_button.setStyleSheet('background-color: blue; color: white; font-weight: bold;')
58
+ self._donate_button.clicked.connect(self.handle_donate_button)
59
+ return self._donate_button
60
+
61
+ def stacked_panel(self):
62
+ if not self._stacked_panel:
63
+ self._stacked_panel = StackedPanel()
64
+ return self._stacked_panel
65
+
66
+ def panels(self):
67
+ return self._panels
68
+
69
+ # ADDING PANELS
70
+
71
+ def add_panel(self, panel, name):
72
+ self.panels()[name] = panel.title()
73
+ self.stacked_panel().add_panel(panel, name)
74
+
75
+ def select_panel(self, name):
76
+ self.title_label().setText(self.panels().get(name))
77
+ self.stacked_panel().switch_to(name)
78
+
79
+ # EVENT HANDLERS
80
+
81
+ def handle_donate_button(self):
82
+ webbrowser.open(DONATE_URL)
File without changes
@@ -0,0 +1,299 @@
1
+ import os
2
+
3
+ from PySide6.QtWidgets import (
4
+ QLineEdit,
5
+ QSpinBox,
6
+ QComboBox,
7
+ QCheckBox,
8
+ QHBoxLayout,
9
+ QVBoxLayout,
10
+ QFormLayout,
11
+ QPushButton,
12
+ QFileDialog,
13
+ QMessageBox,
14
+ )
15
+ from PySide6.QtCore import (
16
+ QThread,
17
+ Slot,
18
+ )
19
+
20
+ from mosamatic2.core.managers.logmanager import LogManager
21
+ from mosamatic2.ui.widgets.panels.defaultpanel import DefaultPanel
22
+ from mosamatic2.ui.settings import Settings
23
+ from mosamatic2.ui.utils import is_macos
24
+ from mosamatic2.ui.worker import Worker
25
+ from mosamatic2.core.pipelines import DefaultPipeline
26
+
27
+ LOG = LogManager()
28
+
29
+ PANEL_TITLE = 'DefaultPipeline'
30
+ PANEL_NAME = 'defaultpipeline'
31
+ MODEL_TYPE_ITEM_NAMES = ['tensorflow', 'pytorch']
32
+ MODEL_VERSION_ITEM_NAMES = ['1.0', '2.2']
33
+
34
+
35
+ class DefaultPipelinePanel(DefaultPanel):
36
+ def __init__(self):
37
+ super(DefaultPipelinePanel, self).__init__()
38
+ self.set_title(PANEL_TITLE)
39
+ self._images_dir_line_edit = None
40
+ self._images_dir_select_button = None
41
+ self._model_files_dir_line_edit = None
42
+ self._model_files_dir_select_button = None
43
+ self._output_dir_line_edit = None
44
+ self._output_dir_select_button = None
45
+ self._target_size_spinbox = None
46
+ self._model_type_combobox = None
47
+ self._model_version_combobox = None
48
+ self._fig_width_spinbox = None
49
+ self._fig_height_spinbox = None
50
+ self._full_scan_checkbox = None
51
+ self._overwrite_checkbox = None
52
+ self._form_layout = None
53
+ self._run_pipeline_button = None
54
+ self._settings = None
55
+ self._task = None
56
+ self._worker = None
57
+ self._thread = None
58
+ self.init_layout()
59
+
60
+ def images_dir_line_edit(self):
61
+ if not self._images_dir_line_edit:
62
+ self._images_dir_line_edit = QLineEdit()
63
+ self._images_dir_line_edit.setText(self.settings().get(f'{PANEL_NAME}/images_dir'))
64
+ return self._images_dir_line_edit
65
+
66
+ def images_dir_select_button(self):
67
+ if not self._images_dir_select_button:
68
+ self._images_dir_select_button = QPushButton('Select')
69
+ self._images_dir_select_button.clicked.connect(self.handle_images_dir_select_button)
70
+ return self._images_dir_select_button
71
+
72
+ def model_files_dir_line_edit(self):
73
+ if not self._model_files_dir_line_edit:
74
+ self._model_files_dir_line_edit = QLineEdit()
75
+ self._model_files_dir_line_edit.setText(self.settings().get(f'{PANEL_NAME}/model_files_dir'))
76
+ return self._model_files_dir_line_edit
77
+
78
+ def model_files_dir_select_button(self):
79
+ if not self._model_files_dir_select_button:
80
+ self._model_files_dir_select_button = QPushButton('Select')
81
+ self._model_files_dir_select_button.clicked.connect(self.handle_model_files_dir_select_button)
82
+ return self._model_files_dir_select_button
83
+
84
+ def output_dir_line_edit(self):
85
+ if not self._output_dir_line_edit:
86
+ self._output_dir_line_edit = QLineEdit()
87
+ self._output_dir_line_edit.setText(self.settings().get(f'{PANEL_NAME}/output_dir'))
88
+ return self._output_dir_line_edit
89
+
90
+ def output_dir_select_button(self):
91
+ if not self._output_dir_select_button:
92
+ self._output_dir_select_button = QPushButton('Select')
93
+ self._output_dir_select_button.clicked.connect(self.handle_output_dir_select_button)
94
+ return self._output_dir_select_button
95
+
96
+ def target_size_spinbox(self):
97
+ if not self._target_size_spinbox:
98
+ self._target_size_spinbox = QSpinBox()
99
+ self._target_size_spinbox.setMinimum(0)
100
+ self._target_size_spinbox.setMaximum(1024)
101
+ self._target_size_spinbox.setValue(self.settings().get_int(f'{PANEL_NAME}/target_size', 512))
102
+ return self._target_size_spinbox
103
+
104
+ def model_type_combobox(self):
105
+ if not self._model_type_combobox:
106
+ self._model_type_combobox = QComboBox()
107
+ self._model_type_combobox.addItems(MODEL_TYPE_ITEM_NAMES)
108
+ self._model_type_combobox.setCurrentText(self.settings().get(f'{PANEL_NAME}/model_type'))
109
+ self._model_type_combobox.currentTextChanged.connect(self.handle_model_type_combobox)
110
+ return self._model_type_combobox
111
+
112
+ def model_version_combobox(self):
113
+ if not self._model_version_combobox:
114
+ self._model_version_combobox = QComboBox()
115
+ self._model_version_combobox.addItems(MODEL_VERSION_ITEM_NAMES)
116
+ self._model_version_combobox.setCurrentText(self.settings().get(f'{PANEL_NAME}/model_version'))
117
+ self._model_version_combobox.currentTextChanged.connect(self.handle_model_version_combobox)
118
+ return self._model_version_combobox
119
+
120
+ def fig_width_spinbox(self):
121
+ if not self._fig_width_spinbox:
122
+ self._fig_width_spinbox = QSpinBox()
123
+ self._fig_width_spinbox.setValue(self.settings().get_int(f'{PANEL_NAME}/fig_width', default=10))
124
+ return self._fig_width_spinbox
125
+
126
+ def fig_height_spinbox(self):
127
+ if not self._fig_height_spinbox:
128
+ self._fig_height_spinbox = QSpinBox()
129
+ self._fig_height_spinbox.setValue(self.settings().get_int(f'{PANEL_NAME}/fig_height', default=10))
130
+ return self._fig_height_spinbox
131
+
132
+ def full_scan_checkbox(self):
133
+ if not self._full_scan_checkbox:
134
+ self._full_scan_checkbox = QCheckBox('')
135
+ self._full_scan_checkbox.setChecked(self.settings().get_bool(f'{PANEL_NAME}/full_scan', False))
136
+ return self._full_scan_checkbox
137
+
138
+ def overwrite_checkbox(self):
139
+ if not self._overwrite_checkbox:
140
+ self._overwrite_checkbox = QCheckBox('')
141
+ self._overwrite_checkbox.setChecked(self.settings().get_bool(f'{PANEL_NAME}/overwrite', True))
142
+ return self._overwrite_checkbox
143
+
144
+ def form_layout(self):
145
+ if not self._form_layout:
146
+ self._form_layout = QFormLayout()
147
+ if is_macos():
148
+ self._form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
149
+ return self._form_layout
150
+
151
+ def run_pipeline_button(self):
152
+ if not self._run_pipeline_button:
153
+ self._run_pipeline_button = QPushButton('Run pipeline')
154
+ self._run_pipeline_button.clicked.connect(self.handle_run_pipeline_button)
155
+ return self._run_pipeline_button
156
+
157
+ def settings(self):
158
+ if not self._settings:
159
+ self._settings = Settings()
160
+ return self._settings
161
+
162
+ def init_help_dialog(self):
163
+ self.help_dialog().set_text('Show some help information')
164
+
165
+ def init_layout(self):
166
+ images_dir_layout = QHBoxLayout()
167
+ images_dir_layout.addWidget(self.images_dir_line_edit())
168
+ images_dir_layout.addWidget(self.images_dir_select_button())
169
+ model_files_dir_layout = QHBoxLayout()
170
+ model_files_dir_layout.addWidget(self.model_files_dir_line_edit())
171
+ model_files_dir_layout.addWidget(self.model_files_dir_select_button())
172
+ output_dir_layout = QHBoxLayout()
173
+ output_dir_layout.addWidget(self.output_dir_line_edit())
174
+ output_dir_layout.addWidget(self.output_dir_select_button())
175
+ self.form_layout().addRow('Images directory', images_dir_layout)
176
+ self.form_layout().addRow('Model files directory', model_files_dir_layout)
177
+ self.form_layout().addRow('Output directory', output_dir_layout)
178
+ self.form_layout().addRow('Overwrite', self.overwrite_checkbox())
179
+ layout = QVBoxLayout()
180
+ layout.addLayout(self.form_layout())
181
+ layout.addWidget(self.run_pipeline_button())
182
+ self.setLayout(layout)
183
+ self.setObjectName(PANEL_NAME)
184
+
185
+ def handle_images_dir_select_button(self):
186
+ last_directory = self.settings().get('last_directory')
187
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
188
+ if directory:
189
+ self.images_dir_line_edit().setText(directory)
190
+ self.settings().set('last_directory', directory)
191
+
192
+ def handle_model_files_dir_select_button(self):
193
+ last_directory = self.settings().get('last_directory')
194
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
195
+ if directory:
196
+ self.model_files_dir_line_edit().setText(directory)
197
+ self.settings().set('last_directory', directory)
198
+
199
+ def handle_output_dir_select_button(self):
200
+ last_directory = self.settings().get('last_directory')
201
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
202
+ if directory:
203
+ self.output_dir_line_edit().setText(directory)
204
+ self.settings().set('last_directory', directory)
205
+
206
+ def handle_model_type_combobox(self, text):
207
+ if text == 'tensorflow':
208
+ self.model_version_combobox().setCurrentText('1.0')
209
+ if text == 'pytorch':
210
+ self.model_version_combobox().setCurrentText('2.2')
211
+
212
+ def handle_model_version_combobox(self, text):
213
+ if text == '1.0':
214
+ self.model_type_combobox().setCurrentText('tensorflow')
215
+ if text == '2.2':
216
+ self.model_type_combobox().setCurrentText('pytorch')
217
+
218
+ def handle_run_pipeline_button(self):
219
+ errors = self.check_inputs_and_parameters()
220
+ if len(errors) > 0:
221
+ error_message = 'Following errors were encountered:\n'
222
+ for error in errors:
223
+ error_message += f' - {error}\n'
224
+ QMessageBox.information(self, 'Error', error_message)
225
+ else:
226
+ LOG.info('Running pipeline...')
227
+ self.run_pipeline_button().setEnabled(False)
228
+ self.save_inputs_and_parameters()
229
+ self._task = DefaultPipeline(
230
+ inputs={
231
+ 'images': self.images_dir_line_edit().text(),
232
+ 'model_files': self.model_files_dir_line_edit().text(),
233
+ },
234
+ params={
235
+ 'file_type': 'npy',
236
+ 'model_type': 'tensorflow',
237
+ 'model_version': 1.0,
238
+ 'target_size': 512,
239
+ 'fig_width': 10,
240
+ 'fig_height': 10,
241
+ },
242
+ output=self.output_dir_line_edit().text(),
243
+ overwrite=self.overwrite_checkbox().isChecked(),
244
+ )
245
+ self._worker = Worker(self._task)
246
+ self._thread = QThread()
247
+ self._worker.moveToThread(self._thread)
248
+ self._thread.started.connect(self._worker.run)
249
+ self._worker.progress.connect(self.handle_progress)
250
+ self._worker.status.connect(self.handle_status)
251
+ self._worker.finished.connect(self.handle_finished)
252
+ self._worker.finished.connect(self._thread.quit)
253
+ self._worker.finished.connect(self._worker.deleteLater)
254
+ self._thread.finished.connect(self._thread.deleteLater)
255
+ self._thread.start()
256
+
257
+ @Slot(int)
258
+ def handle_progress(self, progress):
259
+ LOG.info(f'Progress: {progress} / 100%')
260
+
261
+ @Slot(str)
262
+ def handle_status(self, status):
263
+ LOG.info(f'Status: {status}')
264
+
265
+ @Slot()
266
+ def handle_finished(self):
267
+ self.run_pipeline_button().setEnabled(True)
268
+
269
+ def check_inputs_and_parameters(self):
270
+ errors = []
271
+ if self.images_dir_line_edit().text() == '':
272
+ errors.append('Empty images directory path')
273
+ elif not os.path.isdir(self.images_dir_line_edit().text()):
274
+ errors.append('Images directory does not exist')
275
+ if self.model_files_dir_line_edit().text() == '':
276
+ errors.append('Empty model files directory path')
277
+ elif not os.path.isdir(self.model_files_dir_line_edit().text()):
278
+ errors.append('Model files directory does not exist')
279
+ if self.output_dir_line_edit().text() == '':
280
+ errors.append('Empty output directory path')
281
+ elif os.path.isdir(self.output_dir_line_edit().text()) and not self.overwrite_checkbox().isChecked():
282
+ errors.append('Output directory exists but overwrite=False. Please remove output directory first')
283
+ # if self.target_size_spinbox().value() != 512:
284
+ # errors.append('Target size must be 512')
285
+ # if self.full_scan_checkbox().isChecked():
286
+ # errors.append('Full scan support is not available yet')
287
+ return errors
288
+
289
+ def save_inputs_and_parameters(self):
290
+ self.settings().set(f'{PANEL_NAME}/images_dir', self.images_dir_line_edit().text())
291
+ self.settings().set(f'{PANEL_NAME}/model_files_dir', self.model_files_dir_line_edit().text())
292
+ self.settings().set(f'{PANEL_NAME}/output_dir', self.output_dir_line_edit().text())
293
+ # self.settings().set(f'{PANEL_NAME}/target_size', self.target_size_spinbox().value())
294
+ # self.settings().set(f'{PANEL_NAME}/model_type', self.model_type_combobox().currentText())
295
+ # self.settings().set(f'{PANEL_NAME}/model_version', self.model_version_combobox().currentText())
296
+ # self.settings().set(f'{PANEL_NAME}/fig_width', self.fig_width_spinbox().value())
297
+ # self.settings().set(f'{PANEL_NAME}/fig_height', self.fig_height_spinbox().value())
298
+ # self.settings().set(f'{PANEL_NAME}/full_scan', self.full_scan_checkbox().isChecked())
299
+ self.settings().set(f'{PANEL_NAME}/overwrite', self.overwrite_checkbox().isChecked())
@@ -0,0 +1,22 @@
1
+ from PySide6.QtWidgets import QStackedWidget
2
+
3
+
4
+ class StackedPanel(QStackedWidget):
5
+ def __init__(self):
6
+ super(StackedPanel, self).__init__()
7
+ self._current_panel_name = None
8
+ self._panels = {}
9
+
10
+ def add_panel(self, panel, name):
11
+ if name not in self._panels.keys():
12
+ self._panels[name] = panel
13
+ self._current_panel_name = name
14
+ self.addWidget(panel)
15
+
16
+ def current_panel_name(self):
17
+ return self._current_panel_name
18
+
19
+ def switch_to(self, name):
20
+ panel = self._panels[name]
21
+ self._current_panel_name = name
22
+ self.setCurrentWidget(panel)
@@ -0,0 +1,6 @@
1
+ from mosamatic2.ui.widgets.panels.defaultpanel import DefaultPanel
2
+
3
+
4
+ class TaskPanel(DefaultPanel):
5
+ def __init__(self):
6
+ super(TaskPanel, self).__init__()
File without changes