'Given the keyword arguments used to initialize a Column, specifically
those that typically read from a FITS header (so excluding array),
verify that each keyword has a valid value.
Returns a 2-tuple of dicts.  The first maps valid keywords to their
values.  The second maps invalid keywords to a 2-tuple of their value,
and a message explaining why they were found invalid.'

@classmethod
def _verify_keywords(cls, name=None, format=None, unit=None, null=None, bscale=None, bzero=None, disp=None, start=None, dim=None, ascii=None, coord_type=None, coord_unit=None, coord_ref_point=None, coord_ref_value=None, coord_inc=None, time_ref_pos=None):

    valid = {}
    invalid = {}
    (format, recformat) = cls._determine_formats(format, start, dim, ascii)
    valid.update(format=format, recformat=recformat)
    for (k, v) in [('name', name), ('unit', unit), ('bscale', bscale), ('bzero', bzero)]:
        if ((v is not None) and (v != '')):
            valid[k] = v
    if ((null is not None) and (null != '')):
        msg = None
        if isinstance(format, _AsciiColumnFormat):
            null = str(null)
            if (len(null) > format.width):
                msg = "ASCII    table    null    option    (TNULLn)    is    longer    than    the    column's    character    width    and    will    be    truncated    (got    {!r}).".format(null)
        else:
            tnull_formats = ('B', 'I', 'J', 'K')
            if (not _is_int(null)):
                msg = 'Column    null    option    (TNULLn)    must    be    an    integer    for    binary    table    columns    (got    {!r}).        The    invalid    value    will    be    ignored    for    the    purpose    of    formatting    the    data    in    this    column.'.format(null)
            elif (not ((format.format in tnull_formats) or ((format.format in ('P', 'Q')) and (format.p_format in tnull_formats)))):
                msg = 'Column    null    option    (TNULLn)    is    invalid    for    binary    table    columns    of    type    {!r}    (got    {!r}).        The    invalid    value    will    be    ignored    for    the    purpose    of    formatting    the    data    in    this    column.'.format(format, null)
        if (msg is None):
            valid['null'] = null
        else:
            invalid['null'] = (null, msg)
    if ((disp is not None) and (disp != '')):
        msg = None
        if (not isinstance(disp, string_types)):
            msg = 'Column    disp    option    (TDISPn)    must    be    a    string    (got    {!r}).The    invalid    value    will    be    ignored    for    the    purpose    of    formatting    the    data    in    this    column.'.format(disp)
        elif (isinstance(format, _AsciiColumnFormat) and (disp[0].upper() == 'L')):
            msg = "Column    disp    option    (TDISPn)    may    not    use    the    'L'    format    with    ASCII    table    columns.        The    invalid    value    will    be    ignored    for    the    purpose    of    formatting    the    data    in    this    column."
        if (msg is None):
            valid['disp'] = disp
        else:
            invalid['disp'] = (disp, msg)
    if ((start is not None) and (start != '')):
        msg = None
        if (not isinstance(format, _AsciiColumnFormat)):
            msg = 'Column    start    option    (TBCOLn)    is    not    allowed    for    binary    table    columns    (got    {!r}).        The    invalid    keyword    will    be    ignored    for    the    purpose    of    formatting    the    data    in    this    column.'.format(start)
        else:
            try:
                start = int(start)
            except (TypeError, ValueError):
                pass
            if ((not _is_int(start)) or (start < 1)):
                msg = 'Column    start    option    (TBCOLn)    must    be    a    positive    integer    (got    {!r}).        The    invalid    value    will    be    ignored    for    the    purpose    of    formatting    the    data    in    this    column.'.format(start)
        if (msg is None):
            valid['start'] = start
        else:
            invalid['start'] = (start, msg)
    if ((dim is not None) and (dim != '')):
        msg = None
        dims_tuple = tuple()
        if isinstance(format, _AsciiColumnFormat):
            msg = 'Column    dim    option    (TDIMn)    is    not    allowed    for    ASCII    table    columns    (got    {!r}).        The    invalid    keyword    will    be    ignored    for    the    purpose    of    formatting    this    column.'.format(dim)
        elif isinstance(dim, string_types):
            dims_tuple = _parse_tdim(dim)
        elif isinstance(dim, tuple):
            dims_tuple = dim
        else:
            msg = '`dim`    argument    must    be    a    string    containing    a    valid    value    for    the    TDIMn    header    keyword    associated    with    this    column,    or    a    tuple    containing    the    C-order    dimensions    for    the    column.        The    invalid    value    will    be    ignored    for    the    purpose    of    formatting    this    column.'
        if dims_tuple:
            if (reduce(operator.mul, dims_tuple) > format.repeat):
                msg = 'The    repeat    count    of    the    column    format    {!r}    for    column    {!r}    is    fewer    than    the    number    of    elements    per    the    TDIM    argument    {!r}.        The    invalid    TDIMn    value    will    be    ignored    for    the    purpose    of    formatting    this    column.'.format(name, format, dim)
        if (msg is None):
            valid['dim'] = dims_tuple
        else:
            invalid['dim'] = (dim, msg)
    if ((coord_type is not None) and (coord_type != '')):
        msg = None
        if (not isinstance(coord_type, string_types)):
            msg = 'Coordinate/axis    type    option    (TCTYPn)    must    be    a    string    (got    {!r}).    The    invalid    keyword    will    be    ignored    for    the    purpose    of    formatting    this    column.'.format(coord_type)
        elif (len(coord_type) > 8):
            msg = 'Coordinate/axis    type    option    (TCTYPn)    must    be    a    string    of    atmost    8    characters    (got    {!r}).    The    invalid    keyword    will    be    ignored    for    the    purpose    of    formatting    this    column.'.format(coord_type)
        if (msg is None):
            valid['coord_type'] = coord_type
        else:
            invalid['coord_type'] = (coord_type, msg)
    if ((coord_unit is not None) and (coord_unit != '')):
        msg = None
        if (not isinstance(coord_unit, string_types)):
            msg = 'Coordinate/axis    unit    option    (TCUNIn)    must    be    a    string    (got    {!r}).    The    invalid    keyword    will    be    ignored    for    the    purpose    of    formatting    this    column.'.format(coord_unit)
        if (msg is None):
            valid['coord_unit'] = coord_unit
        else:
            invalid['coord_unit'] = (coord_unit, msg)
    for (k, v) in [('coord_ref_point', coord_ref_point), ('coord_ref_value', coord_ref_value), ('coord_inc', coord_inc)]:
        if ((v is not None) and (v != '')):
            msg = None
            if (not isinstance(v, numbers.Real)):
                msg = 'Column    {}    option    ({}n)    must    be    a    real    floating    type    (got    {!r}).    The    invalid    value    will    be    ignored    for    the    purpose    of    formatting    the    data    in    this    column.'.format(k, ATTRIBUTE_TO_KEYWORD[k], v)
            if (msg is None):
                valid[k] = v
            else:
                invalid[k] = (v, msg)
    if ((time_ref_pos is not None) and (time_ref_pos != '')):
        msg = None
        if (not isinstance(time_ref_pos, string_types)):
            msg = 'Time    coordinate    reference    position    option    (TRPOSn)    must    be    a    string    (got    {!r}).    The    invalid    keyword    will    be    ignored    for    the    purpose    of    formatting    this    column.'.format(time_ref_pos)
        if (msg is None):
            valid['time_ref_pos'] = time_ref_pos
        else:
            invalid['time_ref_pos'] = (time_ref_pos, msg)
    return (valid, invalid)
