Calculation of coverage factors of bipolar cell types in inner and outer plexiform layer
based on convex hulls


In [1]:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from scipy.io import loadmat
from scipy.spatial import ConvexHull
import pandas as pd
import seaborn as sns
from shapely.geometry import Polygon
import shapely.ops
%matplotlib inline
matplotlib.rcParams.update({'font.size': 14})
sns.set_style("whitegrid")
matplotlib.rcParams['font.family'] = 'sans-serif'
matplotlib.rcParams['font.sans-serif'] = ['Arial']

In [2]:
skeleton_data=loadmat('data/skeletons_OPL_final.mat')
skeleton_ids=skeleton_data['kn_allSkeletons_e2006_IDs'].flatten()
skeletons=skeleton_data['kn_allSkeletons_e2006'].flatten()
M=np.loadtxt('data/coordinate_rotation')
cell_ids=np.loadtxt('data/BC_IDs_new')

In [3]:
soma_data=loadmat('data/soma_positions.mat')
soma_pos=soma_data['kn_e2006_ALLSKELETONS_FINAL2012_allSomata']
soma_internal_ids=soma_data['kn_e2006_ALLSKELETONS_FINAL2012_cellIDs']
soma_line_ids=soma_data['kn_e2006_ALLSKELETONS_FINAL2012_cellIDs_pure_forSomata']

In [4]:
BC_excluded=np.array([691,709,827,836])

In [5]:
def coverage(selection,layer):
    area=[]
    total_nodes=np.empty((0,2))
    polygons=[]
    for cell in cell_ids[selection,0]:
        if not cell in BC_excluded:
            nodes_cell=np.empty((0,3))
            for skel in np.where(skeleton_ids==cell)[0]:
                nodes=skeletons[skel].item()[list(skeletons[skel].dtype.names).index('nodes')][:,:3]
                edges=skeletons[skel].item()[list(skeletons[skel].dtype.names).index('edges')]
                nodes=nodes[np.unique(edges)-1,:]
                if nodes.shape[0]<2:
                    continue
                nodes=nodes[:,:3]/[16.5,16.5,25]
                nodes=np.dot(M,nodes.T).T
                soma=np.dot(M,soma_pos[soma_line_ids[0,np.where(soma_internal_ids==cell_ids[cell_ids[:,0]==390,1])[1][0]]-1,:3].T).T
                if layer=='OPL':
                    nodes_cell=np.concatenate((nodes_cell,nodes[nodes[:,0]<soma[0],0:3]),axis=0)
                elif layer=='IPL':
                    nodes_cell=np.concatenate((nodes_cell,nodes[nodes[:,0]>soma[0],0:3]),axis=0) 
                else:
                    print("Layer has to be 'IPL' or 'OPL'")
                    return(np.nan,np.nan,np.nan)
            nodes_cell=nodes_cell[:,1:]/[2000/33,40]
            if nodes_cell.shape[0]>2:
                total_nodes=np.concatenate((total_nodes,nodes_cell),axis=0)
                hull=ConvexHull(nodes_cell)
                polygons.append(Polygon(nodes_cell[hull.vertices,:]))    
    for i in range(len(polygons)):
        area.append(polygons[i].area)
    area=np.array(area)
    hull=ConvexHull(total_nodes)
    overlaps=[]
    for i in range(len(polygons)):
        for j in range(i+1,len(polygons)):
            overlaps.append([cell_ids[selection,0][i],cell_ids[selection,0][j],polygons[i].intersection(polygons[j]).area])
    overlaps=np.array(overlaps)
    return(np.mean(area),np.std(area)/np.sqrt(len(area)-1),np.sum(area)/shapely.ops.cascaded_union(polygons).area)

In [6]:
BC_data=np.zeros((14,8))
BC_data[:,0]=np.arange(58,72)

In [7]:
for i in range(len(BC_data)):
    BC_data[i,1]=np.sum((cell_ids[:,4]==BC_data[i,0])&(np.in1d(cell_ids[:,0],BC_excluded,invert=True)))
    BC_data[i,2:5]=coverage(cell_ids[:,4]==BC_data[i,0],'OPL')
    BC_data[i,5:8]=coverage(cell_ids[:,4]==BC_data[i,0],'IPL')

In [8]:
BC_data=pd.DataFrame(BC_data,columns=['type','n','OPL_hull_mean','OPL_hull_SEM','OPL_coverage','IPL_hull_mean','IPL_hull_SEM','IPL_coverage'])

In [ ]: