Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7001639
Implement adaptive change point detection algorithms (ADWIN, AV-CUSUM…
A-Aherbil Jan 12, 2026
7f236a6
Implement adaptive change point detection algorithms (ADWIN, AV-CUSUM…
A-Aherbil Jan 12, 2026
8135a9d
Clean up codebase: remove test files, unused modules, and inline comm…
A-Aherbil Jan 12, 2026
7c197bf
Cleanup
A-Aherbil Jan 12, 2026
59000b8
solve merge conflicts
A-Aherbil Jan 13, 2026
1062ef7
Clean up and fix minor issues
A-Aherbil Jan 13, 2026
d1b5c2c
Fix tests and refactor shared resources for change point detection
Jan 21, 2026
ddee68d
Update documentation with correct usage examples and fix contributor …
Jan 21, 2026
f7d017b
Move GUI to ftio/gui/ and add script entry in pyproject.toml
Jan 21, 2026
dc5fad0
Update documentation with ftio_gui command
Jan 21, 2026
ed7b682
solved merge conflict
Jan 21, 2026
b8e883c
Refactoring
Jan 22, 2026
cd065aa
fix bug: add missing change point fields causing KeyError in socket l…
Jan 24, 2026
7f72d67
Merge branch 'development' into feature/pattern_change_detection
A-Tarraf Jan 27, 2026
1af4f84
fixed unused code and formating
A-Tarraf Jan 27, 2026
0e431df
fixed unused code and formating 2
A-Tarraf Jan 27, 2026
038ac00
add --gui flag, fix documentation, and fix change point display bug
Jan 31, 2026
25f2145
fix import sorting and update documentation examples
Jan 31, 2026
7630e42
fix black formatting
Jan 31, 2026
4d7dbd3
fix merged cosine view and remove unused auto-update button
Jan 31, 2026
61b156a
fix dense merged view by normalizing each prediction to 5 wave cycles
Jan 31, 2026
28c092c
remove unused State import
Jan 31, 2026
055cf96
fix black formatting
Jan 31, 2026
89c99c0
add call tree for change point detection and GUI integration
Jan 31, 2026
45ea05b
docs: clarify pure vs hybrid mode for change point detection
Jan 31, 2026
86d8705
Add docstrings to SocketLogger and SocketListener classes
Feb 4, 2026
aee0417
Add docstrings to SocketLogger and SocketListener classes
Feb 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions ChangeLog.md

This file was deleted.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ test:

check_style: check_tools
black .
isort .
ruff check --fix
# flake8 .

check_tools:
Expand Down
24 changes: 23 additions & 1 deletion docs/approach.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ An overview of the core of FTIO is provided below:

<p align="right"><a href="#approach">⬆</a></p>

## Online Prediction
## Online Prediction

The tool [`predictor`](https://github.com/tuda-parallel/FTIO/tree/main/ftio/cli/predictor.py) launches `ftio` in a loop. It monitors a file for changes. The file contains bandwidth values over time. Once the file changes, `ftio` is called and a new prediction is found. `predictor` performs a few additional steps compared `ftio`:
* FTIO results are merged into frequency ranges using DB-Scan​
Expand All @@ -51,6 +51,28 @@ An overview of predictor.py is provided in the image below:
</div>
<br />

### Usage Examples

```bash
# Basic usage: X = number of MPI ranks
predictor X.jsonl -e no -f 100

# With window adaptation based on frequency hits
predictor X.jsonl -e no -f 100 -w frequency_hits

# With change point detection (ADWIN algorithm, default)
predictor X.jsonl -e no -f 100 -w frequency_hits --online_adaptation adwin

# With CUSUM or Page-Hinkley change point detection
predictor X.jsonl -e no -f 100 -w frequency_hits --online_adaptation cusum
predictor X.jsonl -e no -f 100 -w frequency_hits --online_adaptation ph

# With GUI dashboard visualization (works with any algorithm)
ftio-gui # Start dashboard first in separate terminal
predictor X.jsonl -e no -f 100 -w frequency_hits --online_adaptation adwin --gui
```

For more details on change point detection algorithms, see [Change Point Detection](change_point_detection.md).

<p align="right"><a href="#approach">⬆</a></p>

189 changes: 189 additions & 0 deletions docs/change_point_detection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# Change Point Detection for Online I/O Pattern Analysis

This document describes the adaptive change point detection feature for FTIO's online predictor, which enables automatic detection of I/O pattern changes during streaming analysis.

## Overview

Change point detection allows FTIO to automatically detect when the I/O pattern changes during online prediction. When a change is detected, the analysis window is adapted to focus on the new pattern, improving prediction accuracy.

Three algorithms are available:
- **ADWIN** (Adaptive Windowing) - Default
- **CUSUM** (Cumulative Sum)
- **Page-Hinkley** (Sequential change detection)

## Usage

### Command Line

There are two configuration modes:

**Pure change point detection**:
```bash
# Only change point detection, no hit-based optimization
predictor X.jsonl -e no -f 100 --online_adaptation adwin
predictor X.jsonl -e no -f 100 --online_adaptation cusum
predictor X.jsonl -e no -f 100 --online_adaptation ph
```

**Hybrid mode**:
```bash
# Change point detection + hit-based optimization
predictor X.jsonl -e no -f 100 -w frequency_hits --online_adaptation adwin
predictor X.jsonl -e no -f 100 -w frequency_hits --online_adaptation cusum
predictor X.jsonl -e no -f 100 -w frequency_hits --online_adaptation ph
```

### Configuration Modes Explained

| Mode | Flags |
|------|-------|
| Pure | `--online_adaptation <algo>` |
| Hybrid | `-w frequency_hits --online_adaptation <algo>` |

In **hybrid mode**, the two mechanisms are complementary:
- **Change point detection** handles pattern transitions (primary mechanism)
- **Hit-based** optimizes stable periods by shrinking the window (secondary optimization)

Hit-based only activates when change point detection reports no change. They do not interfere with each other.

## Algorithms

### ADWIN (Adaptive Windowing)

ADWIN uses Hoeffding bounds to detect statistically significant changes in the frequency distribution.

**How it works:**
1. Maintains a sliding window of frequency observations
2. Tests all possible cut points in the window
3. Uses Hoeffding inequality to determine if the means differ significantly
4. When change detected, discards old data and adapts window

**Parameters:**
- `delta` (default: 0.05): Confidence parameter. Lower values = higher confidence required for detection


### AV-CUSUM (Adaptive-Variance Cumulative Sum)

CUSUM tracks cumulative deviations from a reference value, with adaptive thresholds based on data variance.

**How it works:**
1. Establishes reference frequency from initial observations
2. Calculates positive and negative cumulative sums: `S+ = max(0, S+ + x - μ - k)` and `S- = max(0, S- - x + μ - k)`
3. Detects change when cumulative sum exceeds adaptive threshold (2σ)
4. Drift parameter (k = 0.5σ) prevents small fluctuations from accumulating

**Parameters:**
- `window_size` (default: 50): Size of rolling window for variance calculation


### STPH (Self-Tuning Page-Hinkley)

Page-Hinkley uses a running mean as reference and detects when observations deviate significantly.

**How it works:**
1. Maintains running mean as reference
2. Tracks cumulative positive and negative differences from reference
3. Uses adaptive threshold and delta based on rolling standard deviation
4. Detects change when cumulative difference exceeds threshold

**Parameters:**
- `window_size` (default: 10): Size of rolling window for variance calculation


## Window Adaptation

When a change point is detected:

1. **Exact timestamp** of the change is recorded
2. **Analysis window** is adapted to start from the change point
3. **Safety bounds** ensure minimum window size (0.5-1.0 seconds)
4. **Maximum lookback** limits window to prevent using stale data (10 seconds)

```
Before change detection:
|-------- old pattern --------|-- new pattern --|
^ change point

After adaptation:
|-- new pattern --|
^ analysis starts here
```

## GUI Dashboard

A real-time visualization dashboard is available for monitoring predictions and change points.

### Starting the Dashboard

```bash
# Install GUI dependencies (if not already installed)
pip install -e .[gui]

# 1. Start the GUI dashboard first
ftio-gui

# 2. Then run predictor with --gui flag to forward data to the dashboard
# Pure mode:
predictor X.jsonl -e no -f 100 --online_adaptation adwin --gui
# Or hybrid mode:
predictor X.jsonl -e no -f 100 -w frequency_hits --online_adaptation adwin --gui
```

The dashboard runs on `http://localhost:8050` and displays:
- Frequency timeline with change point markers
- Continuous cosine wave visualization
- Statistics (total predictions, changes detected, current frequency)

### Dashboard Features

- **Auto-updating**: Refreshes automatically as new predictions arrive
- **Change point markers**: Red vertical lines indicate detected changes
- **Frequency annotations**: Shows old → new frequency at each change
- **Gap visualization**: Displays periods with no detected frequency
- **Auto-connect**: The predictor automatically connects to the GUI when `--gui` flag is used



### Algorithm Selection

Algorithm is selected via the `--online_adaptation` flag:

| Flag Value | Algorithm | Description |
|------------|-----------|-------------|
| `adwin` | ADWIN | Statistical guarantees with Hoeffding bounds |
| `cusum` | AV-CUSUM | Rapid detection with adaptive variance |
| `ph` | Page-Hinkley | Sequential detection with running mean |

## Call Tree

### Change Point Detection Call Tree
```
ftio/cli/predictor.py::main()
└── ftio/prediction/processes.py::predictor_with_processes()
└── ftio/prediction/online_analysis.py::ftio_process()
└── online_analysis.py::window_adaptation()
├── online_analysis.py::get_change_detector()
│ ├── ftio/prediction/change_point_detection.py::ChangePointDetector() # ADWIN
│ ├── ftio/prediction/change_point_detection.py::CUSUMDetector() # CUSUM
│ └── ftio/prediction/change_point_detection.py::SelfTuningPageHinkleyDetector() # PH
└── change_point_detection.py::detect_pattern_change_adwin() # or _cusum() or _pagehinkley()
└── ChangePointDetector::add_prediction()
└── ChangePointDetector::_detect_change()
```

### GUI Integration Call Tree
```
ftio/cli/predictor.py::main()
├── ftio/prediction/online_analysis.py::init_socket_logger()
│ └── online_analysis.py::SocketLogger()
└── ftio/prediction/processes.py::predictor_with_processes()
└── ftio/prediction/online_analysis.py::ftio_process()
└── online_analysis.py::log_to_gui_and_console()
└── online_analysis.py::get_socket_logger()
└── SocketLogger::send_log() # Sends to ftio-gui dashboard

ftio/gui/dashboard.py::main() # ftio-gui command
└── FTIODashApp::run()
├── ftio/gui/socket_listener.py::SocketListener() # Receives from predictor
└── FTIODashApp::_create_cosine_timeline_plot() # Renders merged view
```
2 changes: 2 additions & 0 deletions docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,5 +386,7 @@ We sincerely thank the following contributors for their valuable contributions:
- [Jean-Baptiste Bensard](https://github.com/besnardjb): Metric proxy integration
- [Anton Holderied](https://github.com/AntonBeasis): bachelor thesis –> new periodicity score
- [Tim Dieringer](https://github.com/Tim-Dieringer): bachelor thesis -> Additional integration for Metric Proxy
- [Amine Aherbil](https://github.com/amineaherbil): bachelor thesis -> adaptive change point detection
- [Julian Opper](https://github.com/JulianOpper), [Luca Schultze](https://github.com/lucasch03): PPT Lab -> Improved
CI/CD pipeline

5 changes: 4 additions & 1 deletion ftio/api/gekkoFs/predictor_gekko.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ def prediction_process(
# display results
text = display_result(freq, prediction, shared_resources=shared_resources)
# data analysis to decrease window
text += window_adaptation(parsed_args, prediction, freq, shared_resources)
adaptation_text, _, _ = window_adaptation(
parsed_args, prediction, freq, shared_resources
)
text += adaptation_text
console.print(text)
while not shared_resources.queue.empty():
shared_resources.data.append(shared_resources.queue.get())
Expand Down
5 changes: 4 additions & 1 deletion ftio/api/gekkoFs/predictor_gekko_zmq.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ def prediction_zmq_process(
# display results
text = display_result(freq, prediction, shared_resources)
# data analysis to decrease window thus change start_time
text += window_adaptation(parsed_args, prediction, freq, shared_resources)
adaptation_text, _, _ = window_adaptation(
parsed_args, prediction, freq, shared_resources
)
text += adaptation_text
# print text
console.print(text)

Expand Down
7 changes: 7 additions & 0 deletions ftio/cli/predictor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import sys

from ftio.parse.helper import print_info
from ftio.prediction.online_analysis import init_socket_logger
from ftio.prediction.pools import predictor_with_pools
from ftio.prediction.processes import predictor_with_processes
from ftio.prediction.processes_zmq import predictor_with_processes_zmq
Expand All @@ -22,6 +23,12 @@ def main(args: list[str] = sys.argv) -> None:
shared_resources = SharedResources()
mode = "procs" # "procs" or "pool"

# Initialize GUI socket logger if --gui flag is present
gui_enabled = "--gui" in args
init_socket_logger(gui_enabled)
if gui_enabled:
print("[INFO] GUI mode enabled - forwarding predictions to ftio-gui dashboard")

if "pool" in mode.lower():
# prediction with a Pool of process and a callback mechanism
predictor_with_pools(shared_resources, args)
Expand Down
4 changes: 1 addition & 3 deletions ftio/freq/discretize.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ def sample_data(
text += f"Recommended sampling frequency: {freq:.3e} Hz\n"
# Apply limit if freq is negative
N = int(np.floor((t[-1] - t[0]) * freq))
# N = N + 1 if N != 0 else 0 # include end point
limit_N = int(memory_limit // np.dtype(np.float64).itemsize)
text += f"memory limit: {memory_limit/ 1000**3:.3e} GB ({limit_N} samples)\n"
if limit_N < N:
Expand All @@ -73,9 +72,8 @@ def sample_data(
text += f"[yellow]Adjusted sampling frequency due to memory limit: {freq:.3e} Hz[/])\n"
else:
text += f"Sampling frequency: {freq:.3e} Hz\n"
# Compute the number of samples
# Compute number of samples
N = int(np.floor((t[-1] - t[0]) * freq))
# N = N + 1 if N != 0 else 0 # include end point

text += f"Expected samples: {N}\n"
# print(" '-> \033[1;Start time: %f s \033[1;0m"%t[0])
Expand Down
41 changes: 41 additions & 0 deletions ftio/gui/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""
FTIO GUI Dashboard for real-time prediction visualization.

This module provides a Dash-based web dashboard for visualizing FTIO predictions
and change point detection results in real-time.

Author: Amine Aherbil
Copyright (c) 2025 TU Darmstadt, Germany
Date: January 2025

Licensed under the BSD 3-Clause License.
For more information, see the LICENSE file in the project root:
https://github.com/tuda-parallel/FTIO/blob/main/LICENSE

Requires: pip install ftio-hpc[gui]
"""

__all__ = [
"FTIODashApp",
"PredictionData",
"ChangePoint",
"PredictionDataStore",
"SocketListener",
]


def __getattr__(name):
"""Lazy import to avoid requiring dash unless actually used."""
if name == "FTIODashApp":
from ftio.gui.dashboard import FTIODashApp

return FTIODashApp
elif name == "SocketListener":
from ftio.gui.socket_listener import SocketListener

return SocketListener
elif name in ("PredictionData", "ChangePoint", "PredictionDataStore"):
from ftio.gui import data_models

return getattr(data_models, name)
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
Loading