尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證An explainable wastewater measurement review tool using historical baselines and Isolation Forest.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Second Opinion helps wastewater treatment operators decide which unusual measurements are worth checking first. It compares each daily reading with the recent history of the same measurement point, flags readings that deviate or look like a broken sensor, groups flagged days into cases, and ranks them per plant. An experimental Isolation Forest adds a second, independent ranking.
It is built around measurement data from TAI's Z-info platform. The aim is to help TAI and the plant operators who use Z-info catch readings that existing limit-based validation lets through, and to help them spend review time where it matters most.
This repository contains no TAI, Z-info or plant data. Every example, illustration and figure in it is synthetic, and the whole pipeline can be run on a fully simulated export.
Second Opinion supports the operator's judgement and does not replace it. A flag is a reason to look, not a diagnosis, a confirmed fault or proof that everything else is fine.
An 84-second explainer of the problem and the product, for people who have not seen it before. It uses synthetic illustrations only.
Plants record thousands of measurements every day, and most validation relies on fixed limits. Two problems follow:
The data has no confirmed anomaly labels, so Second Opinion is built to be transparent rather than clever. Every flag shows the value, the historical median, the robust spread, the rule that fired and the source row it came from.
| Stage | What it does | Code |
|---|---|---|
| Prepare | Streams a Z-info table export (Installations, MeasurementPoints, MeasurementValues), keeps every row with its source file and row number, parses dates and values, and flags quality issues without deleting, imputing or converting anything. | src/data_prep/ |
| Detect | Scores each reading against the prior 28 days of its own series using a rolling median and a floored MAD spread, with thresholds calibrated per series. Rules catch stuck sensors, dropouts to zero and negative values. | src/history_detector/ |
| Group | Merges nearby flagged days into cases and ranks them within each plant: rule hits first, then duration, then peak score. | src/history_detector/ |
| Second view | Fits one Isolation Forest per measurement group on six history-based features, trained chronologically (train ≤ 2023, validate 2024, hold out 2025). | src/isolation_forest/ |
| Review | A local web dashboard shows flagged readings, their history and the evidence, in Dutch or English, with an optional Claude explanation. | dashboard/ |
The pipeline covers six exploratory measurement groups: influent volume, and activated-sludge oxygen, ammonium, nitrate, suspended solids and temperature. Each is a narrow metadata filter, not every reading of that type. Plants are never compared with each other, because they differ in geography, process and timing, and each has its own operator.
See the methodology for the full method, design choices and limitations, or step through each stage interactively on synthetic data.
Use Python 3.11, the version in .python-version (tools such as uv and pyenv pick it up). From the repository root:
python3 -m venv .venv
source .venv/bin/activate # Windows PowerShell: .venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
requirements.txt pins every package, including the ones the direct dependencies install, so a fresh environment matches the one the results were made with. To upgrade, change the pins deliberately and rerun the tests.
Second Opinion reads a Z-info table export of daily measurements. No data ships with this repository. Place your export at:
data/tai/extracted/
├── Installations/*.csv.gz
├── MeasurementPoints/*.csv.gz
└── MeasurementValues/*.csv.gz
data/ is git-ignored. Measurement data, prepared files, scores and fitted models are derived from operational data, so keep them local and never commit them.
No access to the export? Generate a fully simulated one with the same schema and known, injected anomalies: python src/simulation/simulate_tai.py, which writes straight into data/tai/ so the rest of the pipeline and the dashboard work unchanged. Add --workers N to generate N plants at once (see Running in parallel).
python src/pipeline.py --plan # show what would run or be skipped
python src/pipeline.py --smoke 30 # quick partial run, 30 points per group
python src/pipeline.py # full run
python src/pipeline.py --groups oxygen --force detect # redo oxygen detection and downstream
python src/pipeline.py --with-faults # add the artificial-fault evaluation
python src/pipeline.py --workers 8 --jobs 3 # run in parallel (see Running in parallel below)
The driver fingerprints each stage's script, arguments and upstream stages in data/tai/pipeline_state.json and skips stages that are already complete and unchanged. It never deletes output: anything that must be redone is first renamed <name>.old-<timestamp>. Outputs and one log per stage go to data/tai/pipeline/ (or data/tai/pipeline_smoke<N>/). Full preparation needs substantial time and disk space. A full run ends by building the dashboard's results index (data/tai/second_opinion_web_index.sqlite) with the dashboard's own code, so connecting the dashboard to data/tai/pipeline reuses it instead of indexing again. Smoke runs leave the shared index alone; the dashboard indexes a smoke folder when it connects. While it runs, the driver keeps one status line at the bottom of the terminal: with one stage running it shows that stage's own progress (files and rows for preparation and verification, numbered steps for the detectors and forests, rows for the dashboard index), and with several it shows the overall share and each running stage. Started and finished messages print above it, and every stage's own output goes to its log. Run on their own, the scripts (and the simulator) show their bar directly.
Everything runs one thing at a time by default. Three settings run work side by side to save time. None of them changes any output; they only use more of the computer.
| Setting | What runs at the same time | Mainly uses |
|---|---|---|
simulate_tai.py --workers N | Up to N simulated plants are generated, each in its own process | CPU cores |
pipeline.py --workers N | The prepare stage cleans up to N raw files, each in its own process | CPU cores, plus temporary disk space |
pipeline.py --jobs N | Up to N pipeline stages that do not depend on each other | Memory |
--workers speeds up the work inside one step. Prepare's last part, the cross-file quality index and duplicate reports, still runs in one process.
--jobs decides how many stages can overlap, within the order they depend on each other:
--with-faults, the artificial-fault comparisons only need verify.--with-faults); a higher --jobs has no further effect.Apart from prepare with --workers, each stage runs in a single process, and each history check holds its whole measurement group in memory. Memory is therefore what limits --jobs.
Choosing values:
--workers: up to the number of physical CPU cores, leaving one or two free for the rest of the computer. For example, 8 on a 10-core machine.--jobs: start with 2 or 3, watch memory while the history checks run, and raise it only if plenty is left free.The two settings never compete, because prepare runs before any other stage starts, so set both at once: python src/pipeline.py --workers 8 --jobs 3.
python dashboard/server.py
Open http://127.0.0.1:8518 and click Connect results; it reads data/tai/pipeline/ by default. See the dashboard guide for other result folders and the optional Claude explanation.
python -B -m unittest discover -s tests -t . -v
python -B -m unittest discover -s dashboard -p "test_*.py" -v
node --test dashboard/test_assistant_ui.cjs # dashboard frontend, needs Node.js
All tests use small artificial fixtures, never real measurements.
The guides are also published on the website, rendered from the markdown below.
| Guide | Covers |
|---|---|
| Methodology | Problem framing, the full method, design decisions and limitations |
| Data preparation | Input format, preparation outputs, verification and supplementary reports |
| History detector | Measurement groups, scoring, rules, cases, options and the artificial-fault evaluation |
| Isolation Forest | Features, eligibility, chronological splits, thresholds and the budget comparison |
| Pitch video | The 84-second explainer video, its script and the source that renders it |
| Simulated dataset | A generated stand-in for the export, with injected anomalies and an answer key |
| Dashboard | The local review workspace, its results layout and the optional Claude explanation |
| Website | The public site: landing page, interactive pipeline walk-through and these guides, published to GitHub Pages |
src/pipeline.py Pipeline driver
src/dashboard_index.py Prebuilds the dashboard index (last pipeline stage)
src/progress_bar.py Shared terminal progress line used by the pipeline and its scripts
src/data_prep/ Preparation, verification and data reports
src/history_detector/ History detector and artificial-fault evaluation
src/isolation_forest/ Experimental Isolation Forest
src/simulation/ Simulated Z-info export generator
dashboard/ Local web dashboard (Python server, JavaScript frontend)
tests/ Synthetic-fixture tests
docs/ Methodology, component guides, README graphics and the pitch video
docs/website/ Project website source (GitHub Pages)
data/ Local data and outputs (git-ignored)
Second Opinion is a research prototype run on historical, day-level data. It is not a live alerting system. Measurement meanings, units, reporting periods and observation availability still need to be confirmed with TAI. The thresholds encode an assumed review workload, roughly 1% of readings, not a validated false-alarm rate. Next steps would be expert review of a documented sample of flagged and unflagged cases, persistent operator feedback, and a comparison against the validation limits that actually applied at the time.
Built by Joshua Varghese Thomji, Sunil Parameswaran, Smriti Sridhar and Oindrilla Banerjee.