def test_check_params_02(self): '''Test that ValueError is raised if electrode outside head''' radii = [1., 2., 4., 10.] sigmas = [1., 2., 4., 8.] r_el1 = np.array([[0., 0., 15.]]) r_el2 = np.array([[0., 0., 1.5], [12., 0., 0.]]) with np.testing.assert_raises(ValueError): eegmegcalc.FourSphereVolumeConductor(r_el1, radii, sigmas) with np.testing.assert_raises(ValueError): eegmegcalc.FourSphereVolumeConductor(r_el2, radii, sigmas)
def make_class_object(rz, r_el): '''Return class object fs''' radii = [79., 80., 85., 90.] sigmas = [0.3, 0.015, 15, 0.3] fs = eegmegcalc.FourSphereVolumeConductor(r_el, radii, sigmas) fs._rz_params(rz) return fs
def test_get_transformation_matrix_00(self): '''Test radial and tangential parts of dipole sums to dipole''' radii = [88000, 90000, 95000, 100000] sigmas = [0.3, 1.5, 0.015, 0.3] dips = np.array([[[1000., 0., 0.]], [[-1000., 0., 0.]], [[0., 1000., 0.]], [[0., -1000., 0.]], [[0., 0., 1000.]], [[0., 0., -1000.]]]) p_locs = np.array([[87000., 0., 0.], [-87000., 0., 0.], [0., 87000., 0.], [0., -87000., 0.], [0., 0., 87000], [0., 0., -87000]]) el_locs = np.array([[[99000., 0., 0.]], [[-99000., 0., 0.]], [[0., 99000., 0.]], [[0., -99000., 0.]], [[0., 0., 99000.]], [[0., 0., -99000.]]]) for i in range(len(p_locs)): fs = eegmegcalc.FourSphereVolumeConductor(el_locs[i], radii, sigmas) phi = fs.get_dipole_potential(dips[i].T, p_locs[i]) M = fs.get_transformation_matrix(p_locs[i]) np.testing.assert_allclose(M @ dips[i].T, phi)
def test_get_dipole_potential_02(self): '''Test radial and tangential parts of dipole sums to dipole''' radii = [88000, 90000, 95000, 100000] sigmas = [0.3, 1.5, 0.015, 0.3] dips = np.array([[[1000., 0., 0.]], [[-1000., 0., 0.]], [[0., 1000., 0.]], [[0., -1000., 0.]], [[0., 0., 1000.]], [[0., 0., -1000.]]]) p_locs = np.array([[87000., 0., 0.], [-87000., 0., 0.], [0., 87000., 0.], [0., -87000., 0.], [0., 0., 87000], [0., 0., -87000]]) el_locs = np.array([[[99000., 0., 0.]], [[-99000., 0., 0.]], [[0., 99000., 0.]], [[0., -99000., 0.]], [[0., 0., 99000.]], [[0., 0., -99000.]]]) for i in range(len(p_locs)): fs = eegmegcalc.FourSphereVolumeConductor(el_locs[i], radii, sigmas) phi = fs.get_dipole_potential(dips[i].T, p_locs[i]) if i == 0: phi0 = phi[0][0] else: np.testing.assert_equal(phi0, phi[0][0])
def test_check_params_01(self): '''Test that Error is raised if invalid entries in sigmas''' radii = [1., 2., 4., 10.] sigmas1 = [1., 'str', 4., 8.] sigmas2 = [-1., 2., 4., 8.] sigmas3 = [1., 2., -4., 8.] sigmas4 = [1., 2., 4., -8.] r_el = np.array([[0., 0., 1.5]]) with np.testing.assert_raises(ValueError): eegmegcalc.FourSphereVolumeConductor(r_el, radii, sigmas1) with np.testing.assert_raises(RuntimeError): eegmegcalc.FourSphereVolumeConductor(r_el, radii, sigmas2) with np.testing.assert_raises(RuntimeError): eegmegcalc.FourSphereVolumeConductor(r_el, radii, sigmas3) with np.testing.assert_raises(RuntimeError): eegmegcalc.FourSphereVolumeConductor(r_el, radii, sigmas4)
def test_check_params_00(self): '''Test that invalid radius values raises RuntimeError''' radii1 = [-1., 2., 4., 8.] radii2 = [1., .5, 4., 8.] radii3 = [1., 2., 1.1, 8.] radii4 = [1., 2., 4., 1.] sigmas = [1., 2., 4., 8.] r_el = np.array([[0., 0., 1.5]]) with np.testing.assert_raises(RuntimeError): eegmegcalc.FourSphereVolumeConductor(r_el, radii1, sigmas) with np.testing.assert_raises(RuntimeError): eegmegcalc.FourSphereVolumeConductor(r_el, radii2, sigmas) with np.testing.assert_raises(RuntimeError): eegmegcalc.FourSphereVolumeConductor(r_el, radii3, sigmas) with np.testing.assert_raises(RuntimeError): eegmegcalc.FourSphereVolumeConductor(r_el, radii4, sigmas)
def test_calc_phi_01(self): '''Test phi: azimuthal angle between rx and rxy, check that theta is not NaN, due to round-off errors''' radii = [79000., 80000., 85000., 100000.] sigmas = [0.3, 0.015, 15, 0.3] rz = np.array([0., 0., 76500.]) r_el = np.array([[1e-5, 0, 99999.], [0, 0.000123, 99998.9], [-5.59822325e3, -9.69640709e3, -9.93712111e4], [99990., 0., 0.001]]) fs = eegmegcalc.FourSphereVolumeConductor(r_el, radii, sigmas) fs._rz_params(rz) P1 = np.array([[0., 0., 123456789.], [0., 0., 0.05683939], [89892340., 0., -123456789], [0.00004, 0.002, .0987654321], [0., 0., 0.05683939], [0.0003, 0.001, 123456789.], [1e-11, 1e-12, 1000.], [1e-15, 0, 1000.]]).T p_rad, p_tan = fs._decompose_dipole(P1) phi = fs._calc_phi(p_tan) np.testing.assert_equal(np.isnan(phi).any(), False)
def test_decompose_dipole_01(self): '''Test radial and tangential parts of dipole sums to dipole''' radii = [88000, 90000, 95000, 100000] sigmas = [0.3, 1.5, 0.015, 0.3] ps = np.array([[1000., 0., 0.], [-1000., 0., 0.], [0., 1000., 0.], [0., -1000., 0.], [0., 0., 1000.], [0., 0., -1000.], [10., 20., 30.], [-10., -20., -30.]]).T p_locs = np.array([[87000., 0., 0.], [-87000., 0., 0.], [0., 87000., 0.], [0., -87000., 0.], [0., 0., 87000.], [0., 0., -87000.], [80000., 2000., 3000.], [-2000., -80000., -3000.]]) el_locs = np.array([[90000., 5000., -5000.]]) fs = eegmegcalc.FourSphereVolumeConductor( el_locs, radii, sigmas) for p_loc in p_locs: fs._rz_params(p_loc) p_rads, p_tans = fs._decompose_dipole(ps) np.testing.assert_equal(p_rads + p_tans, ps)
def make_simple_class_object(): '''Return class object fs''' radii = [1., 2., 4., 8.] sigmas = [1., 2., 4., 8.] rz1 = np.array([0., 0., .9]) r_el = np.array([[0., 0., 1.5]]) fs = eegmegcalc.FourSphereVolumeConductor(r_el, radii, sigmas) fs._rz_params(rz1) return fs
def test_get_dipole_potential_00(self): '''test comparison between four-sphere model and model for infinite homogeneous space when sigma is constant and r4 goes to infinity''' sigmas = [0.3, 0.3, 0.3 + 1e-16, 0.3] radii = [10., 20 * 1e6, 30. * 1e6, 40. * 1e6] rz = np.array([0., 0., 3.]) p = np.array([[0., 0., 100.], [50., 50., 0.]]).T r_elec = np.array([[0., 0., 9.], [0., 0., 15.], [0., 0., 25.], [0., 0., 40.], [0., 9., 0.], [0., 15., 0.], [0., 25., 0.], [0., 40., 0.]]) four_s = eegmegcalc.FourSphereVolumeConductor(r_elec, radii, sigmas) pots_4s = four_s.get_dipole_potential(p, rz) inf_s = eegmegcalc.InfiniteVolumeConductor(0.3) pots_inf = inf_s.get_dipole_potential(p, r_elec - rz) np.testing.assert_allclose(pots_4s, pots_inf, rtol=1e-6)
def test_rz_params_00(self): radii = [1., 2., 4., 8.] sigmas = [1., 2., 4., 8.] r_el = np.array([[1., 0., 7.]]) fs = eegmegcalc.FourSphereVolumeConductor(r_electrodes=r_el, radii=radii, sigmas=sigmas) rz1 = np.array([0., 0., 0.]) with np.testing.assert_raises(RuntimeError): fs._rz_params(rz1) rz2 = np.array([0., 0., 1.]) with np.testing.assert_raises(RuntimeError): fs._rz_params(rz2) rz3 = np.array([0., 0., 1.2]) with np.testing.assert_raises(RuntimeError): fs._rz_params(rz3)
def test_get_dipole_potential_05(self): # check that predictions are rotation invariant radii = [79000., 80000., 85000., 90000.] # (µm) sigmas = [0.3, 1.5, 0.015, 0.3] # (S/m) # locations in yz-plane along outer layer surface r_e = radii[-1] - 1 # radius for prediction sites (µm) theta = np.linspace(0, 2 * np.pi, 72, endpoint=False) # polar (rad) phi = 0 # azimuth angle (rad) r_el = r_e * np.c_[np.sin(theta) * np.sin(phi), np.sin(theta) * np.cos(phi), np.cos(theta)] sphere_model = eegmegcalc.FourSphereVolumeConductor( r_electrodes=r_el, radii=radii, sigmas=sigmas) # radial dipole locations in yz-plane r = radii[0] - 1000 # dipole location(µm) theta_p = np.linspace(0, 2 * np.pi, 8, endpoint=False) # polar(rad) phi_p = 0 # azimuth angle (rad) r_p = r * np.c_[np.sin(theta_p) * np.sin(phi_p), np.sin(theta_p) * np.cos(phi_p), np.cos(theta_p)] # unit radial current dipoles at each location: p = (r_p.T / np.linalg.norm(r_p, axis=-1)).T # (nAµm) def R_x(theta=0): '''rotation matrix around x-axis by some angle theta (rad)''' return np.c_[[1, 0, 0], [0, np.cos(theta), -np.sin(theta)], [0, np.sin(theta), np.cos(theta)]].T R_x_45 = R_x(theta=np.pi / 4) # rotate by 45 deg V_e = np.zeros((theta_p.size, theta.size)) for i, (r_p_, p_, theta_p_) in enumerate( zip(r_p, p @ R_x_45, theta_p)): V_e[i] = np.roll( sphere_model.get_dipole_potential(np.expand_dims(p_, -1), r_p_).ravel(), -i * theta.size // theta_p.size) assert np.allclose(V_e, V_e[0])
def test_get_dipole_potential_01(self): '''test comparison between analytical 4S-model and FEM simulation''' # load data fem_sim = np.load( os.path.join(lfpykit.__path__[0], 'tests', 'fem_mix_dip.npz')) pot_fem = fem_sim['pot_fem'] # [µV] p = fem_sim['p'].T # [nA µm] rz = fem_sim['rz'] # [µm] radii = fem_sim['radii'] # [µm] sigmas = fem_sim['sigmas'] # [S/cm] ele_coords = fem_sim['ele_coords'] # [µm] fs = eegmegcalc.FourSphereVolumeConductor(ele_coords, radii, sigmas) k_mV_to_muV = 1e3 pot_analytical = fs.get_dipole_potential(p, rz).reshape( (len(ele_coords), )).reshape(pot_fem.shape) * k_mV_to_muV global_error = np.abs(pot_analytical - pot_fem) / \ (np.max(np.abs(pot_fem))) np.testing.assert_array_less(global_error, 0.01)