//! Calibration for [`wai::jpegai_pipeline::reconstruct_yhat`] — the SGMM //! autoregressive spine — on REAL `test256.bin` data: rebuild the synthesis-input //! latent `y_hat` from the reference's dequantized residual (`resi_dq_y`) and hyper //! params (`psi_y`), and compare against the reference `yhat_y`. //! //! This closes the last structural gap in the decode chain: entropy → dequant → //! **reconstruct** → synthesis. The float reference loop reproduces `yhat_y` to //! ~139 dB (float round-off); our Q16 integer MCM stages carry the 16-bit PTQ floor //! of the MCM nets themselves (~61–74 dB per stage), so we assert well above that. //! //! env: WAI_JPEGAI_RECON_FIXTURE = recon_fixture.json {resi_dq_y, psi_y, yhat_y, c, h2, w2} //! WAI_JPEGAI_MCM_WEIGHTS_DIR = dir with mcm_stage0..3_y.json #![cfg(all(feature = "neural_int", feature = "legacy_int"))] use wai::jpegai_pipeline::reconstruct_yhat; use wai::jpegai_synthesis::Weights; fn q16(f: &[f64]) -> Vec { f.iter().map(|&x| (x * 65536.0).round() as i64).collect() } #[test] fn reconstruct_yhat_on_real_reference_data() { let fx = match std::env::var("WAI_JPEGAI_RECON_FIXTURE") { Ok(p) if std::path::Path::new(&p).exists() => p, _ => { eprintln!("skip: set WAI_JPEGAI_RECON_FIXTURE"); return; } }; let wdir = match std::env::var("WAI_JPEGAI_MCM_WEIGHTS_DIR") { Ok(p) if std::path::Path::new(&p).exists() => p, _ => { eprintln!("skip: set WAI_JPEGAI_MCM_WEIGHTS_DIR"); return; } }; let v: serde_json::Value = serde_json::from_slice(&std::fs::read(&fx).unwrap()).unwrap(); let f64v = |k: &str| v[k].as_array().unwrap().iter().map(|x| x.as_f64().unwrap()).collect::>(); let (c, h2, w2) = ( v["c"].as_u64().unwrap() as usize, v["h2"].as_u64().unwrap() as usize, v["w2"].as_u64().unwrap() as usize, ); let resi = q16(&f64v("resi_dq_y")); let psi = q16(&f64v("psi_y")); let yhat_ref = f64v("yhat_y"); let load = |i: usize| -> Weights { let raw = std::fs::read(format!("{wdir}/mcm_stage{i}_y.json")).unwrap(); Weights::from_json(&serde_json::from_slice(&raw).unwrap()).unwrap() }; let (w0, w1, w2w, w3) = (load(0), load(1), load(2), load(3)); let got = reconstruct_yhat(&resi, &psi, c, h2, w2, [&w0, &w1, &w2w, &w3]); assert_eq!(got.len(), yhat_ref.len(), "y_hat size mismatch"); let (mut maxd, mut se, mut sig) = (0f64, 0f64, 0f64); for i in 0..got.len() { let g = got[i] as f64 / 65536.0; let r = yhat_ref[i]; let d = (g - r).abs(); maxd = maxd.max(d); se += d * d; sig += r * r; } let snr = 10.0 * (sig / se).log10(); eprintln!("reconstruct_yhat on real data: max|Δ| = {maxd:.5} SNR = {snr:.2} dB"); assert!(snr > 45.0, "SGMM reconstruction regressed (SNR {snr:.2} dB)"); }