Exemple #1
0
                            planemesh.faces,
                            process=False)

coil_minus = trimesh.Trimesh(planemesh.vertices + center_offset - standoff,
                             planemesh.faces,
                             process=False)

joined_planes = combine_meshes((coil_plus, coil_minus))

joined_planes = joined_planes.subdivide()

# Create mesh class object
coil = MeshConductor(
    verts=joined_planes.vertices,
    tris=joined_planes.faces,
    fix_normals=True,
    basis_name="suh",
    N_suh=100,
)

#%%
# Set up target and stray field points

# Here, the target points are on a volumetric grid within a sphere

center = np.array([0, 0, 0]) * scaling_factor

sidelength = 2 * scaling_factor
n = 8
xx = np.linspace(-sidelength / 2, sidelength / 2, n)
yy = np.linspace(-sidelength / 2, sidelength / 2, n)
Exemple #2
0
standoff = np.array([0, 4, 0])

# Create coil plane pairs
coil_plus = trimesh.Trimesh(planemesh.vertices + center_offset + standoff,
                            planemesh.faces,
                            process=False)

coil_minus = trimesh.Trimesh(planemesh.vertices + center_offset - standoff,
                             planemesh.faces,
                             process=False)

mesh1 = combine_meshes((coil_plus, coil_minus))
mesh2 = mesh1.copy()
mesh2.apply_scale(1.4)

coil = MeshConductor(mesh_obj=mesh1, basis_name="inner", N_sph=4)
shieldcoil = MeshConductor(mesh_obj=mesh2, basis_name="inner", N_sph=4)

#%%
# Plot geometry
f = mlab.figure(None,
                bgcolor=(1, 1, 1),
                fgcolor=(0.5, 0.5, 0.5),
                size=(800, 800))
coil.plot_mesh(opacity=0.2, figure=f)
shieldcoil.plot_mesh(opacity=0.2, figure=f)

#%%
# Compute inductances and coupling

M11 = coil.inductance
==================================

First 15 surface harmonics of a triangle mesh. The index (and spatial frequency) increases from left to right, row by row. The hole and outer boundary have zero tangential derivative. The mesh discretization is shown in the magnified inset to the right.

"""
from bfieldtools.mesh_conductor import MeshConductor

import numpy as np

SAVE = False
SAVE_DIR = "./Surface harmonics/"

c = MeshConductor(
    mesh_file=SAVE_DIR + "arbitrary_surface.stl",
    process=True,
    basis_name="suh",
    N_suh=15,
    fix_normals=True,
)

T_x = 1.5 * np.pi / 2
T_z = -1.02 * np.pi
rotmat = np.array([
    [np.cos(T_z), -np.sin(T_z), 0, 0],
    [np.sin(T_z), np.cos(T_z), 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
]) @ np.array([
    [1, 0, 0, 0],
    [0, np.cos(T_x), -np.sin(T_x), 0],
    [0, np.sin(T_x), np.cos(T_x), 0],
else:

    with np.load(SAVE_DIR + "mne_data.npz", allow_pickle=True) as data:
        mesh = data["mesh"]
        p = data["p"]
        n = data["n"]
        mesh = trimesh.Trimesh(vertices=data["vertices"], faces=data["faces"])

    evoked = mne.Evoked(SAVE_DIR + "left_auditory-ave.fif")


#%%
# Fit the surface current for the auditory evoked response


c = MeshConductor(mesh_obj=mesh, basis_name="suh", N_suh=150)
M = c.mass

sensor_coupling = np.einsum("ijk,ij->ik", c.B_coupling(p), n)
# a = np.linalg.pinv(sensor_coupling, rcond=1e-15) @ field
ss = np.linalg.svd(sensor_coupling @ sensor_coupling.T, False, False)

# reg_exps = [0.5, 1, 2, 3, 4, 5, 6, 7, 8]
reg_exps = [1]
rel_errors = []

for reg_exp in reg_exps:
    _lambda = np.max(ss) * (10 ** (-reg_exp))
    # Laplacian in the suh basis is diagonal
    BB = sensor_coupling.T @ sensor_coupling + _lambda * (-c.laplacian) / np.max(
        abs(c.laplacian)
standoff = np.array([0, 4, 0]) * scaling_factor

# Create coil plane pairs
coil_plus = trimesh.Trimesh(planemesh.vertices + center_offset + standoff,
                            planemesh.faces,
                            process=False)

coil_minus = trimesh.Trimesh(planemesh.vertices + center_offset - standoff,
                             planemesh.faces,
                             process=False)

mesh1 = combine_meshes((coil_minus, coil_plus))
mesh2 = mesh1.copy()
mesh2.apply_scale(1.4)

coil1 = MeshConductor(mesh_obj=mesh1, basis_name="inner", N_sph=4)
coil2 = MeshConductor(mesh_obj=mesh2, basis_name="inner", N_sph=4)

M11 = coil1.inductance
M22 = coil2.inductance
M21 = coil2.mutual_inductance(coil1)
# Mapping from I1 to I2, constraining flux through mesh2 to zero
P = -np.linalg.solve(M22, M21)

A1, Beta1 = coil1.sph_couplings
A2, Beta2 = coil2.sph_couplings

# Use lines below to get coulings with different normalization
# from bfieldtools.sphtools import compute_sphcoeffs_mesh
# A1, Beta1 = compute_sphcoeffs_mesh(mesh1, 5, normalization='energy', R=1)
# A2, Beta2 = compute_sphcoeffs_mesh(mesh2, 5, normalization='energy', R=1)
Exemple #6
0
# To spice things up, let's distort the planes a bit
joined_planes.vertices = (
    joined_planes.vertices -
    0.5 * np.linalg.norm(joined_planes.vertices, axis=1)[:, None] * np.sign(
        joined_planes.vertices[:, 1])[:, None] * joined_planes.vertex_normals)

joined_planes.vertices = (
    joined_planes.vertices -
    0.5 * np.linalg.norm(joined_planes.vertices, axis=1)[:, None] * np.sign(
        joined_planes.vertices[:, 1])[:, None] * joined_planes.vertex_normals)

# Create mesh class object
coil = MeshConductor(
    mesh_obj=joined_planes,
    fix_normals=True,
    basis_name="suh",
    N_suh=100,
    sph_radius=0.2,
    sph_normalization="energy",
)

#%%
# Set up target spherical harmonics components

target_alms = np.zeros((coil.opts["N_sph"] * (coil.opts["N_sph"] + 2), ))
target_blms = np.zeros((coil.opts["N_sph"] * (coil.opts["N_sph"] + 2), ))

target_blms[4] += 1

#%%
# Create bfield specifications used when optimizing the coil geometry
Exemple #7
0
==================

Example showing a gradient coil designed on the surface of a MEG system helmet
"""

import numpy as np
from mayavi import mlab

from bfieldtools.mesh_conductor import MeshConductor
from bfieldtools.coil_optimize import optimize_streamfunctions
from bfieldtools.utils import load_example_mesh
from bfieldtools import sphtools

# Load simple plane mesh that is centered on the origin
helmetmesh = load_example_mesh("meg_helmet")
coil = MeshConductor(mesh_obj=helmetmesh, fix_normals=True)

#%%
# Set up target and stray field points.
# Here, the target points are on a volumetric grid within a sphere

offset = np.array([0, 0, 0.04])
center = offset

sidelength = 0.05
n = 12
xx = np.linspace(-sidelength / 2, sidelength / 2, n)
yy = np.linspace(-sidelength / 2, sidelength / 2, n)
zz = np.linspace(-sidelength / 2, sidelength / 2, n)
X, Y, Z = np.meshgrid(xx, yy, zz, indexing="ij")
Exemple #8
0
    mesh1 = filter_laplacian(mesh1)
    mesh2 = filter_laplacian(mesh2, 0.9)
elif domain == "combined":
    from trimesh.creation import icosphere

    mesh1 = icosphere(4, 0.65)
    mesh2 = load_example_mesh("cube_fillet")
    mesh2.vertices -= mesh2.vertices.mean(axis=0)
    mesh2.vertices *= 0.15
#    mesh2 = mesh2.subdivide()

coil1 = MeshConductor(
    mesh_obj=mesh1,
    N_sph=3,
    inductance_nchunks=100,
    fix_normals=False,
    inductance_quad_degree=2,
)
coil2 = MeshConductor(
    mesh_obj=mesh2,
    N_sph=3,
    inductance_nchunks=100,
    fix_normals=False,
    inductance_quad_degree=2,
)

M11 = coil1.inductance
M22 = coil2.inductance
# Add rank-one matrix, so that M22 can be inverted
M22 += np.ones_like(M22) / M22.shape[0] * np.mean(np.diag(M22))
Exemple #9
0
coilmesh.apply_transform(rotation_matrix)

coilmesh1 = coilmesh.copy()
# coilmesh1.apply_scale(1.3)

coilmesh2 = coilmesh.copy()

# coilmesh1 = coilmesh.union(coilmesh1)
# coilmesh1 = coilmesh1.subdivide().subdivide()
# coilmesh2 = coilmesh.subdivide()

# Create mesh class object
coil = MeshConductor(
    verts=coilmesh1.vertices * 0.75,
    tris=coilmesh1.faces,
    fix_normals=True,
    basis_name="suh",
    N_suh=400,
)


def alu_sigma(T):
    ref_T = 293  # K
    ref_rho = 2.82e-8  # ohm*meter
    alpha = 0.0039  # 1/K

    rho = alpha * (T - ref_T) * ref_rho + ref_rho

    return 1 / rho

Exemple #10
0
#%%
##%% Fit the surface current for the auditory evoked response using pinv
# c = MeshConductor(mesh_obj=mesh, basis_name="suh", N_suh=35)
# M = c.mass
# B_sensors = np.einsum("ijk,ij->ik", c.B_coupling(p), n)
#
#
# asuh = np.linalg.pinv(B_sensors, rcond=1e-15) @ field
#
# s = StreamFunction(asuh, c)
# b_filt = B_sensors @ s

#%% Suh fit

c = MeshConductor(mesh_obj=mesh, basis_name="suh", N_suh=150)
M = c.mass

B_sensors = np.einsum("ijk,ij->ik", c.B_coupling(p), n)
ss = np.linalg.svd(B_sensors @ B_sensors.T, False, False)

reg_exp = 1
plot_this = True
rel_errors = []
_lambda = np.max(ss) * (10**(-reg_exp))
# Laplacian in the suh basis is diagonal
BB = B_sensors.T @ B_sensors + _lambda * (-c.laplacian) / np.max(
    abs(c.laplacian))
a = np.linalg.solve(BB, B_sensors.T @ field)

s = StreamFunction(a, c)
standoff = np.array([0, 3, 0])

# Create coil plane pairs
coil_plus = trimesh.Trimesh(
    planemesh.vertices + center_offset + standoff, planemesh.faces, process=False
)

coil_minus = trimesh.Trimesh(
    planemesh.vertices + center_offset - standoff, planemesh.faces, process=False
)

joined_planes = combine_meshes((coil_plus, coil_minus))

# Create mesh class object
coil = MeshConductor(
    mesh_obj=joined_planes, fix_normals=True, basis_name="suh", N_suh=100
)

#%%
# Set up target and stray field points

# Here, the target points are on a volumetric grid within a sphere

center = np.array([0, 0, 0])

sidelength = 1.5
n = 8
xx = np.linspace(-sidelength / 2, sidelength / 2, n)
yy = np.linspace(-sidelength / 2, sidelength / 2, n)
zz = np.linspace(-sidelength / 2, sidelength / 2, n)
X, Y, Z = np.meshgrid(xx, yy, zz, indexing="ij")
Exemple #12
0
from bfieldtools.mesh_calculus import gradient
from bfieldtools.mesh_magnetics import (
    magnetic_field_coupling,
    magnetic_field_coupling_analytic,
)
from bfieldtools.mesh_conductor import MeshConductor
import pkg_resources


# Load simple plane mesh that is centered on the origin
file_obj = pkg_resources.resource_filename(
    "bfieldtools", "example_meshes/10x10_plane.obj"
)
coilmesh = trimesh.load(file_obj, process=False)
coil = MeshConductor(mesh_obj=coilmesh)
weights = np.zeros(coilmesh.vertices.shape[0])
weights[coil.inner_vertices] = 1

test_points = coilmesh.vertices + np.array([0, 1, 0])

B0 = magnetic_field_coupling(coilmesh, test_points) @ weights
B1 = magnetic_field_coupling_analytic(coilmesh, test_points) @ weights


f = mlab.figure(None, bgcolor=(1, 1, 1), fgcolor=(0.5, 0.5, 0.5), size=(800, 800))

s = mlab.triangular_mesh(
    *coilmesh.vertices.T, coilmesh.faces, scalars=weights, colormap="viridis"
)
s.enable_contours = True
standoff = np.array([0, 4, 0]) * scaling_factor

# Create coil plane pairs
coil_plus = trimesh.Trimesh(planemesh.vertices + center_offset + standoff,
                            planemesh.faces,
                            process=False)

coil_minus = trimesh.Trimesh(planemesh.vertices + center_offset - standoff,
                             planemesh.faces,
                             process=False)

joined_planes = combine_meshes((coil_plus, coil_minus))

# Create mesh class object
coil = MeshConductor(mesh_obj=joined_planes,
                     fix_normals=True,
                     basis_name="inner")

# Separate object for shield geometry
shieldmesh = trimesh.load(
    file_obj=pkg_resources.resource_filename(
        "bfieldtools", "example_meshes/closed_cylinder_remeshed.stl"),
    process=True,
)
shieldmesh.apply_scale(15)

shield = MeshConductor(mesh_obj=shieldmesh,
                       process=True,
                       fix_normals=True,
                       basis_name="vertex")
Exemple #14
0
center_offset = np.array([0, 0, 0])
standoff = np.array([0, 20, 0])

# Create coil plane pairs
coil_plus = trimesh.Trimesh(
    planemesh.vertices + center_offset + standoff, planemesh.faces, process=False
)

coil_minus = trimesh.Trimesh(
    planemesh.vertices + center_offset - standoff, planemesh.faces, process=False
)

joined_planes = combine_meshes((coil_plus, coil_minus))

# Create MeshConductor object, which finds the holes and sets the boundary condition
coil = MeshConductor(mesh_obj=joined_planes, fix_normals=True)

#%%
# Set up target and stray field points

# Here, the target points are on a volumetric grid within a sphere

center = np.array([0, 0, 0])

sidelength = 10
n = 8
xx = np.linspace(-sidelength / 2, sidelength / 2, n)
yy = np.linspace(-sidelength / 2, sidelength / 2, n)
zz = np.linspace(-sidelength / 2, sidelength / 2, n)
X, Y, Z = np.meshgrid(xx, yy, zz, indexing="ij")
Exemple #15
0
    
An example stream function (red--blue colormap) and its rotated gradient, i.e. the surface current density (arrows; green colormap) on a surface mesh with a hole in it. The surface normal is oriented up towards the reader.
"""

from bfieldtools.mesh_conductor import MeshConductor, StreamFunction
import pkg_resources
from bfieldtools.mesh_calculus import gradient
import numpy as np

SAVE = True
SAVE_DIR = "./Streamfunction gradient/"

c = MeshConductor(
    mesh_file=pkg_resources.resource_filename(
        "bfieldtools", "example_meshes/curved_surf_w_hole.stl"),
    process=True,
    basis_name="suh",
    N_suh=10,
    fix_normals=True,
)

T_x = 1.5 * np.pi / 2
T_z = -1.02 * np.pi
rotmat = np.array([
    [np.cos(T_z), -np.sin(T_z), 0, 0],
    [np.sin(T_z), np.cos(T_z), 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
]) @ np.array([
    [1, 0, 0, 0],
    [0, np.cos(T_x), -np.sin(T_x), 0],
    [0, np.sin(T_x), np.cos(T_x), 0],
standoff = np.array([0, 3, 0])

# Create coil plane pairs
coil_plus = trimesh.Trimesh(planemesh.vertices + center_offset + standoff,
                            planemesh.faces,
                            process=False)

coil_minus = trimesh.Trimesh(planemesh.vertices + center_offset - standoff,
                             planemesh.faces,
                             process=False)

joined_planes = combine_meshes((coil_plus, coil_minus))

# Create mesh class object
coil = MeshConductor(mesh_obj=joined_planes,
                     fix_normals=True,
                     basis_name="suh",
                     N_suh=100)

#%%
# Set up target and stray field points

# Here, the target points are on a volumetric grid within a sphere

center = np.array([0, 0, 0])

sidelength = 1.5
n = 8
xx = np.linspace(-sidelength / 2, sidelength / 2, n)
yy = np.linspace(-sidelength / 2, sidelength / 2, n)
zz = np.linspace(-sidelength / 2, sidelength / 2, n)
X, Y, Z = np.meshgrid(xx, yy, zz, indexing="ij")
standoff = np.array([0, 4, 0]) * scaling_factor

# Create coil plane pairs
coil_plus = trimesh.Trimesh(planemesh.vertices + center_offset + standoff,
                            planemesh.faces,
                            process=False)

coil_minus = trimesh.Trimesh(planemesh.vertices + center_offset - standoff,
                             planemesh.faces,
                             process=False)

joined_planes = combine_meshes((coil_plus, coil_minus))
planemesh = joined_planes

# Create mesh class object
coil = MeshConductor(mesh_obj=joined_planes, fix_normals=True)

# Separate object for shield geometry
shieldmesh = load_example_mesh("closed_cylinder_remeshed")
shieldmesh.apply_scale(15)

shield = MeshConductor(mesh_obj=shieldmesh, process=True, fix_normals=True)

#%%
N = 80
points = np.zeros((N * N, 3))
w = 12
X, Y = np.meshgrid(np.linspace(-w, w, N), np.linspace(-w, w, N), indexing="ij")
X += planemesh.vertices.mean(axis=0)[0]
Y += planemesh.vertices.mean(axis=0)[1]
points[:, 0] = X.flatten()