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, output_mask):
      """
  
      :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:
      """
      sparse_input_shape = input_tensor.shape.as_list()
      if input_mask is None:
          _input_mask = tf.ones([sparse_input_shape[-1]]) > 0
      else:
          _input_mask = input_mask
      if output_mask is None:
          _output_mask = tf.ones([self.n_output_chns]) > 0
      else:
          _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 = layer_util.expand_spatial_params(
          self.kernel_size, spatial_rank
      )
      # expand kernel size to include number of features
      w_full_size = w_full_size + (
          n_full_input_chns,
          self.n_output_chns,
      )
  
      full_stride = layer_util.expand_spatial_params(
          self.stride, spatial_rank
      )
  
      full_dilation = layer_util.expand_spatial_params(
          self.dilation, spatial_rank
      )
  
      conv_kernel = tf.get_variable(
          "w",
          shape=w_full_size,
          initializer=self.initializers["w"],
          regularizer=self.regularizers["w"],
      )
  
      if spatial_rank == 2:
          transpositions = [[3, 2, 1, 0], [1, 0, 2, 3], [3, 2, 0, 1]]
      elif spatial_rank == 3:
          transpositions = [
              [4, 3, 2, 1, 0],
              [1, 0, 2, 3, 4],
              [4, 3, 2, 0, 1],
          ]
      else:
          raise NotImplementedError("spatial rank not supported")
  
      sparse_kernel = tf.transpose(conv_kernel, transpositions[0])
      sparse_kernel = tf.boolean_mask(sparse_kernel, _output_mask)
      sparse_kernel = tf.transpose(sparse_kernel, transpositions[1])
      sparse_kernel = tf.boolean_mask(sparse_kernel, _input_mask)
      sparse_kernel = tf.transpose(sparse_kernel, transpositions[2])
  
      output_tensor = tf.nn.convolution(
          input=input_tensor,
          filter=sparse_kernel,
          strides=full_stride,
          dilation_rate=full_dilation,
          padding=self.padding,
          name="conv",
      )
      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_term = tf.get_variable(
          "b",
          shape=self.n_output_chns,
          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 ChannelSparseConvLayer obj's underlying member method code with example usage: obj.layer_op(input_tensor, input_mask, output_mask) and returns: output_tensor, output_tensor