def testTreeStructure(self): self.loadTTree() cm = CompartmentFitter(self.tree) # set of locations fit_locs1 = [(1,.5), (4,.5), (5,.5)] # no bifurcations fit_locs2 = [(1,.5), (4,.5), (5,.5), (8,.5)] # w bifurcation, should be added fit_locs3 = [(1,.5), (4,1.), (5,.5), (8,.5)] # w bifurcation, already added # test fit_locs1, no bifurcation are added # input paradigm 1 cm.setCTree(fit_locs1, extend_w_bifurc=True)
def testChannelFitMats(self): self.loadBall() cm = CompartmentFitter(self.tree) cm.setCTree([(1, .5)]) # check if reversals are correct for key in set(cm.ctree[0].currents) - {'L'}: assert np.abs(cm.ctree[0].currents[key][1] - \ self.tree[1].currents[key][1]) < 1e-10 # fit the passive model cm.fitPassive(use_all_channels=False) fit_mats_cm_na = cm.evalChannel('Na_Ta', parallel=False) fit_mats_cm_k = cm.evalChannel('Kv3_1', parallel=False) fit_mats_control_na, fit_mats_control_k = self.reduceExplicit() # test whether potassium fit matrices agree for fm_cm, fm_control in zip(fit_mats_cm_k, fit_mats_control_k): assert np.allclose(np.sum(fm_cm[0]), fm_control[0][0, 0]) # feature matrices assert np.allclose(fm_cm[1], fm_control[1]) # target vectors # test whether sodium fit matrices agree for fm_cm, fm_control in zip(fit_mats_cm_na[4:], fit_mats_control_na): assert np.allclose(np.sum(fm_cm[0]), fm_control[0][0, 0]) # feature matrices assert np.allclose(fm_cm[1], fm_control[1]) # target vectors
def testFitModel(self): self.loadTTree() fit_locs = [(1,.5), (4,1.), (5,.5), (8,.5)] # fit a tree directly from CompartmentTree greens_tree = self.tree.__copy__(new_tree=GreensTree()) greens_tree.setCompTree() freqs = np.array([0.]) greens_tree.setImpedance(freqs) z_mat = greens_tree.calcImpedanceMatrix(fit_locs)[0] ctree = greens_tree.createCompartmentTree(fit_locs) ctree.computeGMC(z_mat) sov_tree = self.tree.__copy__(new_tree=SOVTree()) sov_tree.calcSOVEquations() alphas, phimat = sov_tree.getImportantModes(locarg=fit_locs) ctree.computeC(-alphas[0:1].real*1e3, phimat[0:1,:].real) # fit a tree with compartmentfitter cm = CompartmentFitter(self.tree) ctree_cm = cm.fitModel(fit_locs) # compare the two trees self._checkPasCondProps(ctree_cm, ctree) self._checkPasCaProps(ctree_cm, ctree) self._checkEL(ctree_cm, -75.) # check active channel self.fitBall() locs = [(1, 0.5)] cm = CompartmentFitter(self.tree) ctree_cm_1 = cm.fitModel(locs, parallel=False, use_all_chans_for_passive=False) ctree_cm_2 = cm.fitModel(locs, parallel=False, use_all_chans_for_passive=True) self._checkAllCurrProps(self.ctree, ctree_cm_1) self._checkAllCurrProps(self.ctree, ctree_cm_2)
def testRecalcImpedanceMatrix(self, g_inp=np.linspace(0., 0.01, 20)): self.loadBall() fit_locs = [(1, .5)] cm = CompartmentFitter(self.tree) cm.setCTree(fit_locs) # test only leak # compute impedances explicitly greens_tree = cm.createTreeGF(channel_names=[]) greens_tree.setEEq(-75.) greens_tree.setImpedancesInTree() z_mat = greens_tree.calcImpedanceMatrix(fit_locs, explicit_method=False)[0] z_test = z_mat[:, :, None] / (1. + z_mat[:, :, None] * g_inp[None, None, :]) # compute impedances with compartmentfitter function z_calc = np.array([ \ cm.recalcImpedanceMatrix('fit locs', [g_i], \ channel_names=[] ) \ for g_i in g_inp \ ]) z_calc = np.swapaxes(z_calc, 0, 2) assert np.allclose(z_calc, z_test) # test with z based on all channels (passive) # compute impedances explicitly greens_tree = cm.createTreeGF( channel_names=list(cm.tree.channel_storage.keys())) greens_tree.setEEq(-75.) greens_tree.setImpedancesInTree() z_mat = greens_tree.calcImpedanceMatrix(fit_locs, explicit_method=False)[0] z_test = z_mat[:, :, None] / (1. + z_mat[:, :, None] * g_inp[None, None, :]) # compute impedances with compartmentfitter function z_calc = np.array([ \ cm.recalcImpedanceMatrix('fit locs', [g_i], \ channel_names=list(cm.tree.channel_storage.keys())) \ for g_i in g_inp \ ]) z_calc = np.swapaxes(z_calc, 0, 2) assert np.allclose(z_calc, z_test)
def testParallel(self, w_benchmark=False): self.loadTSegmentTree() locs = [(nn.index,0.5) for nn in self.tree.nodes[:30]] cm = CompartmentFitter(self.tree) ctree_cm = cm.fitModel(locs, parallel=False, use_all_chans_for_passive=True) if w_benchmark: from timeit import default_timer as timer t0 = timer() cm.fitChannels(recompute=False, pprint=False, parallel=False) t1 = timer() print('Not parallel: %.8f s'%(t1-t0)) t0 = timer() cm.fitChannels(recompute=False, pprint=False, parallel=True) t1 = timer() print('Parallel: %.8f s'%(t1-t0))
def testCreateTreeGF(self): self.loadBall() cm = CompartmentFitter(self.tree) # create tree with only 'L' tree_pas = cm.createTreeGF() self._checkChannels(tree_pas, []) # create tree with only 'Na_Ta' tree_na = cm.createTreeGF(['Na_Ta']) self._checkChannels(tree_na, ['Na_Ta']) # create tree with only 'Kv3_1' tree_k = cm.createTreeGF(['Kv3_1']) self._checkChannels(tree_k, ['Kv3_1']) # create tree with all channels tree_all = cm.createTreeGF(['Na_Ta', 'Kv3_1']) self._checkChannels(tree_all, ['Na_Ta', 'Kv3_1'])
def testSynRescale(self, g_inp=np.linspace(0., 0.01, 20)): e_rev, v_eq = 0., -75. self.loadBallAndStick() fit_locs = [(4, .7)] syn_locs = [(4, 1.)] cm = CompartmentFitter(self.tree) cm.setCTree(fit_locs) # compute impedance matrix greens_tree = cm.createTreeGF(channel_names=[]) greens_tree.setEEq(-75.) greens_tree.setImpedancesInTree() z_mat = greens_tree.calcImpedanceMatrix(fit_locs + syn_locs)[0] # analytical synapse scale factors beta_calc = 1. / (1. + (z_mat[1, 1] - z_mat[0, 0]) * g_inp) beta_full = z_mat[0,1] / z_mat[0,0] * (e_rev - v_eq) / \ ((1. + (z_mat[1,1] - z_mat[0,0]) * g_inp ) * (e_rev - v_eq)) # synapse scale factors from compartment fitter beta_cm = np.array([cm.fitSynRescale(fit_locs, syn_locs, [0], [g_i], e_revs=[0.])[0] \ for g_i in g_inp]) assert np.allclose(beta_calc, beta_cm, atol=.020) assert np.allclose(beta_full, beta_cm, atol=.015)
def runCalciumCoinc(recompute_ctree=False, recompute_biophys=False, axdict=None, pshow=True): global D2S_CASPIKE, D2S_APIC global CA_LOC lss_ = ['-', '-.', '--'] css_ = [colours[3], colours[0], colours[1]] lws_ = [.8, 1.2, 1.6] # create the full model phys_tree = getL5Pyramid() sim_tree = phys_tree.__copy__(new_tree=NeuronSimTree()) # compartmentfitter object cfit = CompartmentFitter(phys_tree, name='bac_firing', path='data/') # single branch initiation zone branch = sim_tree.pathToRoot(sim_tree[236])[::-1] locs_sb = sim_tree.distributeLocsOnNodes(D2S_CASPIKE, node_arg=branch, name='single branch') # abpical trunk locations apic = sim_tree.pathToRoot(sim_tree[221])[::-1] locs_apic = sim_tree.distributeLocsOnNodes(D2S_APIC, node_arg=apic, name='apic connection') # store set of locations fit_locs = [(1, .5)] + locs_apic + locs_sb sim_tree.storeLocs(fit_locs, name='ca coinc') # PSP input location index ca_ind = sim_tree.getNearestLocinds([CA_LOC], name='ca coinc')[0] # obtain the simplified tree ctree, clocs = getCTree(cfit, fit_locs, 'data/ctree_bac_firing', recompute_biophys=recompute_biophys, recompute_ctree=recompute_ctree) # print(ctree) print('--- ctree nodes currents') print('\n'.join([str(n.currents) for n in ctree])) reslist, creslist_sb, creslist_sb_ = [], [], [] locindslist_sb, locindslist_apic_sb = [], [] if axdict is None: pl.figure('inp') axes_input = [pl.subplot(131), pl.subplot(132), pl.subplot(133)] pl.figure('V trace') axes_trace = [pl.subplot(131), pl.subplot(132), pl.subplot(133)] pl.figure('morph') axes_morph = [pl.subplot(121), pl.subplot(122)] else: axes_input = axdict['inp'] axes_trace = axdict['trace'] axes_morph = axdict['morph'] pshow = False for jj, stim in enumerate(['current', 'psp', 'coinc']): print('--- sim full ---') rec_locs = sim_tree.getLocs('ca coinc') # runn the simulation res = runCaCoinc(sim_tree, rec_locs, ca_ind, 0, stim_type=stim, rec_kwargs=dict(record_from_syns=True, record_from_iclamps=True)) print('---- sim reduced ----') rec_locs = clocs # run the simulation of the reduced tree csim_tree = createReducedNeuronModel(ctree) cres = runCaCoinc(csim_tree, rec_locs, ca_ind, 0, stim_type=stim, rec_kwargs=dict(record_from_syns=True, record_from_iclamps=True)) id_offset = 1. vd_offset = 7.2 vlim = (-80., 20.) ilim = (-.1, 2.2) # input current ax = axes_input[jj] ax.plot(res['t'], -res['i_clamp'][0], c='r', lw=lwidth) ax.plot(res['t'], res['i_syn'][0] + id_offset, c='b', lw=lwidth) ax.set_yticks([0., id_offset]) if jj == 1 or jj == 2: drawScaleBars(ax, ylabel=' nA', b_offset=0) else: drawScaleBars(ax) if jj == 2: ax.set_yticklabels([r'Soma', r'Dend']) ax.set_ylim(ilim) # somatic trace ax = axes_trace[jj] ax.set_xticks([0., 50.]) ax.plot(res['t'], res['v_m'][0], c='DarkGrey', lw=lwidth) ax.plot(cres['t'], cres['v_m'][0], c=cll[0], lw=1.6 * lwidth, ls='--') # dendritic trace ax.plot(res['t'], res['v_m'][ca_ind] + vd_offset, c='DarkGrey', lw=lwidth) ax.plot(cres['t'], cres['v_m'][ca_ind] + vd_offset, c=cll[1], lw=1.6 * lwidth, ls='--') ax.set_yticks([cres['v_m'][0][0], cres['v_m'][ca_ind][0] + vd_offset]) if jj == 1 or jj == 2: drawScaleBars(ax, xlabel=' ms', ylabel=' mV', b_offset=15) # drawScaleBars(ax, xlabel=' ms', b_offset=25) else: drawScaleBars(ax) if jj == 2: ax.set_yticklabels([r'Soma', r'Dend']) ax.set_ylim(vlim) print('iv') plocs = sim_tree.getLocs('ca coinc') markers = [{'marker': 's', 'mfc': cfl[0], 'mec': 'k', 'ms': markersize/1.1}] + \ [{'marker': 's', 'mfc': cfl[1], 'mec': 'k', 'ms': markersize/1.1} for _ in locs_apic + locs_sb] markers[ca_ind]['marker'] = 'v' plotargs = {'lw': lwidth / 1.3, 'c': 'DarkGrey'} sim_tree.plot2DMorphology(axes_morph[0], use_radius=False, plotargs=plotargs, marklocs=plocs, locargs=markers, lims_margin=0.01) # compartment tree dendrogram labelargs = { 0: { 'marker': 's', 'mfc': cfl[0], 'mec': 'k', 'ms': markersize * 1.2 } } labelargs.update({ ii: { 'marker': 's', 'mfc': cfl[1], 'mec': 'k', 'ms': markersize * 1.2 } for ii in range(1, len(plocs)) }) ctree.plotDendrogram(axes_morph[1], plotargs={ 'c': 'k', 'lw': lwidth }, labelargs=labelargs) pl.show()
def basalAPBackProp(recompute_ctree=False, recompute_biophys=False, axes=None, pshow=True): global STIM_PARAMS, D2S_BASAL, SLOCS global CMAP_MORPH rc, rb = recompute_ctree, recompute_biophys if axes is None: pl.figure(figsize=(7,5)) ax1, ax2, ax4, ax5 = pl.subplot(221), pl.subplot(223), pl.subplot(222), pl.subplot(224) divider = make_axes_locatable(ax1) ax3 = divider.append_axes("top", "30%", pad="10%") ax4, ax5 = myAx(ax4), myAx(ax5) pl.figure(figsize=(5,5)) gs = GridSpec(2,2) ax_morph, ax_red1, ax_red2 = pl.subplot(gs[:,0]), pl.subplot(gs[1,0]), pl.subplot(gs[1,1]) else: ax1, ax2, ax3 = axes['trace'] ax4, ax5 = axes['amp-delay'] ax_morph, ax_red1, ax_red2 = axes['morph'] pshow = False # create the full model phys_tree = getL23PyramidNaK() sim_tree = phys_tree.__copy__(new_tree=NeuronSimTree()) # distribute locations to measure backAPs on branches leafs_basal = [node for node in sim_tree.leafs if node.swc_type == 3] branches = [sim_tree.pathToRoot(leaf)[::-1] for leaf in leafs_basal] locslist = [sim_tree.distributeLocsOnNodes(D2S_BASAL, node_arg=branch) for branch in branches] branchlist = [b for ii, b in enumerate(branches) if len(locslist[ii]) == 3] locs = [locs for locs in locslist if len(locs) == 3][1] # do back prop sims amp_diffs_3loc, delay_diffs_3loc = np.zeros(3), np.zeros(3) amp_diffs_1loc, delay_diffs_1loc = np.zeros(3), np.zeros(3) amp_diffs_biop, delay_diffs_biop = np.zeros(3), np.zeros(3) # compartmentfitter object cfit = CompartmentFitter(phys_tree, name='basal_bAP', path='data/') # create reduced tree ctree, clocs = getCTree(cfit, [SLOCS[0]] + locs, 'data/ctree_basal_bAP_3loc', recompute_ctree=rc, recompute_biophys=rb) csimtree = createReducedNeuronModel(ctree) print(ctree) # run the simulation of he full tree res = runSim(sim_tree, locs, SLOCS[0], stim_params=STIM_PARAMS) calcAmpDelayWidth(res) amp_diffs_biop[:] = res['amp'][1:] delay_diffs_biop[:] = res['delay'][1:] # run the simulation of the reduced tree cres = runSim(csimtree, clocs[1:], clocs[0], stim_params=STIM_PARAMS) calcAmpDelayWidth(cres) amp_diffs_3loc[:] = cres['amp'][1:] delay_diffs_3loc[:] = cres['delay'][1:] # reduced models with one single dendritic site creslist = [] for jj, loc in enumerate(locs): # create reduced tree with all 1 single dendritic site locs ctree, clocs = getCTree(cfit, [SLOCS[0]] + [loc], 'data/ctree_basal_bAP_1loc%d'%jj, recompute_ctree=rc, recompute_biophys=False) csimtree = createReducedNeuronModel(ctree) print(ctree) # run the simulation of the reduced tree cres_ss = runSim(csimtree, [clocs[1]], clocs[0], stim_params=STIM_PARAMS) calcAmpDelayWidth(cres_ss) creslist.append(cres_ss) amp_diffs_1loc[jj] = cres_ss['amp'][1] delay_diffs_1loc[jj] = cres_ss['delay'][1] ylim = (-90., 60.) x_range = np.array([-3.,14]) xlim = (0., 12.) tp_full = res['t'][np.argmax(res['v_m'][0])] tp_3comp = cres['t'][np.argmax(cres['v_m'][0])] tp_1comp = creslist[2]['t'][np.argmax(creslist[2]['v_m'][0])] tlim_full = tp_full + x_range tlim_3comp = tp_3comp + x_range tlim_1comp = tp_1comp + x_range i0_full, i1_full = np.round(tlim_full / DT).astype(int) i0_3comp, i1_3comp = np.round(tlim_3comp / DT).astype(int) i0_1comp, i1_1comp = np.round(tlim_1comp / DT).astype(int) ax1.set_ylabel(r'soma') ax1.plot(res['t'][i0_full:i1_full] - tlim_full[0], res['v_m'][0][i0_full:i1_full], lw=lwidth, c='DarkGrey', label=r'full') ax1.plot(cres['t'][i0_3comp:i1_3comp] - tlim_3comp[0], cres['v_m'][0][i0_3comp:i1_3comp], ls='--', lw=1.6*lwidth, c=colours[0], label=r'3 comp') ax1.plot(creslist[2]['t'][i0_1comp:i1_1comp] - tlim_1comp[0], creslist[2]['v_m'][0][i0_1comp:i1_1comp], ls='-.', lw=1.6*lwidth, c=colours[1], label=r'1 comp') ax1.set_ylim(ylim) # ax1.set_xlim(xlim) drawScaleBars(ax1, b_offset=15) myLegend(ax1, add_frame=False, loc='center left', bbox_to_anchor=[0.35, 0.55], fontsize=ticksize, labelspacing=.8, handlelength=2., handletextpad=.2) ax2.set_ylabel(r'dend' + '\n($d_{soma} = 150$ $\mu$m)') ax2.plot(res['t'][i0_full:i1_full] - tlim_full[0], res['v_m'][3][i0_full:i1_full], lw=lwidth, c='DarkGrey', label=r'full') ax2.plot(cres['t'][i0_3comp:i1_3comp] - tlim_3comp[0], cres['v_m'][3][i0_3comp:i1_3comp], ls='--', lw=1.6*lwidth, c=colours[0], label=r'3 comp') ax2.plot(creslist[2]['t'][i0_1comp:i1_1comp] - tlim_1comp[0], creslist[2]['v_m'][1][i0_1comp:i1_1comp], ls='-.', lw=1.6*lwidth, c=colours[1], label=r'1 comp') imax = np.argmax(res['v_m'][3]) xp = res['t'][imax] ax2.annotate(r'$v_{amp}$', xy=(xlim[0], np.mean(ylim)), xytext=(xlim[0], np.mean(ylim)), fontsize=ticksize, ha='center', va='center', rotation=90.) ax2.annotate(r'$t_{delay}$', xy=(xp, ylim[1]), xytext=(xp, ylim[1]), fontsize=ticksize, ha='center', va='center', rotation=0.) ax2.set_ylim(ylim) ax2.set_xlim(xlim) drawScaleBars(ax2, xlabel=' ms', ylabel=' mV', b_offset=15) # myLegend(ax2, add_frame=False, ncol=2, fontsize=ticksize, # loc='upper center', bbox_to_anchor=[.5, -.1], # labelspacing=.6, handlelength=2., handletextpad=.2, columnspacing=.5) ax3.plot(res['t'][i0_full:i1_full] - tlim_full[0], -res['i_clamp'][0][i0_full:i1_full], lw=lwidth, c='r') ax3.set_yticks([0.,3.]) drawScaleBars(ax3, ylabel=' nA', b_offset=0) # ax3.set_xlim(xlim) # color the branches cnodes = [b for branch in branches for b in branch] if cnodes is None: plotargs = {'lw': lwidth/1.3, 'c': 'DarkGrey'} cs = {node.index: 0 for node in sim_tree} else: plotargs = {'lw': lwidth/1.3} cinds = [n.index for n in cnodes] cs = {node.index: 1 if node.index in cinds else 0 for node in sim_tree} # mark example locations plocs = [SLOCS[0]] + locs markers = [{'marker': 's', 'c': cfl[0], 'mec': 'k', 'ms': markersize}] + \ [{'marker': 's', 'c': cfl[1], 'mec': 'k', 'ms': markersize} for _ in plocs[1:]] # plot morphology sim_tree.plot2DMorphology(ax_morph, use_radius=False, plotargs=plotargs, cs=cs, cmap=CMAP_MORPH, marklocs=plocs, locargs=markers, lims_margin=0.01) # plot compartment tree schematic ctree_3l = cfit.setCTree([SLOCS[0]] + locs) ctree_3l = cfit.ctree ctree_1l = cfit.setCTree([SLOCS[0]] + locs[0:1]) ctree_1l = cfit.ctree labelargs = {0: {'marker': 's', 'mfc': cfl[0], 'mec': 'k', 'ms': markersize*1.2}} labelargs.update({ii: {'marker': 's', 'mfc': cfl[1], 'mec': 'k', 'ms': markersize*1.2} for ii in range(1,len(plocs))}) ctree_3l.plotDendrogram(ax_red1, plotargs={'c':'k', 'lw': lwidth}, labelargs=labelargs) labelargs = {0: {'marker': 's', 'mfc': cfl[0], 'mec': 'k', 'ms': markersize*1.2}, 1: {'marker': 's', 'mfc': cfl[1], 'mec': 'k', 'ms': markersize*1.2}} ctree_1l.plotDendrogram(ax_red2, plotargs={'c':'k', 'lw': lwidth}, labelargs=labelargs) ax_red1.set_xticks([]); ax_red1.set_yticks([]) ax_red1.set_xlabel(r'$\Delta x = 50$ $\mu$m', fontsize=ticksize,rotation=60) ax_red2.set_xticks([]); ax_red2.set_yticks([]) ax_red2.set_xlabel(r'$\Delta x = 150$ $\mu$m', fontsize=ticksize,rotation=60) xb = np.arange(3) bwidth = 1./4. xtls = [r'50', r'100', r'150'] ax4, ax5 = myAx(ax4), myAx(ax5) ax4.bar(xb-bwidth, amp_diffs_biop, width=bwidth, align='center', color='DarkGrey', edgecolor='k', label=r'full') ax4.bar(xb, amp_diffs_3loc, width=bwidth, align='center', color=colours[0], edgecolor='k', label=r'4 comp') ax4.bar((xb+bwidth)[-1:], amp_diffs_1loc[-1:], width=bwidth, align='center', color=colours[1], edgecolor='k', label=r'2 comp') ax4.set_ylabel(r'$v_{amp}$ (mV)') ax4.set_xticks(xb) ax4.set_xticklabels([]) ax4.set_ylim(50.,110.) ax4.set_yticks([50., 80.]) myLegend(ax4, add_frame=False, loc='lower center', bbox_to_anchor=[.5, 1.05], fontsize=ticksize, labelspacing=.1, handlelength=1., handletextpad=.2, columnspacing=.5) ax5.bar(xb-bwidth, delay_diffs_biop, width=bwidth, align='center', color='DarkGrey', edgecolor='k', label=r'full') ax5.bar(xb, delay_diffs_3loc, width=bwidth, align='center', color=colours[0], edgecolor='k', label=r'4 comp') ax5.bar((xb+bwidth)[-1:], delay_diffs_1loc[-1:], width=bwidth, align='center', color=colours[1], edgecolor='k', label=r'2 comp') ax5.set_ylabel(r'$t_{delay}$ (ms)') ax5.set_xticks(xb) ax5.set_xticklabels(xtls) ax5.set_xlabel(r'$d_{soma}$ ($\mu$m)') ax5.set_yticks([0., 0.5]) if pshow: pl.show()
def testPassiveFit(self): self.loadTTree() fit_locs = [(1, .5), (4, 1.), (5, .5), (8, .5)] # fit a tree directly from CompartmentTree greens_tree = self.tree.__copy__(new_tree=GreensTree()) greens_tree.setCompTree() freqs = np.array([0.]) greens_tree.setImpedance(freqs) z_mat = greens_tree.calcImpedanceMatrix(fit_locs)[0].real ctree = greens_tree.createCompartmentTree(fit_locs) ctree.computeGMC(z_mat) sov_tree = self.tree.__copy__(new_tree=SOVTree()) sov_tree.calcSOVEquations() alphas, phimat = sov_tree.getImportantModes(locarg=fit_locs) ctree.computeC(-alphas[0:1].real * 1e3, phimat[0:1, :].real) # fit a tree with compartment fitter cm = CompartmentFitter(self.tree) cm.setCTree(fit_locs) cm.fitPassive() cm.fitCapacitance() cm.fitEEq() # check whether both trees are the same self._checkPasCondProps(ctree, cm.ctree) self._checkPasCaProps(ctree, cm.ctree) self._checkEL(cm.ctree, -75.) # test whether all channels are used correctly for passive fit self.loadBall() fit_locs = [(1, .5)] # fit ball model with only leak greens_tree = self.tree.__copy__(new_tree=GreensTree()) greens_tree.channel_storage = {} for n in greens_tree: n.currents = {'L': n.currents['L']} greens_tree.setCompTree() freqs = np.array([0.]) greens_tree.setImpedance(freqs) z_mat = greens_tree.calcImpedanceMatrix(fit_locs)[0].real ctree_leak = greens_tree.createCompartmentTree(fit_locs) ctree_leak.computeGMC(z_mat) sov_tree = greens_tree.__copy__(new_tree=SOVTree()) sov_tree.calcSOVEquations() alphas, phimat = sov_tree.getImportantModes(locarg=fit_locs) ctree_leak.computeC(-alphas[0:1].real * 1e3, phimat[0:1, :].real) # make ball model with leak based on all channels tree = self.tree.__copy__() tree.asPassiveMembrane() greens_tree = tree.__copy__(new_tree=GreensTree()) greens_tree.setCompTree() freqs = np.array([0.]) greens_tree.setImpedance(freqs) z_mat = greens_tree.calcImpedanceMatrix(fit_locs)[0].real ctree_all = greens_tree.createCompartmentTree(fit_locs) ctree_all.computeGMC(z_mat) sov_tree = tree.__copy__(new_tree=SOVTree()) sov_tree.calcSOVEquations() alphas, phimat = sov_tree.getImportantModes(locarg=fit_locs) ctree_all.computeC(-alphas[0:1].real * 1e3, phimat[0:1, :].real) # new compartment fitter cm = CompartmentFitter(self.tree) cm.setCTree(fit_locs) # test fitting cm.fitPassive(use_all_channels=False) cm.fitCapacitance() cm.fitEEq() self._checkPasCondProps(ctree_leak, cm.ctree) self._checkPasCaProps(ctree_leak, cm.ctree) with pytest.raises(AssertionError): self._checkEL(cm.ctree, self.tree[1].currents['L'][1]) cm.fitPassive(use_all_channels=True) cm.fitCapacitance() cm.fitEEq() self._checkPasCondProps(ctree_all, cm.ctree) self._checkPasCaProps(ctree_all, cm.ctree) self._checkEL(cm.ctree, greens_tree[1].currents['L'][1]) with pytest.raises(AssertionError): self._checkEL(cm.ctree, self.tree[1].currents['L'][1]) with pytest.raises(AssertionError): self._checkPasCondProps(ctree_leak, ctree_all)
def testTreeStructure(self): self.loadTTree() cm = CompartmentFitter(self.tree) # set of locations fit_locs1 = [(1, .5), (4, .5), (5, .5)] # no bifurcations fit_locs2 = [(1, .5), (4, .5), (5, .5), (8, .5)] # w bifurcation, should be added fit_locs3 = [(1, .5), (4, 1.), (5, .5), (8, .5)] # w bifurcation, already added # test fit_locs1, no bifurcation are added # input paradigm 1 cm.setCTree(fit_locs1, extend_w_bifurc=True) fl1_a = cm.tree.getLocs('fit locs') cm.setCTree(fit_locs1, extend_w_bifurc=False) fl1_b = cm.tree.getLocs('fit locs') assert len(fl1_a) == len(fl1_b) for fla, flb in zip(fl1_a, fl1_b): assert fla == flb # input paradigm 2 cm.tree.storeLocs(fit_locs1, 'fl1') cm.setCTree('fl1', extend_w_bifurc=True) fl1_a = cm.tree.getLocs('fit locs') assert len(fl1_a) == len(fl1_b) for fla, flb in zip(fl1_a, fl1_b): assert fla == flb # test tree structure assert len(cm.ctree) == 3 for cn in cm.ctree: assert len(cn.child_nodes) <= 1 # test fit_locs2, a bifurcation should be added with pytest.warns(UserWarning): cm.setCTree(fit_locs2, extend_w_bifurc=False) fl2_b = cm.tree.getLocs('fit locs') cm.setCTree(fit_locs2, extend_w_bifurc=True) fl2_a = cm.tree.getLocs('fit locs') assert len(fl2_a) == len(fl2_b) + 1 for fla, flb in zip(fl2_a, fl2_b): assert fla == flb assert fl2_a[-1] == (4, 1.) # test tree structure assert len(cm.ctree) == 5 for cn in cm.ctree: assert len(cn.child_nodes) <= 1 if cn.loc_ind != 4 else \ len(cn.child_nodes) == 2 # test fit_locs2, no bifurcation should be added as it is already present cm.setCTree(fit_locs3, extend_w_bifurc=True) fl3 = cm.tree.getLocs('fit locs') for fl_, fl3 in zip(fit_locs3, fl3): assert fl_ == fl3 # test tree structure assert len(cm.ctree) == 4 for cn in cm.ctree: assert len(cn.child_nodes) <= 1 if cn.loc_ind != 1 else \ len(cn.child_nodes) == 2
def plotSim(delta_ts=[0., 1., 2., 3., 4., 5., 6., 7., 8.], recompute=False): global SYN_NODE_IND, SYN_XCOMP # initialize the full model simtree = BrancoSimTree() simtree.setSynLocs() simtree.setCompTree() # derive the reduced model retaining only soma and synapse locations fit_locs = simtree.getLocs('soma loc') + simtree.getLocs('syn locs') c_fit = CompartmentFitter(simtree, name='sequence_discrimination', path='data/') ctree = c_fit.fitModel(fit_locs, recompute=recompute) clocs = ctree.getEquivalentLocs() # create the reduced model for NEURON simulation csimtree_ = createReducedNeuronModel(ctree) csimtree = csimtree_.__copy__(new_tree=BrancoReducedTree()) csimtree.setSynLocs(clocs) pl.figure('Branco', figsize=(5, 5)) gs = GridSpec(2, 2) ax0 = pl.subplot(gs[0, 0]) ax_ = pl.subplot(gs[0, 1]) ax1 = myAx(pl.subplot(gs[1, :])) # plot the full morphology locargs = [dict(marker='s', mec='k', mfc=cfl[0], ms=markersize)] locargs.extend([ dict(marker='s', mec='k', mfc=cfl[1], ms=markersize) for ii in range(1, len(fit_locs)) ]) pnodes = [n for n in simtree if n.swc_type != 2] plotargs = {'lw': lwidth / 1.3, 'c': 'DarkGrey'} simtree.plot2DMorphology(ax0, use_radius=False, node_arg=pnodes, plotargs=plotargs, marklocs=fit_locs, locargs=locargs, lims_margin=.01, textargs={'fontsize': ticksize}, labelargs={'fontsize': ticksize}) # plot a schematic of the reduced model labelargs = { 0: { 'marker': 's', 'mfc': cfl[0], 'mec': 'k', 'ms': markersize * 1.2 } } labelargs.update({ ii: { 'marker': 's', 'mfc': cfl[1], 'mec': 'k', 'ms': markersize * 1.2 } for ii in range(1, len(fit_locs)) }) ctree.plotDendrogram(ax_, plotargs={ 'c': 'k', 'lw': lwidth }, labelargs=labelargs) xlim, ylim = np.array(ax_.get_xlim()), np.array(ax_.get_ylim()) pp = np.array([np.mean(xlim), np.mean(ylim)]) dp = np.array([2. * np.abs(xlim[1] - xlim[0]) / 3., 0.]) ax_.annotate( 'Centrifugal', #xycoords='axes points', xy=pp, xytext=pp + dp, size=ticksize, rotation=90, ha='center', va='center') ax_.annotate( 'Centripetal', #xycoords='axes points', xy=pp, xytext=pp - dp, size=ticksize, rotation=90, ha='center', va='center') # plot voltage traces legend_handles = [] for ii, delta_t in enumerate(delta_ts): res_cp, res_cf = simtree.runSim(delta_t=delta_t) ax1.plot(res_cp['t'], res_cp['v_m'][0], c='DarkGrey', lw=lwidth) ax1.plot(res_cf['t'], res_cf['v_m'][0], c='DarkGrey', lw=lwidth) cres_cp, cres_cf = csimtree.runSim(delta_t=delta_t) line = ax1.plot(cres_cp['t'], cres_cp['v_m'][0], c=colours[ii % len(colours)], ls='--', lw=1.6 * lwidth, label=r'$\Delta t = ' + '%.1f$ ms' % delta_t) ax1.plot(cres_cf['t'], cres_cf['v_m'][0], c=colours[ii % len(colours)], ls='-.', lw=1.6 * lwidth) legend_handles.append(line[0]) legend_handles.append( mlines.Line2D([0, 0], [0, 0], ls='--', lw=1.6 * lwidth, c='DarkGrey', label=r'centripetal')) legend_handles.append( mlines.Line2D([0, 0], [0, 0], ls='-.', lw=1.6 * lwidth, c='DarkGrey', label=r'centrifugal')) drawScaleBars(ax1, r' ms', r' mV', b_offset=20, h_offset=15, v_offset=15) myLegend(ax1, loc='upper left', bbox_to_anchor=(.7, 1.3), handles=legend_handles, fontsize=ticksize, handlelength=2.7) pl.tight_layout() pl.show()
def plotSim(delta_ts=[0.,1.,2.,3.,4.,5.,6.,7.,8.], recompute=False): class BrancoSimTree(NeuronSimTree): ''' Inherits from :class:`NeuronSimTree` to implement Branco model ''' def __init__(self): super().__init__() phys_tree = getL23PyramidPas() phys_tree.__copy__(new_tree=self) def setSynLocs(self): global SYN_NODE_IND, SYN_XCOMP # set computational tree self.setCompTree() self.treetype = 'computational' # define the locations locs = [MorphLoc((SYN_NODE_IND, x), self, set_as_comploc=True) for x in SYN_XCOMP] self.storeLocs(locs, name='syn locs') self.storeLocs([(1., 0.5)], name='soma loc') # set treetype back self.treetype = 'original' def deleteModel(self): super(BrancoSimTree, self).deleteModel() self.pres = [] self.nmdas = [] def addAMPASynapse(self, loc, g_max, tau): loc = MorphLoc(loc, self) # create the synapse syn = h.AlphaSynapse(self.sections[loc['node']](loc['x'])) syn.tau = tau syn.gmax = g_max # store the synapse self.syns.append(syn) def addNMDASynapse(self, loc, g_max, e_rev, c_mg, dur_rel, amp_rel): loc = MorphLoc(loc, self) # create the synapse syn = h.NMDA_Mg_T(self.sections[loc['node']](loc['x'])) syn.gmax = g_max syn.Erev = e_rev syn.mg = c_mg # create the presynaptic segment for release pre = h.Section(name='pre %d'%len(self.pres)) pre.insert('release_BMK') pre(0.5).release_BMK.dur = dur_rel pre(0.5).release_BMK.amp = amp_rel # connect h.setpointer(pre(0.5).release_BMK._ref_T, 'C', syn) # store the synapse self.nmdas.append(syn) self.pres.append(pre) # setpointer cNMDA[n].C, PRE[n].T_rel(0.5) # setpointer im_xtra(x), i_membrane(x) # h.setpointer(dend(seg.x)._ref_i_membrane, 'im', dend(seg.x).xtra) def setSpikeTime(self, syn_index, spike_time): spk_tm = spike_time + self.t_calibrate # add spike for AMPA synapse self.syns[syn_index].onset = spk_tm # add spike for NMDA synapse self.pres[syn_index](0.5).release_BMK.delay = spk_tm def addAllSynapses(self): global G_MAX_AMPA, TAU_AMPA, G_MAX_NMDA, E_REV_NMDA, C_MG, DUR_REL, AMP_REL for loc in self.getLocs('syn locs'): # ampa synapse self.addAMPASynapse(loc, G_MAX_AMPA, TAU_AMPA) # nmda synapse self.addNMDASynapse(loc, G_MAX_NMDA, E_REV_NMDA, C_MG, DUR_REL, AMP_REL) def setSequence(self, delta_t, centri='fugal', t0=10., tadd=100.): n_loc = len(self.getLocs('syn locs')) if centri == 'fugal': for ll in range(n_loc): self.setSpikeTime(ll, t0 + ll * delta_t) elif centri == 'petal': for tt, ll in enumerate(range(n_loc)[::-1]): self.setSpikeTime(ll, t0 + tt * delta_t) else: raise IOError('Only centrifugal or centripetal sequences are allowed, ' + \ 'use \'fugal\' resp. \'petal\' as second arg.') return n_loc * delta_t + t0 + tadd def reduceModel(self, pprint=False): global SYN_NODE_IND, SYN_XCOMP locs = [MorphLoc((1, .5), self, set_as_comploc=True)] + \ [MorphLoc((SYN_NODE_IND, x), self, set_as_comploc=True) for x in SYN_XCOMP] # creat the reduced compartment tree ctree = self.createCompartmentTree(locs) # create trees to derive fitting matrices sov_tree, greens_tree = self.getZTrees() # compute the steady state impedance matrix z_mat = greens_tree.calcImpedanceMatrix(locs)[0].real # fit the conductances to steady state impedance matrix ctree.computeGMC(z_mat, channel_names=['L']) if pprint: np.set_printoptions(precision=1, linewidth=200) print(('Zmat original (MOhm) =\n' + str(z_mat))) print(('Zmat fitted (MOhm) =\n' + str(ctree.calcImpedanceMatrix()))) # get SOV constants alphas, phimat = sov_tree.getImportantModes(locarg=locs, sort_type='importance', eps=1e-12) # n_mode = len(locs) # alphas, phimat = alphas[:n_mode], phimat[:n_mode, :] importance = sov_tree.getModeImportance(sov_data=(alphas, phimat), importance_type='full') # fit the capacitances from SOV time-scales # ctree.computeC(-alphas*1e3, phimat, weight=importance) ctree.computeC(-alphas[:1]*1e3, phimat[:1,:], importance=importance[:1]) if pprint: print(('Taus original (ms) =\n' + str(np.abs(1./alphas)))) lambdas, _, _ = ctree.calcEigenvalues() print(('Taus fitted (ms) =\n' + str(np.abs(1./lambdas)))) return ctree def runSim(self, delta_t=12.): try: el = self[0].currents['L'][1] except AttributeError: el = self[1].currents['L'][1] # el=-75. self.initModel(dt=0.025, t_calibrate=0., v_init=el, factor_lambda=10.) # add the synapses self.addAllSynapses() t_max = self.setSequence(delta_t, centri='petal') # set recording locs self.storeLocs(self.getLocs('soma loc') + self.getLocs('syn locs'), name='rec locs') # run the simulation res_centripetal = self.run(t_max, pprint=True) # delete the model self.deleteModel() self.initModel(dt=0.025, t_calibrate=0., v_init=el, factor_lambda=10.) # add the synapses self.addAllSynapses() t_max = self.setSequence(delta_t, centri='fugal') # set recording locs self.storeLocs(self.getLocs('soma loc') + self.getLocs('syn locs'), name='rec locs') # run the simulation res_centrifugal = self.run(t_max, pprint=True) # delete the model self.deleteModel() return res_centripetal, res_centrifugal class BrancoReducedTree(NeuronCompartmentTree, BrancoSimTree): def __init__(self): # call the initializer of :class:`NeuronSimTree`, follows after # :class:`BrancoSimTree` in MRO super(BrancoSimTree, self).__init__(file_n=None, types=[1,3,4]) def setSynLocs(self, equivalent_locs): self.storeLocs(equivalent_locs[1:], name='syn locs') self.storeLocs(equivalent_locs[:1], name='soma loc') global SYN_NODE_IND, SYN_XCOMP # initialize the full model simtree = BrancoSimTree() simtree.setSynLocs() simtree.setCompTree() # derive the reduced model retaining only soma and synapse locations fit_locs = simtree.getLocs('soma loc') + simtree.getLocs('syn locs') c_fit = CompartmentFitter(simtree, name='sequence_discrimination', path='data/') ctree = c_fit.fitModel(fit_locs, recompute=recompute) clocs = ctree.getEquivalentLocs() # create the reduced model for NEURON simulation csimtree_ = createReducedNeuronModel(ctree) csimtree = csimtree_.__copy__(new_tree=BrancoReducedTree()) csimtree.setSynLocs(clocs) pl.figure('Branco', figsize=(5,5)) gs = GridSpec(2,2) ax0 = pl.subplot(gs[0,0]) ax_ = pl.subplot(gs[0,1]) ax1 = myAx(pl.subplot(gs[1,:])) # plot the full morphology locargs = [dict(marker='s', mec='k', mfc=cfl[0], ms=markersize)] locargs.extend([dict(marker='s', mec='k', mfc=cfl[1], ms=markersize) for ii in range(1,len(fit_locs))]) pnodes = [n for n in simtree if n.swc_type != 2] plotargs = {'lw': lwidth/1.3, 'c': 'DarkGrey'} simtree.plot2DMorphology(ax0, use_radius=False,node_arg=pnodes, plotargs=plotargs, marklocs=fit_locs, locargs=locargs, lims_margin=.01, textargs={'fontsize': ticksize}, labelargs={'fontsize': ticksize}) # plot a schematic of the reduced model labelargs = {0: {'marker': 's', 'mfc': cfl[0], 'mec': 'k', 'ms': markersize*1.2}} labelargs.update({ii: {'marker': 's', 'mfc': cfl[1], 'mec': 'k', 'ms': markersize*1.2} for ii in range(1,len(fit_locs))}) ctree.plotDendrogram(ax_, plotargs={'c':'k', 'lw': lwidth}, labelargs=labelargs) xlim, ylim = np.array(ax_.get_xlim()), np.array(ax_.get_ylim()) pp = np.array([np.mean(xlim), np.mean(ylim)]) dp = np.array([2.*np.abs(xlim[1]-xlim[0])/3.,0.]) ax_.annotate('Centrifugal', #xycoords='axes points', xy=pp, xytext=pp+dp, size=ticksize, rotation=90, ha='center', va='center') ax_.annotate('Centripetal', #xycoords='axes points', xy=pp, xytext=pp-dp, size=ticksize, rotation=90, ha='center', va='center') # plot voltage traces legend_handles = [] for ii, delta_t in enumerate(delta_ts): res_cp, res_cf = simtree.runSim(delta_t=delta_t) ax1.plot(res_cp['t'], res_cp['v_m'][0], c='DarkGrey', lw=lwidth) ax1.plot(res_cf['t'], res_cf['v_m'][0], c='DarkGrey', lw=lwidth) cres_cp, cres_cf = csimtree.runSim(delta_t=delta_t) line = ax1.plot(cres_cp['t'], cres_cp['v_m'][0], c=colours[ii%len(colours)], ls='--', lw=1.6*lwidth, label=r'$\Delta t = ' + '%.1f$ ms'%delta_t) ax1.plot(cres_cf['t'], cres_cf['v_m'][0], c=colours[ii%len(colours)], ls='-.', lw=1.6*lwidth) legend_handles.append(line[0]) legend_handles.append(mlines.Line2D([0,0],[0,0], ls='--', lw=1.6*lwidth, c='DarkGrey', label=r'centripetal')) legend_handles.append(mlines.Line2D([0,0],[0,0], ls='-.', lw=1.6*lwidth, c='DarkGrey', label=r'centrifugal')) drawScaleBars(ax1, r' ms', r' mV', b_offset=20, h_offset=15, v_offset=15) myLegend(ax1, loc='upper left', bbox_to_anchor=(.7,1.3), handles=legend_handles, fontsize=ticksize, handlelength=2.7) pl.tight_layout() pl.show()