From 2429b275fd30bbf05fc4dcd995e2080a3d2f5356 Mon Sep 17 00:00:00 2001 From: jigyasaba Date: Fri, 20 Feb 2026 14:32:07 +0530 Subject: [PATCH 1/4] Remove outdated TODO block for performance metrics in parallel validation test --- gwlearn/tests/test_base.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/gwlearn/tests/test_base.py b/gwlearn/tests/test_base.py index 02f4b451..8662ac7e 100644 --- a/gwlearn/tests/test_base.py +++ b/gwlearn/tests/test_base.py @@ -1653,11 +1653,6 @@ def test_regressor_n_jobs_consistency(sample_regression_data): rtol=1e-5, ) - # TODO: Check that performance metrics are also equal - # assert reg_sequential.focal_score_ == pytest.approx(reg_parallel.focal_score_) - # assert reg_sequential.mae_ == pytest.approx(reg_parallel.mae_) - # assert reg_sequential.mse_ == pytest.approx(reg_parallel.mse_) - # Check that global models have the same coefficients np.testing.assert_allclose( reg_sequential.global_model.coef_, From d763d795644a88f5629668fedb376d1bbe306911 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 17:30:47 -0400 Subject: [PATCH 2/4] [pre-commit.ci] pre-commit autoupdate (#115) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8079fcef..cf4acc10 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ --- repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.14.10" + rev: "v0.15.9" hooks: - id: ruff-check files: "gwlearn\/|docs\/" From aeea7bf432a4498bea60f4c29b208bb5de97056a Mon Sep 17 00:00:00 2001 From: jigyasaba Date: Wed, 8 Apr 2026 17:51:29 +0530 Subject: [PATCH 3/4] test: add coverage for predict, predict_proba, and keep_models behavior in GWLogisticRegression --- gwlearn/tests/test_linear_model.py | 70 ++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/gwlearn/tests/test_linear_model.py b/gwlearn/tests/test_linear_model.py index eb390f8f..ea5ba7c0 100644 --- a/gwlearn/tests/test_linear_model.py +++ b/gwlearn/tests/test_linear_model.py @@ -279,3 +279,73 @@ def test_against_mgwr(): assert_almost_equal(gwlr.aicc_, res.aicc, decimal=0) assert_almost_equal(gwlr.effective_df_, res.ENP) assert_almost_equal(gwlr.log_likelihood_, res.llf) + +def test_gwlogistic_predict(sample_data): + # Unpack sample dataset (features, target, spatial geometry) + X, y, geometry = sample_data + + # Initialize model with keep_models=True (required for prediction) + model = GWLogisticRegression( + bandwidth=10, + fixed=False, + keep_models=True, + max_iter=1000, + ) + + # Fit geographically weighted logistic model + model.fit(X, y, geometry=geometry) + + # Generate predictions using fitted local models + preds = model.predict(X,geometry=geometry) + + # Assert: number of predictions matches number of input samples + assert len(preds) == len(X) + + # Assert: predictions are valid binary outputs (0/1 or True/False) + assert set(np.unique(preds.dropna())).issubset({0, 1}) + + # Ensure predictions are not all NaN + assert not preds.isna().all() + +def test_gwlogistic_predict_proba(sample_data): + # Unpack sample dataset + X, y, geometry = sample_data + + # Initialize model with keep_models=True for probability prediction + model = GWLogisticRegression( + bandwidth=10, + fixed=False, + keep_models=True, + max_iter=1000, + ) + + # Fit model + model.fit(X, y, geometry=geometry) + + # Get class probability predictions + proba = model.predict_proba(X, geometry=geometry) + + # Assert: number of rows equals number of samples + assert proba.shape[0] == len(X) + + # Assert: binary classification → exactly 2 probability columns + assert proba.shape[1] == 2 + + +def test_predict_requires_keep_models(sample_data): + # Unpack sample dataset + X, y, geometry = sample_data + + # Initialize model WITHOUT storing local models + model = GWLogisticRegression( + bandwidth=10, + fixed=False, + keep_models=False, + max_iter=1000 + ) + #Fit model + model.fit(X, y, geometry=geometry) + + # prediction requires stored local models → should fail + with pytest.raises(AttributeError,match="_local_models"): + model.predict(X, geometry=geometry) From dcd2b56e1fde60815be04e0c42897d1152892164 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 12:52:35 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- gwlearn/tests/test_linear_model.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/gwlearn/tests/test_linear_model.py b/gwlearn/tests/test_linear_model.py index ea5ba7c0..d021f6f8 100644 --- a/gwlearn/tests/test_linear_model.py +++ b/gwlearn/tests/test_linear_model.py @@ -280,6 +280,7 @@ def test_against_mgwr(): assert_almost_equal(gwlr.effective_df_, res.ENP) assert_almost_equal(gwlr.log_likelihood_, res.llf) + def test_gwlogistic_predict(sample_data): # Unpack sample dataset (features, target, spatial geometry) X, y, geometry = sample_data @@ -296,17 +297,18 @@ def test_gwlogistic_predict(sample_data): model.fit(X, y, geometry=geometry) # Generate predictions using fitted local models - preds = model.predict(X,geometry=geometry) + preds = model.predict(X, geometry=geometry) # Assert: number of predictions matches number of input samples assert len(preds) == len(X) # Assert: predictions are valid binary outputs (0/1 or True/False) assert set(np.unique(preds.dropna())).issubset({0, 1}) - + # Ensure predictions are not all NaN assert not preds.isna().all() + def test_gwlogistic_predict_proba(sample_data): # Unpack sample dataset X, y, geometry = sample_data @@ -338,14 +340,11 @@ def test_predict_requires_keep_models(sample_data): # Initialize model WITHOUT storing local models model = GWLogisticRegression( - bandwidth=10, - fixed=False, - keep_models=False, - max_iter=1000 + bandwidth=10, fixed=False, keep_models=False, max_iter=1000 ) - #Fit model + # Fit model model.fit(X, y, geometry=geometry) # prediction requires stored local models → should fail - with pytest.raises(AttributeError,match="_local_models"): + with pytest.raises(AttributeError, match="_local_models"): model.predict(X, geometry=geometry)