import math


def round_float(plotgui, value, minimum_flag):
    """
    Round a floating point value to the nearest significant figure.

    If the plotgui.matplotlib_rounding flag is False this performs rounding of
    floating point values to convenient values for such things as
    calculating plot ranges.  In some cases the matplotlib rounding is
    not very good so this is provided as a way to get better results.
    When one is using a logarithmic scaling the matplotlib ropunding is
    not always good, for example, and this routine can do better.  In
    other cases this routine does not work as well, such as when the
    total range of values on the plot is small.

    Parmeters
    ---------
        plotgui :       A matplotlib_user_interface object

        value :         A floating point number to be rounded off

        minimum_flag :  A boolean value value to determine whether the
                        value should be rounded down.  If True values
                        are rounded down as one wishes for the minimum
                        value in a plot, and if False values are rounded
                        up as one wishes for the maximum value in a plot.

    Returns
    -------
       rounded_value :    The rounded off floating point number calculated
                          from `value', or the input value in the case
                          where the plotgui.matplotlib_routine flag is True.

    The code differs from use of the floor and ceil functions in that
    it tries to round to the nearest significant figure for a given
    value.  So passing in a value of 1.2e-08, for exmaple, with
    minimum_flag = False returns 2.0e-08, and if the flag is True it
    returns 1.0e-08.

    The code uses the math log10, floor, and ceil functions.

    """
    if plotgui.matplotlib_rounding.get():
        return value
    if value == 0.:
        return value
    if value < 0.:
        sign = -1.
        value1 = -value
    else:
        sign = 1.
        value1 = value
    power = math.log10(value1)
    if power < 0.:
        exp = int(power-1.)
    else:
        exp = int(power)
    shift = 10.**exp
    x = value1/shift
    delx = 1.0
    if x < 1.7:
        x = x*10.
        shift = shift/10.
    elif x < 2.5:
        x = x*5.
        shift = shift/5.
    if (minimum_flag) and sign > 0.:
        x = math.floor(x)
    elif (minimum_flag) and sign < 0.:
        x = math.ceil(x)
    elif (not minimum_flag) and sign > 0.:
        x = math.ceil(x)
    elif (not minimum_flag) and sign < 0.:
        x = math.floor(x)
    rounded_value = x*shift*sign
    # If the rounded value is very close to the input value, offset
    # by one unit in x...not normally part of the routine, but needed
    # for matplotlib plots because of symbols close to the edges of
    # the plot.
    ratio = abs(value/rounded_value)
    if (ratio > 0.97) and (ratio < 1.03):
        if (minimum_flag) and sign > 0.:
            rounded_value = (x-delx)*shift*sign
        elif (minimum_flag) and sign < 0.:
            rounded_value = (x+delx)*shift*sign
        elif (not minimum_flag) and sign > 0.:
            rounded_value = (x+delx)*shift*sign
        elif (not minimum_flag) and sign < 0.:
            rounded_value = (x-delx)*shift*sign
    return rounded_value