highlight : None or string
         if string, then only the label of this population is set and the box is highlighted

def network_sketch(ax, highlight=None, labels=True, yscaling=1.):    
    '''
    highlight : None or string
         if string, then only the label of this population is set and the box is highlighted
    '''

    name_to_id_mapping={'L6E':(0,0),
                        'L6I':(0,1),
                        'L5E':(1,0),
                        'L5I':(1,1),
                        'L4E':(2,0),
                        'L4I':(2,1),
                        'L23E':(3,0),
                        'L23I':(3,1)
    } 
    
    showgrid=False  ## switch on/off grid

    ## sketch parameters
    layer_x=0.1                            ## x position of left boundary of cortex layers
    layer6_y=0.2*yscaling                           ## y position of lower boundary of layer 6
    layer_width=0.65                       ## width of cortex layers
    layer_height=0.21*yscaling                      ## height of cortex layers
    layer_colors=['0.9','0.8','0.9','0.8'] ## layer colors
    c_pop_size=0.15                        ## cortex population size
    c_pop_dist=0.17                        ## distance between cortex populations
    t_pop_size=0.15                        ## thalamus population size
    t_pop_y=0.0                         ## y position of lower thalamus boundary
    axon_cell_sep=0.04                     ## distance between axons and popualations
    cc_input_y=0.6*yscaling                        ## y position of cortico-cortical synapses (relative to cortex population)
    tc_input_y=0.4*yscaling                         ## y position of thalamo-cortical synapses (relative to cortex population)

    exc_clr = 'k' if analysis_params.bw else analysis_params.colorE                            ## color of excitatory axons/synapses
    inh_clr = 'gray' if analysis_params.bw else analysis_params.colorI                            ## color of inhibitory axons/synapses

    lw_pop=0.5                              ## linewidth for populations
    lw_axons=0.4                           ## linewidth for axons

    arrow_size=0.013                       ## arrow size
    conn_radius=0.005                      ## radius of connector marker

    legend_length=0.07                     ## length of legend arrows
    
    colors = phlp.get_colors(8)[::-1]            ## colors of each population

    fontdict1={'fontsize': 6, ## population name 
              'weight':'normal',
              'horizontalalignment':'center',
              'verticalalignment':'center'}

    fontdict2={'fontsize': 6, ## cortico-cortical input
              'weight':'normal',
              'horizontalalignment':'center',
              'verticalalignment':'center'}

    fontdict3={'fontsize': 6, ## legend 
              'weight':'normal',
              'horizontalalignment':'left',
              'verticalalignment':'center'}

    ######################################################################################

    def draw_box(ax,pos,lw=1.,ls='solid',eclr='k',fclr='w',zorder=0, clip_on=False,
                 boxstyle=patches.BoxStyle("Round", pad=0.0), padadjust=0.):
        '''Draws a rectangle.'''    
        rect = patches.FancyBboxPatch((pos[0]+padadjust, pos[1]+padadjust),
            pos[2]-2*padadjust, pos[3]-2*padadjust, ec=eclr, fc=fclr,
            lw=lw, ls=ls, zorder=zorder, clip_on=clip_on,
            boxstyle=boxstyle)
        ax.add_patch(rect)

    def draw_circle(ax,xy,radius,lw=1.,ls='solid',eclr='k',fclr='w',zorder=0):
        '''Draws a circle.'''    
        circ = plt.Circle((xy[0],xy[1]),radius=radius, ec=eclr,fc=fclr,lw=lw,ls=ls,zorder=zorder)
        ax.add_patch(circ)

    def put_text(ax,xy,txt,clr,fontdict,zorder=10):
        '''Puts text to a specific position.'''
        ax.text(xy[0],xy[1],txt,fontdict=fontdict,color=clr,zorder=zorder)

    def draw_line(ax,path,lw=1.,ls='solid',lclr='k',zorder=0):
        '''Draws a path.'''
        #pth = path.Path(np.array(path))
        pth = Path(np.array(path))        
        patch = patches.PathPatch(pth, fill=False, lw=lw,ls=ls,ec=lclr,fc=lclr,zorder=zorder)
        ax.add_patch(patch)

    def draw_arrow(ax,path,lw=1.0,ls='solid',lclr='k',arrow_size=0.025,zorder=0):
        '''Draws a path with an arrow at the end. '''
        x=path[-2][0]
        y=path[-2][1]
        dx=path[-1][0]-path[-2][0]
        dy=path[-1][1]-path[-2][1]

        D=np.array([dx,dy])
        D=D/np.sqrt(D[0]**2+D[1]**2)
        path2=np.array(path).copy()
        path2[-1,:]=path2[-1,:]-arrow_size*D

        pth = Path(np.array(path2))
        patch = patches.PathPatch(pth, fill=False, lw=lw,ls=ls,ec=lclr,fc=lclr,zorder=zorder)
        ax.add_patch(patch)

        arr=patches.FancyArrow(\
            x,y,dx,dy,\
                length_includes_head=True,width=0.0,head_width=arrow_size,\
                overhang=0.2,ec=lclr,fc=lclr,linewidth=0)
        ax.add_patch(arr)


    ##################################################
    ## populations

    ## cortex
    layer_pos=[]
    c_pop_pos=[]
    for i in xrange(4):

        ## cortex layers
        layer_pos+=[[layer_x,layer6_y+i*layer_height*yscaling,layer_width,layer_height]] ## layer positions
        draw_box(ax,layer_pos[i],lw=0.,fclr=layer_colors[i],zorder=0)

        ## cortex populations
        l_margin=(layer_width-2.*c_pop_size-c_pop_dist)/2.
        b_margin=(layer_height-c_pop_size)/2.

        ## positions of cortex populations
        c_pop_pos+=[[ [layer_pos[i][0] + l_margin,
                       layer_pos[i][1] + b_margin,
                       c_pop_size, c_pop_size], ## E
                      [layer_pos[i][0] + l_margin + c_pop_size + c_pop_dist,
                       layer_pos[i][1] + b_margin,
                       c_pop_size, c_pop_size]  ]] ## I

        #draw_box(ax,c_pop_pos[i][0],lw=lw_pop,eclr='k',fclr='w',zorder=2) ## E
        #draw_box(ax,c_pop_pos[i][1],lw=lw_pop,eclr='k',fclr='w',zorder=2) ## I    
        draw_box(ax,c_pop_pos[i][0],lw=lw_pop,eclr='k',fclr=colors[i*2+1],zorder=2,
                 boxstyle=patches.BoxStyle("Round", pad=0.02), padadjust=0.02) ## E
        draw_box(ax,c_pop_pos[i][1],lw=lw_pop,eclr='k',fclr=colors[i*2],zorder=2,
                 boxstyle=patches.BoxStyle("Round", pad=0.02), padadjust=0.02) ## I    


    ## thalamus
    c_center_x=layer_x+layer_width/2. ## x position of cortex center
    t_pos=[c_center_x-t_pop_size/2.,t_pop_y*yscaling,t_pop_size,t_pop_size] ## thalamus position
    #draw_box(ax,t_pos,lw=lw_pop,eclr='k',fclr='w',zorder=2) ## Th
    draw_box(ax,t_pos,lw=lw_pop,eclr='k',fclr='k',zorder=2,
             boxstyle=patches.BoxStyle("Round", pad=0.02), padadjust=0.02) ## Th

    ##################################################
    ## intracortical axons

    axon_x_dist=(c_pop_dist-2.*axon_cell_sep)/7.
    assert(axon_x_dist>0.)
    axon_y_dist=c_pop_size/9.#*yscaling
    c_axon_x=[]
    c_axon_y=[]

    # x positions of vertical intracortical axons
    for i in xrange(4): # pre layer
        exc=c_pop_pos[i][0][0]+c_pop_size+axon_cell_sep+i*axon_x_dist ## E
        inh=exc+4.*axon_x_dist ## I
        c_axon_x+=[[exc,inh]]

    # y positions of horizontal intracortical axons
    for i in xrange(4): ## post layer
        c_axon_y+=[[]]
        for j in xrange(4): ## pre layer
            exc=c_pop_pos[i][0][1]+(j+1.)*axon_y_dist ## E
            inh=c_pop_pos[i][0][1]+c_pop_size-(j+1.)*axon_y_dist ## I        
            c_axon_y[i]+=[[exc,inh]]

    ## vertical intracortical axons
    for i in xrange(4):
        draw_line(ax,[[c_axon_x[i][0],c_axon_y[0][i][0]],[c_axon_x[i][0],c_axon_y[-1][i][0]]],lw=lw_axons,ls='solid',lclr=exc_clr,zorder=1)
        draw_line(ax,[[c_axon_x[i][1],c_axon_y[0][i][1]],[c_axon_x[i][1],c_axon_y[-1][i][1]]],lw=lw_axons,ls='solid',lclr=inh_clr,zorder=0)

    ## horizontal intracortical axons
    for i in xrange(4): ## post layer
        for j in xrange(4): ## pre layer
            path=[[c_axon_x[j][0],c_axon_y[i][j][0]],[c_pop_pos[i][0][0]+c_pop_size,c_axon_y[i][j][0]]]        
            draw_arrow(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,arrow_size=arrow_size,zorder=1)

            path=[[c_axon_x[j][0],c_axon_y[i][j][0]],[c_pop_pos[i][1][0],c_axon_y[i][j][0]]]        
            draw_arrow(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,arrow_size=arrow_size,zorder=1)

            path=[[c_axon_x[j][1],c_axon_y[i][j][1]],[c_pop_pos[i][1][0],c_axon_y[i][j][1]]]
            draw_arrow(ax,path,lw=lw_axons,ls='solid',lclr=inh_clr,arrow_size=arrow_size,zorder=0)

            path=[[c_axon_x[j][1],c_axon_y[i][j][1]],[c_pop_pos[i][0][0]+c_pop_size,c_axon_y[i][j][1]]]
            draw_arrow(ax,path,lw=lw_axons,ls='solid',lclr=inh_clr,arrow_size=arrow_size,zorder=0)

            ## connector markers
            draw_circle(ax,[c_axon_x[j][0],c_axon_y[i][j][0]],conn_radius,lw=0,fclr=exc_clr,zorder=0)
            draw_circle(ax,[c_axon_x[j][1],c_axon_y[i][j][1]],conn_radius,lw=0,fclr=inh_clr,zorder=0)        

    ## cell outputs
    for i in xrange(4):

        path=[[c_pop_pos[i][0][0]+c_pop_size/2.,c_pop_pos[i][0][1]],
              [c_pop_pos[i][0][0]+c_pop_size/2.,c_pop_pos[i][0][1]-axon_y_dist],
              [c_axon_x[i][0],c_pop_pos[i][0][1]-axon_y_dist]]
        draw_line(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,zorder=1)  ## excitatory
        draw_circle(ax,path[-1],conn_radius,lw=0,fclr=exc_clr,zorder=0) ## connector

        path=[[c_pop_pos[i][1][0]+c_pop_size/2.,c_pop_pos[i][1][1]],
              [c_pop_pos[i][1][0]+c_pop_size/2.,c_pop_pos[i][1][1]-axon_y_dist],
              [c_axon_x[-1-i][1],c_pop_pos[i][1][1]-axon_y_dist]]
        draw_line(ax,path,lw=lw_axons,ls='solid',lclr=inh_clr,zorder=1)  ## inhibitory
        draw_circle(ax,path[-1],conn_radius,lw=0,fclr=inh_clr,zorder=0) ## connector

    ## remaining first segments for L6
    path=[[c_axon_x[0][0],c_pop_pos[0][0][1]-axon_y_dist],[c_axon_x[0][0],c_axon_y[0][0][0]]]        
    draw_line(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,zorder=0)        
    path=[[c_axon_x[-1][1],c_pop_pos[0][1][1]-axon_y_dist],[c_axon_x[-1][1],c_axon_y[0][0][1]]]        
    draw_line(ax,path,lw=lw_axons,ls='solid',lclr=inh_clr,zorder=0)        

    ##################################################
    ## cortico-cortical axons

    ## horizontal branch in L1
    path=[[0.,c_pop_pos[-1][0][1]+c_pop_size+axon_cell_sep],
          [c_pop_pos[-1][1][0]+c_pop_size+axon_cell_sep,c_pop_pos[-1][0][1]+c_pop_size+axon_cell_sep]]
    draw_line(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,zorder=1)

    ## vertical branches
    path=[[c_pop_pos[-1][0][0]-axon_cell_sep,c_pop_pos[-1][0][1]+c_pop_size+axon_cell_sep],
          [c_pop_pos[-1][0][0]-axon_cell_sep,c_pop_pos[0][0][1]+cc_input_y*c_pop_size]]
    draw_line(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,zorder=1) ## cc input to exc pop
    draw_circle(ax,path[0],conn_radius,lw=0,fclr=exc_clr,zorder=0) ## connector
    path=[[c_pop_pos[-1][1][0]+c_pop_size+axon_cell_sep,c_pop_pos[-1][0][1]+c_pop_size+axon_cell_sep],
          [c_pop_pos[-1][1][0]+c_pop_size+axon_cell_sep,c_pop_pos[0][0][1]+cc_input_y*c_pop_size]]
    draw_line(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,zorder=1) ## cc input to inh pop
    draw_circle(ax,path[0],conn_radius,lw=0,fclr=exc_clr,zorder=0) ## connector

    ## horizontal branches (arrows)
    for i in xrange(4):
        ## cc input to excitatory populations
        path=[[c_pop_pos[-1][0][0]-axon_cell_sep,c_pop_pos[i][0][1]+cc_input_y*c_pop_size],
              [c_pop_pos[-1][0][0],c_pop_pos[i][0][1]+cc_input_y*c_pop_size],]
        draw_arrow(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,arrow_size=arrow_size,zorder=0)
        draw_circle(ax,path[0],conn_radius,lw=0,fclr=exc_clr,zorder=0) ## connector

        ## cc input to inhibitory populations
        path=[[c_pop_pos[-1][1][0]+c_pop_size+axon_cell_sep,c_pop_pos[i][0][1]+cc_input_y*c_pop_size],
              [c_pop_pos[-1][1][0]+c_pop_size,c_pop_pos[i][0][1]+cc_input_y*c_pop_size]]
        draw_arrow(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,arrow_size=arrow_size,zorder=0)
        draw_circle(ax,path[0],conn_radius,lw=0,fclr=exc_clr,zorder=0) ## connector

    ##################################################
    ## thalamo-cortical axons

    path=[[t_pos[0]+t_pop_size/2.,t_pos[1]+t_pop_size],
          [t_pos[0]+t_pop_size/2.,t_pos[1]+t_pop_size+axon_y_dist]]
    draw_line(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,zorder=1) ## thalamic output
    draw_circle(ax,path[-1],conn_radius,lw=0,fclr=exc_clr,zorder=0) ## connector

    path=[[c_pop_pos[0][0][0]-(axon_cell_sep+axon_y_dist),t_pos[1]+t_pop_size+axon_y_dist],
          [c_pop_pos[0][1][0]+c_pop_size+(axon_cell_sep+axon_y_dist),t_pos[1]+t_pop_size+axon_y_dist]]
    draw_line(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,zorder=1) ## horizontal branch

    path=[[c_pop_pos[0][0][0]-(axon_cell_sep+axon_y_dist),t_pos[1]+t_pop_size+axon_y_dist],
          [c_pop_pos[0][0][0]-(axon_cell_sep+axon_y_dist),c_pop_pos[2][0][1]+tc_input_y*c_pop_size]]
    draw_line(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,zorder=1) ## left vertical branch

    path=[[c_pop_pos[0][1][0]+c_pop_size+(axon_cell_sep+axon_y_dist),t_pos[1]+t_pop_size+axon_y_dist],
          [c_pop_pos[0][1][0]+c_pop_size+(axon_cell_sep+axon_y_dist),c_pop_pos[2][0][1]+tc_input_y*c_pop_size]]
    draw_line(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,zorder=1) ## right vertical branch

    path=[[c_pop_pos[0][0][0]-(axon_cell_sep+axon_y_dist),c_pop_pos[2][0][1]+tc_input_y*c_pop_size],
          [c_pop_pos[0][0][0],c_pop_pos[2][0][1]+tc_input_y*c_pop_size],]
    draw_arrow(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,arrow_size=arrow_size,zorder=1) ## Th -> L4E synapses (arrows)
    draw_circle(ax,path[0],conn_radius,lw=0,fclr=exc_clr,zorder=0) ## connector

    path=[[c_pop_pos[0][0][0]-(axon_cell_sep+axon_y_dist),c_pop_pos[0][0][1]+tc_input_y*c_pop_size],
          [c_pop_pos[0][0][0],c_pop_pos[0][0][1]+tc_input_y*c_pop_size],]
    draw_arrow(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,arrow_size=arrow_size,zorder=1) ## Th -> L6E synapses (arrows)
    draw_circle(ax,path[0],conn_radius,lw=0,fclr=exc_clr,zorder=0) ## connector

    path=[[c_pop_pos[0][1][0]+c_pop_size+(axon_cell_sep+axon_y_dist),c_pop_pos[2][0][1]+tc_input_y*c_pop_size],
          [c_pop_pos[0][1][0]+c_pop_size,c_pop_pos[2][0][1]+tc_input_y*c_pop_size],]
    draw_arrow(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,arrow_size=arrow_size,zorder=1) ## Th -> L4I synapses (arrows)
    draw_circle(ax,path[0],conn_radius,lw=0,fclr=exc_clr,zorder=0) ## connector

    path=[[c_pop_pos[0][1][0]+c_pop_size+(axon_cell_sep+axon_y_dist),c_pop_pos[0][0][1]+tc_input_y*c_pop_size],
          [c_pop_pos[0][1][0]+c_pop_size,c_pop_pos[0][0][1]+tc_input_y*c_pop_size],]
    draw_arrow(ax,path,lw=lw_axons,ls='solid',lclr=exc_clr,arrow_size=arrow_size,zorder=1) ## Th -> L6I synapses (arrows)
    draw_circle(ax,path[0],conn_radius,lw=0,fclr=exc_clr,zorder=0) ## connector

    if labels:
        ##################################################
        ## legend
        legend_x=[t_pos[0]+t_pop_size+axon_cell_sep,t_pos[0]+t_pop_size+axon_cell_sep+legend_length]
        legend_y=[t_pos[1],(t_pos[1]+2*t_pop_size/3)]
        draw_arrow(ax,[[legend_x[0],legend_y[1]],[legend_x[1],legend_y[1]]],lw=lw_axons,ls='solid',lclr=exc_clr,arrow_size=arrow_size,zorder=1)
        draw_arrow(ax,[[legend_x[0],legend_y[0]],[legend_x[1],legend_y[0]]],lw=lw_axons,ls='solid',lclr=inh_clr,arrow_size=arrow_size,zorder=1)

        ##################################################
        ## population names

        put_text(ax,[t_pos[0]+t_pop_size/2.,(t_pos[1]+t_pop_size/2.)],r'TC','w',fontdict1)

        put_text(ax,[c_pop_pos[0][0][0]+c_pop_size/2.,c_pop_pos[0][0][1]+c_pop_size/2.],r'L6E','w' if analysis_params.bw else 'k',fontdict1)
        put_text(ax,[c_pop_pos[0][1][0]+c_pop_size/2.,c_pop_pos[0][1][1]+c_pop_size/2.],r'L6I','w' if analysis_params.bw else 'k',fontdict1)
        
        put_text(ax,[c_pop_pos[1][0][0]+c_pop_size/2.,c_pop_pos[1][0][1]+c_pop_size/2.],r'L5E','w' if analysis_params.bw else 'k',fontdict1)
        put_text(ax,[c_pop_pos[1][1][0]+c_pop_size/2.,c_pop_pos[1][1][1]+c_pop_size/2.],r'L5I','w' if analysis_params.bw else 'k',fontdict1)
        
        put_text(ax,[c_pop_pos[2][0][0]+c_pop_size/2.,c_pop_pos[2][0][1]+c_pop_size/2.],r'L4E','w' if analysis_params.bw else 'k',fontdict1)
        put_text(ax,[c_pop_pos[2][1][0]+c_pop_size/2.,c_pop_pos[2][1][1]+c_pop_size/2.],r'L4I','w' if analysis_params.bw else 'k',fontdict1)
    
        put_text(ax,[c_pop_pos[3][0][0]+c_pop_size/2.,c_pop_pos[3][0][1]+c_pop_size/2.],r'L23E','w' if analysis_params.bw else 'k',fontdict1)
        put_text(ax,[c_pop_pos[3][1][0]+c_pop_size/2.,c_pop_pos[3][1][1]+c_pop_size/2.],r'L23I','w' if analysis_params.bw else 'k',fontdict1)
        
        put_text(ax,[c_pop_pos[-1][0][0],
                 c_pop_pos[-1][0][1]+c_pop_size+1.7*axon_cell_sep + 0.01],
                 r'cortico-cortical input','k',fontdict2)

        put_text(ax,[legend_x[1]+axon_y_dist,legend_y[1]],r'excitatory','k',fontdict3)
        put_text(ax,[legend_x[1]+axon_y_dist,legend_y[0]],r'inhibitory','k',fontdict3)

        ##################################################
        ## layer names

        put_text(ax,[0.2*c_pop_pos[0][0][0],c_pop_pos[0][1][1]+c_pop_size/2.],r'L6','k',fontdict1)
        put_text(ax,[0.2*c_pop_pos[1][0][0],c_pop_pos[1][1][1]+c_pop_size/2.],r'L5','k',fontdict1)
        put_text(ax,[0.2*c_pop_pos[2][0][0],c_pop_pos[2][1][1]+c_pop_size/2.],r'L4','k',fontdict1)
        put_text(ax,[0.2*c_pop_pos[3][0][0],c_pop_pos[3][1][1]+c_pop_size/2.],r'L2/3','k',fontdict1)
        
                
    if highlight is not None:
        ids = name_to_id_mapping[highlight]
        fontdict1['fontsize']=4
        put_text(ax,[c_pop_pos[ids[0]][ids[1]][0]+c_pop_size/2.,c_pop_pos[ids[0]][ids[1]][1]+c_pop_size/2.],highlight,'k',fontdict1)

    ax.xaxis.set_ticks([])
    ax.yaxis.set_ticks([])
    ax.axis(ax.axis('equal'))
    
    return ax