Format a latitudinal angle as sexagesimal degrees in a string.

    Arguments are:

    radians
      The angle, in radians.
    norm (default "raise")
      The normalization mode, used for angles outside of the standard range
      of -π/2 to π/2. If "none", the value is formatted ignoring any potential
      problems. If "wrap", it is wrapped to lie within the standard range.
      If "raise", a :exc:`ValueError` is raised.
    precision (default 2)
      The number of decimal places in the "arcseconds" place to use in the
      formatted string.
    seps (default "::")
      A two- or three-item iterable, used to separate the degrees, arcminutes,
      and arcseconds components. If a third element is present, it appears
      after the arcseconds component. Specifying "dms" yields something like
      "+12d34m56s"; specifying ``['', '']`` yields something like "123456".

    Returns a string. The return value always includes a plus or minus sign.
    Note that the default of *norm* is different than in :func:`fmthours` and
    :func:`fmtdeglon` since it's not so clear what a "latitude" of 110 degrees
    (e.g.) means.

def fmtdeglat (radians, norm='raise', precision=2, seps='::'):
    """Format a latitudinal angle as sexagesimal degrees in a string.

    Arguments are:

    radians
      The angle, in radians.
    norm (default "raise")
      The normalization mode, used for angles outside of the standard range
      of -π/2 to π/2. If "none", the value is formatted ignoring any potential
      problems. If "wrap", it is wrapped to lie within the standard range.
      If "raise", a :exc:`ValueError` is raised.
    precision (default 2)
      The number of decimal places in the "arcseconds" place to use in the
      formatted string.
    seps (default "::")
      A two- or three-item iterable, used to separate the degrees, arcminutes,
      and arcseconds components. If a third element is present, it appears
      after the arcseconds component. Specifying "dms" yields something like
      "+12d34m56s"; specifying ``['', '']`` yields something like "123456".

    Returns a string. The return value always includes a plus or minus sign.
    Note that the default of *norm* is different than in :func:`fmthours` and
    :func:`fmtdeglon` since it's not so clear what a "latitude" of 110 degrees
    (e.g.) means.

    """
    if norm == 'none':
        pass
    elif norm == 'raise':
        if radians > halfpi or radians < -halfpi:
            raise ValueError ('illegal latitude of %f radians' % radians)
    elif norm == 'wrap':
        radians = angcen (radians)
        if radians > halfpi:
            radians = pi - radians
        elif radians < -halfpi:
            radians = -pi - radians
    else:
        raise ValueError ('unrecognized normalization type "%s"' % norm)

    if len (seps) < 2:
        # To ponder: we accept len(seps) > 3; seems OK.
        raise ValueError ('there must be at least two sexagesimal separators; '
                          'got value "%s"' % seps)

    precision = max (int (precision), 0)
    if precision == 0:
        width = 2
    else:
        width = precision + 3

    degrees = radians * R2D

    if degrees >= 0:
        sgn = '+'
    else:
        sgn = '-'
        degrees = -degrees

    deg = int (np.floor (degrees))
    amin = int (np.floor ((degrees - deg) * 60))
    asec = round (3600 * (degrees - deg - amin / 60.), precision)

    if asec >= 60:
        # Can happen if we round up
        asec -= 60
        amin += 1

        if amin >= 60:
            amin -= 60
            deg += 1

    if len (seps) > 2:
        sep2 = seps[2]
    else:
        sep2 = ''

    return '%s%02d%s%02d%s%0*.*f%s' % \
        (sgn, deg, seps[0], amin, seps[1], width, precision, asec, sep2)