class_docstr: Resnet block with optional bottleneck activated by default
  Arguments:
      down_conv_nn (len of 2 or 3) :
                      sizes of input, intermediate, output.
                      If length == 2 then intermediate =  num_outputs // 4
      radius : radius of the conv kernel
      sigma :
      density_parameter : density parameter for the kernel
      max_num_neighbors : maximum number of neighboors for the neighboor search
      activation : activation function
      has_bottleneck: wether to use the bottleneck or not
      bn_momentum
      bn : batch norm (can be None -> no batch norm)
      grid_size : size of the grid,
      prev_grid_size : size of the grid at previous step.
                      In case of a strided block, this is different than grid_size
class_docstr_tok: ["Resnet","block","with","optional","bottleneck","activated","by","default","Arguments",":","down_conv_nn","(","len","of","2","or","3",")",":","sizes","of","input",",","intermediate",",","output",".","If","length","==","2","then","intermediate","=","num_outputs","\/\/","4","radius",":","radius","of","the","conv","kernel","sigma",":","density_parameter",":","density","parameter","for","the","kernel","max_num_neighbors",":","maximum","number","of","neighboors","for","the","neighboor","search","activation",":","activation","function","has_bottleneck",":","wether","to","use","the","bottleneck","or","not","bn_momentum","bn",":","batch","norm","(","can","be","None","-",">","no","batch","norm",")","grid_size",":","size","of","the","grid",",","prev_grid_size",":","size","of","the","grid","at","previous","step",".","In","case","of","a","strided","block",",","this","is","different","than","grid_size"]
docstr: data: x, pos, batch_idx and idx_neighbour when the neighboors of each point in pos have already been computed
docstr_tok: ["data",":","x",",","pos",",","batch_idx","and","idx_neighbour","when","the","neighboors","of","each","point","in","pos","have","already","been","computed"]
code: def forward(self, data, precomputed=None, **kwargs):
      """
      data: x, pos, batch_idx and idx_neighbour when the neighboors of each point in pos have already been computed
      """
      # Main branch
      output = data.clone()
      shortcut_x = data.x
      if self.has_bottleneck:
          output.x = self.unary_1(output.x)
      output = self.kp_conv(output, precomputed=precomputed)
      if self.has_bottleneck:
          output.x = self.unary_2(output.x)
  
      # Shortcut
      if self.is_strided:
          idx_neighboors = output.idx_neighboors
          shortcut_x = torch.cat(
              [shortcut_x, torch.zeros_like(shortcut_x[:1, :])], axis=0
          )  # Shadow feature
          neighborhood_features = shortcut_x[idx_neighboors]
          shortcut_x = torch.max(
              neighborhood_features, dim=1, keepdim=False
          )[0]
  
      shortcut = self.shortcut_op(shortcut_x)
      output.x += shortcut
      return output
  
imports: import torch
  import sys
  from torch.nn import Linear
  from .kernels import KPConvLayer, KPConvDeformableLayer
  from torch_points3d.core.common_modules.base_modules import BaseModule, FastBatchNorm1d
  from torch_points3d.core.spatial_ops import RadiusNeighbourFinder
  from torch_points3d.core.data_transform import GridSampling3D
  from torch_points3d.utils.enums import ConvolutionFormat
  from torch_points3d.core.base_conv.message_passing import GlobalBaseModule
  from torch_points3d.core.common_modules.base_modules import Identity
  from torch_points3d.utils.config import is_list
label_desc: Use image node_id 2 for calling the ResnetBBlock obj's underlying member method code with example usage: obj.forward(data, precomputed) and returns: output