def ra_as_hours(ra_degrees, seconds_decimal_places=2):
    """ Takes Right Ascension degrees as float, returns RA string. TESTS OK 2020-10-24.
    :param ra_degrees: Right Ascension in degrees, limited to 0 through 360. [float]
    :param seconds_decimal_places: number of places at end of RA string (no period if zero). [int]
    :return: RA in hours/hex format. [string, or None if outside RA range]
    """
    if (ra_degrees < 0) | (ra_degrees > 360):
        return None
    seconds_decimal_places = int(max(0, seconds_decimal_places))  # ensure int and non-negative.
    total_ra_seconds = ra_degrees * (3600 / 15)
    int_hours = int(total_ra_seconds // 3600)
    remaining_seconds = total_ra_seconds - 3600 * int_hours
    int_minutes = int(remaining_seconds // 60)
    remaining_seconds -= 60 * int_minutes
    if seconds_decimal_places > 0:
        seconds, fract_seconds = divmod(remaining_seconds, 1)
        int_fract_seconds = int(round(fract_seconds * 10 ** seconds_decimal_places))
    else:
        seconds, fract_seconds, int_fract_seconds = round(remaining_seconds), 0, 0
    int_seconds = int(seconds)
    if seconds_decimal_places > 0:
        if int_fract_seconds >= 10 ** seconds_decimal_places:
            int_fract_seconds -= 10 ** seconds_decimal_places
            int_seconds += 1
    if int_seconds >= 60:
        int_seconds -= 60
        int_minutes += 1
    if int_minutes >= 60:
        int_minutes -= 60
        int_hours += 1
    if int_hours >= 24:
        int_hours -= 24
    if seconds_decimal_places > 0:
        format_string = '{0:02d}:{1:02d}:{2:02d}.{3:0' + str(int(seconds_decimal_places)) + 'd}'
    else:
        format_string = '{0:02d}:{1:02d}:{2:02d}'
    ra_string = format_string.format(int_hours, int_minutes, int_seconds, int_fract_seconds)
    return ra_string