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

@verifyhash/psychrometrics

v0.1.1

Published

Zero-dependency humidity & moist-air math: saturation vapour pressure, dew point, relative & absolute humidity, NOAA heat index, and Stull wet-bulb temperature.

Readme

psychrometrics

A tiny, zero-dependency Node library for humidity and moist-air math: saturation vapour pressure, dew point, relative and absolute humidity, the NOAA heat index, and Stull's wet-bulb temperature.

Every export is a pure function: no I/O, no network, no daemon, no dependencies, and no mutation of its arguments. The same inputs always give the same output. Everything is in SI-friendly units — degrees Celsius, percent RH, hectopascals (hPa == millibars), and grams per cubic metre.

Who it's for

Developers building HVAC, weather, or agriculture tools who need reliable moist-air numbers without pulling in a large scientific package or hitting an API:

  • an HVAC/indoor-climate app converting between temperature, RH, and dew point;
  • a weather dashboard showing "feels like" (heat index) and wet-bulb stress;
  • an agriculture / greenhouse model tracking condensation risk (dew point) and vapour density (absolute humidity).

Install / use

Copy the folder in, or require it directly — there is nothing to install.

const psy = require('./psychrometrics'); // path to this folder

psy.dewPoint(30, 50);               // → 18.45  (°C)
psy.saturationVaporPressure(20);    // → 23.33  (hPa)
psy.heatIndex(32, 70);              // → 40.4   (°C, "feels like")
psy.absoluteHumidity(20, 50);       // → 8.62   (g/m³)
psy.wetBulb(20, 50);                // → 13.70  (°C)

Run the tests

One command, offline, no framework:

node test/psychrometrics.test.js

It exits 0 on success and prints N passed, 0 failed. (Or npm test.)

API

All temperatures are °C, all relative humidity is percent (0..100), vapour pressure is hPa, absolute humidity is g/m³.

saturationVaporPressure(tempC) → hPa

Saturation vapour pressure of water over a flat liquid surface.

  • Formula: Magnus/Tetens form, es = 6.1094 · exp(17.625·T / (243.04 + T)), using the Alduchov & Eskridge (1996) "AERK" coefficients (J. Appl. Meteorol. 35, 601–609).
  • Accuracy: better than 0.4 % over roughly −40 °C … +50 °C.
  • Caveats: over ice (below 0 °C) the true saturation pressure is slightly lower than this over-liquid value; if you need frost-point work, use an over-ice coefficient set. Not valid far outside the fitted range.
  • Reference: es(0 °C) = 6.1094 hPa, es(20 °C) ≈ 23.3 hPa.

dewPoint(tempC, rhPct) → °C

Temperature to which the air must cool (at constant pressure and water content) to reach saturation.

  • Formula: analytic Magnus inverse of saturationVaporPressure, with the same AERK coefficients, so dewPoint and relativeHumidity are mutually consistent.
  • Domain: rhPct in [0, 100]. At 100 % the dew point equals the air temperature; at 0 % it is -Infinity (dry air never saturates on cooling).
  • Accuracy: inherits the < 0.4 % vapour-pressure fit; dew-point error is typically a few hundredths of a degree versus an exact inversion.
  • Reference: dewPoint(30, 50) ≈ 18.4 °C.

relativeHumidity(tempC, dewPointC) → %

Relative humidity from air temperature and dew point, as the ratio of saturation vapour pressure at the dew point to that at the air temperature.

  • Formula: 100 · es(dewPointC) / es(tempC).
  • Round-trip: relativeHumidity(T, dewPoint(T, rh)) ≈ rh to machine precision (verified in the tests).
  • Caveat: returns > 100 when dewPointC > tempC (supersaturation); that is intentional, not clamped, so callers can detect bad/edge inputs.

absoluteHumidity(tempC, rhPct) → g/m³

Mass of water vapour per cubic metre of air (vapour density).

  • Formula: ideal-gas law on the vapour partial pressure, AH = e / (Rv · T_K) with e = es(T)·RH/100 in Pa, Rv = 461.5 J/(kg·K), T_K = T + 273.15, result converted to g/m³.
  • Domain: rhPct in [0, 100]. Linear in RH at fixed temperature.
  • Caveat: treats vapour as an ideal gas (excellent at ambient conditions; small errors near boiling). Independent of barometric pressure, since it is a density, not a mixing ratio.
  • Reference: absoluteHumidity(20, 100) ≈ 17.3 g/m³ (saturated 20 °C air).

heatIndex(tempC, rhPct) → °C

Apparent "feels-like" temperature from heat and humidity.

  • Formula: NOAA/NWS Rothfusz regression. Computed internally in °F and returned in °C. Matching the NWS reference implementation, it first tries the simpler Steadman average; if that stays below 80 °F (≈ 27 °C) the heat index is essentially the air temperature and that value is returned. Otherwise the full 9-term polynomial is applied, followed by the two documented corrections — a low-RH subtraction (RH < 13 %, 80–112 °F) and a high-RH addition (RH > 85 %, 80–87 °F).
  • Valid range: the regression is fit for hot, humid conditions, roughly T ≳ 27 °C and RH ≳ 40 %. Outside that the returned value approaches the air temperature and should be read as "no meaningful heat stress," not as a precise apparent temperature. Heat index also assumes shade and light wind; direct sun can add up to ~8 °C.
  • Reference: heatIndex(32, 70) ≈ 40 °C (well above the 32 °C air temperature).

wetBulb(tempC, rhPct) → °C

Wet-bulb temperature: the lowest temperature reachable by evaporative cooling at the given humidity — a key metric for heat stress and cooling-tower design.

  • Formula: Stull (2011), "Wet-Bulb Temperature from Relative Humidity and Air Temperature", J. Appl. Meteorol. Climatol. 50, 2267–2269, an empirical closed-form fit (no iteration).
  • Valid range: standard sea-level pressure (1013.25 hPa), roughly −20 °C ≤ T ≤ 50 °C and 5 % ≤ RH ≤ 99 %, where it agrees with an exact psychrometric solver to about ±1 °C. Error grows at very low RH / very low temperature.
  • Caveat: not altitude-corrected — at high elevation (lower pressure) the true wet bulb is lower than this returns.
  • Reference: wetBulb(20, 50) ≈ 13.7 °C (Stull's worked example).

Domain guards

Inputs are validated so unit mistakes fail loudly instead of silently producing garbage:

  • Every numeric argument must be a finite number or a TypeError is thrown.
  • rhPct must be within [0, 100] percent or a RangeError is thrown. The library throws rather than clamps — a caller who accidentally passes a 0..1 fraction (or a percentage over 100) finds out immediately. The test suite covers this behaviour.

Honest limits

  • These are standard engineering approximations, not a full equation-of-state psychrometric solver. For most HVAC/weather/agriculture work they are well within measurement noise; for research-grade work near the edges of the stated ranges, use a dedicated reference implementation.
  • Saturation is computed over liquid water; sub-freezing frost-point work needs an over-ice variant.
  • heatIndex and wetBulb are empirical regressions valid in the ranges noted above; outside them they degrade gracefully but are not authoritative.

License

MIT.

Install

npm install @verifyhash/psychrometrics
const psy = require('@verifyhash/psychrometrics');

psy.dewPoint(30, 50);  // 18.45  (°C)
psy.heatIndex(32, 70); // 40.4   (°C, "feels like")
psy.wetBulb(20, 50);   // 13.70  (°C)