mosamatic2 2.0.24__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. models.py +259 -0
  2. mosamatic2/__init__.py +0 -0
  3. mosamatic2/app.py +32 -0
  4. mosamatic2/cli.py +50 -0
  5. mosamatic2/commands/__init__.py +0 -0
  6. mosamatic2/commands/boadockerpipeline.py +48 -0
  7. mosamatic2/commands/calculatemaskstatistics.py +59 -0
  8. mosamatic2/commands/calculatescores.py +73 -0
  9. mosamatic2/commands/createdicomsummary.py +61 -0
  10. mosamatic2/commands/createpngsfromsegmentations.py +65 -0
  11. mosamatic2/commands/defaultdockerpipeline.py +84 -0
  12. mosamatic2/commands/defaultpipeline.py +70 -0
  13. mosamatic2/commands/dicom2nifti.py +55 -0
  14. mosamatic2/commands/liveranalysispipeline.py +61 -0
  15. mosamatic2/commands/rescaledicomimages.py +54 -0
  16. mosamatic2/commands/segmentmusclefatl3tensorflow.py +55 -0
  17. mosamatic2/commands/selectslicefromscans.py +66 -0
  18. mosamatic2/commands/totalsegmentator.py +77 -0
  19. mosamatic2/constants.py +27 -0
  20. mosamatic2/core/__init__.py +0 -0
  21. mosamatic2/core/data/__init__.py +5 -0
  22. mosamatic2/core/data/dicomimage.py +27 -0
  23. mosamatic2/core/data/dicomimageseries.py +26 -0
  24. mosamatic2/core/data/dixonseries.py +22 -0
  25. mosamatic2/core/data/filedata.py +26 -0
  26. mosamatic2/core/data/multidicomimage.py +30 -0
  27. mosamatic2/core/data/multiniftiimage.py +26 -0
  28. mosamatic2/core/data/multinumpyimage.py +26 -0
  29. mosamatic2/core/data/niftiimage.py +13 -0
  30. mosamatic2/core/data/numpyimage.py +13 -0
  31. mosamatic2/core/managers/__init__.py +0 -0
  32. mosamatic2/core/managers/logmanager.py +45 -0
  33. mosamatic2/core/managers/logmanagerlistener.py +3 -0
  34. mosamatic2/core/pipelines/__init__.py +4 -0
  35. mosamatic2/core/pipelines/boadockerpipeline/__init__.py +0 -0
  36. mosamatic2/core/pipelines/boadockerpipeline/boadockerpipeline.py +70 -0
  37. mosamatic2/core/pipelines/defaultdockerpipeline/__init__.py +0 -0
  38. mosamatic2/core/pipelines/defaultdockerpipeline/defaultdockerpipeline.py +28 -0
  39. mosamatic2/core/pipelines/defaultpipeline/__init__.py +0 -0
  40. mosamatic2/core/pipelines/defaultpipeline/defaultpipeline.py +90 -0
  41. mosamatic2/core/pipelines/liveranalysispipeline/__init__.py +0 -0
  42. mosamatic2/core/pipelines/liveranalysispipeline/liveranalysispipeline.py +48 -0
  43. mosamatic2/core/pipelines/pipeline.py +14 -0
  44. mosamatic2/core/singleton.py +9 -0
  45. mosamatic2/core/tasks/__init__.py +13 -0
  46. mosamatic2/core/tasks/applythresholdtosegmentationstask/__init__.py +0 -0
  47. mosamatic2/core/tasks/applythresholdtosegmentationstask/applythresholdtosegmentationstask.py +117 -0
  48. mosamatic2/core/tasks/calculatemaskstatisticstask/__init__.py +0 -0
  49. mosamatic2/core/tasks/calculatemaskstatisticstask/calculatemaskstatisticstask.py +104 -0
  50. mosamatic2/core/tasks/calculatescorestask/__init__.py +0 -0
  51. mosamatic2/core/tasks/calculatescorestask/calculatescorestask.py +152 -0
  52. mosamatic2/core/tasks/createdicomsummarytask/__init__.py +0 -0
  53. mosamatic2/core/tasks/createdicomsummarytask/createdicomsummarytask.py +88 -0
  54. mosamatic2/core/tasks/createpngsfromsegmentationstask/__init__.py +0 -0
  55. mosamatic2/core/tasks/createpngsfromsegmentationstask/createpngsfromsegmentationstask.py +101 -0
  56. mosamatic2/core/tasks/dicom2niftitask/__init__.py +0 -0
  57. mosamatic2/core/tasks/dicom2niftitask/dicom2niftitask.py +45 -0
  58. mosamatic2/core/tasks/rescaledicomimagestask/__init__.py +0 -0
  59. mosamatic2/core/tasks/rescaledicomimagestask/rescaledicomimagestask.py +64 -0
  60. mosamatic2/core/tasks/segmentationnifti2numpytask/__init__.py +0 -0
  61. mosamatic2/core/tasks/segmentationnifti2numpytask/segmentationnifti2numpytask.py +57 -0
  62. mosamatic2/core/tasks/segmentationnumpy2niftitask/__init__.py +0 -0
  63. mosamatic2/core/tasks/segmentationnumpy2niftitask/segmentationnumpy2niftitask.py +86 -0
  64. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/__init__.py +0 -0
  65. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/paramloader.py +39 -0
  66. mosamatic2/core/tasks/segmentmusclefatl3tensorflowtask/segmentmusclefatl3tensorflowtask.py +122 -0
  67. mosamatic2/core/tasks/segmentmusclefatt4pytorchtask/__init__.py +0 -0
  68. mosamatic2/core/tasks/segmentmusclefatt4pytorchtask/paramloader.py +39 -0
  69. mosamatic2/core/tasks/segmentmusclefatt4pytorchtask/segmentmusclefatt4pytorchtask.py +128 -0
  70. mosamatic2/core/tasks/selectslicefromscanstask/__init__.py +0 -0
  71. mosamatic2/core/tasks/selectslicefromscanstask/selectslicefromscanstask.py +249 -0
  72. mosamatic2/core/tasks/task.py +50 -0
  73. mosamatic2/core/tasks/totalsegmentatortask/__init__.py +0 -0
  74. mosamatic2/core/tasks/totalsegmentatortask/totalsegmentatortask.py +75 -0
  75. mosamatic2/core/utils.py +405 -0
  76. mosamatic2/server.py +146 -0
  77. mosamatic2/ui/__init__.py +0 -0
  78. mosamatic2/ui/mainwindow.py +426 -0
  79. mosamatic2/ui/resources/VERSION +1 -0
  80. mosamatic2/ui/resources/icons/mosamatic2.icns +0 -0
  81. mosamatic2/ui/resources/icons/mosamatic2.ico +0 -0
  82. mosamatic2/ui/resources/icons/spinner.gif +0 -0
  83. mosamatic2/ui/resources/images/body-composition.jpg +0 -0
  84. mosamatic2/ui/settings.py +62 -0
  85. mosamatic2/ui/utils.py +36 -0
  86. mosamatic2/ui/widgets/__init__.py +0 -0
  87. mosamatic2/ui/widgets/dialogs/__init__.py +0 -0
  88. mosamatic2/ui/widgets/dialogs/dialog.py +16 -0
  89. mosamatic2/ui/widgets/dialogs/helpdialog.py +9 -0
  90. mosamatic2/ui/widgets/panels/__init__.py +0 -0
  91. mosamatic2/ui/widgets/panels/defaultpanel.py +31 -0
  92. mosamatic2/ui/widgets/panels/logpanel.py +65 -0
  93. mosamatic2/ui/widgets/panels/mainpanel.py +82 -0
  94. mosamatic2/ui/widgets/panels/pipelines/__init__.py +0 -0
  95. mosamatic2/ui/widgets/panels/pipelines/boadockerpipelinepanel.py +195 -0
  96. mosamatic2/ui/widgets/panels/pipelines/defaultdockerpipelinepanel.py +314 -0
  97. mosamatic2/ui/widgets/panels/pipelines/defaultpipelinepanel.py +302 -0
  98. mosamatic2/ui/widgets/panels/pipelines/liveranalysispipelinepanel.py +187 -0
  99. mosamatic2/ui/widgets/panels/pipelines/pipelinepanel.py +6 -0
  100. mosamatic2/ui/widgets/panels/settingspanel.py +16 -0
  101. mosamatic2/ui/widgets/panels/stackedpanel.py +22 -0
  102. mosamatic2/ui/widgets/panels/tasks/__init__.py +0 -0
  103. mosamatic2/ui/widgets/panels/tasks/applythresholdtosegmentationstaskpanel.py +271 -0
  104. mosamatic2/ui/widgets/panels/tasks/calculatemaskstatisticstaskpanel.py +215 -0
  105. mosamatic2/ui/widgets/panels/tasks/calculatescorestaskpanel.py +238 -0
  106. mosamatic2/ui/widgets/panels/tasks/createdicomsummarytaskpanel.py +206 -0
  107. mosamatic2/ui/widgets/panels/tasks/createpngsfromsegmentationstaskpanel.py +247 -0
  108. mosamatic2/ui/widgets/panels/tasks/dicom2niftitaskpanel.py +183 -0
  109. mosamatic2/ui/widgets/panels/tasks/rescaledicomimagestaskpanel.py +184 -0
  110. mosamatic2/ui/widgets/panels/tasks/segmentationnifti2numpytaskpanel.py +192 -0
  111. mosamatic2/ui/widgets/panels/tasks/segmentationnumpy2niftitaskpanel.py +213 -0
  112. mosamatic2/ui/widgets/panels/tasks/segmentmusclefatl3tensorflowtaskpanel.py +216 -0
  113. mosamatic2/ui/widgets/panels/tasks/segmentmusclefatt4pytorchtaskpanel.py +217 -0
  114. mosamatic2/ui/widgets/panels/tasks/selectslicefromscanstaskpanel.py +193 -0
  115. mosamatic2/ui/widgets/panels/tasks/taskpanel.py +6 -0
  116. mosamatic2/ui/widgets/panels/tasks/totalsegmentatortaskpanel.py +195 -0
  117. mosamatic2/ui/widgets/panels/visualizations/__init__.py +0 -0
  118. mosamatic2/ui/widgets/panels/visualizations/liversegmentvisualization/__init__.py +0 -0
  119. mosamatic2/ui/widgets/panels/visualizations/liversegmentvisualization/liversegmentpicker.py +96 -0
  120. mosamatic2/ui/widgets/panels/visualizations/liversegmentvisualization/liversegmentviewer.py +130 -0
  121. mosamatic2/ui/widgets/panels/visualizations/liversegmentvisualization/liversegmentvisualization.py +120 -0
  122. mosamatic2/ui/widgets/panels/visualizations/sliceselectionvisualization/__init__.py +0 -0
  123. mosamatic2/ui/widgets/panels/visualizations/sliceselectionvisualization/sliceselectionviewer.py +61 -0
  124. mosamatic2/ui/widgets/panels/visualizations/sliceselectionvisualization/sliceselectionvisualization.py +133 -0
  125. mosamatic2/ui/widgets/panels/visualizations/sliceselectionvisualization/slicetile.py +63 -0
  126. mosamatic2/ui/widgets/panels/visualizations/slicevisualization/__init__.py +0 -0
  127. mosamatic2/ui/widgets/panels/visualizations/slicevisualization/custominteractorstyle.py +80 -0
  128. mosamatic2/ui/widgets/panels/visualizations/slicevisualization/sliceviewer.py +116 -0
  129. mosamatic2/ui/widgets/panels/visualizations/slicevisualization/slicevisualization.py +141 -0
  130. mosamatic2/ui/widgets/panels/visualizations/visualization.py +6 -0
  131. mosamatic2/ui/widgets/splashscreen.py +101 -0
  132. mosamatic2/ui/worker.py +29 -0
  133. mosamatic2-2.0.24.dist-info/METADATA +43 -0
  134. mosamatic2-2.0.24.dist-info/RECORD +136 -0
  135. mosamatic2-2.0.24.dist-info/WHEEL +4 -0
  136. mosamatic2-2.0.24.dist-info/entry_points.txt +5 -0
models.py ADDED
@@ -0,0 +1,259 @@
1
+ import torch
2
+ import torch.nn as nn
3
+ from torch.nn import functional as F
4
+
5
+
6
+ def double_conv(in_c, out_c, dropout_rate):
7
+ conv = nn.Sequential(
8
+ nn.Conv2d(in_c, out_c, kernel_size=3, padding="same"),
9
+ nn.PReLU(),
10
+ nn.BatchNorm2d(out_c),
11
+ nn.Dropout(dropout_rate),
12
+ nn.Conv2d(out_c, out_c, kernel_size=3, padding="same"),
13
+ nn.PReLU(),
14
+ nn.BatchNorm2d(out_c),
15
+ )
16
+ return conv
17
+
18
+
19
+ class UNet(nn.Module):
20
+ def __init__(self, params, num_classes):
21
+ super(UNet, self).__init__()
22
+ # num_classes = params.dict['num_classes_bc']
23
+ dropout_rate = params.dict["dropout_rate"]
24
+
25
+ self.max_pool_2x2 = nn.MaxPool2d(kernel_size=2, stride=2)
26
+ self.down_conv_1 = double_conv(1, 32, dropout_rate)
27
+ self.down_conv_2 = double_conv(32, 64, dropout_rate)
28
+ self.down_conv_3 = double_conv(64, 128, dropout_rate)
29
+ self.down_conv_4 = double_conv(128, 256, dropout_rate)
30
+ self.down_conv_5 = double_conv(256, 512, dropout_rate)
31
+
32
+ self.up_trans_1 = nn.ConvTranspose2d(
33
+ in_channels=512, out_channels=256, kernel_size=2, stride=2
34
+ )
35
+
36
+ self.up_conv_1 = double_conv(512, 256, dropout_rate)
37
+
38
+ self.up_trans_2 = nn.ConvTranspose2d(
39
+ in_channels=256, out_channels=128, kernel_size=2, stride=2
40
+ )
41
+
42
+ self.up_conv_2 = double_conv(256, 128, dropout_rate)
43
+
44
+ self.up_trans_3 = nn.ConvTranspose2d(
45
+ in_channels=128, out_channels=64, kernel_size=2, stride=2
46
+ )
47
+
48
+ self.up_conv_3 = double_conv(128, 64, dropout_rate)
49
+
50
+ self.up_trans_4 = nn.ConvTranspose2d(
51
+ in_channels=64, out_channels=32, kernel_size=2, stride=2
52
+ )
53
+
54
+ self.up_conv_4 = double_conv(64, 32, dropout_rate)
55
+
56
+ self.out = nn.Conv2d(in_channels=32, out_channels=num_classes, kernel_size=1)
57
+
58
+ def forward(self, image):
59
+
60
+ x1 = self.down_conv_1(image)
61
+ # after each convolution apply max_pooling
62
+ p1 = self.max_pool_2x2(x1)
63
+
64
+ x2 = self.down_conv_2(p1)
65
+ p2 = self.max_pool_2x2(x2)
66
+
67
+ x3 = self.down_conv_3(p2)
68
+ p3 = self.max_pool_2x2(x3)
69
+
70
+ x4 = self.down_conv_4(p3)
71
+ p4 = self.max_pool_2x2(x4)
72
+
73
+ x5 = self.down_conv_5(p4)
74
+
75
+ # decoder
76
+ u6 = self.up_trans_1(x5)
77
+ x6 = self.up_conv_1(torch.cat([u6, x4], 1))
78
+
79
+ u7 = self.up_trans_2(x6)
80
+ x7 = self.up_conv_2(torch.cat([u7, x3], 1))
81
+
82
+ u8 = self.up_trans_3(x7)
83
+ x8 = self.up_conv_3(torch.cat([u8, x2], 1))
84
+
85
+ u9 = self.up_trans_4(x8)
86
+ x9 = self.up_conv_4(torch.cat([u9, x1], 1))
87
+
88
+ x = self.out(x9)
89
+ x = F.softmax(x, dim=1)
90
+ return x
91
+
92
+
93
+ class BasicConv2d(nn.Module):
94
+ def __init__(self, in_channels, out_channels, dropout, **kwargs):
95
+ super(BasicConv2d, self).__init__()
96
+ self.conv = nn.Conv2d(
97
+ in_channels,
98
+ out_channels,
99
+ kernel_size=3,
100
+ stride=1,
101
+ padding="same",
102
+ bias=True,
103
+ **kwargs
104
+ )
105
+ # self.norm = nn.GroupNorm(32, out_channels, affine=True)
106
+ # self.norm = nn.InstanceNorm2d(out_channels, affine=True)
107
+ self.norm = nn.BatchNorm2d(out_channels)
108
+ self.dropout = nn.Dropout(dropout)
109
+
110
+ def forward(self, x):
111
+ x = self.conv(x)
112
+ x = self.norm(x)
113
+ x = F.relu(x, inplace=True)
114
+ x = self.dropout(x)
115
+ return x
116
+
117
+
118
+ class AttentionGate2D(nn.Module):
119
+ def __init__(self, in_channels_g, in_channels_l, out_channels, **kwargs):
120
+ super(AttentionGate2D, self).__init__()
121
+ self.wg = nn.Conv2d(
122
+ in_channels_g, out_channels, bias=True, padding=0, kernel_size=1, stride=1
123
+ )
124
+ # self.norm_wg = nn.GroupNorm(num_groups=32, num_channels=out_channels, affine=True)
125
+ # self.norm_wg = nn.InstanceNorm2d(out_channels, affine=True)
126
+ self.norm_wg = nn.BatchNorm2d(out_channels)
127
+ self.wx = nn.Conv2d(
128
+ in_channels_l, out_channels, bias=True, padding=0, kernel_size=1, stride=1
129
+ )
130
+ # self.norm_wx = nn.GroupNorm(num_groups=32, num_channels=out_channels, affine=True)
131
+ # self.norm_wx = nn.InstanceNorm2d(out_channels, affine=True)
132
+ self.norm_wx = nn.BatchNorm2d(out_channels)
133
+ self.psi = nn.Conv2d(
134
+ in_channels=out_channels,
135
+ out_channels=1,
136
+ bias=True,
137
+ padding=0,
138
+ kernel_size=1,
139
+ stride=1,
140
+ )
141
+ # self.norm_psi = nn.GroupNorm(num_groups=32, num_channels=out_channels, affine=True)
142
+ # self.norm_psi = nn.InstanceNorm2d(out_channels, affine=True)
143
+ self.norm_psi = nn.BatchNorm2d(1)
144
+
145
+ def forward(self, g, x):
146
+ g1 = self.wg(g)
147
+ g1 = self.norm_wg(g1)
148
+ x1 = self.wx(x)
149
+ x1 = self.norm_wx(x1)
150
+ psi = F.relu(g1 + x1, inplace=True)
151
+ psi = self.psi(psi)
152
+ psi = self.norm_psi(psi)
153
+ psi = torch.sigmoid(psi)
154
+ return x * psi
155
+
156
+
157
+ class ConvBlock2D(nn.Module):
158
+ def __init__(self, in_channels, out_channels, dropout, **kwargs):
159
+ super(ConvBlock2D, self).__init__()
160
+ self.conv1 = BasicConv2d(
161
+ in_channels=in_channels, out_channels=out_channels, dropout=dropout
162
+ )
163
+ self.conv2 = BasicConv2d(
164
+ in_channels=out_channels, out_channels=out_channels, dropout=dropout
165
+ )
166
+
167
+ def forward(self, input):
168
+ x1 = self.conv1(input)
169
+ x2 = self.conv2(x1)
170
+ return x2
171
+
172
+
173
+ class AttentionUNet(nn.Module):
174
+ def __init__(self, params, num_classes):
175
+ super(AttentionUNet, self).__init__()
176
+ # num_classes = params.dict['num_classes_bc']
177
+ dropout_rate = params.dict["dropout_rate"]
178
+
179
+ self.max_pool_2x2 = nn.MaxPool2d(kernel_size=2, stride=2)
180
+ # self.down_conv_1 = double_conv(1, 32, dropout_rate)
181
+ self.down1 = ConvBlock2D(1, 32, dropout_rate)
182
+ # self.down_conv_2 = double_conv(32, 64, dropout_rate)
183
+ self.down2 = ConvBlock2D(32, 64, dropout_rate)
184
+ # self.down_conv_3 = double_conv(64, 128, dropout_rate)
185
+ self.down3 = ConvBlock2D(64, 128, dropout_rate)
186
+ # self.down_conv_4 = double_conv(128, 256, dropout_rate)
187
+ self.down4 = ConvBlock2D(128, 256, dropout_rate)
188
+ # self.down_conv_5 = double_conv(256, 512, dropout_rate)
189
+ self.down5 = ConvBlock2D(256, 512, dropout_rate)
190
+
191
+ self.up_trans_5 = nn.ConvTranspose2d(
192
+ in_channels=512, out_channels=256, kernel_size=2, stride=2
193
+ )
194
+
195
+ # self.up_conv_1 = double_conv(512, 256, dropout_rate)
196
+ self.up5 = ConvBlock2D(512, 256, dropout_rate)
197
+ self.ag5 = AttentionGate2D(256, 256, 128)
198
+
199
+ self.up_trans_4 = nn.ConvTranspose2d(
200
+ in_channels=256, out_channels=128, kernel_size=2, stride=2
201
+ )
202
+
203
+ # self.up_conv_2 = double_conv(256, 128, dropout_rate)
204
+ self.up4 = ConvBlock2D(256, 128, dropout_rate)
205
+ self.ag4 = AttentionGate2D(128, 128, 64)
206
+ self.up_trans_3 = nn.ConvTranspose2d(
207
+ in_channels=128, out_channels=64, kernel_size=2, stride=2
208
+ )
209
+
210
+ # self.up_conv_3 = double_conv(128, 64, dropout_rate)
211
+ self.up3 = ConvBlock2D(128, 64, dropout_rate)
212
+ self.ag3 = AttentionGate2D(64, 64, 32)
213
+
214
+ self.up_trans_2 = nn.ConvTranspose2d(
215
+ in_channels=64, out_channels=32, kernel_size=2, stride=2
216
+ )
217
+
218
+ # self.up_conv_4 = double_conv(64, 32, dropout_rate)
219
+ self.up2 = ConvBlock2D(64, 32, dropout_rate)
220
+ self.ag2 = AttentionGate2D(32, 32, 32)
221
+ self.out = nn.Conv2d(in_channels=32, out_channels=num_classes, kernel_size=1)
222
+
223
+ def forward(self, image):
224
+
225
+ x1 = self.down1(image)
226
+ # after each convolution apply max_pooling
227
+ p1 = self.max_pool_2x2(x1)
228
+
229
+ x2 = self.down2(p1)
230
+ p2 = self.max_pool_2x2(x2)
231
+
232
+ x3 = self.down3(p2)
233
+ p3 = self.max_pool_2x2(x3)
234
+
235
+ x4 = self.down4(p3)
236
+ p4 = self.max_pool_2x2(x4)
237
+
238
+ x5 = self.down5(p4)
239
+
240
+ # decoder
241
+ u6 = self.up_trans_5(x5)
242
+ s4 = self.ag5(g=u6, x=x4)
243
+ x6 = self.up5(torch.cat([u6, s4], 1))
244
+
245
+ u7 = self.up_trans_4(x6)
246
+ s3 = self.ag4(u7, x3)
247
+ x7 = self.up4(torch.cat([u7, s3], 1))
248
+
249
+ u8 = self.up_trans_3(x7)
250
+ s2 = self.ag3(u8, x2)
251
+ x8 = self.up3(torch.cat([u8, s2], 1))
252
+
253
+ u9 = self.up_trans_2(x8)
254
+ s1 = self.ag2(u9, x1)
255
+ x9 = self.up2(torch.cat([u9, s1], 1))
256
+
257
+ x = self.out(x9)
258
+ x = F.softmax(x, dim=1)
259
+ return x
mosamatic2/__init__.py ADDED
File without changes
mosamatic2/app.py ADDED
@@ -0,0 +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
+
16
+ def main():
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,50 @@
1
+ import click
2
+ from mosamatic2.commands import (
3
+ calculatescores,
4
+ calculatemaskstatistics,
5
+ rescaledicomimages,
6
+ segmentmusclefatl3tensorflow,
7
+ createpngsfromsegmentations,
8
+ dicom2nifti,
9
+ selectslicefromscans,
10
+ createdicomsummary,
11
+ defaultpipeline,
12
+ defaultdockerpipeline,
13
+ boadockerpipeline,
14
+ liveranalysispipeline,
15
+ totalsegmentator,
16
+ )
17
+ from mosamatic2.core.utils import show_doc_command
18
+
19
+
20
+ class CustomHelpGroup(click.Group):
21
+ def format_commands(self, ctx, formatter):
22
+ commands = self.list_commands(ctx)
23
+ with formatter.section('Commands'):
24
+ for command_name in commands:
25
+ command = self.get_command(ctx, command_name)
26
+ if command is None or command.hidden:
27
+ continue
28
+ help_text = command.get_short_help_str()
29
+ formatter.write_text(f'{command_name:15} {help_text}')
30
+
31
+
32
+ @click.group(cls=CustomHelpGroup)
33
+ def main():
34
+ pass
35
+
36
+
37
+ main.add_command(calculatescores.calculatescores)
38
+ main.add_command(calculatemaskstatistics.calculatemaskstatistics)
39
+ main.add_command(rescaledicomimages.rescaledicomimages)
40
+ main.add_command(segmentmusclefatl3tensorflow.segmentmusclefatl3tensorflow)
41
+ main.add_command(createpngsfromsegmentations.createpngsfromsegmentations)
42
+ main.add_command(dicom2nifti.dicom2nifti)
43
+ main.add_command(selectslicefromscans.selectslicefromscans)
44
+ main.add_command(createdicomsummary.createdicomsummary)
45
+ main.add_command(defaultpipeline.defaultpipeline)
46
+ main.add_command(defaultdockerpipeline.defaultdockerpipeline)
47
+ main.add_command(boadockerpipeline.boadockerpipeline)
48
+ main.add_command(liveranalysispipeline.liveranalysispipeline)
49
+ main.add_command(totalsegmentator.totalsegmentator)
50
+ main.add_command(show_doc_command(main)) # Special command to show long description for command
File without changes
@@ -0,0 +1,48 @@
1
+ import click
2
+
3
+ from mosamatic2.core.pipelines import BoaDockerPipeline
4
+
5
+
6
+ @click.command(help='Runs 3D body composition analysis pipeline using BOA algorithm')
7
+ @click.option(
8
+ '--scans',
9
+ required=True,
10
+ type=click.Path(exists=True),
11
+ help='Root directory with scan directories for each patient (no spaces allowed)',
12
+ )
13
+ @click.option(
14
+ '--output',
15
+ required=True,
16
+ type=click.Path(),
17
+ help='Output directory (no spaces allowed)'
18
+ )
19
+ @click.option(
20
+ '--overwrite',
21
+ type=click.BOOL,
22
+ default=False,
23
+ help='Overwrite [true|false]'
24
+ )
25
+ def boadockerpipeline(scans, output, overwrite):
26
+ """
27
+ Runs 3D body composition analysis pipeline using BOA algorithm.
28
+
29
+ Parameters
30
+ ----------
31
+ --scans : str
32
+ Root directory with scan directories for each patient. Each scan directory should
33
+ contain DICOM images for a single scan only and nothing else. Also, the directory
34
+ paths cannot contain any spaces.
35
+
36
+ --output : str
37
+ Path to output directory. No spaces allowed.
38
+
39
+ --overwrite : bool
40
+ Overwrite contents output directory [true|false]
41
+ """
42
+ pipeline = BoaDockerPipeline(
43
+ inputs={'scans': scans},
44
+ params=None,
45
+ output=output,
46
+ overwrite=overwrite,
47
+ )
48
+ pipeline.run()
@@ -0,0 +1,59 @@
1
+ import click
2
+
3
+ from mosamatic2.core.tasks import CalculateMaskStatisticsTask
4
+
5
+
6
+ @click.command(help='Calculates segmentation mask statistics')
7
+ @click.option(
8
+ '--scans',
9
+ required=True,
10
+ type=click.Path(exists=True),
11
+ help='Directory with scans in NIFTI format',
12
+ )
13
+ @click.option(
14
+ '--masks',
15
+ required=True,
16
+ type=click.Path(exists=True),
17
+ help='Directory with segmentation mask files in NIFTI format',
18
+ )
19
+ @click.option(
20
+ '--output',
21
+ required=True,
22
+ type=click.Path(),
23
+ help='Output directory'
24
+ )
25
+ @click.option(
26
+ '--overwrite',
27
+ type=click.BOOL,
28
+ default=False,
29
+ help='Overwrite [true|false]'
30
+ )
31
+ def calculatemaskstatistics(scans, masks, output, overwrite):
32
+ """
33
+ Calculates segmentation mask statistics. The following metrics are calculated:
34
+
35
+ (1) Mean radiation attenuation (HU)
36
+ (2) Standard deviation radiation attenuation (HU)
37
+ (3) Segmentation mask volume (mL)
38
+
39
+ Parameters
40
+ ----------
41
+ --scans : str
42
+ Directory with scans in NIFTI format
43
+
44
+ --masks : str
45
+ Directory with segmentation mask files in NIFTI format
46
+
47
+ --output : str
48
+ Path to output directory
49
+
50
+ --overwrite : bool
51
+ Overwrite contents output directory [true|false]
52
+ """
53
+ task = CalculateMaskStatisticsTask(
54
+ inputs={'scans': scans, 'masks': masks},
55
+ params=None,
56
+ output=output,
57
+ overwrite=overwrite,
58
+ )
59
+ task.run()
@@ -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 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,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,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()