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,426 @@
1
+ import os
2
+ import mosamatic2.constants as constants
3
+ from PySide6.QtWidgets import (
4
+ QMainWindow,
5
+ )
6
+ from PySide6.QtGui import (
7
+ QGuiApplication,
8
+ QAction,
9
+ QIcon,
10
+ )
11
+ from PySide6.QtCore import Qt, QByteArray
12
+ from mosamatic2.ui.utils import version, resource_path, is_macos
13
+ from mosamatic2.core.managers.logmanager import LogManager
14
+ from mosamatic2.ui.settings import Settings
15
+ from mosamatic2.ui.widgets.panels.mainpanel import MainPanel
16
+ from mosamatic2.ui.widgets.panels.logpanel import LogPanel
17
+ from mosamatic2.ui.widgets.panels.tasks.rescaledicomimagestaskpanel import RescaleDicomImagesTaskPanel
18
+ from mosamatic2.ui.widgets.panels.tasks.segmentmusclefatl3tensorflowtaskpanel import SegmentMuscleFatL3TensorFlowTaskPanel
19
+ from mosamatic2.ui.widgets.panels.tasks.segmentmusclefatt4pytorchtaskpanel import SegmentMuscleFatT4PyTorchTaskPanel
20
+ from mosamatic2.ui.widgets.panels.tasks.createpngsfromsegmentationstaskpanel import CreatePngsFromSegmentationsTaskPanel
21
+ from mosamatic2.ui.widgets.panels.tasks.calculatescorestaskpanel import CalculateScoresTaskPanel
22
+ from mosamatic2.ui.widgets.panels.tasks.dicom2niftitaskpanel import Dicom2NiftiTaskPanel
23
+ from mosamatic2.ui.widgets.panels.tasks.segmentationnifti2numpytaskpanel import SegmentationNifti2NumpyTaskPanel
24
+ from mosamatic2.ui.widgets.panels.tasks.segmentationnumpy2niftitaskpanel import SegmentationNumpy2NiftiTaskPanel
25
+ from mosamatic2.ui.widgets.panels.tasks.createdicomsummarytaskpanel import CreateDicomSummaryTaskPanel
26
+ from mosamatic2.ui.widgets.panels.tasks.selectslicefromscanstaskpanel import SelectSliceFromScansTaskPanel
27
+ from mosamatic2.ui.widgets.panels.tasks.totalsegmentatortaskpanel import TotalSegmentatorTaskPanel
28
+ from mosamatic2.ui.widgets.panels.tasks.calculatemaskstatisticstaskpanel import CalculateMaskStatisticsTaskPanel
29
+ from mosamatic2.ui.widgets.panels.tasks.applythresholdtosegmentationstaskpanel import ApplyThresholdToSegmentationsTaskPanel
30
+ from mosamatic2.ui.widgets.panels.pipelines.defaultpipelinepanel import DefaultPipelinePanel
31
+ from mosamatic2.ui.widgets.panels.pipelines.defaultdockerpipelinepanel import DefaultDockerPipelinePanel
32
+ from mosamatic2.ui.widgets.panels.pipelines.boadockerpipelinepanel import BoaDockerPipelinePanel
33
+ from mosamatic2.ui.widgets.panels.pipelines.liveranalysispipelinepanel import LiverAnalysisPipelinePanel
34
+ from mosamatic2.ui.widgets.panels.visualizations.slicevisualization.slicevisualization import SliceVisualization
35
+ from mosamatic2.ui.widgets.panels.visualizations.sliceselectionvisualization.sliceselectionvisualization import SliceSelectionVisualization
36
+ from mosamatic2.ui.widgets.panels.visualizations.liversegmentvisualization.liversegmentvisualization import LiverSegmentVisualization
37
+
38
+
39
+ LOG = LogManager()
40
+
41
+
42
+ class MainWindow(QMainWindow):
43
+ def __init__(self):
44
+ super(MainWindow, self).__init__()
45
+ self._settings = None
46
+ self._main_panel = None
47
+ self._log_panel = None
48
+ self._decompress_dicom_files_task_panel = None
49
+ self._rescale_dicom_images_task_panel = None
50
+ self._segment_muscle_fat_l3_tensorflow_task_panel = None
51
+ self._segment_muscle_fat_t4_pytorch_task_panel = None
52
+ self._create_pngs_from_segmentations_task_panel = None
53
+ self._calculate_scores_task_panel = None
54
+ self._dicom2nifti_task_panel = None
55
+ self._segmentation_numpy_to_nifti_task_panel = None
56
+ self._segmentation_nifti_to_numpy_task_panel = None
57
+ self._create_dicom_summary_task_panel = None
58
+ self._select_slice_from_scans_task_panel = None
59
+ self._total_segmentator_task_panel = None
60
+ self._calculate_mask_statistics_task_panel = None
61
+ self._apply_threshold_to_segmentations_task_panel = None
62
+ self._default_pipeline_panel = None
63
+ self._default_docker_pipeline_panel = None
64
+ self._boa_docker_pipeline_panel = None
65
+ self._liver_analysis_pipeline_panel = None
66
+ self._slice_visualization = None
67
+ self._slice_selection_visualization = None
68
+ self._liver_segment_visualization = None
69
+ self.init_window()
70
+
71
+ def init_window(self):
72
+ self.setWindowTitle(f'{constants.MOSAMATIC2_WINDOW_TITLE} {version()}')
73
+ icon_file_name = constants.MOSAMATIC2_APP_ICON_FILE_NAME_MAC if is_macos() else constants.MOSAMATIC2_APP_ICON_FILE_NAME_WIN
74
+ icon_path = resource_path(os.path.join(constants.MOSAMATIC2_ICONS_DIR_PATH, icon_file_name))
75
+ self.setWindowIcon(QIcon(icon_path))
76
+ if not self.load_geometry_and_state():
77
+ self.set_default_size_and_position()
78
+ self.init_menus()
79
+ self.init_status_bar()
80
+ self.addDockWidget(Qt.DockWidgetArea.TopDockWidgetArea, self.main_panel())
81
+ self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, self.log_panel())
82
+
83
+ def init_menus(self):
84
+ self.init_app_menu()
85
+ self.init_tasks_menu()
86
+ self.init_pipelines_menu()
87
+ self.init_visualizations_menu()
88
+ if is_macos():
89
+ self.menuBar().setNativeMenuBar(False)
90
+
91
+ def init_app_menu(self):
92
+ exit_action = QAction('Exit', self)
93
+ exit_action.triggered.connect(self.close)
94
+ app_menu = self.menuBar().addMenu('Application')
95
+ app_menu.addAction(exit_action)
96
+
97
+ def init_tasks_menu(self):
98
+ rescale_dicom_images_task_action = QAction('RescaleDicomImagesTask', self)
99
+ rescale_dicom_images_task_action.triggered.connect(self.handle_rescale_dicom_images_task_action)
100
+ segment_muscle_fat_l3_tensorflow_task_action = QAction('SegmentMuscleAndFatL3TensorFlowTask', self)
101
+ segment_muscle_fat_l3_tensorflow_task_action.triggered.connect(self.handle_segment_muscle_fat_l3_tensorflow_task_action)
102
+ segment_muscle_fat_t4_pytorch_task_action = QAction("SegmentMuscleFatT4PytorchTask", self)
103
+ segment_muscle_fat_t4_pytorch_task_action.triggered.connect(self.handle_segment_muscle_fat_t4_pytorch_task_action)
104
+ calculate_scores_task_action = QAction('CalculateScoresTask', self)
105
+ calculate_scores_task_action.triggered.connect(self.handle_calculate_scores_task_action)
106
+ create_pngs_from_segmentations_task_action = QAction('CreatePngsFromSegmentationsTask', self)
107
+ create_pngs_from_segmentations_task_action.triggered.connect(self.handle_create_pngs_from_segmentations_task_action)
108
+ dicom2nifti_task_action = QAction('Dicom2NiftiTask', self)
109
+ dicom2nifti_task_action.triggered.connect(self.handle_dicom2nifti_task_action)
110
+ segmentation_numpy_to_nifti_task_action = QAction('SegmentationNumpy2NiftiTask', self)
111
+ segmentation_numpy_to_nifti_task_action.triggered.connect(self.handle_segmentation_numpy_to_nifti_task_action)
112
+ segmentation_nifti_to_numpy_task_action = QAction('SegmentationNifti2NumpyTask', self)
113
+ segmentation_nifti_to_numpy_task_action.triggered.connect(self.handle_segmentation_nifti_to_numpy_task_action)
114
+ create_dicom_summary_task_action = QAction('CreateDicomSummaryTask', self)
115
+ create_dicom_summary_task_action.triggered.connect(self.handle_create_dicom_summary_task_action)
116
+ select_slice_from_scans_task_action = QAction('SelectSliceFromScansTask', self)
117
+ select_slice_from_scans_task_action.triggered.connect(self.handle_select_slice_from_scans_task_action)
118
+ total_segmentator_task_action = QAction('TotalSegmentatorTask', self)
119
+ total_segmentator_task_action.triggered.connect(self.handle_total_segmentator_task_action)
120
+ calculate_mask_statistics_task_action = QAction('CalculateMaskStatisticsTask', self)
121
+ calculate_mask_statistics_task_action.triggered.connect(self.handle_calculate_mask_statistics_task_action)
122
+ apply_threshold_to_segmentations_task_action = QAction('ApplyThresholdToSegmentationsTask', self)
123
+ apply_threshold_to_segmentations_task_action.triggered.connect(self.handle_apply_threshold_to_segmentations_task_action)
124
+ tasks_menu = self.menuBar().addMenu('Tasks')
125
+ tasks_menu.addAction(rescale_dicom_images_task_action)
126
+ tasks_menu.addAction(segment_muscle_fat_l3_tensorflow_task_action)
127
+ tasks_menu.addAction(segment_muscle_fat_t4_pytorch_task_action)
128
+ tasks_menu.addAction(calculate_scores_task_action)
129
+ tasks_menu.addAction(create_pngs_from_segmentations_task_action)
130
+ tasks_menu.addAction(dicom2nifti_task_action)
131
+ tasks_menu.addAction(segmentation_numpy_to_nifti_task_action)
132
+ tasks_menu.addAction(segmentation_nifti_to_numpy_task_action)
133
+ tasks_menu.addAction(create_dicom_summary_task_action)
134
+ tasks_menu.addAction(select_slice_from_scans_task_action)
135
+ tasks_menu.addAction(total_segmentator_task_action)
136
+ tasks_menu.addAction(calculate_mask_statistics_task_action)
137
+ tasks_menu.addAction(apply_threshold_to_segmentations_task_action)
138
+
139
+ def init_pipelines_menu(self):
140
+ default_pipeline_action = QAction('DefaultPipeline', self)
141
+ default_pipeline_action.triggered.connect(self.handle_default_pipeline_action)
142
+ default_docker_pipeline_action = QAction('DefaultDockerPipeline', self)
143
+ default_docker_pipeline_action.triggered.connect(self.handle_default_docker_pipeline_action)
144
+ boa_docker_pipeline_action = QAction('BoaDockerPipeline', self)
145
+ boa_docker_pipeline_action.triggered.connect(self.handle_boa_docker_pipeline_action)
146
+ liver_analysis_pipeline_action = QAction('LiverAnalysisPipeline', self)
147
+ liver_analysis_pipeline_action.triggered.connect(self.handle_liver_analysis_pipeline_action)
148
+ pipelines_menu = self.menuBar().addMenu('Pipelines')
149
+ pipelines_menu.addAction(default_pipeline_action)
150
+ pipelines_menu.addAction(default_docker_pipeline_action)
151
+ pipelines_menu.addAction(boa_docker_pipeline_action)
152
+ pipelines_menu.addAction(liver_analysis_pipeline_action)
153
+
154
+ def init_visualizations_menu(self):
155
+ slice_visualization_action = QAction('SliceVisualization', self)
156
+ slice_visualization_action.triggered.connect(self.handle_slice_visualization_action)
157
+ slice_selection_visualization_action = QAction('SliceSelectionVisualization', self)
158
+ slice_selection_visualization_action.triggered.connect(self.handle_slice_selection_visualization_action)
159
+ liver_segment_visualization_action = QAction('LiverSegmentVisualization', self)
160
+ liver_segment_visualization_action.triggered.connect(self.handle_liver_segment_visualization_action)
161
+ visualizations_menu = self.menuBar().addMenu('Visualizations')
162
+ visualizations_menu.addAction(slice_visualization_action)
163
+ visualizations_menu.addAction(slice_selection_visualization_action)
164
+ visualizations_menu.addAction(liver_segment_visualization_action)
165
+
166
+ def init_status_bar(self):
167
+ self.set_status('Ready')
168
+
169
+ # GET
170
+
171
+ def settings(self):
172
+ if not self._settings:
173
+ self._settings = Settings()
174
+ return self._settings
175
+
176
+ def main_panel(self):
177
+ if not self._main_panel:
178
+ self._main_panel = MainPanel(self)
179
+ self._main_panel.add_panel(self.rescale_dicom_images_task_panel(), 'rescaledicomimagestaskpanel')
180
+ self._main_panel.add_panel(self.segment_muscle_fat_l3_tensorflow_task_panel(), 'segmentmusclefatl3tensorflowtaskpanel')
181
+ self._main_panel.add_panel(self.segment_muscle_fat_t4_pytorch_task_panel(), 'segmentmusclefatt4pytorchtaskpanel')
182
+ self._main_panel.add_panel(self.create_pngs_from_segmentations_task_panel(), 'createpngsfromsegmentationstaskpanel')
183
+ self._main_panel.add_panel(self.calculate_scores_task_panel(), 'calculatescorestaskpanel')
184
+ self._main_panel.add_panel(self.dicom2nifti_task_panel(), 'dicom2niftitaskpanel')
185
+ self._main_panel.add_panel(self.segmentation_numpy_to_nifti_task_panel(), 'segmentationnumpy2niftitaskpanel')
186
+ self._main_panel.add_panel(self.segmentation_nifti_to_numpy_task_panel(), 'segmentationnifti2numpytaskpanel')
187
+ self._main_panel.add_panel(self.create_dicom_summary_task_panel(), 'createdicomsummarytaskpanel')
188
+ self._main_panel.add_panel(self.select_slice_from_scans_task_panel(), 'selectslicefromscanstaskpanel')
189
+ self._main_panel.add_panel(self.total_segmentator_task_panel(), 'totalsegmentatortaskpanel')
190
+ self._main_panel.add_panel(self.calculate_mask_statistics_task_panel(), 'calculatemaskstatisticstaskpanel')
191
+ self._main_panel.add_panel(self.apply_threshold_to_segmentations_task_panel(), 'applythresholdtosegmentationstaskpanel')
192
+ self._main_panel.add_panel(self.default_pipeline_panel(), 'defaultpipelinepanel')
193
+ self._main_panel.add_panel(self.default_docker_pipeline_panel(), 'defaultdockerpipelinepanel')
194
+ self._main_panel.add_panel(self.boa_docker_pipeline_panel(), 'boadockerpipelinepanel')
195
+ self._main_panel.add_panel(self.liver_analysis_pipeline_panel(), 'liveranalysispipelinepanel')
196
+ self._main_panel.add_panel(self.slice_visualization(), 'slicevisualization')
197
+ self._main_panel.add_panel(self.slice_selection_visualization(), 'sliceselectionvisualization')
198
+ self._main_panel.add_panel(self.liver_segment_visualization(), 'liversegmentvisualization')
199
+ self._main_panel.select_panel('defaultpipelinepanel')
200
+ return self._main_panel
201
+
202
+ def log_panel(self):
203
+ if not self._log_panel:
204
+ self._log_panel = LogPanel()
205
+ LOG.add_listener(self._log_panel)
206
+ return self._log_panel
207
+
208
+ # MISCELLANEOUS
209
+
210
+ def rescale_dicom_images_task_panel(self):
211
+ if not self._rescale_dicom_images_task_panel:
212
+ self._rescale_dicom_images_task_panel = RescaleDicomImagesTaskPanel()
213
+ return self._rescale_dicom_images_task_panel
214
+
215
+ def segment_muscle_fat_l3_tensorflow_task_panel(self):
216
+ if not self._segment_muscle_fat_l3_tensorflow_task_panel:
217
+ self._segment_muscle_fat_l3_tensorflow_task_panel = SegmentMuscleFatL3TensorFlowTaskPanel()
218
+ return self._segment_muscle_fat_l3_tensorflow_task_panel
219
+
220
+ def segment_muscle_fat_t4_pytorch_task_panel(self):
221
+ if not self._segment_muscle_fat_t4_pytorch_task_panel:
222
+ self._segment_muscle_fat_t4_pytorch_task_panel = SegmentMuscleFatT4PyTorchTaskPanel()
223
+ return self._segment_muscle_fat_t4_pytorch_task_panel
224
+
225
+ def create_pngs_from_segmentations_task_panel(self):
226
+ if not self._create_pngs_from_segmentations_task_panel:
227
+ self._create_pngs_from_segmentations_task_panel = CreatePngsFromSegmentationsTaskPanel()
228
+ return self._create_pngs_from_segmentations_task_panel
229
+
230
+ def calculate_scores_task_panel(self):
231
+ if not self._calculate_scores_task_panel:
232
+ self._calculate_scores_task_panel = CalculateScoresTaskPanel()
233
+ return self._calculate_scores_task_panel
234
+
235
+ def dicom2nifti_task_panel(self):
236
+ if not self._dicom2nifti_task_panel:
237
+ self._dicom2nifti_task_panel = Dicom2NiftiTaskPanel()
238
+ return self._dicom2nifti_task_panel
239
+
240
+ def segmentation_numpy_to_nifti_task_panel(self):
241
+ if not self._segmentation_numpy_to_nifti_task_panel:
242
+ self._segmentation_numpy_to_nifti_task_panel = SegmentationNumpy2NiftiTaskPanel()
243
+ return self._segmentation_numpy_to_nifti_task_panel
244
+
245
+ def segmentation_nifti_to_numpy_task_panel(self):
246
+ if not self._segmentation_nifti_to_numpy_task_panel:
247
+ self._segmentation_nifti_to_numpy_task_panel = SegmentationNifti2NumpyTaskPanel()
248
+ return self._segmentation_nifti_to_numpy_task_panel
249
+
250
+ def create_dicom_summary_task_panel(self):
251
+ if not self._create_dicom_summary_task_panel:
252
+ self._create_dicom_summary_task_panel = CreateDicomSummaryTaskPanel()
253
+ return self._create_dicom_summary_task_panel
254
+
255
+ def select_slice_from_scans_task_panel(self):
256
+ if not self._select_slice_from_scans_task_panel:
257
+ self._select_slice_from_scans_task_panel = SelectSliceFromScansTaskPanel()
258
+ return self._select_slice_from_scans_task_panel
259
+
260
+ def total_segmentator_task_panel(self):
261
+ if not self._total_segmentator_task_panel:
262
+ self._total_segmentator_task_panel = TotalSegmentatorTaskPanel()
263
+ return self._total_segmentator_task_panel
264
+
265
+ def calculate_mask_statistics_task_panel(self):
266
+ if not self._calculate_mask_statistics_task_panel:
267
+ self._calculate_mask_statistics_task_panel = CalculateMaskStatisticsTaskPanel()
268
+ return self._calculate_mask_statistics_task_panel
269
+
270
+ def apply_threshold_to_segmentations_task_panel(self):
271
+ if not self._apply_threshold_to_segmentations_task_panel:
272
+ self._apply_threshold_to_segmentations_task_panel = ApplyThresholdToSegmentationsTaskPanel()
273
+ return self._apply_threshold_to_segmentations_task_panel
274
+
275
+ def default_pipeline_panel(self):
276
+ if not self._default_pipeline_panel:
277
+ self._default_pipeline_panel = DefaultPipelinePanel()
278
+ return self._default_pipeline_panel
279
+
280
+ def default_docker_pipeline_panel(self):
281
+ if not self._default_docker_pipeline_panel:
282
+ self._default_docker_pipeline_panel = DefaultDockerPipelinePanel()
283
+ return self._default_docker_pipeline_panel
284
+
285
+ def boa_docker_pipeline_panel(self):
286
+ if not self._boa_docker_pipeline_panel:
287
+ self._boa_docker_pipeline_panel = BoaDockerPipelinePanel()
288
+ return self._boa_docker_pipeline_panel
289
+
290
+ def liver_analysis_pipeline_panel(self):
291
+ if not self._liver_analysis_pipeline_panel:
292
+ self._liver_analysis_pipeline_panel = LiverAnalysisPipelinePanel()
293
+ return self._liver_analysis_pipeline_panel
294
+
295
+ def slice_visualization(self):
296
+ if not self._slice_visualization:
297
+ self._slice_visualization = SliceVisualization()
298
+ return self._slice_visualization
299
+
300
+ def slice_selection_visualization(self):
301
+ if not self._slice_selection_visualization:
302
+ self._slice_selection_visualization = SliceSelectionVisualization()
303
+ return self._slice_selection_visualization
304
+
305
+ def liver_segment_visualization(self):
306
+ if not self._liver_segment_visualization:
307
+ self._liver_segment_visualization = LiverSegmentVisualization()
308
+ return self._liver_segment_visualization
309
+
310
+ # SETTERS
311
+
312
+ def set_status(self, message):
313
+ self.statusBar().showMessage(message)
314
+
315
+ # EVENT HANDLERS
316
+
317
+ def handle_rescale_dicom_images_task_action(self):
318
+ self.main_panel().select_panel('rescaledicomimagestaskpanel')
319
+
320
+ def handle_segment_muscle_fat_l3_tensorflow_task_action(self):
321
+ self.main_panel().select_panel('segmentmusclefatl3tensorflowtaskpanel')
322
+
323
+ def handle_segment_muscle_fat_t4_pytorch_task_action(self):
324
+ self.main_panel().select_panel('segmentmusclefatt4pytorchtaskpanel')
325
+
326
+ def handle_create_pngs_from_segmentations_task_action(self):
327
+ self.main_panel().select_panel('createpngsfromsegmentationstaskpanel')
328
+
329
+ def handle_calculate_scores_task_action(self):
330
+ self.main_panel().select_panel('calculatescorestaskpanel')
331
+
332
+ def handle_dicom2nifti_task_action(self):
333
+ self.main_panel().select_panel('dicom2niftitaskpanel')
334
+
335
+ def handle_segmentation_numpy_to_nifti_task_action(self):
336
+ self.main_panel().select_panel('segmentationnumpy2niftitaskpanel')
337
+
338
+ def handle_segmentation_nifti_to_numpy_task_action(self):
339
+ self.main_panel().select_panel('segmentationnifti2numpytaskpanel')
340
+
341
+ def handle_create_dicom_summary_task_action(self):
342
+ self.main_panel().select_panel('createdicomsummarytaskpanel')
343
+
344
+ def handle_select_slice_from_scans_task_action(self):
345
+ self.main_panel().select_panel('selectslicefromscanstaskpanel')
346
+
347
+ def handle_total_segmentator_task_action(self):
348
+ self.main_panel().select_panel('totalsegmentatortaskpanel')
349
+
350
+ def handle_calculate_mask_statistics_task_action(self):
351
+ self.main_panel().select_panel('calculatemaskstatisticstaskpanel')
352
+
353
+ def handle_apply_threshold_to_segmentations_task_action(self):
354
+ self.main_panel().select_panel('applythresholdtosegmentationstaskpanel')
355
+
356
+ def handle_default_pipeline_action(self):
357
+ self.main_panel().select_panel('defaultpipelinepanel')
358
+
359
+ def handle_default_docker_pipeline_action(self):
360
+ self.main_panel().select_panel('defaultdockerpipelinepanel')
361
+
362
+ def handle_boa_docker_pipeline_action(self):
363
+ self.main_panel().select_panel('boadockerpipelinepanel')
364
+
365
+ def handle_liver_analysis_pipeline_action(self):
366
+ self.main_panel().select_panel('liveranalysispipelinepanel')
367
+
368
+ def handle_slice_visualization_action(self):
369
+ self.main_panel().select_panel('slicevisualization')
370
+
371
+ def handle_slice_selection_visualization_action(self):
372
+ self.main_panel().select_panel('sliceselectionvisualization')
373
+
374
+ def handle_liver_segment_visualization_action(self):
375
+ self.main_panel().select_panel('liversegmentvisualization')
376
+
377
+ def showEvent(self, event):
378
+ return super().showEvent(event)
379
+
380
+ def closeEvent(self, event):
381
+ self.save_geometry_and_state()
382
+ # Save inputs and parameters of relevant panels
383
+ self.rescale_dicom_images_task_panel().save_inputs_and_parameters()
384
+ self.segment_muscle_fat_l3_tensorflow_task_panel().save_inputs_and_parameters()
385
+ self.segment_muscle_fat_t4_pytorch_task_panel().save_inputs_and_parameters()
386
+ self.create_pngs_from_segmentations_task_panel().save_inputs_and_parameters()
387
+ self.calculate_scores_task_panel().save_inputs_and_parameters()
388
+ self.dicom2nifti_task_panel().save_inputs_and_parameters()
389
+ self.segmentation_numpy_to_nifti_task_panel().save_inputs_and_parameters()
390
+ self.segmentation_nifti_to_numpy_task_panel().save_inputs_and_parameters()
391
+ self.create_dicom_summary_task_panel().save_inputs_and_parameters()
392
+ self.select_slice_from_scans_task_panel().save_inputs_and_parameters()
393
+ self.total_segmentator_task_panel().save_inputs_and_parameters()
394
+ self.calculate_mask_statistics_task_panel().save_inputs_and_parameters()
395
+ self.apply_threshold_to_segmentations_task_panel().save_inputs_and_parameters()
396
+ self.default_pipeline_panel().save_inputs_and_parameters()
397
+ self.default_docker_pipeline_panel().save_inputs_and_parameters()
398
+ self.boa_docker_pipeline_panel().save_inputs_and_parameters()
399
+ self.liver_analysis_pipeline_panel().save_inputs_and_parameters()
400
+ self.slice_visualization().save_inputs_and_parameters()
401
+ self.slice_selection_visualization().save_inputs_and_parameters()
402
+ self.liver_segment_visualization().save_inputs_and_parameters()
403
+ return super().closeEvent(event)
404
+
405
+ def load_geometry_and_state(self):
406
+ geometry = self.settings().get(constants.MOSAMATIC2_WINDOW_GEOMETRY_KEY)
407
+ state = self.settings().get(constants.MOSAMATIC2_WINDOW_STATE_KEY)
408
+ if isinstance(geometry, QByteArray) and self.restoreGeometry(geometry):
409
+ if isinstance(state, QByteArray):
410
+ self.restoreState(state)
411
+ return True
412
+ return False
413
+
414
+ def save_geometry_and_state(self):
415
+ self.settings().set(constants.MOSAMATIC2_WINDOW_GEOMETRY_KEY, self.saveGeometry())
416
+ self.settings().set(constants.MOSAMATIC2_WINDOW_STATE_KEY, self.saveState())
417
+
418
+ def set_default_size_and_position(self):
419
+ self.resize(constants.MOSAMATIC2_WINDOW_W, constants.MOSAMATIC2_WINDOW_H)
420
+ self.center_window()
421
+
422
+ def center_window(self):
423
+ screen = QGuiApplication.primaryScreen().geometry()
424
+ x = (screen.width() - self.geometry().width()) / 2
425
+ y = (screen.height() - self.geometry().height()) / 2
426
+ self.move(int(x), int(y))
@@ -0,0 +1 @@
1
+ 2.0.24
@@ -0,0 +1,62 @@
1
+ import mosamatic2.constants as constants
2
+ from PySide6.QtCore import QSettings
3
+ from mosamatic2.core.managers.logmanager import LogManager
4
+
5
+ LOG = LogManager()
6
+
7
+
8
+ class Settings(QSettings):
9
+ def __init__(self):
10
+ super(Settings, self).__init__(
11
+ QSettings.IniFormat,
12
+ QSettings.UserScope,
13
+ constants.MOSAMATIC2_BUNDLE_IDENTIFIER,
14
+ constants.MOSAMATIC2_APP_NAME,
15
+ )
16
+
17
+ def prepend_bundle_identifier_and_name(self, name):
18
+ return '{}.{}.{}'.format(constants.MOSAMATIC2_BUNDLE_IDENTIFIER, constants.MOSAMATIC2_APP_NAME, name)
19
+
20
+ def get(self, name, default=None):
21
+ if not name.startswith(constants.MOSAMATIC2_BUNDLE_IDENTIFIER):
22
+ name = self.prepend_bundle_identifier_and_name(name)
23
+ value = self.value(name)
24
+ if value is None or value == '':
25
+ return default
26
+ return value
27
+
28
+ def get_int(self, name, default=None):
29
+ try:
30
+ return int(self.get(name, default))
31
+ except ValueError as e:
32
+ return default
33
+
34
+ def get_float(self, name, default=None):
35
+ try:
36
+ return float(self.get(name, default))
37
+ except ValueError as e:
38
+ return default
39
+
40
+ def get_bool(self, name, default=None):
41
+ try:
42
+ value = self.get(name, default)
43
+ if value and isinstance(value, str):
44
+ if value == '0' or value.lower() == 'false':
45
+ return False
46
+ elif value == '1' or value.lower() == 'true':
47
+ return True
48
+ else:
49
+ return default
50
+ if value and isinstance(value, bool):
51
+ return value
52
+ except ValueError as e:
53
+ return default
54
+
55
+ def set(self, name, value):
56
+ name = self.prepend_bundle_identifier_and_name(name)
57
+ self.setValue(name, value)
58
+
59
+ def print(self):
60
+ LOG.info(f'Settings path: {self.fileName()}')
61
+ for key in self.allKeys():
62
+ LOG.info(f'Settings: {key}')
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)