mosamatic2 2.0.6__tar.gz → 2.0.8__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.
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/PKG-INFO +1 -1
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/pyproject.toml +1 -1
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/cli.py +2 -0
- mosamatic2-2.0.8/src/mosamatic2/commands/createdicomsummary.py +61 -0
- mosamatic2-2.0.8/src/mosamatic2/core/pipelines/__init__.py +1 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/tasks/__init__.py +2 -1
- mosamatic2-2.0.8/src/mosamatic2/core/tasks/createdicomsummarytask/createdicomsummarytask.py +60 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/server.py +16 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/mainwindow.py +15 -0
- mosamatic2-2.0.8/src/mosamatic2/ui/resources/VERSION +1 -0
- mosamatic2-2.0.8/src/mosamatic2/ui/widgets/panels/tasks/createdicomsummarytaskpanel.py +183 -0
- mosamatic2-2.0.8/src/mosamatic2/ui/widgets/panels/visualizations/__init__.py +0 -0
- mosamatic2-2.0.8/src/mosamatic2/ui/widgets/panels/visualizations/slicevisualization/__init__.py +0 -0
- mosamatic2-2.0.6/src/mosamatic2/core/pipelines/__init__.py +0 -1
- mosamatic2-2.0.6/src/mosamatic2/ui/resources/VERSION +0 -1
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/README.md +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/models.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/app.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/commands/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/commands/calculatescores.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/commands/createpngsfromsegmentations.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/commands/dicom2nifti.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/commands/rescaledicomimages.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/commands/segmentmusclefatl3tensorflow.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/commands/selectslicefromscans.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/constants.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/data/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/data/dicomimage.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/data/dicomimageseries.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/data/dixonseries.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/data/filedata.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/data/multidicomimage.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/data/multinumpyimage.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/data/numpyimage.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/managers/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/managers/logmanager.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/managers/logmanagerlistener.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/core/tasks/calculatescorestask → mosamatic2-2.0.8/src/mosamatic2/core/pipelines/defaultpipeline}/__init__.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/core/pipelines → mosamatic2-2.0.8/src/mosamatic2/core/pipelines/defaultpipeline}/defaultpipeline.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/pipelines/pipeline.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/singleton.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/core/tasks/createpngsfromsegmentationstask → mosamatic2-2.0.8/src/mosamatic2/core/tasks/calculatescorestask}/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/tasks/calculatescorestask/calculatescorestask.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/core/tasks/dicom2niftitask → mosamatic2-2.0.8/src/mosamatic2/core/tasks/createdicomsummarytask}/__init__.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/core/tasks/rescaledicomimagestask → mosamatic2-2.0.8/src/mosamatic2/core/tasks/createpngsfromsegmentationstask}/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/tasks/createpngsfromsegmentationstask/createpngsfromsegmentationstask.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask → mosamatic2-2.0.8/src/mosamatic2/core/tasks/dicom2niftitask}/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/tasks/dicom2niftitask/dicom2niftitask.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/core/tasks/selectslicefromscanstask → mosamatic2-2.0.8/src/mosamatic2/core/tasks/rescaledicomimagestask}/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/tasks/rescaledicomimagestask/rescaledicomimagestask.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/ui → mosamatic2-2.0.8/src/mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask}/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/paramloader.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/segmentmusclefatl3tensorflowtask.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/ui/widgets → mosamatic2-2.0.8/src/mosamatic2/core/tasks/selectslicefromscanstask}/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/tasks/selectslicefromscanstask/selectslicefromscanstask.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/tasks/task.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/utils.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/dialogs → mosamatic2-2.0.8/src/mosamatic2/ui}/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/resources/icons/mosamatic2.icns +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/resources/icons/mosamatic2.ico +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/resources/icons/spinner.gif +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/resources/images/body-composition.jpg +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/settings.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/utils.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/panels → mosamatic2-2.0.8/src/mosamatic2/ui/widgets}/__init__.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/panels/pipelines → mosamatic2-2.0.8/src/mosamatic2/ui/widgets/dialogs}/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/dialogs/dialog.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/dialogs/helpdialog.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/panels/tasks → mosamatic2-2.0.8/src/mosamatic2/ui/widgets/panels}/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/defaultpanel.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/logpanel.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/mainpanel.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/panels/visualizations → mosamatic2-2.0.8/src/mosamatic2/ui/widgets/panels/pipelines}/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/pipelines/defaultpipelinepanel.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/pipelines/pipelinepanel.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/stackedpanel.py +0 -0
- {mosamatic2-2.0.6/src/mosamatic2/ui/widgets/panels/visualizations/slicevisualization → mosamatic2-2.0.8/src/mosamatic2/ui/widgets/panels/tasks}/__init__.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/tasks/calculatescorestaskpanel.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/tasks/createpngsfromsegmentationstaskpanel.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/tasks/dicom2niftitaskpanel.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/tasks/rescaledicomimagestaskpanel.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/tasks/segmentmusclefatl3tensorflowtaskpanel.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/tasks/selectslicefromscanstaskpanel.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/tasks/taskpanel.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/visualizations/slicevisualization/custominteractorstyle.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/visualizations/slicevisualization/sliceviewer.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/visualizations/slicevisualization/slicevisualization.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/visualizations/visualization.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/splashscreen.py +0 -0
- {mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/worker.py +0 -0
|
@@ -6,6 +6,7 @@ from mosamatic2.commands import (
|
|
|
6
6
|
createpngsfromsegmentations,
|
|
7
7
|
dicom2nifti,
|
|
8
8
|
selectslicefromscans,
|
|
9
|
+
createdicomsummary,
|
|
9
10
|
)
|
|
10
11
|
from mosamatic2.core.utils import show_doc_command
|
|
11
12
|
|
|
@@ -33,4 +34,5 @@ main.add_command(segmentmusclefatl3tensorflow.segmentmusclefatl3tensorflow)
|
|
|
33
34
|
main.add_command(createpngsfromsegmentations.createpngsfromsegmentations)
|
|
34
35
|
main.add_command(dicom2nifti.dicom2nifti)
|
|
35
36
|
main.add_command(selectslicefromscans.selectslicefromscans)
|
|
37
|
+
main.add_command(createdicomsummary.createdicomsummary)
|
|
36
38
|
main.add_command(show_doc_command(main)) # Special command to show long description for command
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from mosamatic2.core.tasks import CreateDicomSummaryTask
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@click.command(help='Creates a DICOM summary inside a root directory')
|
|
7
|
+
@click.option(
|
|
8
|
+
'--directory',
|
|
9
|
+
required=True,
|
|
10
|
+
type=click.Path(exists=True),
|
|
11
|
+
help='Root directory with DICOM images (can be multiple scans)',
|
|
12
|
+
)
|
|
13
|
+
@click.option(
|
|
14
|
+
'--output',
|
|
15
|
+
required=True,
|
|
16
|
+
type=click.Path(),
|
|
17
|
+
help='Output directory'
|
|
18
|
+
)
|
|
19
|
+
@click.option(
|
|
20
|
+
'--overwrite',
|
|
21
|
+
type=click.BOOL,
|
|
22
|
+
default=False,
|
|
23
|
+
help='Overwrite [true|false]'
|
|
24
|
+
)
|
|
25
|
+
def createdicomsummary(directory, output, overwrite):
|
|
26
|
+
"""
|
|
27
|
+
Creates a DICOM summary inside a root directory. Each patient should have
|
|
28
|
+
its own directory. Inside each patient's directory, there can be multiple
|
|
29
|
+
scans (called series) and multiple DICOM files per scan. The output of this
|
|
30
|
+
command is a file summary.txt (stored in the output directory) that contains
|
|
31
|
+
the following information:
|
|
32
|
+
|
|
33
|
+
- A list of patient directory names with the number of scans inside each
|
|
34
|
+
patient directory
|
|
35
|
+
- For each patient directory and scan directory the following information:
|
|
36
|
+
- Nr. of DICOM images in the scan
|
|
37
|
+
- Modality (e.g., CT or MRI)
|
|
38
|
+
- Image type (e.g., for Dixon scans can be in-phase, opposite-phase,
|
|
39
|
+
water or fat images)
|
|
40
|
+
- Rows/columns (size of the images)
|
|
41
|
+
- Pixel spacing (size of each pixel in mm^2)
|
|
42
|
+
- Slice thickness: (thickness of each image slice)
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
--directory : str
|
|
47
|
+
Root directory with patient directories, scans and DICOM images
|
|
48
|
+
|
|
49
|
+
--output : str
|
|
50
|
+
Path to output directory
|
|
51
|
+
|
|
52
|
+
--overwrite : bool
|
|
53
|
+
Overwrite contents output directory [true|false]
|
|
54
|
+
"""
|
|
55
|
+
task = CreateDicomSummaryTask(
|
|
56
|
+
inputs={'directory': directory},
|
|
57
|
+
params=None,
|
|
58
|
+
output=output,
|
|
59
|
+
overwrite=overwrite,
|
|
60
|
+
)
|
|
61
|
+
task.run()
|
|
@@ -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)
|
|
@@ -7,6 +7,7 @@ from mosamatic2.core.tasks import CalculateScoresTask
|
|
|
7
7
|
from mosamatic2.core.tasks import CreatePngsFromSegmentationsTask
|
|
8
8
|
from mosamatic2.core.tasks import Dicom2NiftiTask
|
|
9
9
|
from mosamatic2.core.tasks import SelectSliceFromScansTask
|
|
10
|
+
from mosamatic2.core.tasks import CreateDicomSummaryTask
|
|
10
11
|
|
|
11
12
|
app = Flask(__name__)
|
|
12
13
|
|
|
@@ -122,6 +123,21 @@ def run_selectslicefromscans():
|
|
|
122
123
|
return 'PASSED'
|
|
123
124
|
|
|
124
125
|
|
|
126
|
+
@app.route('/createdicomsummary')
|
|
127
|
+
def run_createdicomsummary():
|
|
128
|
+
directory = request.args.get('directory')
|
|
129
|
+
output = request.args.get('output')
|
|
130
|
+
overwrite = request.args.get('overwrite', default=True, type=bool)
|
|
131
|
+
task = CreateDicomSummaryTask(
|
|
132
|
+
inputs={'directory': directory},
|
|
133
|
+
params=None,
|
|
134
|
+
output=output,
|
|
135
|
+
overwrite=overwrite,
|
|
136
|
+
)
|
|
137
|
+
task.run()
|
|
138
|
+
return 'PASSED'
|
|
139
|
+
|
|
140
|
+
|
|
125
141
|
def main():
|
|
126
142
|
parser = argparse.ArgumentParser()
|
|
127
143
|
parser.add_argument('--port', type=int, default=constants.MOSAMATIC2_SERVER_PORT)
|
|
@@ -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 @@
|
|
|
1
|
+
2.0.8
|
|
@@ -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())
|
|
File without changes
|
mosamatic2-2.0.8/src/mosamatic2/ui/widgets/panels/visualizations/slicevisualization/__init__.py
ADDED
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from mosamatic2.core.pipelines.defaultpipeline import DefaultPipeline
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.0.6
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/commands/createpngsfromsegmentations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/commands/segmentmusclefatl3tensorflow.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/core/tasks/dicom2niftitask/dicom2niftitask.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/resources/images/body-composition.jpg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/pipelines/pipelinepanel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mosamatic2-2.0.6 → mosamatic2-2.0.8}/src/mosamatic2/ui/widgets/panels/tasks/dicom2niftitaskpanel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|