def breaks_from_binwidth(x_range, binwidth=None, center=None,
                         boundary=None):
    """
    Calculate breaks given binwidth

    Parameters
    ----------
    x_range : array_like
        Range over with to calculate the breaks. Must be
        of size 2.
    binwidth : float
        Separation between the breaks
    center : float
        The center of one of the bins
    boundary : float
        A boundary between two bins

    Returns
    -------
    out : array_like
        Sequence of break points.
    """
    if binwidth <= 0:
        raise PlotnineError("The 'binwidth' must be positive.")

    if boundary is not None and center is not None:
        raise PlotnineError("Only one of 'boundary' and 'center' "
                            "may be specified.")
    elif boundary is None:
        if center is None:
            # This puts min and max of data in outer half
            # of their bins
            boundary = binwidth/2
        else:
            boundary = center - binwidth/2

    epsilon = np.finfo(float).eps
    shift = np.floor((x_range[0]-boundary)/binwidth)
    origin = boundary + shift * binwidth
    # The (1-epsilon) factor prevents numerical roundoff in the
    # binwidth from creating an extra break beyond the one that
    # includes x_range[1].
    max_x = x_range[1]+binwidth*(1-epsilon)
    breaks = np.arange(origin, max_x, binwidth)
    return breaks
Calculate breaks given binwidth

    Parameters
    ----------
    x_range : array_like
        Range over with to calculate the breaks. Must be
        of size 2.
    binwidth : float
        Separation between the breaks
    center : float
        The center of one of the bins
    boundary : float
        A boundary between two bins

    Returns
    -------
    out : array_like
        Sequence of break points.