code: def _truncation_checks(general_info, image_defs, permit_truncated):
      """Check for presence of truncation in PAR file parameters
  
      Raise error if truncation present and `permit_truncated` is False.
      """
  
      def _err_or_warn(msg):
          if not permit_truncated:
              raise PARRECError(msg)
          warnings.warn(msg)
  
      def _chk_trunc(idef_name, gdef_max_name):
          if gdef_max_name not in general_info:
              return
          id_values = image_defs[idef_name + " number"]
          n_have = len(set(id_values))
          n_expected = general_info[gdef_max_name]
          if n_have != n_expected:
              _err_or_warn(
                  f"Header inconsistency: Found {n_have} {idef_name} "
                  f"values, but expected {n_expected}"
              )
  
      _chk_trunc("slice", "max_slices")
      _chk_trunc("echo", "max_echoes")
      _chk_trunc("dynamic scan", "max_dynamics")
      _chk_trunc("diffusion b value", "max_diffusion_values")
      _chk_trunc("gradient orientation", "max_gradient_orient")
  
      # Final check for partial volumes
      if not np.all(
          vol_is_full(
              image_defs["slice number"], general_info["max_slices"]
          )
      ):
          _err_or_warn("Found one or more partial volume(s)")
  
imports: import re
  import warnings
  from collections import OrderedDict
  from copy import deepcopy
  from io import StringIO
  from locale import getpreferredencoding
  import numpy
  from .affines import apply_affine, dot_reduce, from_matvec
  from .eulerangles import euler2mat
  from .fileslice import fileslice, strided_scalar
  from .nifti1 import unit_codes
  from .openers import ImageOpener
  from .spatialimages import SpatialHeader, SpatialImage
  from .volumeutils import Recoder, array_from_file
label_desc: Use image node_id 6 for calling a global function with example usage: _truncation_checks(general_info, image_defs, permit_truncated) without return types