Skip to content

Commit b1f5fa0

Browse files
Morten Taborclaude
andcommitted
Fix ruff lint and format errors from Andrews-Ploberger commit
Sort imports and __all__ entries to satisfy ruff I001 and RUF022 rules across 4 source files. Apply ruff format to 3 files with formatting drift. All 718 tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent efb2d45 commit b1f5fa0

File tree

7 files changed

+71
-67
lines changed

7 files changed

+71
-67
lines changed

src/regimes/__init__.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@
4040
ARResults,
4141
BaiPerronResults,
4242
BaiPerronTest,
43+
BreakResultsBase,
44+
ChowTest,
45+
ChowTestResults,
46+
CovType,
4347
CUSUMResults,
4448
CUSUMSQResults,
4549
CUSUMSQTest,
4650
CUSUMTest,
47-
ChowTest,
48-
ChowTestResults,
49-
BreakResultsBase,
50-
CovType,
5151
DiagnosticsResults,
5252
DiagnosticTestResult,
5353
OLSResults,
@@ -77,8 +77,8 @@
7777
plot_breaks,
7878
plot_cusum,
7979
plot_cusum_sq,
80-
plot_f_sequence,
8180
plot_diagnostics,
81+
plot_f_sequence,
8282
plot_params_over_time,
8383
plot_regime_means,
8484
plot_residual_acf,
@@ -93,18 +93,18 @@
9393
"AR",
9494
"OLS",
9595
"ADLResults",
96+
"ARResults",
9697
"AndrewsPlobergerResults",
9798
"AndrewsPlobergerTest",
98-
"ARResults",
9999
"BaiPerronResults",
100100
"BaiPerronTest",
101+
"BreakResultsBase",
101102
"CUSUMResults",
102103
"CUSUMSQResults",
103104
"CUSUMSQTest",
104105
"CUSUMTest",
105106
"ChowTest",
106107
"ChowTestResults",
107-
"BreakResultsBase",
108108
"CovType",
109109
"DiagnosticTestResult",
110110
"DiagnosticsResults",

src/regimes/api.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@
5656
AndrewsPlobergerTest,
5757
BaiPerronResults,
5858
BaiPerronTest,
59+
ChowTest,
60+
ChowTestResults,
5961
CUSUMResults,
6062
CUSUMSQResults,
6163
CUSUMSQTest,
6264
CUSUMTest,
63-
ChowTest,
64-
ChowTestResults,
6565
)
6666

6767
# Visualization
@@ -71,8 +71,8 @@
7171
plot_breaks,
7272
plot_cusum,
7373
plot_cusum_sq,
74-
plot_f_sequence,
7574
plot_diagnostics,
75+
plot_f_sequence,
7676
plot_params_over_time,
7777
plot_regime_means,
7878
plot_residual_acf,
@@ -84,24 +84,21 @@
8484
__all__ = [
8585
"ADL",
8686
"AR",
87-
# Models
8887
"OLS",
8988
"ADLResults",
89+
"ARResults",
9090
"AndrewsPlobergerResults",
9191
"AndrewsPlobergerTest",
92-
"ARResults",
9392
"BaiPerronResults",
94-
# Tests
9593
"BaiPerronTest",
94+
"BreakResultsBase",
9695
"CUSUMResults",
9796
"CUSUMSQResults",
9897
"CUSUMSQTest",
9998
"CUSUMTest",
10099
"ChowTest",
101100
"ChowTestResults",
102-
"BreakResultsBase",
103101
"CovType",
104-
# Diagnostics
105102
"DiagnosticTestResult",
106103
"DiagnosticsResults",
107104
"OLSResults",
@@ -111,7 +108,6 @@
111108
"RecursiveARResults",
112109
"RecursiveOLS",
113110
"RecursiveOLSResults",
114-
# Base classes
115111
"RegimesModelBase",
116112
"RegimesResultsBase",
117113
"RegressionResultsBase",
@@ -121,7 +117,6 @@
121117
"RollingARResults",
122118
"RollingCovType",
123119
"RollingEstimatorBase",
124-
# Rolling/Recursive estimation
125120
"RollingOLS",
126121
"RollingOLSResults",
127122
"RollingResultsBase",
@@ -130,12 +125,11 @@
130125
"ar_summary_by_regime",
131126
"plot_actual_fitted",
132127
"plot_break_confidence",
133-
# Visualization
134128
"plot_breaks",
135-
"plot_f_sequence",
136129
"plot_cusum",
137130
"plot_cusum_sq",
138131
"plot_diagnostics",
132+
"plot_f_sequence",
139133
"plot_params_over_time",
140134
"plot_regime_means",
141135
"plot_residual_acf",

src/regimes/tests/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
"""Structural break tests."""
22

3-
from regimes.tests.andrews_ploberger import AndrewsPlobergerResults, AndrewsPlobergerTest
3+
from regimes.tests.andrews_ploberger import (
4+
AndrewsPlobergerResults,
5+
AndrewsPlobergerTest,
6+
)
47
from regimes.tests.bai_perron import BaiPerronResults, BaiPerronTest
58
from regimes.tests.base import BreakTestBase, BreakTestResultsBase
69
from regimes.tests.chow import ChowTest, ChowTestResults

src/regimes/tests/andrews_ploberger.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,9 @@ class AndrewsPlobergerResults(BreakTestResultsBase):
338338
exp_f_pvalue: float = np.nan
339339
ave_f_pvalue: float = np.nan
340340
f_sequence: np.ndarray = field(default_factory=lambda: np.array([]))
341-
candidate_indices: np.ndarray = field(default_factory=lambda: np.array([], dtype=int))
341+
candidate_indices: np.ndarray = field(
342+
default_factory=lambda: np.array([], dtype=int)
343+
)
342344
sup_f_break_index: int = 0
343345
trimming: float = 0.15
344346
q: int = 0
@@ -451,8 +453,7 @@ def summary(self) -> str:
451453
lines.append("-" * 78)
452454
n_rejected = sum(1 for v in self.rejected.values() if v)
453455
lines.append(
454-
f"\nRejected H0 for {n_rejected} of 3 statistics "
455-
f"at the {alpha:.0%} level"
456+
f"\nRejected H0 for {n_rejected} of 3 statistics at the {alpha:.0%} level"
456457
)
457458
lines.append("=" * 78)
458459
return "\n".join(lines)
@@ -834,9 +835,7 @@ def fit(
834835
# ExpF: use log-sum-exp trick for numerical stability
835836
half_f = 0.5 * f_sequence
836837
max_half_f = np.max(half_f)
837-
exp_f = float(
838-
max_half_f + np.log(np.mean(np.exp(half_f - max_half_f)))
839-
)
838+
exp_f = float(max_half_f + np.log(np.mean(np.exp(half_f - max_half_f))))
840839

841840
# Break location
842841
sup_f_break_index = int(candidate_indices[np.argmax(f_sequence)])

src/regimes/visualization/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
__all__ = [
3333
"REGIMES_COLORS",
3434
"REGIMES_COLOR_CYCLE",
35-
"plot_f_sequence",
3635
"add_break_dates",
3736
"add_confidence_band",
3837
"add_source",
@@ -44,6 +43,7 @@
4443
"plot_cusum",
4544
"plot_cusum_sq",
4645
"plot_diagnostics",
46+
"plot_f_sequence",
4747
"plot_params_over_time",
4848
"plot_regime_means",
4949
"plot_residual_acf",

src/regimes/visualization/andrews_ploberger.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,7 @@ def plot_f_sequence(
116116
)
117117

118118
# Zero line
119-
ax.axhline(
120-
y=0, color=REGIMES_COLORS["near_black"], linewidth=0.5, alpha=0.3
121-
)
119+
ax.axhline(y=0, color=REGIMES_COLORS["near_black"], linewidth=0.5, alpha=0.3)
122120

123121
ax.set_title(title or "Andrews-Ploberger F-statistic sequence")
124122
ax.set_xlabel(xlabel)

tests/test_tests/test_andrews_ploberger.py

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,12 @@ def test_break_location_near_truth(
5454

5555
def test_strong_break_rejects(self, rng: np.random.Generator) -> None:
5656
"""A very large mean shift should be detected by all three statistics."""
57-
y = np.concatenate([
58-
rng.standard_normal(100),
59-
rng.standard_normal(100) + 10,
60-
])
57+
y = np.concatenate(
58+
[
59+
rng.standard_normal(100),
60+
rng.standard_normal(100) + 10,
61+
]
62+
)
6163

6264
test = AndrewsPlobergerTest(y)
6365
results = test.fit()
@@ -122,10 +124,12 @@ def test_sup_f_geq_ave_f(
122124

123125
def test_large_for_strong_break(self, rng: np.random.Generator) -> None:
124126
"""Statistics should be large for a strong break."""
125-
y = np.concatenate([
126-
rng.standard_normal(100),
127-
rng.standard_normal(100) + 10,
128-
])
127+
y = np.concatenate(
128+
[
129+
rng.standard_normal(100),
130+
rng.standard_normal(100) + 10,
131+
]
132+
)
129133

130134
test = AndrewsPlobergerTest(y)
131135
results = test.fit()
@@ -243,9 +247,7 @@ def test_critical_values_increasing_with_alpha(
243247
]:
244248
assert cv_dict[0.10] < cv_dict[0.05] < cv_dict[0.01]
245249

246-
def test_critical_values_vary_with_trimming(
247-
self, rng: np.random.Generator
248-
) -> None:
250+
def test_critical_values_vary_with_trimming(self, rng: np.random.Generator) -> None:
249251
"""Critical values should differ for different trimming fractions."""
250252
y = rng.standard_normal(200)
251253

@@ -281,9 +283,9 @@ def test_small_pvalues_for_break(
281283
results = test.fit()
282284

283285
# At least one p-value should be small
284-
assert min(
285-
results.sup_f_pvalue, results.exp_f_pvalue, results.ave_f_pvalue
286-
) < 0.10
286+
assert (
287+
min(results.sup_f_pvalue, results.exp_f_pvalue, results.ave_f_pvalue) < 0.10
288+
)
287289

288290
def test_large_pvalues_for_no_break(self, rng: np.random.Generator) -> None:
289291
"""P-values should be large when there is no break."""
@@ -297,10 +299,12 @@ def test_large_pvalues_for_no_break(self, rng: np.random.Generator) -> None:
297299

298300
def test_pvalues_consistent_with_cvs(self, rng: np.random.Generator) -> None:
299301
"""P-values should be consistent with critical value comparison."""
300-
y = np.concatenate([
301-
rng.standard_normal(100),
302-
rng.standard_normal(100) + 5,
303-
])
302+
y = np.concatenate(
303+
[
304+
rng.standard_normal(100),
305+
rng.standard_normal(100) + 5,
306+
]
307+
)
304308

305309
test = AndrewsPlobergerTest(y)
306310
results = test.fit()
@@ -336,9 +340,7 @@ def test_various_trimming_values(
336340
assert results.trimming == trimming
337341
assert len(results.f_sequence) > 0
338342

339-
def test_narrower_trimming_more_candidates(
340-
self, rng: np.random.Generator
341-
) -> None:
343+
def test_narrower_trimming_more_candidates(self, rng: np.random.Generator) -> None:
342344
"""Narrower trimming should produce more candidate dates."""
343345
y = rng.standard_normal(200)
344346

@@ -578,10 +580,12 @@ class TestEdgeCases:
578580

579581
def test_small_sample(self, rng: np.random.Generator) -> None:
580582
"""Test with a small sample."""
581-
y = np.concatenate([
582-
rng.standard_normal(30),
583-
rng.standard_normal(30) + 5,
584-
])
583+
y = np.concatenate(
584+
[
585+
rng.standard_normal(30),
586+
rng.standard_normal(30) + 5,
587+
]
588+
)
585589

586590
test = AndrewsPlobergerTest(y)
587591
results = test.fit(trimming=0.15)
@@ -608,10 +612,12 @@ def test_partial_break(self, rng: np.random.Generator) -> None:
608612

609613
def test_strong_break_all_reject(self, rng: np.random.Generator) -> None:
610614
"""Very strong break should cause all three statistics to reject."""
611-
y = np.concatenate([
612-
rng.standard_normal(100),
613-
rng.standard_normal(100) + 10,
614-
])
615+
y = np.concatenate(
616+
[
617+
rng.standard_normal(100),
618+
rng.standard_normal(100) + 10,
619+
]
620+
)
615621

616622
test = AndrewsPlobergerTest(y)
617623
results = test.fit()
@@ -620,10 +626,12 @@ def test_strong_break_all_reject(self, rng: np.random.Generator) -> None:
620626

621627
def test_constant_only_model(self, rng: np.random.Generator) -> None:
622628
"""Test with default constant-only (mean-shift) model."""
623-
y = np.concatenate([
624-
rng.standard_normal(100),
625-
rng.standard_normal(100) + 3,
626-
])
629+
y = np.concatenate(
630+
[
631+
rng.standard_normal(100),
632+
rng.standard_normal(100) + 3,
633+
]
634+
)
627635

628636
test = AndrewsPlobergerTest(y)
629637
results = test.fit()
@@ -669,10 +677,12 @@ def test_plot_f_sequence_function(self, rng: np.random.Generator) -> None:
669677
"""Test the standalone plot_f_sequence function."""
670678
import matplotlib.pyplot as plt
671679

672-
y = np.concatenate([
673-
rng.standard_normal(100),
674-
rng.standard_normal(100) + 3,
675-
])
680+
y = np.concatenate(
681+
[
682+
rng.standard_normal(100),
683+
rng.standard_normal(100) + 3,
684+
]
685+
)
676686

677687
test = AndrewsPlobergerTest(y)
678688
results = test.fit()

0 commit comments

Comments
 (0)