2014-09-11 59 views
1

我想知道是否有任何人根据美国心脏协会使用matplotlib实现了左心室的牛眼。 我想要这样的:左心室眼球(AHA)matplotlib

plotBullEye(data)其中数据有17个值,每个值对应于一个特定的牛眼区域。

LV Bull Eye (AHA)

回答

2

最后我实现了使用极投影的功能。此外,此功能接受要突出显示的区域列表。 这是代码:

def bulleye_plot(data, ax=None, figsize=(12,8), vlim=None, segBold=[]): 
    """ 
    Bull eye for the Left Ventricle according to the AHA representation 
    Use Example: 
     data = range(17) 
     bulleye_plot(data) 
    """ 
    data = np.array(data).ravel() 

    if vlim is None: 
     vlim = [data.min(), data.max()] 

    axnone = False 
    if ax is None: 
     fig, ax = plt.subplots(figsize=figsize, subplot_kw=dict(projection='polar')) 
     fig.canvas.set_window_title('Left Ventricle Bull Eyes (AHA) Plot') 
     axnone = True 


    theta = np.linspace(0, 2*np.pi, 768) 
    r = np.linspace(0.2, 1, 4) 


    # Armamos los bordes del circulo 
    linewidth = 2 
    for i in range(r.shape[0]): 
     ax.plot(theta, np.repeat(r[i], theta.shape), '-k', lw=linewidth) 

    # Armamos las lineas que separan las regiones 1-12 
    for i in range(6): 
     theta_i = i * 60 * np.pi/180 
     ax.plot([theta_i, theta_i], [r[1], 1], '-k', lw=linewidth) 

    # Armamos las lineas que separan las regiones 13-16 
    for i in range(4): 
     theta_i = i * 90 * np.pi/180 - 45*np.pi/180 
     ax.plot([theta_i, theta_i], [r[0], r[1]], '-k', lw=linewidth) 





    # Rellenamos las regiones 1-6 
    r0 = r[2:4] 
    r0 = np.repeat(r0[:,np.newaxis], 128, axis=1).T 
    for i in range(6): 
     theta0 = theta[i*128:i*128+128] + 60*np.pi/180 # sumamos 60 porque empieza en la reg 6 
     theta0 = np.repeat(theta0[:,np.newaxis], 2, axis=1) 
     z = np.ones((128,2)) * data[i] 
     ax.pcolormesh(theta0, r0, z, vmin=vlim[0], vmax=vlim[1]) 
     if i+1 in segBold: 
      ax.plot(theta0, r0, '-k', lw=linewidth+2) 
      ax.plot(theta0[0], [r[2],r[3]], '-k', lw=linewidth+1) 
      ax.plot(theta0[-1], [r[2],r[3]], '-k', lw=linewidth+1) 

    # Rellenamos las regiones 7-12 
    r0 = r[1:3] 
    r0 = np.repeat(r0[:,np.newaxis], 128, axis=1).T 
    for i in range(6): 
     theta0 = theta[i*128:i*128+128] + 60*np.pi/180 # sumamos 60 porque empieza en la reg 6 
     theta0 = np.repeat(theta0[:,np.newaxis], 2, axis=1) 
     z = np.ones((128,2)) * data[i+6] 
     ax.pcolormesh(theta0, r0, z, vmin=vlim[0], vmax=vlim[1]) 
     if i+7 in segBold: 
      ax.plot(theta0, r0, '-k', lw=linewidth+2) 
      ax.plot(theta0[0], [r[1],r[2]], '-k', lw=linewidth+1) 
      ax.plot(theta0[-1], [r[1],r[2]], '-k', lw=linewidth+1) 


    # Rellenamos las regiones 13-16 
    r0 = r[0:2] 
    r0 = np.repeat(r0[:,np.newaxis], 192, axis=1).T 
    for i in range(4): 
     theta0 = theta[i*192:i*192+192] + 45*np.pi/180 # sumamos 60 porque empieza en la reg 6 
     theta0 = np.repeat(theta0[:,np.newaxis], 2, axis=1) 
     z = np.ones((192,2)) * data[i+12] 
     ax.pcolormesh(theta0, r0, z, vmin=vlim[0], vmax=vlim[1]) 
     if i+13 in segBold: 
      ax.plot(theta0, r0, '-k', lw=linewidth+2) 
      ax.plot(theta0[0], [r[0],r[1]], '-k', lw=linewidth+1) 
      ax.plot(theta0[-1], [r[0],r[1]], '-k', lw=linewidth+1) 

    #Rellenamos la region 17 
    if data.size == 17: 
     r0 = np.array([0, r[0]]) 
     r0 = np.repeat(r0[:,np.newaxis], theta.size, axis=1).T 
     theta0 = np.repeat(theta[:,np.newaxis], 2, axis=1) 
     z = np.ones((theta.size,2)) * data[16] 
     ax.pcolormesh(theta0, r0, z, vmin=vlim[0], vmax=vlim[1]) 
     if 17 in segBold: 
      ax.plot(theta0, r0, '-k', lw=linewidth+2) 


    ax.set_ylim([0, 1]) 
    ax.set_yticklabels([]) 
    ax.set_xticklabels([]) 


    #Add legend 
    if axnone: 
     cm = plt.cm.jet 

     #define the bins and normalize 
     cNorm = mpl.colors.Normalize(vmin=vlim[0], vmax=vlim[1]) 

     ax = fig.add_axes([0.3, 0.04, 0.45, 0.05]) 
     ticks = [vlim[0], 0, vlim[1]] 
     cb = mpl.colorbar.ColorbarBase(ax, cmap=cm, norm=cNorm, 
             orientation='horizontal', ticks=ticks) 

    plt.show() 

    if axnone: 
     return fig, ax 

的一些结果:如下图所示 LV AHA

LV AHA with segments = [5,6,11,12,16] in bold

+0

您是否愿意将此函数添加到matplotlib文档中(我认为在示例或库中)?我对这个功能有一些小小的嘲讽(不是内部创建轴的巨大粉丝,它应该返回创建的艺术家列表)。 – tacaswell 2014-09-13 17:40:48

+0

是的,我可以将此函数添加到matplotlib文档中(我不清楚是否最好的地方是在示例/ pylab_example文件夹中的git中)。另一方面,我根据自己的特定要求完成了这个功能,其中一个就是将所有内容封装在坐标轴中(我在子图的循环中使用了这个功能)。关于轴的内部创建,我最好保持清晰的实现而不是优化的实现。如果您有任何建议,请让我知道。 – Ariel 2014-09-14 11:13:07

+0

我认为在绘图函数中包括图形创建是优化版本,期望传入的Axes对象是清晰的版本;'example/pylab_example'是一个很好的起点。 – tacaswell 2014-09-14 14:33:08

0
你也可以做使用多边形

点产生。 大部分代码重复都可以概括,因为理解它是保留原样。

def plotBull(): 
import matplotlib.pyplot as plt 
plt.axes() 

# inner most region # 
points = stack3(50,0,180) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#575757' , edgecolor='#575757') 
plt.gca().add_patch(line) 
plt.text(0,0,'17') 

points = stack3(50,-180,0) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#575757' , edgecolor='#575757') 
plt.gca().add_patch(line) 


# bottom up ############# 
points = stack3(100,45,135) 
line = plt.Polygon(points, closed=True , fill=True ,fc = 'm' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(0,75,'13') 

points = stack3(100,135,225) 
line = plt.Polygon(points, closed=True , fill=True ,fc = 'g' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(-75,0,'14') 

points = stack3(100,225,315) 
line = plt.Polygon(points, closed=True , fill=True ,fc = 'b' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(0,-75 ,'15') 

points = stack3(100,315,405) 
line = plt.Polygon(points, closed=True , fill=True ,fc = 'y' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(75,0,'16') 

#botton up1############### 

points = stack3(150,0,62) 
line = plt.Polygon(points, closed=True , fill=True ,fc = 'c' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(100,60,'12') 

points = stack3(150,60,122) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#3358fc' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(0,115,'7') 

points = stack3(150,120,182) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#245465' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(-100,60,'8') 

points = stack3(150,180,242) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#D3E130' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(-100,-60,'9') 

points = stack3(150,240,302) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#8928b1' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(0,-115,'10') 

points = stack3(150,300,362) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#12ED89' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(100,-60,'11') 

#botton up1############### 

points = stack3(200,0,62) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#FF2E34' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(150,80,'6') 

points = stack3(200,60,122) 
line = plt.Polygon(points, closed=True , fill=True ,fc = 'b' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(0,165,'1') 

points = stack3(200,120,182) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#12D154' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(-150,80,'2') 

points = stack3(200,180,242) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#D3FF65' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(-150,-80,'3') 

points = stack3(200,240,302) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#54DBEF' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(0,-165,'4') 

points = stack3(200,300,362) 
line = plt.Polygon(points, closed=True , fill=True ,fc = '#C121EE' , edgecolor='k') 
plt.gca().add_patch(line) 
plt.text(150,-80,'5') 

plt.axis('scaled') 
plt.axis('off') 

plt.show() 


def stack3(radius,startAngle,endAngle): 
    import math 
    startRadian = math.pi*startAngle/180 
    endRadian = math.pi*endAngle/180 

    import math 
    mainList = [] 
    for idx in range(0,100): 
    subList = [] 
    theta = 2*3.1415926 * float(idx)/float(100) 

    theta += startRadian 

    if theta > endRadian :  
     break 
    x = radius* math.cos(theta) 
    y = radius* math.sin(theta) 
    subList.append(x) 
    subList.append(y) 
    mainList.append(subList) 
    tempList = [] 
    for idx in range(0,100): 
    subList = [] 
    theta = 2*3.1415926 * float(idx)/float(100) 
    theta += startRadian 
    if theta > endRadian : 
     break 
    x = (radius - 50) * math.cos(theta) 
    y = (radius - 50) * math.sin(theta) 
    subList.append(x) 
    subList.append(y) 
    tempList.append(subList) 
    tempList.reverse() 
    for idx in range(0,len(tempList)): 
    mainList.append(tempList[idx]) 
    return mainList 
    pass