torc 0.3
Chris Billington, May 13, 2026
torc is a Python library for computing magnetic fields and gradients resulting from
current-carrying objects (loops, straight wires, round coils and racetrack coils of
rectangular cross-section) positioned and oriented arbitrarily in 3D space.
Finite cross-section conductors are approximated by distributing multiple idealised 1D current elements through the cross-section. Loop fields are computed analytically using elliptic integrals; straight wire fields use the Biot–Savart result for a finite wire; arcs and curved segments are approximated as sequences of straight segments.
All quantities are in SI units (metres, amps, tesla). Convenience constants for common unit conversions are included.
View on PyPI | View on GitHub | Read the docs
Installation
To install torc, run:
$ pip install torc
or to install from source, clone the repository and run:
$ pip install .
Example usage
This example shows constructing a coilpair in anti-Helmholtz configuration, and evaluating and plotting fields and gradients along lines and on a grid.
import matplotlib.pyplot as plt
import numpy as np
from torc import RoundCoil, CoilPair, Z, cm, gauss, gauss_per_cm
R_inner = 4 * cm
R_outer = 6 * cm
separation = 10 * cm
height = 1 * cm
# A pair of round coils in anti-Helmholtz configuration:
coils = CoilPair(
coiltype=RoundCoil,
r0=(0, 0, 0), # centred at the origin
n=Z, # normal direction is +Z
separation=separation,
height=height,
inner_radius=R_inner,
outer_radius=R_outer,
num_turns=100,
parity='anti-helmholtz',
)
def plot_2d_field_and_gradient():
# Compute the field and z gradient for current I = 1A in a 2D x-z plane:
# Construct grid - first dimension will be z and second will be x, so that when we
# imshow() the 2D results, the z direction will be the vertical direction:
x = np.linspace(-10 * cm, 10 * cm, 256)[np.newaxis, :]
y = 0
z = np.linspace(-10 * cm, 10 * cm, 256)[:, np.newaxis]
# Compute B field on the grid
B = coils.B((x,y,z), I=1)
# Compute z derivative of B on the grid
dB_dz = coils.dB((x,y,z), s=Z, I=1)
# Mask out areas inside or within 0.25cm of the coils:
d_mask = 0.25 * cm
mask = (
(abs(x) > R_inner - d_mask)
& (abs(x) < R_outer + d_mask)
& (abs(z) > separation / 2 - height / 2 - d_mask)
& (abs(z) < separation / 2 + height / 2 + d_mask)
)
B[:, mask] = 0
dB_dz[:, mask] = 0
# Extract components:
Bx, By, Bz = B
dBz_dz, dBy_dz, dBz_dz = dB_dz
# Bz 2D plot
plt.subplot(221)
plt.imshow(
Bz / gauss,
extent=[x.min() / cm, x.max() / cm, z.min() / cm, z.max() / cm],
origin='lower',
cmap='seismic',
vmin=-abs(Bz / gauss).max(),
vmax=abs(Bz / gauss).max(),
)
plt.grid(True, color='k', linestyle=":", alpha=0.5)
plt.xlabel('$x$ (cm)')
plt.ylabel('$z$ (cm)')
plt.colorbar(label='$B_z$ (G)')
# dBz_dz 2D plot
plt.subplot(222)
plt.imshow(
dBz_dz / gauss_per_cm,
extent=[x.min() / cm, x.max() / cm, z.min() / cm, z.max() / cm],
origin='lower',
cmap='seismic',
vmin=-abs(dBz_dz / gauss_per_cm).max(),
vmax=abs(dBz_dz / gauss_per_cm).max(),
)
plt.grid(True, color='k', linestyle=":", alpha=0.5)
plt.xlabel('$x$ (cm)')
plt.ylabel('$z$ (cm)')
plt.colorbar(label='$dB_z/dz$ (G/cm)')
def plot_1d_field_and_gradient():
z = np.linspace(-10 * cm, 10 * cm, 1024)
# Compute B field on the z axis for current I = 1A
B = coils.B((0, 0, z), I=1)
# Compute z derivative of B on the z axis for current I = 1A
dB_dz = coils.dB((0, 0, z), s=Z, I=1)
# Extract components:
Bx, By, Bz = B
dBz_dz, dBy_dz, dBz_dz = dB_dz
# Plot Bz and dBz_dz:
plt.subplot(223)
plt.plot(z / cm, Bz / gauss)
plt.grid(True, color='k', linestyle=":", alpha=0.5)
plt.xlabel('$z$ (cm)')
plt.ylabel('$B_z$ (G)')
plt.subplot(224)
plt.plot(z / cm, dBz_dz / gauss_per_cm)
plt.grid(True, color='k', linestyle=":", alpha=0.5)
plt.xlabel('$z$ (cm)')
plt.ylabel('$dB_z/dz$ (G/cm)')
# Calculate fields/gradients and show plots:
plt.figure(figsize=(9, 6))
plot_2d_field_and_gradient()
plot_1d_field_and_gradient()
plt.tight_layout()
plt.savefig('anti-helmholtz-plots.png')
plt.show()
# Display a 3D rendering of the coils:
coils.show()
Unit constants
Multiply by these constants to convert to SI units.
- mm = 0.001
Millimetres — multiply by this to convert mm to metres.
- cm = 0.01
Centimetres — multiply by this to convert cm to metres.
- inch = 0.0254
Inches — multiply by this to convert inches to metres.
- gauss = 0.0001
Gauss — multiply by this to convert gauss to tesla.
- gauss_per_cm = 0.01
Gauss per centimetre — multiply by this to convert gauss/cm to tesla/metre.
Colours
RGB colour tuples for use with show().
- COPPER = (0.722, 0.451, 0.2)
RGB colour tuple for copper, for use with
CurrentObject.show().
- SILVER = (0.75, 0.75, 0.75)
RGB colour tuple for silver, for use with
CurrentObject.show().
Unit vectors and coordinates
- X = array([1., 0., 0.])
Unit vector in the x direction.
- Y = array([0., 1., 0.])
Unit vector in the y direction.
- Z = array([0., 0., 1.])
Unit vector in the z direction.
- ORIGIN = array([0., 0., 0.])
Coordinate vector of the origin
Module reference
- class CurrentObject(r0, n, u=None, num_turns=1, name=None)
Base class for a current-carrying object with its own local coordinate frame.
The object is centred at position r0 with a right-handed local coordinate system (u, v, n) defined by the primary axis n and secondary axis u. The third axis v is computed as n × u. The two provided axes do not need to be normalised (they will be normalised automatically), but must be orthogonal.
- Parameters:
r0 (tuple or array-like) – Position
(x, y, z)of the object’s centre (metres).n (tuple or array-like) – Primary axis direction (nx, ny, nz) in lab coordinates. For planar objects (coils, arcs), this is the normal to the plane. Need not be normalised.
u (tuple or array-like, optional) – Secondary axis direction (ux, uy, uz) in lab coordinates, must be orthogonal to n. If
None(the default), an arbitrary orthogonal direction is chosen, suitable for objects with rotational symmetry.num_turns (float) – Overall multiplier for the current used in field calculations. Defaults to 1.
name (str, optional) – An identifying name, used for lookup in a
Container.
- r0
Centre position
(x, y, z)in the lab frame (metres).
- n
Unit vector for the local n axis in lab coordinates.
- u
Unit vector for the local u axis in lab coordinates.
- v
Unit vector for the local v axis in lab coordinates (computed as n × u).
- num_turns
Overall current multiplier used in field calculations.
- property x
The x coordinate of the object’s centre position in the lab frame.
- property y
The y coordinate of the object’s centre position in the lab frame.
- property z
The z coordinate of the object’s centre position in the lab frame.
- B(r, I)
Compute the magnetic field at a position in lab coordinates.
The current is multiplied by
num_turnsbefore being passed to the underlying field calculation.- Parameters:
r (tuple or numpy.ndarray) – Position
(x, y, z)in the lab frame (metres). Components may be arrays for vectorised evaluation.I (float) – Current (amps).
- Returns:
Magnetic field
(Bx, By, Bz)in the lab frame (tesla).- Return type:
- dB(r, I, s, ds=1e-05)
Compute a directional derivative of the magnetic field.
Returns dB/ds, the derivative of the field vector in the direction s, evaluated using a 2nd-order central finite difference.
- Parameters:
r (tuple or numpy.ndarray) – Position
(x, y, z)in the lab frame (metres). Components may be arrays for vectorised evaluation.I (float) – Current (amps).
s (str or array-like) – Direction of differentiation. Either
'x','y','z', or an arbitrary vector whose direction will be used (magnitude is ignored).ds (float) – Step size for numerical differentiation (metres). Defaults to 10 um.
- Returns:
Field derivative
(dBx/ds, dBy/ds, dBz/ds)(tesla per metre).- Return type:
- surfaces()
Return a list of 3D surface meshes in lab coordinates for visualisation. Each element is an array of shape
(3, m, n)suitable for mesh rendering. Local-frame arrays have components(u, v, n).
- lines()
Return a list of 3D line paths in lab coordinates for visualisation. Each element is an array of shape
(3, n). Local-frame arrays have components(u, v, n).
- show(surfaces=True, lines=False, line_width=5, color=(0.722, 0.451, 0.2), blocking=True)
Open an interactive 3D pyqtgraph/OpenGL window displaying this object’s geometry.
- Parameters:
surfaces (bool) – Whether to render solid surfaces. Defaults to
True.lines (bool) – Whether to render current lines. Defaults to
False.color (tuple) – RGB colour as a 3-tuple of floats in
[0, 1]. Defaults toCOPPER.blocking (bool) – Whether to enter the Qt event loop, blocking until the window is closed. Defaults to
True. To block later, e.g. after adding additional items to the view or creating multiple views, callapp=pg.mkQApp(); app.exec().
- Returns:
The view widget.
- Return type:
pyqtgraph.opengl.GLViewWidget
- class Container(*children, r0=(0, 0, 0), n=array([0., 0., 1.]), u=None, num_turns=1, name=None)
A group of
CurrentObjectinstances whose fields are summed.Children can be passed at construction or added later with
add(). Individual children can be accessed by integer index, slice, or by name string.See
CurrentObjectfor inherited attributes and methods.- add(*children)
Add one or more
CurrentObjectinstances as children.
- index(item)
Return the index of a child object.
- B(r, I)
Compute the total magnetic field at a position by summing all children.
- Parameters:
r (tuple or numpy.ndarray) – Position
(x, y, z)in the lab frame (metres).I (float) – Current (amps).
- Returns:
Total magnetic field
(Bx, By, Bz)(tesla).- Return type:
- surfaces()
Return surface meshes from this object and all children, in lab coordinates.
- lines()
Return line paths from this object and all children, in lab coordinates.
- class Loop(r0, n, radius, num_turns=1, name=None)
A circular current loop.
Current flows counterclockwise when viewed from the direction the normal vector n points.
- Parameters:
r0 (tuple or array-like) – Centre position
(x, y, z)(metres).n (tuple or array-like) – Normal vector direction. Need not be normalised.
radius (float) – Radius of the loop (metres).
num_turns (float) – Overall current multiplier. Defaults to 1.
name (str, optional) – Identifying name for
Containerlookup.
See
CurrentObjectfor inherited attributes and methods.
- class Line(r_start, r_end, num_turns=1, name=None)
A straight current-carrying wire segment.
Current flows from r_start to r_end. The object’s centre (
r0) is the midpoint of the wire. The local n axis points along the wire direction.
- Parameters:
See
CurrentObjectfor inherited attributes and methods.
- class Arc(r0, n, u, radius, swept_angle, num_turns=1, num_segs=12, name=None)
A current arc forming part of a circular loop.
The arc is centred at r0 with normal vector n. The u direction defines the start of the arc, and swept_angle is the angle swept out from u. Current flows in the direction of increasing angle, which if swept_angle > 0, is in the positive (counterclockwise) sense with respect to n. The arc is approximated as
num_segsstraightLinesegments.
- Parameters:
r0 (tuple or array-like) – Centre position
(x, y, z)(metres).n (tuple or array-like) – Normal vector direction. Need not be normalised.
u (tuple or array-like) – Direction perpendicular to n defining the start of the arc.
radius (float) – Radius of the arc (metres).
swept_angle (float) – Angle swept out from the u direction (radians).
num_turns (float) – Overall current multiplier. Defaults to 1.
num_segs (int) – Number of straight line segments used to approximate the arc. Defaults to 12.
name (str, optional) – Identifying name for
Containerlookup.
See
CurrentObjectfor inherited attributes and methods.
- class RoundCoil(r0, n, height, inner_radius, outer_radius, num_turns=1, num_segs=12, name=None)
A round coil with rectangular cross-section.
The coil is centred at r0 with normal vector n. Its finite cross-section is approximated by distributing
num_segsidealisedLoopelements evenly through the rectangular cross-section.
- Parameters:
r0 (tuple or array-like) – Centre position
(x, y, z)(metres).n (tuple or array-like) – Normal vector direction. Need not be normalised.
height (float) – Height of the cross-section in the n direction (metres).
inner_radius (float) – Inner radius (metres).
outer_radius (float) – Outer radius (metres).
num_turns (float) – Overall current multiplier. Defaults to 1.
num_segs (int) – Number of
Loopelements used to approximate the finite cross-section. Defaults to 12.name (str, optional) – Identifying name for
Containerlookup.
See
CurrentObjectfor inherited attributes and methods.
- class StraightSegment(r0, n, u, length, width, height, num_turns=1, num_segs=12, name=None)
A straight conductor segment with rectangular cross-section.
The segment is centred at r0 with current flowing along the u direction. The cross-section lies in the v-n plane:
widthis measured along v,heightalong n — consistent with the meaning of these dimensions in other classes.lengthis the extent along u. The finite cross-section is approximated by distributingnum_segsidealisedLineelements evenly through the rectangular cross-section.
- Parameters:
r0 (tuple or array-like) – Centre position
(x, y, z)(metres).n (tuple or array-like) – Normal direction, defining the height direction of the cross-section. Must be perpendicular to u.
u (tuple or array-like) – Current direction, defining the length direction of the segment.
length (float) – Extent of the segment along u (metres).
width (float) – Extent of the cross-section along v (metres).
height (float) – Extent of the cross-section along n (metres).
num_turns (float) – Overall current multiplier. Defaults to 1.
num_segs (int) – Number of
Lineelements used to approximate the finite cross-section. Defaults to 12.name (str, optional) – Identifying name for
Containerlookup.
See
CurrentObjectfor inherited attributes and methods.
- class CurvedSegment(r0, n, u, height, inner_radius, outer_radius, swept_angle, num_turns=1, num_segs=12, num_arc_segs=12, name=None)
A curved conductor segment with rectangular cross-section.
Forms part of a round coil centred at r0 with normal vector n. The u direction defines the start of the arc, and swept_angle is the angle swept out from u. Current flows in the direction of increasing angle, which if swept_angle > 0, is in the positive (counterclockwise) sense with respect to n. The finite cross-section is approximated by distributing
num_segs` idealised :class:`Arc` elements evenly through the rectangular cross-section, each itself approximated as ``num_arc_segsstraight lines.
- Parameters:
r0 (tuple or array-like) – Centre position
(x, y, z)(metres).n (tuple or array-like) – Normal vector direction. Need not be normalised.
u (tuple or array-like) – Direction perpendicular to n defining the start of the arc.
height (float) – Height of the cross-section in the n direction (metres).
inner_radius (float) – Inner radius (metres).
outer_radius (float) – Outer radius (metres).
swept_angle (float) – Angle swept out from the u direction (radians).
num_turns (float) – Overall current multiplier. Defaults to 1.
num_segs (int) – Number of
Arcelements used to approximate the finite cross-section. Defaults to 12.num_arc_segs (int) – Number of straight line segments per arc. Defaults to 12.
name (str, optional) – Identifying name for
Containerlookup.
See
CurrentObjectfor inherited attributes and methods.
- class RacetrackCoil(r0, n, u, inner_length, inner_width, height, inner_radius, outer_radius, num_turns=1, num_segs=12, num_arc_segs=12, name=None)
A racetrack (rounded-rectangle) coil with rectangular cross-section.
Comprises four straight
StraightSegmentsections and four 90-degreeCurvedSegmentcorners. The coil is centred at r0 with normal vector n. u defines the direction along whichinner_lengthis measured (inner-surface to inner-surface);inner_widthis measured along v.inner_lengthis conventionally the longest direction. The finite cross-section is approximated by distributingnum_segsidealised current elements evenly through the rectangular cross-section, and each curved element is further approximated asnum_arc_segsstraight lines.
- Parameters:
r0 (tuple or array-like) – Centre position
(x, y, z)(metres).n (tuple or array-like) – Normal vector direction. Need not be normalised.
u (tuple or array-like) – Direction perpendicular to n defining the inner_length direction.
inner_length (float) – Inner-surface to inner-surface distance along u (metres). Conventionally the longest direction.
inner_width (float) – Inner-surface to inner-surface distance along v (metres).
height (float) – Height of the cross-section in the n direction (metres).
inner_radius (float) – Inner radius of curvature of the corners (metres).
outer_radius (float) – Outer radius of curvature of the corners (metres).
num_turns (float) – Overall current multiplier. Defaults to 1.
num_segs (int) – Number of current elements used to approximate the finite cross-section. Defaults to 12.
num_arc_segs (int) – Number of straight line segments per 90-degree corner. Defaults to 12.
name (str, optional) – Identifying name for
Containerlookup.
See
CurrentObjectfor inherited attributes and methods.
- class CoilPair(coiltype, r0, n, separation, *args, **kwargs)
A symmetric pair of identical coils.
Creates two coils of the given type, placed symmetrically about r0 along the normal direction n. One coil is at
r0 + separation/2 * nand the other atr0 - separation/2 * n. In Helmholtz configuration both coils have the same normal; in anti-Helmholtz configuration the normals are opposite, producing a field gradient at the centre.
- Parameters:
coiltype (type) – The coil class to instantiate (any class accepting r0 and n as its first two positional arguments, e.g.
RoundCoilorRacetrackCoil).r0 (tuple or array-like) – Midpoint position
(x, y, z)between the two coils (metres).n (tuple or array-like) – Normal vector direction. Need not be normalised.
separation (float) – Total distance between the two coils along n (metres).
*args – Additional positional arguments passed to coiltype.
**kwargs –
Additional keyword arguments passed to coiltype. Two keyword arguments are intercepted and not forwarded:
parity (int or str) —
1,'Helmholtz'(default, case-insensitive) for same-direction normals, or-1,'anti-Helmholtz'(case-insensitive) for opposite normals.name (str, optional) — Identifying name for
Containerlookup.
See
CurrentObjectfor inherited attributes and methods.