Diagnostics - #10
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Introduces a GPR diagnostics/checkpointing API and replaces the previous single GPR unit test with broader tests covering diagnostics, core training/prediction behavior, and checkpoint save/load.
Changes:
- Added diagnostics utilities (LOO predictions/cross-validation + residual plotting) and corresponding unit tests.
- Added checkpoint save/load functions for trained GPR models (including normalization stats and training data) with unit tests.
- Reorganized exports via a new
SimulationSupport.gprpackage interface and removed the oldtest_gpr.py.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_gpr.py | Removed legacy GPR unit test file in favor of more granular coverage. |
| tests/test_diagnostics.py | Adds unit tests for new diagnostics helpers (LOO + residuals). |
| tests/test_core.py | Adds unit tests for core GPR behavior and checkpoint save/load round-trips. |
| src/SimulationSupport/gpr/diagnostics.py | New diagnostics module implementing LOO prediction/CV and residual plotting. |
| src/SimulationSupport/gpr/init.py | New package export surface for core + diagnostics. |
| src/SimulationSupport/gpr.py | Updates documentation/formatting and adds checkpoint save/load functions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def setUp(self): | ||
| self.df = make_df() | ||
|
|
||
| def tearDown(self): | ||
| plt.close("all") | ||
|
|
||
| def test_returns_four_outputs(self): | ||
| # Test that the function returns (X, Y, predictions_LOO, uncertainties_LOO) | ||
| result = loo_predictions( | ||
| self.df, | ||
| inputVar="initial_separation", | ||
| outputVar="initial_orbital_frequency", | ||
| ) | ||
| self.assertEqual(len(result), 4) | ||
|
|
||
| def test_output_types_are_arrays(self): | ||
| # Test that all four outputs are numpy arrays (and not lists or tensors) | ||
| X, Y, preds, uncertainties = loo_predictions( | ||
| self.df, | ||
| inputVar="initial_separation", | ||
| outputVar="initial_orbital_frequency", | ||
| ) | ||
| for arr in (X, Y, preds, uncertainties): | ||
| self.assertIsInstance(arr, np.ndarray) | ||
|
|
||
| def test_output_shapes_match_input(self): | ||
| # Test that each returned array has one entry per row in the DataFrame | ||
| X, Y, preds, uncertainties = loo_predictions( | ||
| self.df, | ||
| inputVar="initial_separation", | ||
| outputVar="initial_orbital_frequency", | ||
| ) | ||
| n = len(self.df) | ||
| for arr in (X, Y, preds, uncertainties): | ||
| self.assertEqual(arr.shape, (n,)) | ||
|
|
||
| def test_X_matches_input_column(self): | ||
| # Returned X should be exactly the values of the inputVar column | ||
| X, _, _, _ = loo_predictions( | ||
| self.df, | ||
| inputVar="initial_separation", | ||
| outputVar="initial_orbital_frequency", | ||
| ) | ||
| np.testing.assert_array_equal(X, self.df["initial_separation"].values) |
| def setUp(self): | ||
| """ | ||
| Train a model and save a checkpoint once for all tests in this class. | ||
| Individual tests inspect different aspects of the saved file. | ||
| """ | ||
| # Temporary directory | ||
| self.tmp_dir = tempfile.TemporaryDirectory() | ||
| self.ckpt_path = str(Path(self.tmp_dir.name) / "test_model.pt") | ||
|
|
||
| self.model, self.likelihood, self.features, self.X, self.Y = ( | ||
| _train_test_model() | ||
| ) | ||
| self.run_col = "initial_orbital_frequency" | ||
| self.pn_col = "spec_pn_guess_omega" | ||
|
|
||
| # Save once - all tests below read this file | ||
| save_gpr_checkpoint( | ||
| self.model, | ||
| self.likelihood, | ||
| self.features, | ||
| "omega", | ||
| self.run_col, | ||
| self.pn_col, | ||
| self.X, | ||
| self.Y, | ||
| self.ckpt_path, | ||
| ) | ||
|
|
||
| def tearDown(self): | ||
| # Temporary directory | ||
| self.tmp_dir.cleanup() |
| self.assertFalse(model.training) | ||
|
|
||
| def test_likelihood_in_eval_mode(self): | ||
| # Test lihelihood.training is False |
795ff5e to
99a78b8
Compare
bf62555 to
5d719fd
Compare
d45ce19 to
f6fbf68
Compare
|
@vtommasini for some reason the CI tests take forever and time out at 6 hours. Any idea what's happening? Doe the tests run quick on your machine? |
| [tool.pytest.ini_options] | ||
| testpaths = ["tests"] | ||
| addopts = "-ra" | ||
| python_files = ["Test_*.py", "test_*.py"] |
There was a problem hiding this comment.
These changes look like they revert a commit I added a while ago, probably accidentally during a rebase?
Simplified parallelization and tests, and decreased number of test_data points to make tests run faster Shortened tests, fixed multiprocessing hang in loo_crossval that was causing tests to time out
Functions to carry out leave-one-out cross validation for GPR model