class TestSOVTree(): def loadTTree(self): ''' Load the T-tree morphology in memory 6--5--4--7--8 | | 1 ''' print '>>> loading T-tree <<<' fname = 'test_morphologies/Tsovtree.swc' self.tree = SOVTree(fname, types=[1, 3, 4]) self.tree.fitLeakCurrent(e_eq_target=-75., tau_m_target=10.) self.tree.setCompTree() def loadValidationTree(self): ''' Load the T-tree morphology in memory 5---1---4 ''' print '>>> loading validation tree <<<' fname = 'test_morphologies/sovvalidationtree.swc' self.tree = SOVTree(fname, types=[1, 3, 4]) self.tree.fitLeakCurrent(e_eq_target=-75., tau_m_target=10.) self.tree.setCompTree() def testSOVCalculation(self): # validate the calculation on analytical model self.loadValidationTree() # do SOV calculation self.tree.calcSOVEquations() alphas, gammas = self.tree.getSOVMatrices([(1, 0.5)]) # compute time scales analytically self.tree.treetype = 'computational' lambda_m_test = np.sqrt(self.tree[4].R_sov / \ (2.*self.tree[4].g_m*self.tree[4].r_a)) tau_m_test = self.tree[4].c_m / self.tree[4].g_m * 1e3 alphas_test = \ (1. + \ (np.pi * np.arange(20) * lambda_m_test / \ (self.tree[4].L_sov + self.tree[5].L_sov))**2) / \ tau_m_test # compare analytical and computed time scales assert np.allclose(alphas[:20], alphas_test) # compute the spatial mode functions analytically # import matplotlib.pyplot as pl # self.tree.distributeLocsUniform(dx=4., name='NET_eval') # alphas, gammas = self.tree.getSOVMatrices(self.tree.getLocs(name='NET_eval')) # for kk in range(5): # print 'tau_' + str(kk) + ' =', -1./alphas[kk].real # pl.plot(range(gammas.shape[1]), gammas[kk,:]) # pl.plot(range(gammas.shape[1]), g) # pl.show() ## TODO # test basic identities self.loadTTree() self.tree.calcSOVEquations(maxspace_freq=500) # sets of location locs_0 = [(6, .5), (8, .5)] locs_1 = [(1, .5), (4, .5), (4, 1.), (5, .5), (6, .5), (7, .5), (8, .5)] locs_2 = [(7, .5), (8, .5)] self.tree.storeLocs(locs_0, '0') self.tree.storeLocs(locs_1, '1') self.tree.storeLocs(locs_2, '2') # test mode importance imp_a = self.tree.getModeImportance(locs=locs_0) imp_b = self.tree.getModeImportance(name='0') imp_c = self.tree.getModeImportance(sov_data=self.tree.getSOVMatrices( locs=locs_0)) imp_d = self.tree.getModeImportance(sov_data=self.tree.getSOVMatrices( name='0')) assert np.allclose(imp_a, imp_b) assert np.allclose(imp_a, imp_c) assert np.allclose(imp_a, imp_d) assert np.abs(1. - np.max(imp_a)) < 1e-12 with pytest.raises(IOError): self.tree.getModeImportance() # test important modes imp_2 = self.tree.getModeImportance(name='2') assert not np.allclose(imp_a, imp_2) # test impedance matrix z_mat_a = self.tree.calcImpedanceMatrix( sov_data=self.tree.getImportantModes(name='1', eps=1e-10)) z_mat_b = self.tree.calcImpedanceMatrix(name='1', eps=1e-10) assert np.allclose(z_mat_a, z_mat_b) assert np.allclose(z_mat_a - z_mat_a.T, np.zeros(z_mat_a.shape)) for ii, z_row in enumerate(z_mat_a): assert np.argmax(z_row) == ii # test Fourrier impedance matrix ft = ke.FourrierTools(np.arange(0., 100., 0.1)) z_mat_ft = self.tree.calcImpedanceMatrix(name='1', eps=1e-10, freqs=ft.s) print z_mat_ft[ft.ind_0s, :, :] print z_mat_a assert np.allclose(z_mat_ft[ft.ind_0s,:,:].real, \ z_mat_a, atol=1e-1) # check steady state assert np.allclose(z_mat_ft - np.transpose(z_mat_ft, axes=(0,2,1)), \ np.zeros(z_mat_ft.shape)) # check symmetry assert np.allclose(z_mat_ft[:ft.ind_0s,:,:].real, \ z_mat_ft[ft.ind_0s+1:,:,:][::-1,:,:].real) # check real part even assert np.allclose(z_mat_ft[:ft.ind_0s,:,:].imag, \ -z_mat_ft[ft.ind_0s+1:,:,:][::-1,:,:].imag) # check imaginary part odd # import matplotlib.pyplot as pl # pl.plot(ft.s.imag, z_mat_ft[:,2,4].real, 'b') # pl.plot(ft.s.imag, z_mat_ft[:,2,4].imag, 'r') # pl.show() # self.tree.distributeLocsUniform(dx=4., name='NET_eval') # print [str(loc) for loc in self.tree.getLocs(name='NET_eval')] # z_m = self.tree.calcImpedanceMatrix(name='NET_eval', eps=1e-10) # pl.imshow(z_m, origin='lower', interpolation='none') # alphas, gammas = self.tree.getSOVMatrices(self.tree.getLocs(name='NET_eval')) # for kk in range(5): # print 'tau_' + str(kk) + ' =', -1./alphas[kk].real # pl.plot(range(gammas.shape[1]), gammas[kk,:]) # pl.show() # import morphologyReader as morphR def testNETDerivation(self): # initialize self.loadValidationTree() self.tree.calcSOVEquations() # construct the NET net = self.tree.constructNET() # print str(net) # initialize self.loadTTree() self.tree.calcSOVEquations() # construct the NET net = self.tree.constructNET(dz=20.) # print str(net) # contruct the NET with linear terms net, lin_terms = self.tree.constructNET(dz=20., add_lin_terms=True) # check if correct alphas, gammas = self.tree.getImportantModes(name='NET_eval', eps=1e-4, sort_type='timescale') for ii, lin_term in enumerate(lin_terms): z_k_trans = net.getReducedTree([0, ii ]).getRoot().z_kernel + lin_term assert np.abs(z_k_trans.k_bar - Kernel( (alphas, gammas[:, 0] * gammas[:, ii])).k_bar) < 1e-8
class TestGreensTree(): def loadTTree(self): """ Load the T-tree morphology in memory 6--5--4--7--8 | | 1 """ fname = os.path.join(MORPHOLOGIES_PATH_PREFIX, 'Tsovtree.swc') self.tree = GreensTree(fname, types=[1,3,4]) self.tree.fitLeakCurrent(-75., 10.) self.tree.setCompTree() def loadValidationTree(self): """ Load the T-tree morphology in memory 5---1---4 """ fname = os.path.join(MORPHOLOGIES_PATH_PREFIX, 'sovvalidationtree.swc') self.tree = GreensTree(fname, types=[1,3,4]) self.tree.fitLeakCurrent(-75., 10.) self.tree.setCompTree() def loadSOVTTree(self): """ Load the T-tree morphology in memory 6--5--4--7--8 | | 1 """ fname = os.path.join(MORPHOLOGIES_PATH_PREFIX, 'Tsovtree.swc') self.sovtree = SOVTree(fname, types=[1,3,4]) self.sovtree.fitLeakCurrent(-75., 10.) self.sovtree.setCompTree() self.sovtree.calcSOVEquations() def loadSOVValidationTree(self): """ Load the T-tree morphology in memory 5---1---4 """ fname = os.path.join(MORPHOLOGIES_PATH_PREFIX, 'sovvalidationtree.swc') self.sovtree = SOVTree(fname, types=[1,3,4]) self.sovtree.fitLeakCurrent(-75., 10.) self.sovtree.setCompTree() self.sovtree.calcSOVEquations() def testBasicProperties(self): self.loadTTree() # test Fourrier impedance matrix ft = ke.FourrierTools(np.arange(0.,100.,0.1)) # set the impedances self.tree.setImpedance(ft.s) # sets of location locs_0 = [(6, .5), (8, .5)] locs_1 = [(1, .5), (4, .5), (4, 1.), (5, .5), (6, .5), (7, .5), (8, .5)] locs_2 = [(7, .5), (8, .5)] self.tree.storeLocs(locs_0, '0') self.tree.storeLocs(locs_1, '1') self.tree.storeLocs(locs_2, '2') # compute impedance matrices z_mat_0 = self.tree.calcImpedanceMatrix('0')[ft.ind_0s] z_mat_1 = self.tree.calcImpedanceMatrix('1')[ft.ind_0s] z_mat_2 = self.tree.calcImpedanceMatrix('2')[ft.ind_0s] # check complex steady state component zero assert np.allclose(z_mat_0.imag, np.zeros_like(z_mat_0.imag)) assert np.allclose(z_mat_1.imag, np.zeros_like(z_mat_1.imag)) assert np.allclose(z_mat_2.imag, np.zeros_like(z_mat_2.imag)) # check symmetry assert np.allclose(z_mat_0, z_mat_0.T) assert np.allclose(z_mat_1, z_mat_1.T) assert np.allclose(z_mat_2, z_mat_2.T) # check symmetry directly assert np.allclose(self.tree.calcZF(locs_0[0], locs_0[1]), self.tree.calcZF(locs_0[1], locs_0[0])) assert np.allclose(self.tree.calcZF(locs_1[0], locs_1[3]), self.tree.calcZF(locs_1[3], locs_1[0])) assert np.allclose(self.tree.calcZF(locs_1[2], locs_1[5]), self.tree.calcZF(locs_1[5], locs_1[2])) # check transitivity z_14_ = self.tree.calcZF(locs_1[1], locs_1[3]) * \ self.tree.calcZF(locs_1[3], locs_1[4]) / \ self.tree.calcZF(locs_1[3], locs_1[3]) z_14 = self.tree.calcZF(locs_1[1], locs_1[4]) assert np.allclose(z_14, z_14_) z_06_ = self.tree.calcZF(locs_1[0], locs_1[5]) * \ self.tree.calcZF(locs_1[5], locs_1[6]) / \ self.tree.calcZF(locs_1[5], locs_1[5]) z_06 = self.tree.calcZF(locs_1[0], locs_1[6]) assert np.allclose(z_06, z_06_) z_46_ = self.tree.calcZF(locs_1[4], locs_1[2]) * \ self.tree.calcZF(locs_1[2], locs_1[6]) / \ self.tree.calcZF(locs_1[2], locs_1[2]) z_46 = self.tree.calcZF(locs_1[4], locs_1[6]) assert np.allclose(z_46, z_46_) z_n15_ = self.tree.calcZF(locs_1[1], locs_1[3]) * \ self.tree.calcZF(locs_1[3], locs_1[5]) / \ self.tree.calcZF(locs_1[3], locs_1[3]) z_15 = self.tree.calcZF(locs_1[1], locs_1[5]) assert not np.allclose(z_15, z_n15_) def testValues(self): # load trees self.loadTTree() self.loadSOVTTree() # test Fourrier impedance matrix ft = ke.FourrierTools(np.arange(0.,100.,0.1)) # set the impedances self.tree.setImpedance(ft.s) # sets of location locs = [(1, .5), (4, .5), (4, 1.), (5, .5), (6, .5), (7, .5), (8, .5)] self.tree.storeLocs(locs, 'locs') self.sovtree.storeLocs(locs, 'locs') # compute impedance matrices with both methods z_sov = self.sovtree.calcImpedanceMatrix(locarg='locs', eps=1e-10) z_gf = self.tree.calcImpedanceMatrix('locs')[ft.ind_0s].real assert np.allclose(z_gf, z_sov, atol=5e-1) z_gf2 = self.tree.calcImpedanceMatrix('locs', explicit_method=False)[ft.ind_0s].real assert np.allclose(z_gf2, z_gf, atol=5e-6) zf_sov = self.sovtree.calcImpedanceMatrix(locarg='locs', eps=1e-10, freqs=ft.s) zf_gf = self.tree.calcImpedanceMatrix('locs') assert np.allclose(zf_gf, zf_sov, atol=5e-1) zf_gf2 = self.tree.calcImpedanceMatrix('locs', explicit_method=False) assert np.allclose(zf_gf2, zf_gf, atol=5e-6) # load trees self.loadValidationTree() self.loadSOVValidationTree() # test Fourrier impedance matrix ft = ke.FourrierTools(np.arange(0.,100.,0.1)) # set the impedances self.tree.setImpedance(ft.s) # set of locations locs = [(1, .5), (4, .5), (4, 1.), (5, .5), (5, 1.)] self.tree.storeLocs(locs, 'locs') self.sovtree.storeLocs(locs, 'locs') # compute impedance matrices with both methods z_sov = self.sovtree.calcImpedanceMatrix(locarg='locs', eps=1e-10) z_gf = self.tree.calcImpedanceMatrix('locs')[ft.ind_0s].real assert np.allclose(z_gf, z_sov, atol=5e-1) z_gf2 = self.tree.calcImpedanceMatrix('locs', explicit_method=False)[ft.ind_0s].real assert np.allclose(z_gf2, z_gf, atol=5e-6) zf_sov = self.sovtree.calcImpedanceMatrix(locarg='locs', eps=1e-10, freqs=ft.s) zf_gf = self.tree.calcImpedanceMatrix('locs') assert np.allclose(zf_gf, zf_sov, atol=5e-1) zf_gf2 = self.tree.calcImpedanceMatrix('locs', explicit_method=False) assert np.allclose(zf_gf2, zf_gf, atol=5e-6)
class TestCompartmentTree(): def loadTTree(self): ''' Load the T-tree morphology in memory 6--5--4--7--8 | | 1 ''' print '>>> loading T-tree <<<' fname = 'test_morphologies/Tsovtree.swc' self.tree = SOVTree(fname, types=[1, 3, 4]) self.tree.fitLeakCurrent(e_eq_target=-75., tau_m_target=10.) self.tree.setCompTree() # do SOV calculation self.tree.calcSOVEquations() def testTreeDerivation(self): self.loadTTree() # locations locs_soma = [(1, 0.5)] locs_prox = [(4, 0.2)] locs_bifur = [(4, 1.0)] locs_dist_nobifur = [(6., 0.5), (8., 0.5)] locs_dist_bifur = [(4, 1.0), (6., 0.5), (8., 0.5)] locs_dist_nroot = [(4, 1.0), (4, 0.5), (6., 0.5), (8., 0.5)] # test structures with pytest.raises(KeyError): self.tree.createCompartmentTree('set0') # test root (is soma) in set self.tree.storeLocs(locs_dist_bifur + locs_soma, 'set0') ctree = self.tree.createCompartmentTree('set0') assert ctree[0].loc_ind == 3 assert ctree[1].loc_ind == 0 cloc_inds = [cn.loc_ind for cn in ctree[1].child_nodes] assert 1 in cloc_inds and 2 in cloc_inds # test soma not in set (but common root) self.tree.storeLocs(locs_dist_bifur, 'set1') ctree = self.tree.createCompartmentTree('set1') assert ctree[0].loc_ind == 0 cloc_inds = [cn.loc_ind for cn in ctree[0].child_nodes] assert 1 in cloc_inds and 2 in cloc_inds # test soma not in set and no common root self.tree.storeLocs(locs_dist_nobifur, 'set2') with pytest.warns(UserWarning): ctree = self.tree.createCompartmentTree('set2') assert self.tree.getLocs('set2')[0] == (4, 1.) cloc_inds = [cn.loc_ind for cn in ctree[0].child_nodes] assert 1 in cloc_inds and 2 in cloc_inds # test 2 locs on common root self.tree.storeLocs(locs_dist_nroot, 'set3') ctree = self.tree.createCompartmentTree('set3') assert ctree[0].loc_ind == 1 assert ctree[1].loc_ind == 0 def testFitting(self): self.loadTTree() # locations locs_soma = [(1, 0.5)] locs_prox = [(4, 0.2)] locs_bifur = [(4, 1.0)] locs_dist_nobifur = [(6., 0.5), (8., 0.5)] locs_dist_bifur = [(4, 1.0), (6., 0.5), (8., 0.5)] # store the locations self.tree.storeLocs(locs_soma + locs_prox, 'prox') self.tree.storeLocs(locs_soma + locs_bifur, 'bifur') self.tree.storeLocs(locs_soma + locs_dist_nobifur, 'dist_nobifur') self.tree.storeLocs(locs_soma + locs_dist_bifur, 'dist_bifur') # derive steady state impedance matrices z_mat_prox = self.tree.calcImpedanceMatrix(name='prox') z_mat_bifur = self.tree.calcImpedanceMatrix(name='bifur') z_mat_dist_nobifur = self.tree.calcImpedanceMatrix(name='dist_nobifur') z_mat_dist_bifur = self.tree.calcImpedanceMatrix(name='dist_bifur') # create the tree structures ctree_prox = self.tree.createCompartmentTree('prox') ctree_bifur = self.tree.createCompartmentTree('bifur') ctree_dist_nobifur = self.tree.createCompartmentTree('dist_nobifur') ctree_dist_bifur = self.tree.createCompartmentTree('dist_bifur') # test the tree structures assert len(ctree_prox) == len(locs_prox) + 1 assert len(ctree_bifur) == len(locs_bifur) + 1 assert len(ctree_dist_nobifur) == len(locs_dist_nobifur) + 1 assert len(ctree_dist_bifur) == len(locs_dist_bifur) + 1 # fit the steady state models ctree_prox.computeGMC(z_mat_prox) ctree_bifur.computeGMC(z_mat_bifur) ctree_dist_nobifur.computeGMC(z_mat_dist_nobifur) ctree_dist_bifur.computeGMC(z_mat_dist_bifur) # compute the fitted impedance matrices z_fit_prox = ctree_prox.calcImpedanceMatrix() z_fit_bifur = ctree_bifur.calcImpedanceMatrix() z_fit_dist_nobifur = ctree_dist_nobifur.calcImpedanceMatrix() z_fit_dist_bifur = ctree_dist_bifur.calcImpedanceMatrix() # test correctness assert np.allclose(z_fit_prox, z_mat_prox, atol=0.5) assert np.allclose(z_fit_bifur, z_mat_bifur, atol=0.5) assert not np.allclose( z_fit_dist_nobifur, z_mat_dist_nobifur, atol=0.5) assert np.allclose(z_fit_dist_bifur, z_mat_dist_bifur, atol=0.5) # TODO: test with capacitances def testReordering(self): self.loadTTree() # test reordering locs_dist_badorder = [(1., 0.5), (8., 0.5), (4, 1.0)] self.tree.storeLocs(locs_dist_badorder, 'badorder') z_mat_badorder = self.tree.calcImpedanceMatrix(name='badorder') ctree_badorder = self.tree.createCompartmentTree('badorder') # check if location indices are assigned correctly assert [node.loc_ind for node in ctree_badorder] == [0, 2, 1] # check if reordering works z_mat_reordered = ctree_badorder._preprocessZMatArg(z_mat_badorder) assert np.allclose(z_mat_reordered, z_mat_badorder[:, [0, 2, 1]][[0, 2, 1], :]) # check if fitting is correct ctree_badorder.computeGMC(z_mat_badorder) z_fit_badorder = ctree_badorder.calcImpedanceMatrix() assert np.allclose(z_mat_badorder, z_fit_badorder, atol=0.5) assert not np.allclose(z_mat_reordered, z_fit_badorder) # test if equivalent locs are returned correctly locs_equiv = ctree_badorder.getEquivalentLocs() assert all([ loc == loc_ for loc, loc_ in zip(locs_equiv, [(0, .5), (2, .5), (1, .5)]) ]) def loadBallAndStick(self): self.greens_tree = GreensTree( file_n='test_morphologies/ball_and_stick.swc') for node in self.greens_tree: node.setPhysiology( 0.8, # Cm [uF/cm^2] 100. / 1e6, # Ra [MOhm*cm] ) node.addCurrent( 'L', # leak current 100., # g_max [uS/cm^2] -75., # e_rev [mV] ) self.greens_tree.setCompTree() # set the impedances self.freqs = np.array([0., 1., 10., 100., 1000]) * 1j self.greens_tree.setImpedance(self.freqs) def testLocationMapping(self, n_loc=20): self.loadBallAndStick() # define locations xvals = np.linspace(0., 1., n_loc + 1)[1:] locs_1 = [(1, 0.5)] + [(4, x) for x in xvals] locs_2 = [(1, 0.5)] + [(4, x) for x in xvals][::-1] locs_3 = [(4, x) for x in xvals] + [(1, 0.5)] # create compartment trees ctree_1 = self.greens_tree.createCompartmentTree(locs_1) ctree_2 = self.greens_tree.createCompartmentTree(locs_2) ctree_3 = self.greens_tree.createCompartmentTree(locs_3) # test location indices locinds_1 = np.array([node.loc_ind for node in ctree_1]) locinds_2 = np.array([node.loc_ind for node in ctree_2]) locinds_3 = np.array([node.loc_ind for node in ctree_3]) # check consecutive assert np.allclose(locinds_1[:-1], locinds_1[1:] - 1) # check permutation assert np.allclose(locinds_1[1:], locinds_2[1:][::-1]) assert np.allclose(locinds_1[:-1], locinds_3[1:]) def testGCFit(self, n_loc=20): self.loadBallAndStick() # define locations xvals = np.linspace(0., 1., n_loc + 1)[1:] locs_1 = [(1, 0.5)] + [(4, x) for x in xvals] locs_2 = [(1, 0.5)] + [(4, x) for x in xvals][::-1] locs_3 = [(4, x) for x in xvals] + [(1, 0.5)] locs_4 = random.sample(locs_1, k=len(locs_1)) # calculate impedance matrices z_mat_1 = self.greens_tree.calcImpedanceMatrix(locs_1) z_mat_2 = self.greens_tree.calcImpedanceMatrix(locs_2) z_mat_3 = self.greens_tree.calcImpedanceMatrix(locs_3) z_mat_4 = self.greens_tree.calcImpedanceMatrix(locs_4) # create compartment trees ctree_1 = self.greens_tree.createCompartmentTree(locs_1) ctree_2 = self.greens_tree.createCompartmentTree(locs_2) ctree_3 = self.greens_tree.createCompartmentTree(locs_3) ctree_4 = self.greens_tree.createCompartmentTree(locs_4) # fit g_m and g_c ctree_1.computeGMC(z_mat_1[0, :, :], channel_names=['L']) ctree_2.computeGMC(z_mat_2[0, :, :], channel_names=['L']) ctree_3.computeGMC(z_mat_3[0, :, :], channel_names=['L']) ctree_4.computeGMC(z_mat_4[0, :, :], channel_names=['L']) # fit c_m ctree_1.computeC(self.freqs, z_mat_1) ctree_2.computeC(self.freqs, z_mat_2) ctree_3.computeC(self.freqs, z_mat_3) ctree_4.computeC(self.freqs, z_mat_4) # compare both models assert str(ctree_1) == str(ctree_2) assert str(ctree_1) == str(ctree_3) assert str(ctree_1) == str(ctree_4) # compare impedance matrices z_fit_1 = ctree_1.calcImpedanceMatrix(self.freqs) z_fit_2 = ctree_2.calcImpedanceMatrix(self.freqs) z_fit_3 = ctree_3.calcImpedanceMatrix(self.freqs) z_fit_4 = ctree_4.calcImpedanceMatrix(self.freqs) assert np.allclose(z_fit_1, z_mat_1, atol=0.1) assert np.allclose(z_fit_2, z_mat_2, atol=0.1) assert np.allclose(z_fit_3, z_mat_3, atol=0.1) assert np.allclose(z_fit_4, z_mat_4, atol=0.1) assert np.allclose( z_fit_1, ctree_2.calcImpedanceMatrix(self.freqs, indexing='tree')) assert np.allclose( z_fit_1, ctree_3.calcImpedanceMatrix(self.freqs, indexing='tree')) assert np.allclose( z_fit_1, ctree_4.calcImpedanceMatrix(self.freqs, indexing='tree'))
class TestCompartmentTree(): def loadTTree(self): """ Load the T-tree morphology in memory 6--5--4--7--8 | | 1 """ fname = os.path.join(MORPHOLOGIES_PATH_PREFIX, 'Tsovtree.swc') self.tree = SOVTree(fname, types=[1, 3, 4]) self.tree.fitLeakCurrent(-75., 10.) self.tree.setCompTree() # do SOV calculation self.tree.calcSOVEquations() def testTreeDerivation(self): self.loadTTree() # locations locs_soma = [(1, 0.5)] locs_prox = [(4, 0.2)] locs_bifur = [(4, 1.0)] locs_dist_nobifur = [(6., 0.5), (8., 0.5)] locs_dist_bifur = [(4, 1.0), (6., 0.5), (8., 0.5)] locs_dist_nroot = [(4, 1.0), (4, 0.5), (6., 0.5), (8., 0.5)] # test structures with pytest.raises(KeyError): self.tree.createCompartmentTree('set0') # test root (is soma) in set self.tree.storeLocs(locs_dist_bifur + locs_soma, 'set0') ctree = self.tree.createCompartmentTree('set0') assert ctree[0].loc_ind == 3 assert ctree[1].loc_ind == 0 cloc_inds = [cn.loc_ind for cn in ctree[1].child_nodes] assert 1 in cloc_inds and 2 in cloc_inds # test soma not in set (but common root) self.tree.storeLocs(locs_dist_bifur, 'set1') ctree = self.tree.createCompartmentTree('set1') assert ctree[0].loc_ind == 0 cloc_inds = [cn.loc_ind for cn in ctree[0].child_nodes] assert 1 in cloc_inds and 2 in cloc_inds # test soma not in set and no common root self.tree.storeLocs(locs_dist_nobifur, 'set2') with pytest.warns(UserWarning): ctree = self.tree.createCompartmentTree('set2') assert self.tree.getLocs('set2')[0] == (4, 1.) cloc_inds = [cn.loc_ind for cn in ctree[0].child_nodes] assert 1 in cloc_inds and 2 in cloc_inds # test 2 locs on common root self.tree.storeLocs(locs_dist_nroot, 'set3') ctree = self.tree.createCompartmentTree('set3') assert ctree[0].loc_ind == 1 assert ctree[1].loc_ind == 0 def testFitting(self): self.loadTTree() # locations locs_soma = [(1, 0.5)] locs_prox = [(4, 0.2)] locs_bifur = [(4, 1.0)] locs_dist_nobifur = [(6., 0.5), (8., 0.5)] locs_dist_bifur = [(4, 1.0), (6., 0.5), (8., 0.5)] # store the locations self.tree.storeLocs(locs_soma + locs_prox, 'prox') self.tree.storeLocs(locs_soma + locs_bifur, 'bifur') self.tree.storeLocs(locs_soma + locs_dist_nobifur, 'dist_nobifur') self.tree.storeLocs(locs_soma + locs_dist_bifur, 'dist_bifur') # derive steady state impedance matrices z_mat_prox = self.tree.calcImpedanceMatrix(locarg='prox') z_mat_bifur = self.tree.calcImpedanceMatrix(locarg='bifur') z_mat_dist_nobifur = self.tree.calcImpedanceMatrix( locarg='dist_nobifur') z_mat_dist_bifur = self.tree.calcImpedanceMatrix(locarg='dist_bifur') # create the tree structures ctree_prox = self.tree.createCompartmentTree('prox') ctree_bifur = self.tree.createCompartmentTree('bifur') ctree_dist_nobifur = self.tree.createCompartmentTree('dist_nobifur') ctree_dist_bifur = self.tree.createCompartmentTree('dist_bifur') # test the tree structures assert len(ctree_prox) == len(locs_prox) + 1 assert len(ctree_bifur) == len(locs_bifur) + 1 assert len(ctree_dist_nobifur) == len(locs_dist_nobifur) + 1 assert len(ctree_dist_bifur) == len(locs_dist_bifur) + 1 # fit the steady state models ctree_prox.computeGMC(z_mat_prox) ctree_bifur.computeGMC(z_mat_bifur) ctree_dist_nobifur.computeGMC(z_mat_dist_nobifur) ctree_dist_bifur.computeGMC(z_mat_dist_bifur) # compute the fitted impedance matrices z_fit_prox = ctree_prox.calcImpedanceMatrix() z_fit_bifur = ctree_bifur.calcImpedanceMatrix() z_fit_dist_nobifur = ctree_dist_nobifur.calcImpedanceMatrix() z_fit_dist_bifur = ctree_dist_bifur.calcImpedanceMatrix() # test correctness assert np.allclose(z_fit_prox, z_mat_prox, atol=0.5) assert np.allclose(z_fit_bifur, z_mat_bifur, atol=0.5) assert not np.allclose( z_fit_dist_nobifur, z_mat_dist_nobifur, atol=0.5) assert np.allclose(z_fit_dist_bifur, z_mat_dist_bifur, atol=0.5) def testReordering(self): self.loadTTree() # test reordering locs_dist_badorder = [(1., 0.5), (8., 0.5), (4, 1.0)] self.tree.storeLocs(locs_dist_badorder, 'badorder') z_mat_badorder = self.tree.calcImpedanceMatrix(locarg='badorder') ctree_badorder = self.tree.createCompartmentTree('badorder') # check if location indices are assigned correctly assert [node.loc_ind for node in ctree_badorder] == [0, 2, 1] # check if reordering works z_mat_reordered = ctree_badorder._preprocessZMatArg(z_mat_badorder) assert np.allclose(z_mat_reordered, z_mat_badorder[:, [0, 2, 1]][[0, 2, 1], :]) # check if fitting is correct ctree_badorder.computeGMC(z_mat_badorder) z_fit_badorder = ctree_badorder.calcImpedanceMatrix() assert np.allclose(z_mat_badorder, z_fit_badorder, atol=0.5) assert not np.allclose(z_mat_reordered, z_fit_badorder) # test if equivalent locs are returned correctly locs_equiv = ctree_badorder.getEquivalentLocs() assert all([ loc == loc_ for loc, loc_ in zip(locs_equiv, [(0, .5), (2, .5), (1, .5)]) ]) def loadBallAndStick(self): self.greens_tree = GreensTree(file_n=os.path.join( MORPHOLOGIES_PATH_PREFIX, 'ball_and_stick.swc')) self.greens_tree.setPhysiology(0.8, 100. / 1e6) self.greens_tree.setLeakCurrent(100., -75.) self.greens_tree.setCompTree() # set the impedances self.freqs = np.array([0.]) * 1j self.greens_tree.setImpedance(self.freqs) # create sov tree self.sov_tree = self.greens_tree.__copy__(new_tree=SOVTree()) self.sov_tree.calcSOVEquations(maxspace_freq=50.) def testLocationMapping(self, n_loc=20): self.loadBallAndStick() # define locations xvals = np.linspace(0., 1., n_loc + 1)[1:] locs_1 = [(1, 0.5)] + [(4, x) for x in xvals] locs_2 = [(1, 0.5)] + [(4, x) for x in xvals][::-1] locs_3 = [(4, x) for x in xvals] + [(1, 0.5)] # create compartment trees ctree_1 = self.greens_tree.createCompartmentTree(locs_1) ctree_2 = self.greens_tree.createCompartmentTree(locs_2) ctree_3 = self.greens_tree.createCompartmentTree(locs_3) # test location indices locinds_1 = np.array([node.loc_ind for node in ctree_1]) locinds_2 = np.array([node.loc_ind for node in ctree_2]) locinds_3 = np.array([node.loc_ind for node in ctree_3]) # check consecutive assert np.allclose(locinds_1[:-1], locinds_1[1:] - 1) # check permutation assert np.allclose(locinds_1[1:], locinds_2[1:][::-1]) assert np.allclose(locinds_1[:-1], locinds_3[1:]) def testGSSFit(self, n_loc=20): self.loadBallAndStick() # define locations xvals = np.linspace(0., 1., n_loc + 1)[1:] locs_1 = [(1, 0.5)] + [(4, x) for x in xvals] locs_2 = [(1, 0.5)] + [(4, x) for x in xvals][::-1] locs_3 = [(4, x) for x in xvals] + [(1, 0.5)] locs_4 = random.sample(locs_1, k=len(locs_1)) # calculate impedance matrices z_mat_1 = self.greens_tree.calcImpedanceMatrix(locs_1)[0].real z_mat_2 = self.greens_tree.calcImpedanceMatrix(locs_2)[0].real z_mat_3 = self.greens_tree.calcImpedanceMatrix(locs_3)[0].real z_mat_4 = self.greens_tree.calcImpedanceMatrix(locs_4)[0].real # create compartment trees ctree_1 = self.greens_tree.createCompartmentTree(locs_1) ctree_2 = self.greens_tree.createCompartmentTree(locs_2) ctree_3 = self.greens_tree.createCompartmentTree(locs_3) ctree_4 = self.greens_tree.createCompartmentTree(locs_4) # fit g_m and g_c ctree_1.computeGMC(z_mat_1, channel_names=['L']) ctree_2.computeGMC(z_mat_2, channel_names=['L']) ctree_3.computeGMC(z_mat_3, channel_names=['L']) ctree_4.computeGMC(z_mat_4, channel_names=['L']) # compare both models assert str(ctree_1) == str(ctree_2) assert str(ctree_1) == str(ctree_3) assert str(ctree_1) == str(ctree_4) # compare impedance matrices z_fit_1 = ctree_1.calcImpedanceMatrix(self.freqs) z_fit_2 = ctree_2.calcImpedanceMatrix(self.freqs) z_fit_3 = ctree_3.calcImpedanceMatrix(self.freqs) z_fit_4 = ctree_4.calcImpedanceMatrix(self.freqs) assert np.allclose(z_fit_1, z_mat_1, atol=1e-8) assert np.allclose(z_fit_2, z_mat_2, atol=1e-8) assert np.allclose(z_fit_3, z_mat_3, atol=1e-8) assert np.allclose(z_fit_4, z_mat_4, atol=1e-8) assert np.allclose(z_fit_1, ctree_2.calcImpedanceMatrix(indexing='tree')) assert np.allclose(z_fit_1, ctree_3.calcImpedanceMatrix(indexing='tree')) assert np.allclose(z_fit_1, ctree_4.calcImpedanceMatrix(indexing='tree')) def testCFit(self, n_loc=20): self.loadBallAndStick() # define locations xvals = np.linspace(0., 1., n_loc + 1)[1:] locs = [(1, 0.5)] + [(4, x) for x in xvals] # create compartment tree ctree = self.greens_tree.createCompartmentTree(locs) # steady state fit z_mat = self.greens_tree.calcImpedanceMatrix(locs)[0].real ctree.computeGMC(z_mat) # get SOV constants for capacitance fit alphas, phimat, importance = self.sov_tree.getImportantModes( locarg=locs, sort_type='importance', eps=1e-12, return_importance=True) # fit the capacitances from SOV time-scales ctree.computeC(-alphas[0:1].real * 1e3, phimat[0:1, :].real, weights=importance[0:1]) # check if equal to membrane time scale nds = [self.greens_tree[loc[0]] for loc in locs] taus_orig = np.array([n.c_m / n.currents['L'][0] for n in nds]) taus_fit = np.array([n.ca / n.currents['L'][0] for n in ctree]) assert np.allclose(taus_orig, taus_fit) # fit capacitances with experimental vector fit for n in ctree: n.ca = 1. self.greens_tree.setImpedance(freqs=ke.create_logspace_freqarray()) z_mat = self.greens_tree.calcImpedanceMatrix(locs) # run the vector fit ctree.computeCVF(self.greens_tree.freqs, z_mat) taus_fit2 = np.array([n.ca / n.currents['L'][0] for n in ctree]) assert np.allclose(taus_orig, taus_fit2, atol=.3) def fitBallAndStick(self, n_loc=20): self.loadBallAndStick() # define locations xvals = np.linspace(0., 1., n_loc + 1)[1:] np.random.shuffle(xvals) locs = [(1, 0.5)] + [(4, x) for x in xvals] # create compartment tree ctree = self.greens_tree.createCompartmentTree(locs) # steady state fit z_mat = self.greens_tree.calcImpedanceMatrix(locs)[0].real ctree.computeGMC(z_mat) # get SOV constants for capacitance fit alphas, phimat, importance = self.sov_tree.getImportantModes( locarg=locs, sort_type='importance', eps=1e-12, return_importance=True) # fit the capacitances from SOV time-scales ctree.computeC(-alphas[0:1].real * 1e3, phimat[0:1, :].real, weights=importance[0:1]) self.ctree = ctree def testPasFunctionality(self, n_loc=10): self.fitBallAndStick(n_loc=n_loc) # test equilibrium potential setting e_eq = -75. + np.random.randint(10, size=n_loc + 1) # with tree indexing self.ctree.setEEq(e_eq, indexing='tree') assert np.allclose(e_eq, np.array([n.e_eq for n in self.ctree])) assert np.allclose(e_eq, self.ctree.getEEq(indexing='tree')) assert not np.allclose(e_eq, self.ctree.getEEq(indexing='locs')) # with loc indexing self.ctree.setEEq(e_eq, indexing='locs') assert not np.allclose(e_eq, np.array([n.e_eq for n in self.ctree])) assert not np.allclose(e_eq, self.ctree.getEEq(indexing='tree')) assert np.allclose(e_eq, self.ctree.getEEq(indexing='locs')) # conductance matrices gm1 = self.ctree.calcConductanceMatrix(indexing='locs') gm2 = self.ctree.calcSystemMatrix(indexing='locs', channel_names=['L'], with_ca=True, use_conc=False) gm3 = self.ctree.calcSystemMatrix(indexing='locs', channel_names=['L'], with_ca=False, use_conc=False) gm4 = self.ctree.calcSystemMatrix(indexing='locs', channel_names=['L'], with_ca=False, use_conc=True) gm5 = self.ctree.calcSystemMatrix(indexing='locs', with_ca=False, use_conc=True) gm6 = self.ctree.calcSystemMatrix(indexing='tree', with_ca=False, use_conc=True) assert np.allclose(gm1, gm2) assert np.allclose(gm1, gm3) assert np.allclose(gm1, gm4) assert np.allclose(gm1, gm5) assert not np.allclose(gm1, gm6) # eigenvalues alphas, phimat, phimat_inv = self.ctree.calcEigenvalues() ca_vec = np.array([1. / node.ca for node in self.ctree]) * 1e-3 assert np.allclose(np.dot(phimat, phimat_inv), np.diag(ca_vec)) assert np.allclose( np.array([n.ca / n.currents['L'][0] for n in self.ctree]), np.ones(len(self.ctree)) * np.max(1e-3 / np.abs(alphas))) def loadBall(self): self.greens_tree = GreensTree( file_n=os.path.join(MORPHOLOGIES_PATH_PREFIX, 'ball.swc')) # capacitance and axial resistance self.greens_tree.setPhysiology(0.8, 100. / 1e6) # ion channels k_chan = channelcollection.Kv3_1() self.greens_tree.addCurrent(k_chan, 0.766 * 1e6, -85.) na_chan = channelcollection.Na_Ta() self.greens_tree.addCurrent(na_chan, 1.71 * 1e6, 50.) # fit leak current self.greens_tree.fitLeakCurrent(-75., 10.) # set computational tree self.greens_tree.setCompTree() # set the impedances self.freqs = np.array([0.]) self.greens_tree.setImpedance(self.freqs) # create sov tree self.sov_tree = self.greens_tree.__copy__(new_tree=SOVTree()) self.sov_tree.calcSOVEquations(maxspace_freq=100.) def testChannelFit(self): self.loadBall() locs = [(1, 0.5)] e_eqs = [-75., -55., -35., -15.] # create compartment tree ctree = self.greens_tree.createCompartmentTree(locs) ctree.addCurrent(channelcollection.Na_Ta(), 50.) ctree.addCurrent(channelcollection.Kv3_1(), -85.) # create tree with only leak greens_tree_pas = self.greens_tree.__copy__() greens_tree_pas[1].currents = {'L': greens_tree_pas[1].currents['L']} greens_tree_pas.setCompTree() greens_tree_pas.setImpedance(self.freqs) # compute the passive impedance matrix z_mat_pas = greens_tree_pas.calcImpedanceMatrix(locs)[0] # create tree with only potassium greens_tree_k = self.greens_tree.__copy__() greens_tree_k[1].currents = {key: val for key, val in greens_tree_k[1].currents.items() \ if key != 'Na_Ta'} # compute potassium impedance matrices z_mats_k = [] for e_eq in e_eqs: greens_tree_k.setEEq(e_eq) greens_tree_k.setCompTree() greens_tree_k.setImpedance(self.freqs) z_mats_k.append(greens_tree_k.calcImpedanceMatrix(locs)) # create tree with only sodium greens_tree_na = self.greens_tree.__copy__() greens_tree_na[1].currents = {key: val for key, val in greens_tree_na[1].currents.items() \ if key != 'Kv3_1'} # create state variable expansion points svs = [] e_eqs_ = [] na_chan = greens_tree_na.channel_storage['Na_Ta'] for e_eq1 in e_eqs: sv1 = na_chan.computeVarinf(e_eq1) for e_eq2 in e_eqs: e_eqs_.append(e_eq2) sv2 = na_chan.computeVarinf(e_eq2) svs.append({'m': sv2['m'], 'h': sv1['h']}) # compute sodium impedance matrices z_mats_na = [] for ii, sv in enumerate(svs): greens_tree_na.setEEq(e_eqs[ii % len(e_eqs)]) greens_tree_na[1].setExpansionPoint('Na_Ta', sv) greens_tree_na.setCompTree() greens_tree_na.setImpedance(self.freqs) z_mats_na.append(greens_tree_na.calcImpedanceMatrix(locs)) # compute combined impedance matrices z_mats_comb = [] for e_eq in e_eqs: self.greens_tree.setEEq(e_eq) self.greens_tree.setCompTree() self.greens_tree.setImpedance(self.freqs) z_mats_comb.append(self.greens_tree.calcImpedanceMatrix(locs)) # passive fit ctree.computeGMC(z_mat_pas) # get SOV constants for capacitance fit sov_tree = greens_tree_pas.__copy__(new_tree=SOVTree()) sov_tree.setCompTree() sov_tree.calcSOVEquations() alphas, phimat, importance = sov_tree.getImportantModes( locarg=locs, sort_type='importance', eps=1e-12, return_importance=True) # fit the capacitances from SOV time-scales ctree.computeC(-alphas[0:1].real * 1e3, phimat[0:1, :].real, weights=importance[0:1]) ctree1 = copy.deepcopy(ctree) ctree2 = copy.deepcopy(ctree) ctree3 = copy.deepcopy(ctree) ctree4 = copy.deepcopy(ctree) # fit paradigm 1 --> separate impedance matrices and separate fits # potassium channel fit for z_mat_k, e_eq in zip(z_mats_k, e_eqs): ctree1.computeGSingleChanFromImpedance('Kv3_1', z_mat_k, e_eq, self.freqs, other_channel_names=['L']) ctree1.runFit() # sodium channel fit for z_mat_na, e_eq, sv in zip(z_mats_na, e_eqs_, svs): ctree1.computeGSingleChanFromImpedance('Na_Ta', z_mat_na, e_eq, self.freqs, sv=sv, other_channel_names=['L']) ctree1.runFit() # fit paradigm 2 --> separate impedance matrices, same fit for z_mat_k, e_eq in zip(z_mats_k, e_eqs): ctree2.computeGSingleChanFromImpedance( 'Kv3_1', z_mat_k, e_eq, self.freqs, all_channel_names=['Kv3_1', 'Na_Ta']) for z_mat_na, e_eq, sv in zip(z_mats_na, e_eqs_, svs): ctree2.computeGSingleChanFromImpedance( 'Na_Ta', z_mat_na, e_eq, self.freqs, sv=sv, all_channel_names=['Kv3_1', 'Na_Ta']) ctree2.runFit() # fit paradigm 3 --> same impedance matrices for z_mat_comb, e_eq in zip(z_mats_comb, e_eqs): ctree3.computeGChanFromImpedance(['Kv3_1', 'Na_Ta'], z_mat_comb, e_eq, self.freqs) ctree3.runFit() # fit paradigm 4 --> fit incrementally for z_mat_na, e_eq, sv in zip(z_mats_na, e_eqs_, svs): ctree4.computeGSingleChanFromImpedance('Na_Ta', z_mat_na, e_eq, self.freqs, sv=sv) ctree4.runFit() for z_mat_comb, e_eq in zip(z_mats_comb, e_eqs): ctree4.computeGSingleChanFromImpedance( 'Kv3_1', z_mat_comb, e_eq, self.freqs, other_channel_names=['Na_Ta', 'L']) ctree4.runFit() # test if correct keys = ['L', 'Na_Ta', 'Kv3_1'] # soma surface (cm) for total conductance calculation a_soma = 4. * np.pi * (self.greens_tree[1].R * 1e-4)**2 conds = np.array( [self.greens_tree[1].currents[key][0] * a_soma for key in keys]) # compartment models conductances cconds1 = np.array([ctree1[0].currents[key][0] for key in keys]) cconds2 = np.array([ctree2[0].currents[key][0] for key in keys]) cconds3 = np.array([ctree3[0].currents[key][0] for key in keys]) cconds4 = np.array([ctree4[0].currents[key][0] for key in keys]) assert np.allclose(conds, cconds1) assert np.allclose(conds, cconds2) assert np.allclose(conds, cconds3) assert np.allclose(conds, cconds4) # rename for further testing ctree = ctree1 # frequency array ft = ke.FourrierTools(np.linspace(0., 50., 100)) freqs = ft.s # compute impedance matrix v_h = -42. # original self.greens_tree.setEEq(v_h) self.greens_tree.setCompTree() self.greens_tree.setImpedance(freqs) z_mat_orig = self.greens_tree.calcImpedanceMatrix([(1., .5)]) # potassium greens_tree_k.setEEq(v_h) greens_tree_k.setCompTree() greens_tree_k.setImpedance(freqs) z_mat_k = greens_tree_k.calcImpedanceMatrix([(1, .5)]) # sodium greens_tree_na.removeExpansionPoints() greens_tree_na.setEEq(v_h) greens_tree_na.setCompTree() greens_tree_na.setImpedance(freqs) z_mat_na = greens_tree_na.calcImpedanceMatrix([(1, .5)]) # passive greens_tree_pas.setCompTree() greens_tree_pas.setImpedance(freqs) z_mat_pas = greens_tree_pas.calcImpedanceMatrix([(1, .5)]) # reduced impedance matrices ctree.removeExpansionPoints() ctree.setEEq(v_h) z_mat_fit = ctree.calcImpedanceMatrix(freqs=freqs) z_mat_fit_k = ctree.calcImpedanceMatrix(channel_names=['L', 'Kv3_1'], freqs=freqs) z_mat_fit_na = ctree.calcImpedanceMatrix(channel_names=['L', 'Na_Ta'], freqs=freqs) z_mat_fit_pas = ctree.calcImpedanceMatrix(channel_names=['L'], freqs=freqs) assert np.allclose(z_mat_orig, z_mat_fit) assert np.allclose(z_mat_k, z_mat_fit_k) assert np.allclose(z_mat_na, z_mat_fit_na) assert np.allclose(z_mat_pas, z_mat_fit_pas) # test total current, conductance sv = svs[-1] p_open = sv['m']**3 * sv['h'] # with p_open given g1 = ctree[0].getGTot(ctree.channel_storage, channel_names=['L', 'Na_Ta'], p_open_channels={'Na_Ta': p_open}) i1 = ctree[0].getGTot(ctree.channel_storage, channel_names=['L', 'Na_Ta'], p_open_channels={'Na_Ta': p_open}) # with expansion point given ctree.setExpansionPoints({'Na_Ta': sv}) g2 = ctree[0].getGTot(ctree.channel_storage, channel_names=['L', 'Na_Ta']) i2 = ctree[0].getGTot(ctree.channel_storage, channel_names=['L', 'Na_Ta']) # with e_eq given g3 = ctree[0].getGTot(ctree.channel_storage, v=e_eqs[-1], channel_names=['L', 'Na_Ta']) i3 = ctree[0].getGTot(ctree.channel_storage, v=e_eqs[-1], channel_names=['L', 'Na_Ta']) # with e_eq stored ctree.setEEq(e_eqs[-1]) g4 = ctree[0].getGTot(ctree.channel_storage, channel_names=['L', 'Na_Ta']) i4 = ctree[0].getGTot(ctree.channel_storage, channel_names=['L', 'Na_Ta']) # check if correct assert np.abs(g1 - g2) < 1e-10 assert np.abs(g1 - g3) < 1e-10 assert np.abs(g1 - g4) < 1e-10 assert np.abs(i1 - i2) < 1e-10 assert np.abs(i1 - i3) < 1e-10 assert np.abs(i1 - i4) < 1e-10 # compare current, conductance g_ = ctree[0].getGTot(ctree.channel_storage, channel_names=['Na_Ta']) i_ = ctree[0].getITot(ctree.channel_storage, channel_names=['Na_Ta']) assert np.abs(g_ * (e_eqs[-1] - ctree[0].currents['Na_Ta'][1]) - i_) < 1e-10 # test leak fitting self.greens_tree.setEEq(-75.) self.greens_tree.setCompTree() ctree.setEEq(-75.) ctree.removeExpansionPoints() ctree.fitEL() assert np.abs(ctree[0].currents['L'][1] - self.greens_tree[1].currents['L'][1]) < 1e-10
class TestSOVTree(): def loadTTree(self): """ Load the T-tree morphology in memory 6--5--4--7--8 | | 1 """ fname = os.path.join(MORPHOLOGIES_PATH_PREFIX, 'Tsovtree.swc') self.tree = SOVTree(fname, types=[1,3,4]) self.tree.fitLeakCurrent(-75., 10.) self.tree.setCompTree() def loadValidationTree(self): """ Load the T-tree morphology in memory 5---1---4 """ fname = os.path.join(MORPHOLOGIES_PATH_PREFIX, 'sovvalidationtree.swc') self.tree = SOVTree(fname, types=[1,3,4]) self.tree.fitLeakCurrent(-75., 10.) self.tree.setCompTree() def testSOVCalculation(self): # validate the calculation on analytical model self.loadValidationTree() # do SOV calculation self.tree.calcSOVEquations() alphas, gammas = self.tree.getSOVMatrices([(1, 0.5)]) # compute time scales analytically self.tree.treetype = 'computational' lambda_m_test = np.sqrt(self.tree[4].R_sov / \ (2.*self.tree[4].g_m*self.tree[4].r_a)) tau_m_test = self.tree[4].c_m / self.tree[4].g_m * 1e3 alphas_test = \ (1. + \ (np.pi * np.arange(20) * lambda_m_test / \ (self.tree[4].L_sov + self.tree[5].L_sov))**2) / \ tau_m_test # compare analytical and computed time scales assert np.allclose(alphas[:20], alphas_test) # compute the spatial mode functions analytically ## TODO # test basic identities self.loadTTree() self.tree.calcSOVEquations(maxspace_freq=500) # sets of location locs_0 = [(6, .5), (8, .5)] locs_1 = [(1, .5), (4, .5), (4, 1.), (5, .5), (6, .5), (7, .5), (8, .5)] locs_2 = [(7, .5), (8, .5)] self.tree.storeLocs(locs_0, '0') self.tree.storeLocs(locs_1, '1') self.tree.storeLocs(locs_2, '2') # test mode importance imp_a = self.tree.getModeImportance(locarg=locs_0) imp_b = self.tree.getModeImportance(locarg='0') imp_c = self.tree.getModeImportance( sov_data=self.tree.getSOVMatrices(locarg=locs_0)) imp_d = self.tree.getModeImportance( sov_data=self.tree.getSOVMatrices(locarg='0')) assert np.allclose(imp_a, imp_b) assert np.allclose(imp_a, imp_c) assert np.allclose(imp_a, imp_d) assert np.abs(1. - np.max(imp_a)) < 1e-12 with pytest.raises(IOError): self.tree.getModeImportance() # test important modes imp_2 = self.tree.getModeImportance(locarg='2') assert not np.allclose(imp_a, imp_2) # test impedance matrix z_mat_a = self.tree.calcImpedanceMatrix( sov_data=self.tree.getImportantModes(locarg='1', eps=1e-10)) z_mat_b = self.tree.calcImpedanceMatrix(locarg='1', eps=1e-10) assert np.allclose(z_mat_a, z_mat_b) assert np.allclose(z_mat_a - z_mat_a.T, np.zeros(z_mat_a.shape)) for ii, z_row in enumerate(z_mat_a): assert np.argmax(z_row) == ii # test Fourrier impedance matrix ft = ke.FourrierTools(np.arange(0.,100.,0.1)) z_mat_ft = self.tree.calcImpedanceMatrix(locarg='1', eps=1e-10, freqs=ft.s) assert np.allclose(z_mat_ft[ft.ind_0s,:,:].real, \ z_mat_a, atol=1e-1) # check steady state assert np.allclose(z_mat_ft - np.transpose(z_mat_ft, axes=(0,2,1)), \ np.zeros(z_mat_ft.shape)) # check symmetry assert np.allclose(z_mat_ft[:ft.ind_0s,:,:].real, \ z_mat_ft[ft.ind_0s+1:,:,:][::-1,:,:].real) # check real part even assert np.allclose(z_mat_ft[:ft.ind_0s,:,:].imag, \ -z_mat_ft[ft.ind_0s+1:,:,:][::-1,:,:].imag) # check imaginary part odd def loadBall(self): """ Load point neuron model """ fname = os.path.join(MORPHOLOGIES_PATH_PREFIX, 'ball.swc') self.btree = SOVTree(fname, types=[1,3,4]) self.btree.fitLeakCurrent(-75., 10.) self.btree.setCompTree() def testSingleCompartment(self): self.loadBall() # for validation greenstree = self.btree.__copy__(new_tree=GreensTree()) greenstree.setCompTree() greenstree.setImpedance(np.array([0.])) z_inp = greenstree.calcImpedanceMatrix([(1.,0.5)]) self.btree.calcSOVEquations(maxspace_freq=500) alphas, gammas = self.btree.getSOVMatrices(locarg=[(1.,.5)]) z_inp_sov = self.btree.calcImpedanceMatrix(locarg=[(1.,.5)]) assert alphas.shape[0] == 1 assert gammas.shape == (1,1) assert np.abs(1./np.abs(alphas[0]) - 10.) < 1e-10 g_m = self.btree[1].getGTot(self.btree.channel_storage) g_s = g_m * 4.*np.pi*(self.btree[1].R*1e-4)**2 assert np.abs(gammas[0,0]**2/np.abs(alphas[0]) - 1./g_s) < 1e-10 assert np.abs(z_inp_sov - 1./g_s) < 1e-10 def testNETDerivation(self): # initialize self.loadValidationTree() self.tree.calcSOVEquations() # construct the NET net = self.tree.constructNET() # initialize self.loadTTree() self.tree.calcSOVEquations() # construct the NET net = self.tree.constructNET(dz=20.) # contruct the NET with linear terms net, lin_terms = self.tree.constructNET(dz=20., add_lin_terms=True) # check if correct alphas, gammas = self.tree.getImportantModes(locarg='net eval', eps=1e-4, sort_type='timescale') for ii, lin_term in lin_terms.items(): z_k_trans = net.getReducedTree([0,ii]).getRoot().z_kernel + lin_term assert np.abs(z_k_trans.k_bar - Kernel((alphas, gammas[:,0]*gammas[:,ii])).k_bar) < 1e-8