class_docstr: ### Description
  implementation of Dense-V-Net:
     Gibson et al., "Automatic multi-organ segmentation on abdominal CT with
     dense V-networks" 2018
  
  ### Diagram
  
  DFS = Dense Feature Stack Block
  
  - Initial image is first downsampled to a given size.
  - Each DFS+SD outputs a skip link + a downsampled output.
  - All outputs are upscaled to the initial downsampled size.
  - If initial prior is given add it to the output prediction.
  
  Input
    |
    --[ DFS ]-----------------------[ Conv ]------------[ Conv ]------[+]-->
         |                                       |  |              |
         -----[ DFS ]---------------[ Conv ]------  |              |
                 |                                  |              |
                 -----[ DFS ]-------[ Conv ]---------              |
                                                        [ Prior ]---
  
  The layer DenseFeatureStackBlockWithSkipAndDownsample layer implements
  [DFS + Conv + Downsampling] in a single module, and outputs 2 elements:
      - Skip layer:          [ DFS + Conv]
      - Downsampled output:  [ DFS + Down]
  
  ### Constraints
  - Input size has to be divisible by 2*dilation_rates
code: def create_network(self):
      hyperparams = self.hyperparams
  
      # Create initial convolutional layer
      initial_conv = ConvolutionalLayer(
          hyperparams["n_initial_conv_channels"],
          kernel_size=5,
          stride=2,
      )
      # name='initial_conv')
  
      # Create dense vblocks
      num_blocks = len(
          hyperparams["n_dense_channels"]
      )  # Num dense blocks
      dense_ch = hyperparams["n_dense_channels"]
      seg_ch = hyperparams["n_seg_channels"]
      down_ch = hyperparams["n_down_channels"]
      dil_rate = hyperparams["dilation_rates"]
      use_bdo = hyperparams["use_bdo"]
  
      dense_vblocks = []
      for i in range(num_blocks):
          vblock = DenseFeatureStackBlockWithSkipAndDownsample(
              n_dense_channels=dense_ch[i],
              kernel_size=3,
              dilation_rates=dil_rate[i],
              n_seg_channels=seg_ch[i],
              n_down_channels=down_ch[i],
              use_bdo=use_bdo,
              acti_func="relu",
          )
          dense_vblocks.append(vblock)
  
      # Create final convolutional layer
      final_conv = ConvolutionalLayer(
          self.num_classes,
          kernel_size=hyperparams["seg_kernel_size"],
          feature_normalization=None,
          with_bias=True,
      )
      #  name='final_conv')
  
      # Create a structure with all the fields of a DenseVNet
      dense_vnet = namedtuple(
          "DenseVNet", ["initial_conv", "dense_vblocks", "final_conv"]
      )
  
      return dense_vnet(
          initial_conv=initial_conv,
          dense_vblocks=dense_vblocks,
          final_conv=final_conv,
      )
  
imports: from __future__ import absolute_import, print_function
  import tensorflow
  from niftynet.io.misc_io import image3_axial
  from niftynet.layer import layer_util
  from niftynet.layer.affine_augmentation import AffineAugmentationLayer
  from niftynet.layer.base_layer import TrainableLayer
  from niftynet.layer.bn import BNLayer
  from niftynet.layer.channel_sparse_convolution import ChannelSparseConvolutionalLayer
  from niftynet.layer.convolution import ConvolutionalLayer
  from niftynet.layer.linear_resize import LinearResizeLayer
  from niftynet.layer.downsample import DownSampleLayer
  from niftynet.network.base_net import BaseNet
  from collections import namedtuple
label_desc: Use image node_id 2 for calling the DenseVNet obj's underlying member method code with example usage: obj.create_network() and returns: dense_vnet