npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tmmcore

v0.2.0

Published

Transfer-matrix method for multilayer thin-film optics, with exact analytic derivatives and phase dispersion. JavaScript, C and WebAssembly.

Readme

Transfer-matrix method for multilayer thin-film optics, with exact analytic derivatives.

npm License: MIT

Documentation · Getting started · API · Validation

Takes a stack of layers and returns reflectance, transmittance and absorptance for absorbing and dispersive materials, at any angle of incidence, in s and p polarization. Alongside the spectra it returns the exact thickness Jacobian, the exact thickness Hessian, and the needle-insertion P-function, computed analytically rather than by finite differences.

It also computes phase, group delay, GDD and third-order dispersion, by carrying the same matrix in third-order Taylor arithmetic. Those come out analytically too, so they do not depend on the wavelength grid you sampled and there is no finite-difference step to tune. Their thickness gradients come along in the same call, which is what makes chirped-mirror design a gradient problem.

Ships as JavaScript, as C, and as a WebAssembly build of the C. The JavaScript has no dependencies and works on import. WebAssembly is opt-in and roughly an order of magnitude faster.

Install

npm install tmmcore

The .wasm is prebuilt and included, so no Emscripten toolchain is required.

Use

import { tmm } from 'tmmcore';

// A quarter-wave MgF2 layer on glass, at 550 nm, normal incidence.
const { R, T, A } = tmm(
    550,            // wavelength, nm
    0,              // angle of incidence, degrees from normal
    's',            // polarization: 's' or 'p'
    [1.0, 0],       // incident medium, ñ = [n, k]
    [1.52, 0],      // substrate
    [{ n: [1.38, 0], d: 550 / (4 * 1.38) }]   // quarter wave, thickness in nm
);

console.log(R);   // 0.012600790214630274

Layers run from the incident medium toward the substrate.

Conventions

Mismatched conventions are the most common cause of two TMM codes disagreeing, so check these first.

| | | |---|---| | Refractive index | ñ = n + i·k, with k ≥ 0 for absorbing media | | Time factor | exp(−iωt), so a wave exp(i(kz − ωt)) decays for k > 0 | | Wavelength, thickness | nanometres | | Angle | degrees from normal | | Complex numbers | [re, im] pairs | | Layer order | incident medium → substrate |

This is the complex conjugate of Macleod's convention. R, T and A are identical under conjugation; phase-sensitive quantities are not.

Verify it yourself

Three commands, none needing anything but Node:

node examples/01-single-layer.mjs   # matches the closed-form solution
npm test                            # the JavaScript and the C agree
npm run compare                     # and both agree with an independent implementation

The first tests the equations rather than agreement, and is the only one here that does. A single quarter-wave layer at normal incidence has an exact solution (Macleod §3.2); tmmcore reproduces it to 1.4e-17, inside double-precision epsilon of 2.2e-16.

The second drives both implementations with identical inputs across absorbing, dispersive and oblique-incidence cases and compares every returned quantity. 64,416 comparisons, worst disagreement 4.4e-16. This is two implementations by the same author, so it catches porting bugs and establishes nothing beyond that.

The third checks them against Steven Byrnes' tmm, written independently in Python under the same complex-index convention, so only the mathematics is under test. 12,352 values, worst disagreement 8.6e-14, which is float64 accumulation noise over a forty-layer matrix product.

Validation sets out what each level does and does not establish, and lists what is not tested at all.

The comparison with four other TMM packages covers accuracy as well as speed, including which of them run in single precision. Reproducing the timings needs a Python environment; the accuracy table does not.

Documentation

Using the C directly

src/tmm_kernel.c is C99 with no dependencies beyond libm. Drop it into a project and compile:

cc -std=c99 -O2 -c src/tmm_kernel.c

Licence

MIT © Andrey Achapovsky

Built for and used by TFStudio, an open-source optical coating design application.