|
| 1 | +# Per-plot residual analysis on 12.3.9 (CSI_SCALE = 0.7): density-dependent calibration lever |
| 2 | + |
| 3 | +2026-05-28. The v27c, v29 input-based tests for BGI were null. v30 asks the |
| 4 | +orthogonal question via post-hoc residual regression: does any per-plot |
| 5 | +covariate predict the model's per-plot BA error well enough to support a |
| 6 | +fitted calibration factor? |
| 7 | + |
| 8 | +## Result |
| 9 | + |
| 10 | +100 ME FIA plots, 12.3.9 production posture (MORTCAL on, CutPoint = 0, |
| 11 | +CSI_SCALE = 0.7). 93 plots had complete covariate coverage. Univariate |
| 12 | +regressions on per-plot residual = BA_pred - BA_obs: |
| 13 | + |
| 14 | +| predictor | R^2 | adj R^2 | p-value | |
| 15 | +|--------------------------|---------|---------|---------| |
| 16 | +| BGI | 0.0006 | -0.011 | 0.82 | |
| 17 | +| log(BGI) | 0.0014 | -0.010 | 0.73 | |
| 18 | +| SICOND | 0.0015 | -0.010 | 0.72 | |
| 19 | +| ClimateSI_ft | 0.0077 | -0.003 | 0.40 | |
| 20 | +| **BA_t1** | **0.1877** | **0.1788** | **1.4e-5** | |
| 21 | +| BA_t1 + I(BA_t1^2) | 0.2390 | 0.2220 | 4.6e-6 | |
| 22 | +| BA_t1 + ClimateSI_ft | 0.1918 | 0.1739 | 6.9e-5 | |
| 23 | +| BA_t1 + BGI | 0.1891 | 0.1710 | 8.0e-5 | |
| 24 | + |
| 25 | +The clean finding: **BA_t1 (initial stand basal area) is the strongest single |
| 26 | +predictor of the model's per-plot residual.** It explains roughly 19 percent |
| 27 | +of residual variance with p = 1.4e-5. Adding a quadratic term lifts to 24 |
| 28 | +percent. BGI, SICOND, ClimateSI_ft add essentially nothing beyond BA_t1. |
| 29 | + |
| 30 | +## Fitted correction |
| 31 | + |
| 32 | + residual = 40.6345 - 0.3344 * BA_t1 (R^2 = 0.188, n = 93) |
| 33 | + |
| 34 | +The model overshoots low-density stands and undershoots high-density stands, |
| 35 | +with the crossover near BA_t1 = 121 ft^2/ac. |
| 36 | + |
| 37 | +| starting BA (ft^2/ac) | predicted overshoot | |
| 38 | +|-----------------------|----------------------| |
| 39 | +| 50 | +23.9 | |
| 40 | +| 90 | +10.5 | |
| 41 | +| 120 | +0.5 | |
| 42 | +| 180 | -19.6 | |
| 43 | + |
| 44 | +## Effect of applying the correction (in-sample) |
| 45 | + |
| 46 | +| metric | original | corrected | |
| 47 | +|-----------------------|-----------|-----------| |
| 48 | +| BA_pred mean | 107.26 | 96.60 | |
| 49 | +| BA_obs mean | 96.60 | 96.60 | |
| 50 | +| BA bias % | +11.04 | 0.00 | |
| 51 | +| R^2 (BA_pred vs obs) | 0.382 | **0.533** | |
| 52 | + |
| 53 | +BA bias closes to exactly zero (by construction) and per-plot R^2 lifts by |
| 54 | +0.15. The lever the entire BGI investigation was looking for is here, just |
| 55 | +not in BGI: it's in stand density. |
| 56 | + |
| 57 | +## Interpretation |
| 58 | + |
| 59 | +This is the signature of a density-dependent miscalibration in the dDBH or |
| 60 | +mortality equation. The Kuehne et al. 2020 diameter increment uses a BAL |
| 61 | +(basal area in larger trees) competition term. If the BAL coefficient is too |
| 62 | +weak, the model under-suppresses diameter growth in dense stands, which |
| 63 | +shows as overshoot in low-density stands (where BAL is small) and undershoot |
| 64 | +in high-density stands (where BAL is large) — exactly the pattern we see. |
| 65 | + |
| 66 | +Alternative explanation: the Glover/Hool mortality is missing density-dependent |
| 67 | +acceleration in dense stands, so high-density stands keep too many trees and |
| 68 | +their BA undershoots because the model is removing the wrong ones. |
| 69 | + |
| 70 | +Both stories are plausible; both are paper-sized refits. The post-hoc |
| 71 | +correction is the practical fix that ships now. |
| 72 | + |
| 73 | +## Why BGI was null even though density isn't |
| 74 | + |
| 75 | +BGI is fundamentally a remote-sensing measure of realized growth: a stand |
| 76 | +with high BGI grew faster than the model expected based on what was |
| 77 | +visible from the air. The model already sees stand density through BA_t1 |
| 78 | +explicitly (and through BAL inside the dDBH equation). So BGI is mostly |
| 79 | +proxying what the model already knows about density. The residual it |
| 80 | +could explain is what is left after density is accounted for, and |
| 81 | +within-stand productivity variation conditional on density is small on |
| 82 | +this sample. |
| 83 | + |
| 84 | +## What to ship |
| 85 | + |
| 86 | +Three nested options for the customRun bridge in 12.3.9 (no model code |
| 87 | +changes; just a post-projection multiplier on BA_pred): |
| 88 | + |
| 89 | + 1. **Linear**: BA_corrected = BA_pred - (40.6 - 0.334 * BA_t1). |
| 90 | + In-sample bias 0 percent, R^2 0.533. Risk: only validated on n = 93, |
| 91 | + could over-fit. |
| 92 | + |
| 93 | + 2. **Capped linear**: same formula but clamp the correction to within |
| 94 | + +/- 25 ft^2/ac so it can't introduce a worse error than the original |
| 95 | + baseline residual sd of 39 ft^2/ac. |
| 96 | + |
| 97 | + 3. **Hold off and refit BAL coefficient**. Re-fit the Kuehne BAL term |
| 98 | + against ME FIA. This is the paper-sized version; closes the bias at |
| 99 | + the equation level instead of post-hoc. |
| 100 | + |
| 101 | +The right autopilot move is option 2 with holdout validation. v31 will |
| 102 | +implement it as a bridge function `apply_density_correction(BA_pred, BA_t1)` |
| 103 | +and validate on a 50/50 holdout split of the v30 sample. |
| 104 | + |
| 105 | +## Files |
| 106 | + |
| 107 | +`cardinal_acadgy_residualcal_v30.R`, `acdgy_residualcal_v30_perplot.csv` |
| 108 | +(per-plot data), `acdgy_residualcal_v30_results.csv` (aggregate). Cardinal |
| 109 | +SLURM job 10968650. |
0 commit comments