pbp-anomaly 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tendai Chikake, Boris Goldengorin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,181 @@
1
+ Metadata-Version: 2.4
2
+ Name: pbp-anomaly
3
+ Version: 0.2.0
4
+ Summary: Training-free anomaly detection via pseudo-Boolean polynomial decomposition
5
+ Author: Boris Goldengorin
6
+ Author-email: Tendai Chikake <tendaichikake@gmail.com>
7
+ License: MIT
8
+ Project-URL: Repository, https://github.com/Tenfleques/pbp-anomaly
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: numpy>=1.21
13
+ Requires-Dist: pandas>=1.3
14
+ Requires-Dist: scipy>=1.7
15
+ Requires-Dist: scikit-learn>=1.0
16
+ Requires-Dist: tmc-pbp>=0.1.0
17
+ Provides-Extra: noaa
18
+ Requires-Dist: requests; extra == "noaa"
19
+ Provides-Extra: figures
20
+ Requires-Dist: matplotlib>=3.5; extra == "figures"
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=7.0; extra == "dev"
23
+ Provides-Extra: all
24
+ Requires-Dist: requests; extra == "all"
25
+ Requires-Dist: matplotlib>=3.5; extra == "all"
26
+ Requires-Dist: pytest>=7.0; extra == "all"
27
+ Dynamic: license-file
28
+
29
+ # pbp-anomaly
30
+
31
+ Training-free anomaly detection in environmental sensor networks via pseudo-Boolean polynomial (PBP) decomposition.
32
+
33
+ Reference implementation of the PBP anomaly scoring described in:
34
+
35
+ > T. M. Chikake and B. Goldengorin, "Pseudo-Boolean polynomial anomaly scoring for intelligent multisensor environmental monitoring," in *International Conference on Advanced Sensing and Intelligent Systems (ICASIS 2026)*, Proc. SPIE 14309, 2026. https://doi.org/10.1117/12.3121130
36
+
37
+ The repository also contains the multi-dataset experiments of an extended study.
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ pip install pbp-anomaly
43
+ ```
44
+
45
+ This also installs the PBP core, [`tmc-pbp`](https://pypi.org/project/tmc-pbp/) (imported as `pbp`).
46
+
47
+ ## Quick start (reproducing the experiments)
48
+
49
+ ```bash
50
+ git clone https://github.com/Tenfleques/pbp-anomaly.git
51
+ cd pbp-anomaly
52
+ pip install -e ".[all]"
53
+
54
+ # Download large datasets (Beijing, NOAA weather stations)
55
+ python experiments/download_data.py
56
+
57
+ # Verify pre-computed results (should report 200+ PASS, 0 FAIL)
58
+ python experiments/verify_consistency.py
59
+
60
+ # Generate all figures
61
+ python experiments/generate_figures.py
62
+ ```
63
+
64
+ ## What this repo contains
65
+
66
+ - `pbp_anomaly/` -- Python package implementing the PBP anomaly detector
67
+ - `data/` -- Small datasets shipped with the repo (UCI, OpenMeteo); large datasets downloaded via script
68
+ - `results/precomputed/` -- Pre-computed experiment results (JSON/CSV) for instant verification
69
+ - `experiments/` -- Scripts to reproduce all results and figures from the paper
70
+ - `tests/` -- Unit tests (27 tests)
71
+
72
+ ## Datasets
73
+
74
+ The paper evaluates PBP across 9 datasets spanning two sensor domains:
75
+
76
+ | Dataset | Domain | Sensors | Readings | Source | Shipped |
77
+ |---------|--------|---------|----------|--------|---------|
78
+ | UCI Air Quality (Italy) | Air quality | 8 | 9,357 | [UCI MLR](https://archive.ics.uci.edu/dataset/360/air+quality) | Yes |
79
+ | Beijing Dongsi | Air quality | 10 | 35,064 | [Zhang et al. 2017](https://archive.ics.uci.edu/dataset/501/beijing+multi+site+air+quality+data) | Download |
80
+ | EPA AQS (Los Angeles) | Air quality | 4 | 26,280 | [EPA AQS](https://aqs.epa.gov/aqsweb/airdata/download_files.html) | Optional |
81
+ | Sao Paulo (CAMS) | Air quality | 6 | 17,520 | [Open-Meteo](https://open-meteo.com/en/docs/air-quality-api) | Yes |
82
+ | Cape Town (CAMS) | Air quality | 6 | 17,520 | [Open-Meteo](https://open-meteo.com/en/docs/air-quality-api) | Yes |
83
+ | Chicago O'Hare | Weather | 6 | 17,520 | [NOAA ISD](https://www.ncei.noaa.gov/products/land-based-station/integrated-surface-database) | Download |
84
+ | Miami | Weather | 6 | 17,520 | [NOAA ISD](https://www.ncei.noaa.gov/products/land-based-station/integrated-surface-database) | Download |
85
+ | San Francisco | Weather | 6 | 17,520 | [NOAA ISD](https://www.ncei.noaa.gov/products/land-based-station/integrated-surface-database) | Download |
86
+ | Fairbanks | Weather | 6 | 17,520 | [NOAA ISD](https://www.ncei.noaa.gov/products/land-based-station/integrated-surface-database) | Download |
87
+
88
+ "Shipped" means the CSV is included in this repo. "Download" means `download_data.py` fetches it automatically.
89
+
90
+ ## Reproducing results
91
+
92
+ ### Verify pre-computed results
93
+
94
+ ```bash
95
+ python experiments/verify_consistency.py
96
+ ```
97
+
98
+ This checks every number cited in the manuscript against the pre-computed result files in `results/precomputed/`. No data download required.
99
+
100
+ ### Full replication from raw data
101
+
102
+ ```bash
103
+ # Download datasets
104
+ python experiments/download_data.py
105
+
106
+ # Run all experiments (may take several hours)
107
+ python experiments/replicate_all.py --output-dir results/local
108
+
109
+ # Verify fresh results
110
+ python experiments/verify_consistency.py --results-dir results/local
111
+
112
+ # Generate figures from fresh results
113
+ python experiments/generate_figures.py --results-dir results/local
114
+ ```
115
+
116
+ For a quick smoke test on a single dataset:
117
+
118
+ ```bash
119
+ python experiments/replicate_all.py --datasets UCI --quick --output-dir results/local
120
+ ```
121
+
122
+ ### Figures
123
+
124
+ ```bash
125
+ python experiments/generate_figures.py
126
+ ```
127
+
128
+ Generates Fig 1 (temporal robustness), Fig 2 (hub variable heatmap), and Fig 3 (sensor-pair z-score case study) in `figures/`.
129
+
130
+ ## Library usage
131
+
132
+ ```python
133
+ from pbp_anomaly import AnomalyDetector
134
+ import pandas as pd
135
+
136
+ df = pd.read_csv('your_sensor_data.csv')
137
+ detector = AnomalyDetector(window_size=6, mode='both')
138
+ result = detector.fit_score(df, sensor_cols=['CO', 'NO2', 'O3'])
139
+
140
+ print(f"AUC-ROC: {result['standard']['auc_roc']:.3f}")
141
+ print(f"Top sensor pairs: {result['pair_ranking'][:3]}")
142
+ ```
143
+
144
+ Or via CLI:
145
+
146
+ ```bash
147
+ pbp-anomaly detect data.csv --sensors CO,NO2,O3 --mode both
148
+ ```
149
+
150
+ ## Running tests
151
+
152
+ ```bash
153
+ pytest tests/ -v
154
+ ```
155
+
156
+ ## Dependencies
157
+
158
+ Core: numpy, pandas, scipy, scikit-learn, [tmc-pbp](https://github.com/Tenfleques/tmc-pbp) (Python >= 3.10)
159
+
160
+ Optional: matplotlib (figures), requests (NOAA download), pytest (tests)
161
+
162
+ All installed automatically via `pip install -e ".[all]"`.
163
+
164
+ ## Citation
165
+
166
+ ```bibtex
167
+ @inproceedings{Chikake2026icasis,
168
+ author = {Chikake, Tendai M. and Goldengorin, Boris},
169
+ title = {Pseudo-Boolean polynomial anomaly scoring for intelligent multisensor environmental monitoring},
170
+ booktitle = {International Conference on Advanced Sensing and Intelligent Systems (ICASIS 2026)},
171
+ series = {Proc. SPIE},
172
+ volume = {14309},
173
+ publisher = {SPIE},
174
+ year = {2026},
175
+ doi = {10.1117/12.3121130}
176
+ }
177
+ ```
178
+
179
+ ## License
180
+
181
+ MIT
@@ -0,0 +1,153 @@
1
+ # pbp-anomaly
2
+
3
+ Training-free anomaly detection in environmental sensor networks via pseudo-Boolean polynomial (PBP) decomposition.
4
+
5
+ Reference implementation of the PBP anomaly scoring described in:
6
+
7
+ > T. M. Chikake and B. Goldengorin, "Pseudo-Boolean polynomial anomaly scoring for intelligent multisensor environmental monitoring," in *International Conference on Advanced Sensing and Intelligent Systems (ICASIS 2026)*, Proc. SPIE 14309, 2026. https://doi.org/10.1117/12.3121130
8
+
9
+ The repository also contains the multi-dataset experiments of an extended study.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pip install pbp-anomaly
15
+ ```
16
+
17
+ This also installs the PBP core, [`tmc-pbp`](https://pypi.org/project/tmc-pbp/) (imported as `pbp`).
18
+
19
+ ## Quick start (reproducing the experiments)
20
+
21
+ ```bash
22
+ git clone https://github.com/Tenfleques/pbp-anomaly.git
23
+ cd pbp-anomaly
24
+ pip install -e ".[all]"
25
+
26
+ # Download large datasets (Beijing, NOAA weather stations)
27
+ python experiments/download_data.py
28
+
29
+ # Verify pre-computed results (should report 200+ PASS, 0 FAIL)
30
+ python experiments/verify_consistency.py
31
+
32
+ # Generate all figures
33
+ python experiments/generate_figures.py
34
+ ```
35
+
36
+ ## What this repo contains
37
+
38
+ - `pbp_anomaly/` -- Python package implementing the PBP anomaly detector
39
+ - `data/` -- Small datasets shipped with the repo (UCI, OpenMeteo); large datasets downloaded via script
40
+ - `results/precomputed/` -- Pre-computed experiment results (JSON/CSV) for instant verification
41
+ - `experiments/` -- Scripts to reproduce all results and figures from the paper
42
+ - `tests/` -- Unit tests (27 tests)
43
+
44
+ ## Datasets
45
+
46
+ The paper evaluates PBP across 9 datasets spanning two sensor domains:
47
+
48
+ | Dataset | Domain | Sensors | Readings | Source | Shipped |
49
+ |---------|--------|---------|----------|--------|---------|
50
+ | UCI Air Quality (Italy) | Air quality | 8 | 9,357 | [UCI MLR](https://archive.ics.uci.edu/dataset/360/air+quality) | Yes |
51
+ | Beijing Dongsi | Air quality | 10 | 35,064 | [Zhang et al. 2017](https://archive.ics.uci.edu/dataset/501/beijing+multi+site+air+quality+data) | Download |
52
+ | EPA AQS (Los Angeles) | Air quality | 4 | 26,280 | [EPA AQS](https://aqs.epa.gov/aqsweb/airdata/download_files.html) | Optional |
53
+ | Sao Paulo (CAMS) | Air quality | 6 | 17,520 | [Open-Meteo](https://open-meteo.com/en/docs/air-quality-api) | Yes |
54
+ | Cape Town (CAMS) | Air quality | 6 | 17,520 | [Open-Meteo](https://open-meteo.com/en/docs/air-quality-api) | Yes |
55
+ | Chicago O'Hare | Weather | 6 | 17,520 | [NOAA ISD](https://www.ncei.noaa.gov/products/land-based-station/integrated-surface-database) | Download |
56
+ | Miami | Weather | 6 | 17,520 | [NOAA ISD](https://www.ncei.noaa.gov/products/land-based-station/integrated-surface-database) | Download |
57
+ | San Francisco | Weather | 6 | 17,520 | [NOAA ISD](https://www.ncei.noaa.gov/products/land-based-station/integrated-surface-database) | Download |
58
+ | Fairbanks | Weather | 6 | 17,520 | [NOAA ISD](https://www.ncei.noaa.gov/products/land-based-station/integrated-surface-database) | Download |
59
+
60
+ "Shipped" means the CSV is included in this repo. "Download" means `download_data.py` fetches it automatically.
61
+
62
+ ## Reproducing results
63
+
64
+ ### Verify pre-computed results
65
+
66
+ ```bash
67
+ python experiments/verify_consistency.py
68
+ ```
69
+
70
+ This checks every number cited in the manuscript against the pre-computed result files in `results/precomputed/`. No data download required.
71
+
72
+ ### Full replication from raw data
73
+
74
+ ```bash
75
+ # Download datasets
76
+ python experiments/download_data.py
77
+
78
+ # Run all experiments (may take several hours)
79
+ python experiments/replicate_all.py --output-dir results/local
80
+
81
+ # Verify fresh results
82
+ python experiments/verify_consistency.py --results-dir results/local
83
+
84
+ # Generate figures from fresh results
85
+ python experiments/generate_figures.py --results-dir results/local
86
+ ```
87
+
88
+ For a quick smoke test on a single dataset:
89
+
90
+ ```bash
91
+ python experiments/replicate_all.py --datasets UCI --quick --output-dir results/local
92
+ ```
93
+
94
+ ### Figures
95
+
96
+ ```bash
97
+ python experiments/generate_figures.py
98
+ ```
99
+
100
+ Generates Fig 1 (temporal robustness), Fig 2 (hub variable heatmap), and Fig 3 (sensor-pair z-score case study) in `figures/`.
101
+
102
+ ## Library usage
103
+
104
+ ```python
105
+ from pbp_anomaly import AnomalyDetector
106
+ import pandas as pd
107
+
108
+ df = pd.read_csv('your_sensor_data.csv')
109
+ detector = AnomalyDetector(window_size=6, mode='both')
110
+ result = detector.fit_score(df, sensor_cols=['CO', 'NO2', 'O3'])
111
+
112
+ print(f"AUC-ROC: {result['standard']['auc_roc']:.3f}")
113
+ print(f"Top sensor pairs: {result['pair_ranking'][:3]}")
114
+ ```
115
+
116
+ Or via CLI:
117
+
118
+ ```bash
119
+ pbp-anomaly detect data.csv --sensors CO,NO2,O3 --mode both
120
+ ```
121
+
122
+ ## Running tests
123
+
124
+ ```bash
125
+ pytest tests/ -v
126
+ ```
127
+
128
+ ## Dependencies
129
+
130
+ Core: numpy, pandas, scipy, scikit-learn, [tmc-pbp](https://github.com/Tenfleques/tmc-pbp) (Python >= 3.10)
131
+
132
+ Optional: matplotlib (figures), requests (NOAA download), pytest (tests)
133
+
134
+ All installed automatically via `pip install -e ".[all]"`.
135
+
136
+ ## Citation
137
+
138
+ ```bibtex
139
+ @inproceedings{Chikake2026icasis,
140
+ author = {Chikake, Tendai M. and Goldengorin, Boris},
141
+ title = {Pseudo-Boolean polynomial anomaly scoring for intelligent multisensor environmental monitoring},
142
+ booktitle = {International Conference on Advanced Sensing and Intelligent Systems (ICASIS 2026)},
143
+ series = {Proc. SPIE},
144
+ volume = {14309},
145
+ publisher = {SPIE},
146
+ year = {2026},
147
+ doi = {10.1117/12.3121130}
148
+ }
149
+ ```
150
+
151
+ ## License
152
+
153
+ MIT
@@ -0,0 +1,20 @@
1
+ """
2
+ pbp-anomaly: Training-free anomaly detection via pseudo-Boolean polynomial decomposition.
3
+
4
+ Detects anomalies in multivariate sensor streams by extracting polynomial features
5
+ from binarized sliding windows. No training data required.
6
+
7
+ Usage:
8
+ from pbp_anomaly import detect, AnomalyDetector
9
+
10
+ detector = AnomalyDetector(window_size=6, thresholds='auto')
11
+ scores = detector.fit_score(dataframe, sensor_cols=['CO', 'NO2', 'O3'])
12
+
13
+ # Or one-shot:
14
+ result = detect(dataframe, sensor_cols=['CO', 'NO2', 'O3'])
15
+ """
16
+
17
+ from pbp_anomaly.detector import AnomalyDetector, detect
18
+
19
+ __all__ = ['AnomalyDetector', 'detect']
20
+ __version__ = '0.2.0'
@@ -0,0 +1,104 @@
1
+ """
2
+ CLI for pbp-anomaly.
3
+
4
+ Usage:
5
+ pbp-anomaly detect data.csv --sensors CO,NO2,O3 --mode standard
6
+ pbp-anomaly detect data.csv --sensors CO,NO2,O3 --mode both --window 12
7
+ pbp-anomaly info
8
+ """
9
+
10
+ import argparse
11
+ import json
12
+ import sys
13
+
14
+ from pbp_anomaly.detector import AnomalyDetector, get_backend
15
+
16
+
17
+ def cmd_detect(args):
18
+ from pbp_anomaly.parsers import load_csv
19
+
20
+ sensor_cols = [s.strip() for s in args.sensors.split(',')]
21
+ ref_cols = [s.strip() for s in args.ref.split(',')] if args.ref else None
22
+
23
+ ds = load_csv(args.csv, sensor_cols, ref_cols, name=args.csv)
24
+
25
+ detector = AnomalyDetector(
26
+ window_size=args.window,
27
+ mode=args.mode,
28
+ percentile=args.percentile,
29
+ two_tailed=args.two_tailed,
30
+ top_k=args.top_k,
31
+ )
32
+
33
+ print(f"Dataset: {ds['name']}")
34
+ print(f"Readings: {len(ds['data'])}, Sensors: {len(sensor_cols)}")
35
+ print(f"Backend: {get_backend()}")
36
+ print(f"Mode: {args.mode}, Window: {args.window}, Percentile: {args.percentile}")
37
+ print()
38
+
39
+ result = detector.fit_score(ds['data'], ds['sensor_cols'], ds['ref_cols'])
40
+
41
+ print(f"Windows: {result['n_windows']}")
42
+ print(f"Anomaly rate: {100 * result['anomaly_fraction']:.1f}%")
43
+ print()
44
+
45
+ if 'standard' in result:
46
+ r = result['standard']
47
+ print(f"PBP standard: AUC = {r['auc_roc']:.4f} CI = {r['ci_95']}")
48
+ if 'pair' in result:
49
+ r = result['pair']
50
+ print(f"PBP pair: AUC = {r['auc_roc']:.4f} CI = {r['ci_95']}")
51
+ if 'pair_ranking' in result:
52
+ print(f"\nTop 5 sensor pairs:")
53
+ for p in result['pair_ranking'][:5]:
54
+ print(f" {p['pair']:<20s} AUC = {p['auc']:.4f}")
55
+
56
+ if args.output:
57
+ # Remove non-serializable arrays
58
+ out = {k: v for k, v in result.items() if k not in ('scores', 'labels')}
59
+ with open(args.output, 'w') as f:
60
+ json.dump(out, f, indent=2, default=str)
61
+ print(f"\nResults saved to {args.output}")
62
+
63
+
64
+ def cmd_info(args):
65
+ from pbp_anomaly import __version__
66
+ print(f"pbp-anomaly v{__version__}")
67
+ print(f"PBP backend: {get_backend()}")
68
+ print(f"Features per window: 6 (degree, monomial_count, entropy, coeff_std, l1_norm, coeff_range)")
69
+ print(f"Modes: standard (full-matrix), pair (sensor-pair decomposition), both")
70
+
71
+
72
+ def main():
73
+ parser = argparse.ArgumentParser(
74
+ prog='pbp-anomaly',
75
+ description='Training-free anomaly detection via PBP decomposition',
76
+ )
77
+ sub = parser.add_subparsers(dest='command')
78
+
79
+ # detect
80
+ p_detect = sub.add_parser('detect', help='Run anomaly detection on a CSV file')
81
+ p_detect.add_argument('csv', help='Path to CSV file')
82
+ p_detect.add_argument('--sensors', required=True, help='Comma-separated sensor column names')
83
+ p_detect.add_argument('--ref', default=None, help='Reference columns for labels (default: same as sensors)')
84
+ p_detect.add_argument('--mode', default='standard', choices=['standard', 'pair', 'both'])
85
+ p_detect.add_argument('--window', type=int, default=6, help='Window size (default: 6)')
86
+ p_detect.add_argument('--percentile', type=int, default=95, help='Threshold percentile (default: 95)')
87
+ p_detect.add_argument('--two-tailed', action='store_true', help='Flag both high and low extremes')
88
+ p_detect.add_argument('--top-k', type=int, default=5, help='Top-K features for composite (default: 5)')
89
+ p_detect.add_argument('--output', '-o', help='Save results to JSON file')
90
+
91
+ # info
92
+ sub.add_parser('info', help='Show library info')
93
+
94
+ args = parser.parse_args()
95
+ if args.command == 'detect':
96
+ cmd_detect(args)
97
+ elif args.command == 'info':
98
+ cmd_info(args)
99
+ else:
100
+ parser.print_help()
101
+
102
+
103
+ if __name__ == '__main__':
104
+ main()