def plot(task, ax, runs, methods, args):
    assert runs
    try:
        title = task.split('_', 1)[1].replace('_', ' ').title()
    except IndexError:
        title = task.title()
    ax.set_title(title)
    xlim = [(+ np.inf), (- np.inf)]
    for (index, method) in enumerate(methods):
        relevant = [r for r in runs if (r.method == method)]
        if (not relevant):
            continue
        if any(((r.xs is None) for r in relevant)):
            baseline(index, method, ax, relevant, args)
        else:
            if (args.aggregate == 'none'):
                (xs, ys) = curve_lines(index, task, method, ax, relevant, args)
            else:
                (xs, ys) = curve_area(index, task, method, ax, relevant, args)
            if (len(xs) == len(ys) == 0):
                print(f'Skipping empty: {task} {method}')
                continue
            xlim = [min(xlim[0], xs.min()), max(xlim[1], xs.max())]
    ax.ticklabel_format(axis='x', style='sci', scilimits=(0, 0))
    steps = [1, 2, 2.5, 5, 10]
    ax.xaxis.set_major_locator(ticker.MaxNLocator(args.xticks, steps=steps))
    ax.yaxis.set_major_locator(ticker.MaxNLocator(args.yticks, steps=steps))
    if np.isfinite(xlim).all():
        ax.set_xlim((args.xlim or xlim))
    if args.xlim:
        ticks = sorted({*ax.get_xticks(), *args.xlim})
        ticks = [x for x in ticks if (args.xlim[0] <= x <= args.xlim[1])]
        ax.set_xticks(ticks)
    if args.ylim:
        ax.set_ylim(args.ylim)
        if args.ylimticks:
            ticks = sorted({*ax.get_yticks(), *args.ylim})
            ticks = [x for x in ticks if (args.ylim[0] <= x <= args.ylim[1])]
            ax.set_yticks(ticks)
def plot(task, ax, runs, methods, args):
    assert runs
    try:
        title = task.split('_', 1)[1].replace('_', ' ').title()
    except IndexError:
        title = task.title()
    ax.set_title(title)
    xlim = [(+ np.inf), (- np.inf)]
    for (index, method) in enumerate(methods):
        relevant = [r for r in runs if (r.method == method)]
        if (not relevant):
            continue
        if any(((r.xs is None) for r in relevant)):
            baseline(index, method, ax, relevant, args)
        else:
            if (args.aggregate == 'none'):
                (xs, ys) = curve_lines(index, task, method, ax, relevant, args)
            else:
                (xs, ys) = curve_area(index, task, method, ax, relevant, args)
            if (len(xs) == len(ys) == 0):
                print(f'Skipping empty: {task} {method}')
                continue
            xlim = [min(xlim[0], xs.min()), max(xlim[1], xs.max())]
    ax.ticklabel_format(axis='x', style='sci', scilimits=(0, 0))
    steps = [1, 2, 2.5, 5, 10]
    ax.xaxis.set_major_locator(ticker.MaxNLocator(args.xticks, steps=steps))
    ax.yaxis.set_major_locator(ticker.MaxNLocator(args.yticks, steps=steps))
    if np.isfinite(xlim).all():
        ax.set_xlim((args.xlim or xlim))
    if args.xlim:
        ticks = sorted({*ax.get_xticks(), *args.xlim})
        ticks = [x for x in ticks if (args.xlim[0] <= x <= args.xlim[1])]
        ax.set_xticks(ticks)
    if args.ylim:
        ax.set_ylim(args.ylim)
        if args.ylimticks:
            ticks = sorted({*ax.get_yticks(), *args.ylim})
            ticks = [x for x in ticks if (args.ylim[0] <= x <= args.ylim[1])]
            ax.set_yticks(ticks)