def draw_spectra_stacked(ss, title=None, num_rows=None, setup=_default_setup):
    """Same as plot_spectra_stacked(), but does not call plt.show(); returns figure"""
    n = len(ss)
    assert n > 0, "ss is empty"
    if not num_rows:
        num_rows = n
        num_cols = 1
    else:
        num_cols = int(np.ceil(float(n) / num_rows))
    a99.format_BLB()

    fig, axarr = plt.subplots(num_rows, num_cols, sharex=True, squeeze=False)
    xmin = 1e38
    xmax = -1e38
    i, j = -1, num_cols
    xunit, yunit = None, None
    any_span = False
    for s in ss:
        j += 1
        if j >= num_cols:
            i += 1
            if i >= num_rows:
                break
            j = 0
        assert isinstance(s, ft.Spectrum)
        ax = axarr[i, j]
        y = s.y
        ax.plot(s.x, y)
        ymin_, ymax = ax.get_ylim()
        ymin_now = ymin_ if setup.ymin is None else setup.ymin
        ax.set_ylim([ymin_now, ymin_now + (ymax - ymin_now) * (1 + _T)])  # prevents top of line from being hidden by plot box

        _set_plot(ax.set_ylabel, setup.fmt_ylabel, s)
        _set_plot(ax.set_title, setup.fmt_title, s)

        if len(s.x) > 0:
            xmin, xmax = min(min(s.x), xmin), max(max(s.x), xmax)
            any_span = True

        if xunit is None:
            xunit = s.xunit
        else:
            if xunit != s.xunit:
                raise RuntimeError("Spectra x-units do not match")

        if yunit is None:
            yunit = s.yunit
        else:
            if yunit != s.yunit:
                raise RuntimeError("Spectra x-units do not match")

    if any_span:
        span = xmax - xmin
        ax.set_xlim([xmin - span * _T, xmax + span * _T])
    for j in range(num_cols):
        ax = axarr[num_rows - 1, j]
        if setup.flag_xlabel and setup.fmt_xlabel:
            _set_plot(ax.set_xlabel, setup.fmt_xlabel, s)
    plt.tight_layout()
    if title is not None:
        fig.canvas.set_window_title(title)
    return fig