docs: def _read_header(f, header_param):
      """
      Read and parse data from 1st line of a file.
  
      :param f: :func:`file` or :class:`~StringIO.StringIO` object from which to
          read 1st line.
      :type f: file
      :param header_param: Parameters used to parse the data from the header.
          Contains "delimiter" and "fields".
      :type header_param: dict
      :returns: Dictionary of data read from header.
      :rtype: dict
      :raises: :exc:`~simkit.core.exceptions.UnnamedDataError`
  
      The **header_param** argument contains keys to read the 1st line of **f**.
      If "delimiter" is ``None`` or missing, the default delimiter is a comma,
      otherwise "delimiter" can be any single character, integer or sequence of
      ``int``.
  
      * single character -- a delimiter
      * single integer -- uniform fixed width
      * sequence of ``int`` -- fixed widths, the number of fields should \
          correspond to the length of the sequence.
  
      The "fields" key is a list of (parameter-name, parameter-type[, parameter-
      units]) lists.
      """
      # default delimiter is a comma, can't be None
      header_delim = str(header_param.get('delimiter', ','))
      # don't allow unnamed fields
      if 'fields' not in header_param:
          raise UnnamedDataError(f.name)
      header_fields = {field[0]: field[1:] for field in header_param['fields']}
      # header_names can't be generator b/c DictReader needs list, and can't be
      # dictionary b/c must be same order as 'fields' to match data readby csv
      header_names = [field[0] for field in header_param['fields']]
      # read header
      header_str = StringIO(f.readline())  # read the 1st line
      # use csv because it will preserve quoted fields with commas
      # make a csv.DictReader from header string, use header names for
      # fieldnames and set delimiter to header delimiter
      header_reader = csv.DictReader(header_str, header_names,
                                     delimiter=header_delim,
                                     skipinitialspace=True)
      data = header_reader.next()  # parse the header dictionary
      # iterate over items in data
      for k, v in data.iteritems():
          header_type = header_fields[k][0]  # spec'd type
          # whitelist header types
          if isinstance(header_type, basestring):
              if header_type.lower().startswith('int'):
                  header_type = int  # coerce to integer
              elif header_type.lower().startswith('long'):
                  header_type = long  # coerce to long integer
              elif header_type.lower().startswith('float'):
                  header_type = float  # to floating decimal point
              elif header_type.lower().startswith('str'):
                  header_type = str  # coerce to string
              elif header_type.lower().startswith('bool'):
                  header_type = bool  # coerce to boolean
              else:
                  raise TypeError('"%s" is not a supported type.' % header_type)
              # WARNING! Use of `eval` considered harmful. `header_type` is read
              # from JSON file, not secure input, could be used to exploit system
          data[k] = header_type(v)  # cast v to type
          # check for units in 3rd element
          if len(header_fields[k]) > 1:
              units = UREG(str(header_fields[k][1]))  # spec'd units
              data[k] = data[k] * units  # apply units
      return data