微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

matplotlib seaborn 热图 x,y 网格对数尺度问题

如何解决matplotlib seaborn 热图 x,y 网格对数尺度问题

所以我的问题是,我想将多个热图绘制为多图,其中我有 X、Y 轴对数,并向热图添加补丁,以突出显示具有调整 alpha 值的某些区域(参见附图)。 问题是,使用 pcolormesh,您可以轻松地对 X、Y 使用 logscale,因为它使用确切的数据来显示,但是 seaborn 只能使用数据的索引。 另一方面,使用 pcolormesh 我没有找到添加 pacthes 的方法,但是使用 seaborn 很容易做到...

所以我想提出一个解决方案,其中可以完成对数缩放和向绘图添加路径...

添加了一部分代码,并附上了一张我可以用 seaborn 做的图片

所以这是在 jupyter-notebook 中完成的带有 sime custom x,ytics 的 seaborn 热图多图的代码

def HeatMapPlotter(alphaval,im_w,im_h,tissue_type,hl_x_min,hl_x_max,hl_y_min,hl_y_max): # alpha value of heatmap highlights,image width and height,type of tissue: blood or colon


    data_type = ["n","gamma","d","r0"]
    c_labels =["$n_\mathrm{drift}$","$\gamma_\mathrm{drift}$","$d_\mathrm{drift}$","$r_0^\mathrm{drift}$"] 
    vminR = [0.99,1.99,0.99,1e-4]
    sb.set_style('white',{'axes.linewidth': 0.5})
    plt.rcParams['xtick.major.size'] = 20
    plt.rcParams['xtick.major.width'] = 4
    plt.rcParams['xtick.bottom'] = True
    plt.rcParams['ytick.left'] = True
    
    if tissue_type=="blood":
        points = p_b
        n_points = n_p_b
        Ns = Nsb
        mus = musb
        Nsl = ['{:.1e}'.format(i) for i in Nsb]
        Nsl = [reformatE(i) for i in Nsl]
        musl = ['{:.1e}'.format(j) for j in musb]
        musl = [reformatE(i) for i in musl]
    else:
        points = p_c
        n_points = n_p_c        
        Ns = Nsc
        mus = musc
        Nsl = ['{:.1e}'.format(i) for i in Nsc]
        Nsl = [reformatE(i) for i in Nsl]
        musl = ['{:.1e}'.format(j) for j in musc]
        musl = [reformatE(i) for i in musl]
        
    dataColl = [0]*8
    d_index = 0
    for d in range(8):

        if d_index==4:
            d_index=0

        if d<4:

            dataColl[d] = array([point[data_type[d_index]] for point in points]).reshape(RES,RES)
        else:

            dataColl[d] = array([point[data_type[d_index]] for point in n_points]).reshape(RES,RES)

        d_index+=1

    y,x = np.meshgrid(mus,Ns)
    fig,axes = plt.subplots(figsize=(im_w,im_h),nrows=2,ncols=4);

    m_index=0
    #fig.suptitle(tissue_type+" "+"scd (top) and neutral (bottom)") 

    for m,ax in zip(range(0,8),axes.flat):
        plt.figure(m);
        sb.set(font_scale=cb_scale);  # set colorbar font scale
        
        
        if m_index==4:
            m_index=0
        if m==3 or m==7:
            sb.heatmap(dataColl[m],cmap = ListedColormap(newcolors),norm=Lognorm(),cbar_kws={'label': c_labels[m_index]},vmin=vminR[m_index],vmax=amax(dataColl[m]),ax=ax)
        else:
            sb.heatmap(dataColl[m],ax=ax)
        if m%4==0:
            
            ax.set_ylabel("$\mu$",fontsize=mu_l_s);
        else:
            ax.set_ylabel(" ",fontsize=mu_l_s);

        ax.set_xticklabels(Nsl,rotation=x_rot); #set xtics label (default is 0,1,2...)
        ax.set_yticklabels(musl,rotation=y_rot); #set ytics label (default is 0,2...)            
            

        plt.setp(ax.get_xticklabels()[1::2],visible=False);  # every 2nd tic is highlighted for xtics
        plt.setp(ax.get_yticklabels()[1::2],visible=False);  # every 2nd tic is highlighted for ytics  
        ax.set_xlabel("\n$N$",fontsize=N_l_s); # set xlabel   
        ax.tick_params(direction='out',length=16,width=6,colors='black',grid_color='black',grid_alpha=1.0,labelsize=tick_ls);     # tick settings
        
        
        # set the highlighted Box and set alpha by user input (see description in a cell below)
        ax.add_patch(Rectangle((hl_x_min,hl_y_min),hl_x_max-hl_x_min,hl_y_max-hl_y_min,fill=False,edgecolor='black',linestyle = '--',lw=5,alpha=1.0));
        for r in range(RES):
            for c in range(RES):
                if (r>=hl_x_min and r<hl_x_max) and (c<hl_y_max and c>=hl_y_min):
                    continue
                else:
                    ax.add_patch(Rectangle((r,c),fill=True,color = 'gray',edgecolor=None,lw=0,alpha=alphaval));

        m_index +=1
    plt.tight_layout();

以及 pcolormesh 版本的代码,其中 logscale 可以工作并且不添加补丁......

import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.ticker as plticker
from matplotlib import cm
from matplotlib.colors import ListedColormap
from matplotlib.colors import Lognorm
from matplotlib.patches import Rectangle
import matplotlib.patches as patches
import matplotlib as mpl

data_type = ["n","r0"]
c_labels =["$n_\mathrm{drift}$","$r_0^\mathrm{drift}$"] 
vminR = [1.0,1.0,1e-4]


hl_x_min,hl_y_max = 3,10,2,8

alphaval = 0.6

labels_size = 24 # X,Y,Z labels size

cb_ts = 15 # colorbar tick number font size

tick_ls = 15

title_s = 60 # size of title
im_w,im_h = 40,12  # image width and height
cb_scale = 4.8   # scale of colorbar font size
x_rot,y_rot = 90,0  # rotation of x and y tick labels

dataColl = [0]*8
d_index = 0
for d in range(8):

    if d_index==4:
        d_index=0

    if d<4:

        dataColl[d] = array([point[data_type[d_index]] for point in points]).reshape(RES,RES)
    else:

        dataColl[d] = array([point[data_type[d_index]] for point in n_points]).reshape(RES,RES)

    d_index+=1


fig,ncols=4);

m_index=0
#fig.suptitle(tissue_type+" "+"scd (top) and neutral (bottom)") 

fig.text(0.483,0.86,"blood \n \n",fontsize = 35)
fig.text(0.488,0.82,"scd \n \n",fontsize = 35)
fig.text(0.48,0.38,"neutral \n \n",fontsize = 35)
plt.subplots_adjust(wspace=0.1,hspace=0.5) 

for m,axes.flat):
    
    y,Ns)
    z = dataColl[m]
    z=z.T
    
    if m_index==4:
        m_index=0
    
    if m==3 or m==7:
        cmesh = ax.pcolormesh(x,y,z,cmap=ListedColormap(newcolors),vmax=amax(z),antialiased=True,shading="nearest",snap=True,edgecolors="face") 
    else:
        cmesh = ax.pcolormesh(x,edgecolors="face") 
    cb=fig.colorbar(cmesh,ax=ax)
    cb.set_label(label=c_labels[m_index],fontsize=labels_size,rotation = 90)

    ax.set_xscale('log')
    ax.set_yscale('log')
    ax.tick_params(direction='out',length=4,width=2,labelsize=tick_ls);     # tick settings
        
    cb.ax.tick_params(labelsize=cb_ts)
    
    
    if m>3:
        ax.set_xlabel("$N$",fontsize=labels_size)
    if m_index ==0:
        ax.set_ylabel("$\mu$",fontsize=labels_size)
    
    # set the highlighted Box and set alpha by user input (see description in a cell below)
    ax.add_patch(Rectangle((hl_x_min,alpha=1.0));
    for r in range(RES):
        for c in range(RES):
            if (r>=hl_x_min and r<hl_x_max) and (c<hl_y_max and c>=hl_y_min):
                continue
            else:
                ax.add_patch(Rectangle((r,alpha=alphaval));
    m_index +=1


#plt.tight_layout();

plt.show()

fig.savefig("pcmesh.pdf")

希望这是可以理解的,我试图搜索这个问题,我已经阅读了很多东西,但我找不到任何东西......

先谢谢你!

This is the seaborn plot

And this is the pcolormesh version,where the logscale tics matter

解决方法

好的,经过更多小时的搜索,我找到了解决方案。 我的错误是我用 pcolormesh 处理了 add_patch(),因为它会使用索引坐标而不是实际的 X、Y 网格数据,我不得不将 zorder >0 添加到 Rectangle() 函数中。

在这里引用这个问题:Draw Circles on Top Level of Figure

ax.add_patch(Rectangle((hl_x_min,hl_y_min),hl_x_max-hl_x_min,hl_y_max-hl_y_min,fill=False,edgecolor='black',linestyle = '--',lw=5,alpha=1.0,zorder = 10));

(hl_x_min,hl_y_max-hl_y_min 坐标必须不是索引 (0,1,2...) 而是实际数据间隔(如 (1e-4;1e-2) )。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。