code: def transform_pattern(pattern):
      # get parameters from batch_norm layer
      gamma = pattern.batchnorm.gamma.val
      beta = pattern.batchnorm.beta.val
      mean = pattern.batchnorm.mean.val
      variance = pattern.batchnorm.variance.val
      epsilon = pattern.batchnorm.epsilon.val
      # get weight, bias and groups from conv layer
  
      conv_weight = pattern.conv.weight.val
      conv_bias = pattern.conv.bias
      groups = pattern.conv.groups.val
  
      # get type of the conv layer
      is_deconv = pattern.conv.op_type == "conv_transpose"
      is_conv_1d = len(conv_weight.shape) == 3
  
      # D_in denotes the spatial dimensions for conv kernel weight
      # for conv_transpose, conv_weight has shape [Cin, Cout / groups, *D_in]
      # for conv, conv_weight has shape [Cout, Cin / groups, *D_in]
      if is_deconv:
          Cout = conv_weight.shape[1] * groups
          Cin = conv_weight.shape[0]
      else:
          Cout = conv_weight.shape[0]
          Cin = conv_weight.shape[1] * groups
  
      # get the type of the conv weight
      conv_weight_type = conv_weight.dtype
  
      # create bias for conv if not exist
      if conv_bias is None:
          conv_bias = np.zeros(Cout)
      else:
          conv_bias = conv_bias.val
      conv_bias = conv_bias.astype(conv_weight_type)
  
      # get the original shape of weight and bias
      origin_weight_shape = conv_weight.shape
      origin_bias_shape = conv_bias.shape
  
      # update the weight for conv layer
      new_conv_weight = []
      new_conv_bias = []
  
      if is_deconv:
          conv_weight = np.transpose(
              conv_weight, [1, 0, 2] if is_conv_1d else [1, 0, 2, 3]
          )
          conv_weight = np.reshape(
              conv_weight,
              [Cout, Cin // groups] + list(conv_weight.shape[2:]),
          )
  
      for i in range(Cout):
          # get batch norm parameters for each channel
          _gamma = gamma[i]
          _beta = beta[i]
          _mean = mean[i]
          _variance = variance[i]
          _scale = _gamma / np.sqrt(_variance + epsilon)
  
          # get conv weight and bias for each channel
          _conv_weight = conv_weight[i]
          _conv_bias = conv_bias[i]
  
          # update the conv weight and bias
          _conv_weight = _conv_weight * _scale
          _conv_bias = _scale * (_conv_bias - _mean) + _beta
          new_conv_weight.append(_conv_weight)
          new_conv_bias.append(_conv_bias)
  
      new_conv_weight = np.array(new_conv_weight).astype(
          conv_weight_type
      )
      new_conv_bias = np.array(new_conv_bias).astype(conv_weight_type)
  
      if is_deconv:
          new_conv_weight = np.reshape(
              new_conv_weight,
              [Cout // groups, Cin] + list(new_conv_weight.shape[2:]),
          )
          new_conv_weight = np.transpose(
              new_conv_weight, [1, 0, 2] if is_conv_1d else [1, 0, 2, 3]
          )
  
      # make sure the updated weight and bias have the same shape as the original ones
      assert (
          new_conv_weight.shape == origin_weight_shape
      ), "conv weight should have the same shape before and after the fuse_conv_batchnorm pass."
      assert (
          new_conv_bias.shape == origin_bias_shape
      ), "conv bias should have the same shape before and after the fuse_conv_batchnorm pass."
  
      # create a new conv op with the new bias value, copying rest of the attributes
      out_name = pattern.batchnorm.outputs[0].name
      conv_kargs = {
          "weight": new_conv_weight,
          "bias": new_conv_bias,
          "name": out_name,
          "before_op": pattern.conv,
      }
  
      for k, v in pattern.conv.inputs.items():
          if k in ["weight", "bias"]:
              continue
          conv_kargs[k] = v
  
      if is_deconv:
          x = mb.conv_transpose(**conv_kargs)
      else:
          x = mb.conv(**conv_kargs)
  
      pattern.batchnorm.enclosing_block.replace_uses_of_var_after_op(
          anchor_op=pattern.batchnorm,
          old_var=pattern.batchnorm.outputs[0],
          new_var=x,
      )
      # Remove all the ops at once
      pattern.block.remove_ops(pattern.op_list())
  
imports: import os
  import numpy
  from coremltools.converters.mil import Builder
  from coremltools.converters.mil.experimental.passes.generic_pass_infrastructure import register_generic_pass
label_desc: Use image node_id 2 for calling a global function with example usage: transform_pattern(pattern) without return types