code: def _read_bti_header(pdf_fname, config_fname, sort_by_ch_name=True):
      """Read bti PDF header."""
      info = (
          _read_bti_header_pdf(pdf_fname)
          if pdf_fname is not None
          else dict()
      )
      cfg = _read_config(config_fname)
      info["bti_transform"] = cfg["transforms"]
  
      # augment channel list by according info from config.
      # get channels from config present in PDF
      chans = info.get("chs", None)
      if chans is not None:
          chans_cfg = [
              c
              for c in cfg["chs"]
              if c["chan_no"] in [c_["chan_no"] for c_ in chans]
          ]
  
          # sort chans_cfg and chans
          chans = sorted(chans, key=lambda k: k["chan_no"])
          chans_cfg = sorted(chans_cfg, key=lambda k: k["chan_no"])
  
          # check all pdf channels are present in config
          match = [c["chan_no"] for c in chans_cfg] == [
              c["chan_no"] for c in chans
          ]
  
          if not match:
              raise RuntimeError(
                  "Could not match raw data channels with"
                  " config channels. Some of the channels"
                  " found are not described in config."
              )
      else:
          chans_cfg = cfg["chs"]
          chans = [dict() for _ in chans_cfg]
  
      # transfer channel info from config to channel info
      for ch, ch_cfg in zip(chans, chans_cfg):
          ch["upb"] = ch_cfg["units_per_bit"]
          ch["gain"] = ch_cfg["gain"]
          ch["name"] = ch_cfg["name"]
          if (
              ch_cfg.get("dev", dict()).get("transform", None)
              is not None
          ):
              ch["loc"] = _coil_trans_to_loc(ch_cfg["dev"]["transform"])
          else:
              ch["loc"] = np.full(12, np.nan)
          if pdf_fname is not None:
              if (
                  info["data_format"] <= 2
              ):  # see DTYPES, implies integer
                  ch["cal"] = (
                      ch["scale"] * ch["upb"] / float(ch["gain"])
                  )
              else:  # float
                  ch["cal"] = ch["scale"] * ch["gain"]
          else:  # if we are in this mode we don't read data, only channel info.
              ch["cal"] = ch[
                  "scale"
              ] = 1.0  # so we put a trivial default value
  
      if sort_by_ch_name:
          by_index = [(i, d["index"]) for i, d in enumerate(chans)]
          by_index.sort(key=lambda c: c[1])
          by_index = [idx[0] for idx in by_index]
          chs = [chans[pos] for pos in by_index]
  
          sort_by_name_idx = [(i, d["name"]) for i, d in enumerate(chs)]
          a_chs = [c for c in sort_by_name_idx if c[1].startswith("A")]
          other_chs = [
              c for c in sort_by_name_idx if not c[1].startswith("A")
          ]
          sort_by_name_idx = sorted(
              a_chs, key=lambda c: int(c[1][1:])
          ) + sorted(other_chs)
  
          sort_by_name_idx = [idx[0] for idx in sort_by_name_idx]
  
          info["chs"] = [chans[pos] for pos in sort_by_name_idx]
          info["order"] = sort_by_name_idx
      else:
          info["chs"] = chans
          info["order"] = np.arange(len(chans))
  
      # finally add some important fields from the config
      info["e_table"] = cfg["user_blocks"][BTI.UB_B_E_TABLE_USED]
      info["weights"] = cfg["user_blocks"][BTI.UB_B_WEIGHTS_USED]
  
      return info
  
imports: import functools
  import os.path
  from io import BytesIO
  from itertools import count
  import numpy
  from ..._fiff._digitization import _make_bti_dig_points
  from ..._fiff.constants import FIFF
  from ..._fiff.meas_info import _empty_info
  from ..._fiff.tag import _coil_trans_to_loc, _loc_to_coil_trans
  from ..._fiff.utils import _mult_cal_one, read_str
  from ...transforms import Transform, combine_transforms, invert_transform
  from ...utils import _stamp_to_dt, _validate_type, logger, path_like, verbose
  from ..base import BaseRaw
  from .constants import BTI
  from .read import read_char, read_dev_header, read_double, read_double_matrix, read_float, read_float_matrix, read_int16, read_int16_matrix, read_int32, read_int64, read_transform, read_uint16, read_uint32
label_desc: Use image node_id 19 for calling a global function with example usage: _read_bti_header(pdf_fname, config_fname, sort_by_ch_name) and returns: info