Как отрегулировать размер (высоту и ширину) независимой цветовой шкалы с помощьюлотной_строкой в ​​matplotlib - PullRequest
0 голосов
/ 31 января 2019

Я пытаюсь построить два трехмерных каркасных графика и цветную полосу в одном ряду на одной фигуре.Чтобы применить цветовую шкалу к каркасу, я следовал этому ответу Stackoverflow .Из-за этого мне пришлось генерировать независимую цветовую панель.Так как я использую tight_layout, цветовая панель потребляет всю высоту и появляется с большой шириной.

До сих пор я не мог найти никакого решения для контроля размера цветовой панели.Я попытался изменить width_ratio сетки, но ширина осталась неизменной.Кажется, высота не может быть отрегулирована в tight layout.

Мой код для построения приведен ниже.Буду благодарен за любую помощь в этом вопросе.

def plot_signature(hh, hv, vh, vv,  wireframe=False):

    x_c, y_c, z_c = synthesize(hh=hh, hv=hv, vh=vh, vv=vv, channel=False)
    x_x, y_x, z_x = synthesize(hh=hh, hv=hv, vh=vh, vv=vv, channel=True)

    xticks = np.linspace(0, 180, 13)
    yticks = np.linspace(-45, 45, 7)
    zticks = np.linspace(0, 1, 11)

    xt_labels = np.core.defchararray.add(xticks.astype(int).astype(str), u"\u00b0")
    yt_labels = np.core.defchararray.add(yticks.astype(int).astype(str), u"\u00b0")

    plt.ion()

    fig = plt.figure(tight_layout=True)
    grid = fig.add_gridspec(nrows=1, ncols=3, width_ratios=[1, 10, 10])
    ax_cbar = fig.add_subplot(grid[0, 0])
    ax_cpol = fig.add_subplot(grid[0, 1], projection='3d')
    ax_xpol = fig.add_subplot(grid[0, 2], projection='3d')

    ax_cpol.set_xlim([0, 180])
    ax_cpol.set_ylim([-45, 45])
    ax_cpol.set_zlim([0, 1])

    ax_xpol.set_xlim([0, 180])
    ax_xpol.set_ylim([-45, 45])
    ax_xpol.set_zlim([0, 1])

    cfont = {'fontname':'CMU Serif'}
    color_map = cm.rainbow

    if wireframe:
        norm_c = plt.Normalize(z_c.min(), z_c.max())
        norm_x = plt.Normalize(z_x.min(), z_x.max())
        colors_c = color_map(norm_c(z_c))
        colors_x = color_map(norm_c(z_x))
        rcount_c, ccount_c, _ = colors_c.shape
        rcount_x, ccount_x, _ = colors_x.shape
        pfig_c = ax_cpol.plot_surface(x_c, y_c, z_c, rcount=rcount_c, ccount=ccount_c, facecolors=colors_c, shade=False)
        pfig_x = ax_xpol.plot_surface(x_x, y_x, z_x, rcount=rcount_x, ccount=ccount_x, facecolors=colors_x, shade=False)
        pfig_c.set_facecolor((0, 0, 0, 0))
        pfig_x.set_facecolor((0, 0, 0, 0))
    else:
        ax_cpol.plot_surface(x_c, y_c, z_c, cmap=color_map, linewidth=0, antialiased=True)
        ax_xpol.plot_surface(x_x, y_x, z_x, cmap=color_map, linewidth=0, antialiased=True)

    ax_cpol.set_xticks(xticks)
    ax_xpol.set_xticks(xticks)
    ax_cpol.set_xticklabels(xt_labels)
    ax_xpol.set_xticklabels(xt_labels)
    ax_cpol.set_yticks(yticks)
    ax_xpol.set_yticks(yticks)
    ax_cpol.set_yticklabels(yt_labels)
    ax_xpol.set_yticklabels(yt_labels)
    ax_cpol.set_xlabel('Orientation Angle ($\psi$)', labelpad=16, fontsize=16, **cfont)
    ax_xpol.set_xlabel('Orientation Angle ($\psi$)', labelpad=16, fontsize=16, **cfont)
    ax_cpol.set_ylabel('Ellipticity Angle ($\chi$)', labelpad=16, fontsize=16, **cfont)
    ax_xpol.set_ylabel('Ellipticity Angle ($\chi$)', labelpad=16, fontsize=16, **cfont)
    ax_cpol.set_zlabel("Relative Intensity", labelpad=16, fontsize=16, **cfont)
    ax_xpol.set_zlabel("Relative Intensity", labelpad=16, fontsize=16, **cfont)
    ax_cpol.set_zticks(zticks)
    ax_xpol.set_zticks(zticks)
    ax_cpol.set_title("Co-pol Signature", fontsize=20, pad=20, **cfont)
    ax_xpol.set_title("Cross-pol Signature", fontsize=20, pad=20, **cfont)

    cb_norm = mpl.colors.Normalize(vmin=0,vmax=1)
    cb_ticks = np.linspace(0.0, 1.0, 11)

    cb = mpl.colorbar.ColorbarBase(
        ax_cbar,cmap=color_map,
        norm=cb_norm,ticks=cb_ticks,
        label='Color Map',
        orientation='vertical'
    )

    cb_label = cb.ax.yaxis.label
    cb.ax.yaxis.labelpad = 10
    custom_font = mpl.font_manager.FontProperties(family='CMU Serif', size=12)
    cb_label.set_font_properties(custom_font)
    plt.show()

В настоящее время сюжет выглядит следующим образом:

Current Plot

Однако я хочу, чтобы он был примерно таким:

Expected Plot

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

ImportanceOfBeingErnes уже опубликовал правильное рабочее решение.Я собираюсь показать реализацию своего ответа.Обратите внимание, что на этот раз я реализовал каркасный график с цветовой картой немного по-другому ( Источник ).

def plot_signature(hh, hv, vh, vv, wireframe=False):
    x_c, y_c, z_c = synthesize(
        hh=hh,
        hv=hv,
        vh=vh,
        vv=vv,
        channel=False
    )

    x_x, y_x, z_x = synthesize(
        hh=hh,
        hv=hv,
        vh=vh,
        vv=vv,
        channel=True
    )

    xticks = np.linspace(0, 180, 13)
    yticks = np.linspace(-45, 45, 7)
    zticks = np.linspace(0, 1, 11)

    xt_labels = np.core.defchararray.add(
        xticks.astype(int).astype(str),
        u"\u00b0"
    )

    yt_labels = np.core.defchararray.add(
        yticks.astype(int).astype(str),
        u"\u00b0"
    )

    plt.ion()
    fig = plt.figure(num='Polarimetric Signatures', tight_layout=True)

    gs_root = mpl.gridspec.GridSpec(
        nrows=1,
        ncols=3,
        width_ratios=[1, 10, 10]
    )

    cb_gs = mpl.gridspec.GridSpecFromSubplotSpec(
        nrows=3,
        ncols=3,
        height_ratios=[2, 5, 2],
        width_ratios=[1.1, 0.8, 1.1],
        subplot_spec=gs_root[0]
    )

    ax_cbar = fig.add_subplot(cb_gs[1, 1])
    ax_cpol = fig.add_subplot(gs_root[0, 1], projection='3d')
    ax_xpol = fig.add_subplot(gs_root[0, 2], projection='3d')

    ax_cpol.set_xlim([0, 180])
    ax_cpol.set_ylim([-45, 45])
    ax_cpol.set_zlim([0, 1])

    ax_xpol.set_xlim([0, 180])
    ax_xpol.set_ylim([-45, 45])
    ax_xpol.set_zlim([0, 1])

    cfont = {'fontname': 'CMU Serif'}
    color_map = cm.rainbow

    if wireframe:

        wire_c = ax_cpol.plot_wireframe(
            x_c,
            y_c,
            z_c,
            rstride=1,
            cstride=2
        )
        nx_c, ny_c, _ = np.shape(wire_c._segments3d)
        wire_c_x = np.array(wire_c._segments3d)[:, :, 0].ravel()
        wire_c_y = np.array(wire_c._segments3d)[:, :, 1].ravel()
        wire_c_z = np.array(wire_c._segments3d)[:, :, 2].ravel()
        wire_c.remove()
        wire_c_x1 = np.vstack([wire_c_x, np.roll(wire_c_x, 1)])
        wire_c_y1 = np.vstack([wire_c_y, np.roll(wire_c_y, 1)])
        wire_c_z1 = np.vstack([wire_c_z, np.roll(wire_c_z, 1)])
        to_delete = np.arange(0, (nx_c * ny_c), ny_c)
        wire_c_x1 = np.delete(wire_c_x1, to_delete, axis=1)
        wire_c_y1 = np.delete(wire_c_y1, to_delete, axis=1)
        wire_c_z1 = np.delete(wire_c_z1, to_delete, axis=1)
        scalars_c = np.delete(wire_c_z, to_delete)
        segs_c = [
            list(zip(x_c, y_c, z_c))
            for x_c, y_c, z_c in zip(wire_c_x1.T, wire_c_y1.T, wire_c_z1.T)
        ]
        my_wire_c = art3d.Line3DCollection(segs_c, cmap=color_map)
        my_wire_c.set_array(scalars_c)
        ax_cpol.add_collection(my_wire_c)

        wire_x = ax_xpol.plot_wireframe(
            x_x,
            y_x,
            z_x,
            rstride=1,
            cstride=2
        )
        nx_x, ny_x, _ = np.shape(wire_x._segments3d)
        wire_x_x = np.array(wire_x._segments3d)[:, :, 0].ravel()
        wire_x_y = np.array(wire_x._segments3d)[:, :, 1].ravel()
        wire_x_z = np.array(wire_x._segments3d)[:, :, 2].ravel()
        wire_x.remove()
        wire_x_x1 = np.vstack([wire_x_x, np.roll(wire_x_x, 1)])
        wire_x_y1 = np.vstack([wire_x_y, np.roll(wire_x_y, 1)])
        wire_x_z1 = np.vstack([wire_x_z, np.roll(wire_x_z, 1)])
        to_delete = np.arange(0, (nx_x * ny_x), ny_x)
        wire_x_x1 = np.delete(wire_x_x1, to_delete, axis=1)
        wire_x_y1 = np.delete(wire_x_y1, to_delete, axis=1)
        wire_x_z1 = np.delete(wire_x_z1, to_delete, axis=1)
        scalars_x = np.delete(wire_x_z, to_delete)
        segs_x = [
            list(zip(x_x, y_x, z_x))
            for x_x, y_x, z_x in zip(wire_x_x1.T, wire_x_y1.T, wire_x_z1.T)
        ]
        my_wire_x = art3d.Line3DCollection(segs_x, cmap=color_map)
        my_wire_x.set_array(scalars_x)
        ax_xpol.add_collection(my_wire_x)

        cb_norm = mpl.colors.Normalize(vmin=0, vmax=1)
        cb_ticks = np.linspace(0.0, 1.0, 11)
        cb = plt.colorbar(
            my_wire_c,
            ax_cbar, cmap=color_map,
            norm=cb_norm, ticks=cb_ticks,
            orientation='vertical',
            label="Color Map",
            ticklocation='left'
        )
        cb_label = cb.ax.yaxis.label
        cb.ax.yaxis.labelpad = 10
        custom_font = mpl.font_manager.FontProperties(
            family='CMU Serif',
            size=12
        )
        cb_label.set_font_properties(custom_font)

    else:
        ax_cpol.plot_surface(
            x_c,
            y_c,
            z_c,
            cmap=color_map,
            linewidth=0,
            antialiased=True
        )

        ax_xpol.plot_surface(
            x_x,
            y_x,
            z_x,
            cmap=color_map,
            linewidth=0,
            antialiased=True
        )

    ax_cpol.set_xticks(xticks)
    ax_xpol.set_xticks(xticks)
    ax_cpol.set_xticklabels(xt_labels)
    ax_xpol.set_xticklabels(xt_labels)
    ax_cpol.set_yticks(yticks)
    ax_xpol.set_yticks(yticks)
    ax_cpol.set_yticklabels(yt_labels)
    ax_xpol.set_yticklabels(yt_labels)
    ax_cpol.set_xlabel(
        'Orientation Angle ($\psi$)',
        labelpad=16,
        fontsize=16,
        **cfont
    )
    ax_xpol.set_xlabel(
        'Orientation Angle ($\psi$)',
        labelpad=16,
        fontsize=16,
        **cfont)
    ax_cpol.set_ylabel(
        'Ellipticity Angle ($\chi$)',
        labelpad=16,
        fontsize=16,
        **cfont
    )
    ax_xpol.set_ylabel(
        'Ellipticity Angle ($\chi$)',
        labelpad=16,
        fontsize=16,
        **cfont
    )
    ax_cpol.set_zlabel(
        "Relative Intensity",
        labelpad=16,
        fontsize=16,
        **cfont
    )
    ax_xpol.set_zlabel(
        "Relative Intensity",
        labelpad=16,
        fontsize=16,
        **cfont
    )
    ax_cpol.set_zticks(zticks)
    ax_xpol.set_zticks(zticks)
    ax_cpol.set_title(
        "Co-pol Signature",
        fontsize=20,
        pad=20,
        **cfont
    )
    ax_xpol.set_title(
        "Cross-pol Signature",
        fontsize=20,
        pad=20,
        **cfont
    )

    plt.show()

    return 0

Токовый выход показан ниже:

Latest Plot

0 голосов
/ 01 февраля 2019

В настоящее время вы используете сетку 1 x 3.

enter image description here

Рассмотрите возможность использования сетки 3 x 3, когда трехмерные графики покрывают все три строки, ацветовая полоса находится только во втором ряду.

enter image description here

Обратите внимание, что цветовая полоса должна, конечно, использовать ту же нормировку, что и графики поверхности.А на поверхностных участках следует использовать одинаковые нормализации.Коротко: должна быть одна нормализация, иначе график будет передавать неверное сообщение.

Наконец, здесь нет необходимости использовать ColorbarBase;лучше использовать

sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])  # still needed for matplotlib <= 3.0
fig.colorbar(sm, cax=cax) 

Это может позволить различным вариантам также уменьшить цветную полосу.

В идеале ответ превратит все это в код, но в вопросе нет исполняемого кода, которыйпозволит легко сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...