Skip to content

Please include a copyright notice/license if you use external code #3

Description

@research-police

We patrolled your repo and found the following:
It seems that you use code from other code bases:

https://github.com/voxelmorph/voxelmorph/blob/47d5022e7ee0effe4205357077c640d87f44b23a/voxelmorph/torch/networks.py#L12-L144
vs. your UNet implementation:

class Unet(nn.Module):
"""
A unet architecture. Layer features can be specified directly as a list of encoder and decoder
features or as a single integer along with a number of unet levels. The default network features
per layer (when no options are specified) are:
encoder: [16, 32, 32, 32]
decoder: [32, 32, 32, 32, 32, 16, 16]
"""
def __init__(self,ConvBlock,
inshape=None,
infeats=None,
nb_features=None,
nb_levels=None,
max_pool=2,
feat_mult=1,
nb_conv_per_level=1,
half_res=False):
"""
Parameters:
inshape: Input shape. e.g. (192, 192, 192)
infeats: Number of input features.
nb_features: Unet convolutional features. Can be specified via a list of lists with
the form [[encoder feats], [decoder feats]], or as a single integer.
If None (default), the unet features are defined by the default config described in
the class documentation.
nb_levels: Number of levels in unet. Only used when nb_features is an integer.
Default is None.
feat_mult: Per-level feature multiplier. Only used when nb_features is an integer.
Default is 1.
nb_conv_per_level: Number of convolutions per unet level. Default is 1.
half_res: Skip the last decoder upsampling. Default is False.
"""
super().__init__()
# ensure correct dimensionality
ndims = len(inshape)
assert ndims in [1, 2, 3], 'ndims should be one of 1, 2, or 3. found: %d' % ndims
# cache some parameters
self.half_res = half_res
# default encoder and decoder layer features if nothing provided
if nb_features is None:
nb_features = default_unet_features()
# build feature list automatically
if isinstance(nb_features, int):
if nb_levels is None:
raise ValueError('must provide unet nb_levels if nb_features is an integer')
feats = np.round(nb_features * feat_mult ** np.arange(nb_levels)).astype(int)
nb_features = [
np.repeat(feats[:-1], nb_conv_per_level),
np.repeat(np.flip(feats), nb_conv_per_level)
]
elif nb_levels is not None:
raise ValueError('cannot use nb_levels if nb_features is not an integer')
# extract any surplus (full resolution) decoder convolutions
enc_nf, dec_nf = nb_features
nb_dec_convs = len(enc_nf)
final_convs = dec_nf[nb_dec_convs:]
dec_nf = dec_nf[:nb_dec_convs]
self.nb_levels = int(nb_dec_convs / nb_conv_per_level) + 1
if isinstance(max_pool, int):
max_pool = [max_pool] * self.nb_levels
# cache downsampling / upsampling operations
MaxPooling = getattr(nn, 'MaxPool%dd' % ndims)
self.pooling = [MaxPooling(s) for s in max_pool]
self.upsampling = [nn.Upsample(scale_factor=s, mode='nearest') for s in max_pool]
# configure encoder (down-sampling path)
prev_nf = infeats
encoder_nfs = [prev_nf]
self.encoder = nn.ModuleList()
for level in range(self.nb_levels - 1):
convs = nn.ModuleList()
for conv in range(nb_conv_per_level):
nf = enc_nf[level * nb_conv_per_level + conv]
convs.append(ConvBlock(ndims, prev_nf, nf))
prev_nf = nf
self.encoder.append(convs)
encoder_nfs.append(prev_nf)
# configure decoder (up-sampling path)
encoder_nfs = np.flip(encoder_nfs)
self.decoder = nn.ModuleList()
for level in range(self.nb_levels - 1):
convs = nn.ModuleList()
for conv in range(nb_conv_per_level):
nf = dec_nf[level * nb_conv_per_level + conv]
convs.append(ConvBlock(ndims, prev_nf, nf))
prev_nf = nf
self.decoder.append(convs)
if not half_res or level < (self.nb_levels - 2):
prev_nf += encoder_nfs[level]
# now we take care of any remaining convolutions
self.remaining = nn.ModuleList()
for num, nf in enumerate(final_convs):
self.remaining.append(ConvBlock(ndims, prev_nf, nf))
prev_nf = nf
# cache final number of features
self.final_nf = prev_nf
def forward(self, x):
# encoder forward pass
x_history = [x]
for level, convs in enumerate(self.encoder):
for conv in convs:
x = conv(x)
x_history.append(x)
x = self.pooling[level](x)
# decoder forward pass with upsampling and concatenation
for level, convs in enumerate(self.decoder):
for conv in convs:
x = conv(x)
if not self.half_res or level < (self.nb_levels - 2):
x = self.upsampling[level](x)
x = torch.cat([x, x_history.pop()], dim=1)
# remaining convs at full resolution
for conv in self.remaining:
x = conv(x)
return x

As the voxelmorpth is under Apache 2.0 license, please include respective license and copyright notice in your repo.

Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:

(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and

(b) You must cause any modified files to carry prominent notices stating that You changed the files; and

(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; [...]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions