[docs]defbuild_pos(inter,method=None):""" Compute node layout given an interaction matrix. """G=inter.shape[0]# Define graphgraph=nx.Graph()foriinrange(G):graph.add_node(i)forjinrange(0,G):graph.add_node(j)ifnp.abs(inter[i,j]!=0):graph.add_edge(i,j)# Compute graph layoutp=np.random.normal(size=(G,2))ifmethodisNone:p=nx.kamada_kawai_layout(graph,pos=p)ifmethod=='graphviz':p=nx.nx_agraph.graphviz_layout(graph,prog='neato')# Return node positionspos=np.zeros((G,2))forkinrange(0,G):pos[k,:]=p[k]scale=1ifmethodisNoneelse2/(pos.max()-pos.min())center=pos.mean(axis=0)ifG>0else0returnscale*(pos-center)
#### Plotting functions ####defnode(k,ax,pos,name,scale=1.,color=None,fontsize=None,nodesize=1.):ifcolorisNone:color='gray'iffontsizeisNone:fontsize=8*scalex,y=pos[k,0]*scale,pos[k,1]*scaler=nodesize*0.1*scale# Node shapecircle1=Circle((x,y),radius=r,fill=True,facecolor='white',edgecolor='lightgray',lw=1*scale,zorder=3,clip_on=False)ax.add_artist(circle1)# Node labelax.text(x,y-0.007*scale,name,color=color,fontsize=fontsize,zorder=4,horizontalalignment='center',verticalalignment='center')deflink(k1,k2,ax,pos,weight,bend=0.,scale=1.,nodesize=1.,alpha=None):# Node coordinatesx1,y1=pos[k1,0]*scale,pos[k1,1]*scalex2,y2=pos[k2,0]*scale,pos[k2,1]*scaleshrink=9*scale*nodesizeifalphaisNone:alpha=1# Case 1: activationifweight>0:style=ArrowStyle('Simple',tail_width=1.1*scale,head_width=3.5*scale,head_length=5*scale)arrow=FancyArrowPatch((x1,y1),(x2,y2),arrowstyle=style,shrinkA=shrink,shrinkB=shrink,fc=activ,lw=0,zorder=0,connectionstyle='arc3,rad={}'.format(bend),clip_on=False,alpha=alpha)ax.add_artist(arrow)# Case 2: inhibitionifweight<0:style=ArrowStyle('Simple',tail_width=1.1*scale,head_width=0,head_length=1e-9*scale)arrow=FancyArrowPatch((x1,y1),(x2,y2),arrowstyle=style,shrinkA=shrink,shrinkB=shrink,fc=inhib,lw=0,zorder=0,connectionstyle='arc3,rad={}'.format(bend),clip_on=False,alpha=alpha)ax.add_artist(arrow)r=0.125*nodesizeu=pos[k2]-pos[k1]u0=u/np.sqrt(np.sum(u**2))x0=(pos[k1,0]+r*u0[0])*scaley0=(pos[k1,1]+r*u0[1])*scaledx=(u[0]-2*r*u0[0])*scaledy=(u[1]-2*r*u0[1])*scaleh_width=0.07*scaleh_height=0.015*scalex1,y1=x0+dx,y0+dyd=np.sqrt(dx**2+dy**2)u=np.array([dx,dy])/dv=np.array([dy,-dx])/dx=x1+0.2*h_height*u[0]+0.5*h_width*v[0]y=y1+0.2*h_height*u[1]+0.5*h_width*v[1]ifv[0]>0:angle=(180/np.pi)*np.arctan(v[1]/v[0])-180elifv[0]<0:angle=(180/np.pi)*np.arctan(v[1]/v[0])else:angle=np.sign(u[0])*90angle+=np.tanh(bend)*90theta=np.tanh(bend)*(np.pi/2)x3=x2+np.cos(theta)*(x-x2)-np.sin(theta)*(y-y2)y3=y2+np.sin(theta)*(x-x2)+np.cos(theta)*(y-y2)head=Rectangle((x3,y3),h_width,h_height,clip_on=False,angle=angle,fc=inhib,zorder=0,alpha=alpha)ax.add_artist(head)deflink_auto(k,ax,pos,weight,v=None,scale=1.,nodesize=1.,alpha=None):# Node coordinatesx0,y0=pos[k,0]*scale,pos[k,1]*scale# OrientationifvisNone:v=np.array([1,0])v/=np.sqrt(np.sum(v**2))ifv[0]>0:angle0=np.arcsin(v[1])*(180/np.pi)else:angle0=180-np.arcsin(v[1])*(180/np.pi)angle1=58+angle0angle2=300+angle0theta=angle0*(np.pi/180)x,y=x0+0.145*scale,y0x1=x0+np.cos(theta)*(x-x0)-np.sin(theta)*(y-y0)y1=y0+np.sin(theta)*(x-x0)+np.cos(theta)*(y-y0)# Loop diameterd=0.15*scale# Case 1: activationifweight>0:c=activarc=Arc((x1,y1),d,d,angle=180,theta1=angle1,theta2=angle2-30,lw=1.1*scale,color=c,zorder=0,clip_on=False)ax.add_artist(arc)# Activation headhead_width=0.045*scalehead_length=0.065*scaleangle=angle2-180-30theta=angle*(np.pi/180)triangle=np.array([[x1+d/2+head_width/2,y1-head_length/4],[x1+d/2,y1+head_length*3/4],[x1+d/2-head_width/2,y1-head_length/4]])x,y=triangle[:,0].copy(),triangle[:,1].copy()triangle[:,0]=x1+np.cos(theta)*(x-x1)-np.sin(theta)*(y-y1)triangle[:,1]=y1+np.sin(theta)*(x-x1)+np.cos(theta)*(y-y1)triangle-=0.03*(triangle[0]-triangle[2])head=Polygon(triangle,fc=activ,zorder=0,clip_on=False)ax.add_artist(head)# Case 2: inhibitionifweight<0:c=inhibarc=Arc((x1,y1),d,d,angle=180,theta1=angle1,theta2=angle2-2,lw=1.1*scale,color=c,zorder=0,clip_on=False)ax.add_artist(arc)# Inhibition headwidth=0.06*scaleheight=0.015*scaleangle=angle2-180-2theta=angle*(np.pi/180)x=x1-width/2+d/2y=y1-height/2x2=x1+np.cos(theta)*(x-x1)-np.sin(theta)*(y-y1)y2=y1+np.sin(theta)*(x-x1)+np.cos(theta)*(y-y1)head=Rectangle((x2,y2),width,height,angle=angle,fc=c,zorder=0,clip_on=False)ax.add_artist(head)defshow_empty_plot_warning():print('Warning: nothing to show in this plot')defis_isolated(gene,inter):"""Test whether a gene is isolated."""G=inter.shape[0]others=(np.arange(G)!=gene)targets=np.nonzero(inter[gene,others])[0]factors=np.nonzero(inter[others,gene])[0]return(targets.size==0)and(factors.size==0)defis_stimulus_leaf(gene,inter):"""Test whether a gene is a leaf of the stimulus."""G=inter.shape[0]others=(np.arange(G)!=gene)targets=np.nonzero(inter[gene,others])[0]factors=np.nonzero(inter[others,gene])[0]iffactors.size!=1:returnFalseelse:return(targets.size==0)and(factors[0]==0)#### Main function ####
[docs]defplot_network(inter,pos,width=1.,height=1.,scale=1.,names=None,vdict=None,tol=None,root=False,axes=None,nodes=None,n0=True,file=None,verb=False,fontsize=None,vcolor=None,nodesize=1.,bend=0.14,bend_all=False,alpha=None,hide_isolated_genes=False,hide_stimulus_leaves=False):"""Plot a gene regulatory network. Parameters ---------- hide_isolated_genes : bool Hide genes that have no neighbors. hide_stimulus_leaves : bool Hide genes whose only neighbor is the stimulus. """G,G=inter.shapew,h=width/2.54,height/2.54# CentimetersifnamesisNone:names=['']+['{}'.format(k)forkinrange(1,G)]ifvcolorisNone:vcolor=G*['#5C5C5C']ifvdictisNone:vdict={}ifaxesisNone:fig=plt.figure(figsize=(w,h),dpi=100,frameon=False)plt.axes((0,0,1,1))ax=fig.gca()I,J=inter.nonzero()ax.axis('off')else:ax=axesfig=plt.gcf()size=fig.get_size_inches()w,h=size[0],size[1]ifnodesisNone:I,J=inter.nonzero()else:I,J=nodes,nodesax.axis('equal')ax.axis('off')ax_pos=ax.get_position()plt.xlim([-w*ax_pos.width/2,w*ax_pos.width/2])plt.ylim([-h*ax_pos.height/2,h*ax_pos.height/2])scale=scale*np.min([ax_pos.width,ax_pos.height])# Decide which genes to showv=set(range(G))e=set(zip(*inter.nonzero()))ifG==0:show_empty_plot_warning()ifhide_isolated_genes:forkinrange(1,G):ifis_isolated(k,inter):v.discard(k)e.discard((k,k))ifhide_stimulus_leaves:forkinrange(1,G):ifis_stimulus_leaf(k,inter):v.discard(k)e.discard((0,k))# Draw nodesforkinv:node(k,ax,pos,names[k],scale,fontsize=fontsize,color=vcolor[k],nodesize=nodesize)# Draw linksfork1,k2ine:weight=inter[k1,k2]ifk1!=k2:if(k2,k1)ine:link(k1,k2,ax,pos,weight,bend,scale,nodesize=nodesize,alpha=alpha)else:link(k1,k2,ax,pos,weight,bend*bend_all,scale,nodesize=nodesize,alpha=alpha)else:v=vdict.get(k1)ifvisNone:b,c=0,0forkinrange(G):if(k!=k1)and(((k,k1)ine)or((k1,k)ine)):b+=pos[k]c+=1ifc==0:b,c=0,0forkinnp.union1d(I,J):if(k!=k1):b+=pos[k]c+=1v=pos[k1]-b/celse:v=np.array(v)d=np.sqrt(np.sum(v**2))ifd>0:v=v/delse:v=np.array([0,1])link_auto(k1,ax,pos,weight,v,scale,nodesize=nodesize,alpha=alpha)iffileisNone:file='network.pdf'ifaxesisNone:fig.savefig(file,bbox_inches='tight')