class_docstr: Channel sparse convolutions perform convolutions over
  a subset of image channels and generate a subset of output
  channels. This enables spatial dropout without wasted computations
class_docstr_tok: ["Channel","sparse","convolutions","perform","convolutions","over","a","subset","of","image","channels","and","generate","a","subset","of","output","channels",".","This","enables","spatial","dropout","without","wasted","computations"]
docstr: :param input_tensor: image to convolve with kernel
  :param input_mask: 1-Tensor with a binary mask of input channels to use
      If this is None, all channels are used.
  :param output_mask: 1-Tensor with a binary mask of output channels to
      generate. If this is None, all channels are used and the number
      of output channels is set at graph-creation time.
  :return:
docstr_tok: [":","param","input_tensor",":","image","to","convolve","with","kernel",":","param","input_mask",":","1-Tensor","with","a","binary","mask","of","input","channels","to","use","If","this","is","None",",","all","channels","are","used",".",":","param","output_mask",":","1-Tensor","with","a","binary","mask","of","output","channels","to","generate",".","If","this","is","None",",","all","channels","are","used","and","the","number","of","output","channels","is","set","at","graph-creation","time",".",":","return",":"]
code: def layer_op(self, input_tensor, input_mask=None, output_mask=None):
      """
  
      :param input_tensor: image to convolve with kernel
      :param input_mask: 1-Tensor with a binary mask of input channels to use
          If this is None, all channels are used.
      :param output_mask: 1-Tensor with a binary mask of output channels to
          generate. If this is None, all channels are used and the number
          of output channels is set at graph-creation time.
      :return:
      """
  
      input_shape = input_tensor.shape.as_list()
      if input_mask is None:
          _input_mask = tf.ones([input_shape[-1]]) > 0
      else:
          _input_mask = input_mask
  
      if output_mask is None:
          n_sparse_output_chns = self.n_output_chns
          _output_mask = tf.ones([self.n_output_chns]) > 0
      else:
          n_sparse_output_chns = tf.reduce_sum(
              tf.cast(output_mask, tf.float32)
          )
          _output_mask = output_mask
  
      n_full_input_chns = _input_mask.shape.as_list()[0]
      spatial_rank = layer_util.infer_spatial_rank(input_tensor)
  
      # initialize conv kernels/strides and then apply
      w_full_size = np.vstack(
          (
              [self.kernel_size] * spatial_rank,
              self.n_output_chns,
              n_full_input_chns,
          )
      ).flatten()
      full_stride = np.vstack(
          (1, [self.stride] * spatial_rank, 1)
      ).flatten()
      deconv_kernel = tf.get_variable(
          "w",
          shape=w_full_size.tolist(),
          initializer=self.initializers["w"],
          regularizer=self.regularizers["w"],
      )
      if spatial_rank == 2:
          op_ = SUPPORTED_OP["2D"]
      elif spatial_rank == 3:
          op_ = SUPPORTED_OP["3D"]
      else:
          raise ValueError(
              "Only 2D and 3D spatial deconvolutions are supported"
          )
  
      output_dim = infer_output_dims(
          input_shape[1], self.stride, self.kernel_size, self.padding
      )
      sparse_output_size = [
          input_shape[0],
          [output_dim] * spatial_rank,
          n_sparse_output_chns,
      ]
      sparse_output_size = tf.stack(sparse_output_size, 0)
      output_tensor = op_(
          value=input_tensor,
          filter=deconv_kernel,
          output_shape=sparse_output_size,
          strides=full_stride.tolist(),
          padding=self.padding,
          name="deconv",
      )
      if output_mask is None:
          # If all output channels are used, we can specify
          # the number of output channels which is useful for later layers
          old_shape = output_tensor.shape.as_list()
          old_shape[-1] = self.n_output_chns
          output_tensor.set_shape(old_shape)
      if not self.with_bias:
          return output_tensor
  
      # adding the bias term
      bias_full_size = (self.n_output_chns,)
      bias_term = tf.get_variable(
          "b",
          shape=bias_full_size,
          initializer=self.initializers["b"],
          regularizer=self.regularizers["b"],
      )
      sparse_bias = tf.boolean_mask(bias_term, _output_mask)
  
      output_tensor = tf.nn.bias_add(
          output_tensor, sparse_bias, name="add_bias"
      )
      return output_tensor
  
imports: from __future__ import absolute_import, print_function
  import math
  import numpy
  import tensorflow
  from tensorflow.python.training import moving_averages
  import niftynet.layer.bn
  import niftynet.layer.convolution
  import niftynet.layer.deconvolution
  from niftynet.layer import layer_util
  from niftynet.layer.activation import ActiLayer
  from niftynet.layer.base_layer import TrainableLayer
  from niftynet.layer.deconvolution import infer_output_dims
label_desc: Use image node_id 2 for calling the ChannelSparseDeconvLayer obj's underlying member method code with example usage: obj.layer_op(input_tensor, input_mask, output_mask) and returns: output_tensor, output_tensor