code: def _read_gdf_header(fname, exclude, include=None):
      """Read GDF 1.x and GDF 2.x header info."""
      edf_info = dict()
      events = None
      with open(fname, "rb") as fid:
          version = fid.read(8).decode()
          edf_info["type"] = edf_info["subtype"] = version[:3]
          edf_info["number"] = float(version[4:])
          meas_date = None
  
          # GDF 1.x
          # ---------------------------------------------------------------------
          if edf_info["number"] < 1.9:
              # patient ID
              pid = fid.read(80).decode("latin-1")
              pid = pid.split(" ", 2)
              patient = {}
              if len(pid) >= 2:
                  patient["id"] = pid[0]
                  patient["name"] = pid[1]
  
              # Recording ID
              meas_id = {}
              meas_id["recording_id"] = _edf_str(fid.read(80)).strip()
  
              # date
              tm = _edf_str(fid.read(16)).strip()
              try:
                  if tm[14:16] == "  ":
                      tm = tm[:14] + "00" + tm[16:]
                  meas_date = datetime(
                      int(tm[0:4]),
                      int(tm[4:6]),
                      int(tm[6:8]),
                      int(tm[8:10]),
                      int(tm[10:12]),
                      int(tm[12:14]),
                      int(tm[14:16]) * pow(10, 4),
                      tzinfo=timezone.utc,
                  )
              except Exception:
                  pass
  
              header_nbytes = np.fromfile(fid, INT64, 1)[0]
              meas_id["equipment"] = np.fromfile(fid, UINT8, 8)[0]
              meas_id["hospital"] = np.fromfile(fid, UINT8, 8)[0]
              meas_id["technician"] = np.fromfile(fid, UINT8, 8)[0]
              fid.seek(20, 1)  # 20bytes reserved
  
              n_records = np.fromfile(fid, INT64, 1)[0]
              # record length in seconds
              record_length = np.fromfile(fid, UINT32, 2)
              if record_length[0] == 0:
                  record_length[0] = 1.0
                  warn(
                      "Header information is incorrect for record length. "
                      "Default record length set to 1."
                  )
              nchan = int(np.fromfile(fid, UINT32, 1)[0])
              channels = list(range(nchan))
              ch_names = [
                  _edf_str(fid.read(16)).strip() for ch in channels
              ]
              exclude = _find_exclude_idx(ch_names, exclude, include)
              sel = np.setdiff1d(np.arange(len(ch_names)), exclude)
              fid.seek(80 * len(channels), 1)  # transducer
              units = [_edf_str(fid.read(8)).strip() for ch in channels]
              edf_info["units"] = list()
              for i, unit in enumerate(units):
                  if i in exclude:
                      continue
                  if unit[:2] == "uV":
                      edf_info["units"].append(1e-6)
                  else:
                      edf_info["units"].append(1)
              edf_info["units"] = np.array(edf_info["units"], float)
  
              ch_names = [ch_names[idx] for idx in sel]
              physical_min = np.fromfile(fid, FLOAT64, len(channels))
              physical_max = np.fromfile(fid, FLOAT64, len(channels))
              digital_min = np.fromfile(fid, INT64, len(channels))
              digital_max = np.fromfile(fid, INT64, len(channels))
              prefiltering = [
                  _edf_str(fid.read(80)) for ch in channels
              ][:-1]
              highpass, lowpass = _parse_prefilter_string(prefiltering)
  
              # n samples per record
              n_samps = np.fromfile(fid, INT32, len(channels))
  
              # channel data type
              dtype = np.fromfile(fid, INT32, len(channels))
  
              # total number of bytes for data
              bytes_tot = np.sum(
                  [
                      GDFTYPE_BYTE[t] * n_samps[i]
                      for i, t in enumerate(dtype)
                  ]
              )
  
              # Populate edf_info
              dtype_np, dtype_byte = _check_dtype_byte(dtype)
              edf_info.update(
                  bytes_tot=bytes_tot,
                  ch_names=ch_names,
                  data_offset=header_nbytes,
                  digital_min=digital_min,
                  digital_max=digital_max,
                  dtype_byte=dtype_byte,
                  dtype_np=dtype_np,
                  exclude=exclude,
                  highpass=highpass,
                  sel=sel,
                  lowpass=lowpass,
                  meas_date=meas_date,
                  meas_id=meas_id,
                  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,
              )
  
              fid.seek(32 * edf_info["nchan"], 1)  # reserved
              assert fid.tell() == header_nbytes
  
              # Event table
              # -----------------------------------------------------------------
              etp = header_nbytes + n_records * edf_info["bytes_tot"]
              # skip data to go to event table
              fid.seek(etp)
              etmode = np.fromfile(fid, UINT8, 1)[0]
              if etmode in (1, 3):
                  sr = np.fromfile(fid, UINT8, 3).astype(np.uint32)
                  event_sr = sr[0]
                  for i in range(1, len(sr)):
                      event_sr = event_sr + sr[i] * 2 ** (i * 8)
                  n_events = np.fromfile(fid, UINT32, 1)[0]
                  pos = (
                      np.fromfile(fid, UINT32, n_events) - 1
                  )  # 1-based inds
                  typ = np.fromfile(fid, UINT16, n_events)
  
                  if etmode == 3:
                      chn = np.fromfile(fid, UINT16, n_events)
                      dur = np.fromfile(fid, UINT32, n_events)
                  else:
                      chn = np.zeros(n_events, dtype=np.int32)
                      dur = np.ones(n_events, dtype=UINT32)
                  np.maximum(dur, 1, out=dur)
                  events = [n_events, pos, typ, chn, dur]
  
          # GDF 2.x
          # ---------------------------------------------------------------------
          else:
              # FIXED HEADER
              handedness = ("Unknown", "Right", "Left", "Equal")
              gender = ("Unknown", "Male", "Female")
              scale = ("Unknown", "No", "Yes", "Corrected")
  
              # date
              pid = fid.read(66).decode()
              pid = pid.split(" ", 2)
              patient = {}
              if len(pid) >= 2:
                  patient["id"] = pid[0]
                  patient["name"] = pid[1]
              fid.seek(10, 1)  # 10bytes reserved
  
              # Smoking / Alcohol abuse / drug abuse / medication
              sadm = np.fromfile(fid, UINT8, 1)[0]
              patient["smoking"] = scale[sadm % 4]
              patient["alcohol_abuse"] = scale[(sadm >> 2) % 4]
              patient["drug_abuse"] = scale[(sadm >> 4) % 4]
              patient["medication"] = scale[(sadm >> 6) % 4]
              patient["weight"] = np.fromfile(fid, UINT8, 1)[0]
              if patient["weight"] == 0 or patient["weight"] == 255:
                  patient["weight"] = None
              patient["height"] = np.fromfile(fid, UINT8, 1)[0]
              if patient["height"] == 0 or patient["height"] == 255:
                  patient["height"] = None
  
              # Gender / Handedness / Visual Impairment
              ghi = np.fromfile(fid, UINT8, 1)[0]
              patient["sex"] = gender[ghi % 4]
              patient["handedness"] = handedness[(ghi >> 2) % 4]
              patient["visual"] = scale[(ghi >> 4) % 4]
  
              # Recording identification
              meas_id = {}
              meas_id["recording_id"] = _edf_str(fid.read(64)).strip()
              vhsv = np.fromfile(fid, UINT8, 4)
              loc = {}
              if vhsv[3] == 0:
                  loc["vertpre"] = 10 * int(vhsv[0] >> 4) + int(
                      vhsv[0] % 16
                  )
                  loc["horzpre"] = 10 * int(vhsv[1] >> 4) + int(
                      vhsv[1] % 16
                  )
                  loc["size"] = 10 * int(vhsv[2] >> 4) + int(
                      vhsv[2] % 16
                  )
              else:
                  loc["vertpre"] = 29
                  loc["horzpre"] = 29
                  loc["size"] = 29
              loc["version"] = 0
              loc["latitude"] = (
                  float(np.fromfile(fid, UINT32, 1)[0]) / 3600000
              )
              loc["longitude"] = (
                  float(np.fromfile(fid, UINT32, 1)[0]) / 3600000
              )
              loc["altitude"] = (
                  float(np.fromfile(fid, INT32, 1)[0]) / 100
              )
              meas_id["loc"] = loc
  
              meas_date = np.fromfile(fid, UINT64, 1)[0]
              if meas_date != 0:
                  meas_date = datetime(
                      1, 1, 1, tzinfo=timezone.utc
                  ) + timedelta(meas_date * pow(2, -32) - 367)
              else:
                  meas_date = None
  
              birthday = np.fromfile(fid, UINT64, 1).tolist()[0]
              if birthday == 0:
                  birthday = datetime(1, 1, 1, tzinfo=timezone.utc)
              else:
                  birthday = datetime(
                      1, 1, 1, tzinfo=timezone.utc
                  ) + timedelta(birthday * pow(2, -32) - 367)
              patient["birthday"] = birthday
              if patient["birthday"] != datetime(
                  1, 1, 1, 0, 0, tzinfo=timezone.utc
              ):
                  today = datetime.now(tz=timezone.utc)
                  patient["age"] = today.year - patient["birthday"].year
                  today = today.replace(year=patient["birthday"].year)
                  if today < patient["birthday"]:
                      patient["age"] -= 1
              else:
                  patient["age"] = None
  
              header_nbytes = np.fromfile(fid, UINT16, 1)[0] * 256
  
              fid.seek(6, 1)  # 6 bytes reserved
              meas_id["equipment"] = np.fromfile(fid, UINT8, 8)
              meas_id["ip"] = np.fromfile(fid, UINT8, 6)
              patient["headsize"] = np.fromfile(fid, UINT16, 3)
              patient["headsize"] = np.asarray(
                  patient["headsize"], np.float32
              )
              patient["headsize"] = np.ma.masked_array(
                  patient["headsize"],
                  np.equal(patient["headsize"], 0),
                  None,
              ).filled()
              ref = np.fromfile(fid, FLOAT32, 3)
              gnd = np.fromfile(fid, FLOAT32, 3)
              n_records = np.fromfile(fid, INT64, 1)[0]
  
              # record length in seconds
              record_length = np.fromfile(fid, UINT32, 2)
              if record_length[0] == 0:
                  record_length[0] = 1.0
                  warn(
                      "Header information is incorrect for record length. "
                      "Default record length set to 1."
                  )
  
              nchan = int(np.fromfile(fid, UINT16, 1)[0])
              fid.seek(2, 1)  # 2bytes reserved
  
              # Channels (variable header)
              channels = list(range(nchan))
              ch_names = [
                  _edf_str(fid.read(16)).strip() for ch in channels
              ]
              exclude = _find_exclude_idx(ch_names, exclude, include)
              sel = np.setdiff1d(np.arange(len(ch_names)), exclude)
  
              fid.seek(80 * len(channels), 1)  # reserved space
              fid.seek(6 * len(channels), 1)  # phys_dim, obsolete
  
              """The Physical Dimensions are encoded as int16, according to:
              - Units codes :
              https://sourceforge.net/p/biosig/svn/HEAD/tree/trunk/biosig/doc/units.csv
              - Decimal factors codes:
              https://sourceforge.net/p/biosig/svn/HEAD/tree/trunk/biosig/doc/DecimalFactors.txt
              """  # noqa
              units = np.fromfile(fid, UINT16, len(channels)).tolist()
              unitcodes = np.array(units[:])
              edf_info["units"] = list()
              for i, unit in enumerate(units):
                  if i in exclude:
                      continue
                  if unit == 4275:  # microvolts
                      edf_info["units"].append(1e-6)
                  elif unit == 4274:  # millivolts
                      edf_info["units"].append(1e-3)
                  elif unit == 512:  # dimensionless
                      edf_info["units"].append(1)
                  elif unit == 0:
                      edf_info["units"].append(1)  # unrecognized
                  else:
                      warn(
                          "Unsupported physical dimension for channel %d "
                          "(assuming dimensionless). Please contact the "
                          "MNE-Python developers for support." % i
                      )
                      edf_info["units"].append(1)
              edf_info["units"] = np.array(edf_info["units"], float)
  
              ch_names = [ch_names[idx] for idx in sel]
              physical_min = np.fromfile(fid, FLOAT64, len(channels))
              physical_max = np.fromfile(fid, FLOAT64, len(channels))
              digital_min = np.fromfile(fid, FLOAT64, len(channels))
              digital_max = np.fromfile(fid, FLOAT64, len(channels))
  
              fid.seek(68 * len(channels), 1)  # obsolete
              lowpass = np.fromfile(fid, FLOAT32, len(channels))
              highpass = np.fromfile(fid, FLOAT32, len(channels))
              notch = np.fromfile(fid, FLOAT32, len(channels))
  
              # number of samples per record
              n_samps = np.fromfile(fid, INT32, len(channels))
  
              # data type
              dtype = np.fromfile(fid, INT32, len(channels))
  
              channel = {}
              channel["xyz"] = [
                  np.fromfile(fid, FLOAT32, 3)[0] for ch in channels
              ]
  
              if edf_info["number"] < 2.19:
                  impedance = np.fromfile(
                      fid, UINT8, len(channels)
                  ).astype(float)
                  impedance[impedance == 255] = np.nan
                  channel["impedance"] = pow(2, impedance / 8)
                  fid.seek(19 * len(channels), 1)  # reserved
              else:
                  tmp = np.fromfile(fid, FLOAT32, 5 * len(channels))
                  tmp = tmp[::5]
                  fZ = tmp[:]
                  impedance = tmp[:]
                  # channels with no voltage (code 4256) data
                  ch = [unitcodes & 65504 != 4256][0]
                  impedance[np.where(ch)] = None
                  # channel with no impedance (code 4288) data
                  ch = [unitcodes & 65504 != 4288][0]
                  fZ[np.where(ch)[0]] = None
  
              assert fid.tell() == header_nbytes
  
              # total number of bytes for data
              bytes_tot = np.sum(
                  [
                      GDFTYPE_BYTE[t] * n_samps[i]
                      for i, t in enumerate(dtype)
                  ]
              )
  
              # Populate edf_info
              dtype_np, dtype_byte = _check_dtype_byte(dtype)
              edf_info.update(
                  bytes_tot=bytes_tot,
                  ch_names=ch_names,
                  data_offset=header_nbytes,
                  dtype_byte=dtype_byte,
                  dtype_np=dtype_np,
                  digital_min=digital_min,
                  digital_max=digital_max,
                  exclude=exclude,
                  gnd=gnd,
                  highpass=highpass,
                  sel=sel,
                  impedance=impedance,
                  lowpass=lowpass,
                  meas_date=meas_date,
                  meas_id=meas_id,
                  n_records=n_records,
                  n_samps=n_samps,
                  nchan=nchan,
                  notch=notch,
                  subject_info=patient,
                  physical_max=physical_max,
                  physical_min=physical_min,
                  record_length=record_length,
                  ref=ref,
              )
  
              # EVENT TABLE
              # -----------------------------------------------------------------
              etp = (
                  edf_info["data_offset"]
                  + edf_info["n_records"] * edf_info["bytes_tot"]
              )
              fid.seek(etp)  # skip data to go to event table
              etmode = fid.read(1).decode()
              if etmode != "":
                  etmode = np.fromstring(etmode, UINT8).tolist()[0]
  
                  if edf_info["number"] < 1.94:
                      sr = np.fromfile(fid, UINT8, 3)
                      event_sr = sr[0]
                      for i in range(1, len(sr)):
                          event_sr = event_sr + sr[i] * 2 ** (i * 8)
                      n_events = np.fromfile(fid, UINT32, 1)[0]
                  else:
                      ne = np.fromfile(fid, UINT8, 3)
                      n_events = ne[0]
                      for i in range(1, len(ne)):
                          n_events = n_events + ne[i] * 2 ** (i * 8)
                      event_sr = np.fromfile(fid, FLOAT32, 1)[0]
  
                  pos = (
                      np.fromfile(fid, UINT32, n_events) - 1
                  )  # 1-based inds
                  typ = np.fromfile(fid, UINT16, n_events)
  
                  if etmode == 3:
                      chn = np.fromfile(fid, UINT16, n_events)
                      dur = np.fromfile(fid, UINT32, n_events)
                  else:
                      chn = np.zeros(n_events, dtype=np.uint32)
                      dur = np.ones(n_events, dtype=np.uint32)
                  np.maximum(dur, 1, out=dur)
                  events = [n_events, pos, typ, chn, dur]
                  edf_info["event_sfreq"] = event_sr
  
      edf_info.update(
          events=events, sel=np.arange(len(edf_info["ch_names"]))
      )
  
      return edf_info
  
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 10 for calling a global function with example usage: _read_gdf_header(fname, exclude, include) and returns: edf_info