mosamatic2 2.0.24__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.
Files changed (136) hide show
  1. models.py +259 -0
  2. mosamatic2/__init__.py +0 -0
  3. mosamatic2/app.py +32 -0
  4. mosamatic2/cli.py +50 -0
  5. mosamatic2/commands/__init__.py +0 -0
  6. mosamatic2/commands/boadockerpipeline.py +48 -0
  7. mosamatic2/commands/calculatemaskstatistics.py +59 -0
  8. mosamatic2/commands/calculatescores.py +73 -0
  9. mosamatic2/commands/createdicomsummary.py +61 -0
  10. mosamatic2/commands/createpngsfromsegmentations.py +65 -0
  11. mosamatic2/commands/defaultdockerpipeline.py +84 -0
  12. mosamatic2/commands/defaultpipeline.py +70 -0
  13. mosamatic2/commands/dicom2nifti.py +55 -0
  14. mosamatic2/commands/liveranalysispipeline.py +61 -0
  15. mosamatic2/commands/rescaledicomimages.py +54 -0
  16. mosamatic2/commands/segmentmusclefatl3tensorflow.py +55 -0
  17. mosamatic2/commands/selectslicefromscans.py +66 -0
  18. mosamatic2/commands/totalsegmentator.py +77 -0
  19. mosamatic2/constants.py +27 -0
  20. mosamatic2/core/__init__.py +0 -0
  21. mosamatic2/core/data/__init__.py +5 -0
  22. mosamatic2/core/data/dicomimage.py +27 -0
  23. mosamatic2/core/data/dicomimageseries.py +26 -0
  24. mosamatic2/core/data/dixonseries.py +22 -0
  25. mosamatic2/core/data/filedata.py +26 -0
  26. mosamatic2/core/data/multidicomimage.py +30 -0
  27. mosamatic2/core/data/multiniftiimage.py +26 -0
  28. mosamatic2/core/data/multinumpyimage.py +26 -0
  29. mosamatic2/core/data/niftiimage.py +13 -0
  30. mosamatic2/core/data/numpyimage.py +13 -0
  31. mosamatic2/core/managers/__init__.py +0 -0
  32. mosamatic2/core/managers/logmanager.py +45 -0
  33. mosamatic2/core/managers/logmanagerlistener.py +3 -0
  34. mosamatic2/core/pipelines/__init__.py +4 -0
  35. mosamatic2/core/pipelines/boadockerpipeline/__init__.py +0 -0
  36. mosamatic2/core/pipelines/boadockerpipeline/boadockerpipeline.py +70 -0
  37. mosamatic2/core/pipelines/defaultdockerpipeline/__init__.py +0 -0
  38. mosamatic2/core/pipelines/defaultdockerpipeline/defaultdockerpipeline.py +28 -0
  39. mosamatic2/core/pipelines/defaultpipeline/__init__.py +0 -0
  40. mosamatic2/core/pipelines/defaultpipeline/defaultpipeline.py +90 -0
  41. mosamatic2/core/pipelines/liveranalysispipeline/__init__.py +0 -0
  42. mosamatic2/core/pipelines/liveranalysispipeline/liveranalysispipeline.py +48 -0
  43. mosamatic2/core/pipelines/pipeline.py +14 -0
  44. mosamatic2/core/singleton.py +9 -0
  45. mosamatic2/core/tasks/__init__.py +13 -0
  46. mosamatic2/core/tasks/applythresholdtosegmentationstask/__init__.py +0 -0
  47. mosamatic2/core/tasks/applythresholdtosegmentationstask/applythresholdtosegmentationstask.py +117 -0
  48. mosamatic2/core/tasks/calculatemaskstatisticstask/__init__.py +0 -0
  49. mosamatic2/core/tasks/calculatemaskstatisticstask/calculatemaskstatisticstask.py +104 -0
  50. mosamatic2/core/tasks/calculatescorestask/__init__.py +0 -0
  51. mosamatic2/core/tasks/calculatescorestask/calculatescorestask.py +152 -0
  52. mosamatic2/core/tasks/createdicomsummarytask/__init__.py +0 -0
  53. mosamatic2/core/tasks/createdicomsummarytask/createdicomsummarytask.py +88 -0
  54. mosamatic2/core/tasks/createpngsfromsegmentationstask/__init__.py +0 -0
  55. mosamatic2/core/tasks/createpngsfromsegmentationstask/createpngsfromsegmentationstask.py +101 -0
  56. mosamatic2/core/tasks/dicom2niftitask/__init__.py +0 -0
  57. mosamatic2/core/tasks/dicom2niftitask/dicom2niftitask.py +45 -0
  58. mosamatic2/core/tasks/rescaledicomimagestask/__init__.py +0 -0
  59. mosamatic2/core/tasks/rescaledicomimagestask/rescaledicomimagestask.py +64 -0
  60. mosamatic2/core/tasks/segmentationnifti2numpytask/__init__.py +0 -0
  61. mosamatic2/core/tasks/segmentationnifti2numpytask/segmentationnifti2numpytask.py +57 -0
  62. mosamatic2/core/tasks/segmentationnumpy2niftitask/__init__.py +0 -0
  63. mosamatic2/core/tasks/segmentationnumpy2niftitask/segmentationnumpy2niftitask.py +86 -0
  64. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/__init__.py +0 -0
  65. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/paramloader.py +39 -0
  66. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/segmentmusclefatl3tensorflowtask.py +122 -0
  67. mosamatic2/core/tasks/segmentmusclefatt4pytorchtask/__init__.py +0 -0
  68. mosamatic2/core/tasks/segmentmusclefatt4pytorchtask/paramloader.py +39 -0
  69. mosamatic2/core/tasks/segmentmusclefatt4pytorchtask/segmentmusclefatt4pytorchtask.py +128 -0
  70. mosamatic2/core/tasks/selectslicefromscanstask/__init__.py +0 -0
  71. mosamatic2/core/tasks/selectslicefromscanstask/selectslicefromscanstask.py +249 -0
  72. mosamatic2/core/tasks/task.py +50 -0
  73. mosamatic2/core/tasks/totalsegmentatortask/__init__.py +0 -0
  74. mosamatic2/core/tasks/totalsegmentatortask/totalsegmentatortask.py +75 -0
  75. mosamatic2/core/utils.py +405 -0
  76. mosamatic2/server.py +146 -0
  77. mosamatic2/ui/__init__.py +0 -0
  78. mosamatic2/ui/mainwindow.py +426 -0
  79. mosamatic2/ui/resources/VERSION +1 -0
  80. mosamatic2/ui/resources/icons/mosamatic2.icns +0 -0
  81. mosamatic2/ui/resources/icons/mosamatic2.ico +0 -0
  82. mosamatic2/ui/resources/icons/spinner.gif +0 -0
  83. mosamatic2/ui/resources/images/body-composition.jpg +0 -0
  84. mosamatic2/ui/settings.py +62 -0
  85. mosamatic2/ui/utils.py +36 -0
  86. mosamatic2/ui/widgets/__init__.py +0 -0
  87. mosamatic2/ui/widgets/dialogs/__init__.py +0 -0
  88. mosamatic2/ui/widgets/dialogs/dialog.py +16 -0
  89. mosamatic2/ui/widgets/dialogs/helpdialog.py +9 -0
  90. mosamatic2/ui/widgets/panels/__init__.py +0 -0
  91. mosamatic2/ui/widgets/panels/defaultpanel.py +31 -0
  92. mosamatic2/ui/widgets/panels/logpanel.py +65 -0
  93. mosamatic2/ui/widgets/panels/mainpanel.py +82 -0
  94. mosamatic2/ui/widgets/panels/pipelines/__init__.py +0 -0
  95. mosamatic2/ui/widgets/panels/pipelines/boadockerpipelinepanel.py +195 -0
  96. mosamatic2/ui/widgets/panels/pipelines/defaultdockerpipelinepanel.py +314 -0
  97. mosamatic2/ui/widgets/panels/pipelines/defaultpipelinepanel.py +302 -0
  98. mosamatic2/ui/widgets/panels/pipelines/liveranalysispipelinepanel.py +187 -0
  99. mosamatic2/ui/widgets/panels/pipelines/pipelinepanel.py +6 -0
  100. mosamatic2/ui/widgets/panels/settingspanel.py +16 -0
  101. mosamatic2/ui/widgets/panels/stackedpanel.py +22 -0
  102. mosamatic2/ui/widgets/panels/tasks/__init__.py +0 -0
  103. mosamatic2/ui/widgets/panels/tasks/applythresholdtosegmentationstaskpanel.py +271 -0
  104. mosamatic2/ui/widgets/panels/tasks/calculatemaskstatisticstaskpanel.py +215 -0
  105. mosamatic2/ui/widgets/panels/tasks/calculatescorestaskpanel.py +238 -0
  106. mosamatic2/ui/widgets/panels/tasks/createdicomsummarytaskpanel.py +206 -0
  107. mosamatic2/ui/widgets/panels/tasks/createpngsfromsegmentationstaskpanel.py +247 -0
  108. mosamatic2/ui/widgets/panels/tasks/dicom2niftitaskpanel.py +183 -0
  109. mosamatic2/ui/widgets/panels/tasks/rescaledicomimagestaskpanel.py +184 -0
  110. mosamatic2/ui/widgets/panels/tasks/segmentationnifti2numpytaskpanel.py +192 -0
  111. mosamatic2/ui/widgets/panels/tasks/segmentationnumpy2niftitaskpanel.py +213 -0
  112. mosamatic2/ui/widgets/panels/tasks/segmentmusclefatl3tensorflowtaskpanel.py +216 -0
  113. mosamatic2/ui/widgets/panels/tasks/segmentmusclefatt4pytorchtaskpanel.py +217 -0
  114. mosamatic2/ui/widgets/panels/tasks/selectslicefromscanstaskpanel.py +193 -0
  115. mosamatic2/ui/widgets/panels/tasks/taskpanel.py +6 -0
  116. mosamatic2/ui/widgets/panels/tasks/totalsegmentatortaskpanel.py +195 -0
  117. mosamatic2/ui/widgets/panels/visualizations/__init__.py +0 -0
  118. mosamatic2/ui/widgets/panels/visualizations/liversegmentvisualization/__init__.py +0 -0
  119. mosamatic2/ui/widgets/panels/visualizations/liversegmentvisualization/liversegmentpicker.py +96 -0
  120. mosamatic2/ui/widgets/panels/visualizations/liversegmentvisualization/liversegmentviewer.py +130 -0
  121. mosamatic2/ui/widgets/panels/visualizations/liversegmentvisualization/liversegmentvisualization.py +120 -0
  122. mosamatic2/ui/widgets/panels/visualizations/sliceselectionvisualization/__init__.py +0 -0
  123. mosamatic2/ui/widgets/panels/visualizations/sliceselectionvisualization/sliceselectionviewer.py +61 -0
  124. mosamatic2/ui/widgets/panels/visualizations/sliceselectionvisualization/sliceselectionvisualization.py +133 -0
  125. mosamatic2/ui/widgets/panels/visualizations/sliceselectionvisualization/slicetile.py +63 -0
  126. mosamatic2/ui/widgets/panels/visualizations/slicevisualization/__init__.py +0 -0
  127. mosamatic2/ui/widgets/panels/visualizations/slicevisualization/custominteractorstyle.py +80 -0
  128. mosamatic2/ui/widgets/panels/visualizations/slicevisualization/sliceviewer.py +116 -0
  129. mosamatic2/ui/widgets/panels/visualizations/slicevisualization/slicevisualization.py +141 -0
  130. mosamatic2/ui/widgets/panels/visualizations/visualization.py +6 -0
  131. mosamatic2/ui/widgets/splashscreen.py +101 -0
  132. mosamatic2/ui/worker.py +29 -0
  133. mosamatic2-2.0.24.dist-info/METADATA +43 -0
  134. mosamatic2-2.0.24.dist-info/RECORD +136 -0
  135. mosamatic2-2.0.24.dist-info/WHEEL +4 -0
  136. mosamatic2-2.0.24.dist-info/entry_points.txt +5 -0
@@ -0,0 +1,213 @@
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 mosamatic2.core.managers.logmanager import LogManager
20
+ from mosamatic2.ui.widgets.panels.tasks.taskpanel import TaskPanel
21
+ from mosamatic2.ui.settings import Settings
22
+ from mosamatic2.ui.utils import is_macos
23
+ from mosamatic2.ui.worker import Worker
24
+ from mosamatic2.core.tasks import SegmentationNumpy2NiftiTask
25
+
26
+ LOG = LogManager()
27
+
28
+ PANEL_TITLE = 'SegmentationNumpy2NiftiTask'
29
+ PANEL_NAME = 'segmentationnumpy2niftitaskpanel'
30
+
31
+
32
+ class SegmentationNumpy2NiftiTaskPanel(TaskPanel):
33
+ def __init__(self):
34
+ super(SegmentationNumpy2NiftiTaskPanel, self).__init__()
35
+ self.set_title(PANEL_TITLE)
36
+ self._images_dir_line_edit = None
37
+ self._images_dir_select_line_button = None
38
+ self._segmentations_dir_line_edit = None
39
+ self._segmentations_dir_select_button = None
40
+ self._output_dir_line_edit = None
41
+ self._output_dir_select_button = None
42
+ self._overwrite_checkbox = None
43
+ self._form_layout = None
44
+ self._run_task_button = None
45
+ self._settings = None
46
+ self._task = None
47
+ self._worker = None
48
+ self._thread = None
49
+ self.init_layout()
50
+
51
+ def images_dir_line_edit(self):
52
+ if not self._images_dir_line_edit:
53
+ self._images_dir_line_edit = QLineEdit(self.settings().get(f'{PANEL_NAME}/images_dir'))
54
+ return self._images_dir_line_edit
55
+
56
+ def images_dir_select_button(self):
57
+ if not self._images_dir_select_line_button:
58
+ self._images_dir_select_line_button = QPushButton('Select')
59
+ self._images_dir_select_line_button.clicked.connect(self.handle_images_dir_select_button)
60
+ return self._images_dir_select_line_button
61
+
62
+ def segmentations_dir_line_edit(self):
63
+ if not self._segmentations_dir_line_edit:
64
+ self._segmentations_dir_line_edit = QLineEdit(self.settings().get(f'{PANEL_NAME}/segmentations_dir'))
65
+ return self._segmentations_dir_line_edit
66
+
67
+ def segmentations_dir_select_button(self):
68
+ if not self._segmentations_dir_select_button:
69
+ self._segmentations_dir_select_button = QPushButton('Select')
70
+ self._segmentations_dir_select_button.clicked.connect(self.handle_segmentations_dir_select_button)
71
+ return self._segmentations_dir_select_button
72
+
73
+ def output_dir_line_edit(self):
74
+ if not self._output_dir_line_edit:
75
+ self._output_dir_line_edit = QLineEdit(self.settings().get(f'{PANEL_NAME}/output_dir'))
76
+ return self._output_dir_line_edit
77
+
78
+ def output_dir_select_button(self):
79
+ if not self._output_dir_select_button:
80
+ self._output_dir_select_button = QPushButton('Select')
81
+ self._output_dir_select_button.clicked.connect(self.handle_output_dir_select_button)
82
+ return self._output_dir_select_button
83
+
84
+ def overwrite_checkbox(self):
85
+ if not self._overwrite_checkbox:
86
+ self._overwrite_checkbox = QCheckBox('')
87
+ self._overwrite_checkbox.setChecked(self.settings().get_bool(f'{PANEL_NAME}/overwrite', True))
88
+ return self._overwrite_checkbox
89
+
90
+ def form_layout(self):
91
+ if not self._form_layout:
92
+ self._form_layout = QFormLayout()
93
+ if is_macos():
94
+ self._form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
95
+ return self._form_layout
96
+
97
+ def run_task_button(self):
98
+ if not self._run_task_button:
99
+ self._run_task_button = QPushButton('Run task')
100
+ self._run_task_button.clicked.connect(self.handle_run_task_button)
101
+ return self._run_task_button
102
+
103
+ def settings(self):
104
+ if not self._settings:
105
+ self._settings = Settings()
106
+ return self._settings
107
+
108
+ def init_layout(self):
109
+ images_dir_layout = QHBoxLayout()
110
+ images_dir_layout.addWidget(self.images_dir_line_edit())
111
+ images_dir_layout.addWidget(self.images_dir_select_button())
112
+ segmentations_dir_layout = QHBoxLayout()
113
+ segmentations_dir_layout.addWidget(self.segmentations_dir_line_edit())
114
+ segmentations_dir_layout.addWidget(self.segmentations_dir_select_button())
115
+ output_dir_layout = QHBoxLayout()
116
+ output_dir_layout.addWidget(self.output_dir_line_edit())
117
+ output_dir_layout.addWidget(self.output_dir_select_button())
118
+ self.form_layout().addRow('Images directory', images_dir_layout)
119
+ self.form_layout().addRow('Segmentations directory', segmentations_dir_layout)
120
+ self.form_layout().addRow('Output directory', output_dir_layout)
121
+ self.form_layout().addRow('Overwrite', self.overwrite_checkbox())
122
+ layout = QVBoxLayout()
123
+ layout.addLayout(self.form_layout())
124
+ layout.addWidget(self.run_task_button())
125
+ self.setLayout(layout)
126
+ self.setObjectName(PANEL_NAME)
127
+
128
+ def handle_images_dir_select_button(self):
129
+ last_directory = self.settings().get('last_directory')
130
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
131
+ if directory:
132
+ self.images_dir_line_edit().setText(directory)
133
+ self.settings().set('last_directory', directory)
134
+
135
+ def handle_segmentations_dir_select_button(self):
136
+ last_directory = self.settings().get('last_directory')
137
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
138
+ if directory:
139
+ self.segmentations_dir_line_edit().setText(directory)
140
+ self.settings().set('last_directory', directory)
141
+
142
+ def handle_output_dir_select_button(self):
143
+ last_directory = self.settings().get('last_directory')
144
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
145
+ if directory:
146
+ self.output_dir_line_edit().setText(directory)
147
+ self.settings().set('last_directory', directory)
148
+
149
+ def handle_run_task_button(self):
150
+ errors = self.check_inputs_and_parameters()
151
+ if len(errors) > 0:
152
+ error_message = 'Following errors were encountered:\n'
153
+ for error in errors:
154
+ error_message += f' - {error}\n'
155
+ QMessageBox.information(self, 'Error', error_message)
156
+ else:
157
+ LOG.info('Running task...')
158
+ self.run_task_button().setEnabled(False)
159
+ self.save_inputs_and_parameters()
160
+ self._task = SegmentationNumpy2NiftiTask(
161
+ inputs={
162
+ 'images': self.images_dir_line_edit().text(),
163
+ 'segmentations': self.segmentations_dir_line_edit().text()
164
+ },
165
+ params=None,
166
+ output=self.output_dir_line_edit().text(),
167
+ overwrite=self.overwrite_checkbox().isChecked(),
168
+ )
169
+ self._worker = Worker(self._task)
170
+ self._thread = QThread()
171
+ self._worker.moveToThread(self._thread)
172
+ self._thread.started.connect(self._worker.run)
173
+ self._worker.progress.connect(self.handle_progress)
174
+ self._worker.status.connect(self.handle_status)
175
+ self._worker.finished.connect(self.handle_finished)
176
+ self._worker.finished.connect(self._thread.quit)
177
+ self._worker.finished.connect(self._worker.deleteLater)
178
+ self._thread.finished.connect(self._thread.deleteLater)
179
+ self._thread.start()
180
+
181
+ @Slot(int)
182
+ def handle_progress(self, progress):
183
+ LOG.info(f'Progress: {progress} / 100%')
184
+
185
+ @Slot(str)
186
+ def handle_status(self, status):
187
+ LOG.info(f'Status: {status}')
188
+
189
+ @Slot()
190
+ def handle_finished(self):
191
+ self.run_task_button().setEnabled(True)
192
+
193
+ # HELPERS
194
+
195
+ def check_inputs_and_parameters(self):
196
+ errors = []
197
+ if self.images_dir_line_edit().text() == '':
198
+ errors.append('Empty images directory path')
199
+ if self.segmentations_dir_line_edit().text() == '':
200
+ errors.append('Empty segmentations directory path')
201
+ if not os.path.isdir(self.segmentations_dir_line_edit().text()):
202
+ errors.append('Segmentations directory does not exist')
203
+ if self.output_dir_line_edit().text() == '':
204
+ errors.append('Empty output directory path')
205
+ if os.path.isdir(self.output_dir_line_edit().text()) and not self.overwrite_checkbox().isChecked():
206
+ errors.append('Output directory exists but overwrite=False. Please remove output directory first')
207
+ return errors
208
+
209
+ def save_inputs_and_parameters(self):
210
+ self.settings().set(f'{PANEL_NAME}/images_dir', self.images_dir_line_edit().text())
211
+ self.settings().set(f'{PANEL_NAME}/segmentations_dir', self.segmentations_dir_line_edit().text())
212
+ self.settings().set(f'{PANEL_NAME}/output_dir', self.output_dir_line_edit().text())
213
+ self.settings().set(f'{PANEL_NAME}/overwrite', self.overwrite_checkbox().isChecked())
@@ -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.tasks.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,217 @@
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.tasks.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 SegmentMuscleFatT4PyTorchTask
24
+
25
+ LOG = LogManager()
26
+
27
+ PANEL_TITLE = 'SegmentMuscleFatT4PyTorchTask'
28
+ PANEL_NAME = 'segmentmusclefatt4pytorchtaskpanel'
29
+
30
+
31
+ class SegmentMuscleFatT4PyTorchTaskPanel(TaskPanel):
32
+ def __init__(self):
33
+ super(SegmentMuscleFatT4PyTorchTaskPanel, 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 = SegmentMuscleFatT4PyTorchTask(
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._task.run()
169
+ self._worker = Worker(self._task)
170
+ self._thread = QThread()
171
+ self._worker.moveToThread(self._thread)
172
+ self._thread.started.connect(self._worker.run)
173
+ self._worker.progress.connect(self.handle_progress)
174
+ self._worker.status.connect(self.handle_status)
175
+ self._worker.finished.connect(self.handle_finished)
176
+ self._worker.finished.connect(self._thread.quit)
177
+ self._worker.finished.connect(self._worker.deleteLater)
178
+ self._thread.finished.connect(self._thread.deleteLater)
179
+ self._thread.start()
180
+
181
+ @Slot(int)
182
+ def handle_progress(self, progress):
183
+ LOG.info(f'Progress: {progress} / 100%')
184
+
185
+ @Slot(str)
186
+ def handle_status(self, status):
187
+ LOG.info(f'Status: {status}')
188
+
189
+ @Slot()
190
+ def handle_finished(self):
191
+ self.run_task_button().setEnabled(True)
192
+
193
+ # HELPERS
194
+
195
+ def check_inputs_and_parameters(self):
196
+ errors = []
197
+ if self.images_dir_line_edit().text() == '':
198
+ errors.append('Empty images directory path')
199
+ if not os.path.isdir(self.images_dir_line_edit().text()):
200
+ errors.append('Images directory does not exist')
201
+ if self.model_files_dir_line_edit().text() == '':
202
+ errors.append('Empty model files directory path')
203
+ if not os.path.isdir(self.model_files_dir_line_edit().text()):
204
+ errors.append('Model files directory does not exist')
205
+ if len(os.listdir(self.model_files_dir_line_edit().text())) != 3:
206
+ errors.append('Model files directory should ONLY contain "model-1.0.pt", "contour_model-1.0.pt" and "params-1.0.json", nothing else!')
207
+ if self.output_dir_line_edit().text() == '':
208
+ errors.append('Empty output directory path')
209
+ if os.path.isdir(self.output_dir_line_edit().text()) and not self.overwrite_checkbox().isChecked():
210
+ errors.append('Output directory exists but overwrite=False. Please remove output directory first')
211
+ return errors
212
+
213
+ def save_inputs_and_parameters(self):
214
+ self.settings().set(f'{PANEL_NAME}/images_dir', self.images_dir_line_edit().text())
215
+ self.settings().set(f'{PANEL_NAME}/model_files_dir', self.model_files_dir_line_edit().text())
216
+ self.settings().set(f'{PANEL_NAME}/output_dir', self.output_dir_line_edit().text())
217
+ self.settings().set(f'{PANEL_NAME}/overwrite', self.overwrite_checkbox().isChecked())