--- title: "Original Source Code (V1)" author: "Bill Denney" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Original Source Code (V1)} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` Below is the original Visual Basic source code for the V1 class-based EQUIL-2 module (`clsEquil2`), the basis of the `equil2_v1()` function in this package. It is included to allow users to inspect the fidelity of the code translation. This program is intended for research use, only. The code within is translated from Visual Basic code based on Werness, et al 1985 to R. The Visual Basic code was kindly provided by Dr. John Lieske of the Mayo Clinic and shared on the equil2 issue tracker by Lea Lerose ([issue #2](https://github.com/billdenney/equil2/issues/2)). # Reference Werness PG, Brown CM, Smith LH, Finlayson B. Equil2: A Basic Computer Program for the Calculation of Urinary Saturation. Journal of Urology. 1985;134(6):1242-1244. doi:10.1016/S0022-5347(17)47703-2 # How V1 differs from V5 The V5 form-based BASIC source (in `vignette("original-source")`) is a stripped-down version of V1. V1 adds several pathways that V5 omits: - **CO2 / bicarbonate / carbonate** chemistry (H2CO3, HCO3, CO3, plus the Na2CO3 / CaCO3 / MgCO3 complexes). - **TRIS buffer** (HTRIS). - **Pyrophosphate (PP)** speciation — though, see the caveat below. - **Struvite (MgNH4PO4)** included in the Mg and NH4 mass balances (V5 computes struvite SS but does not feed it back into the balances). - **Sodium-urate, ammonium-urate, and potassium-urate** complexes included in the Na/NH4/K mass balances (V5 reports their SS but does not couple them back into the cation balance). - **Chloride auto-fill** via electroneutrality when no chloride is supplied (V5 requires a chloride input). - **Inputs in mmol per collection volume** (V1) vs **mg/dL** (V5). V1's approach is unit-unambiguous and does not need per-species atomic-weight conversion factors — see issue #2 for why this matters. V1 and V5 share the same stability constants for the core CaOx / Brushite / HAP / Uric Acid / Sodium-urate / Ammonium-urate pathways. The constants that differ are concentrated in the CO2 / PP / HU pathways that V5 doesn't use anyway (e.g. P7 for CO2 dissociation is 0.00229 in V1 vs 0.00123 in V5; the HU formation constant is `7.943e10` in V1 vs `2.78e5` in V5). V1 reports **activity products** (`APCaOx`, `APBr`, `APStru`, `APUA`, `APNaU`) and **relative saturation ratios** (RSR = AP / Ksp) for **Calcium Oxalate, Brushite, Struvite, and Uric Acid** only. V5 additionally reports SS values for **Hydroxyapatite, Sodium Urate, and Ammonium Urate**, plus a negative ΔGibbs energy for each. For those V5-only outputs use the `equil2()` function. V1's iteration loop is capped at **500** iterations (vs 50 in V5) and raises a warning on non-convergence. # Quirks preserved by the R port Three quirks of the V1 source are preserved verbatim in `equil2_v1()` for fidelity: 1. **Pyrophosphate is disabled.** After reading the input, V1 unconditionally sets `TPP = 0` and `PP = 0`, which short-circuits the entire pyrophosphate pathway. The R port keeps this; users who want PP chemistry can edit the two `TPP <- 0` / `PP_var <- 0` lines in `R/equil2_v1.R`. 2. **`NH4PO4` is uninitialized.** V1 declares `Dim NH4PO4 As Double` but never assigns it, so it is always zero (VBA default). In the R port we make this explicit with `NH4PO4 <- 0`. 3. **Urate-cation complexes (`NaU`, `KU`, `NH4U`) are not in the cation mass balance.** V1 computes them and uses them for ionic strength and for the chloride electroneutrality auto-fill, but `STNa` / `STK` / `STNH4` do *not* include them. Effectively V1 treats them as trace species that don't deplete free Na, K, or NH4. The R port matches this. # Numerical verification against the V1 VBA module The R port has been cross-validated against the original VBA module by running `clsEquil2.bas` in LibreOffice 26.2.4 with `Option VBASupport 1` and `Option ClassModule`, using LibreOffice's Python UNO bridge to drive the Calc method. On the LabCorp inputs in the package examples, ionic strength agrees to <1 ppm and the four reported activity products / relative saturation ratios agree to ~10 ppm. The residual differences are floating-point reordering noise from how mass-balance sums are grouped in R vs the original BASIC. # EQUIL-2 V1 source The code below is the basis of the `equil2_v1()` function. ```{r v1-source, echo=FALSE, results='asis'} src_path <- system.file("clsEquil2.bas.txt", package = "equil2") if (!nzchar(src_path)) { # Fall back to the inst/ source if not yet installed # (e.g. devtools::build_vignettes() before install). src_path <- file.path("..", "inst", "clsEquil2.bas.txt") } cat("```vb\n") cat(readLines(src_path), sep = "\n") cat("\n```\n") ```