mosamatic2 2.0.6__tar.gz → 2.0.7__tar.gz

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 (91) hide show
  1. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/PKG-INFO +1 -1
  2. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/pyproject.toml +1 -1
  3. mosamatic2-2.0.7/src/mosamatic2/core/pipelines/__init__.py +1 -0
  4. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/tasks/__init__.py +2 -1
  5. mosamatic2-2.0.7/src/mosamatic2/core/tasks/createdicomsummarytask/createdicomsummarytask.py +60 -0
  6. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/mainwindow.py +15 -0
  7. mosamatic2-2.0.7/src/mosamatic2/ui/resources/VERSION +1 -0
  8. mosamatic2-2.0.7/src/mosamatic2/ui/widgets/panels/tasks/createdicomsummarytaskpanel.py +183 -0
  9. mosamatic2-2.0.7/src/mosamatic2/ui/widgets/panels/visualizations/__init__.py +0 -0
  10. mosamatic2-2.0.7/src/mosamatic2/ui/widgets/panels/visualizations/slicevisualization/__init__.py +0 -0
  11. mosamatic2-2.0.6/src/mosamatic2/core/pipelines/__init__.py +0 -1
  12. mosamatic2-2.0.6/src/mosamatic2/ui/resources/VERSION +0 -1
  13. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/README.md +0 -0
  14. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/models.py +0 -0
  15. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/__init__.py +0 -0
  16. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/app.py +0 -0
  17. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/cli.py +0 -0
  18. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/commands/__init__.py +0 -0
  19. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/commands/calculatescores.py +0 -0
  20. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/commands/createpngsfromsegmentations.py +0 -0
  21. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/commands/dicom2nifti.py +0 -0
  22. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/commands/rescaledicomimages.py +0 -0
  23. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/commands/segmentmusclefatl3tensorflow.py +0 -0
  24. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/commands/selectslicefromscans.py +0 -0
  25. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/constants.py +0 -0
  26. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/__init__.py +0 -0
  27. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/data/__init__.py +0 -0
  28. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/data/dicomimage.py +0 -0
  29. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/data/dicomimageseries.py +0 -0
  30. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/data/dixonseries.py +0 -0
  31. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/data/filedata.py +0 -0
  32. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/data/multidicomimage.py +0 -0
  33. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/data/multinumpyimage.py +0 -0
  34. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/data/numpyimage.py +0 -0
  35. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/managers/__init__.py +0 -0
  36. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/managers/logmanager.py +0 -0
  37. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/managers/logmanagerlistener.py +0 -0
  38. {mosamatic2-2.0.6/src/mosamatic2/core/tasks/calculatescorestask → mosamatic2-2.0.7/src/mosamatic2/core/pipelines/defaultpipeline}/__init__.py +0 -0
  39. {mosamatic2-2.0.6/src/mosamatic2/core/pipelines → mosamatic2-2.0.7/src/mosamatic2/core/pipelines/defaultpipeline}/defaultpipeline.py +0 -0
  40. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/pipelines/pipeline.py +0 -0
  41. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/singleton.py +0 -0
  42. {mosamatic2-2.0.6/src/mosamatic2/core/tasks/createpngsfromsegmentationstask → mosamatic2-2.0.7/src/mosamatic2/core/tasks/calculatescorestask}/__init__.py +0 -0
  43. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/tasks/calculatescorestask/calculatescorestask.py +0 -0
  44. {mosamatic2-2.0.6/src/mosamatic2/core/tasks/dicom2niftitask → mosamatic2-2.0.7/src/mosamatic2/core/tasks/createdicomsummarytask}/__init__.py +0 -0
  45. {mosamatic2-2.0.6/src/mosamatic2/core/tasks/rescaledicomimagestask → mosamatic2-2.0.7/src/mosamatic2/core/tasks/createpngsfromsegmentationstask}/__init__.py +0 -0
  46. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/tasks/createpngsfromsegmentationstask/createpngsfromsegmentationstask.py +0 -0
  47. {mosamatic2-2.0.6/src/mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask → mosamatic2-2.0.7/src/mosamatic2/core/tasks/dicom2niftitask}/__init__.py +0 -0
  48. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/tasks/dicom2niftitask/dicom2niftitask.py +0 -0
  49. {mosamatic2-2.0.6/src/mosamatic2/core/tasks/selectslicefromscanstask → mosamatic2-2.0.7/src/mosamatic2/core/tasks/rescaledicomimagestask}/__init__.py +0 -0
  50. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/tasks/rescaledicomimagestask/rescaledicomimagestask.py +0 -0
  51. {mosamatic2-2.0.6/src/mosamatic2/ui → mosamatic2-2.0.7/src/mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask}/__init__.py +0 -0
  52. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/paramloader.py +0 -0
  53. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/segmentmusclefatl3tensorflowtask.py +0 -0
  54. {mosamatic2-2.0.6/src/mosamatic2/ui/widgets → mosamatic2-2.0.7/src/mosamatic2/core/tasks/selectslicefromscanstask}/__init__.py +0 -0
  55. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/tasks/selectslicefromscanstask/selectslicefromscanstask.py +0 -0
  56. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/tasks/task.py +0 -0
  57. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/core/utils.py +0 -0
  58. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/server.py +0 -0
  59. {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/dialogs → mosamatic2-2.0.7/src/mosamatic2/ui}/__init__.py +0 -0
  60. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/resources/icons/mosamatic2.icns +0 -0
  61. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/resources/icons/mosamatic2.ico +0 -0
  62. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/resources/icons/spinner.gif +0 -0
  63. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/resources/images/body-composition.jpg +0 -0
  64. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/settings.py +0 -0
  65. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/utils.py +0 -0
  66. {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/panels → mosamatic2-2.0.7/src/mosamatic2/ui/widgets}/__init__.py +0 -0
  67. {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/panels/pipelines → mosamatic2-2.0.7/src/mosamatic2/ui/widgets/dialogs}/__init__.py +0 -0
  68. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/dialogs/dialog.py +0 -0
  69. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/dialogs/helpdialog.py +0 -0
  70. {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/panels/tasks → mosamatic2-2.0.7/src/mosamatic2/ui/widgets/panels}/__init__.py +0 -0
  71. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/defaultpanel.py +0 -0
  72. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/logpanel.py +0 -0
  73. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/mainpanel.py +0 -0
  74. {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/panels/visualizations → mosamatic2-2.0.7/src/mosamatic2/ui/widgets/panels/pipelines}/__init__.py +0 -0
  75. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/pipelines/defaultpipelinepanel.py +0 -0
  76. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/pipelines/pipelinepanel.py +0 -0
  77. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/stackedpanel.py +0 -0
  78. {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/panels/visualizations/slicevisualization → mosamatic2-2.0.7/src/mosamatic2/ui/widgets/panels/tasks}/__init__.py +0 -0
  79. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/tasks/calculatescorestaskpanel.py +0 -0
  80. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/tasks/createpngsfromsegmentationstaskpanel.py +0 -0
  81. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/tasks/dicom2niftitaskpanel.py +0 -0
  82. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/tasks/rescaledicomimagestaskpanel.py +0 -0
  83. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/tasks/segmentmusclefatl3tensorflowtaskpanel.py +0 -0
  84. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/tasks/selectslicefromscanstaskpanel.py +0 -0
  85. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/tasks/taskpanel.py +0 -0
  86. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/visualizations/slicevisualization/custominteractorstyle.py +0 -0
  87. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/visualizations/slicevisualization/sliceviewer.py +0 -0
  88. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/visualizations/slicevisualization/slicevisualization.py +0 -0
  89. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/panels/visualizations/visualization.py +0 -0
  90. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/widgets/splashscreen.py +0 -0
  91. {mosamatic2-2.0.6 → mosamatic2-2.0.7}/src/mosamatic2/ui/worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mosamatic2
3
- Version: 2.0.6
3
+ Version: 2.0.7
4
4
  Summary:
5
5
  Author: Ralph Brecheisen
6
6
  Author-email: r.brecheisen@maastrichtuniversity.nl
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mosamatic2"
3
- version = "2.0.6"
3
+ version = "2.0.7"
4
4
  description = ""
5
5
  authors = [
6
6
  {name = "Ralph Brecheisen", email = "r.brecheisen@maastrichtuniversity.nl"}
@@ -0,0 +1 @@
1
+ from mosamatic2.core.pipelines.defaultpipeline.defaultpipeline import DefaultPipeline
@@ -3,4 +3,5 @@ from mosamatic2.core.tasks.segmentmusclefatl3tensorflowtask.segmentmusclefatl3te
3
3
  from mosamatic2.core.tasks.calculatescorestask.calculatescorestask import CalculateScoresTask
4
4
  from mosamatic2.core.tasks.createpngsfromsegmentationstask.createpngsfromsegmentationstask import CreatePngsFromSegmentationsTask
5
5
  from mosamatic2.core.tasks.dicom2niftitask.dicom2niftitask import Dicom2NiftiTask
6
- from mosamatic2.core.tasks.selectslicefromscanstask.selectslicefromscanstask import SelectSliceFromScansTask
6
+ from mosamatic2.core.tasks.selectslicefromscanstask.selectslicefromscanstask import SelectSliceFromScansTask
7
+ from mosamatic2.core.tasks.createdicomsummarytask.createdicomsummarytask import CreateDicomSummaryTask
@@ -0,0 +1,60 @@
1
+ import os
2
+ import json
3
+ from mosamatic2.core.tasks.task import Task
4
+ from mosamatic2.core.managers.logmanager import LogManager
5
+ from mosamatic2.core.utils import is_dicom, load_dicom
6
+
7
+ LOG = LogManager()
8
+
9
+
10
+ class CreateDicomSummaryTask(Task):
11
+ INPUTS = ['directory']
12
+ PARAMS = []
13
+
14
+ def __init__(self, inputs, params, output, overwrite):
15
+ super(CreateDicomSummaryTask, self).__init__(inputs, params, output, overwrite)
16
+
17
+ def run(self):
18
+ nr_steps = len(os.listdir(self.input('directory'))) * 2
19
+ LOG.info('Collecting data...')
20
+ data = {}
21
+ step = 0
22
+ for patient_dir_name in os.listdir(self.input('directory')):
23
+ data[patient_dir_name] = {}
24
+ patient_dir_path = os.path.join(self.input('directory'), patient_dir_name)
25
+ for root, dirs, files in os.walk(patient_dir_path):
26
+ for f in files:
27
+ f_path = os.path.join(root, f)
28
+ if is_dicom(f_path):
29
+ p = load_dicom(f_path, stop_before_pixels=True)
30
+ series_instance_uid = p.SeriesInstanceUID
31
+ if not series_instance_uid in data[patient_dir_name].keys():
32
+ data[patient_dir_name][series_instance_uid] = []
33
+ data[patient_dir_name][series_instance_uid].append(p)
34
+ self.set_progress(step, nr_steps)
35
+ step += 1
36
+ LOG.info('Building summary...')
37
+ summary = {
38
+ 'nr_series_per_patient': {},
39
+ }
40
+ # Calculate nr. of series per patient
41
+ for patient_dir_name in data.keys():
42
+ summary['nr_series_per_patient'][patient_dir_name] = len(data[patient_dir_name].keys())
43
+ # Summarize series data per patient
44
+ for patient_dir_name in data.keys():
45
+ summary[patient_dir_name] = {}
46
+ for series_instance_uid in data[patient_dir_name].keys():
47
+ summary[patient_dir_name][series_instance_uid] = {
48
+ 'nr_images': len(data[patient_dir_name][series_instance_uid]),
49
+ 'modality': data[patient_dir_name][series_instance_uid][0].Modality,
50
+ 'image_type': str(data[patient_dir_name][series_instance_uid][0].ImageType),
51
+ 'rows': data[patient_dir_name][series_instance_uid][0].Rows,
52
+ 'columns': data[patient_dir_name][series_instance_uid][0].Columns,
53
+ 'pixel_spacing': str(data[patient_dir_name][series_instance_uid][0].PixelSpacing),
54
+ 'slice_thickness': data[patient_dir_name][series_instance_uid][0].SliceThickness,
55
+ }
56
+ self.set_progress(step, nr_steps)
57
+ step += 1
58
+ LOG.info('Exporting summary...')
59
+ with open(os.path.join(self.output(), 'summary.txt'), 'w') as f:
60
+ json.dump(summary, f, indent=4)
@@ -19,6 +19,7 @@ from mosamatic2.ui.widgets.panels.tasks.segmentmusclefatl3tensorflowtaskpanel im
19
19
  from mosamatic2.ui.widgets.panels.tasks.createpngsfromsegmentationstaskpanel import CreatePngsFromSegmentationsTaskPanel
20
20
  from mosamatic2.ui.widgets.panels.tasks.calculatescorestaskpanel import CalculateScoresTaskPanel
21
21
  from mosamatic2.ui.widgets.panels.tasks.dicom2niftitaskpanel import Dicom2NiftiTaskPanel
22
+ from mosamatic2.ui.widgets.panels.tasks.createdicomsummarytaskpanel import CreateDicomSummaryTaskPanel
22
23
  from mosamatic2.ui.widgets.panels.tasks.selectslicefromscanstaskpanel import SelectSliceFromScansTaskPanel
23
24
  from mosamatic2.ui.widgets.panels.pipelines.defaultpipelinepanel import DefaultPipelinePanel
24
25
  from mosamatic2.ui.widgets.panels.visualizations.slicevisualization.slicevisualization import SliceVisualization
@@ -38,6 +39,7 @@ class MainWindow(QMainWindow):
38
39
  self._create_pngs_from_segmentations_task_panel = None
39
40
  self._calculate_scores_task_panel = None
40
41
  self._dicom2nifti_task_panel = None
42
+ self._create_dicom_summary_task_panel = None
41
43
  self._select_slice_from_scans_task_panel = None
42
44
  self._default_pipeline_panel = None
43
45
  self._slice_visualization = None
@@ -80,6 +82,8 @@ class MainWindow(QMainWindow):
80
82
  create_pngs_from_segmentations_task_action.triggered.connect(self.handle_create_pngs_from_segmentations_task_action)
81
83
  dicom2nifti_task_action = QAction('Dicom2NiftiTask', self)
82
84
  dicom2nifti_task_action.triggered.connect(self.handle_dicom2nifti_task_action)
85
+ create_dicom_summary_task_action = QAction('CreateDicomSummaryTask', self)
86
+ create_dicom_summary_task_action.triggered.connect(self.handle_create_dicom_summary_task_action)
83
87
  select_slice_from_scans_task_action = QAction('SelectSliceFromScansTask', self)
84
88
  select_slice_from_scans_task_action.triggered.connect(self.handle_select_slice_from_scans_task_action)
85
89
  tasks_menu = self.menuBar().addMenu('Tasks')
@@ -88,6 +92,7 @@ class MainWindow(QMainWindow):
88
92
  tasks_menu.addAction(calculate_scores_task_action)
89
93
  tasks_menu.addAction(create_pngs_from_segmentations_task_action)
90
94
  tasks_menu.addAction(dicom2nifti_task_action)
95
+ tasks_menu.addAction(create_dicom_summary_task_action)
91
96
  tasks_menu.addAction(select_slice_from_scans_task_action)
92
97
 
93
98
  def init_pipelines_menu(self):
@@ -120,6 +125,7 @@ class MainWindow(QMainWindow):
120
125
  self._main_panel.add_panel(self.create_pngs_from_segmentations_task_panel(), 'createpngsfromsegmentationstaskpanel')
121
126
  self._main_panel.add_panel(self.calculate_scores_task_panel(), 'calculatescorestaskpanel')
122
127
  self._main_panel.add_panel(self.dicom2nifti_task_panel(), 'dicom2niftitaskpanel')
128
+ self._main_panel.add_panel(self.create_dicom_summary_task_panel(), 'createdicomsummarytaskpanel')
123
129
  self._main_panel.add_panel(self.select_slice_from_scans_task_panel(), 'selectslicefromscanstaskpanel')
124
130
  self._main_panel.add_panel(self.default_pipeline_panel(), 'defaultpipelinepanel')
125
131
  self._main_panel.add_panel(self.slice_visualization(), 'slicevisualization')
@@ -158,6 +164,11 @@ class MainWindow(QMainWindow):
158
164
  if not self._dicom2nifti_task_panel:
159
165
  self._dicom2nifti_task_panel = Dicom2NiftiTaskPanel()
160
166
  return self._dicom2nifti_task_panel
167
+
168
+ def create_dicom_summary_task_panel(self):
169
+ if not self._create_dicom_summary_task_panel:
170
+ self._create_dicom_summary_task_panel = CreateDicomSummaryTaskPanel()
171
+ return self._create_dicom_summary_task_panel
161
172
 
162
173
  def select_slice_from_scans_task_panel(self):
163
174
  if not self._select_slice_from_scans_task_panel:
@@ -196,6 +207,9 @@ class MainWindow(QMainWindow):
196
207
  def handle_dicom2nifti_task_action(self):
197
208
  self.main_panel().select_panel('dicom2niftitaskpanel')
198
209
 
210
+ def handle_create_dicom_summary_task_action(self):
211
+ self.main_panel().select_panel('createdicomsummarytaskpanel')
212
+
199
213
  def handle_select_slice_from_scans_task_action(self):
200
214
  self.main_panel().select_panel('selectslicefromscanstaskpanel')
201
215
 
@@ -216,6 +230,7 @@ class MainWindow(QMainWindow):
216
230
  self.create_pngs_from_segmentations_task_panel().save_inputs_and_parameters()
217
231
  self.calculate_scores_task_panel().save_inputs_and_parameters()
218
232
  self.dicom2nifti_task_panel().save_inputs_and_parameters()
233
+ self.create_dicom_summary_task_panel().save_inputs_and_parameters()
219
234
  self.select_slice_from_scans_task_panel().save_inputs_and_parameters()
220
235
  self.default_pipeline_panel().save_inputs_and_parameters()
221
236
  self.slice_visualization().save_inputs_and_parameters()
@@ -0,0 +1,183 @@
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 CreateDicomSummaryTask
25
+
26
+ LOG = LogManager()
27
+
28
+ PANEL_TITLE = 'CreateDicomSummaryTaskPanel'
29
+ PANEL_NAME = 'createdicomsummarytaskpanel'
30
+
31
+
32
+ class CreateDicomSummaryTaskPanel(TaskPanel):
33
+ def __init__(self):
34
+ super(CreateDicomSummaryTaskPanel, self).__init__()
35
+ self.set_title(PANEL_TITLE)
36
+ self._images_dir_line_edit = None
37
+ self._images_dir_select_button = None
38
+ self._output_dir_line_edit = None
39
+ self._output_dir_select_button = None
40
+ self._overwrite_checkbox = None
41
+ self._form_layout = None
42
+ self._run_task_button = None
43
+ self._settings = None
44
+ self._task = None
45
+ self._worker = None
46
+ self._thread = None
47
+ self.init_layout()
48
+
49
+ def images_dir_line_edit(self):
50
+ if not self._images_dir_line_edit:
51
+ self._images_dir_line_edit = QLineEdit(self.settings().get(f'{PANEL_NAME}/images_dir'))
52
+ return self._images_dir_line_edit
53
+
54
+ def images_dir_select_button(self):
55
+ if not self._images_dir_select_button:
56
+ self._images_dir_select_button = QPushButton('Select')
57
+ self._images_dir_select_button.clicked.connect(self.handle_images_dir_select_button)
58
+ return self._images_dir_select_button
59
+
60
+ def output_dir_line_edit(self):
61
+ if not self._output_dir_line_edit:
62
+ self._output_dir_line_edit = QLineEdit(self.settings().get(f'{PANEL_NAME}/output_dir'))
63
+ return self._output_dir_line_edit
64
+
65
+ def output_dir_select_button(self):
66
+ if not self._output_dir_select_button:
67
+ self._output_dir_select_button = QPushButton('Select')
68
+ self._output_dir_select_button.clicked.connect(self.handle_output_dir_select_button)
69
+ return self._output_dir_select_button
70
+
71
+ def overwrite_checkbox(self):
72
+ if not self._overwrite_checkbox:
73
+ self._overwrite_checkbox = QCheckBox('')
74
+ self._overwrite_checkbox.setChecked(self.settings().get_bool(f'{PANEL_NAME}/overwrite', True))
75
+ return self._overwrite_checkbox
76
+
77
+ def form_layout(self):
78
+ if not self._form_layout:
79
+ self._form_layout = QFormLayout()
80
+ if is_macos():
81
+ self._form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
82
+ return self._form_layout
83
+
84
+ def run_task_button(self):
85
+ if not self._run_task_button:
86
+ self._run_task_button = QPushButton('Run task')
87
+ self._run_task_button.clicked.connect(self.handle_run_task_button)
88
+ return self._run_task_button
89
+
90
+ def settings(self):
91
+ if not self._settings:
92
+ self._settings = Settings()
93
+ return self._settings
94
+
95
+ def init_layout(self):
96
+ images_dir_layout = QHBoxLayout()
97
+ images_dir_layout.addWidget(self.images_dir_line_edit())
98
+ images_dir_layout.addWidget(self.images_dir_select_button())
99
+ output_dir_layout = QHBoxLayout()
100
+ output_dir_layout.addWidget(self.output_dir_line_edit())
101
+ output_dir_layout.addWidget(self.output_dir_select_button())
102
+ self.form_layout().addRow('Images directory', images_dir_layout)
103
+ self.form_layout().addRow('Output directory', output_dir_layout)
104
+ self.form_layout().addRow('Overwrite', self.overwrite_checkbox())
105
+ layout = QVBoxLayout()
106
+ layout.addLayout(self.form_layout())
107
+ layout.addWidget(self.run_task_button())
108
+ self.setLayout(layout)
109
+ self.setObjectName(PANEL_NAME)
110
+
111
+ def handle_images_dir_select_button(self):
112
+ last_directory = self.settings().get('last_directory')
113
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
114
+ if directory:
115
+ self.images_dir_line_edit().setText(directory)
116
+ self.settings().set('last_directory', directory)
117
+
118
+ def handle_output_dir_select_button(self):
119
+ last_directory = self.settings().get('last_directory')
120
+ directory = QFileDialog.getExistingDirectory(dir=last_directory)
121
+ if directory:
122
+ self.output_dir_line_edit().setText(directory)
123
+ self.settings().set('last_directory', directory)
124
+
125
+ def handle_run_task_button(self):
126
+ errors = self.check_inputs_and_parameters()
127
+ if len(errors) > 0:
128
+ error_message = 'Following errors were encountered:\n'
129
+ for error in errors:
130
+ error_message += f' - {error}\n'
131
+ QMessageBox.information(self, 'Error', error_message)
132
+ else:
133
+ LOG.info('Running task...')
134
+ self.run_task_button().setEnabled(False)
135
+ self.save_inputs_and_parameters()
136
+ self._task = CreateDicomSummaryTask(
137
+ inputs={'directory': self.images_dir_line_edit().text()},
138
+ params=None,
139
+ output=self.output_dir_line_edit().text(),
140
+ overwrite=self.overwrite_checkbox().isChecked(),
141
+ )
142
+ self._worker = Worker(self._task)
143
+ self._thread = QThread()
144
+ self._worker.moveToThread(self._thread)
145
+ self._thread.started.connect(self._worker.run)
146
+ self._worker.progress.connect(self.handle_progress)
147
+ self._worker.status.connect(self.handle_status)
148
+ self._worker.finished.connect(self.handle_finished)
149
+ self._worker.finished.connect(self._thread.quit)
150
+ self._worker.finished.connect(self._worker.deleteLater)
151
+ self._thread.finished.connect(self._thread.deleteLater)
152
+ self._thread.start()
153
+
154
+ @Slot(int)
155
+ def handle_progress(self, progress):
156
+ LOG.info(f'Progress: {progress} / 100%')
157
+
158
+ @Slot(str)
159
+ def handle_status(self, status):
160
+ LOG.info(f'Status: {status}')
161
+
162
+ @Slot()
163
+ def handle_finished(self):
164
+ self.run_task_button().setEnabled(True)
165
+
166
+ # HELPERS
167
+
168
+ def check_inputs_and_parameters(self):
169
+ errors = []
170
+ if self.images_dir_line_edit().text() == '':
171
+ errors.append('Empty images directory path')
172
+ if not os.path.isdir(self.images_dir_line_edit().text()):
173
+ errors.append('Images directory does not exist')
174
+ if self.output_dir_line_edit().text() == '':
175
+ errors.append('Empty output directory path')
176
+ if os.path.isdir(self.output_dir_line_edit().text()) and not self.overwrite_checkbox().isChecked():
177
+ errors.append('Output directory exists but overwrite=False. Please remove output directory first')
178
+ return errors
179
+
180
+ def save_inputs_and_parameters(self):
181
+ self.settings().set(f'{PANEL_NAME}/images_dir', self.images_dir_line_edit().text())
182
+ self.settings().set(f'{PANEL_NAME}/output_dir', self.output_dir_line_edit().text())
183
+ self.settings().set(f'{PANEL_NAME}/overwrite', self.overwrite_checkbox().isChecked())
@@ -1 +0,0 @@
1
- from mosamatic2.core.pipelines.defaultpipeline import DefaultPipeline
@@ -1 +0,0 @@
1
- 2.0.6
File without changes
File without changes