mosamatic2 2.0.5__py3-none-any.whl → 2.0.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mosamatic2 might be problematic. Click here for more details.
- mosamatic2/ui/mainwindow.py +19 -0
- mosamatic2/ui/resources/VERSION +1 -1
- mosamatic2/ui/widgets/panels/pipelines/defaultpipelinepanel.py +2 -2
- mosamatic2/ui/widgets/panels/pipelines/pipelinepanel.py +6 -0
- mosamatic2/ui/widgets/panels/tasks/calculatescorestaskpanel.py +1 -1
- mosamatic2/ui/widgets/panels/tasks/createpngsfromsegmentationstaskpanel.py +1 -1
- mosamatic2/ui/widgets/panels/tasks/dicom2niftitaskpanel.py +1 -1
- mosamatic2/ui/widgets/panels/tasks/rescaledicomimagestaskpanel.py +1 -1
- mosamatic2/ui/widgets/panels/tasks/segmentmusclefatl3tensorflowtaskpanel.py +1 -1
- mosamatic2/ui/widgets/panels/tasks/selectslicefromscanstaskpanel.py +1 -1
- mosamatic2/ui/widgets/panels/visualizations/__init__.py +0 -0
- mosamatic2/ui/widgets/panels/visualizations/slicevisualization/__init__.py +0 -0
- mosamatic2/ui/widgets/panels/visualizations/slicevisualization/custominteractorstyle.py +62 -0
- mosamatic2/ui/widgets/panels/visualizations/slicevisualization/sliceviewer.py +98 -0
- mosamatic2/ui/widgets/panels/visualizations/slicevisualization/slicevisualization.py +106 -0
- mosamatic2/ui/widgets/panels/visualizations/visualization.py +6 -0
- {mosamatic2-2.0.5.dist-info → mosamatic2-2.0.6.dist-info}/METADATA +3 -1
- {mosamatic2-2.0.5.dist-info → mosamatic2-2.0.6.dist-info}/RECORD +21 -14
- /mosamatic2/ui/widgets/panels/{taskpanel.py → tasks/taskpanel.py} +0 -0
- {mosamatic2-2.0.5.dist-info → mosamatic2-2.0.6.dist-info}/WHEEL +0 -0
- {mosamatic2-2.0.5.dist-info → mosamatic2-2.0.6.dist-info}/entry_points.txt +0 -0
mosamatic2/ui/mainwindow.py
CHANGED
|
@@ -21,6 +21,7 @@ from mosamatic2.ui.widgets.panels.tasks.calculatescorestaskpanel import Calculat
|
|
|
21
21
|
from mosamatic2.ui.widgets.panels.tasks.dicom2niftitaskpanel import Dicom2NiftiTaskPanel
|
|
22
22
|
from mosamatic2.ui.widgets.panels.tasks.selectslicefromscanstaskpanel import SelectSliceFromScansTaskPanel
|
|
23
23
|
from mosamatic2.ui.widgets.panels.pipelines.defaultpipelinepanel import DefaultPipelinePanel
|
|
24
|
+
from mosamatic2.ui.widgets.panels.visualizations.slicevisualization.slicevisualization import SliceVisualization
|
|
24
25
|
|
|
25
26
|
LOG = LogManager()
|
|
26
27
|
|
|
@@ -39,6 +40,7 @@ class MainWindow(QMainWindow):
|
|
|
39
40
|
self._dicom2nifti_task_panel = None
|
|
40
41
|
self._select_slice_from_scans_task_panel = None
|
|
41
42
|
self._default_pipeline_panel = None
|
|
43
|
+
self._slice_visualization = None
|
|
42
44
|
self.init_window()
|
|
43
45
|
|
|
44
46
|
def init_window(self):
|
|
@@ -57,6 +59,7 @@ class MainWindow(QMainWindow):
|
|
|
57
59
|
self.init_app_menu()
|
|
58
60
|
self.init_tasks_menu()
|
|
59
61
|
self.init_pipelines_menu()
|
|
62
|
+
self.init_visualizations_menu()
|
|
60
63
|
if is_macos():
|
|
61
64
|
self.menuBar().setNativeMenuBar(False)
|
|
62
65
|
|
|
@@ -93,6 +96,12 @@ class MainWindow(QMainWindow):
|
|
|
93
96
|
pipelines_menu = self.menuBar().addMenu('Pipelines')
|
|
94
97
|
pipelines_menu.addAction(default_pipeline_action)
|
|
95
98
|
|
|
99
|
+
def init_visualizations_menu(self):
|
|
100
|
+
slice_visualization_action = QAction('SliceVisualization', self)
|
|
101
|
+
slice_visualization_action.triggered.connect(self.handle_slice_visualization_action)
|
|
102
|
+
visualizations_menu = self.menuBar().addMenu('Visualizations')
|
|
103
|
+
visualizations_menu.addAction(slice_visualization_action)
|
|
104
|
+
|
|
96
105
|
def init_status_bar(self):
|
|
97
106
|
self.set_status('Ready')
|
|
98
107
|
|
|
@@ -113,6 +122,7 @@ class MainWindow(QMainWindow):
|
|
|
113
122
|
self._main_panel.add_panel(self.dicom2nifti_task_panel(), 'dicom2niftitaskpanel')
|
|
114
123
|
self._main_panel.add_panel(self.select_slice_from_scans_task_panel(), 'selectslicefromscanstaskpanel')
|
|
115
124
|
self._main_panel.add_panel(self.default_pipeline_panel(), 'defaultpipelinepanel')
|
|
125
|
+
self._main_panel.add_panel(self.slice_visualization(), 'slicevisualization')
|
|
116
126
|
self._main_panel.select_panel('defaultpipelinepanel')
|
|
117
127
|
return self._main_panel
|
|
118
128
|
|
|
@@ -158,6 +168,11 @@ class MainWindow(QMainWindow):
|
|
|
158
168
|
if not self._default_pipeline_panel:
|
|
159
169
|
self._default_pipeline_panel = DefaultPipelinePanel()
|
|
160
170
|
return self._default_pipeline_panel
|
|
171
|
+
|
|
172
|
+
def slice_visualization(self):
|
|
173
|
+
if not self._slice_visualization:
|
|
174
|
+
self._slice_visualization = SliceVisualization()
|
|
175
|
+
return self._slice_visualization
|
|
161
176
|
|
|
162
177
|
# SETTERS
|
|
163
178
|
|
|
@@ -187,6 +202,9 @@ class MainWindow(QMainWindow):
|
|
|
187
202
|
def handle_default_pipeline_action(self):
|
|
188
203
|
self.main_panel().select_panel('defaultpipelinepanel')
|
|
189
204
|
|
|
205
|
+
def handle_slice_visualization_action(self):
|
|
206
|
+
self.main_panel().select_panel('slicevisualization')
|
|
207
|
+
|
|
190
208
|
def showEvent(self, event):
|
|
191
209
|
return super().showEvent(event)
|
|
192
210
|
|
|
@@ -200,6 +218,7 @@ class MainWindow(QMainWindow):
|
|
|
200
218
|
self.dicom2nifti_task_panel().save_inputs_and_parameters()
|
|
201
219
|
self.select_slice_from_scans_task_panel().save_inputs_and_parameters()
|
|
202
220
|
self.default_pipeline_panel().save_inputs_and_parameters()
|
|
221
|
+
self.slice_visualization().save_inputs_and_parameters()
|
|
203
222
|
return super().closeEvent(event)
|
|
204
223
|
|
|
205
224
|
def load_geometry_and_state(self):
|
mosamatic2/ui/resources/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.0.
|
|
1
|
+
2.0.6
|
|
@@ -18,7 +18,7 @@ from PySide6.QtCore import (
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
from mosamatic2.core.managers.logmanager import LogManager
|
|
21
|
-
from mosamatic2.ui.widgets.panels.
|
|
21
|
+
from mosamatic2.ui.widgets.panels.pipelines.pipelinepanel import PipelinePanel
|
|
22
22
|
from mosamatic2.ui.settings import Settings
|
|
23
23
|
from mosamatic2.ui.utils import is_macos
|
|
24
24
|
from mosamatic2.ui.worker import Worker
|
|
@@ -32,7 +32,7 @@ MODEL_TYPE_ITEM_NAMES = ['tensorflow', 'pytorch']
|
|
|
32
32
|
MODEL_VERSION_ITEM_NAMES = ['1.0', '2.2']
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
class DefaultPipelinePanel(
|
|
35
|
+
class DefaultPipelinePanel(PipelinePanel):
|
|
36
36
|
def __init__(self):
|
|
37
37
|
super(DefaultPipelinePanel, self).__init__()
|
|
38
38
|
self.set_title(PANEL_TITLE)
|
|
@@ -17,7 +17,7 @@ from PySide6.QtCore import (
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
from mosamatic2.core.managers.logmanager import LogManager
|
|
20
|
-
from mosamatic2.ui.widgets.panels.taskpanel import TaskPanel
|
|
20
|
+
from mosamatic2.ui.widgets.panels.tasks.taskpanel import TaskPanel
|
|
21
21
|
from mosamatic2.ui.settings import Settings
|
|
22
22
|
from mosamatic2.ui.utils import is_macos
|
|
23
23
|
from mosamatic2.ui.worker import Worker
|
|
@@ -17,7 +17,7 @@ from PySide6.QtCore import (
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
from mosamatic2.core.managers.logmanager import LogManager
|
|
20
|
-
from mosamatic2.ui.widgets.panels.taskpanel import TaskPanel
|
|
20
|
+
from mosamatic2.ui.widgets.panels.tasks.taskpanel import TaskPanel
|
|
21
21
|
from mosamatic2.ui.settings import Settings
|
|
22
22
|
from mosamatic2.ui.utils import is_macos
|
|
23
23
|
from mosamatic2.ui.worker import Worker
|
|
@@ -17,7 +17,7 @@ from PySide6.QtCore import (
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
from mosamatic2.core.managers.logmanager import LogManager
|
|
20
|
-
from mosamatic2.ui.widgets.panels.taskpanel import TaskPanel
|
|
20
|
+
from mosamatic2.ui.widgets.panels.tasks.taskpanel import TaskPanel
|
|
21
21
|
from mosamatic2.ui.settings import Settings
|
|
22
22
|
from mosamatic2.ui.utils import is_macos
|
|
23
23
|
from mosamatic2.ui.worker import Worker
|
|
@@ -17,7 +17,7 @@ from PySide6.QtCore import (
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
from mosamatic2.core.managers.logmanager import LogManager
|
|
20
|
-
from mosamatic2.ui.widgets.panels.taskpanel import TaskPanel
|
|
20
|
+
from mosamatic2.ui.widgets.panels.tasks.taskpanel import TaskPanel
|
|
21
21
|
from mosamatic2.ui.settings import Settings
|
|
22
22
|
from mosamatic2.ui.utils import is_macos
|
|
23
23
|
from mosamatic2.ui.worker import Worker
|
|
@@ -16,7 +16,7 @@ from PySide6.QtCore import (
|
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
from mosamatic2.core.managers.logmanager import LogManager
|
|
19
|
-
from mosamatic2.ui.widgets.panels.taskpanel import TaskPanel
|
|
19
|
+
from mosamatic2.ui.widgets.panels.tasks.taskpanel import TaskPanel
|
|
20
20
|
from mosamatic2.ui.settings import Settings
|
|
21
21
|
from mosamatic2.ui.utils import is_macos
|
|
22
22
|
from mosamatic2.ui.worker import Worker
|
|
@@ -17,7 +17,7 @@ from PySide6.QtCore import (
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
from mosamatic2.core.managers.logmanager import LogManager
|
|
20
|
-
from mosamatic2.ui.widgets.panels.taskpanel import TaskPanel
|
|
20
|
+
from mosamatic2.ui.widgets.panels.tasks.taskpanel import TaskPanel
|
|
21
21
|
from mosamatic2.ui.settings import Settings
|
|
22
22
|
from mosamatic2.ui.utils import is_macos
|
|
23
23
|
from mosamatic2.ui.worker import Worker
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import vtk
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CustomInteractorStyle(vtk.vtkInteractorStyleImage):
|
|
5
|
+
def __init__(self, image_data, slice_mapper, status_actor, slice_obj, orientation="axial"):
|
|
6
|
+
super(CustomInteractorStyle, self).__init__()
|
|
7
|
+
self.AddObserver("MouseWheelForwardEvent", self.move_slice_forward)
|
|
8
|
+
self.AddObserver("MouseWheelBackwardEvent", self.move_slice_backward)
|
|
9
|
+
self.AddObserver("MouseMoveEvent", self.update_overlay, 1.0)
|
|
10
|
+
self.AddObserver("KeyPressEvent", self.key_press_event)
|
|
11
|
+
|
|
12
|
+
self.image_data = image_data
|
|
13
|
+
self.slice_mapper = slice_mapper
|
|
14
|
+
self.status_actor = status_actor
|
|
15
|
+
self.slice_obj = slice_obj
|
|
16
|
+
self.orientation = orientation
|
|
17
|
+
|
|
18
|
+
xmin, xmax, ymin, ymax, zmin, zmax = image_data.GetExtent()
|
|
19
|
+
if orientation == "axial":
|
|
20
|
+
self.min_slice, self.max_slice = zmin, zmax
|
|
21
|
+
elif orientation == "sagittal":
|
|
22
|
+
self.min_slice, self.max_slice = xmin, xmax
|
|
23
|
+
elif orientation == "coronal":
|
|
24
|
+
self.min_slice, self.max_slice = ymin, ymax
|
|
25
|
+
else:
|
|
26
|
+
raise ValueError(f"Unknown orientation: {orientation}")
|
|
27
|
+
|
|
28
|
+
self.slice = (self.min_slice + self.max_slice) // 2
|
|
29
|
+
self.slice_mapper.SetSliceNumber(self.slice)
|
|
30
|
+
self.update_status_message()
|
|
31
|
+
|
|
32
|
+
def update_status_message(self):
|
|
33
|
+
window = int(self.slice_obj.GetProperty().GetColorWindow())
|
|
34
|
+
level = int(self.slice_obj.GetProperty().GetColorLevel())
|
|
35
|
+
message = f'Slice {self.slice + 1}/{self.max_slice + 1} | W: {window} L: {level}'
|
|
36
|
+
self.status_actor.GetMapper().SetInput(message)
|
|
37
|
+
|
|
38
|
+
def move_slice_forward(self, obj, event):
|
|
39
|
+
if self.slice < self.max_slice:
|
|
40
|
+
self.slice += 1
|
|
41
|
+
self.slice_mapper.SetSliceNumber(self.slice)
|
|
42
|
+
self.update_status_message()
|
|
43
|
+
self.GetInteractor().GetRenderWindow().Render()
|
|
44
|
+
|
|
45
|
+
def move_slice_backward(self, obj, event):
|
|
46
|
+
if self.slice > self.min_slice:
|
|
47
|
+
self.slice -= 1
|
|
48
|
+
self.slice_mapper.SetSliceNumber(self.slice)
|
|
49
|
+
self.update_status_message()
|
|
50
|
+
self.GetInteractor().GetRenderWindow().Render()
|
|
51
|
+
|
|
52
|
+
def key_press_event(self, obj, event):
|
|
53
|
+
key = self.GetInteractor().GetKeySym()
|
|
54
|
+
if key == "Up":
|
|
55
|
+
self.move_slice_forward(obj, event)
|
|
56
|
+
elif key == "Down":
|
|
57
|
+
self.move_slice_backward(obj, event)
|
|
58
|
+
|
|
59
|
+
def update_overlay(self, obj, event):
|
|
60
|
+
super(CustomInteractorStyle, self).OnMouseMove()
|
|
61
|
+
self.update_status_message()
|
|
62
|
+
self.GetInteractor().GetRenderWindow().Render()
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import vtk
|
|
3
|
+
import pydicom
|
|
4
|
+
from PySide6.QtWidgets import QWidget, QVBoxLayout, QMessageBox
|
|
5
|
+
from mosamatic2.ui.widgets.panels.visualizations.slicevisualization.custominteractorstyle import CustomInteractorStyle
|
|
6
|
+
from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
|
|
7
|
+
|
|
8
|
+
COLOR_WINDOW = 400
|
|
9
|
+
COLOR_LEVEL = 40
|
|
10
|
+
IMAGE_SHIFT_SCALE = -1000
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SliceViewer(QWidget):
|
|
14
|
+
def __init__(self):
|
|
15
|
+
super(SliceViewer, self).__init__()
|
|
16
|
+
self._nifti_file_or_dicom_dir = None
|
|
17
|
+
self._view_orientation = 'axial'
|
|
18
|
+
self._vtk_widget = QVTKRenderWindowInteractor(self)
|
|
19
|
+
self._render_window = self._vtk_widget.GetRenderWindow()
|
|
20
|
+
self._interactor = self._render_window.GetInteractor()
|
|
21
|
+
self._interactor_style = None
|
|
22
|
+
layout = QVBoxLayout()
|
|
23
|
+
layout.addWidget(self._vtk_widget)
|
|
24
|
+
self.setLayout(layout)
|
|
25
|
+
self._default_renderer = vtk.vtkRenderer()
|
|
26
|
+
self._default_renderer.SetBackground(0.0, 0.0, 0.0) # black
|
|
27
|
+
self._render_window.AddRenderer(self._default_renderer)
|
|
28
|
+
self._render_window.Render()
|
|
29
|
+
|
|
30
|
+
def nifti_file_or_dicom_dir(self):
|
|
31
|
+
return self._nifti_file_or_dicom_dir
|
|
32
|
+
|
|
33
|
+
def set_nifti_file_or_dicom_dir(self, nifti_file_or_dicom_dir):
|
|
34
|
+
self._nifti_file_or_dicom_dir = nifti_file_or_dicom_dir
|
|
35
|
+
|
|
36
|
+
def create_text_actor(self, text, x, y, font_size, align_bottom=False, normalized=False):
|
|
37
|
+
text_prop = vtk.vtkTextProperty()
|
|
38
|
+
text_prop.SetFontFamilyToCourier()
|
|
39
|
+
text_prop.SetFontSize(font_size)
|
|
40
|
+
text_prop.SetVerticalJustificationToBottom() if align_bottom else text_prop.SetVerticalJustificationToTop()
|
|
41
|
+
text_prop.SetJustificationToLeft()
|
|
42
|
+
text_mapper = vtk.vtkTextMapper()
|
|
43
|
+
text_mapper.SetInput(text)
|
|
44
|
+
text_mapper.SetTextProperty(text_prop)
|
|
45
|
+
text_actor = vtk.vtkActor2D()
|
|
46
|
+
text_actor.SetMapper(text_mapper)
|
|
47
|
+
if normalized:
|
|
48
|
+
text_actor.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay()
|
|
49
|
+
text_actor.SetPosition(x, y)
|
|
50
|
+
return text_actor
|
|
51
|
+
|
|
52
|
+
def is_nifti_file(self, file_path):
|
|
53
|
+
return file_path.endswith('.nii') or file_path.endswith('.nii.gz')
|
|
54
|
+
|
|
55
|
+
def is_dicom_dir(self, dir_path):
|
|
56
|
+
first_dicom_file = os.path.join(dir_path, os.listdir(dir_path)[0])
|
|
57
|
+
return pydicom.dcmread(first_dicom_file, stop_before_pixels=True)
|
|
58
|
+
|
|
59
|
+
def load_image(self):
|
|
60
|
+
if not self.nifti_file_or_dicom_dir():
|
|
61
|
+
QMessageBox.warning(self, 'Warning', 'No NIFTI file or DICOM directory set')
|
|
62
|
+
return
|
|
63
|
+
if self.is_nifti_file(self.nifti_file_or_dicom_dir()):
|
|
64
|
+
reader = vtk.vtkNIFTIImageReader()
|
|
65
|
+
reader.SetFileName(self.nifti_file_or_dicom_dir())
|
|
66
|
+
elif self.is_dicom_dir(self.nifti_file_or_dicom_dir()):
|
|
67
|
+
reader = vtk.vtkDICOMImageReader()
|
|
68
|
+
reader.SetDirectoryName(self.nifti_file_or_dicom_dir())
|
|
69
|
+
reader.Update()
|
|
70
|
+
image_data = reader.GetOutput()
|
|
71
|
+
xmin, xmax, ymin, ymax, zmin, zmax = image_data.GetExtent()
|
|
72
|
+
axial_index = (zmin + zmax) // 2
|
|
73
|
+
slice_mapper = vtk.vtkImageSliceMapper()
|
|
74
|
+
slice_mapper.SetInputData(image_data)
|
|
75
|
+
slice_mapper.SetOrientationToZ() # axial orientation
|
|
76
|
+
slice_mapper.SetSliceNumber(axial_index)
|
|
77
|
+
slice = vtk.vtkImageSlice()
|
|
78
|
+
slice.GetProperty().SetColorWindow(400)
|
|
79
|
+
slice.GetProperty().SetColorLevel(40)
|
|
80
|
+
slice.SetMapper(slice_mapper)
|
|
81
|
+
slice_text_actor = self.create_text_actor("", 0.01, 0.01, 12, align_bottom=True, normalized=True)
|
|
82
|
+
usage_text_actor = self.create_text_actor(
|
|
83
|
+
"- Slice with mouse wheel or Up/Down-Key (first click inside viewer)\n"
|
|
84
|
+
"- Zoom with pressed right mouse button while dragging\n"
|
|
85
|
+
"- Pan with middle mouse button while dragging\n"
|
|
86
|
+
"- Change contrast/brightness with pressed left mouse while dragging",
|
|
87
|
+
0.01, 0.99, 12, normalized=True)
|
|
88
|
+
ren = vtk.vtkRenderer()
|
|
89
|
+
ren.AddActor2D(slice_text_actor)
|
|
90
|
+
ren.AddActor2D(usage_text_actor)
|
|
91
|
+
ren.AddViewProp(slice)
|
|
92
|
+
ren.ResetCamera()
|
|
93
|
+
self._render_window.RemoveRenderer(self._default_renderer)
|
|
94
|
+
self._render_window.AddRenderer(ren)
|
|
95
|
+
self._interactor_style = CustomInteractorStyle(image_data, slice_mapper, slice_text_actor, slice)
|
|
96
|
+
self._interactor.SetInteractorStyle(self._interactor_style)
|
|
97
|
+
self._interactor.Initialize()
|
|
98
|
+
self._render_window.Render()
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from PySide6.QtWidgets import (
|
|
2
|
+
QLineEdit,
|
|
3
|
+
QHBoxLayout,
|
|
4
|
+
QVBoxLayout,
|
|
5
|
+
QFormLayout,
|
|
6
|
+
QPushButton,
|
|
7
|
+
QFileDialog,
|
|
8
|
+
)
|
|
9
|
+
from mosamatic2.ui.widgets.panels.visualizations.visualization import Visualization
|
|
10
|
+
from mosamatic2.ui.widgets.panels.visualizations.slicevisualization.sliceviewer import SliceViewer
|
|
11
|
+
from mosamatic2.core.managers.logmanager import LogManager
|
|
12
|
+
from mosamatic2.ui.settings import Settings
|
|
13
|
+
from mosamatic2.ui.utils import is_macos
|
|
14
|
+
|
|
15
|
+
LOG = LogManager()
|
|
16
|
+
PANEL_TITLE = 'SliceVisualization'
|
|
17
|
+
PANEL_NAME = 'slicevisualization'
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SliceVisualization(Visualization):
|
|
21
|
+
def __init__(self):
|
|
22
|
+
super(SliceVisualization, self).__init__()
|
|
23
|
+
self.set_title(PANEL_TITLE)
|
|
24
|
+
self._image_line_edit = None
|
|
25
|
+
self._image_select_button = None
|
|
26
|
+
self._image_dir_select_button = None
|
|
27
|
+
self._load_image_button = None
|
|
28
|
+
self._slice_viewer = None
|
|
29
|
+
self._form_layout = None
|
|
30
|
+
self._settings = None
|
|
31
|
+
self.init_layout()
|
|
32
|
+
|
|
33
|
+
def image_line_edit(self):
|
|
34
|
+
if not self._image_line_edit:
|
|
35
|
+
self._image_line_edit = QLineEdit(self.settings().get(f'{PANEL_NAME}/image'))
|
|
36
|
+
return self._image_line_edit
|
|
37
|
+
|
|
38
|
+
def image_select_button(self):
|
|
39
|
+
if not self._image_select_button:
|
|
40
|
+
self._image_select_button = QPushButton('Select Image')
|
|
41
|
+
self._image_select_button.clicked.connect(self.handle_image_select_button)
|
|
42
|
+
return self._image_select_button
|
|
43
|
+
|
|
44
|
+
def image_dir_select_button(self):
|
|
45
|
+
if not self._image_dir_select_button:
|
|
46
|
+
self._image_dir_select_button = QPushButton('Select Directory')
|
|
47
|
+
self._image_dir_select_button.clicked.connect(self.handle_image_dir_select_button)
|
|
48
|
+
return self._image_dir_select_button
|
|
49
|
+
|
|
50
|
+
def load_image_button(self):
|
|
51
|
+
if not self._load_image_button:
|
|
52
|
+
self._load_image_button = QPushButton('Load')
|
|
53
|
+
self._load_image_button.clicked.connect(self.handle_load_image_button)
|
|
54
|
+
return self._load_image_button
|
|
55
|
+
|
|
56
|
+
def slice_viewer(self):
|
|
57
|
+
if not self._slice_viewer:
|
|
58
|
+
self._slice_viewer = SliceViewer()
|
|
59
|
+
return self._slice_viewer
|
|
60
|
+
|
|
61
|
+
def form_layout(self):
|
|
62
|
+
if not self._form_layout:
|
|
63
|
+
self._form_layout = QFormLayout()
|
|
64
|
+
if is_macos():
|
|
65
|
+
self._form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
|
|
66
|
+
return self._form_layout
|
|
67
|
+
|
|
68
|
+
def settings(self):
|
|
69
|
+
if not self._settings:
|
|
70
|
+
self._settings = Settings()
|
|
71
|
+
return self._settings
|
|
72
|
+
|
|
73
|
+
def init_layout(self):
|
|
74
|
+
image_layout = QHBoxLayout()
|
|
75
|
+
image_layout.addWidget(self.image_line_edit())
|
|
76
|
+
image_layout.addWidget(self.image_select_button())
|
|
77
|
+
image_layout.addWidget(self.image_dir_select_button())
|
|
78
|
+
self.form_layout().addRow('NIFTI file or DICOM directory', image_layout)
|
|
79
|
+
layout = QVBoxLayout()
|
|
80
|
+
layout.addLayout(self.form_layout())
|
|
81
|
+
layout.addWidget(self.load_image_button())
|
|
82
|
+
layout.addWidget(self.slice_viewer())
|
|
83
|
+
self.setLayout(layout)
|
|
84
|
+
self.setObjectName(PANEL_NAME)
|
|
85
|
+
|
|
86
|
+
def handle_image_select_button(self):
|
|
87
|
+
last_directory = self.settings().get('last_directory')
|
|
88
|
+
file_path, _ = QFileDialog.getOpenFileName(dir=last_directory)
|
|
89
|
+
if file_path:
|
|
90
|
+
self.image_line_edit().setText(file_path)
|
|
91
|
+
self.settings().set('last_directory', file_path)
|
|
92
|
+
|
|
93
|
+
def handle_image_dir_select_button(self):
|
|
94
|
+
last_directory = self.settings().get('last_directory')
|
|
95
|
+
dir_path = QFileDialog.getExistingDirectory(dir=last_directory)
|
|
96
|
+
if dir_path:
|
|
97
|
+
self.image_line_edit().setText(dir_path)
|
|
98
|
+
self.settings().set('last_directory', dir_path)
|
|
99
|
+
|
|
100
|
+
def handle_load_image_button(self):
|
|
101
|
+
self.slice_viewer().set_nifti_file_or_dicom_dir(self.image_line_edit().text())
|
|
102
|
+
# self.slice_viewer().set_view_orientation('axial')
|
|
103
|
+
self.slice_viewer().load_image()
|
|
104
|
+
|
|
105
|
+
def save_inputs_and_parameters(self):
|
|
106
|
+
self.settings().set(f'{PANEL_NAME}/image', self.image_line_edit().text())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: mosamatic2
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.6
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Ralph Brecheisen
|
|
6
6
|
Author-email: r.brecheisen@maastrichtuniversity.nl
|
|
@@ -17,6 +17,7 @@ Requires-Dist: pandas (>=2.3.2)
|
|
|
17
17
|
Requires-Dist: pendulum (>=3.1.0)
|
|
18
18
|
Requires-Dist: pillow (>=11.3.0)
|
|
19
19
|
Requires-Dist: pydicom (>=3.0.1)
|
|
20
|
+
Requires-Dist: pyqtgraph (>=0.13.7)
|
|
20
21
|
Requires-Dist: pyside6-essentials (>=6.9)
|
|
21
22
|
Requires-Dist: python-gdcm (>=3.0.26)
|
|
22
23
|
Requires-Dist: scipy (>=1.15.3)
|
|
@@ -30,6 +31,7 @@ Requires-Dist: tensorflow-macos (==2.15.0) ; platform_system == "Darwin" and pla
|
|
|
30
31
|
Requires-Dist: torch (>=2.8.0)
|
|
31
32
|
Requires-Dist: torchvision (>=0.23.0)
|
|
32
33
|
Requires-Dist: totalsegmentator (>=2.11.0)
|
|
34
|
+
Requires-Dist: vtk (>=9.5.1)
|
|
33
35
|
Description-Content-Type: text/markdown
|
|
34
36
|
|
|
35
37
|
|
|
@@ -44,12 +44,12 @@ mosamatic2/core/tasks/task.py,sha256=APPnid6dpSGkPuDqU1vm2RIMR5vkpvbP1CPHUMjympg
|
|
|
44
44
|
mosamatic2/core/utils.py,sha256=zh44FNOWxNKuZ4FcM7VIfMvdlzOr4AA8_PJ1r-6_83k,10855
|
|
45
45
|
mosamatic2/server.py,sha256=jiUc7-aFaDMSY2hg6BhMC9C2FU4V2OrMBSoiIAP8Zcs,4158
|
|
46
46
|
mosamatic2/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
|
-
mosamatic2/ui/mainwindow.py,sha256=
|
|
47
|
+
mosamatic2/ui/mainwindow.py,sha256=1QjT0ZMQd5ibuVp0v1Ar_KfzEcw0jEXqOA1dRN8so2M,12124
|
|
48
48
|
mosamatic2/ui/resources/icons/mosamatic2.icns,sha256=OfhC-diJTIgaNMOezxKKilGsY7mRkaGdU5dGr0MOjIA,2994125
|
|
49
49
|
mosamatic2/ui/resources/icons/mosamatic2.ico,sha256=ySD3RYluHK3pgS0Eas7eKrVk_AskdLQ4qs_IT-wNhq4,12229
|
|
50
50
|
mosamatic2/ui/resources/icons/spinner.gif,sha256=rvaac6GUZauHSPFSOLWr0RmLfjmtZih2Q8knQ2WP3Po,16240
|
|
51
51
|
mosamatic2/ui/resources/images/body-composition.jpg,sha256=KD-BudbXwThB4lJOZZN-ad5-TZRaaZ5cKTH0Ar1TOZs,21227
|
|
52
|
-
mosamatic2/ui/resources/VERSION,sha256=
|
|
52
|
+
mosamatic2/ui/resources/VERSION,sha256=UGNI9gs9ohX5rxcljrGTsg7aVltkj2MKDIYqc7-b4IE,8
|
|
53
53
|
mosamatic2/ui/settings.py,sha256=YEVHYJIfNsqMO3v1pjzgh7Pih9GGoUX7S9s8S-sBNUk,2121
|
|
54
54
|
mosamatic2/ui/utils.py,sha256=6bbPIrh4RJ_yhQKNZrgPbL4XeUEogjIjbk_e5c3QS5g,853
|
|
55
55
|
mosamatic2/ui/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -61,19 +61,26 @@ mosamatic2/ui/widgets/panels/defaultpanel.py,sha256=Ry32Xv6ibxm6NdZ7eBOCcisWNcmn
|
|
|
61
61
|
mosamatic2/ui/widgets/panels/logpanel.py,sha256=ogswJ6_ryb6u7JeVnOsh2Ez8KWg6jtCFZwij8s87xO4,1861
|
|
62
62
|
mosamatic2/ui/widgets/panels/mainpanel.py,sha256=KqI8dA7GpLFd2unqVRTBkNxdnh6AWGpVPwQuaEg8PmI,2431
|
|
63
63
|
mosamatic2/ui/widgets/panels/pipelines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
64
|
-
mosamatic2/ui/widgets/panels/pipelines/defaultpipelinepanel.py,sha256=
|
|
64
|
+
mosamatic2/ui/widgets/panels/pipelines/defaultpipelinepanel.py,sha256=qkfI4BnLIXqE_YvSQj4sO_FjnK0eVdIMqAZ8sktgI-8,13727
|
|
65
|
+
mosamatic2/ui/widgets/panels/pipelines/pipelinepanel.py,sha256=SlkKme8Wv2Bvp2Alen98mFjv3F5eZCwJylj294gd5uU,178
|
|
65
66
|
mosamatic2/ui/widgets/panels/stackedpanel.py,sha256=dK1YWuHUzxRhVb5gP0Lu9rAiW4XagjcHmGF__5Lpufk,657
|
|
66
|
-
mosamatic2/ui/widgets/panels/taskpanel.py,sha256=t8lIx1P8sS1Fa-aNm6eEha6297pJQNbBRizkobBexz8,170
|
|
67
67
|
mosamatic2/ui/widgets/panels/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
68
|
-
mosamatic2/ui/widgets/panels/tasks/calculatescorestaskpanel.py,sha256=
|
|
69
|
-
mosamatic2/ui/widgets/panels/tasks/createpngsfromsegmentationstaskpanel.py,sha256=
|
|
70
|
-
mosamatic2/ui/widgets/panels/tasks/dicom2niftitaskpanel.py,sha256=
|
|
71
|
-
mosamatic2/ui/widgets/panels/tasks/rescaledicomimagestaskpanel.py,sha256=
|
|
72
|
-
mosamatic2/ui/widgets/panels/tasks/segmentmusclefatl3tensorflowtaskpanel.py,sha256=
|
|
73
|
-
mosamatic2/ui/widgets/panels/tasks/selectslicefromscanstaskpanel.py,sha256=
|
|
68
|
+
mosamatic2/ui/widgets/panels/tasks/calculatescorestaskpanel.py,sha256=NmPLQizj4x9jgf9UA7VZSjARNHYJB_jrfB0kvaVncdw,9387
|
|
69
|
+
mosamatic2/ui/widgets/panels/tasks/createpngsfromsegmentationstaskpanel.py,sha256=JFnmYjPemRtXPXV2fk2cjB45fseN5BZ8gI_T1zVLGV8,7879
|
|
70
|
+
mosamatic2/ui/widgets/panels/tasks/dicom2niftitaskpanel.py,sha256=gIv5xo0z2EEfFzHI4Q6H87maf-nPIeC8yIxLL5iWuCw,7480
|
|
71
|
+
mosamatic2/ui/widgets/panels/tasks/rescaledicomimagestaskpanel.py,sha256=ds7JxynpMeNvqfHKtg1LQR23rb3_Y7xoDLbZ2wl-TMw,7597
|
|
72
|
+
mosamatic2/ui/widgets/panels/tasks/segmentmusclefatl3tensorflowtaskpanel.py,sha256=QCEZs9lqaE-XAJuyyrfZVnFkNRyjMw6Cfa-6qP9WaV8,9630
|
|
73
|
+
mosamatic2/ui/widgets/panels/tasks/selectslicefromscanstaskpanel.py,sha256=iZu_li_7Zr3n8nVp-FI1GFV_HuCf_I4NY9PNr9aX-oY,8077
|
|
74
|
+
mosamatic2/ui/widgets/panels/tasks/taskpanel.py,sha256=t8lIx1P8sS1Fa-aNm6eEha6297pJQNbBRizkobBexz8,170
|
|
75
|
+
mosamatic2/ui/widgets/panels/visualizations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
76
|
+
mosamatic2/ui/widgets/panels/visualizations/slicevisualization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
77
|
+
mosamatic2/ui/widgets/panels/visualizations/slicevisualization/custominteractorstyle.py,sha256=GaXmO5SvXwLAnrVtAGglTXgPx6mD0Q6f8gYrGN5WRO4,2644
|
|
78
|
+
mosamatic2/ui/widgets/panels/visualizations/slicevisualization/sliceviewer.py,sha256=DLvTQ-VboPqjViA9EzGTSm4eGmrgYPH0degpxprEWI4,4600
|
|
79
|
+
mosamatic2/ui/widgets/panels/visualizations/slicevisualization/slicevisualization.py,sha256=2cLTHsGrdMMt_dbnq0EUAFSSW7naR6B1neB7RnUOmjQ,4214
|
|
80
|
+
mosamatic2/ui/widgets/panels/visualizations/visualization.py,sha256=JvqTJi7cCGYK1-wrN2oURdCOBoPS2clVUyYglhkoVJg,178
|
|
74
81
|
mosamatic2/ui/widgets/splashscreen.py,sha256=MS-OczOWfwwEQNQd-JWe9_Mh57css0cSQgbu973rwQo,4056
|
|
75
82
|
mosamatic2/ui/worker.py,sha256=v7e3gq7MUudgpB1BJW-P7j5wurzu6-HG5m7I6WHgJp0,699
|
|
76
|
-
mosamatic2-2.0.
|
|
77
|
-
mosamatic2-2.0.
|
|
78
|
-
mosamatic2-2.0.
|
|
79
|
-
mosamatic2-2.0.
|
|
83
|
+
mosamatic2-2.0.6.dist-info/entry_points.txt,sha256=MCUpKkgbej1clgp8EqlLQGs0BIKwGPcBPiVWLfGz9Gw,126
|
|
84
|
+
mosamatic2-2.0.6.dist-info/METADATA,sha256=UTDzgaH6Wa-Op3cuwXokrC0rFV34RAo9pD8BlRh8QSY,1467
|
|
85
|
+
mosamatic2-2.0.6.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
86
|
+
mosamatic2-2.0.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|