Low-cost air sensor calibration against a reference: clean spikes and stuck values, fit linear, RH-corrected or Deming models

Paste or open a low-cost sensor's readings (with humidity and temperature if you have them) and a co-located reference. The page removes out-of-range, stuck and spike readings (Hampel filter), averages both to the same periods, fits a linear, multilinear (RH, T) or Deming calibration, reports R², RMSE, MAE and bias on fit and test periods, and applies the calibration to new data. CSV in and out.

Keep it one tap away for everyday use.

Bookmark Sensor calibration?

Press Ctrl + D now. Your browser opens its own bookmark box, where you choose the name and folder.

  1. Data
  2. Clean
  3. Fit
  4. Apply
Nothing is uploadedWorks offline once open

Data

Low-cost sensor

Reference instrument

One row per reading, with a header row. Times like 2026-03-01 13:05 (ISO, with or without a zone such as Z or +05:30), 01/03/2026 13:05, or Unix seconds. Both files must use the same clock and time zone, and each time should mark the start of its averaging period. Data stay in your browser.

Cleaning and alignment

Readings outside the valid range (such as −999 error codes), runs of identical readings (a frozen sensor; 0 turns this off) and spikes are removed from the sensor data. The spike filter (Hampel) compares each reading with the median of its neighbours and removes it when it is further away than the threshold times the scaled median absolute deviation (0 turns it off). Then both series are averaged over the same periods, and periods with fewer sensor readings than asked are left out.

Calibration

R² is 1 − (sum of squared errors ÷ total sum of squares) against the reference, so it also counts bias. RMSE and MAE are in the units of the readings; bias is the mean of (value − reference). The fit uses the earlier periods; the test periods were not used to fit, so they show how well the calibration carries forward.

Download

Apply to new data

Uses the same column names as the sensor data above (or the same positions), the calibration above, and the readings as they are (not averaged). Readings removed by cleaning, or with a missing RH or temperature the model needs, get no calibrated value.

What it does

Low-cost air quality sensors are cheap enough to put everywhere, but their raw readings are rarely right. Particle sensors read high in humid air; gas sensors drift with temperature; any sensor can freeze, spike or log an error code. The usual fix is to run the sensor next to a reference instrument for a few weeks, then fit a calibration that turns the sensor’s readings into reference-like values.

This page does the whole job in your browser:

  1. Cleans the sensor data: removes readings outside a valid range (such as −999 error codes), runs of identical readings (a frozen sensor) and spikes (a Hampel filter).
  2. Aligns the two series by averaging both over the same periods (for example one hour) and keeping periods where both have data.
  3. Fits a calibration: reference = a + b × sensor, optionally with relative humidity and temperature terms, or a Deming line that allows for error in both instruments.
  4. Tests it on the last part of the record, which the fit never saw, and reports R², RMSE, MAE and bias before and after.
  5. Applies it to new sensor data and gives you a CSV.

How to use it

  1. Paste or open the sensor data (a time column, the reading, and humidity and temperature if you have them) and the reference data (time and reading). Pick the columns if the guesses are wrong.
  2. Set the valid range, the number of identical readings that count as stuck, the spike filter window and threshold, and the averaging period.
  3. Choose a model and the share of periods to keep back for the test.
  4. Read the equation, the coefficient table and the agreement table. Look at the scatter plot and the time series.
  5. Paste new sensor readings under Apply to new data and download the calibrated CSV.

Worked example

Press Use the example. It is made up: three weeks of 5-minute particle (PM2.5) readings from a sensor that reads about a quarter high and more so in humid air, with spikes, a 90-minute frozen spell and six −999 error codes, next to an hourly reference.

With the defaults (valid range 0 to 1000, stuck after 10 identical readings, spike window ±6 readings at 3 × MAD, hourly averages with at least 9 readings, linear with humidity, last 30 % for testing), the cleaning facts list the six out-of-range readings, the 18 stuck ones and the spikes removed. The equation reads like “Calibrated = a + b × sensor − c × RH”, with b below 1 and a negative humidity term, because the made-up sensor reads high in humid air. In the agreement table, the raw sensor’s bias of several µg/m³ falls to near zero after calibration, and RMSE drops too, in the test periods as well as the fit periods.

Try Linear alone: the test RMSE is higher, because the humidity effect is left in. Try Deming to see a line that treats both instruments as uncertain.

Tips

  • Co-locate for at least two to four weeks, covering the weather and pollution levels the sensor will see later. A calibration only holds within the conditions it was fitted on.
  • Judge models on the test periods. Adding terms always improves the fit periods; it only helps if the test improves too.
  • Check the time zones: if one logger writes UTC and the other local time, nothing lines up. The matched-periods count tells you quickly.
  • Re-check the calibration every few months; sensors age.
  • Humidity effects on particle sensors are often non-linear at very high humidity. Removing periods above about 90 % RH (with the valid range of a filtered file) can help.

FAQ

Which way round is the fit? The reference is predicted from the sensor (reference = a + b × sensor + …), so the equation applies straight to new sensor readings. Deming uses the same direction but allows error in both.

What is λ in Deming regression? The ratio of the reference’s error variance to the sensor’s. With λ = 1 both are taken as equally noisy (orthogonal regression). A very large λ gives ordinary least squares.

Why are the averages “periods” and not times? Each period starts at a whole multiple of the averaging time from midnight, and holds the readings from its start up to the next period. The reference’s time should mark the start of its own averaging period too.

Is my data uploaded? No. Everything is worked out in this page and nothing leaves your device.

Where the numbers come from

  • Hampel filter, stuck-value and range checks, time averaging, ordinary least squares, Deming regression and the agreement metrics are written by fibub. The tests check them against pandas (rolling median and MAD, run lengths, resample with origin='epoch'), statsmodels OLS (coefficients, standard errors, R², adjusted R²), scipy.odr (Deming as orthogonal distance regression) and numpy.
  • The method (co-location with a reference, then a regression with humidity and temperature terms, judged on data not used to fit) is general practice for low-cost sensors; no agency's coefficients or thresholds are copied.
  • The example data (three weeks of particle readings, humidity, temperature and a reference) are made up by fibub.

Standard scientific values, such as constants, atomic weights and melting points, are facts found in every textbook; we name where ours were checked. If you are an author or publisher and want a value, a credit or a table changed or removed, tell us and we will act quickly.

Last updated 2026-11-09.

Related tools

Air quality calculator #116 Convert gas concentrations between ppm, ppb, µg/m³ and mg/m³ at any temperature and pressure, and work out the US Air Quality Index (with the 2024 PM2.5 breakpoints), India's National AQI and Canada's Air Quality Health Index from your own readings. Trend and anomaly analyser #138 Paste or open a time series (yearly, monthly or any steps) and test for a trend with Mann-Kendall, the Hamed-Rao autocorrelation correction or the seasonal test, get Sen's slope with its confidence interval, a Pettitt change point and anomalies from a baseline period. Method validation statistics #87 Paste replicate results by day, analyst or instrument: mean, SD, RSD and confidence interval, the Grubbs outlier test, bias and recovery against a true value, repeatability and intermediate precision by ANOVA, and the Horwitz ratio. Calibration curve with LOD and LOQ #28 Paste your standards and get the calibration line, R², limits of detection and quantitation (ICH Q2), and the concentration of each unknown with a 95 % interval. Gaussian plume calculator #118 Estimate how a chimney plume spreads downwind: Pasquill stability class from the wind and sky, Briggs dispersion curves for open country or a city, buoyant plume rise, the highest ground-level concentration and where it lands, and a plan-view map. UV index estimator #504 Estimate the clear-sky UV index for any place, date and time from the Sun's zenith angle and the ozone column, with factors for height, snow or sand and cloud. See the curve through the day, the peak at solar noon, the hours above each UV band and how long a chosen erythemal dose takes. An estimate: check your local UV forecast.