class_docstr: The backbone network used in VoxelMorph. See :py:class:`monai.networks.nets.VoxelMorph` for more details.
  
  A concatenated pair of images (moving and fixed) is first passed through a UNet. The output of the UNet is then
  passed through a series of convolution blocks to produce the final prediction of the displacement field (DDF) or the
  stationary velocity field (DVF).
  
  In the original implementation, downsample is achieved through maxpooling, here one has the option to use either
  maxpooling or strided convolution for downsampling. The default is to use maxpooling as it is consistent with the
  original implementation. Note that for upsampling, the authors of VoxelMorph used nearest neighbor interpolation
  instead of transposed convolution. In this implementation, only nearest neighbor interpolation is supported in order
  to be consistent with the original implementation.
  
  An instance of this class can be used as a backbone network for constructing a VoxelMorph network. See the
  documentation of :py:class:`monai.networks.nets.VoxelMorph` for more details and an example on how to construct a
  VoxelMorph network.
  
  Args:
      spatial_dims: number of spatial dimensions.
      in_channels: number of channels in the input volume after concatenation of moving and fixed images.
      unet_out_channels: number of channels in the output of the UNet.
      channels: number of channels in each layer of the UNet. See the following example for more details.
      final_conv_channels: number of channels in each layer of the final convolution block.
      final_conv_act: activation type for the final convolution block. Defaults to LeakyReLU.
          Since VoxelMorph was originally implemented in tensorflow where the default negative slope for
          LeakyReLU was 0.2, we use the same default value here.
      kernel_size: kernel size for all convolution layers in the UNet. Defaults to 3.
      up_kernel_size: kernel size for all convolution layers in the upsampling path of the UNet. Defaults to 3.
      act: activation type for all convolution layers in the UNet. Defaults to LeakyReLU with negative slope 0.2.
      norm: feature normalization type and arguments for all convolution layers in the UNet. Defaults to None.
      dropout: dropout ratio for all convolution layers in the UNet. Defaults to 0.0 (no dropout).
      bias: whether to use bias in all convolution layers in the UNet. Defaults to True.
      use_maxpool: whether to use maxpooling in the downsampling path of the UNet. Defaults to True.
          Using maxpooling is the consistent with the original implementation of VoxelMorph.
          But one can optionally use strided convolution instead (i.e. set `use_maxpool` to False).
      adn_ordering: ordering of activation, dropout, and normalization. Defaults to "NDA".
class_docstr_tok: ["The","backbone","network","used","in","VoxelMorph",".","See",":","py",":","class",":","`","monai.networks.nets.VoxelMorph","`","for","more","details",".","A","concatenated","pair","of","images","(","moving","and","fixed",")","is","first","passed","through","a","UNet",".","The","output","of","the","UNet","is","then","passed","through","a","series","of","convolution","blocks","to","produce","the","final","prediction","of","the","displacement","field","(","DDF",")","or","the","stationary","velocity","field","(","DVF",")",".","In","the","original","implementation",",","downsample","is","achieved","through","maxpooling",",","here","one","has","the","option","to","use","either","maxpooling","or","strided","convolution","for","downsampling",".","The","default","is","to","use","maxpooling","as","it","is","consistent","with","the","original","implementation",".","Note","that","for","upsampling",",","the","authors","of","VoxelMorph","used","nearest","neighbor","interpolation","instead","of","transposed","convolution",".","In","this","implementation",",","only","nearest","neighbor","interpolation","is","supported","in","order","to","be","consistent","with","the","original","implementation",".","An","instance","of","this","class","can","be","used","as","a","backbone","network","for","constructing","a","VoxelMorph","network",".","See","the","documentation","of",":","py",":","class",":","`","monai.networks.nets.VoxelMorph","`","for","more","details","and","an","example","on","how","to","construct","a","VoxelMorph","network",".","Args",":","spatial_dims",":","number","of","spatial","dimensions",".","in_channels",":","number","of","channels","in","the","input","volume","after","concatenation","of","moving","and","fixed","images",".","unet_out_channels",":","number","of","channels","in","the","output","of","the","UNet",".","channels",":","number","of","channels","in","each","layer","of","the","UNet",".","See","the","following","example","for","more","details",".","final_conv_channels",":","number","of","channels","in","each","layer","of","the","final","convolution","block",".","final_conv_act",":","activation","type","for","the","final","convolution","block",".","Defaults","to","LeakyReLU",".","Since","VoxelMorph","was","originally","implemented","in","tensorflow","where","the","default","negative","slope","for","LeakyReLU","was","0.2",",","we","use","the","same","default","value","here",".","kernel_size",":","kernel","size","for","all","convolution","layers","in","the","UNet",".","Defaults","to","3.","up_kernel_size",":","kernel","size","for","all","convolution","layers","in","the","upsampling","path","of","the","UNet",".","Defaults","to","3.","act",":","activation","type","for","all","convolution","layers","in","the","UNet",".","Defaults","to","LeakyReLU","with","negative","slope","0.2.","norm",":","feature","normalization","type","and","arguments","for","all","convolution","layers","in","the","UNet",".","Defaults","to","None",".","dropout",":","dropout","ratio","for","all","convolution","layers","in","the","UNet",".","Defaults","to","0.0","(","no","dropout",")",".","bias",":","whether","to","use","bias","in","all","convolution","layers","in","the","UNet",".","Defaults","to","True",".","use_maxpool",":","whether","to","use","maxpooling","in","the","downsampling","path","of","the","UNet",".","Defaults","to","True",".","Using","maxpooling","is","the","consistent","with","the","original","implementation","of","VoxelMorph",".","But","one","can","optionally","use","strided","convolution","instead","(","i.e",".","set","`","use_maxpool","`","to","False",")",".","adn_ordering",":","ordering","of","activation",",","dropout",",","and","normalization",".","Defaults","to","``","NDA","''","."]
code: def __init__(
      self,
      spatial_dims: int,
      in_channels: int,
      unet_out_channels: int,
      channels: Sequence[int],
      final_conv_channels: Sequence[int],
      final_conv_act: tuple | str | None = "LEAKYRELU",
      kernel_size: Sequence[int] | int = 3,
      up_kernel_size: Sequence[int] | int = 3,
      act: tuple | str = "LEAKYRELU",
      norm: tuple | str | None = None,
      dropout: float = 0.0,
      bias: bool = True,
      use_maxpool: bool = True,
      adn_ordering: str = "NDA",
  ) -> None:
      super().__init__()
  
      if spatial_dims not in (2, 3):
          raise ValueError("spatial_dims must be either 2 or 3.")
      if in_channels % 2 != 0:
          raise ValueError("in_channels must be divisible by 2.")
      if len(channels) < 2:
          raise ValueError(
              "the length of `channels` should be no less than 2."
          )
      if len(channels) % 2 != 0:
          raise ValueError(
              "the elements of `channels` should be specified in pairs."
          )
      if (
          isinstance(kernel_size, Sequence)
          and len(kernel_size) != spatial_dims
      ):
          raise ValueError(
              "the length of `kernel_size` should equal to `dimensions`."
          )
      if (
          isinstance(up_kernel_size, Sequence)
          and len(up_kernel_size) != spatial_dims
      ):
          raise ValueError(
              "the length of `up_kernel_size` should equal to `dimensions`."
          )
  
      # UNet args
      self.dimensions = spatial_dims
      self.in_channels = in_channels
      self.unet_out_channels = unet_out_channels
      self.channels = channels
      self.kernel_size = kernel_size
      self.up_kernel_size = up_kernel_size
      self.act = (
          ("leakyrelu", {"negative_slope": 0.2, "inplace": True})
          if isinstance(act, str) and act.upper() == "LEAKYRELU"
          else act
      )
      self.norm = norm
      self.dropout = dropout
      self.bias = bias
      self.use_maxpool = use_maxpool
      self.adn_ordering = adn_ordering
  
      # final convolutions args
      self.final_conv_channels = final_conv_channels
      self.final_conv_act = (
          ("leakyrelu", {"negative_slope": 0.2, "inplace": True})
          if isinstance(final_conv_act, str)
          and final_conv_act.upper() == "LEAKYRELU"
          else final_conv_act
      )
  
      def _create_block(
          inc: int, outc: int, channels: Sequence[int], is_top: bool
      ) -> nn.Module:
          """
          Builds the UNet structure recursively.
  
          Args:
              inc: number of input channels.
              outc: number of output channels.
              channels: sequence of channels for each pair of down and up layers.
              is_top: True if this is the top block.
          """
  
          next_c_in, next_c_out = channels[0:2]
          upc = next_c_in + next_c_out
  
          subblock: nn.Module
  
          if len(channels) > 2:
              subblock = _create_block(
                  next_c_in, next_c_out, channels[2:], is_top=False
              )  # continue recursion down
          else:
              # the next layer is the bottom so stop recursion, create the bottom layer as the sublock for this layer
              subblock = self._get_bottom_layer(next_c_in, next_c_out)
  
          down = self._get_down_layer(
              inc, next_c_in, is_top
          )  # create layer in downsampling path
          up = self._get_up_layer(
              upc, outc, is_top
          )  # create layer in upsampling path
  
          return self._get_connection_block(down, up, subblock)
  
      def _create_final_conv(
          inc: int, outc: int, channels: Sequence[int]
      ) -> nn.Module:
          """
          Builds the final convolution blocks.
  
          Args:
              inc: number of input channels, should be the same as `unet_out_channels`.
              outc: number of output channels, should be the same as `spatial_dims`.
              channels: sequence of channels for each convolution layer.
  
          Note: there is no activation after the last convolution layer as per the original implementation.
          """
  
          mod: nn.Module = nn.Sequential()
  
          for i, c in enumerate(channels):
              mod.add_module(
                  f"final_conv_{i}",
                  Convolution(
                      self.dimensions,
                      inc,
                      c,
                      kernel_size=self.kernel_size,
                      act=self.final_conv_act,
                      norm=self.norm,
                      dropout=self.dropout,
                      bias=self.bias,
                      adn_ordering=self.adn_ordering,
                  ),
              )
              inc = c
  
          mod.add_module(
              "final_conv_out",
              Convolution(
                  self.dimensions,
                  inc,
                  outc,
                  kernel_size=self.kernel_size,
                  act=None,
                  norm=self.norm,
                  dropout=self.dropout,
                  bias=self.bias,
                  adn_ordering=self.adn_ordering,
              ),
          )
  
          return mod
  
      self.net = nn.Sequential(
          _create_block(
              in_channels, unet_out_channels, self.channels, is_top=True
          ),
          _create_final_conv(
              unet_out_channels,
              self.dimensions,
              self.final_conv_channels,
          ),
      )
  
imports: from __future__ import annotations
  from collections.abc import Sequence
  import torch
  import torch.nn
  import torch.nn.functional
  from monai.networks.blocks.convolutions import Convolution
  from monai.networks.blocks.upsample import UpSample
  from monai.networks.blocks.warp import DVF2DDF, Warp
  from monai.networks.layers.simplelayers import SkipConnection
  from monai.utils import alias, export
label_desc: Use image node_id 1 to create a new VoxelMorphUNet object from inherited base classes: nn with example: obj = VoxelMorphUNet(spatial_dims, in_channels, unet_out_channels, channels, final_conv_channels, final_conv_act, kernel_size, up_kernel_size, act, norm, dropout, bias, use_maxpool, adn_ordering)