Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Struktura

Time-series anomaly detection with no training data.

Struktura is a Rust crate and CLI. It measures the correlation structure of a time series with detrended fluctuation analysis (DFA) and runs a streaming monitor (struktura guard) that calibrates itself on the first rows of your data: a CSV goes in, an exit code comes out.

Why Struktura?

Most monitoring checks whether a value leaves a band (“is the temperature above 80 C?”). That is fast when a fault makes values bigger. It misses faults that change how values follow each other while their spread stays the same, and it false-alarms on healthy signals that wander slowly. Struktura’s monitor looks at structure as well as level. Use it next to limit checks, not instead of them.

Measured results, with the command behind each number, are in the README and in docs/claims.tsv, which CI re-runs.

Install

cargo add struktura

Quick Start

Analyze any signal

#![allow(unused)]
fn main() {
use struktura::{analyze, health_check, HealthVerdict};

// Load your time series data
let data: Vec<f64> = load_csv("vibration.csv");

// Analyze structural health
let law = analyze(&data);
println!("DFA alpha: {:.3}", law.dfa.alpha);
println!("R-squared: {:.4}", law.dfa.r_squared);
println!("Quality: {:?}", law.quality);

// Compare against a known healthy baseline
let verdict = health_check(&law, 0.389); // baseline from calibration
match verdict {
    HealthVerdict::Healthy => println!("System is healthy"),
    HealthVerdict::Watch => println!("Minor structural shift detected"),
    HealthVerdict::Warning => println!("Significant structural change"),
    HealthVerdict::Critical => println!("CRITICAL: Major structural departure"),
}
}

What the numbers mean

  • DFA alpha near 0.5: uncorrelated noise — no exploitable structure
  • DFA alpha 0.5-1.0: long-range correlated — healthy complex system
  • Alpha shift > 0.08 from baseline: something is changing
  • R-squared > 0.7: the measurement is reliable
  • R-squared < 0.7: ABSTAIN — not enough structure to diagnose

How DFA Works

Detrended Fluctuation Analysis measures long-range correlation in a time series.

The algorithm in 4 steps

  1. Profile: compute the cumulative sum of deviations from the mean
  2. Box: divide the profile into non-overlapping boxes of size s
  3. Detrend: fit and subtract a linear trend within each box
  4. Scale: measure the root-mean-square residual F(s) at each box size

The scaling exponent alpha is the slope of log F(s) vs log s.

What alpha means

Alpha rangeInterpretation
~0.5White noise (uncorrelated)
0.5 - 1.0Long-range correlated (healthy complexity)
~1.01/f noise (pink noise)
> 1.0Non-stationary / trend-dominated

When it helps anomaly detection

Many healthy systems keep a characteristic alpha, and some faults change it. Whether alpha moves before an amplitude monitor fires depends on the fault. On the bundled CWRU bearing excerpts alpha drops from 0.689 to 0.183 while RMS amplitude rises 11% (struktura demo). On the IMS run-to-failure bearing a plain RMS threshold trips earlier than the alpha alarm (see REPRODUCIBILITY.md). So alpha complements amplitude checks; it does not replace them.

References

  1. Peng et al., “Mosaic organization of DNA nucleotide sequences,” Physical Review E 49(2), 1994.
  2. Peng et al., “Quantification of scaling exponents,” Chaos 5(1), 1995.
  3. Goldberger et al., “Fractal dynamics in physiology,” PNAS 99(suppl 1), 2002.

Bearing Fault Detection

On 12 kHz vibration data from the Case Western Reserve University Bearing Data Center, DFA α separates a normal bearing from one with an inner-race fault:

ConditionDFA α
Normal0.689
Inner-race fault0.183

Reproduce with struktura demo (the data is embedded). CI re-checks these two numbers (docs/claims.tsv, row bearing-alpha). Other fault types (outer race, ball) are not part of the checked set.

How to use it

#![allow(unused)]
fn main() {
use struktura::{analyze, health_check};

let normal = analyze(&normal_vibration);
let baseline = normal.dfa.alpha; // establish during healthy operation

// Later, during monitoring:
let current = analyze(&current_vibration);
let verdict = health_check(&current, baseline);
}

health_check compares α against the baseline with fixed thresholds (0.03 / 0.08 / 0.15). They are defaults, not significance tests; decide what shift matters for your machine.

What DFA measures

DFA measures how the fluctuations of a signal scale with the window size, which reflects its correlation structure. A fault can change that structure without adding a new frequency peak, so DFA complements spectral (FFT) and amplitude checks. On the NASA IMS run-to-failure bearing, a plain RMS threshold alarmed earlier than struktura, so do not treat DFA as an early-warning method.

Cross-Domain Results

The same DFA runs on very different signals. These are α values measured on bundled data; only the bearing pair is a normal-vs-fault comparison.

DomainSignalDFA αR²
BearingsCWRU 12 kHz vibration, normal0.689
BearingsCWRU 12 kHz vibration, inner-race fault0.183
GenomeHuman chr1 GC% in 1 kb windows (struktura genome)0.9670.980

Shuffle control

To check that a measured structure is real and not an artifact, permute the signal and run DFA again. If shuffling moves α toward 0.5, the order of the values carried the structure. struktura prove <file> runs this test with a bootstrap interval on α.

The full list of checked numbers, with commands and controls, is docs/claims.tsv.

API Reference

Core functions

dfa(values: &[f64]) -> DfaResult

Compute the DFA scaling exponent. Returns alpha and R-squared.

acr(values: &[f64]) -> DfaResult

Compute autocorrelation decay exponent.

analyze(values: &[f64]) -> StructuralLaw

Full structural analysis: DFA + ACR + statistics.

health_check(law: &StructuralLaw, baseline: f64) -> HealthVerdict

Compare current DFA alpha against a baseline.

Types

DfaResult { alpha: f64, r_squared: f64 }

StructuralLaw { hurst, dfa, acr, mean, std_dev, kurtosis, p99, max, n, quality }

LawQuality — Exact, Strong, Good, Approx, Abstain, Insufficient

HealthVerdict — Healthy, Watch, Warning, Critical

Thresholds

Shift from baselineVerdict
< 0.03Healthy
0.03 - 0.08Watch
0.08 - 0.15Warning
> 0.15Critical