Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { pow } from "./math_pow.ts"; ← from math.pow ^1.0.0 · built alongside by fune
import { roundFloat } from "./math_round_float.ts"; ← from math.round-float ^1.0.0 · built alongside by fune
import { type CreatinineUnit, type Egfr, type Sex } from "./health_egfr_types.ts";
/** Inker et al. 2021, footnote to table 2: mg/dL × 88.4 = µmol/L. */
const UMOL_PER_MG_DL = 88.4;
/**
* Estimated GFR by the CKD-EPI 2021 creatinine equation without race
* (Inker et al., NEJM 2021;385:1737-49, table 2):
*
* eGFR = 142 × min(Scr/κ, 1)^α × max(Scr/κ, 1)^-1.200 × 0.9938^age × 1.012 [if female]
*
* with Scr in mg/dL, κ 0.7 (female) or 0.9 (male), α -0.241 (female) or
* -0.302 (male). Powers go through math.pow so all three languages produce
* the same double; the whole-number result is rounded from the unrounded
* estimate, never from the one-decimal value (143.4993 is 143, not 144).
*/
export function egfrCkdEpi2021(creatinine: number, unit: CreatinineUnit, ageYears: number, sex: Sex): Egfr {
let low: number;
let high: number;
if (unit === "umol-per-l") {
low = 10;
high = 4000;
} else if (unit === "mg-per-dl") {
low = 0.1;
high = 45;
} else {
throw new RangeError(`unit must be umol-per-l or mg-per-dl, received ${unit}`);
}
if (typeof creatinine !== "number" || !Number.isFinite(creatinine) || creatinine < low || creatinine > high) {
throw new RangeError(`creatinine must be a number from ${low} to ${high} ${unit}, received ${creatinine}`);
}
if (!Number.isInteger(ageYears) || ageYears < 18 || ageYears > 120) {
throw new RangeError(`ageYears must be a whole number from 18 to 120, received ${ageYears}`);
}
if (sex !== "female" && sex !== "male") {
throw new RangeError(`sex must be female or male, received ${sex}`);
}
const female = sex === "female";
const scr = unit === "umol-per-l" ? creatinine / UMOL_PER_MG_DL : creatinine;
const kappa = female ? 0.7 : 0.9;
const alpha = female ? -0.241 : -0.302;
const ratio = scr / kappa;
// Below the knot the max() term is 1, above it the min() term is 1.
const creatinineTerm = ratio <= 1 ? pow(ratio, alpha) : pow(ratio, -1.2);
let estimate = 142 * creatinineTerm * pow(0.9938, ageYears);
if (female) estimate = estimate * 1.012;
return { value: roundFloat(estimate, 1), reported: roundFloat(estimate, 0) };
}