Download analysis/code/test_composite_model.py from ekwan16/MagNET: direct link, hf CLI and curl.
- Browser
- Download file 5.93 kB
-
https://huggingface.co/ekwan16/MagNET/resolve/fe222d1894afb2d954fe8d2e67e70731a006c8d2/analysis/code/test_composite_model.py
- Command line
-
hf download hf://ekwan16/MagNET@fe222d1894afb2d954fe8d2e67e70731a006c8d2/analysis/code/test_composite_model.py
-
curl -L -o test_composite_model.py https://huggingface.co/ekwan16/MagNET/resolve/fe222d1894afb2d954fe8d2e67e70731a006c8d2/analysis/code/test_composite_model.py
5.93 kB
| """Tests for build_composite_model.py: the composite_model/ group in applications.hdf5 reproduces | |
| from the shipped delta-22 data, so the natural-products coefficients need no private tree or | |
| environment variables. Skipped when the large hdf5 files are absent.""" | |
| import os | |
| import random | |
| import sys | |
| import numpy as np | |
| import pytest | |
| HERE = os.path.dirname(os.path.abspath(__file__)) | |
| REPO = os.path.abspath(os.path.join(HERE, "..", "..")) | |
| for _p in ("analysis/code", "analysis/code/shared", "data/delta22", "data/applications"): | |
| sys.path.insert(0, os.path.join(REPO, _p)) | |
| import build_composite_model as B # noqa: E402 | |
| import paths # noqa: E402 | |
| DELTA22 = paths.dataset_file("delta22", root=REPO) | |
| APPLICATIONS = paths.dataset_file("applications", root=REPO) | |
| _HAVE_DATA = os.path.exists(DELTA22) and os.path.exists(APPLICATIONS) | |
| # The fixed-point integer encoding (int32 x 1e4) sets the reproduction floor; recipe errors are ~1. | |
| ENCODING_TOL = 5e-3 | |
| def _reader(): | |
| from applications_reader import Applications | |
| return Applications(APPLICATIONS) | |
| def test_ols_and_pcm_reproduce(): | |
| """Every OLS formula (all solvents, both nuclei) and both PCM-conversion tables reproduce.""" | |
| reader = _reader() | |
| full_tab, _fit_tab, _apply_tab, factors = B._load_tables() | |
| worst = 0.0 | |
| for formula in reader.composite_formulas("ols_coefficients"): | |
| regressors = B._regressor_columns(formula) | |
| for reg in regressors: | |
| B._ensure_column(full_tab, reg) | |
| for nucleus in ("H", "C"): | |
| stored = reader.ols_coefficients(formula, nucleus).set_index("parameter") | |
| for solvent in stored.columns: | |
| sub = full_tab[(full_tab["nucleus"] == nucleus) & (full_tab["solvent"] == solvent)] | |
| got = B._decompose(B._fit(sub, regressors), regressors, solvent, nucleus, factors) | |
| worst = max(worst, max(abs(float(stored.loc[p, solvent]) - got[p]) for p in stored.index)) | |
| assert worst < ENCODING_TOL, f"OLS max diff {worst}" | |
| for nucleus in ("H", "C"): | |
| stored = reader.pcm_conversion_factors(nucleus).set_index("solvent")["pcm_conversion_factor"] | |
| got = B._pcm_table(factors, nucleus).set_index("solvent")["pcm_conversion_factor"] | |
| assert np.abs(got - stored.reindex(got.index)).max() < 1e-9 | |
| def test_bootstrap_and_rmse_reproduce(): | |
| """Bootstrap coefficients and RMSE distributions reproduce on a sample of seeds (the fixed-seed | |
| resampler makes every seed deterministic, so a sample is representative). This is the fast CI | |
| check; build_composite_model.main() re-fits all 1000 seeds and is the authoritative full pass.""" | |
| reader = _reader() | |
| _full_tab, fit_tab, apply_tab, factors = B._load_tables() | |
| seeds = range(0, 1000, 97) | |
| worst = 0.0 | |
| for formula in reader.composite_formulas("bootstrap_coefficients"): | |
| regressors = B._regressor_columns(formula) | |
| for reg in regressors: | |
| B._ensure_column(fit_tab, reg) | |
| for nucleus in ("H", "C"): | |
| try: | |
| stored = reader.bootstrap_coefficients(formula, nucleus) | |
| except KeyError: | |
| continue | |
| params = [c for c in stored.columns if c not in ("solvent", "seed")] | |
| for solvent in stored["solvent"].unique(): | |
| for seed in seeds: | |
| row = stored[(stored["solvent"] == solvent) & (stored["seed"] == seed)] | |
| if not len(row): | |
| continue | |
| got = B._decompose(B._fit(B._bootstrap_sample(fit_tab, nucleus, solvent, seed), | |
| regressors), regressors, solvent, nucleus, factors) | |
| for p in params: | |
| key = "intercept" if p == "Intercept" else p | |
| worst = max(worst, abs(float(row[p].iloc[0]) - got[key])) | |
| assert worst < ENCODING_TOL, f"bootstrap max diff {worst}" | |
| worst = 0.0 | |
| for nucleus in ("H", "C"): | |
| stored = reader.rmse_distribution(nucleus) | |
| for formula in stored["formula"].unique(): | |
| sub = stored[stored["formula"] == formula] | |
| for solvent in sub["solvent"].unique(): | |
| for seed in seeds: | |
| row = sub[(sub["solvent"] == solvent) & (sub["seed"] == seed)] | |
| if not len(row): | |
| continue | |
| got = B._rmse(fit_tab, apply_tab, formula, nucleus, solvent, seed, factors) | |
| worst = max(worst, abs(float(row["Bootstrap_RMSE"].iloc[0]) - got)) | |
| assert worst < ENCODING_TOL, f"rmse max diff {worst}" | |
| def test_bootstrap_is_deterministic(): | |
| """The resampler reseeds internally, so a given seed draws the same solutes no matter the | |
| external RNG state going in.""" | |
| fit_tab = B._load_tables()[1] | |
| random.seed(123) | |
| a = B._bootstrap_sample(fit_tab, "C", "chloroform", 7) | |
| random.seed(456) | |
| b = B._bootstrap_sample(fit_tab, "C", "chloroform", 7) | |
| assert list(a["solute"]) == list(b["solute"]) | |
| def test_write_roundtrips(tmp_path): | |
| """write() serializes the regenerated tables into an hdf5 file that reads back unchanged through | |
| Applications, so --write cannot silently corrupt the shipped file's composite_model group.""" | |
| from applications_reader import Applications | |
| regenerated = B.regenerate(_reader()) | |
| scratch = str(tmp_path / "cm.hdf5") | |
| B.write(scratch, regenerated) | |
| worst = B.verify(Applications(scratch), regenerated) | |
| assert worst < 1e-6, f"write/read round-trip diff {worst}" | |