Repository: Project-MONAI/MONAI

Issue:
Add Padding as an Argument to AutoEncoder
**Is your feature request related to a problem? Please describe.**
In the current implementation of the AutoEncoder class in the `monai.networks.nets` module, the padding parameter is not customizable. This limits the model's flexibility, as different padding strategies might suit different data-sizes. 
https://github.com/Project-MONAI/MONAI/blob/18a671a7f12389dd8263a4c2232196dcca814bb9/monai/networks/nets/autoencoder.py#L90

**Describe the solution you'd like**
I would like to propose adding a padding argument to the AutoEncoder class constructor. This would allow users to specify the padding strategy when instantiating the model. 

**Describe alternatives you've considered**
An alternative solution could be to create a subclass of AutoEncoder (like CustomAE) whenever a different padding strategy is needed. See below,
```{python}
class CustomAE(AutoEncoder):
    def __init__(self, padding, **kwargs):
        self.padding = padding
        super().__init__(**kwargs)
    
    def _get_encode_layer(self, in_channels: int, out_channels: int, strides: int, is_last: bool) -> nn.Module:
        # ...
        mod = Convolution(
            spatial_dims=self.dimensions,
            in_channels=in_channels,
            out_channels=out_channels,
            strides=strides,
            kernel_size=self.kernel_size,
            padding=self.padding,
            # ...
        )
        return mod

```



Discussion:

Resolving patch:
diff --git a/monai/networks/nets/autoencoder.py b/monai/networks/nets/autoencoder.py
--- a/monai/networks/nets/autoencoder.py
+++ b/monai/networks/nets/autoencoder.py
@@ -58,6 +58,8 @@ class AutoEncoder(nn.Module):
         bias: whether to have a bias term in convolution blocks. Defaults to True.
             According to `Performance Tuning Guide <https://pytorch.org/tutorials/recipes/recipes/tuning_guide.html>`_,
             if a conv layer is directly followed by a batch norm layer, bias should be False.
+        padding: controls the amount of implicit zero-paddings on both sides for padding number of points
+            for each dimension in convolution blocks. Defaults to None.
 
     Examples::
 
@@ -104,6 +106,7 @@ def __init__(
         norm: tuple | str = Norm.INSTANCE,
         dropout: tuple | str | float | None = None,
         bias: bool = True,
+        padding: Sequence[int] | int | None = None,
     ) -> None:
         super().__init__()
         self.dimensions = spatial_dims
@@ -118,6 +121,7 @@ def __init__(
         self.norm = norm
         self.dropout = dropout
         self.bias = bias
+        self.padding = padding
         self.num_inter_units = num_inter_units
         self.inter_channels = inter_channels if inter_channels is not None else []
         self.inter_dilations = list(inter_dilations or [1] * len(self.inter_channels))
@@ -178,6 +182,7 @@ def _get_intermediate_module(self, in_channels: int, num_inter_units: int) -> tu
                         dropout=self.dropout,
                         dilation=di,
                         bias=self.bias,
+                        padding=self.padding,
                     )
                 else:
                     unit = Convolution(
@@ -191,6 +196,7 @@ def _get_intermediate_module(self, in_channels: int, num_inter_units: int) -> tu
                         dropout=self.dropout,
                         dilation=di,
                         bias=self.bias,
+                        padding=self.padding,
                     )
 
                 intermediate.add_module("inter_%i" % i, unit)
@@ -231,6 +237,7 @@ def _get_encode_layer(self, in_channels: int, out_channels: int, strides: int, i
                 norm=self.norm,
                 dropout=self.dropout,
                 bias=self.bias,
+                padding=self.padding,
                 last_conv_only=is_last,
             )
             return mod
@@ -244,6 +251,7 @@ def _get_encode_layer(self, in_channels: int, out_channels: int, strides: int, i
             norm=self.norm,
             dropout=self.dropout,
             bias=self.bias,
+            padding=self.padding,
             conv_only=is_last,
         )
         return mod
@@ -264,6 +272,7 @@ def _get_decode_layer(self, in_channels: int, out_channels: int, strides: int, i
             norm=self.norm,
             dropout=self.dropout,
             bias=self.bias,
+            padding=self.padding,
             conv_only=is_last and self.num_res_units == 0,
             is_transposed=True,
         )
@@ -282,6 +291,7 @@ def _get_decode_layer(self, in_channels: int, out_channels: int, strides: int, i
                 norm=self.norm,
                 dropout=self.dropout,
                 bias=self.bias,
+                padding=self.padding,
                 last_conv_only=is_last,
             )
 


Test patch: