Skip to main content

anafibre logo


License: MIT PyPI Python arXiv ORCID

Anafibre is an analytical mode solver for cylindrical step-index optical fibres. It computes guided modes by solving dispersion relations and evaluating corresponding electromagnetic fields analytically.

Features

  • 🔬 Analytical solutions for guided modes in cylindrical fibres
  • 🌈 Mode visualisation with plotting utilities for field components
  • 📊 Dispersion analysis helpers and effective index calculations
  • ⚡ Fast computation of propagation constants with SciPy-based root finding
  • 🎯 Flexible materials support via fixed indices, callables or refractiveindex.info database
  • 📐 Optional unit support through Astropy

Installation

Install from PyPI

pip install anafibre

Optional extras

  • Interactive notebook display support (IPython/Jupyter)

    pip install "anafibre[ipython]"
    
  • Plotting and animations with Matplotlib

    pip install "anafibre[plot]"
    
  • Units support using astropy.units.Quantity

    pip install "anafibre[units]"
    
  • refractiveindex.info database support via the refractiveindex package

    pip install "anafibre[refractiveindex]"
    
  • All optional features (ipython + plot + units + refractiveindex)

    pip install "anafibre[all]"
    

Special thanks to Ivan Toftul, author of the refractiveindex package, which powers Anafibre’s refractiveindex.info integration.

Core API Overview

Anafibre has two main objects:

  • StepIndexFibre — defines the waveguide (geometry + materials)
  • GuidedMode — represents a single solved eigenmode

The typical workflow is:

# Set up the fibre
fibre = fib.StepIndexFibre(core_radius=250e-9, n_core=2.00, n_clad=1.33)
# Set up the fundamental mode (here with x polarisation)
HE11 = fibre.HE(ell=1, n=1, wl=700e-9, a_plus=1/np.sqrt(2), a_minus=1/np.sqrt(2))
# Construct the grid
x = np.linspace(-2*fibre.core_radius, 2*fibre.core_radius, 100)
y = np.linspace(-2*fibre.core_radius, 2*fibre.core_radius, 100)
X, Y = np.meshgrid(x, y)
# Evaluate the field on the grid 
E = mode.E(x=X, y=Y)

StepIndexFibre

Defines the fibre geometry and material parameters and provides dispersion utilities.

Required inputs

  • core_radius (float in meters or astropy.units.Quantity)
  • One of:
    • core, clad as RefractiveIndexMaterial
    • n_core, n_clad (float or callable λ→ε(λ))
    • eps_core, eps_clad (float or callable λ→ε(λ))

Optional inputs

  • mu_core, mu_clad (float or callable λ→ε(λ))

Example

fibre = fib.StepIndexFibre(core_radius=250e-9, n_core=2.00, n_clad=1.33)

# Or with astropy.units imported as u and with refractiveindex installed:
fibre = fib.StepIndexFibre(
  core_radius = 250*u.nm,
  core = fib.RefractiveIndexMaterial('main','Si3N4','Luke'),
  clad = fib.RefractiveIndexMaterial('main','H2O','Hale'))

Provides

  • Mode constructors for HEℓn , EHℓn , TE0n , and TM0n modes

    fibre.HE(ell, n, wl, a_plus=..., a_minus=...)
    fibre.EH(...)
    fibre.TE(n, wl, a=...)
    fibre.TM(...)
    

    Each returns a GuidedMode object.

  • Dispersion utilities to find V, b, kz , and neff and the dispersion function F for given parameters

    fibre.V(wavelength)
    fibre.b(ell, m, V=..., wavelength=..., mode_type=...)
    fibre.kz(...)
    fibre.neff(...)
    fibre.F(ell, b, V=..., wavelength=..., mode_type=...)
    
  • Geometry and material properties as attributes

    fibre.core_radius
    fibre.n_core(wavelength)
    fibre.n_clad(...)
    fibre.eps_core(...)
    fibre.eps_clad(...)
    fibre.mu_core(...)
    fibre.mu_clad(...)
    
  • Maximum mode order supported for a given wavelength

    fibre.ell_max(wavelength, m=1, mode_type=...)
    fibre.m_max(ell, wavelength, mode_type=...)
    

GuidedMode

Represents a guided mode with methods to calculate fields and properties. It is created using StepIndexFibre mode constructors.

Provides

  • Field evaluation in (ρ,ϕ,z) or (x,y,z) coordinates, when z is not provided z=0 is assumed

    E = mode.E(rho=Rho, phi=Phi, z=Z)
    H = mode.H(rho=Rho, phi=Phi, z=Z)
    E = mode.E(x=X, y=Y, z=Z)
    H = mode.H(x=X, y=Y, z=Z)
    

Both return arrays with a shape (..., 3) corresponding to the Cartesian vector components. Note that if a grid is passed to the function then it is cached, so subsequent calls with the same grid (for example to get magnetic field) will be much faster.

  • Jacobians (gradients) of the fields

    J_E = mode.gradE(rho=Rho, phi=Phi, z=Z)
    J_H = mode.gradH(rho=Rho, phi=Phi, z=Z)
    J_E = mode.gradE(x=X, y=Y, z=Z)
    J_H = mode.gradH(x=X, y=Y, z=Z)
    

Both return arrays with a shape of (..., 3, 3), corresponding to the Cartesian tensor components.

  • Power evaluated via numerical integration

    P = mode.Power()
    

Visualisation

The package ships with a built-in plotting utility that creates time-resolved animations of the electromagnetic field in the transverse cross-section of the fibre. There are two options for using it:

  • Option A − Passing the mode(s) with weights to the animate_fields_xy function directly:

    anim = fib.animate_fields_xy(
          modes=None,            # GuidedMode or list[GuidedMode]
          weights=None,          # complex or list[complex] (amplitudes/relative phases), default 1
          n_radii=2.0,           # grid half-size in units of core radius (when building grid)
          Np=200,                # grid resolution per axis
          ...)
    
  • Option B − Passing fields with their own ω:

    anim = fib.animate_fields_xy(
          fields=None,           # list of tuples (E, H, omega) with E/H phasors on same X,Y grid
          X=None, Y=None,        # grid for Option B (required if fields given)
          z=0.0,                 # z-slice to evaluate modes at (ignored if fields given)
          ...)
    

Whichever way you choose, the resulting anim object is a standard Matplotlib animation and can be displayed in Jupyter notebooks or saved to file. One can also specify which field components to show (E, H, or both) and figure size instead of ... in the above snippets.

anim = fib.animate_fields_xy(
      ...,
      show=("E", "H"),       # any subset of {"E","H"}
      n_frames=60,           # number of frames in the animation 
      interval=50,           # delay between frames in ms 
      figsize=(8, 4.5))      # figure size in inches (width, height)

Finally, the animation can be displayed in a Jupyter notebook using the display_anim helper function:

fib.display_anim(anim)

or saved to file using the standard Matplotlib API:

# Save as mp4 (requires ffmpeg)
anim.save("mode_animation.mp4", writer="ffmpeg", fps=30)

# Or as a gif
anim.save("mode_animation.gif", writer="pillow", fps=15)

Citation

If Anafibre contributes to work that you publish, please cite the associated paper:

@misc{golat2026anafibre,
  title         = {A robust and efficient method to calculate electromagnetic modes on a cylindrical step-index nanofibre}, 
  author        = {Sebastian Golat and Francisco J. Rodríguez-Fortuño},
  year          = {2026},
  eprint        = {2602.14930},
  archivePrefix = {arXiv},
  primaryClass  = {physics.optics},
  url           = {https://arxiv.org/abs/2602.14930}}

Metadata

Release files for anafibre 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for anafibre 0.1.2
File Size Uploaded
anafibre-0.1.2.tar.gz 3.6 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for anafibre 0.1.2
File Interpreter ABI Platform
anafibre-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 3.7 MB

Release files / anafibre-0.1.2.tar.gz

Download URL anafibre-0.1.2.tar.gz
Size 3.6 MB
Tags Source
SHA-256 checksum
How to use checksums
2cafb4cbe819d9988d0ecbb10887d5bca14e9fdb39b71c8f154614854a55d5da
BLAKE2b-256 checksum
How to use checksums
2ff377edf389649f3c2fbf85d19ee3682c5edce1c06a0a3267bcc844ed997db4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release files / anafibre-0.1.2-py3-none-any.whl

Download URL anafibre-0.1.2-py3-none-any.whl
Size 51.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5d757642bcdb26547096176a0ea12dca37ba3b8051d1b56eac4facb43df314b4
BLAKE2b-256 checksum
How to use checksums
071bcbbb56f541bb8d112388315a8c29c0451bda2c8b870507096178fcc80882
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page