code: def _read_edf_header(fname, exclude, infer_types, include=None):
      """Read header information from EDF+ or BDF file."""
      edf_info = {"events": []}
  
      with open(fname, "rb") as fid:
          fid.read(8)  # version (unused here)
  
          # patient ID
          patient = {}
          id_info = fid.read(80).decode("latin-1").rstrip()
          id_info = id_info.split(" ")
          if len(id_info):
              patient["id"] = id_info[0]
              if len(id_info) >= 4:
                  try:
                      birthdate = datetime.strptime(
                          id_info[2], "%d-%b-%Y"
                      )
                  except ValueError:
                      birthdate = "X"
                  patient["sex"] = id_info[1]
                  patient["birthday"] = birthdate
                  patient["name"] = id_info[3]
                  if len(id_info) > 4:
                      for info in id_info[4:]:
                          if "=" in info:
                              key, value = info.split("=")
                              if key in ["weight", "height"]:
                                  patient[key] = float(value)
                              elif key in ["hand"]:
                                  patient[key] = int(value)
                              else:
                                  warn(
                                      f"Invalid patient information {key}"
                                  )
  
          # Recording ID
          meas_id = {}
          rec_info = fid.read(80).decode("latin-1").rstrip().split(" ")
          valid_startdate = False
          if len(rec_info) == 5:
              try:
                  startdate = datetime.strptime(rec_info[1], "%d-%b-%Y")
              except ValueError:
                  startdate = "X"
              else:
                  valid_startdate = True
              meas_id["startdate"] = startdate
              meas_id["study_id"] = rec_info[2]
              meas_id["technician"] = rec_info[3]
              meas_id["equipment"] = rec_info[4]
  
          # If startdate available in recording info, use it instead of the
          # file's meas_date since it contains all 4 digits of the year
          if valid_startdate:
              day = meas_id["startdate"].day
              month = meas_id["startdate"].month
              year = meas_id["startdate"].year
              fid.read(8)  # skip file's meas_date
          else:
              meas_date = fid.read(8).decode("latin-1")
              day, month, year = (int(x) for x in meas_date.split("."))
              year = year + 2000 if year < 85 else year + 1900
  
          meas_time = fid.read(8).decode("latin-1")
          hour, minute, sec = (int(x) for x in meas_time.split("."))
          try:
              meas_date = datetime(
                  year,
                  month,
                  day,
                  hour,
                  minute,
                  sec,
                  tzinfo=timezone.utc,
              )
          except ValueError:
              warn(
                  f"Invalid date encountered ({year:04d}-{month:02d}-"
                  f"{day:02d} {hour:02d}:{minute:02d}:{sec:02d})."
              )
              meas_date = None
  
          header_nbytes = int(_edf_str(fid.read(8)))
  
          # The following 44 bytes sometimes identify the file type, but this is
          # not guaranteed. Therefore, we skip this field and use the file
          # extension to determine the subtype (EDF or BDF, which differ in the
          # number of bytes they use for the data records; EDF uses 2 bytes
          # whereas BDF uses 3 bytes).
          fid.read(44)
          subtype = os.path.splitext(fname)[1][1:].lower()
  
          n_records = int(_edf_str(fid.read(8)))
          record_length = float(_edf_str(fid.read(8)))
          record_length = np.array([record_length, 1.0])  # in seconds
          if record_length[0] == 0:
              record_length[0] = 1.0
              warn(
                  "Header information is incorrect for record length. Default "
                  "record length set to 1.\nIt is possible that this file only"
                  " contains annotations and no signals. In that case, please "
                  "use mne.read_annotations() to load these annotations."
              )
  
          nchan = int(_edf_str(fid.read(4)))
          channels = list(range(nchan))
  
          # read in 16 byte labels and strip any extra spaces at the end
          ch_labels = [
              fid.read(16).strip().decode("latin-1") for _ in channels
          ]
  
          # get channel names and optionally channel type
          # EDF specification contains 16 bytes that encode channel names,
          # optionally prefixed by a string representing channel type separated
          # by a space
          if infer_types:
              ch_types, ch_names = [], []
              for ch_label in ch_labels:
                  ch_type, ch_name = "EEG", ch_label  # default to EEG
                  parts = ch_label.split(" ")
                  if len(parts) > 1:
                      if parts[0].upper() in CH_TYPE_MAPPING:
                          ch_type = parts[0].upper()
                          ch_name = " ".join(parts[1:])
                          logger.info(
                              f"Channel '{ch_label}' recognized as type "
                              f"{ch_type} (renamed to '{ch_name}')."
                          )
                  ch_types.append(ch_type)
                  ch_names.append(ch_name)
          else:
              ch_types, ch_names = ["EEG"] * nchan, ch_labels
  
          exclude = _find_exclude_idx(ch_names, exclude, include)
          tal_idx = _find_tal_idx(ch_names)
          exclude = np.concatenate([exclude, tal_idx])
          sel = np.setdiff1d(np.arange(len(ch_names)), exclude)
          for ch in channels:
              fid.read(80)  # transducer
          units = [
              fid.read(8).strip().decode("latin-1") for ch in channels
          ]
          edf_info["units"] = list()
          for i, unit in enumerate(units):
              if i in exclude:
                  continue
              # allow μ (greek mu), µ (micro symbol) and μ (sjis mu) codepoints
              if unit in ("\u03BCV", "\u00B5V", "\x83\xCAV", "uV"):
                  edf_info["units"].append(1e-6)
              elif unit == "mV":
                  edf_info["units"].append(1e-3)
              else:
                  edf_info["units"].append(1)
          edf_info["units"] = np.array(edf_info["units"], float)
  
          ch_names = [ch_names[idx] for idx in sel]
          units = [units[idx] for idx in sel]
  
          # make sure channel names are unique
          ch_names = _unique_channel_names(ch_names)
          orig_units = dict(zip(ch_names, units))
  
          physical_min = np.array(
              [float(_edf_str_num(fid.read(8))) for ch in channels]
          )[sel]
          physical_max = np.array(
              [float(_edf_str_num(fid.read(8))) for ch in channels]
          )[sel]
          digital_min = np.array(
              [float(_edf_str_num(fid.read(8))) for ch in channels]
          )[sel]
          digital_max = np.array(
              [float(_edf_str_num(fid.read(8))) for ch in channels]
          )[sel]
          prefiltering = [
              _edf_str(fid.read(80)).strip() for ch in channels
          ][:-1]
          highpass, lowpass = _parse_prefilter_string(prefiltering)
  
          # number of samples per record
          n_samps = np.array(
              [int(_edf_str(fid.read(8))) for ch in channels]
          )
  
          # Populate edf_info
          edf_info.update(
              ch_names=ch_names,
              ch_types=ch_types,
              data_offset=header_nbytes,
              digital_max=digital_max,
              digital_min=digital_min,
              highpass=highpass,
              sel=sel,
              lowpass=lowpass,
              meas_date=meas_date,
              n_records=n_records,
              n_samps=n_samps,
              nchan=nchan,
              subject_info=patient,
              physical_max=physical_max,
              physical_min=physical_min,
              record_length=record_length,
              subtype=subtype,
              tal_idx=tal_idx,
          )
  
          fid.read(32 * nchan).decode()  # reserved
          assert fid.tell() == header_nbytes
  
          fid.seek(0, 2)
          n_bytes = fid.tell()
          n_data_bytes = n_bytes - header_nbytes
          total_samps = (
              n_data_bytes // 3
              if subtype == "bdf"
              else n_data_bytes // 2
          )
          read_records = total_samps // np.sum(n_samps)
          if n_records != read_records:
              warn(
                  "Number of records from the header does not match the file "
                  "size (perhaps the recording was not stopped before exiting)."
                  " Inferring from the file size."
              )
              edf_info["n_records"] = read_records
          del n_records
  
          if subtype == "bdf":
              edf_info["dtype_byte"] = 3  # 24-bit (3 byte) integers
              edf_info["dtype_np"] = UINT8
          else:
              edf_info["dtype_byte"] = 2  # 16-bit (2 byte) integers
              edf_info["dtype_np"] = INT16
  
      return edf_info, orig_units
  
imports: import os
  import re
  from datetime import datetime, timedelta, timezone
  import numpy
  from scipy.interpolate import interp1d
  from ..._fiff.constants import FIFF
  from ..._fiff.meas_info import _empty_info, _unique_channel_names
  from ..._fiff.utils import _blk_read_lims, _mult_cal_one
  from ...annotations import Annotations
  from ...filter import resample
  from ...utils import _validate_type, fill_doc, logger, verbose, warn
  from ..base import BaseRaw, _get_scaling
label_desc: Use image node_id 8 for calling a global function with example usage: _read_edf_header(fname, exclude, infer_types, include) and returns: edf_info,  orig_units