--- title: "Diffusion capacity (DLCO / TLCO): reference, Hb correction, interpretation" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Diffusion capacity (DLCO / TLCO): reference, Hb correction, interpretation} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") library(pft) ``` Diffusion measurements (DLCO in traditional units, TLCO in SI) quantify gas-exchange capacity at the alveolar-capillary membrane. The sections below cover the reference values pft computes (`pft_diffusion()`, GLI 2017), the hemoglobin correction (`pft_dlco_hb_correct()`), and the Hughes & Pride categorical classifier (`pft_diffusion_interpret()`). # 1. Reference values `pft_diffusion()` implements the GLI 2017 standard (Stanojevic et al. ERJ 2017, with the 2020 author correction applied) for adults and children aged 5-90 years (the GLI calculator caps at 85; the underlying spline tables extend to 90). By default it emits **traditional units** (DLCO, KCO, VA in mL/min/mmHg, mL/min/mmHg/L, and L respectively); `SI.units = TRUE` switches to SI units (TLCO and KCO in mmol/min/kPa and mmol/min/kPa/L). VA is the same column either way. ```{r} patient <- data.frame( sex = "M", age = 45, height = 178, dlco_measured = 22.0, va_measured = 5.8, kco_tr_measured = 3.79 ) out <- pft_diffusion(patient) out[, grep("dlco|va|kco", colnames(out), value = TRUE)] ``` The output carries the same per-measure `_pred` / `_lln` / `_uln` / `_zscore` / `_pctpred` shape as `pft_spirometry()` and `pft_volumes()`. # 2. Hemoglobin correction DLCO measured against the standard reference Hb may misrepresent patients who are anemic (DLCO under-reads) or polycythemic (DLCO over-reads). `pft_dlco_hb_correct()` applies the Cotes 1972 formula to express the measured DLCO at the standard reference Hb: \[ \text{DLCO}_\text{adj} = \text{DLCO} \cdot \frac{1.7 \cdot \text{Hb}_\text{ref}}{\text{Hb} + 0.7 \cdot \text{Hb}_\text{ref}}. \] The reference Hb is age- and sex-dependent: 146 g/L for males aged >= 15, 134 g/L for females and for children < 15 of either sex (Cotes 1972 / Stanojevic 2017 Table 5). ```{r} # Anemic adult male: corrected DLCO is higher than measured. pft_dlco_hb_correct(dlco = 20.0, hemoglobin = 110, sex = "M", age = 45) # Polycythemic adult male: corrected is lower than measured. pft_dlco_hb_correct(dlco = 25.0, hemoglobin = 180, sex = "M", age = 45) ``` Pass `hemoglobin` in g/L (the package does not detect or convert g/dL inputs). **Apply the correction before computing z-scores** when comparing across patients whose Hb varies; the GLI 2017 reference values assume Hb is at the sex-/age-specific standard. # 3. Clinical sub-pattern (Hughes & Pride 2012) `pft_diffusion_interpret()` classifies a diffusion result into one of six clinical categories per the Hughes & Pride 2012 framework (adopted by the Stanojevic 2017 task force). The classifier uses z-scores only, so it works identically on traditional and SI columns: ```{r} mixed_cohort <- data.frame( dlco_zscore = c(-0.5, -2.0, -2.5, -2.5, -2.0, 0.0), va_zscore = c(-0.5, -0.5, -2.0, -2.5, -0.5, 0.0), kco_tr_zscore = c(-0.5, -2.0, 0.0, -2.5, 0.5, 2.0) ) pft_diffusion_interpret(mixed_cohort) ``` The decision tree (Stanojevic 2017 / Hughes & Pride 2012): | Category | DLCO | VA | KCO | |------------------------|------|----|-----| | **Normal** | OK | OK | OK | | **Parenchymal** | low | OK | low | | **Volume loss** | low | low | OK / high | | **Mixed** | low | low | low | | **Vascular (suggested)** | low | OK | low or high | | **Elevated KCO** | OK | -- | high | | **Other** | other combinations | | | Categories label the z-score pattern only. Hughes & Pride 2012 describes the differential diagnosis associated with each pattern; that interpretation is out of scope for the package. In `pft_interpret()` the classifier runs automatically whenever the diffusion z-score columns are present, so the `diffusion_category` column is attached for free in the standard workflow: ```{r} patient2 <- data.frame( sex = "F", age = 60, height = 165, race = "Caucasian", fev1_measured = 1.6, fvc_measured = 1.9, fev1fvc_measured = 0.84, tlc_measured = 4.0, dlco_measured = 10.0, va_measured = 3.5, kco_tr_measured = 2.86 ) r <- pft_interpret(patient2) r[, c("ats_classification", "diffusion_category")] ``` # 4. How VA shapes the classifier output Alveolar volume (VA) is the axis that splits restriction into the classifier's two volume-loss categories: * **Low VA, low KCO** -> labelled **Mixed** (both alveolar volume and per-alveolus gas exchange reduced). * **Low VA, normal-or-high KCO** -> labelled **Volume loss** (fewer alveoli, each exchanging gas normally per unit volume). These are descriptive labels for the z-score pattern; clinical interpretation of what underlies the pattern is the reader's job. # 5. Cohort-level diffusion summaries For cohort-level breakdowns of `diffusion_category`, group and count with `dplyr` directly on a `pft_interpret()` result: ```{r, eval = requireNamespace("dplyr", quietly = TRUE)} library(dplyr) cohort <- data.frame( sex = c("M","F","M","F","M","F"), age = c(45,60,30,55,70,28), height = c(178,165,175,160,170,180), race = "Caucasian", fev1_measured = c(2.5, 1.8, 4.0, 1.5, 2.2, 3.8), fvc_measured = c(3.8, 2.4, 5.2, 2.5, 3.5, 5.0), tlc_measured = c(6.0, 4.5, 6.8, 4.0, 6.5, 7.0), dlco_measured = c(20.0, 12.5, 28.0, 10.0, 18.0, 25.0), va_measured = c(5.8, 4.0, 6.5, 3.5, 5.5, 6.0), kco_tr_measured = c(3.5, 3.2, 4.3, 2.9, 3.3, 4.0) ) pft_interpret(cohort) |> count(sex, diffusion_category) ``` # See also * `vignette("interpretation-guide")` -- pattern decision tree and severity bands. * `vignette("longitudinal-analysis")` -- serial DLCO change and decline. * `?pft_diffusion`, `?pft_diffusion_interpret`, `?pft_dlco_hb_correct` for the function references.