mosamatic2 2.0.1__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.
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: mosamatic2
|
|
3
|
+
Version: 2.0.1
|
|
4
|
+
Summary:
|
|
5
|
+
Author: Ralph Brecheisen
|
|
6
|
+
Author-email: r.brecheisen@maastrichtuniversity.nl
|
|
7
|
+
Requires-Python: >=3.11,<3.12
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
|
|
File without changes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "mosamatic2"
|
|
3
|
+
version = "2.0.1"
|
|
4
|
+
description = ""
|
|
5
|
+
authors = [
|
|
6
|
+
{name = "Ralph Brecheisen", email = "r.brecheisen@maastrichtuniversity.nl"}
|
|
7
|
+
]
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.11,<3.12"
|
|
10
|
+
dependencies = [
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[tool.poetry]
|
|
14
|
+
packages = [
|
|
15
|
+
{include = "mosamatic2", from = "src"},
|
|
16
|
+
{include = "models.py", from = "src" },
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[tool.poetry.scripts]
|
|
20
|
+
mosamatic2 = "mosamatic2.app:main"
|
|
21
|
+
mosamatic2-api = "mosamatic2.api:main"
|
|
22
|
+
|
|
23
|
+
[tool.poetry.group.dev.dependencies]
|
|
24
|
+
pytest = "^8.4.1"
|
|
25
|
+
|
|
26
|
+
[build-system]
|
|
27
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
28
|
+
build-backend = "poetry.core.masonry.api"
|
|
@@ -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
|
|
File without changes
|