Blame LFPy-2.0.7/examples/bioRxiv281717/figure_4.py

7d68d07
# -*- coding: utf-8 -*-
7d68d07
'''plotting script for figure 4 in manuscript preprint on output of
7d68d07
example_parallel_network.py
7d68d07
7d68d07
Copyright (C) 2018 Computational Neuroscience Group, NMBU.
7d68d07
7d68d07
This program is free software: you can redistribute it and/or modify
7d68d07
it under the terms of the GNU General Public License as published by
7d68d07
the Free Software Foundation, either version 3 of the License, or
7d68d07
(at your option) any later version.
7d68d07
7d68d07
This program is distributed in the hope that it will be useful,
7d68d07
but WITHOUT ANY WARRANTY; without even the implied warranty of
7d68d07
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7d68d07
GNU General Public License for more details.
7d68d07
'''
7d68d07
from __future__ import division
7d68d07
import matplotlib.pyplot as plt
7d68d07
from matplotlib.gridspec import GridSpec
7d68d07
from matplotlib.collections import PolyCollection
7d68d07
from matplotlib.ticker import MaxNLocator
7d68d07
import os
7d68d07
import numpy as np
7d68d07
import h5py
7d68d07
from LFPy import NetworkCell
7d68d07
import example_parallel_network_plotting as plotting
7d68d07
from mpi4py import MPI
7d68d07
7d68d07
# set up MPI environment
7d68d07
COMM = MPI.COMM_WORLD
7d68d07
SIZE = COMM.Get_size()
7d68d07
RANK = COMM.Get_rank()
7d68d07
7d68d07
7d68d07
# # set default plotting parameters
7d68d07
plt.rcParams.update({
7d68d07
    'axes.xmargin': 0.0,
7d68d07
    'axes.ymargin': 0.0,
7d68d07
})
7d68d07
fontsize=14
7d68d07
titlesize=16
7d68d07
legendsize=12
7d68d07
plt.rcParams.update({
7d68d07
    'axes.xmargin': 0.0,
7d68d07
    'axes.ymargin': 0.0,
7d68d07
    'axes.labelsize': fontsize,
7d68d07
    'axes.titlesize': titlesize,
7d68d07
    'figure.titlesize': fontsize,
7d68d07
    'font.size': fontsize,
7d68d07
    'legend.fontsize': legendsize,
7d68d07
})
7d68d07
7d68d07
def plot_quantity_YXL(axes, PSET, quantity,
7d68d07
                      y=['p23', 'b23', 'nb23', 'p4', 'ss4(L23)', 'ss4(L4)',
7d68d07
                         'b4', 'nb4', 'p5(L23)', 'p5(L56)', 'b5', 'nb5',
7d68d07
                         'p6(L4)', 'p6(L56)', 'b6', 'nb6'],
7d68d07
                      label=r'$\mathcal{L}_{YXL}$', layers = ['L1', 'L2/3', 'L4', 'L5', 'L6'],
7d68d07
                      cmap=plt.get_cmap('inferno')):
7d68d07
                            
7d68d07
    '''make a bunch of image plots, each showing the spatial normalized
7d68d07
    connectivity of synapses'''
7d68d07
    if np.array(axes).ndim == 1:
7d68d07
        nrows = 1
7d68d07
        ncols = np.array(axes).size
7d68d07
    else:
7d68d07
        (nrows, ncols) = np.array(axes).shape
7d68d07
    
7d68d07
    
7d68d07
    #assess vlims
7d68d07
    vmin = 0
7d68d07
    vmax = 0
7d68d07
    for yi in y:
7d68d07
        if quantity[yi].max() > vmax:
7d68d07
            vmax = quantity[yi].max()
7d68d07
    
7d68d07
    for i, yi in enumerate(y):
7d68d07
        ax = np.array(axes).flatten()[i]
7d68d07
7d68d07
        masked_array = np.ma.array(quantity[yi], mask=quantity[yi]==0)
7d68d07
        
7d68d07
        im = ax.pcolormesh(masked_array,
7d68d07
                            vmin=vmin, vmax=vmax,
7d68d07
                            cmap=cmap,
7d68d07
                            )
7d68d07
        ax.invert_yaxis()
7d68d07
7d68d07
        ax.axis(ax.axis('tight'))
7d68d07
        ax.set_xticks(np.arange(len(y))+0.5)
7d68d07
        ax.set_yticks(np.arange(len(layers))+0.5)
7d68d07
        
7d68d07
        if i % ncols == 0:
7d68d07
            ax.set_yticklabels(layers, )
7d68d07
            ax.set_ylabel('$L$', labelpad=0.)
7d68d07
        else:
7d68d07
            ax.set_yticklabels([])
7d68d07
        if i < ncols:
7d68d07
            ax.set_xlabel(r'$X$', labelpad=-1)
7d68d07
            ax.set_xticklabels(y, rotation=90)
7d68d07
        else:
7d68d07
            ax.set_xticklabels([])
7d68d07
        
7d68d07
        ax.set_title(r'$Y=${}'.format(yi))
7d68d07
    
7d68d07
        #colorbar
7d68d07
        if (i // ncols==0) and (i % ncols) == ncols-1:
7d68d07
            rect = np.array(ax.get_position().bounds)
7d68d07
            rect[0] += rect[2] + 0.0025
7d68d07
            rect[2] = 0.005
7d68d07
            cax = fig.add_axes(rect)
7d68d07
            cbar = plt.colorbar(im, cax=cax)
7d68d07
            cbar.set_label(label, labelpad=0)
7d68d07
7d68d07
def plot_multapseargs(ax, PSET, cmap=plt.get_cmap('inferno'),
7d68d07
                      data='multapseargs', cbarlabel=r'$\overline{n}_\mathrm{syn}$',
7d68d07
                      key='loc'):
7d68d07
7d68d07
    '''make an imshow of connectivity parameters'''
7d68d07
    item = PSET.connParams[data]
7d68d07
    array = [[i[key] for i in j]  for j in item]
7d68d07
    
7d68d07
    masked_array = np.ma.array(array, mask=np.array(array)==0.)
7d68d07
    cmap.set_bad('k', 0.5)
7d68d07
    im = ax.pcolormesh(masked_array, cmap=cmap, vmin=0, )
7d68d07
    ax.axis(ax.axis('tight'))
7d68d07
    ax.invert_yaxis()
7d68d07
    ax.xaxis.set_ticks_position('top')
7d68d07
    ax.set_xticks(np.arange(PSET.populationParameters.size)+0.5)
7d68d07
    ax.set_yticks(np.arange(PSET.populationParameters.size)+0.5)
7d68d07
    ax.set_xticklabels(PSET.populationParameters['m_type'], rotation=270)
7d68d07
    ax.set_yticklabels(PSET.populationParameters['m_type'], )
7d68d07
    ax.xaxis.set_label_position('top')
7d68d07
    ax.set_xlabel(r'$Y$', labelpad=0)
7d68d07
    ax.set_ylabel(r'$X$', labelpad=0, rotation=0)
7d68d07
7d68d07
    rect = np.array(ax.get_position().bounds)
7d68d07
    rect[0] += rect[2] + 0.0025
7d68d07
    rect[2] = 0.005
7d68d07
    fig = plt.gcf()
7d68d07
    cax = fig.add_axes(rect)
7d68d07
7d68d07
    cbar = plt.colorbar(im, cax=cax)
7d68d07
    cbar.set_label(cbarlabel, labelpad=0)
7d68d07
7d68d07
7d68d07
if __name__ == '__main__':
7d68d07
    # get simulation parameters
7d68d07
    from example_parallel_network_parameters import PSET
7d68d07
7d68d07
    # cell type colors 
7d68d07
    colors = [plt.get_cmap('Set1', PSET.populationParameters.size)(i) for i in range(PSET.populationParameters.size)]
7d68d07
7d68d07
    # Set up figure and subplots 
7d68d07
    fig = plt.figure(figsize=(16, 10))
7d68d07
    fig.subplots_adjust(left=0.075, right=0.95, hspace=0.2, wspace=0.7,
7d68d07
                        bottom=0.05, top=0.95)
7d68d07
    gs = GridSpec(16, 40, hspace=0.2, wspace=0.5)
7d68d07
    alphabet = 'ABCDEFG'
7d68d07
    dz = 50 #spatial resolution of histograms
7d68d07
    
7d68d07
    # PANEL A. Morphology overview
7d68d07
    ax = fig.add_subplot(gs[:12, :12])
7d68d07
    plotting.remove_axis_junk(ax, lines=['top', 'bottom', 'right'])
7d68d07
    n_segs, areas = plotting.plot_m_types(ax, PSET, colors, spacing=300.)
7d68d07
    ax.set_title('')
7d68d07
    ax.set_xticks([])
7d68d07
    ax.set_xticklabels([])
7d68d07
    ax.set_ylabel('layer')
7d68d07
    ax.text(-0.05, 1.05, alphabet[0],
7d68d07
        horizontalalignment='center',
7d68d07
        verticalalignment='center',
7d68d07
        fontsize=16, fontweight='demibold',
7d68d07
        transform=ax.transAxes)
7d68d07
    axis = ax.axis()
7d68d07
7d68d07
7d68d07
    ax = fig.add_subplot(gs[12:, :12])
7d68d07
    ax.axis('off')
7d68d07
    ax.set_xlim(left=axis[0], right=axis[1])
7d68d07
7d68d07
    # # table data with population sizes etc.
7d68d07
    h_spacing=300.
7d68d07
    v_spacing=100.
7d68d07
    keys =   ['m_type',              'm_type',               'e_type',             'me_type',       'n_seg',                           'POP_SIZE',                 'F_y',                 'extrinsic_input_density', 'extrinsic_input_frequency',
7d68d07
              'pop_args[loc]',                          'pop_args[scale]']
7d68d07
    labels = ['population ($X/Y$):', 'morphology type (m):', 'electric type (e):', 'cell model #:', 'segment count $n_\mathrm{seg}$:', 'population count $N_X$:', r'Occurrence $F_X$:',  r'$n_\mathrm{ext}$:',      r'$\nu_\mathrm{ext}$ (s$^{-1}$):',
7d68d07
              r'$\overline{z}_X^\mathrm{soma}$ ($\mu$m):', r'$\sigma_{\overline{z},X}^\mathrm{soma}$ ($\mu$m)']
7d68d07
    # PSET.populationParameters
7d68d07
    z = -PSET.layer_data['thickness'].sum()
7d68d07
    ax.set_ylim(top=z-v_spacing, bottom=z-len(keys)*v_spacing+v_spacing)
7d68d07
    for i, (label, key) in enumerate(zip(labels, keys)):
7d68d07
        ax.text(axis[0], z-(i+1)*v_spacing, label, ha='right', va='top')
7d68d07
        for j, popData in enumerate(PSET.populationParameters):
7d68d07
            if key == 'pop_args[loc]':
7d68d07
                ax.text(j*h_spacing, z-(i+1)*v_spacing, int(popData['pop_args']['loc']), ha='center', va='top')
7d68d07
            elif key == 'pop_args[scale]':
7d68d07
                ax.text(j*h_spacing, z-(i+1)*v_spacing, int(popData['pop_args']['scale']), ha='center', va='top')
7d68d07
            elif key == 'me_type':
7d68d07
                ax.text(j*h_spacing, z-(i+1)*v_spacing, popData[key].lstrip(popData['m_type'] + '_' + popData['e_type']), ha='center', va='top')
7d68d07
            elif key == 'n_seg':
7d68d07
                ax.text(j*h_spacing, z-(i+1)*v_spacing, n_segs[j], ha='center', va='top')
7d68d07
            elif key == 'F_y':
7d68d07
                ax.text(j*h_spacing, z-(i+1)*v_spacing, '{:.2f}'.format(popData['POP_SIZE']/PSET.populationParameters['POP_SIZE'].sum()), ha='center', va='top')
7d68d07
            elif key == 'extrinsic_input_density':
7d68d07
                ax.text(j*h_spacing, z-(i+1)*v_spacing, '{:.0f}'.format(int(areas[j]*popData[key])), ha='center', va='top')
7d68d07
            else:
7d68d07
                ax.text(j*h_spacing, z-(i+1)*v_spacing, popData[key], ha='center', va='top')
7d68d07
    
7d68d07
    
7d68d07
    # PANEL B. Connection probability
7d68d07
    ax = fig.add_subplot(gs[:3, 14:17])
7d68d07
    plotting.plot_connectivity(ax, PSET, data='connprob', cbarlabel='')
7d68d07
    ax.xaxis.set_ticks_position('bottom')
7d68d07
    ax.xaxis.set_label_position('bottom')
7d68d07
    ax.set_title(r'$C_{YX}$')
7d68d07
    ax.text(-0.1, 1.15, alphabet[1],
7d68d07
        horizontalalignment='center',
7d68d07
        verticalalignment='center',
7d68d07
        fontsize=16, fontweight='demibold',
7d68d07
        transform=ax.transAxes)
7d68d07
    
7d68d07
    # PANEL C. Mean number of synapses per connection
7d68d07
    ax = fig.add_subplot(gs[:3, 19:22])
7d68d07
    plot_multapseargs(ax, PSET, data='multapseargs', cbarlabel='', key='loc')
7d68d07
    ax.set_yticklabels([])
7d68d07
    ax.set_ylabel('')
7d68d07
    ax.xaxis.set_ticks_position('bottom')
7d68d07
    ax.xaxis.set_label_position('bottom')
7d68d07
    ax.set_title(r'$\overline{n}_\mathrm{syn}$')
7d68d07
    ax.text(-0.1, 1.15, alphabet[2],
7d68d07
        horizontalalignment='center',
7d68d07
        verticalalignment='center',
7d68d07
        fontsize=16, fontweight='demibold',
7d68d07
        transform=ax.transAxes)
7d68d07
7d68d07
    
7d68d07
    # PANEL D. Layer specificites of connections
7d68d07
    axes = [fig.add_subplot(gs[:3, i*4+4:i*4+8]) for i in range(5, 9)]
7d68d07
    plot_quantity_YXL(axes=axes, PSET=PSET,
7d68d07
                      quantity=PSET.L_YXL_m_types,
7d68d07
                      y=PSET.populationParameters['m_type'],
7d68d07
                      layers = PSET.layer_data['layer'],
7d68d07
                      label=r'$\mathcal{L}_{YXL}$')
7d68d07
    for ax in axes:
7d68d07
        ax.set_ylabel('')
7d68d07
    axes[0].text(-0.075, 1.15, alphabet[3],
7d68d07
        horizontalalignment='center',
7d68d07
        verticalalignment='center',
7d68d07
        fontsize=16, fontweight='demibold',
7d68d07
        transform=axes[0].transAxes)
7d68d07
7d68d07
    
7d68d07
    # PANEL E. Population illustration
7d68d07
    ax = fig.add_subplot(gs[6:, 13:20])
7d68d07
    # plot electrode contact points
7d68d07
    ax.plot(PSET.electrodeParams['x'], PSET.electrodeParams['z'], 'ko',
7d68d07
            markersize=5, clip_on=False)
7d68d07
    # plot ECoG electrode
7d68d07
    ax.plot([-PSET.ecogParameters['r'], PSET.ecogParameters['r']], [PSET.ecogParameters['z'][0]]*2, 'gray', lw=5, zorder=-1, clip_on=False)
7d68d07
    
7d68d07
    plotting.remove_axis_junk(ax)
7d68d07
7d68d07
    # draw the first NCELLS cells in each population
7d68d07
    NCELLS = 20
7d68d07
    CWD=PSET.CWD
7d68d07
    CELLPATH=PSET.CELLPATH
7d68d07
    # cell positions and rotations file:
7d68d07
    f = h5py.File(os.path.join(PSET.OUTPUTPATH,
7d68d07
                               'cell_positions_and_rotations.h5'), 'r')
7d68d07
    
7d68d07
    for i, data in enumerate(PSET.populationParameters):
7d68d07
        NRN = data["me_type"]
7d68d07
        os.chdir(os.path.join(CWD, CELLPATH, NRN))
7d68d07
        for j in range(NCELLS):
7d68d07
            try:                
7d68d07
                cell = NetworkCell(**PSET.cellParameters[NRN])
7d68d07
                cell.set_pos(x=f[NRN]['x'][j], y=f[NRN]['y'][j], z=f[NRN]['z'][j])
7d68d07
                cell.set_rotation(x=f[NRN]['x_rot'][j], y=f[NRN]['y_rot'][j], z=f[NRN]['z_rot'][j])
7d68d07
        
7d68d07
                zips = []
7d68d07
                for x, z in cell.get_idx_polygons(projection=('x', 'z')):
7d68d07
                    zips.append(list(zip(x, z)))
7d68d07
        
7d68d07
                polycol = PolyCollection(zips,
7d68d07
                                         edgecolors=colors[i],
7d68d07
                                         linewidths=0.05,
7d68d07
                                         facecolors=colors[i],
7d68d07
                                         label=NRN,
7d68d07
                                         zorder=f[NRN]['y'][j],
7d68d07
                                         )
7d68d07
                ax.add_collection(polycol)
7d68d07
                neuron.h('forall delete_section()')
7d68d07
            except IndexError:
7d68d07
                pass # NCELLS > cell count in population, plotting all there is. 
7d68d07
        os.chdir(CWD)
7d68d07
7d68d07
    ax.axis(ax.axis('equal'))
7d68d07
    ax.set_ylim(-PSET.layer_data['thickness'].sum(), 0)
7d68d07
    # draw lines showing the layer boundaries
7d68d07
    ax.hlines(np.r_[0., -PSET.layer_data['thickness'].cumsum()], -536.09990331936808, 536.09990331936808, 'k', lw=0.5)
7d68d07
    ax.set_yticks(PSET.layer_data['center'])
7d68d07
    ax.set_yticklabels(PSET.layer_data['layer'])
7d68d07
    ax.set_ylabel('layer')
7d68d07
    ax.set_xticks([-data['pop_args']['radius'], 0, data['pop_args']['radius']])
7d68d07
    ax.set_xlabel('$x$ ($\mu$m)')
7d68d07
    
7d68d07
7d68d07
    ax.text(-0.05, 1.05, alphabet[4],
7d68d07
        horizontalalignment='center',
7d68d07
        verticalalignment='center',
7d68d07
        fontsize=16, fontweight='demibold',
7d68d07
        transform=ax.transAxes)
7d68d07
7d68d07
    
7d68d07
    # PANEL F. Population densities across depth 
7d68d07
    ax = fig.add_subplot(gs[6:, 20:24])
7d68d07
    plotting.remove_axis_junk(ax)
7d68d07
    ax.text(-0.075, 1.05, alphabet[5],
7d68d07
        horizontalalignment='center',
7d68d07
        verticalalignment='center',
7d68d07
        fontsize=16, fontweight='demibold',
7d68d07
        transform=ax.transAxes)
7d68d07
    
7d68d07
    # open file for reading
7d68d07
    f = h5py.File(os.path.join(PSET.OUTPUTPATH,
7d68d07
                               'cell_positions_and_rotations.h5'), 'r')
7d68d07
    # spatial bins across depth
7d68d07
    bins = np.arange(0, -PSET.layer_data['thickness'].sum(), -50)[::-1]
7d68d07
    for color, post, key in zip(colors, PSET.populationParameters['m_type'], PSET.populationParameters['me_type']):
7d68d07
        ax.hist(f[key]['z'], bins=bins, color=color, alpha=1, orientation='horizontal', histtype='step', label=r'{}'.format(post), clip_on=False)
7d68d07
    ax.set_xlabel('count')
7d68d07
    axis = ax.axis('tight')
7d68d07
    ax.axis(axis)
7d68d07
    ax.set_ylim(-PSET.layer_data['thickness'].sum(), 0)
7d68d07
    # draw lines showing the layer boundaries
7d68d07
    ax.hlines(np.r_[0., -PSET.layer_data['thickness'].cumsum()], axis[0], axis[1], 'k', lw=0.5)
7d68d07
    ax.set_yticks(PSET.layer_data['center'])
7d68d07
    ax.set_yticklabels([])
7d68d07
    ax.legend(loc=8)
7d68d07
    ax.xaxis.set_major_locator(MaxNLocator(3))
7d68d07
    
7d68d07
7d68d07
    # PANEL G. Resulting densities of synapses across depth onto each cell type
7d68d07
    axes = [fig.add_subplot(gs[6:, i*4+4:i*4+8]) for i in range(5, 9)]
7d68d07
    axes[0].text(-0.075, 1.05, alphabet[6],
7d68d07
        horizontalalignment='center',
7d68d07
        verticalalignment='center',
7d68d07
        fontsize=16, fontweight='demibold',
7d68d07
        transform=axes[0].transAxes)
7d68d07
    
7d68d07
    # spatial bins across depth
7d68d07
    bins = np.arange(0, -PSET.layer_data['thickness'].sum(), -50)[::-1]
7d68d07
7d68d07
    # file output
7d68d07
    f = h5py.File(os.path.join(PSET.OUTPUTPATH, 'synapse_positions.h5'))
7d68d07
    for i, (m_post, post) in enumerate(zip(PSET.populationParameters['m_type'], PSET.populationParameters['me_type'])):
7d68d07
        ax = axes[i]
7d68d07
        plotting.remove_axis_junk(ax)
7d68d07
        ax.set_xlabel('count ($10^3$)')
7d68d07
        ax.set_yticklabels([])
7d68d07
        ax.set_title(r'$Y=${}'.format(m_post))
7d68d07
        for color, m_pre, pre in zip(colors, PSET.populationParameters['m_type'], PSET.populationParameters['me_type']):
7d68d07
            key = '{}:{}'.format(pre, post)
7d68d07
            ax.hist(f[key]['z'], bins=bins, color=color, alpha=1, orientation='horizontal', histtype='step', label=r'{}'.format(m_pre), clip_on=False, weights=1E-3*np.ones(f[key]['z'].size))
7d68d07
        axis = ax.axis('tight')
7d68d07
        ax.axis(axis)
7d68d07
        ax.set_ylim(-PSET.layer_data['thickness'].sum(), 0)
7d68d07
        # draw lines showing the layer boundaries
7d68d07
        ax.hlines(np.r_[0., -PSET.layer_data['thickness'].cumsum()], axis[0], axis[1], 'k', lw=0.5)
7d68d07
        ax.set_yticks(PSET.layer_data['center'])
7d68d07
        ax.xaxis.set_major_locator(MaxNLocator(2))
7d68d07
        
7d68d07
7d68d07
                
7d68d07
7d68d07
7d68d07
    fig.savefig(os.path.join(PSET.OUTPUTPATH, 'figure_4.pdf'), bbox_inches='tight')
7d68d07
7d68d07
    plt.show()