def labeled_intervals(intervals, labels, label_set=None,
                      base=None, height=None, extend_labels=True,
                      ax=None, tick=True, **kwargs):
    '''Plot labeled intervals with each label on its own row.
    Parameters
    ----------
    intervals : np.ndarray, shape=(n, 2)
        segment intervals, in the format returned by
        :func:`mir_eval.io.load_intervals` or
        :func:`mir_eval.io.load_labeled_intervals`.
    labels : list, shape=(n,)
        reference segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    label_set : list
        An (ordered) list of labels to determine the plotting order.
        If not provided, the labels will be inferred from
        ``ax.get_yticklabels()``.
        If no ``yticklabels`` exist, then the sorted set of unique values
        in ``labels`` is taken as the label set.
    base : np.ndarray, shape=(n,), optional
        Vertical positions of each label.
        By default, labels are positioned at integers
        ``np.arange(len(labels))``.
    height : scalar or np.ndarray, shape=(n,), optional
        Height for each label.
        If scalar, the same value is applied to all labels.
        By default, each label has ``height=1``.
    extend_labels : bool
        If ``False``, only values of ``labels`` that also exist in
        ``label_set`` will be shown.
        If ``True``, all labels are shown, with those in `labels` but
        not in `label_set` appended to the top of the plot.
        A horizontal line is drawn to indicate the separation between
        values in or out of ``label_set``.
    ax : matplotlib.pyplot.axes
        An axis handle on which to draw the intervals.
        If none is provided, a new set of axes is created.
    tick : bool
        If ``True``, sets tick positions and labels on the y-axis.
    kwargs
        Additional keyword arguments to pass to
        `matplotlib.collection.BrokenBarHCollection`.
    Returns
    -------
    ax : matplotlib.pyplot.axes._subplots.AxesSubplot
        A handle to the (possibly constructed) plot axes
    '''
    ax, _ = __get_axes(ax=ax)
    intervals = np.atleast_2d(intervals)
    if label_set is None:
        label_set = [_.get_text() for _ in ax.get_yticklabels()]
        if not any(label_set):
            label_set = []
    else:
        label_set = list(label_set)
    if extend_labels:
        ticks = label_set + sorted(set(labels) - set(label_set))
    elif label_set:
        ticks = label_set
    else:
        ticks = sorted(set(labels))
    style = dict(linewidth=1)
    style.update(next(ax._get_patches_for_fill.prop_cycler))
    style['facecolor'] = style.pop('color')
    style.update(kwargs)
    if base is None:
        base = np.arange(len(ticks))
    if height is None:
        height = 1
    if np.isscalar(height):
        height = height * np.ones_like(base)
    seg_y = dict()
    for ybase, yheight, lab in zip(base, height, ticks):
        seg_y[lab] = (ybase, yheight)
    xvals = defaultdict(list)
    for ival, lab in zip(intervals, labels):
        if lab not in seg_y:
            continue
        xvals[lab].append((ival[0], ival[1] - ival[0]))
    for lab in seg_y:
        ax.add_collection(BrokenBarHCollection(xvals[lab], seg_y[lab],
                                               **style))
        style.pop('label', None)
    if label_set != ticks:
        ax.axhline(len(label_set), color='k', alpha=0.5)
    if tick:
        ax.grid(True, axis='y')
        ax.set_yticks([])
        ax.set_yticks(base)
        ax.set_yticklabels(ticks, va='bottom')
        ax.yaxis.set_major_formatter(IntervalFormatter(base, ticks))
    if base.size:
        __expand_limits(ax, [base.min(), (base + height).max()], which='y')
    if intervals.size:
        __expand_limits(ax, [intervals.min(), intervals.max()], which='x')
    return ax