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
@@ -0,0 +1,216 @@
1
+ import os
2
+
3
+ from PySide6.QtWidgets import (
4
+ QLineEdit,
5
+ QCheckBox,
6
+ QHBoxLayout,
7
+ QVBoxLayout,
8
+ QFormLayout,
9
+ QPushButton,
10
+ QFileDialog,
11
+ QMessageBox,
12
+ )
13
+ from PySide6.QtCore import (
14
+ QThread,
15
+ Slot,
16
+ )
17
+
18
+ from mosamatic2.core.managers.logmanager import LogManager
19
+ from mosamatic2.ui.widgets.panels.taskpanel import TaskPanel
20
+ from mosamatic2.ui.settings import Settings
21
+ from mosamatic2.ui.utils import is_macos
22
+ from mosamatic2.ui.worker import Worker
23
+ from mosamatic2.core.tasks import SegmentMuscleFatL3TensorFlowTask
24
+
25
+ LOG = LogManager()
26
+
27
+ PANEL_TITLE = 'SegmentMuscleFatL3TensorFlowTask (TensorFlow)'
28
+ PANEL_NAME = 'segmentmusclefatl3tensorflowtaskpanel'
29
+
30
+
31
+ class SegmentMuscleFatL3TensorFlowTaskPanel(TaskPanel):
32
+ def __init__(self):
33
+ super(SegmentMuscleFatL3TensorFlowTaskPanel, self).__init__()
34
+ self.set_title(PANEL_TITLE)
35
+ self._images_dir_line_edit = None
36
+ self._images_dir_select_button = None
37
+ self._model_files_dir_line_edit = None
38
+ self._model_files_dir_select_button = None
39
+ self._output_dir_line_edit = None
40
+ self._output_dir_select_button = None
41
+ self._overwrite_checkbox = None
42
+ self._form_layout = None
43
+ self._run_task_button = None
44
+ self._settings = None
45
+ self._task = None
46
+ self._worker = None
47
+ self._thread = None
48
+ self.init_layout()
49
+
50
+ def images_dir_line_edit(self):
51
+ if not self._images_dir_line_edit:
52
+ self._images_dir_line_edit = QLineEdit(self.settings().get(f'{PANEL_NAME}/images_dir'))
53
+ return self._images_dir_line_edit
54
+
55
+ def images_dir_select_button(self):
56
+ if not self._images_dir_select_button:
57
+ self._images_dir_select_button = QPushButton('Select')
58
+ self._images_dir_select_button.clicked.connect(self.handle_images_dir_select_button)
59
+ return self._images_dir_select_button
60
+
61
+ def model_files_dir_line_edit(self):
62
+ if not self._model_files_dir_line_edit:
63
+ self._model_files_dir_line_edit = QLineEdit(self.settings().get(f'{PANEL_NAME}/model_files_dir'))
64
+ return self._model_files_dir_line_edit
65
+
66
+ def model_files_dir_select_button(self):
67
+ if not self._model_files_dir_select_button:
68
+ self._model_files_dir_select_button = QPushButton('Select')
69
+ self._model_files_dir_select_button.clicked.connect(self.handle_model_files_dir_select_button)
70
+ return self._model_files_dir_select_button
71
+
72
+ def output_dir_line_edit(self):
73
+ if not self._output_dir_line_edit:
74
+ self._output_dir_line_edit = QLineEdit(self.settings().get(f'{PANEL_NAME}/output_dir'))
75
+ return self._output_dir_line_edit
76
+
77
+ def output_dir_select_button(self):
78
+ if not self._output_dir_select_button:
79
+ self._output_dir_select_button = QPushButton('Select')
80
+ self._output_dir_select_button.clicked.connect(self.handle_output_dir_select_button)
81
+ return self._output_dir_select_button
82
+
83
+ def overwrite_checkbox(self):
84
+ if not self._overwrite_checkbox:
85
+ self._overwrite_checkbox = QCheckBox('')
86
+ self._overwrite_checkbox.setChecked(self.settings().get_bool(f'{PANEL_NAME}/overwrite', True))
87
+ return self._overwrite_checkbox
88
+
89
+ def form_layout(self):
90
+ if not self._form_layout:
91
+ self._form_layout = QFormLayout()
92
+ if is_macos():
93
+ self._form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
94
+ return self._form_layout
95
+
96
+ def run_task_button(self):
97
+ if not self._run_task_button:
98
+ self._run_task_button = QPushButton('Run task')
99
+ self._run_task_button.clicked.connect(self.handle_run_task_button)
100
+ return self._run_task_button
101
+
102
+ def settings(self):
103
+ if not self._settings:
104
+ self._settings = Settings()
105
+ return self._settings
106
+
107
+ def init_layout(self):
108
+ images_dir_layout = QHBoxLayout()
109
+ images_dir_layout.addWidget(self.images_dir_line_edit())
110
+ images_dir_layout.addWidget(self.images_dir_select_button())
111
+ model_files_dir_layout = QHBoxLayout()
112
+ model_files_dir_layout.addWidget(self.model_files_dir_line_edit())
113
+ model_files_dir_layout.addWidget(self.model_files_dir_select_button())
114
+ output_dir_layout = QHBoxLayout()
115
+ output_dir_layout.addWidget(self.output_dir_line_edit())
116
+ output_dir_layout.addWidget(self.output_dir_select_button())
117
+ self.form_layout().addRow('Images directory', images_dir_layout)
118
+ self.form_layout().addRow('Model files directory', model_files_dir_layout)
119
+ self.form_layout().addRow('Output directory', output_dir_layout)
120
+ self.form_layout().addRow('Overwrite', self.overwrite_checkbox())
121
+ layout = QVBoxLayout()
122
+ layout.addLayout(self.form_layout())
123
+ layout.addWidget(self.run_task_button())
124
+ self.setLayout(layout)
125
+ self.setObjectName(PANEL_NAME)
126
+
127
+ def handle_images_dir_select_button(self):
128
+ last_directory = self.settings().get('last_directory')
129
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
130
+ if directory:
131
+ self.images_dir_line_edit().setText(directory)
132
+ self.settings().set('last_directory', directory)
133
+
134
+ def handle_model_files_dir_select_button(self):
135
+ last_directory = self.settings().get('last_directory')
136
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
137
+ if directory:
138
+ self.model_files_dir_line_edit().setText(directory)
139
+ self.settings().set('last_directory', directory)
140
+
141
+ def handle_output_dir_select_button(self):
142
+ last_directory = self.settings().get('last_directory')
143
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
144
+ if directory:
145
+ self.output_dir_line_edit().setText(directory)
146
+ self.settings().set('last_directory', directory)
147
+
148
+ def handle_run_task_button(self):
149
+ errors = self.check_inputs_and_parameters()
150
+ if len(errors) > 0:
151
+ error_message = 'Following errors were encountered:\n'
152
+ for error in errors:
153
+ error_message += f' - {error}\n'
154
+ QMessageBox.information(self, 'Error', error_message)
155
+ else:
156
+ LOG.info('Running task...')
157
+ self.run_task_button().setEnabled(False)
158
+ self.save_inputs_and_parameters()
159
+ self._task = SegmentMuscleFatL3TensorFlowTask(
160
+ inputs={
161
+ 'images': self.images_dir_line_edit().text(),
162
+ 'model_files': self.model_files_dir_line_edit().text(),
163
+ },
164
+ params={'model_version': 1.0},
165
+ output=self.output_dir_line_edit().text(),
166
+ overwrite=self.overwrite_checkbox().isChecked(),
167
+ )
168
+ self._worker = Worker(self._task)
169
+ self._thread = QThread()
170
+ self._worker.moveToThread(self._thread)
171
+ self._thread.started.connect(self._worker.run)
172
+ self._worker.progress.connect(self.handle_progress)
173
+ self._worker.status.connect(self.handle_status)
174
+ self._worker.finished.connect(self.handle_finished)
175
+ self._worker.finished.connect(self._thread.quit)
176
+ self._worker.finished.connect(self._worker.deleteLater)
177
+ self._thread.finished.connect(self._thread.deleteLater)
178
+ self._thread.start()
179
+
180
+ @Slot(int)
181
+ def handle_progress(self, progress):
182
+ LOG.info(f'Progress: {progress} / 100%')
183
+
184
+ @Slot(str)
185
+ def handle_status(self, status):
186
+ LOG.info(f'Status: {status}')
187
+
188
+ @Slot()
189
+ def handle_finished(self):
190
+ self.run_task_button().setEnabled(True)
191
+
192
+ # HELPERS
193
+
194
+ def check_inputs_and_parameters(self):
195
+ errors = []
196
+ if self.images_dir_line_edit().text() == '':
197
+ errors.append('Empty images directory path')
198
+ if not os.path.isdir(self.images_dir_line_edit().text()):
199
+ errors.append('Images directory does not exist')
200
+ if self.model_files_dir_line_edit().text() == '':
201
+ errors.append('Empty model files directory path')
202
+ if not os.path.isdir(self.model_files_dir_line_edit().text()):
203
+ errors.append('Model files directory does not exist')
204
+ if len(os.listdir(self.model_files_dir_line_edit().text())) != 3:
205
+ errors.append('Model files directory should ONLY contain "model-1.1.zip", "contour_model-1.1.zip" and "params-1.1.json", nothing else!')
206
+ if self.output_dir_line_edit().text() == '':
207
+ errors.append('Empty output directory path')
208
+ if os.path.isdir(self.output_dir_line_edit().text()) and not self.overwrite_checkbox().isChecked():
209
+ errors.append('Output directory exists but overwrite=False. Please remove output directory first')
210
+ return errors
211
+
212
+ def save_inputs_and_parameters(self):
213
+ self.settings().set(f'{PANEL_NAME}/images_dir', self.images_dir_line_edit().text())
214
+ self.settings().set(f'{PANEL_NAME}/model_files_dir', self.model_files_dir_line_edit().text())
215
+ self.settings().set(f'{PANEL_NAME}/output_dir', self.output_dir_line_edit().text())
216
+ self.settings().set(f'{PANEL_NAME}/overwrite', self.overwrite_checkbox().isChecked())
@@ -0,0 +1,184 @@
1
+ import os
2
+
3
+ from PySide6.QtWidgets import (
4
+ QLineEdit,
5
+ QCheckBox,
6
+ QSpinBox,
7
+ QHBoxLayout,
8
+ QVBoxLayout,
9
+ QFormLayout,
10
+ QPushButton,
11
+ QFileDialog,
12
+ QMessageBox,
13
+ )
14
+ from PySide6.QtCore import (
15
+ QThread,
16
+ Slot,
17
+ )
18
+
19
+ from mosamaticdesktop.core.utils.logmanager import LogManager
20
+ from mosamaticdesktop.ui.panels.taskpanel import TaskPanel
21
+ from mosamaticdesktop.ui.settings import Settings
22
+ from mosamaticdesktop.ui.utils import is_macos
23
+ from mosamaticdesktop.ui.worker import Worker
24
+
25
+ from mosamatic.tasks import SelectSliceFromScanTask
26
+
27
+ LOG = LogManager()
28
+
29
+ PANEL_TITLE = 'Automatically select L3 or T4 slice from full CT scan'
30
+ PANEL_NAME = 'selectslicefromscantaskpanel'
31
+
32
+
33
+ class SelectSliceFromScanTaskPanel(TaskPanel):
34
+ def __init__(self):
35
+ super(SelectSliceFromScanTaskPanel, self).__init__()
36
+ self.set_title(PANEL_TITLE)
37
+ self._scans_dir_line_edit = None
38
+ self._scans_dir_select_button = None
39
+ self._output_dir_line_edit = None
40
+ self._output_dir_select_button = None
41
+ self._overwrite_checkbox = None
42
+ self._form_layout = None
43
+ self._run_task_button = None
44
+ self._settings = None
45
+ self._task = None
46
+ self._worker = None
47
+ self._thread = None
48
+ self.init_layout()
49
+
50
+ def scans_dir_line_edit(self):
51
+ if not self._scans_dir_line_edit:
52
+ self._scans_dir_line_edit = QLineEdit(self.settings().get(f'{PANEL_NAME}/scans_dir'))
53
+ return self._scans_dir_line_edit
54
+
55
+ def scans_dir_select_button(self):
56
+ if not self._scans_dir_select_button:
57
+ self._scans_dir_select_button = QPushButton('Select')
58
+ self._scans_dir_select_button.clicked.connect(self.handle_scans_dir_select_button)
59
+ return self._scans_dir_select_button
60
+
61
+ def output_dir_line_edit(self):
62
+ if not self._output_dir_line_edit:
63
+ self._output_dir_line_edit = QLineEdit(self.settings().get(f'{PANEL_NAME}/output_dir'))
64
+ return self._output_dir_line_edit
65
+
66
+ def output_dir_select_button(self):
67
+ if not self._output_dir_select_button:
68
+ self._output_dir_select_button = QPushButton('Select')
69
+ self._output_dir_select_button.clicked.connect(self.handle_output_dir_select_button)
70
+ return self._output_dir_select_button
71
+
72
+ def overwrite_checkbox(self):
73
+ if not self._overwrite_checkbox:
74
+ self._overwrite_checkbox = QCheckBox('')
75
+ self._overwrite_checkbox.setChecked(self.settings().get_bool(f'{PANEL_NAME}/overwrite', True))
76
+ return self._overwrite_checkbox
77
+
78
+ def form_layout(self):
79
+ if not self._form_layout:
80
+ self._form_layout = QFormLayout()
81
+ if is_macos():
82
+ self._form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
83
+ return self._form_layout
84
+
85
+ def run_task_button(self):
86
+ if not self._run_task_button:
87
+ self._run_task_button = QPushButton('Run task')
88
+ self._run_task_button.clicked.connect(self.handle_run_task_button)
89
+ return self._run_task_button
90
+
91
+ def settings(self):
92
+ if not self._settings:
93
+ self._settings = Settings()
94
+ return self._settings
95
+
96
+ def init_layout(self):
97
+ scans_dir_layout = QHBoxLayout()
98
+ scans_dir_layout.addWidget(self.scans_dir_line_edit())
99
+ scans_dir_layout.addWidget(self.scans_dir_select_button())
100
+ output_dir_layout = QHBoxLayout()
101
+ output_dir_layout.addWidget(self.output_dir_line_edit())
102
+ output_dir_layout.addWidget(self.output_dir_select_button())
103
+ self.form_layout().addRow('Scans directory', scans_dir_layout)
104
+ self.form_layout().addRow('Output directory', output_dir_layout)
105
+ self.form_layout().addRow('Overwrite', self.overwrite_checkbox())
106
+ layout = QVBoxLayout()
107
+ layout.addLayout(self.form_layout())
108
+ layout.addWidget(self.run_task_button())
109
+ self.setLayout(layout)
110
+ self.setObjectName(PANEL_NAME)
111
+
112
+ def handle_scans_dir_select_button(self):
113
+ last_directory = self.settings().get('last_directory')
114
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
115
+ if directory:
116
+ self.scans_dir_line_edit().setText(directory)
117
+ self.settings().set('last_directory', directory)
118
+
119
+ def handle_output_dir_select_button(self):
120
+ last_directory = self.settings().get('last_directory')
121
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
122
+ if directory:
123
+ self.output_dir_line_edit().setText(directory)
124
+ self.settings().set('last_directory', directory)
125
+
126
+ def handle_run_task_button(self):
127
+ errors = self.check_inputs_and_parameters()
128
+ if len(errors) > 0:
129
+ error_message = 'Following errors were encountered:\n'
130
+ for error in errors:
131
+ error_message += f' - {error}\n'
132
+ QMessageBox.information(self, 'Error', error_message)
133
+ else:
134
+ LOG.info('Running task...')
135
+ self.run_task_button().setEnabled(False)
136
+ self.save_inputs_and_parameters()
137
+ self._task = SelectSliceFromScanTask(
138
+ self.scans_dir_line_edit().text(),
139
+ self.output_dir_line_edit().text(),
140
+ 'vertebrae_L3',
141
+ self.overwrite_checkbox().isChecked()
142
+ )
143
+ self._worker = Worker(self._task)
144
+ self._thread = QThread()
145
+ self._worker.moveToThread(self._thread)
146
+ self._thread.started.connect(self._worker.run)
147
+ self._worker.progress.connect(self.handle_progress)
148
+ self._worker.status.connect(self.handle_status)
149
+ self._worker.finished.connect(self.handle_finished)
150
+ self._worker.finished.connect(self._thread.quit)
151
+ self._worker.finished.connect(self._worker.deleteLater)
152
+ self._thread.finished.connect(self._thread.deleteLater)
153
+ self._thread.start()
154
+
155
+ @Slot(int)
156
+ def handle_progress(self, progress):
157
+ LOG.info(f'Progress: {progress} / 100%')
158
+
159
+ @Slot(str)
160
+ def handle_status(self, status):
161
+ LOG.info(f'Status: {status}')
162
+
163
+ @Slot()
164
+ def handle_finished(self):
165
+ self.run_task_button().setEnabled(True)
166
+
167
+ # HELPERS
168
+
169
+ def check_inputs_and_parameters(self):
170
+ errors = []
171
+ if self.scans_dir_line_edit().text() == '':
172
+ errors.append('Empty scans directory path')
173
+ if not os.path.isdir(self.scans_dir_line_edit().text()):
174
+ errors.append('Scans directory does not exist')
175
+ if self.output_dir_line_edit().text() == '':
176
+ errors.append('Empty output directory path')
177
+ if os.path.isdir(self.output_dir_line_edit().text()) and not self.overwrite_checkbox().isChecked():
178
+ errors.append('Output directory exists but overwrite=False. Please remove output directory first')
179
+ return errors
180
+
181
+ def save_inputs_and_parameters(self):
182
+ self.settings().set(f'{PANEL_NAME}/scans_dir', self.scans_dir_line_edit().text())
183
+ self.settings().set(f'{PANEL_NAME}/output_dir', self.output_dir_line_edit().text())
184
+ self.settings().set(f'{PANEL_NAME}/overwrite', self.overwrite_checkbox().isChecked())
@@ -0,0 +1,101 @@
1
+ import os
2
+ import mosamatic2.constants as constants
3
+ from PySide6.QtWidgets import (
4
+ QWidget,
5
+ QVBoxLayout,
6
+ QPushButton,
7
+ QLabel,
8
+ )
9
+ from PySide6.QtCore import Qt
10
+ from PySide6.QtGui import QPixmap
11
+ from mosamatic2.ui.mainwindow import MainWindow
12
+ from mosamatic2.ui.utils import resource_path, set_opacity, version
13
+
14
+
15
+ class SplashScreen(QWidget):
16
+ def __init__(self):
17
+ super(SplashScreen, self).__init__()
18
+ self._main = None
19
+ self._background_label = None
20
+ self._background_pixmap = None
21
+ self._title_label = None
22
+ self._sub_text_label = None
23
+ self._start_app_button = None
24
+ self._donate_button = None
25
+ self._close_button = None
26
+ self.init_layout()
27
+
28
+ def main(self):
29
+ if not self._main:
30
+ self._main = MainWindow()
31
+ return self._main
32
+
33
+ def background_label(self):
34
+ if not self._background_label:
35
+ self._background_label = QLabel(self)
36
+ self._background_label.setPixmap(self.background_pixmap())
37
+ self._background_label.setGeometry(0, 0, self.width(), self.height())
38
+ self._background_label.lower()
39
+ return self._background_label
40
+
41
+ def background_pixmap(self):
42
+ if not self._background_pixmap:
43
+ self._background_pixmap = QPixmap(resource_path(os.path.join(
44
+ constants.MOSAMATIC2_IMAGES_DIR_PATH, constants.MOSAMATIC2_BACKGROUND_IMAGE_FILE_NAME,
45
+ ))).scaled(self.size(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
46
+ self._background_pixmap = set_opacity(self._background_pixmap, constants.MOSAMATIC2_BACKGROUND_IMAGE_OPACITY)
47
+ return self._background_pixmap
48
+
49
+ def title_label(self):
50
+ if not self._title_label:
51
+ self._title_label = QLabel(f'{constants.MOSAMATIC2_SPLASH_SCREEN_TITLE} {version()}')
52
+ self._title_label.setStyleSheet(constants.MOSAMATIC2_SPLASH_SCREEN_TITLE_STYLESHEET)
53
+ self._title_label.setAlignment(Qt.AlignCenter)
54
+ return self._title_label
55
+
56
+ def sub_text_label(self):
57
+ if not self._sub_text_label:
58
+ message = constants.MOSAMATIC2_SPLASH_SCREEN_SUB_TEXT
59
+ self._sub_text_label = QLabel(message)
60
+ self._sub_text_label.setStyleSheet(constants.MOSAMATIC2_SPLASH_SCREEN_SUB_TEXT_STYLE_SHEET)
61
+ self._sub_text_label.setAlignment(Qt.AlignCenter)
62
+ return self._sub_text_label
63
+
64
+ def start_app_button(self):
65
+ if not self._start_app_button:
66
+ self._start_app_button = QPushButton(constants.MOSAMATIC2_SPLASH_SCREEN_START_BUTTON_TEXT)
67
+ self._start_app_button.clicked.connect(self.handle_start_app_button)
68
+ return self._start_app_button
69
+
70
+ def close_button(self):
71
+ if not self._close_button:
72
+ self._close_button = QPushButton(constants.MOSAMATIC2_SPLASH_SCREEN_QUIT_BUTTON_TEXT)
73
+ self._close_button.clicked.connect(self.handle_close_button)
74
+ return self._close_button
75
+
76
+ # LAYOUT
77
+
78
+ def init_layout(self):
79
+ layout = QVBoxLayout()
80
+ layout.addWidget(self.title_label())
81
+ layout.addWidget(self.sub_text_label())
82
+ layout.addWidget(self.start_app_button())
83
+ layout.addWidget(self.close_button())
84
+ self.setLayout(layout)
85
+ self.setFixedSize(constants.MOSAMATIC2_SPLASH_SCREEN_W, constants.MOSAMATIC2_SPLASH_SCREEN_H)
86
+ self.setWindowFlags(Qt.FramelessWindowHint)
87
+
88
+ # EVENT HANDLERS
89
+
90
+ def handle_start_app_button(self):
91
+ self.close()
92
+ self.main().show()
93
+
94
+ def handle_close_button(self):
95
+ self.close()
96
+
97
+ def resizeEvent(self, event):
98
+ super().resizeEvent(event)
99
+ scaled = self.background_pixmap().scaled(self.size(), Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation)
100
+ self.background_label().setPixmap(scaled)
101
+ self.background_label().setGeometry(0, 0, self.width(), self.height())
@@ -0,0 +1,29 @@
1
+ import traceback
2
+ from PySide6.QtCore import (
3
+ QObject,
4
+ Signal,
5
+ )
6
+ from mosamatic2.core.managers.logmanager import LogManager
7
+
8
+ LOG = LogManager()
9
+
10
+
11
+ class Worker(QObject):
12
+ progress = Signal(int)
13
+ status = Signal(str)
14
+ finished = Signal()
15
+
16
+ def __init__(self, task):
17
+ super(Worker, self).__init__()
18
+ self._task = task
19
+
20
+ def run(self):
21
+ try:
22
+ self.status.emit('started')
23
+ self._task.run()
24
+ self.status.emit('done')
25
+ self.finished.emit()
26
+ except Exception as e:
27
+ self.status.emit('failed')
28
+ LOG.error(traceback.format_exc())
29
+ self.finished.emit()
@@ -0,0 +1,34 @@
1
+ Metadata-Version: 2.3
2
+ Name: mosamatic2
3
+ Version: 2.0.3
4
+ Summary:
5
+ Author: Ralph Brecheisen
6
+ Author-email: r.brecheisen@maastrichtuniversity.nl
7
+ Requires-Python: >=3.11,<3.12
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Requires-Dist: antspyx (>=0.5.4)
11
+ Requires-Dist: flask (>=3.1.2)
12
+ Requires-Dist: nibabel (>=5.3.2)
13
+ Requires-Dist: numpy (>=1.26.4)
14
+ Requires-Dist: openpyxl (>=3.1.5)
15
+ Requires-Dist: pandas (>=2.3.2)
16
+ Requires-Dist: pendulum (>=3.1.0)
17
+ Requires-Dist: pillow (>=11.3.0)
18
+ Requires-Dist: pydicom (>=3.0.1)
19
+ Requires-Dist: pyside6-essentials (>=6.9)
20
+ Requires-Dist: python-gdcm (>=3.0.26)
21
+ Requires-Dist: scipy (>=1.15.3)
22
+ Requires-Dist: tensorboard (==2.15.2)
23
+ Requires-Dist: tensorboard-data-server (==0.7.2)
24
+ Requires-Dist: tensorflow (==2.15.*) ; platform_system == "Linux"
25
+ Requires-Dist: tensorflow-intel (==2.15.0) ; platform_system == "Windows"
26
+ Requires-Dist: tensorflow-io-gcs-filesystem (==0.31.0) ; platform_system == "Windows"
27
+ Requires-Dist: tensorflow-io-gcs-filesystem (>=0.31.0) ; platform_system == "Darwin" and platform_machine == "arm64"
28
+ Requires-Dist: tensorflow-macos (==2.15.0) ; platform_system == "Darwin" and platform_machine == "arm64"
29
+ Requires-Dist: torch (>=2.8.0)
30
+ Requires-Dist: torchvision (>=0.23.0)
31
+ Requires-Dist: totalsegmentator (>=2.11.0)
32
+ Description-Content-Type: text/markdown
33
+
34
+
@@ -0,0 +1,70 @@
1
+ models.py,sha256=Kx6oWKt7IpTTxrhBDrX61X-ZX12J7yPkJFuhVDsDHoQ,8807
2
+ mosamatic2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ mosamatic2/app.py,sha256=RIUa5tvMYFcmEII4xZPLZZdx9dXWqBvwkxkl_R97Jkw,860
4
+ mosamatic2/cli.py,sha256=nrWwbU90RUOcYgmTJ1u5PspO_qy-MPdHX65Nx6kYSkk,1140
5
+ mosamatic2/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ mosamatic2/commands/calculatescores.py,sha256=WtNWB9OKFpiv0z0yqIFJbKuP7ZE5IaeDb70Qlt_WlDY,1989
7
+ mosamatic2/commands/createpngsfromsegmentations.py,sha256=uUAQJVTqOkBCfENzi21RBNYvf6_nuesx1MeR3j_-7dM,1682
8
+ mosamatic2/commands/rescaledicomimages.py,sha256=9yQxk31apPXSJcICbsWgk-2Z6VJkC1bZIMWTJYkbAmo,1285
9
+ mosamatic2/commands/segmentmusclefatl3tensorflow.py,sha256=cTjJZ4uA6IbnuxyGvnjfQmcR4_T5umAzEx4uXsdU8Yg,1429
10
+ mosamatic2/constants.py,sha256=MVYMwO-x2jQSN37o3zNkRseVQ1nYRA3mLv3v_Q0Mlds,1284
11
+ mosamatic2/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ mosamatic2/core/data/__init__.py,sha256=j9iGqUTJlGF0N0gPrzzpe_Dhv0Bj9c6FdQ1g7U-_j2g,298
13
+ mosamatic2/core/data/dicomimage.py,sha256=jv1KIZBgN3SFjqgjXcPG_cx23RPauJ2TF1CzA9vj3Z8,484
14
+ mosamatic2/core/data/dicomimageseries.py,sha256=OZkNi15crL8nEA-PGYsM0k9NMi2mMHRvDRePr_-czvA,849
15
+ mosamatic2/core/data/dixonseries.py,sha256=kq9fy65MSM2XwiScqp7b3rQ09JmpyGwbG6ldZsuPRrM,516
16
+ mosamatic2/core/data/filedata.py,sha256=hCnpizGqOpxzIADJkDS2_NSmKVLL1u49TYjSJE5UXQo,515
17
+ mosamatic2/core/data/multidicomimage.py,sha256=cdd0H4Dq49h7NLKBx51_h_HZVnH7-reu48PY8m6tXwU,1034
18
+ mosamatic2/core/managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ mosamatic2/core/managers/logmanager.py,sha256=NEaXvhl0aILjBbK710GaWanVuuNvB51HpHhE5rgYvng,1391
20
+ mosamatic2/core/managers/logmanagerlistener.py,sha256=Gaig07yjBnyQq9I8sN85olTEeDCDyCFQnEJdwzvmgvc,99
21
+ mosamatic2/core/pipelines/__init__.py,sha256=MXoylu34AlcyudJpjuLa4B7K9gZmxLnZGDaEkK9Ygio,69
22
+ mosamatic2/core/pipelines/defaultpipeline.py,sha256=EUblRhLZXhslz9bdBmx8v9yjpgOdsHviqQZ5elK8gNQ,2901
23
+ mosamatic2/core/pipelines/pipeline.py,sha256=mRxKXLKwgKDpc8R9mCI6gDKGJ2lKVxRQ__Sf0Mfn_Qc,384
24
+ mosamatic2/core/singleton.py,sha256=FV0k_LlOCmFhlWN6gf1c2x7YXWyd8-7DsIMvOKrI6NY,224
25
+ mosamatic2/core/tasks/__init__.py,sha256=ZLdp-N1AdVYDsrXvtBLnoQO5BqFh4xDXRDsM9y73_fc,462
26
+ mosamatic2/core/tasks/calculatescorestask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ mosamatic2/core/tasks/calculatescorestask/calculatescorestask.py,sha256=1CUJK9IsePBbEuF3-0LnZp1sWMxPDiJaNy0a-8DaTUE,6576
28
+ mosamatic2/core/tasks/createpngsfromsegmentationstask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
+ mosamatic2/core/tasks/createpngsfromsegmentationstask/createpngsfromsegmentationstask.py,sha256=1UpOsp1CH668BQ0g4tALou_tFgisC306VcvqOKSDuTo,1884
30
+ mosamatic2/core/tasks/rescaledicomimagestask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ mosamatic2/core/tasks/rescaledicomimagestask/rescaledicomimagestask.py,sha256=vGSpMJoXFtE-IHGxTEO9DMkerMJcfG5r9tXgtvkxm6Y,3053
32
+ mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
+ mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/paramloader.py,sha256=VxTCOYK_1VRAG83P-ulm0LPvqXI-0iT5BCr0Rdr7MWg,900
34
+ mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/segmentmusclefatl3tensorflowtask.py,sha256=bDRG9phYSF4o4mFsdJhyJ613CqOixFPTd5yL2gBFSPY,5351
35
+ mosamatic2/core/tasks/task.py,sha256=yu6XbxFYQCFH3yxL9MVfuNv1rgiyJWtZH8p43gfPfFA,1639
36
+ mosamatic2/core/utils.py,sha256=RHBcvrUshese6NG_OigO4ZGGR3iCOmmeDJjgPnLpaBo,10753
37
+ mosamatic2/server.py,sha256=j-uvJB9YdAKBDSd1eKxFN-t6nQdVjcJFlAGQOWNZTSQ,3173
38
+ mosamatic2/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
+ mosamatic2/ui/mainwindow.py,sha256=SZRv5GRyliufGHrbxDQ4hZMJ-cooZk1T9pwlBGNSFQI,9275
40
+ mosamatic2/ui/resources/icons/mosamatic2.icns,sha256=OfhC-diJTIgaNMOezxKKilGsY7mRkaGdU5dGr0MOjIA,2994125
41
+ mosamatic2/ui/resources/icons/mosamatic2.ico,sha256=ySD3RYluHK3pgS0Eas7eKrVk_AskdLQ4qs_IT-wNhq4,12229
42
+ mosamatic2/ui/resources/icons/spinner.gif,sha256=rvaac6GUZauHSPFSOLWr0RmLfjmtZih2Q8knQ2WP3Po,16240
43
+ mosamatic2/ui/resources/images/body-composition.jpg,sha256=KD-BudbXwThB4lJOZZN-ad5-TZRaaZ5cKTH0Ar1TOZs,21227
44
+ mosamatic2/ui/resources/VERSION,sha256=Hapa2Ade-cQ7nT9Ty0T8o97c5XqhA-txBDtd1-VscFo,8
45
+ mosamatic2/ui/settings.py,sha256=YEVHYJIfNsqMO3v1pjzgh7Pih9GGoUX7S9s8S-sBNUk,2121
46
+ mosamatic2/ui/utils.py,sha256=6bbPIrh4RJ_yhQKNZrgPbL4XeUEogjIjbk_e5c3QS5g,853
47
+ mosamatic2/ui/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ mosamatic2/ui/widgets/dialogs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
+ mosamatic2/ui/widgets/dialogs/dialog.py,sha256=whp1xSDVW2t85eh0xvyx1WofEmEQLRbflDPlynwBhJo,354
50
+ mosamatic2/ui/widgets/dialogs/helpdialog.py,sha256=WTm8w2IE1iGfOKILSs6567co6YGAf9r9mTC9SqmFlto,169
51
+ mosamatic2/ui/widgets/panels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ mosamatic2/ui/widgets/panels/defaultpanel.py,sha256=Ry32Xv6ibxm6NdZ7eBOCcisWNcmn7PQUT2JLT5n5zhE,923
53
+ mosamatic2/ui/widgets/panels/logpanel.py,sha256=ogswJ6_ryb6u7JeVnOsh2Ez8KWg6jtCFZwij8s87xO4,1861
54
+ mosamatic2/ui/widgets/panels/mainpanel.py,sha256=KqI8dA7GpLFd2unqVRTBkNxdnh6AWGpVPwQuaEg8PmI,2431
55
+ mosamatic2/ui/widgets/panels/pipelines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
+ mosamatic2/ui/widgets/panels/pipelines/defaultpipelinepanel.py,sha256=cmjbjllDgwA5zP5EpfRwiYyJI7iXEtPAvh4zSXOhCSw,13714
57
+ mosamatic2/ui/widgets/panels/stackedpanel.py,sha256=dK1YWuHUzxRhVb5gP0Lu9rAiW4XagjcHmGF__5Lpufk,657
58
+ mosamatic2/ui/widgets/panels/taskpanel.py,sha256=t8lIx1P8sS1Fa-aNm6eEha6297pJQNbBRizkobBexz8,170
59
+ mosamatic2/ui/widgets/panels/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
+ mosamatic2/ui/widgets/panels/tasks/calculatescorestaskpanel.py,sha256=kWtRI0SnjSzvE4MGTxs2-W8f3X3uP3LRtXnfyAl8HL0,9381
61
+ mosamatic2/ui/widgets/panels/tasks/createpngsfromsegmentationstaskpanel.py,sha256=Be7SJfYHDAvPCC52iVqbrgr3CbwnAck37Ph_BbyhKBE,7873
62
+ mosamatic2/ui/widgets/panels/tasks/rescaledicomimagestaskpanel.py,sha256=_K-XM4zvzq_AMugLqN4p87iEsfX594qYSVnfjNlmAfU,7591
63
+ mosamatic2/ui/widgets/panels/tasks/segmentmusclefatl3tensorflowtaskpanel.py,sha256=pLEpUXx_vi6PfOykAwp95m5yLRrIvdF_XaupHBOW31U,9624
64
+ mosamatic2/ui/widgets/panels/tasks/selectslicefromscantaskpanel.py,sha256=Q5txmTPssKEQpy_yc-iKCN22K5h3B_7WzPP885uP79Q,7506
65
+ mosamatic2/ui/widgets/splashscreen.py,sha256=MS-OczOWfwwEQNQd-JWe9_Mh57css0cSQgbu973rwQo,4056
66
+ mosamatic2/ui/worker.py,sha256=v7e3gq7MUudgpB1BJW-P7j5wurzu6-HG5m7I6WHgJp0,699
67
+ mosamatic2-2.0.3.dist-info/entry_points.txt,sha256=MCUpKkgbej1clgp8EqlLQGs0BIKwGPcBPiVWLfGz9Gw,126
68
+ mosamatic2-2.0.3.dist-info/METADATA,sha256=KaFTFjQNx_s-DKle87crkY3K8A5OTUsva4RjwSXmaOQ,1365
69
+ mosamatic2-2.0.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
70
+ mosamatic2-2.0.3.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ [console_scripts]
2
+ mosamatic2=mosamatic2.app:main
3
+ mosamatic2-cli=mosamatic2.cli:main
4
+ mosamatic2-server=mosamatic2.server:main
5
+
mosamatic2/api.py DELETED
@@ -1,2 +0,0 @@
1
- def main():
2
- print('Running mosamatic2 API...')
@@ -1,12 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: mosamatic2
3
- Version: 2.0.1
4
- Summary:
5
- Author: Ralph Brecheisen
6
- Author-email: r.brecheisen@maastrichtuniversity.nl
7
- Requires-Python: >=3.11,<3.12
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: Programming Language :: Python :: 3.11
10
- Description-Content-Type: text/markdown
11
-
12
-
@@ -1,8 +0,0 @@
1
- models.py,sha256=Kx6oWKt7IpTTxrhBDrX61X-ZX12J7yPkJFuhVDsDHoQ,8807
2
- mosamatic2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- mosamatic2/api.py,sha256=t1lqcq2BcmbVX3egQtkMO7wdXi-BprvJRd61G69mlbs,51
4
- mosamatic2/app.py,sha256=pwfdnyemo0VlmsF_K99gV7LBQWFWYSWqTAbm-eAWkfM,47
5
- mosamatic2-2.0.1.dist-info/entry_points.txt,sha256=FDljcEQ4K4Tt-8Xof4KZf3AsBHDp9RZIx4uZPCspxo4,85
6
- mosamatic2-2.0.1.dist-info/METADATA,sha256=vuxh6bICEMVtbExN1L9tAaGZ6wrDCbKzgQoV_RRE7P8,311
7
- mosamatic2-2.0.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
8
- mosamatic2-2.0.1.dist-info/RECORD,,