The Beer-Lambert law says that the absorbance of a sample is proportional to the concentration of the absorbing substance and the distance the light travels through it: A = εlc. Absorbance is defined from the light going in and coming out, A = log10(I₀/I), so each extra unit of absorbance cuts the transmitted light by a factor of ten. That single relationship lets a laboratory spectrophotometer turn a colour into a concentration, and it is the starting idea behind the two wavelength trick a pulse oximeter uses to estimate blood oxygen saturation.
This post goes one level deeper than our tour of the electromagnetic spectrum, which explains where ultraviolet, visible and near infrared light sit. Here we stay inside the narrow band from roughly 200 nm to 1000 nm where most absorbance work happens, and ask a practical question: how do you get a trustworthy number out of light that went into a sample and only partly came out?
A note before we start. Safeguard builds single purpose security models for software. They do not do chemistry, optics or medicine, and nothing in this post was calculated by them. The worked examples were computed with a short Python script you can run yourself, shown later in the post. Nothing here is medical advice; if you have questions about a pulse oximeter reading, the FDA's guidance is to contact a health care provider and not to rely only on the device.
Key takeaways
- The law in one line. A = εlc, where A is absorbance (dimensionless), ε is the molar absorption coefficient, l is the path length and c is the amount concentration. In the units most labs use, ε is in L mol⁻¹ cm⁻¹, l in cm and c in mol/L.
- Absorbance is a logarithm. A = log10(I₀/I) = -log10(T). An absorbance of 1 means 10% of the light gets through; an absorbance of 2 means 1%; 3 means 0.1%.
- Three people, three centuries. Pierre Bouguer published on the attenuation of light in 1729, Johann Heinrich Lambert put it in mathematical form in his Photometria of 1760, and August Beer published his measurements on coloured solutions in 1852. A review in ChemPhysChem notes the combined modern form with molar concentration took until the early twentieth century.
- IUPAC prefers "molar (decadic) absorption coefficient" to "extinction coefficient", and warns that values are often quoted without units.
- Instruments are checked against reference materials. NIST sells glass and metal on fused silica filters for the absorbance scale (SRM 930e, SRM 2031b), a potassium dichromate material for UV absorbance and linearity (SRM 935a) and a holmium oxide solution for the wavelength scale (SRM 2034).
- Calibration curves beat single point maths. Five standards, a least squares line and a look at the residuals tell you whether the law holds in your range before you trust an unknown.
- The law breaks down at high concentration, with stray light, with polychromatic light, in scattering samples, with fluorescence and when the absorbing species changes with concentration.
- Pulse oximeters use a ratio, not raw Beer-Lambert. They compare the pulsing part of the red and infrared signals and convert that ratio to SpO2 with an empirical calibration. The FDA says accuracy can be affected by skin pigmentation, poor circulation, skin thickness, skin temperature, tobacco use and nail polish, and in January 2025 it proposed stricter testing across skin tones.
What does the Beer-Lambert law say?
Shine a beam of monochromatic light of intensity I₀ through a sample. Some of it is absorbed, and a smaller intensity I comes out the other side. The Beer-Lambert law describes how I depends on the sample:
A = log10(I0 / I) = -log10(T)
A = ε · l · c
A absorbance (decadic), dimensionless
T transmittance, I / I0, a fraction between 0 and 1
ε molar (decadic) absorption coefficient, usually L mol^-1 cm^-1
l path length through the sample, usually cm
c amount concentration of the absorbing species, usually mol L^-1
The two lines say different things. The first is a definition: absorbance is simply a logarithmic way to report how much light was lost. The second is the physical law: that number grows in direct proportion to how many absorbing molecules the beam meets, which depends on how concentrated they are and how far the beam travels.
Why a logarithm?
Think of the sample as a stack of very thin slices. Each slice absorbs the same fraction of whatever light reaches it, not the same amount. If the first millimetre removes 20% of the light, the second millimetre removes 20% of what is left, and so on. A process where each step removes a fixed fraction is exponential decay:
dI/dx = -α · I (each thin slice removes a fixed fraction)
I(x) = I0 · exp(-α · x)
Taking the logarithm turns that exponential into a straight line. In base e you get the napierian absorbance, ln(I₀/I) = αx. In base 10 you get the decadic absorbance most instruments display. The two differ only by a constant factor of ln(10), about 2.303. The IUPAC Green Book defines both: the decadic absorbance A10 = -lg(1 - αi) and the napierian absorbance Ae = -ln(1 - αi), where αi is the internal absorptance. It also notes that if scattering and luminescence can be neglected, this leads to the customary form of the law with transmittance equal to exp(-κcl), where κ is the molar napierian absorption coefficient.
The ChemPhysChem review by Mayerhöfer, Pahlow and Popp describes the same starting assumption in historical terms: the loss of intensity in an infinitesimally thin layer of a homogeneous medium is proportional to the intensity and to the layer thickness. That assumption is the Bouguer and Lambert part of the law. Beer's contribution was showing how concentration enters.
Absorbance and percent transmittance side by side
Because the scale is logarithmic, absorbance numbers feel small for what they represent. This table is worth memorising:
| Absorbance A | Transmittance T | Percent of light transmitted | What it means at the bench |
|---|---|---|---|
| 0 | 1.000 | 100% | Same as the blank |
| 0.1 | 0.794 | 79.4% | Weak absorber, noisy at low concentration |
| 0.3 | 0.501 | 50.1% | Half the light absorbed |
| 0.5 | 0.316 | 31.6% | Comfortable working range |
| 1.0 | 0.100 | 10% | Still comfortable on most instruments |
| 1.5 | 0.032 | 3.2% | Upper end for many routine methods |
| 2.0 | 0.010 | 1% | Stray light starts to matter |
| 3.0 | 0.001 | 0.1% | Only a tenth of a percent reaches the detector |
The rows follow directly from T = 10^(-A). A reading of A = 2 means the detector sees a hundredth of the light it saw for the blank, which is why small errors in the light that reaches the detector have a large effect at high absorbance. We return to that in the section on stray light.
Who discovered the Beer-Lambert law, and when?
The law carries two names, sometimes three, and none of the people involved wrote it in the form we use today. The dates below are taken from the original publications as catalogued by the Internet Archive and Crossref, and from the historical overview in the 2020 ChemPhysChem review.
| Year | Who | What they contributed | Source checked |
|---|---|---|---|
| 1729 | Pierre Bouguer | Essai d'optique, sur la gradation de la lumière: measured how light weakens as it passes through the atmosphere and other media | Internet Archive catalogue record of the 1729 edition |
| 1760 | Johann Heinrich Lambert | Photometria: gave the attenuation of light with path length its mathematical form | Internet Archive catalogue record of the 1760 edition |
| 1852 | August Beer | "Bestimmung der Absorption des rothen Lichts in farbigen Flüssigkeiten", Annalen der Physik 162, 78 to 88: red light in coloured liquids, showing transmittance stays constant when the product of solute fraction and cell thickness stays constant | Crossref record; ChemPhysChem review |
| 1854 | August Beer | Grundriss des photometrischen Calcüles, which shows he knew Bouguer's and Lambert's work | ChemPhysChem review |
| 1857 | Robert Bunsen and Henry Roscoe | Photochemical absorption work that moved toward the modern formulation | ChemPhysChem review |
| 1900 | Robert Luther | Defined the German term for extinction | ChemPhysChem review |
| 1913 | Robert Luther | The review identifies a 1913 paper of his as apparently the first use of the merged modern formulation | ChemPhysChem review |
Two details from the review are worth keeping. First, Beer corrected for reflection losses at the cuvette walls before drawing his conclusion, something Bouguer and Lambert did not need to worry about because they studied light passing through air, whose refractive index is close to one. Second, Beer did not introduce molar concentration or the quantity we now call absorbance. The tidy A = εlc in every textbook is a later synthesis, which is why some authors prefer the name Bouguer-Beer-Lambert law.
What are absorbance, transmittance, molar absorption coefficient and path length?
These four quantities trip people up mostly because of units and synonyms. The IUPAC Green Book (Quantities, Units and Symbols in Physical Chemistry, third edition) gives the definitions in its table of spectroscopic quantities. Here is the same information in a form you can use at the bench.
| Quantity | IUPAC symbol | Definition | SI unit | Unit you will usually see |
|---|---|---|---|---|
| Transmittance | τ or T | Transmitted power over incident power, P_tr / P₀ | 1 (dimensionless) | Fraction, or percent (%T) |
| Absorptance | α | Absorbed power over incident power | 1 | Fraction |
| Decadic absorbance | A10 or A | -lg(1 - αi), which equals -lg(τi) | 1 | Plain number; "AU" is informal |
| Napierian absorbance | Ae or B | -ln(1 - αi) | 1 | Rare outside physics |
| Linear decadic absorption coefficient | a or K | A10 / l | m⁻¹ | cm⁻¹ |
| Molar decadic absorption coefficient | ε | a / c = A10 / (c·l) | m² mol⁻¹ | L mol⁻¹ cm⁻¹ (also written M⁻¹ cm⁻¹ or mol⁻¹ dm³ cm⁻¹) |
| Path length | l (often b in older texts) | Distance the beam travels in the sample | m | cm; standard cuvettes are 1 cm |
| Amount concentration | c | Amount of substance per volume | mol m⁻³ | mol L⁻¹ (M) |
A few points from the Green Book notes are worth reading slowly:
- "Extinction coefficient" is discouraged. The Green Book says ε is sometimes called the extinction coefficient in the literature, that numerical values are often quoted without units, and that when units are missing they are usually mol⁻¹ dm³ cm⁻¹. It adds that "extinction" should properly be reserved for the combined effect of absorption, scattering and luminescence.
- Internal versus measured quantities. The internal transmittance excludes surface effects and losses at the cuvette, such as reflections. That is why every measurement compares the sample with a reference cell filled with solvent only. The Green Book states that in practice absorbance is measured as the logarithm of the ratio of light transmitted through the reference cell to that transmitted through the sample cell.
- Unit conversion. One L mol⁻¹ cm⁻¹ equals 0.1 m² mol⁻¹, because a litre is 10⁻³ m³ and a centimetre is 10⁻² m. If a paper gives ε in m² mol⁻¹, multiply by 10 to get L mol⁻¹ cm⁻¹.
- ε depends on wavelength. A molar absorption coefficient without a wavelength is meaningless. The full statement is ε(λ), and the spectrum of a compound is just ε plotted against wavelength.
Biochemists and clinical chemists also use a mass based coefficient, often written with a superscript like 1% or in L g⁻¹ cm⁻¹, and NIST's potassium dichromate standard (below) uses an "apparent specific absorbance" in kg g⁻¹ cm⁻¹ because its solutions are prepared by mass. The law is the same; only the concentration unit changes, so always check which coefficient a method uses.
How does a UV-visible spectrophotometer work?
A UV-visible spectrophotometer is a machine for measuring I₀ and I accurately at a chosen wavelength. Every design has the same five building blocks, arranged in different ways.
- Light source. A lamp that covers the range you need. Ultraviolet work traditionally uses a deuterium lamp and visible work a tungsten halogen lamp, with the instrument switching between them; some instruments use a single pulsed xenon lamp.
- Wavelength selector. A monochromator, usually a diffraction grating with entrance and exit slits, picks a narrow band of wavelengths. The width of that band, the spectral bandwidth or bandpass, matters: NIST's reference material certificates specify the maximum bandpass for which their certified values hold.
- Sample compartment. The sample sits in a cuvette of known path length, typically 1 cm. Fused silica (quartz) cuvettes transmit ultraviolet light; ordinary glass and many plastics absorb in the ultraviolet and are limited to the visible region.
- Detector. A photomultiplier tube, a silicon photodiode or an array of photodiodes converts light to an electrical signal.
- Electronics and software. The instrument measures a dark signal, measures the blank (I₀), measures the sample (I), and reports A = log10(I₀/I).
The blank is half the measurement
The blank is the same cuvette type filled with everything except the analyte: the solvent, buffer and any reagents. Measuring the blank first, and setting the instrument to read zero absorbance on it, removes the absorbance of the solvent, the cuvette walls and reflection losses. Skip it, or use the wrong blank, and every number that follows is offset. In a double beam instrument the blank sits in a reference beam and is measured continuously; in a single beam instrument you measure it first and the instrument stores it.
Common instrument designs
| Design | How it measures I₀ and I | Strengths | Watch out for |
|---|---|---|---|
| Single beam scanning | Blank and sample measured one after the other through the same path | Simple, high light throughput | Lamp drift between blank and sample readings; re-blank often |
| Double beam scanning | Beam split or chopped between reference and sample cuvettes | Compensates for lamp drift in real time | More optics, slightly lower throughput |
| Diode array | All wavelengths dispersed after the sample onto an array; whole spectrum at once | Fast full spectra, few moving parts | Sample sees the full lamp output; bandwidth set by optics and pixel size |
| Microplate reader | Many small wells measured in sequence, often vertically | High throughput for assays | Path length depends on fill volume, not a fixed 1 cm |
| Fixed wavelength photometer | Filters or LEDs at a few wavelengths | Cheap, rugged, field use | Wider bandwidth, so more deviation from the ideal law |
The plate reader row is a frequent source of error. When light passes vertically through a well, the path length is the liquid height, which depends on the volume pipetted and the well geometry. Either correct for it or calibrate in the same plate format you use for samples.
How are spectrophotometers checked with NIST reference materials?
A spectrophotometer has two scales that can drift: the wavelength scale (is 546.1 nm really 546.1 nm?) and the photometric scale (is A = 1.000 really 1.000?). NIST Standard Reference Materials (SRMs) give laboratories a traceable way to check both. The certificates below were read from NIST's own certificate archive.
| SRM | What it is | What it checks | Key certified details |
|---|---|---|---|
| 930e | Glass filters for spectrophotometry: three neutral density glass filters plus an empty holder | Transmittance and absorbance scale in the visible region | Filters numbered 10, 20 and 30 for their nominal percent transmittance; certified at five visible wavelengths from 440.0 nm to 635.0 nm at 22 °C; certification valid two years, recertification available |
| 2031b | Metal on fused silica neutral density filters, 250 nm to 635 nm | Transmittance and absorbance scale in the ultraviolet and visible | Filters numbered 10, 30 and 90; ten certified wavelengths; values valid for spectral slit widths of 5 nm or less; certification valid two years |
| 935a | Crystalline potassium dichromate, 15 g, purity above 99.97% by coulometric assay | Accuracy and linearity of the ultraviolet absorbance scale | Solutions of 0.020 to 0.200 g/kg in 0.001 N perchloric acid; certified at 235, 257, 313, 345 and 350 nm at 23.5 °C; bandpass of 1.6 nm or less |
| 2034 | Holmium oxide solution (4% Ho₂O₃ in 10% perchloric acid) sealed in a fused silica cuvette | Wavelength scale | 14 absorption bands from 240 nm to 650 nm certified at six spectral bandwidths from 0.1 nm to 3 nm; certification valid indefinitely if handled as instructed |
For SRM 930e and SRM 2031b, the certificates describe the certified "transmittance density" as -log10(T), which should be indicated by the instrument's absorbance scale when the filter is measured against the empty holder. In other words, the filter's certified absorbance at a given wavelength is what your instrument should read, within the stated uncertainty.
For wavelength checks, SRM 2034 gives the wavelength of minimum transmittance of each holmium band. At a 1 nm spectral bandwidth, for example, the certificate lists band 13 at 536.56 nm and band 14 at 640.50 nm, each with an expanded uncertainty of 0.04 nm. If your instrument finds those minima more than its specified tolerance away, the wavelength scale needs attention before you trust any absorbance at a steep part of a spectrum.
Pharmacopoeias and quality systems set their own acceptance limits for these checks; the NIST material provides the traceable reference, and your method or regulator decides how close is close enough.
Worked example 1: finding a concentration from one absorbance reading
Start with the simplest use of the law: one sample, one wavelength, a known ε.
The setup. A coloured compound has a molar absorption coefficient ε = 15,000 L mol⁻¹ cm⁻¹ at its absorption maximum. (This value is illustrative, chosen to make the arithmetic clear; for a real compound you take ε from a validated method or measure it yourself with standards.) You blank the instrument with the solvent, fill a 1.00 cm cuvette with the sample and read A = 0.450.
Step 1: rearrange the law.
c = A / (ε · l)
Step 2: substitute, keeping units.
c = 0.450 / (15,000 L mol^-1 cm^-1 × 1.00 cm)
c = 0.450 / 15,000 mol^-1 L
c = 3.00 × 10^-5 mol L^-1 = 30.0 µmol/L
The units cancel properly: cm cancels cm, leaving mol L⁻¹.
Step 3: account for dilution. Suppose you diluted the original sample tenfold to bring it into range. The original concentration is 10 × 30.0 µmol/L = 300 µmol/L. Forgetting the dilution factor is one of the most common errors in student and routine work alike.
Step 4: sanity check with transmittance. T = 10^(-0.450) = 0.355, so 35.5% of the light was transmitted. If your instrument only displays %T, the conversion runs the other way: A = -log10(0.355) = 0.450. A reading between about 0.1 and 1.0 sits in the range where most instruments give good relative precision, so this measurement is in a comfortable place.
Step 5: convert to mass concentration if needed. If the compound's molar mass were 300 g/mol, the original solution would contain 300 µmol/L × 300 g/mol = 90 mg/L. Again, the molar mass here is illustrative.
A real certified example: NIST's dichromate calculation
The SRM 935a certificate includes a worked calculation that shows the same law with real, certified numbers. Because the dichromate solutions are prepared by mass, the certificate uses an apparent specific absorbance εa in kg g⁻¹ cm⁻¹ and a mass fraction c in g/kg:
Aa = εa × b × c
Conditions in the certificate example:
wavelength 350 nm, spectral bandpass 0.8 nm or less
b = 0.9982 cm (measured path length of the cuvette)
c = 0.04375 g/kg
t = 23.5 °C
Table 1 of the certificate gives εa = 10.682 at 0.040 g/kg and 10.692 at 0.060 g/kg. Linear interpolation to 0.04375 g/kg gives:
εa = 10.682 + (0.04375 - 0.040) / (0.060 - 0.040) × (10.692 - 10.682)
εa = 10.682 + 0.1875 × 0.010
εa = 10.684
Aa(calc) = 10.684 × 0.9982 × 0.04375 = 0.4666
If your instrument reads that solution at 350 nm and reports something close to 0.467, within the tolerance your method allows, its absorbance scale is behaving at that point. Repeat with the other certified concentrations and you have checked linearity across the range.
Notice two things. The certificate uses the measured path length, 0.9982 cm, not a nominal 1 cm, and the effect is about 0.2%. And εa is not perfectly constant with concentration; we come back to that when we discuss chemical equilibria.
Worked example 2: building and using a calibration curve from five standards
A single ε from a book is fine for teaching, but routine methods use a calibration curve made on the same instrument, with the same cuvettes, on the same day. This absorbs small instrument differences and also shows you whether the law holds over your range.
The data. Five standards of a coloured analyte, prepared from a stock solution, measured at the absorption maximum against a reagent blank in a 1 cm cuvette. (These values are illustrative.)
| Standard | Concentration (mg/L) | Absorbance |
|---|---|---|
| S1 | 2.0 | 0.101 |
| S2 | 4.0 | 0.198 |
| S3 | 6.0 | 0.304 |
| S4 | 8.0 | 0.399 |
| S5 | 10.0 | 0.497 |
Step 1: fit a straight line by least squares. With concentration as x and absorbance as y, ordinary least squares gives:
slope m = 0.04965 L/mg (absorbance per mg/L)
intercept b = 0.0019
R² = 0.99974
The slope is the product εl expressed in mass units. With a 1 cm cell, it is the mass absorption coefficient: 0.04965 L mg⁻¹ cm⁻¹.
Step 2: check the intercept. The Beer-Lambert law predicts a line through the origin. An intercept of 0.0019 absorbance units is small compared with the lowest standard (0.101), so the blank appears to have been handled correctly. A large positive intercept usually means the blank was not matched to the standards; a large negative one can mean the blank absorbs more than the sample matrix.
Step 3: look at the residuals, not just R². Residuals are the measured absorbance minus the absorbance the line predicts. For a sound calibration they are small and scatter randomly above and below zero.
| Standard | Measured A | Predicted A | Residual | Back calculated concentration (mg/L) |
|---|---|---|---|---|
| S1, 2.0 | 0.101 | 0.1012 | -0.0002 | 2.00 |
| S2, 4.0 | 0.198 | 0.2005 | -0.0025 | 3.95 |
| S3, 6.0 | 0.304 | 0.2998 | +0.0042 | 6.09 |
| S4, 8.0 | 0.399 | 0.3991 | -0.0001 | 8.00 |
| S5, 10.0 | 0.497 | 0.4984 | -0.0014 | 9.97 |
The residuals have no pattern and the back calculated concentrations are within about 1.5% of nominal. This calibration supports quantitation between 2 and 10 mg/L.
Step 4: measure the unknown. An unknown sample, prepared the same way, reads A = 0.350:
c = (A - b) / m = (0.350 - 0.0019) / 0.04965 = 7.01 mg/L
That sits inside the calibrated range, which is exactly where you want an unknown to be.
How to spot non-linearity
Now suppose someone extends the curve with two more standards to save a dilution step: 15 mg/L reads 0.725 and 20 mg/L reads 0.880. Using the five point line, the predicted absorbances would be 0.747 and 0.995. The 15 mg/L standard is 0.022 low and the 20 mg/L standard is 0.115 low. The curve is bending over.
What happens if you ignore that and fit a straight line through all seven points?
slope m = 0.04404, intercept b = 0.0345, R² = 0.9927
Residuals (mg/L 2, 4, 6, 8, 10, 15, 20):
-0.022, -0.013, +0.005, +0.012, +0.022, +0.030, -0.035
R² still looks respectable at 0.993, but the residuals now form an arch: negative at the low end, positive in the middle, sharply negative at the top. That systematic pattern is the signature of curvature. The intercept has jumped to 0.0345, and the same unknown at A = 0.350 now calculates as 7.16 mg/L instead of 7.01 mg/L, a 2% error introduced purely by including standards outside the linear range.
The lessons:
- Plot the residuals every time. A high R² does not prove linearity; a patterned residual plot disproves it.
- Restrict the range or dilute. Either calibrate only over the linear part, or dilute samples so they land within it.
- Do not force the line through zero to hide a problem. Python's
statistics.linear_regressionhas aproportional=Trueoption that fits a line through the origin. With the five good standards it gives a slope of 0.04991, very close to the unforced fit, which is reassuring. If forcing through zero changes the slope a lot, something is wrong with the blank or the standards. - Know why the curve bends. It may be stray light, bandwidth, a chemical equilibrium or plain instrument saturation. The breakdown table later in this post lists the usual suspects.
Worked example 3: the two wavelength ratio behind pulse oximetry
Pulse oximeters are the most widely used medical application of absorbance, and they are a good illustration of both the power and the limits of the Beer-Lambert idea. This section explains the physics; it is not guidance on using or interpreting a device.
What a pulse oximeter measures
The FDA describes a pulse oximeter as a device, usually placed on a fingertip, that uses light beams to estimate the oxygen saturation of the blood and the pulse rate, without drawing a blood sample. The reading it displays is SpO2, an estimate of the arterial oxygen saturation SaO2 that a CO-oximeter would measure directly from an arterial blood sample.
A 2015 review in Critical Care by Amal Jubran describes the method as spectrophotometric: the device measures changes in light absorption by oxygenated and deoxygenated haemoglobin at two wavelengths, 660 nm (red) and 940 nm (infrared). It computes the ratio of absorbance at these wavelengths, and that ratio is calibrated against direct measurements of SaO2.
Why two wavelengths work
Oxyhaemoglobin and deoxyhaemoglobin absorb red and infrared light very differently. A widely used compilation of haemoglobin absorption spectra by Scott Prahl at the Oregon Medical Laser Center tabulates these molar extinction coefficients, in cm⁻¹ per mol/L, for haemoglobin in water:
| Wavelength | Oxyhaemoglobin (HbO2) | Deoxyhaemoglobin (Hb) | Which absorbs more |
|---|---|---|---|
| 660 nm (red) | 319.6 | 3,226.56 | Deoxyhaemoglobin, about 10.1 times more |
| 940 nm (infrared) | 1,214 | 693.44 | Oxyhaemoglobin, about 1.75 times more |
So as blood loses oxygen, red absorbance rises sharply while infrared absorbance falls. The ratio of the two moves a long way for a small change in saturation, which is what makes the measurement sensitive.
Why the device looks at the pulse
A finger contains skin, bone, venous blood, tissue and arterial blood. Almost all of that absorbs a constant amount of light. Only the arterial blood volume changes with each heartbeat. The photodetector signal therefore has a large steady part (often called DC) and a small part that rises and falls with the pulse (AC). Dividing the pulsing part by the steady part at each wavelength cancels much of the constant absorption from everything else. The device then takes the ratio of those two normalised signals:
R = (AC_660 / DC_660) / (AC_940 / DC_940)
This is often called the "ratio of ratios". Each normalised AC/DC term is approximately proportional to the change in absorbance caused by the extra arterial blood in each pulse.
An idealised Beer-Lambert model
To see why R tracks saturation, assume the pulsing arterial blood obeys the Beer-Lambert law, that the extra path length is the same at both wavelengths and that only HbO2 and Hb absorb. Let S be the fraction of haemoglobin that is oxygenated. Then the change in absorbance at each wavelength is proportional to a weighted sum of the two coefficients, and the unknown path length and total haemoglobin concentration cancel in the ratio:
R(S) = [ε_HbO2(660)·S + ε_Hb(660)·(1 - S)] / [ε_HbO2(940)·S + ε_Hb(940)·(1 - S)]
= [319.6·S + 3226.56·(1 - S)] / [1214·S + 693.44·(1 - S)]
Plugging in a few saturations:
| Oxygen saturation S | Idealised R |
|---|---|
| 100% | 0.263 |
| 97% | 0.339 |
| 95% | 0.391 |
| 90% | 0.525 |
| 85% | 0.665 |
| 80% | 0.812 |
| 70% | 1.127 |
The relationship can be inverted to give S from a measured R:
S = (3226.56 - 693.44·R) / (2906.96 + 520.56·R)
For example, an idealised R of 0.6 corresponds to S = (3226.56 - 416.06) / (2906.96 + 312.34) = 2810.50 / 3219.30 = 0.873, about 87%.
Why real devices do not use this formula. The idealised model ignores the fact that tissue scatters light strongly, so photons take long, wavelength dependent paths; that the 660 nm and 940 nm light does not travel the same effective distance; that LEDs emit a band of wavelengths rather than one line; and that other haemoglobin species and pigments absorb too. This is why, as Jubran's review describes, the ratio is calibrated empirically against measured arterial saturation in human studies rather than computed from extinction coefficients. The numbers in the table above are a teaching model, not any device's calibration curve, and they should not be used to interpret a real reading.
Why accuracy varies: what the FDA and peer reviewed studies say
Because the calibration is empirical, accuracy depends on how well the calibration population and conditions match the person and situation where the device is used. The FDA's pulse oximeter page summarises its 2021 safety communication: multiple factors can affect the accuracy of a reading, such as poor circulation, skin pigmentation, skin thickness, skin temperature, current tobacco use and fingernail polish.
The peer reviewed evidence on skin pigmentation includes:
- Bickler, Feiner and Severinghaus, Anesthesiology, 2005 (volume 102, pages 715 to 719), "Effects of Skin Pigmentation on Pulse Oximeter Accuracy at Low Saturation." The FDA's draft guidance cites it as laboratory desaturation evidence of accuracy differences, especially at lower saturations.
- Sjoding and colleagues, New England Journal of Medicine, December 2020 (volume 383, pages 2477 to 2478), "Racial Bias in Pulse Oximetry Measurement." The authors looked for occult hypoxaemia, defined as an arterial saturation below 88% despite a pulse oximeter reading of 92% to 96%. In the University of Michigan cohort they found it in 11.7% of measurements in Black patients and 3.6% in White patients; in a multicentre cohort the figures were 17.0% and 6.2%. They concluded that Black patients had nearly three times the frequency of occult hypoxaemia not detected by pulse oximetry.
The FDA's own framing is careful. Its January 2025 draft guidance states that current evidence from laboratory desaturation studies suggests accuracy differences in some pulse oximeters between lightly and darkly pigmented individuals, especially at lower saturations, and also notes that an observed association does not always imply causation. It records that the November 2022 advisory panel said factors other than skin pigmentation, including low perfusion, explain some of the disparate performance and should be examined. Researchers have proposed several mechanisms, including how melanin absorbs light at the two wavelengths and how calibration study populations were composed; the regulatory documents we read treat the question of mechanism as still under study.
Motion is the other big source of error. Jubran's review shows how motion artifact produces an erratic waveform, and explains that ambient light sources can interfere because they can contain the same red and infrared wavelengths. The same review summarises a study in which dark nail polish colours produced the largest bias in critically ill patients.
What the FDA has proposed for testing
The FDA's timeline on its pulse oximeter page runs from the February 2021 safety communication, through FDA funded real world studies with academic partners in 2022, advisory committee meetings on 1 November 2022 and 2 February 2024, and a discussion paper on 16 November 2023, to draft guidance issued on 7 January 2025 (press release dated 6 January 2025). The draft, "Pulse Oximeters for Medical Purposes: Non-Clinical and Clinical Performance Testing, Labeling, and Premarket Submission Recommendations," would supersede the 2013 premarket guidance once finalised.
Key recommendations in the draft that connect directly to this post's physics:
| Draft recommendation | What it means |
|---|---|
| Arms below 3%, shown with statistical significance (upper limit of a two sided 95% confidence interval below 3%) | Arms is the root mean square difference between SpO2 and SaO2 across all paired measurements, as defined in ISO 80601-2-61 |
| 150 or more participants; 3,000 or more paired SpO2 and SaO2 observations | Larger controlled desaturation studies than before |
| Skin tone assessed by the Monk Skin Tone scale (subjective, ten levels) and by Individual Typology Angle from colorimetry (objective) | Participants grouped as MST 1 to 4, 5 to 7 and 8 to 10, with at least 25% in each group |
| Bias differences between skin tone groups below 3.5% for SaO2 of 70% to 85%, and below 1.5% for SaO2 above 85% | A specific test for non-disparate performance |
| Labeling that explains a reading is an estimate | The draft's suggested patient labeling gives the example that a reading of 90% may indicate an arterial saturation of 87% to 93% |
The FDA also notes that the draft applies to pulse oximeters for medical purposes, and not to products sold as general wellness or sporting and aviation products, which the agency does not review before sale. If you want to know which kind of device you have, the label and the FDA's own pages are the place to look. Again, this is a description of regulatory documents, not medical advice; the FDA's consumer advice is that if you are concerned about a reading you should contact a health care provider and not rely only on a pulse oximeter.
When does the Beer-Lambert law break down?
The law is an idealisation. It assumes monochromatic, parallel light; a homogeneous, non-scattering sample; absorbing molecules that act independently of one another; and an absorbing species that does not change with concentration. The ChemPhysChem review adds a deeper point: even with perfect instruments, the law is only an approximation to electromagnetic theory, and effects from the wave nature of light, such as interference in thin films and changes in refractive index, can shift bands and change intensities. In routine solution work those effects are small, but they explain why the law is called a limiting law.
Here are the practical causes of deviation, what they look like and what to do.
| Cause | What you see | Why it happens | Practical fix |
|---|---|---|---|
| High concentration | Calibration curve bends toward the concentration axis | Absorbing molecules interact, and the refractive index of the solution changes | Dilute into the linear range; calibrate only where residuals are random |
| Stray light | Absorbance flattens at high values; apparent maximum absorbance | Light outside the selected band reaches the detector and is not absorbed | Keep readings below about A = 1.5 to 2; check stray light with the manufacturer's procedure; dilute |
| Polychromatic light (wide bandwidth) | Lower than expected absorbance, especially on steep parts of a band | ε varies across the band of wavelengths that pass the slit | Measure at the absorption maximum where ε is flat; use a narrower bandwidth |
| Scattering (turbidity, suspensions, tissue) | Absorbance rises across the whole spectrum, often more at short wavelengths | Light is redirected out of the beam rather than absorbed | Filter or centrifuge; use a scatter correction; in tissue, use empirical calibration as pulse oximeters do |
| Fluorescence | Absorbance lower than expected | The sample re-emits light that reaches the detector | Increase distance to the detector or use instrument geometry that rejects emitted light |
| Chemical equilibria | Apparent ε changes with concentration or pH | The absorbing species converts to another as conditions change | Buffer the solution; measure at an isosbestic point; follow the method exactly |
| Wavelength scale error | Absorbance off when measuring on a band's slope | Instrument reports one wavelength but measures another | Check with a holmium oxide wavelength standard such as SRM 2034 |
| Cuvette mismatch or dirt | Constant offset between blank and samples | Different reflection or absorption by the cell itself | Use matched cells; clean and orient them consistently; re-blank |
| Detector nonlinearity or saturation | Errors at both very low and very high signal | Electronics outside their linear range | Stay inside the instrument's specified photometric range; verify with filters such as SRM 930e or 2031b |
Stray light, in numbers
Stray light is the reason the "comfortable" range in the first table stops around A = 1 to 1.5. Suppose a fraction s of the detected light is stray light that bypasses absorption. The measured transmittance becomes (T + s)/(1 + s), so the measured absorbance is:
A_measured = -log10( (T + s) / (1 + s) ), where T = 10^(-A_true)
With s = 0.1% (0.001):
| True absorbance | Measured absorbance | Error |
|---|---|---|
| 0.5 | 0.499 | Negligible |
| 1.0 | 0.996 | -0.4% |
| 2.0 | 1.959 | -2.1% |
| 3.0 | 2.699 | -10% |
| 4.0 | 2.959 | -26% |
With s = 1% (0.01), a true absorbance of 2.0 reads as 1.703 and nothing can read much above 2.0, however concentrated the sample. A curve that flattens like this is not the sample changing; it is the instrument's floor.
Chemical equilibria, in numbers
The dichromate standard shows a chemical deviation cleanly. In acidic solution, chromium(VI) exists as both hydrogen chromate and dichromate ions, and the balance between them shifts with concentration. NIST's SRM 935a Table 1 reflects this. At 257 nm, the certified apparent specific absorbance rises from 14.262 at 0.020 g/kg to 14.763 at 0.200 g/kg, an increase of about 3.5% over the range. At 345 nm, which the certificate says is near one of the two isosbestic points in the hydrogen chromate and dichromate spectra, the value barely moves, from 10.604 to 10.597. An isosbestic point is a wavelength where two interconverting species absorb equally, so the conversion between them does not change the total absorbance. The certificate also warns that 345 nm sits on the slope of the composite spectrum, so values there depend on wavelength accuracy, and recommends that wavelength only for verifying linearity.
This is the general lesson in miniature: if an apparent ε drifts with concentration, the law has not failed; the absorbing species has changed.
Comparison: lab spectrophotometers, photometers and pulse oximeters
The same physics drives very different devices. This decision table compares them by what they assume and how they are calibrated.
| Laboratory UV-visible spectrophotometer | Fixed wavelength photometer or colorimeter | Microplate reader | Pulse oximeter | |
|---|---|---|---|---|
| Light | Monochromator, narrow selectable band | Filter or LED, few fixed bands | Monochromator or filters | Red and infrared LEDs |
| Sample | Clear solution in a 1 cm cuvette | Clear solution or test strip | Small volumes in wells | Living tissue with pulsing blood |
| Path length | Known and fixed | Fixed | Depends on fill volume | Unknown, cancels in the ratio |
| Does Beer-Lambert apply directly? | Yes, within the linear range | Approximately; wider bandwidth increases deviation | Yes, with path length correction | No; used as a model, then calibrated empirically |
| Calibration | Standards and reference materials such as SRM 930e, 2031b, 935a and 2034 | Standards supplied with the method | Standards in the same plate format | Controlled desaturation studies against arterial blood gas measurements |
| Typical output | Absorbance, spectrum, concentration | Concentration | Many absorbances at once | SpO2 and pulse rate |
| Biggest practical risk | Wrong blank or out of range readings | Interfering colours | Path length and meniscus | Poor perfusion, motion, skin pigmentation effects, nail polish |
Step by step: measuring a concentration and checking linearity
This walkthrough covers a routine absorbance measurement and then reproduces every number in this post with a small Python script. Adapt the instrument steps to your laboratory's validated procedure; they are a general outline, not a replacement for your method.
At the instrument
- Warm up the lamp for the time the manufacturer specifies, so its output is stable.
- Check the wavelength scale periodically with a holmium oxide reference such as SRM 2034, and the photometric scale with neutral density filters such as SRM 930e or 2031b, according to your quality schedule.
- Choose the wavelength. Run a spectrum of a mid range standard and pick the absorption maximum, where ε changes least with small wavelength errors.
- Prepare a matched blank containing everything except the analyte. Use the same cuvette type, and for the best work, the same cuvette.
- Zero on the blank. Fill, wipe the optical faces, place it in the same orientation every time and set zero absorbance.
- Measure standards from low to high, rinsing the cuvette with the next solution before filling.
- Measure unknowns, re-measuring the blank or a check standard every so often to catch drift.
- Dilute any unknown that reads above your highest standard and measure again; never extrapolate.
Reproduce the numbers in Python
The script uses only the Python standard library. statistics.linear_regression and statistics.correlation were added in Python 3.10, and the proportional option of linear_regression in Python 3.11, according to the Python documentation, so check your version first.
python3 --version # needs 3.11 or newer for proportional=True
python3 -m venv .venv
source .venv/bin/activate # on Windows: .venv\Scripts\activate
Save the following as beer_lambert.py:
import math
import statistics as st
# Worked example 1: one reading
eps = 15000.0 # L mol^-1 cm^-1 (illustrative)
l = 1.00 # cm
A = 0.450
c = A / (eps * l)
print(f"c = {c:.3e} mol/L = {c*1e6:.1f} umol/L; T = {10**-A:.3f}")
# NIST SRM 935a example from the certificate
eps_a = 10.682 + (0.04375 - 0.040) / (0.060 - 0.040) * (10.692 - 10.682)
print(f"SRM 935a: eps_a = {eps_a:.3f}, Aa = {eps_a * 0.9982 * 0.04375:.4f}")
# Worked example 2: calibration curve
conc = [2.0, 4.0, 6.0, 8.0, 10.0] # mg/L
absb = [0.101, 0.198, 0.304, 0.399, 0.497]
fit = st.linear_regression(conc, absb)
r2 = st.correlation(conc, absb) ** 2
print(f"slope={fit.slope:.5f} intercept={fit.intercept:.4f} R2={r2:.5f}")
for x, y in zip(conc, absb):
pred = fit.slope * x + fit.intercept
print(f" {x:5.1f} mg/L resid={y - pred:+.4f} back={(y - fit.intercept) / fit.slope:.2f}")
print(f"unknown at A=0.350: {(0.350 - fit.intercept) / fit.slope:.2f} mg/L")
print("through origin slope:", round(st.linear_regression(conc, absb, proportional=True).slope, 5))
# Non-linearity check with two high standards added
conc7 = conc + [15.0, 20.0]
absb7 = absb + [0.725, 0.880]
fit7 = st.linear_regression(conc7, absb7)
print("seven point residuals:",
[round(y - (fit7.slope * x + fit7.intercept), 3) for x, y in zip(conc7, absb7)])
# Worked example 3: idealised pulse oximetry ratio (teaching model only)
e660 = (319.6, 3226.56) # HbO2, Hb (Prahl compilation, cm^-1 per mol/L)
e940 = (1214.0, 693.44)
def ratio(s):
return (e660[0] * s + e660[1] * (1 - s)) / (e940[0] * s + e940[1] * (1 - s))
for s in (1.0, 0.97, 0.95, 0.90, 0.85, 0.80, 0.70):
print(f"S={s:.2f} R={ratio(s):.3f}")
# Stray light effect
for s_frac in (0.001, 0.01):
row = []
for a_true in (0.5, 1, 2, 3, 4):
t = 10 ** -a_true
row.append(round(-math.log10((t + s_frac) / (1 + s_frac)), 3))
print(f"stray={s_frac}: {row}")
Run it:
python3 beer_lambert.py
You should see the same values as the tables above: c = 3.000e-05 mol/L, an SRM 935a absorbance of 0.4666, a slope of 0.04965 with R² of 0.99974, an unknown of 7.01 mg/L, the arched seven point residuals, the idealised R values from 0.263 to 1.127, and the stray light rows.
If you turn a script like this into a shared tool, for example a small web service that a lab uses to process plate reader exports, it stops being a calculation and becomes software with dependencies. Pin the versions you install (pip install -r requirements.txt with exact versions, or a lockfile) and keep them up to date, the same as any other application.
Common mistakes
- Forgetting the blank, or using the wrong one. The blank must contain everything except the analyte. A water blank for a coloured reagent method builds the reagent's absorbance into every result.
- Reading above the linear range. An unknown that reads higher than your top standard is outside the calibration. Dilute and remeasure; never extrapolate the line.
- Mixing up log bases. Instruments report decadic absorbance (log10). Physics texts and some tissue optics papers use napierian absorbance (ln). The factor between them is 2.303. Using an ε from one with an absorbance from the other gives a result off by that factor.
- Confusing %T with absorbance. 50% transmittance is A = 0.301, not A = 0.5. Convert with A = 2 - log10(%T), which is the same as -log10(T) with T as a fraction.
- Ignoring the dilution factor. The concentration in the cuvette is not the concentration in the original sample.
- Quoting ε without units or wavelength. IUPAC warns that "extinction coefficients" are often given without units. Always state ε(λ) with units and solvent.
- Trusting R² alone. As the seven point example shows, R² of 0.993 can hide clear curvature. Plot residuals.
- Measuring on the side of a band. Small wavelength errors cause large absorbance changes on a steep slope. Measure at the maximum, or check wavelength accuracy with a holmium standard.
- Fingerprints and bubbles. Anything on the optical faces or in the beam adds absorbance or scatter. Hold cuvettes by the frosted sides and tap out bubbles.
- Using glass or plastic cuvettes in the ultraviolet. They absorb strongly at short wavelengths; use fused silica for ultraviolet work.
- Treating a pulse oximeter reading like a spectrophotometer reading. A pulse oximeter's output is an empirically calibrated estimate with a stated accuracy, not a direct Beer-Lambert measurement. Consumer and wellness products may not have been reviewed by the FDA at all.
FAQ
What is the Beer-Lambert law in simple terms?
The more of a light absorbing substance the light has to pass through, the less light gets out, and absorbance measures that loss on a logarithmic scale. Absorbance is proportional to concentration and path length: A = εlc. Double the concentration or double the cuvette length and the absorbance doubles.
What is the difference between absorbance and transmittance?
Transmittance is the fraction of light that gets through, T = I/I₀, often shown as a percentage. Absorbance is the negative base 10 logarithm of transmittance, A = -log10(T). Absorbance is the useful quantity because it, not transmittance, is proportional to concentration.
What are the units of molar absorptivity?
The SI unit of the molar decadic absorption coefficient is m² mol⁻¹, but most laboratories use L mol⁻¹ cm⁻¹ (also written M⁻¹ cm⁻¹). One L mol⁻¹ cm⁻¹ equals 0.1 m² mol⁻¹. Absorbance itself has no units.
Why is it sometimes called the Beer-Lambert-Bouguer law?
Pierre Bouguer published on the attenuation of light in 1729, before Lambert's 1760 Photometria and well before Beer's 1852 paper on coloured solutions. Some authors, including the ChemPhysChem review cited here, use the name Bouguer-Beer-Lambert law to credit him.
What absorbance range is best for accurate measurements?
Readings between roughly 0.1 and 1.0 suit most routine work. Very low absorbances are dominated by noise and blank errors, and high absorbances are limited by stray light, as the stray light table shows. Your instrument's specification and your validated method set the exact limits.
Why does my calibration curve bend at high concentration?
Common causes are stray light, a spectral bandwidth that is too wide for the band you are measuring, molecular interactions at high concentration, and chemical equilibria that change the absorbing species. Dilute samples into the linear range and check residuals rather than R².
How does a pulse oximeter use the Beer-Lambert law?
It shines red (around 660 nm) and infrared (around 940 nm) light through tissue, isolates the part of each signal that pulses with arterial blood, and takes the ratio of the two. Because oxygenated and deoxygenated haemoglobin absorb these wavelengths differently, that ratio tracks oxygen saturation. Real devices convert the ratio to SpO2 with an empirical calibration from human studies rather than the pure law, because tissue scatters light.
Does skin colour affect pulse oximeter accuracy?
The FDA lists skin pigmentation among factors that can affect accuracy, and its January 2025 draft guidance says current evidence suggests accuracy differences in some pulse oximeters between lightly and darkly pigmented individuals, especially at lower oxygen levels. A 2020 NEJM study found higher rates of undetected low oxygen in Black patients than White patients. The FDA has proposed larger studies across skin tones. For questions about a reading, contact a health care provider.
What NIST standards are used to check a spectrophotometer?
Common choices are SRM 930e glass filters and SRM 2031b metal on fused silica filters for the absorbance scale, SRM 935a potassium dichromate for ultraviolet absorbance accuracy and linearity, and SRM 2034 holmium oxide solution for the wavelength scale.
Can the Beer-Lambert law be used for gases and the atmosphere?
Yes. Bouguer and Lambert originally studied light passing through the atmosphere, and the same exponential attenuation applies to gases, with concentration expressed as number density or partial pressure. Gas analysers and atmospheric measurements use absorption coefficients suited to those units.
The software around the instruments: an honest bridge
The Beer-Lambert law is physics and chemistry, and Safeguard does not do either. Its models are single purpose security models for software. They do not calculate concentrations, interpret spectra, evaluate pulse oximeter accuracy or analyse laboratory data, and nothing in this post was computed by them. The connection is narrower and practical. Spectrophotometers, plate readers and pulse oximeters run firmware, and the instrument control software, data pipelines, laboratory information systems and dashboards that process their readings are software too. Much of that code, including analysis scripts like the one above once they become shared tools, is built from open source data and plotting libraries, web frameworks and container images. That is where Safeguard helps: scanning repositories, container images and SBOM files for known vulnerable open source components, showing which projects carry a given version, and, when a fixed version exists, opening an upgrade pull request for review.
Every rebuild of a lab data service or an instrument integration pulls its dependencies again, and the firmware and companion apps that ship with instruments and medical devices contain open source components of their own, which only their manufacturers can update. The fit is indirect for the optics itself, but for the code your team builds and ships around these instruments the same dependency hygiene applies, and the section below shows how to close the gap whether or not upstream has a fix yet.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
None of these demos involve optics, chemistry or medical device analysis; they show the software side described in the bridge above.
The first demo is a real Safeguard CLI session: it installs the CLI, opens the interactive terminal and asks it to fix a lodash CVE in a repository. It reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, prints a summary and pushes nothing. The same flow applies to a lab results dashboard or an instrument data web app your team maintains: scan the repository, then let the assistant propose the dependency upgrade under your approval.
Click through it at your own pace, or open it full screen.
The second demo sets up the Safeguard runner on your own machine, approves it with its device code and then scans from the terminal. That suits laboratory and instrument engineering teams who keep analysis scripts and integration code on their own hardware and want the scan to run where the code lives.
Click through it at your own pace, or open it full screen.
The third demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. For an engineer who already works with Claude while building a pipeline for spectrophotometer or plate reader exports, it brings dependency findings into the same conversation, limited to the tools you allow.
Click through it at your own pace, or open it full screen.
To try it on your own repositories, download Safeguard and follow the CLI documentation.
Quick check
A solution reads A = 0.600 in a 1 cm cuvette and the compound has ε = 12,000 L mol⁻¹ cm⁻¹. What is its concentration, and what percent of the light got through?
c = A / (εl) = 0.600 / 12,000 = 5.00 × 10⁻⁵ mol/L, or 50.0 µmol/L. T = 10^(-0.600) = 0.251, so about 25.1% of the light was transmitted.
Why does a pulse oximeter use the ratio of red and infrared pulsatile signals instead of a single absorbance?
Most of the light absorbed in a finger comes from tissue, bone and venous blood that do not change with the heartbeat, and the true path length is unknown. Normalising each pulsing signal by its steady part and taking the red to infrared ratio cancels much of that, leaving a number that tracks the balance of oxygenated and deoxygenated haemoglobin. The device then converts it to SpO2 using an empirical calibration.
Sources
- IUPAC, Quantities, Units and Symbols in Physical Chemistry (Green Book), third edition, 2012 second printing (PDF)
- Mayerhöfer, Pahlow and Popp, The Bouguer-Beer-Lambert Law: Shining Light on the Obscure, ChemPhysChem 21 (2020) 2029 to 2046 (PMC, open access)
- Crossref record: Beer, Bestimmung der Absorption des rothen Lichts in farbigen Flüssigkeiten, Annalen der Physik 162 (1852) 78 to 88
- Internet Archive: Bouguer, Essai d'optique, sur la gradation de la lumière (1729)
- Internet Archive: Lambert, Photometria (1760)
- NIST, SRM 930e Glass Filters for Spectrophotometry, certificate (PDF)
- NIST, SRM 2031b Metal-on-Fused-Silica Neutral Density Filters (250 nm to 635 nm), certificate (PDF)
- NIST, SRM 935a Crystalline Potassium Dichromate for Use as an Ultraviolet Absorbance Standard, certificate (PDF)
- NIST, SRM 2034 Holmium Oxide Solution Wavelength Standard, certificate (PDF)
- NIST Standard Reference Materials
- NIST Chemistry WebBook
- US Food and Drug Administration, Pulse Oximeters
- US Food and Drug Administration, FDA Proposes Updated Recommendations to Help Improve Performance of Pulse Oximeters Across Skin Tones, 6 January 2025
- US Food and Drug Administration, draft guidance: Pulse Oximeters for Medical Purposes, Non-Clinical and Clinical Performance Testing, Labeling, and Premarket Submission Recommendations
- US Food and Drug Administration, draft guidance full text (PDF)
- US Food and Drug Administration, Prospective clinical study of pulse oximeter errors in adult hospitalized patients with varying skin pigmentation
- Jubran, Pulse oximetry, Critical Care 19 (2015) 272 (PMC)
- Sjoding et al., Racial Bias in Pulse Oximetry Measurement, New England Journal of Medicine 383 (2020) 2477 to 2478 (PMC)
- Crossref record: Bickler, Feiner and Severinghaus, Effects of Skin Pigmentation on Pulse Oximeter Accuracy at Low Saturation, Anesthesiology 102 (2005) 715 to 719
- Prahl, Oregon Medical Laser Center, Optical Absorption of Hemoglobin
- Prahl, Oregon Medical Laser Center, Tabulated Molar Extinction Coefficient for Hemoglobin in Water
- Python documentation, statistics module
- NASA Imagine the Universe, The Electromagnetic Spectrum
Last reviewed: 24 October 2026.