code: def fft_canonicalize_shapes_dims(
      input_data: Var,
      shapes: Optional[Var],
      dims: Optional[Var],
      c2r: bool = False,
  ) -> Tuple[Tuple[int], Tuple[int]]:
      """
      Canonicalize shapes and dims for N-D FFT (based on PyTorch's fftn documentation):
      - shapes: Signal size in the transformed dimensions. If given, each dimension dims[i] will
                either be zero-padded or trimmed to the length s[i] before computing the FFT. If a
                length -1 is specified, no padding is done in that dimension.
                Default: s = [input.size(d) for d in dims]
      - dims: Dimensions to be transformed. Default: all dimensions, or the last len(s) dimensions if
              s is given.
      - c2r: Use for "complex to real", such as irfftn, which takes complex and output real data.
      """
      if shapes is not None:
          shapes = shapes.val
          if isinstance(shapes, np.integer):
              shapes = (shapes,)
      if dims is not None:
          dims = dims.val
          if isinstance(dims, np.integer):
              dims = (dims,)
  
      # Input validation.
      input_rank = input_data.rank
      if dims is not None:
          for dim in dims:
              if dim < -input_rank or dim >= input_rank:
                  raise ValueError(f"Invalid dim {dim} in `dims`.")
      if shapes is not None:
          for shape in shapes:
              if shape <= 0:
                  raise ValueError(
                      f"Invalid shape {shape} in `shapes`."
                  )
  
      # Determine if the last dim specified in dims need to be expanded. For IRFFTN, the input is
      # interpreted as a one-sided Hermitian signal in the Fourier domain, as produced by rfftn(), so
      # we need to expand the dim back to the full matrix (with conjugate part not pruned).
      last_dim_expand: bool = shapes is None and c2r
  
      if shapes is not None:
          if dims is None:
              # Has shape, no dim.
              # Default is last len(s) dimensions.
              dims = tuple(range(input_rank - len(shapes), input_rank))
          else:
              # Has shape, has dim.
              if len(shapes) != len(dims):
                  raise ValueError(
                      "shapes and dims must have the same number of elements."
                  )
          shapes = tuple(
              shape if shape != -1 else input_data.shape[dim]
              for (shape, dim) in zip(shapes, dims)
          )
      elif dims is None:
          # No shape, no dim.
          dims = tuple(range(input_rank))
          shapes = tuple(input_data.shape)
      else:
          # No shape, has dim.
          shapes = tuple(input_data.shape[dim] for dim in dims)
  
      # In RFFTN, the output is trimmed (because FFT of real-value input is Hermitian-symmetric, the
      # conjugate part is removed) to ``original_dim // 2 + 1``, so here we do the reverse
      # ``2 * (trimmed_dim - 1)`` to restore the original shape.
      if last_dim_expand:
          target_last_dim_shape = 2 * (input_data.shape[dims[-1]] - 1)
          shapes = shapes[:-1] + (target_last_dim_shape,)
  
      if len(shapes) != len(dims):
          raise ValueError(
              f"shape ({len(shapes)}) and dim ({len(dims)}) should have same number of elements."
          )
  
      return shapes, dims
  
imports: from typing import Optional, Tuple
  import numpy
  from coremltools.converters.mil.mil import Operation, types
  from coremltools.converters.mil.mil.input_type import DefaultInputs, InputSpec, TensorInputType
  from coremltools.converters.mil.mil.ops.registry import SSAOpRegistry
  from coremltools.converters.mil.mil.types.symbolic import any_symbolic, is_symbolic
  from coremltools.converters.mil.mil.types.type_mapping import infer_complex_dtype, infer_fp_dtype_from_complex
  from coremltools.converters.mil.mil.var import ComplexVar, Var
label_desc: Use image node_id 2 for calling a global function with example usage: fft_canonicalize_shapes_dims(input_data, shapes, dims, c2r) and returns: shapes,  dims