Example #1
0
    def test_calc_dadt(self, sphere3_msh):
        phi = sphere3_msh.nodes.node_coord[:, 0] + \
            2 * sphere3_msh.nodes.node_coord[:, 1] + \
            -3 * sphere3_msh.nodes.node_coord[:, 2]
        potential = mesh_io.NodeData(phi, mesh=sphere3_msh)

        dadt = .2 * sphere3_msh.nodes.node_coord
        dadt = mesh_io.NodeData(dadt, mesh=sphere3_msh)

        E = np.zeros((sphere3_msh.elm.nr, 3))
        E = [-1, -2, 3] - dadt.node_data2elm_data().value
        E = mesh_io.ElementData(E, mesh=sphere3_msh)
        E.assign_triangle_values()

        cond = sphere3_msh.elm.tag1
        cond = mesh_io.ElementData(cond, mesh=sphere3_msh)

        m = fem.calc_fields(potential, 'vDJEgsej', cond, dadt=dadt,
                            units='m')
        assert np.allclose(m.field['v'].value, potential.value)
        assert np.allclose(m.field['D'].value, dadt.value)
        assert np.allclose(m.field['g'].value, [1, 2, -3])
        assert np.allclose(m.field['E'].value, E.value)
        assert np.allclose(m.field['J'].value, cond.value[:, None] * E.value)
        assert np.allclose(m.field['conductivity'].value, cond.value)
        assert np.allclose(m.field['normE'].value, np.linalg.norm(E.value, axis=1))
        assert np.allclose(m.field['normJ'].value,
                           np.linalg.norm(cond.value[:, None] * E.value, axis=1))
Example #2
0
    def test_calc_vEJgs(self, sphere3_msh):
        phi = sphere3_msh.nodes.node_coord[:, 0] + \
            2 * sphere3_msh.nodes.node_coord[:, 1] + \
            -3 * sphere3_msh.nodes.node_coord[:, 2]
        potential = mesh_io.NodeData(phi, mesh=sphere3_msh)

        E = np.zeros((sphere3_msh.elm.nr, 3))
        E[:] = [-1., -2., 3.]
        E = mesh_io.ElementData(E, mesh=sphere3_msh)

        cond = sphere3_msh.elm.tag1
        cond = mesh_io.ElementData(cond, mesh=sphere3_msh)

        m = fem.calc_fields(potential, 'vJEgsej', cond)
        assert np.allclose(m.field['v'].value, potential.value)
        assert np.allclose(m.field['E'].value, E.value * 1e3)
        assert np.allclose(m.field['J'].value,
                           cond.value[:, None] * E.value * 1e3)
        assert np.allclose(m.field['g'].value, -E.value * 1e3)
        assert np.allclose(m.field['conductivity'].value, cond.value)
        assert np.allclose(m.field['normE'].value,
                           np.linalg.norm(E.value, axis=1) * 1e3)
        assert np.allclose(
            m.field['normJ'].value,
            np.linalg.norm(cond.value[:, None] * E.value, axis=1) * 1e3)
Example #3
0
    def test_tms_dadt(self, tms_sphere):
        m, cond, dAdt, E_analytical = tms_sphere
        v = fem.tms_dadt(m, cond, dAdt)
        E = -v.gradient().value * 1e3 - dAdt.node_data2elm_data().value
        m.elmdata = [mesh_io.ElementData(E_analytical, 'analytical'),
                     mesh_io.ElementData(E, 'E_FEM'),
                     mesh_io.ElementData(E_analytical + dAdt.node_data2elm_data().value, 'grad_analytical'),
                     dAdt]

        #mesh_io.write_msh(m, '~/Tests/fem.msh')
        assert rdm(E, E_analytical) < .2
        assert np.abs(mag(E, E_analytical)) < np.log(1.1)
Example #4
0
    def test_single_dipole(self, dipole_direction, pos_target, sphere3_msh):
        bar = sphere3_msh.elements_baricenters()[sphere3_msh.elm.tetrahedra]
        vol = sphere3_msh.elements_volumes_and_areas()
        dipole_th = np.argmin(np.linalg.norm(pos_target - bar, axis=1))
        dipole_pos = bar[dipole_th]
        dipole_th = sphere3_msh.elm.tetrahedra[dipole_th]

        surface_nodes = np.unique(
            sphere3_msh.elm[sphere3_msh.elm.tag1 == 1005, :3])
        surface_nodes_pos = sphere3_msh.nodes[surface_nodes]

        analytical_v = analytical_solutions.potential_dipole_3layers(
            [85, 90, 95], 2, 0.1, dipole_pos, dipole_direction,
            surface_nodes_pos)

        # Relationship between primary current J and dipole vector p
        # p = \int J dV
        # p = J*V_i
        # J = p/V_i
        primary_j = mesh_io.ElementData(np.zeros((sphere3_msh.elm.nr, 3)))
        primary_j[dipole_th] = dipole_direction / (vol[dipole_th] * 1e-9)
        cond = 2 * np.ones(sphere3_msh.elm.nr)
        cond[sphere3_msh.elm.tag1 == 4] = 0.1
        S = fem.FEMSystem.electric_dipole(sphere3_msh, cond)
        b = S.assemble_electric_dipole_rhs(primary_j)
        numerical_v = S.solve(b)[surface_nodes - 1]

        analytical_v -= np.average(analytical_v)
        numerical_v -= np.average(numerical_v)
        assert rdm(analytical_v, numerical_v) < 0.2
        assert mag(analytical_v, numerical_v) < 0.15
Example #5
0
    def test_solve_petsc(self, tms_sphere):
        m, cond, dAdt, E_analytical = tms_sphere
        S = fem.FEMSystem.tms(m, cond)
        b = S.assemble_tms_rhs(dAdt)
        x = S.solve(b)
        v = mesh_io.NodeData(x, 'FEM', mesh=m)
        E = -v.gradient().value * 1e3 - dAdt.node_data2elm_data().value
        m.elmdata = [mesh_io.ElementData(E_analytical, 'analytical'),
                     mesh_io.ElementData(E, 'E_FEM'),
                     mesh_io.ElementData(E_analytical + dAdt.node_data2elm_data().value, 'grad_analytical'),
                     dAdt]

        m.nodedata = [mesh_io.NodeData(x, 'FEM')]
        #mesh_io.write_msh(m, '~/Tests/fem.msh')
        assert rdm(E, E_analytical) < .2
        assert np.abs(mag(E, E_analytical)) < np.log(1.1)
Example #6
0
 def test_avoid_mean_field_norm_elm(self, sphere_surf):
     a = opt_struct.TDCSavoid(tissues=[1003],
                              weight=1e4,
                              lf_type='element',
                              mesh=sphere_surf)
     field = mesh_io.ElementData(np.ones((sphere_surf.elm.nr, 3)))
     field[sphere_surf.elm.tag1 == 1003] = [2, 0, 0]
     assert np.isclose(a.mean_field_norm_in_region(field), 2)
Example #7
0
def calc_B(J, n_voxels, affine, calc_res=2., mask=False):
    ''' Calculates the magnetic field caused by a current density distribution J

    Parameters
    ----------
    J: simnibs.msh.ElementData
        ElementData field with the current density field
    n_voxels: list or tuple
        number of voxels in x, y, and z directions for the output B
    affine: ndarray
        A 4x4 matrix specifying the transformation from voxels to xyz for the output B
    calc_res: float (optional)
        Resolution of the space used for the FFT calculations, in mm. Default: 2
    mask: bool (optional)
        Wether to mask the resul using the mesh. Default: False

    Returns
    --------
    B: ndarray
        numpy array of size n_voxesx3 with the magnetic field        

    Reference
    ----------
    Yazdanian, H., Saturnino, G. B., Thielscher, A., & Knudsen, K. (2020).
    Fast evaluation of the Biot-Savart integral using FFT for electrical conductivity imaging.
    Journal of Computational Physics, 109408.
    https://doi.org/10.1016/j.jcp.2020.109408

    Example
    ---------
    Load a simulation result with a 'J' field can calculate B in an ROI
    Defined by a nifti file
    >>> import simnibs
    >>> import nibabel
    >>> simulation_J = simnibs.read_msh('simulation_result_with_J.msh')
    >>> reference_nifti = nibabel.load('reference.nii)
    >>> B = simnibs.simulation.calc_B(simulation_J.field['J'], reference_nifti.shape, reference_nifti.affine)
    '''
    mesh = J.mesh
    # Computational Domain (before zero-padding)
    domain = _comp_domain(mesh, n_voxels, affine)
    # Voxelize J
    J_vol, affine_vol = _voxelize(J, domain, calc_res)
    # Calculate B in the whole domain
    B_vol = _bs_ft(J_vol, calc_res)
    # Interpolate B to the domain of interest
    B = transformations.volumetric_affine((B_vol, affine_vol),
                                          np.eye(4),
                                          affine,
                                          n_voxels,
                                          intorder=1,
                                          keep_vector_length=False)
    if mask:
        msk = mesh_io.ElementData(np.ones(mesh.elm.nr), mesh=mesh)
        msk = msk.interpolate_to_grid(n_voxels, affine, method='assign')
        B *= msk[..., None]

    return B
Example #8
0
 def test_mean_angle(self, sphere_vol):
     t = opt_struct.TDCStarget(indexes=[1, 2],
                               directions=[[1, 0, 0], [0, 1, 0]],
                               mesh=sphere_vol,
                               lf_type='element',
                               radius=0)
     f = mesh_io.ElementData(np.zeros((sphere_vol.elm.nr, 3)))
     f[1] = [1, 1, 0]
     f[2] = [2, 2, 0]
     assert np.isclose(t.mean_angle(f), 45)
Example #9
0
    def test_leadfield(self, input_type, n_workers, field, post_pro, cube_msh):
        if sys.platform == 'win32' and n_workers > 1:
            ''' Same as above, does not work on windows '''
            return
        m = cube_msh
        cond = np.ones(m.elm.nr)
        cond[m.elm.tag1 > 5] = 1e3
        cond = mesh_io.ElementData(cond, mesh=m)
        if input_type == 'tag':
            el = [1100, 1101, 1101]
        elif input_type == 'node':
            el = [
                np.unique(m.elm[m.elm.tag1 == 1100, :3]),
                np.unique(m.elm[m.elm.tag1 == 1101, :3]),
                np.unique(m.elm[m.elm.tag1 == 1101, :3])
            ]
        fn_hdf5 = tempfile.NamedTemporaryFile(delete=False).name
        dataset = 'leadfield'
        if post_pro:

            def post(E):
                return E[:10] * 2
        else:
            post = None

        fem.tdcs_leadfield(m,
                           cond,
                           el,
                           fn_hdf5,
                           dataset,
                           roi=[5],
                           field=field,
                           post_pro=post,
                           n_workers=n_workers,
                           input_type=input_type)

        if not post_pro:
            n_roi = np.sum(m.elm.tag1 == 5)
            with h5py.File(fn_hdf5) as f:
                assert f[dataset].shape == (2, n_roi, 3)
                assert rdm(f[dataset][0, ...],
                           np.tile([0., 100, 0.], (n_roi, 1))) < .2
                assert mag(f[dataset][0, ...],
                           np.tile([0., 100, 0.], (n_roi, 1))) < np.log(1.1)
        if post_pro:
            with h5py.File(fn_hdf5) as f:
                assert f[dataset].shape == (2, 10, 3)
                assert rdm(f[dataset][0, ...], np.tile([0., 200, 0.],
                                                       (10, 1))) < .2
                assert mag(f[dataset][0, ...], np.tile([0., 200, 0.],
                                                       (10, 1))) < np.log(1.1)

        os.remove(fn_hdf5)
Example #10
0
 def test_mean_intensity_none(self, sphere_vol):
     t = opt_struct.TDCStarget(indexes=[1, 2],
                               directions=None,
                               mesh=sphere_vol,
                               lf_type='element',
                               radius=0)
     f = mesh_io.ElementData(np.zeros((sphere_vol.elm.nr, 3)))
     f[1] = [np.sqrt(2), np.sqrt(2), 0]
     f[2] = [np.sqrt(3), np.sqrt(3), np.sqrt(3)]
     vols = sphere_vol.elements_volumes_and_areas()[:]
     m = np.average([2, 3], weights=vols[:2])
     assert np.isclose(t.mean_intensity(f), m)
Example #11
0
 def test_tdcs_neumann_3_el(self, cube_msh):
     m = cube_msh
     cond = np.ones(m.elm.nr)
     cond[m.elm.tag1 > 5] = 1e3
     cond = mesh_io.ElementData(cond)
     el_tags = [1100, 1101, 1101]
     currents = [.5, -1.5, 1.]
     x = fem.tdcs_neumann(m, cond, currents, el_tags)
     sol = (m.nodes.node_coord[:, 1] - 50) / 20
     m.nodedata = [x, mesh_io.NodeData(sol, 'Analytical')]
     #mesh_io.write_msh(m, '~/Tests/fem.msh')
     assert rdm(sol, x.value) < .1
     assert np.abs(mag(x.value, sol)) < np.log(1.1)
Example #12
0
 def test_solve_dirichlet_petsc(self, cube_msh):
     m = cube_msh
     cond = np.ones(m.elm.nr)
     cond[m.elm.tag1 > 5] = 1e3
     cond = mesh_io.ElementData(cond)
     el_tags = [1100, 1101]
     potentials = [1, -1]
     S = fem.FEMSystem.tdcs(m, cond, el_tags, potentials)
     x = S.solve()
     sol = m.nodes.node_coord[:, 1]/50.
     m.nodedata = [mesh_io.NodeData(x, 'FEM'), mesh_io.NodeData(sol, 'Analytical')]
     #mesh_io.write_msh(m, '~/Tests/fem.msh')
     assert rdm(sol, x.T) < .1
     assert np.abs(mag(x, sol)) < np.log(1.1)
Example #13
0
 def test_visualization(self, tensor):
     eig_val, eig_vec = np.linalg.eig(tensor)
     max_eig = eig_val.argmax()
     min_eig = eig_val.argmin()
     t = np.tile(tensor, [10, 1, 1])
     factor = np.arange(1, 11)
     t *= factor[:, None, None]
     t = mesh_io.ElementData(t.reshape(-1, 9))
     fields = cond.TensorVisualization(t, None, all_compoents=True)
     assert np.allclose(fields[0].value / factor[:, None],
                        eig_val[max_eig] * eig_vec[:, max_eig])
     assert np.allclose(fields[2].value / factor[:, None],
                        eig_val[min_eig] * eig_vec[:, min_eig])
     assert np.allclose(fields[3].value / factor,
                        np.prod(eig_val) ** (1.0/3.0))
Example #14
0
 def test_solve_assemble_neumann_petsc(self, cube_msh):
     m = cube_msh
     cond = np.ones(m.elm.nr)
     cond[m.elm.tag1 > 5] = 25
     cond = mesh_io.ElementData(cond)
     el_tags = [1100, 1101]
     currents = [1, -1]
     S = fem.FEMSystem.tdcs_neumann(m, cond, el_tags[0])
     b = S.assemble_tdcs_neumann_rhs(el_tags[1:], currents[1:])
     x = S.solve(b)
     sol = (m.nodes.node_coord[:, 1] - 50) / 10
     m.nodedata = [mesh_io.NodeData(x, 'FEM'), mesh_io.NodeData(sol, 'Analytical')]
     #mesh_io.write_msh(m, '~/Tests/fem.msh')
     assert rdm(sol, x.T) < .1
     assert np.abs(mag(x, sol)) < np.log(1.5)
Example #15
0
def tms_sphere(sphere3_msh):
    m = sphere3_msh.crop_mesh(elm_type=4)
    dipole_pos = np.array([0., 0., 300])
    dipole_moment = np.array([1., 0., 0.])
    didt = 1e6
    r = (m.nodes.node_coord - dipole_pos) * 1e-3
    dAdt = 1e-7 * didt * np.cross(dipole_moment, r) / (np.linalg.norm(r, axis=1)[:, None] ** 3)
    dAdt = mesh_io.NodeData(dAdt, mesh=m)
    dAdt.field_name = 'dAdt'
    dAdt.mesh = m
    pos = m.elements_baricenters().value
    E_analytical = analytical_solutions.tms_E_field(dipole_pos * 1e-3,
                                                    dipole_moment, didt,
                                                    pos * 1e-3)
    cond = mesh_io.ElementData(np.ones(m.elm.nr))
    cond.mesh = m
    return m, cond, dAdt, E_analytical
Example #16
0
 def test_solve_assemble_aniso(self, cube_msh):
     m = cube_msh
     cond = np.tile(np.eye(3), (m.elm.nr, 1, 1))
     cond[m.elm.tag1 > 5] *= 100
     cond[m.elm.tag1 < 5, 0, :] = 0.01
     cond[m.elm.tag1 < 5, 1, :] = 0.1
     cond = mesh_io.ElementData(cond.reshape(-1, 9))
     el_tags = [1100, 1101]
     currents = [1, -1]
     S = fem.FEMSystem.tdcs_neumann(m, cond, el_tags[0])
     b = S.assemble_tdcs_neumann_rhs(el_tags[1:], currents[1:])
     x = S.solve(b)
     sol = (m.nodes.node_coord[:, 1] - 50) / 10
     m.nodedata = [mesh_io.NodeData(x, 'FEM'), mesh_io.NodeData(sol, 'Analytical')]
     #mesh_io.write_msh(m, '~/Tests/fem.msh')
     assert rdm(sol, x.T) < .1
     assert np.abs(mag(x, sol)) < np.log(1.5)
Example #17
0
    def test_calc_tensor(self, sphere3_msh):
        phi = sphere3_msh.nodes.node_coord[:, 0] + \
            2 * sphere3_msh.nodes.node_coord[:, 1] + \
            -3 * sphere3_msh.nodes.node_coord[:, 2]
        potential = mesh_io.NodeData(phi, mesh=sphere3_msh)

        o = np.ones(sphere3_msh.elm.nr)
        z = np.zeros(sphere3_msh.elm.nr)
        cond = np.reshape(np.eye(3) * np.array([1, 2, 3]), -1)
        cond = np.tile(cond, [sphere3_msh.elm.nr, 1])
        cond = mesh_io.ElementData(cond, mesh=sphere3_msh)
        m = fem.calc_fields(potential, 'vJEgsej', cond, units='m')

        assert np.allclose(m.field['v'].value, potential.value)
        assert np.allclose(m.field['g'].value, [1, 2, -3])
        assert np.allclose(m.field['E'].value, [-1, -2, 3])
        assert np.allclose(m.field['J'].value, [-1, -4, 9])
Example #18
0
    def test_calc_gradient(self, cube_msh):
        m = cube_msh
        cond = np.ones(m.elm.nr)
        cond = mesh_io.ElementData(cond)
        S = fem.FEMSystem.tdcs_neumann(m, cond, 1100)

        z = m.nodes.node_coord[:, 0]
        assert np.allclose(S.calc_gradient(z), [1, 0, 0])
        z = m.nodes.node_coord[:, 1]
        assert np.allclose(S.calc_gradient(z), [0, 1, 0])
        z = m.nodes.node_coord[:, 2]
        assert np.allclose(S.calc_gradient(z), [0, 0, 1])

        z = m.nodes.node_coord
        grad = S.calc_gradient(z) * [2, 3, 1]
        assert np.allclose(grad[:, :, 0], [2, 0, 0])
        assert np.allclose(grad[:, :, 1], [0, 3, 0])
        assert np.allclose(grad[:, :, 2], [0, 0, 1])
Example #19
0
 def test_solve_assemble_neumann_nodes(self, cube_msh):
     m = cube_msh
     cond = np.ones(m.elm.nr)
     cond[m.elm.tag1 > 5] = 25
     cond = mesh_io.ElementData(cond)
     currents = [1, -1]
     nodes_top = np.unique(m.elm[m.elm.tag1 == 1100, :3])
     nodes_bottom = np.unique(m.elm[m.elm.tag1 == 1101, :3])
     S = fem.FEMSystem.tdcs_neumann(m, cond, nodes_top, input_type='node')
     b = S.assemble_tdcs_neumann_rhs(nodes_bottom,
                                     currents[1:],
                                     input_type='node')
     x = S.solve(b)
     sol = (m.nodes.node_coord[:, 1] - 50) / 10
     m.nodedata = [
         mesh_io.NodeData(x, 'FEM'),
         mesh_io.NodeData(sol, 'Analytical')
     ]
     #mesh_io.write_msh(m, '~/Tests/fem.msh')
     assert rdm(sol, x.T) < .1
     assert np.abs(mag(x, sol)) < np.log(1.5)