mosamatic2 2.0.1__py3-none-any.whl → 2.0.3__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.

Files changed (72) hide show
  1. mosamatic2/app.py +31 -1
  2. mosamatic2/cli.py +32 -0
  3. mosamatic2/commands/__init__.py +0 -0
  4. mosamatic2/commands/calculatescores.py +73 -0
  5. mosamatic2/commands/createpngsfromsegmentations.py +65 -0
  6. mosamatic2/commands/rescaledicomimages.py +54 -0
  7. mosamatic2/commands/segmentmusclefatl3tensorflow.py +55 -0
  8. mosamatic2/constants.py +27 -0
  9. mosamatic2/core/__init__.py +0 -0
  10. mosamatic2/core/data/__init__.py +5 -0
  11. mosamatic2/core/data/dicomimage.py +18 -0
  12. mosamatic2/core/data/dicomimageseries.py +26 -0
  13. mosamatic2/core/data/dixonseries.py +22 -0
  14. mosamatic2/core/data/filedata.py +26 -0
  15. mosamatic2/core/data/multidicomimage.py +30 -0
  16. mosamatic2/core/managers/__init__.py +0 -0
  17. mosamatic2/core/managers/logmanager.py +45 -0
  18. mosamatic2/core/managers/logmanagerlistener.py +3 -0
  19. mosamatic2/core/pipelines/__init__.py +1 -0
  20. mosamatic2/core/pipelines/defaultpipeline.py +79 -0
  21. mosamatic2/core/pipelines/pipeline.py +14 -0
  22. mosamatic2/core/singleton.py +9 -0
  23. mosamatic2/core/tasks/__init__.py +4 -0
  24. mosamatic2/core/tasks/calculatescorestask/__init__.py +0 -0
  25. mosamatic2/core/tasks/calculatescorestask/calculatescorestask.py +149 -0
  26. mosamatic2/core/tasks/createpngsfromsegmentationstask/__init__.py +0 -0
  27. mosamatic2/core/tasks/createpngsfromsegmentationstask/createpngsfromsegmentationstask.py +52 -0
  28. mosamatic2/core/tasks/rescaledicomimagestask/__init__.py +0 -0
  29. mosamatic2/core/tasks/rescaledicomimagestask/rescaledicomimagestask.py +64 -0
  30. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/__init__.py +0 -0
  31. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/paramloader.py +39 -0
  32. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/segmentmusclefatl3tensorflowtask.py +121 -0
  33. mosamatic2/core/tasks/task.py +49 -0
  34. mosamatic2/core/utils.py +316 -0
  35. mosamatic2/server.py +98 -0
  36. mosamatic2/ui/__init__.py +0 -0
  37. mosamatic2/ui/mainwindow.py +196 -0
  38. mosamatic2/ui/resources/VERSION +1 -0
  39. mosamatic2/ui/resources/icons/mosamatic2.icns +0 -0
  40. mosamatic2/ui/resources/icons/mosamatic2.ico +0 -0
  41. mosamatic2/ui/resources/icons/spinner.gif +0 -0
  42. mosamatic2/ui/resources/images/body-composition.jpg +0 -0
  43. mosamatic2/ui/settings.py +62 -0
  44. mosamatic2/ui/utils.py +36 -0
  45. mosamatic2/ui/widgets/__init__.py +0 -0
  46. mosamatic2/ui/widgets/dialogs/__init__.py +0 -0
  47. mosamatic2/ui/widgets/dialogs/dialog.py +16 -0
  48. mosamatic2/ui/widgets/dialogs/helpdialog.py +9 -0
  49. mosamatic2/ui/widgets/panels/__init__.py +0 -0
  50. mosamatic2/ui/widgets/panels/defaultpanel.py +31 -0
  51. mosamatic2/ui/widgets/panels/logpanel.py +65 -0
  52. mosamatic2/ui/widgets/panels/mainpanel.py +82 -0
  53. mosamatic2/ui/widgets/panels/pipelines/__init__.py +0 -0
  54. mosamatic2/ui/widgets/panels/pipelines/defaultpipelinepanel.py +299 -0
  55. mosamatic2/ui/widgets/panels/stackedpanel.py +22 -0
  56. mosamatic2/ui/widgets/panels/taskpanel.py +6 -0
  57. mosamatic2/ui/widgets/panels/tasks/__init__.py +0 -0
  58. mosamatic2/ui/widgets/panels/tasks/calculatescorestaskpanel.py +215 -0
  59. mosamatic2/ui/widgets/panels/tasks/createpngsfromsegmentationstaskpanel.py +186 -0
  60. mosamatic2/ui/widgets/panels/tasks/rescaledicomimagestaskpanel.py +184 -0
  61. mosamatic2/ui/widgets/panels/tasks/segmentmusclefatl3tensorflowtaskpanel.py +216 -0
  62. mosamatic2/ui/widgets/panels/tasks/selectslicefromscantaskpanel.py +184 -0
  63. mosamatic2/ui/widgets/splashscreen.py +101 -0
  64. mosamatic2/ui/worker.py +29 -0
  65. mosamatic2-2.0.3.dist-info/METADATA +34 -0
  66. mosamatic2-2.0.3.dist-info/RECORD +70 -0
  67. mosamatic2-2.0.3.dist-info/entry_points.txt +5 -0
  68. mosamatic2/api.py +0 -2
  69. mosamatic2-2.0.1.dist-info/METADATA +0 -12
  70. mosamatic2-2.0.1.dist-info/RECORD +0 -8
  71. mosamatic2-2.0.1.dist-info/entry_points.txt +0 -4
  72. {mosamatic2-2.0.1.dist-info → mosamatic2-2.0.3.dist-info}/WHEEL +0 -0
mosamatic2/app.py CHANGED
@@ -1,2 +1,32 @@
1
+ import sys
2
+ import traceback
3
+ import mosamatic2.constants as constants
4
+ from PySide6 import QtWidgets
5
+ from mosamatic2.ui.settings import Settings
6
+ from mosamatic2.core.managers.logmanager import LogManager
7
+ from mosamatic2.ui.widgets.splashscreen import SplashScreen
8
+
9
+ LOG = LogManager()
10
+
11
+
12
+ def run_tests():
13
+ return 'PASSED'
14
+
15
+
1
16
  def main():
2
- print('Running mosamatic2...')
17
+ settings = Settings()
18
+ application_name = settings.get(constants.MOSAMATIC2_WINDOW_TITLE)
19
+ QtWidgets.QApplication.setApplicationName(application_name)
20
+ app = QtWidgets.QApplication(sys.argv)
21
+ app.setApplicationName(application_name)
22
+ try:
23
+ splash = SplashScreen()
24
+ splash.show()
25
+ sys.exit(app.exec())
26
+ except Exception as e:
27
+ LOG.error(str(e))
28
+ LOG.error(traceback.format_exc())
29
+ sys.exit(1)
30
+
31
+ if __name__ == '__main__':
32
+ main()
mosamatic2/cli.py ADDED
@@ -0,0 +1,32 @@
1
+ import click
2
+ from mosamatic2.commands import (
3
+ calculatescores,
4
+ rescaledicomimages,
5
+ segmentmusclefatl3tensorflow,
6
+ createpngsfromsegmentations,
7
+ )
8
+ from mosamatic2.core.utils import show_doc_command
9
+
10
+
11
+ class CustomHelpGroup(click.Group):
12
+ def format_commands(self, ctx, formatter):
13
+ commands = self.list_commands(ctx)
14
+ with formatter.section('Commands'):
15
+ for command_name in commands:
16
+ command = self.get_command(ctx, command_name)
17
+ if command is None or command.hidden:
18
+ continue
19
+ help_text = command.get_short_help_str()
20
+ formatter.write_text(f'{command_name:15} {help_text}')
21
+
22
+
23
+ @click.group(cls=CustomHelpGroup)
24
+ def main():
25
+ pass
26
+
27
+
28
+ main.add_command(calculatescores.calculatescores)
29
+ main.add_command(rescaledicomimages.rescaledicomimages)
30
+ main.add_command(segmentmusclefatl3tensorflow.segmentmusclefatl3tensorflow)
31
+ main.add_command(createpngsfromsegmentations.createpngsfromsegmentations)
32
+ main.add_command(show_doc_command(main)) # Special command to show long description for command
File without changes
@@ -0,0 +1,73 @@
1
+ import click
2
+
3
+ from mosamatic2.core.tasks import CalculateScoresTask
4
+
5
+
6
+ @click.command(help='Calculates body composition scores')
7
+ @click.option(
8
+ '--images',
9
+ required=True,
10
+ type=click.Path(exists=True),
11
+ help='Directory with images',
12
+ )
13
+ @click.option(
14
+ '--segmentations',
15
+ required=True,
16
+ type=click.Path(exists=True),
17
+ help='Directory with segmentations',
18
+ )
19
+ @click.option(
20
+ '--output',
21
+ required=True,
22
+ type=click.Path(),
23
+ help='Output directory'
24
+ )
25
+ @click.option(
26
+ '--file_type',
27
+ default='npy',
28
+ help='Options: [npy, tag]'
29
+ )
30
+ @click.option(
31
+ '--overwrite',
32
+ type=click.BOOL,
33
+ default=False,
34
+ help='Overwrite [true|false]'
35
+ )
36
+ def calculatescores(images, segmentations, output, file_type, overwrite):
37
+ """
38
+ Calculates the following body composition metrics from the muscle and fat
39
+ images and segmentation files:
40
+
41
+ (1) Muscle area (cm^2)
42
+ (2) Mean muscle radiation attenuation (HU)
43
+ (3) Subcutaneous fat area (cm^2)
44
+ (4) Mean subcutaneous fat radiation attenuation (HU)
45
+ (5) Visceral fat area (cm^2)
46
+ (6) Mean visceral fat radiation attenuation (HU)
47
+
48
+ Parameters
49
+ ----------
50
+ --images : str
51
+ Directory with with input L3 images
52
+
53
+ --segmentations : str
54
+ Directory with L3 muscle and fat segmenation files. Must be output of
55
+ "mosamatic2-cli segmentmusclefatl3tensorflow" OR a list of TAG files
56
+ corresponding to the input images
57
+
58
+ --output : str
59
+ Path to output directory
60
+
61
+ --file_type : str
62
+ Type of segmentation file to use. Can be either "npy" or "tag"
63
+
64
+ --overwrite : bool
65
+ Overwrite contents output directory [true|false]
66
+ """
67
+ task = CalculateScoresTask(
68
+ inputs={'images': images, 'segmentations': segmentations},
69
+ params={'file_type': file_type},
70
+ output=output,
71
+ overwrite=overwrite,
72
+ )
73
+ task.run()
@@ -0,0 +1,65 @@
1
+ import click
2
+
3
+ from mosamatic2.core.tasks import CreatePngsFromSegmentationsTask
4
+
5
+
6
+ @click.command(help='Create PNG images from segmentation files')
7
+ @click.option(
8
+ '--segmentations',
9
+ required=True,
10
+ type=click.Path(exists=True),
11
+ help='Input directory to segmentation files'
12
+ )
13
+ @click.option(
14
+ '--output',
15
+ required=True,
16
+ type=click.Path(),
17
+ help='Output directory for PNG images'
18
+ )
19
+ @click.option(
20
+ '--fig_width',
21
+ type=click.Path(),
22
+ default=10,
23
+ help='Figure width (default: 10)'
24
+ )
25
+ @click.option(
26
+ '--fig_height',
27
+ type=click.Path(),
28
+ default=10,
29
+ help='Figure height (default: 10)'
30
+ )
31
+ @click.option(
32
+ '--overwrite',
33
+ type=click.BOOL,
34
+ default=False,
35
+ help='Overwrite [true|false]'
36
+ )
37
+ def createpngsfromsegmentations(segmentations, output, fig_width, fig_height, overwrite):
38
+ """
39
+ Creates PNG images from L3 muscle and fat segmentation files
40
+
41
+ Parameters
42
+ ----------
43
+ --segmentations : str
44
+ Directory with with input segmentation files. Must be L3 muscle and fat segmentations
45
+ (output of "mosamatic2-cli segmentmusclefatl3tensorflow")
46
+
47
+ --output : str
48
+ Path to output directory
49
+
50
+ --fig_width : int
51
+ Width of PNG image
52
+
53
+ --fig_height : int
54
+ Height of PNG image
55
+
56
+ --overwrite : bool
57
+ Overwrite contents output directory [true|false]
58
+ """
59
+ task = CreatePngsFromSegmentationsTask(
60
+ inputs={'segmentations': segmentations},
61
+ params={'fig_width': fig_width, 'fig_height': fig_height},
62
+ output=output,
63
+ overwrite=overwrite,
64
+ )
65
+ task.run()
@@ -0,0 +1,54 @@
1
+ import click
2
+
3
+ from mosamatic2.core.tasks import RescaleDicomImagesTask
4
+
5
+
6
+ @click.command(help='Rescale DICOM files to target size')
7
+ @click.option(
8
+ '--images',
9
+ required=True,
10
+ type=click.Path(exists=True),
11
+ help='Input directory with images'
12
+ )
13
+ @click.option(
14
+ '--output',
15
+ required=True,
16
+ type=click.Path(),
17
+ help='Output directory'
18
+ )
19
+ @click.option(
20
+ '--target_size',
21
+ default=512,
22
+ help='Target size of rescaled images (default: 512)'
23
+ )
24
+ @click.option(
25
+ '--overwrite',
26
+ type=click.BOOL,
27
+ default=False,
28
+ help='Overwrite [true|false]'
29
+ )
30
+ def rescaledicomimages(images, output, target_size, overwrite):
31
+ """
32
+ Rescales DICOM images to given (square) target size
33
+
34
+ Parameters
35
+ ----------
36
+ --images : str
37
+ Directory with with input DICOM images
38
+
39
+ --output : str
40
+ Path to output directory
41
+
42
+ --target_size : int
43
+ Target size for rescaled images (default: 512)
44
+
45
+ --overwrite : bool
46
+ Overwrite contents output directory: [true|false]
47
+ """
48
+ task = RescaleDicomImagesTask(
49
+ inputs={'images': images},
50
+ params={'target_size': target_size},
51
+ output=output,
52
+ overwrite=overwrite
53
+ )
54
+ task.run()
@@ -0,0 +1,55 @@
1
+ import click
2
+
3
+ from mosamatic2.core.tasks import SegmentMuscleFatL3TensorFlowTask
4
+
5
+
6
+ @click.command(help='Extracts muscle and fat regions from CT images at L3 (uses PyTorch)')
7
+ @click.option(
8
+ '--images',
9
+ required=True,
10
+ type=click.Path(),
11
+ help='Input directory with images'
12
+ )
13
+ @click.option(
14
+ '--model_files',
15
+ required=True,
16
+ type=click.Path(),
17
+ help='Input directory with AI model files'
18
+ )
19
+ @click.option(
20
+ '--output',
21
+ required=True,
22
+ type=click.Path(),
23
+ help='Output directory'
24
+ )
25
+ @click.option(
26
+ '--overwrite',
27
+ default=False,
28
+ type=click.BOOL,
29
+ help='Overwrite [true|false]'
30
+ )
31
+ def segmentmusclefatl3tensorflow(images, model_files, output, overwrite):
32
+ """
33
+ Automatically segments muscle and fat tissue in CT images at L3 level.
34
+
35
+ Parameters
36
+ ----------
37
+ --images : str
38
+ Directory with with input L3 images
39
+
40
+ --model_files : str
41
+ Directory with AI model files (model-1.0.zip, contour_model-1.0.zip, params-1.0.json)
42
+
43
+ --output : str
44
+ Path to output directory
45
+
46
+ --overwrite : bool
47
+ Overwrite contents output directory [true|false]
48
+ """
49
+ task = SegmentMuscleFatL3TensorFlowTask(
50
+ inputs={'images': images, 'model_files': model_files},
51
+ params={'model_version': 1.0},
52
+ output=output,
53
+ overwrite=overwrite,
54
+ )
55
+ task.run()
@@ -0,0 +1,27 @@
1
+ MOSAMATIC2_BUNDLE_IDENTIFIER = 'org.mumc'
2
+ MOSAMATIC2_APP_NAME = 'mosamatic2'
3
+ MOSAMATIC2_VERSION_FILE = 'mosamatic2/ui/resources/VERSION'
4
+ MOSAMATIC2_IMAGES_DIR_PATH = 'mosamatic2/ui/resources/images'
5
+ MOSAMATIC2_ICONS_DIR_PATH = 'mosamatic2/ui/resources/icons'
6
+ MOSAMATIC2_APP_ICON_FILE_NAME_WIN = 'mosamatic2.ico'
7
+ MOSAMATIC2_APP_ICON_FILE_NAME_MAC = 'mosamatic2.icns'
8
+ MOSAMATIC2_BACKGROUND_IMAGE_FILE_NAME = 'body-composition.jpg'
9
+ MOSAMATIC2_BACKGROUND_IMAGE_OPACITY = 0.4
10
+
11
+ MOSAMATIC2_SERVER_PORT = 8000
12
+ MOSAMATIC2_SERVER_DEBUG = True
13
+
14
+ MOSAMATIC2_WINDOW_TITLE = 'Mosamatic'
15
+ MOSAMATIC2_WINDOW_W = 1000
16
+ MOSAMATIC2_WINDOW_H = 600
17
+ MOSAMATIC2_WINDOW_GEOMETRY_KEY = 'mainwindow/geometry'
18
+ MOSAMATIC2_WINDOW_STATE_KEY = 'mainwindow/state'
19
+
20
+ MOSAMATIC2_SPLASH_SCREEN_TITLE = MOSAMATIC2_WINDOW_TITLE
21
+ MOSAMATIC2_SPLASH_SCREEN_TITLE_STYLESHEET = 'color: rgb(64, 64, 64); font-weight: bold; font-size: 32pt;'
22
+ MOSAMATIC2_SPLASH_SCREEN_SUB_TEXT = 'This software is for research only'
23
+ MOSAMATIC2_SPLASH_SCREEN_SUB_TEXT_STYLE_SHEET = 'color: rgb(64, 64, 64); font-style: italic; font-size: 10pt;'
24
+ MOSAMATIC2_SPLASH_SCREEN_START_BUTTON_TEXT = 'Start Application'
25
+ MOSAMATIC2_SPLASH_SCREEN_QUIT_BUTTON_TEXT = 'Quit'
26
+ MOSAMATIC2_SPLASH_SCREEN_W = 600
27
+ MOSAMATIC2_SPLASH_SCREEN_H = 300
File without changes
@@ -0,0 +1,5 @@
1
+ from mosamatic2.core.data.filedata import FileData
2
+ from mosamatic2.core.data.dicomimage import DicomImage
3
+ from mosamatic2.core.data.dicomimageseries import DicomImageSeries
4
+ from mosamatic2.core.data.multidicomimage import MultiDicomImage
5
+ from mosamatic2.core.data.dixonseries import DixonSeries
@@ -0,0 +1,18 @@
1
+ from mosamatic2.core.data.filedata import FileData
2
+ from mosamatic2.core.utils import (
3
+ is_dicom,
4
+ load_dicom,
5
+ is_jpeg2000_compressed,
6
+ )
7
+
8
+
9
+ class DicomImage(FileData):
10
+ def load(self):
11
+ if self.path():
12
+ if is_dicom(self.path()):
13
+ p = load_dicom(self.path())
14
+ if is_jpeg2000_compressed(p):
15
+ p.decompress()
16
+ self.set_object(p)
17
+ return True
18
+ return False
@@ -0,0 +1,26 @@
1
+ import os
2
+ from mosamatic2.core.data.filedata import FileData
3
+ from mosamatic2.core.data.dicomimage import DicomImage
4
+
5
+
6
+ class DicomImageSeries(FileData):
7
+ def __init__(self):
8
+ super(DicomImageSeries, self).__init__()
9
+ self._images = []
10
+
11
+ def images(self):
12
+ return self._images
13
+
14
+ def load(self):
15
+ if self.path():
16
+ images = []
17
+ for f in os.listdir(self.path()):
18
+ f_path = os.path.join(self.path(), f)
19
+ image = DicomImage()
20
+ image.set_path(f_path)
21
+ if image.load():
22
+ images.append(image)
23
+ # Sort DICOM objects by instance number
24
+ self._images = sorted(images, key=lambda image: int(image.object().get('InstanceNumber')))
25
+ return True
26
+ return False
@@ -0,0 +1,22 @@
1
+ from mosamatic2.core.data.filedata import FileData
2
+
3
+
4
+ class DixonSeries(FileData):
5
+ def __init__(self):
6
+ super(DixonSeries, self).__init__()
7
+ self._series = {'ip': None, 'op': None, 'water': None, 'fat': None}
8
+
9
+ def ip(self):
10
+ return self._series['ip']
11
+
12
+ def op(self):
13
+ return self._series['op']
14
+
15
+ def water(self):
16
+ return self._series['water']
17
+
18
+ def fat(self):
19
+ return self._series['fat']
20
+
21
+ def load(self):
22
+ pass
@@ -0,0 +1,26 @@
1
+ import os
2
+
3
+
4
+ class FileData:
5
+ def __init__(self):
6
+ self._path = None
7
+ self._name = None
8
+ self._object = None
9
+
10
+ def path(self):
11
+ return self._path
12
+
13
+ def set_path(self, path):
14
+ self._path = path
15
+
16
+ def name(self):
17
+ return os.path.split(self.path())[1]
18
+
19
+ def object(self):
20
+ return self._object
21
+
22
+ def set_object(self, object):
23
+ self._object = object
24
+
25
+ def load(self):
26
+ raise NotImplementedError()
@@ -0,0 +1,30 @@
1
+ import os
2
+ from mosamatic2.core.managers.logmanager import LogManager
3
+ from mosamatic2.core.data.filedata import FileData
4
+ from mosamatic2.core.data.dicomimage import DicomImage
5
+
6
+ LOG = LogManager()
7
+
8
+
9
+ class MultiDicomImage(FileData):
10
+ def __init__(self):
11
+ super(MultiDicomImage, self).__init__()
12
+ self._images = []
13
+
14
+ def images(self):
15
+ return self._images
16
+
17
+ def load(self):
18
+ series_instance_uids = []
19
+ if self.path():
20
+ for f in os.listdir(self.path()):
21
+ f_path = os.path.join(self.path(), f)
22
+ image = DicomImage()
23
+ image.set_path(f_path)
24
+ if image.load():
25
+ series_instance_uid = image.object().SeriesInstanceUID
26
+ if series_instance_uid in series_instance_uids:
27
+ RuntimeError('Cannot load DICOM images with identical series instance UID')
28
+ self._images.append(image)
29
+ return True
30
+ return False
File without changes
@@ -0,0 +1,45 @@
1
+ import os
2
+ import atexit
3
+ import datetime
4
+ from pathlib import Path
5
+ from mosamatic2.core.singleton import singleton
6
+
7
+
8
+ @singleton
9
+ class LogManager:
10
+ def __init__(self, suppress_print=False):
11
+ self._suppress_print = suppress_print
12
+ self._listeners = []
13
+ file_path = os.path.join(Path.home(), 'mosamatic2.log')
14
+ self._file_handle = open(file_path, 'w', buffering=1)
15
+ atexit.register(self.close_file)
16
+
17
+ def _log(self, level, message):
18
+ timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
19
+ message = f'[{timestamp}] {level} : {message}'
20
+ if not self._suppress_print:
21
+ print(message)
22
+ self._file_handle.write(message + '\n')
23
+ self.notify_listeners(message)
24
+ return message
25
+
26
+ def info(self, message):
27
+ return self._log('INFO', message)
28
+
29
+ def warning(self, message):
30
+ return self._log('WARNING', message)
31
+
32
+ def error(self, message):
33
+ return self._log('ERROR', message)
34
+
35
+ def add_listener(self, listener):
36
+ if listener not in self._listeners:
37
+ self._listeners.append(listener)
38
+
39
+ def notify_listeners(self, message):
40
+ for listener in self._listeners:
41
+ listener.new_message(message)
42
+
43
+ def close_file(self):
44
+ if self._file_handle:
45
+ self._file_handle.close()
@@ -0,0 +1,3 @@
1
+ class LogManagerListener:
2
+ def new_message(self, message):
3
+ raise NotImplementedError()
@@ -0,0 +1 @@
1
+ from mosamatic2.core.pipelines.defaultpipeline import DefaultPipeline
@@ -0,0 +1,79 @@
1
+ import os
2
+
3
+ from mosamatic2.core.pipelines.pipeline import Pipeline
4
+ from mosamatic2.core.tasks import (
5
+ RescaleDicomImagesTask,
6
+ SegmentMuscleFatL3TensorFlowTask,
7
+ SegmentMuscleFatL3TensorFlowTask,
8
+ CreatePngsFromSegmentationsTask,
9
+ CalculateScoresTask,
10
+ )
11
+
12
+
13
+ class DefaultPipeline(Pipeline):
14
+ INPUTS = [
15
+ 'images',
16
+ 'model_files',
17
+ ]
18
+ PARAMS = [
19
+ 'target_size',
20
+ 'file_type',
21
+ 'fig_width',
22
+ 'fig_height',
23
+ 'model_type',
24
+ 'model_version',
25
+ ]
26
+ def __init__(self, inputs, params, output, overwrite):
27
+ super(DefaultPipeline, self).__init__(inputs, params, output, overwrite)
28
+ model_type = self.param('model_type')
29
+ # segmentation_task_class = SegmentMuscleFatL3Task if model_type == 'pytorch' else SegmentMuscleFatL3TensorFlowTask
30
+ segmentation_task_class = SegmentMuscleFatL3TensorFlowTask
31
+ self.add_task(
32
+ RescaleDicomImagesTask(
33
+ inputs={'images': self.input('images')},
34
+ params={'target_size': self.param('target_size')},
35
+ output=self.output(),
36
+ overwrite=self.overwrite(),
37
+ )
38
+ )
39
+ self.add_task(
40
+ segmentation_task_class(
41
+ inputs={
42
+ 'images': os.path.join(self.output(), 'rescaledicomimagestask'),
43
+ 'model_files': self.input('model_files'),
44
+ },
45
+ params={'model_version': self.param('model_version')},
46
+ output=self.output(),
47
+ overwrite=self.overwrite(),
48
+ )
49
+ )
50
+ self.add_task(
51
+ CalculateScoresTask(
52
+ inputs={
53
+ 'images': os.path.join(self.output(), 'rescaledicomimagestask'),
54
+ 'segmentations': os.path.join(
55
+ self.output(),
56
+ 'segmentmusclefatl3pytorchtask' if model_type == 'pytorch' else 'segmentmusclefatl3tensorflowtask',
57
+ )
58
+ },
59
+ params={'file_type': self.param('file_type')},
60
+ output=self.output(),
61
+ overwrite=self.overwrite(),
62
+ )
63
+ )
64
+ self.add_task(
65
+ CreatePngsFromSegmentationsTask(
66
+ inputs={
67
+ 'segmentations': os.path.join(
68
+ self.output(),
69
+ 'segmentmusclefatl3pytorchtask' if model_type == 'pytorch' else 'segmentmusclefatl3tensorflowtask',
70
+ )
71
+ },
72
+ params={
73
+ 'fig_width': self.param('fig_width'),
74
+ 'fig_height': self.param('fig_height'),
75
+ },
76
+ output=self.output(),
77
+ overwrite=self.overwrite(),
78
+ )
79
+ )
@@ -0,0 +1,14 @@
1
+ from mosamatic2.core.tasks.task import Task
2
+
3
+
4
+ class Pipeline(Task):
5
+ def __init__(self, inputs, params, output, overwrite=False):
6
+ super(Pipeline, self).__init__(inputs, params, output, overwrite)
7
+ self._tasks = []
8
+
9
+ def add_task(self, task):
10
+ self._tasks.append(task)
11
+
12
+ def run(self):
13
+ for task in self._tasks:
14
+ task.run()
@@ -0,0 +1,9 @@
1
+ def singleton(cls):
2
+ _instances = {}
3
+
4
+ def instance(*args, **kwargs):
5
+ if cls not in _instances:
6
+ _instances[cls] = cls(*args, **kwargs)
7
+ return _instances[cls]
8
+
9
+ return instance
@@ -0,0 +1,4 @@
1
+ from mosamatic2.core.tasks.rescaledicomimagestask.rescaledicomimagestask import RescaleDicomImagesTask
2
+ from mosamatic2.core.tasks.segmentmusclefatl3tensorflowtask.segmentmusclefatl3tensorflowtask import SegmentMuscleFatL3TensorFlowTask
3
+ from mosamatic2.core.tasks.calculatescorestask.calculatescorestask import CalculateScoresTask
4
+ from mosamatic2.core.tasks.createpngsfromsegmentationstask.createpngsfromsegmentationstask import CreatePngsFromSegmentationsTask
File without changes