Head gradient coilΒΆ

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")

x = X.ravel()
y = Y.ravel()
z = Z.ravel()

target_points = np.array([x, y, z]).T

# Turn cube into sphere by rejecting points "in the corners"
# and inner points
target_points = (
    target_points[
        (np.linalg.norm(target_points, axis=1) < sidelength / 2)
        * (np.linalg.norm(target_points, axis=1) > sidelength / 2 * 0.8)
    ]
    + center
)

Specify target field and run solver. Here, we specify the target field through the use of spherical harmonics. We want to produce the field corresponding to a specific beta_l,m-component.

lmax = 3
alm = np.zeros((lmax * (lmax + 2),))
blm = np.zeros((lmax * (lmax + 2),))

# Set one specific component to one
blm[3] += 1

sphfield = sphtools.field(target_points, alm, blm, lmax)

target_field = sphfield / np.max(sphfield[:, 0])

target_field[:, 2] = 0

coil.plot_mesh(opacity=0.5)
mlab.quiver3d(*target_points.T, *sphfield.T)
mlab.gcf().scene.isometric_view()

abs_error = np.zeros_like(target_field)
abs_error[:, 0] += 0.05
abs_error[:, 1:3] += 0.1


target_spec = {
    "coupling": coil.B_coupling(target_points),
    "abs_error": abs_error,
    "target": target_field,
}
../../_images/sphx_glr_head_gradient_coil_design_001.png

Out:

Computing magnetic field coupling matrix, 2044 vertices by 312 target points... took 0.24 seconds.
import mosek

coil.s, prob = optimize_streamfunctions(
    coil,
    [target_spec],
    objective="minimum_inductive_energy",
    solver="MOSEK",
    solver_opts={"mosek_params": {mosek.iparam.num_threads: 8}},
)

Out:

Computing the inductance matrix...
Computing self-inductance matrix using rough quadrature (degree=2).              For higher accuracy, set quad_degree to 4 or more.
Estimating 16313 MiB required for 2044 by 2044 vertices...
Computing inductance matrix in 40 chunks (9384 MiB memory free),              when approx_far=True using more chunks is faster...
Computing triangle-coupling matrix
Inductance matrix computation took 7.43 seconds.
Pre-existing problem not passed, creating...
Passing parameters to problem...
Passing problem to solver...


Problem
  Name                   :
  Objective sense        : min
  Type                   : CONIC (conic optimization problem)
  Constraints            : 3819
  Cones                  : 1
  Scalar variables       : 3893
  Matrix variables       : 0
  Integer variables      : 0

Optimizer started.
Problem
  Name                   :
  Objective sense        : min
  Type                   : CONIC (conic optimization problem)
  Constraints            : 3819
  Cones                  : 1
  Scalar variables       : 3893
  Matrix variables       : 0
  Integer variables      : 0

Optimizer  - threads                : 8
Optimizer  - solved problem         : the dual
Optimizer  - Constraints            : 1946
Optimizer  - Cones                  : 1
Optimizer  - Scalar variables       : 3819              conic                  : 1947
Optimizer  - Semi-definite variables: 0                 scalarized             : 0
Factor     - setup time             : 0.28              dense det. time        : 0.00
Factor     - ML order time          : 0.07              GP order time          : 0.00
Factor     - nonzeros before factor : 1.89e+06          after factor           : 1.89e+06
Factor     - dense dim.             : 0                 flops                  : 8.46e+09
ITE PFEAS    DFEAS    GFEAS    PRSTATUS   POBJ              DOBJ              MU       TIME
0   5.6e+02  1.0e+00  2.0e+00  0.00e+00   0.000000000e+00   -1.000000000e+00  1.0e+00  1.40
1   2.4e+02  4.2e-01  1.2e+00  -9.49e-01  6.650619835e+00   6.946913020e+00   4.2e-01  1.63
2   7.7e+01  1.4e-01  6.3e-01  -8.61e-01  6.505864740e+01   6.862857116e+01   1.4e-01  1.82
3   2.3e+01  4.0e-02  2.4e-01  -6.12e-01  2.768754633e+02   2.845399199e+02   4.0e-02  2.02
4   3.1e+00  5.5e-03  2.6e-02  -9.44e-02  6.459947892e+02   6.513630397e+02   5.5e-03  2.22
5   5.7e-01  1.0e-03  2.2e-03  7.38e-01   5.178338127e+02   5.190086016e+02   1.0e-03  2.42
6   2.8e-01  5.0e-04  7.7e-04  9.52e-01   4.445760451e+02   4.451278532e+02   5.0e-04  2.63
7   5.1e-02  9.0e-05  5.1e-05  9.77e-01   3.974604461e+02   3.975340486e+02   9.0e-05  2.88
8   7.3e-03  1.3e-05  2.7e-06  9.95e-01   3.936012105e+02   3.936113968e+02   1.3e-05  3.15
9   1.0e-03  1.8e-06  1.4e-07  9.99e-01   3.928011290e+02   3.928024812e+02   1.8e-06  3.40
10  1.3e-04  2.4e-07  7.1e-09  1.00e+00   3.927465956e+02   3.927467997e+02   2.4e-07  3.60
11  2.6e-05  4.6e-08  5.9e-10  1.00e+00   3.927424767e+02   3.927425160e+02   4.6e-08  3.81
12  3.0e-06  5.3e-09  2.2e-11  1.00e+00   3.927425347e+02   3.927425392e+02   5.3e-09  4.02
13  4.3e-07  7.6e-10  1.2e-12  1.00e+00   3.927425447e+02   3.927425454e+02   7.6e-10  4.23
14  1.7e-07  1.1e-10  2.2e-13  1.00e+00   3.927425461e+02   3.927425438e+02   9.7e-15  4.46
Optimizer terminated. Time: 4.56


Interior-point solution summary
  Problem status  : PRIMAL_AND_DUAL_FEASIBLE
  Solution status : OPTIMAL
  Primal.  obj: 3.9274254609e+02    nrm: 8e+02    Viol.  con: 3e-13    var: 0e+00    cones: 0e+00
  Dual.    obj: 3.9274254381e+02    nrm: 2e+03    Viol.  con: 3e-10    var: 7e-09    cones: 1e-13

Plot coil windings

loops = coil.s.discretize(N_contours=10)
loops.plot_loops()
../../_images/sphx_glr_head_gradient_coil_design_002.png

Out:

<mayavi.core.scene.Scene object at 0x7f0c11d5cbf0>

Total running time of the script: ( 0 minutes 18.982 seconds)

Estimated memory usage: 1063 MB

Gallery generated by Sphinx-Gallery