code: def parse_header(header):
      
      triples = []
      fields = []
      for col_str in header:
          col = col_str.strip().split(':')
          n = len(col)
          if n == 1:  # default dtype and no shape
              col = [col[0], 'float32', '']
          elif n == 2:
              if castable_to_int(col[1]):  # default dtype and shape
                  col = [col[0], 'float32', col[1]]
              else:  # dtype and no shape
                  col = [col[0], col[1], '']
          elif n > 3:
              raise ValueError('Invalid column description: %s' % col_str)
          field = col[0]
          numpytype = col[1]
          shape = () if not col[2].strip() else (int(col[2]),)
          triples.append((field, numpytype, shape))
          fields.append(field)
      return fields, numpy.dtype(triples)
docs: Convert a list of the form `['fieldname:fieldtype:fieldsize',...]`
      into a numpy composite dtype. The parser understands headers generated
      by :func:`openquake.commonlib.writers.build_header`.
      Here is an example:
  
      >>> parse_header(['PGA:float32', 'PGV', 'avg:float32:2'])
      (['PGA', 'PGV', 'avg'], dtype([('PGA', '<f4'), ('PGV', '<f4'), ('avg', '<f4', (2,))]))
  
      :params header: a list of type descriptions
      :returns: column names and the corresponding composite dtype