1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//! Adaptive-threshold layer on top of [`crate::RandomCutForest`].
//!
//! Where the bare forest returns a raw anomaly score in `[0, ∞)`,
//! [`ThresholdedForest`] tracks the running distribution of those
//! scores and emits a graded verdict — `is_anomaly: bool`,
//! `grade ∈ [0, 1]`, and the `threshold` in effect at observation
//! time. Callers no longer have to hand-pick a magic threshold per
//! deployment: the detector adapts to the traffic it sees.
//!
//! Inspired by the AWS *Thresholded Random Cut Forest* (TRCF)
//! facility in `randomcutforest-parkservices`, but intentionally
//! lighter: only the adaptive μ + z·σ threshold over an EMA of the
//! score stream, without the short/long-term duality or the
//! near-threshold heuristics of the full TRCF.
//!
//! # Example
//!
//! ```ignore
//! use anomstream_core::ThresholdedForestBuilder;
//!
//! let mut detector = ThresholdedForestBuilder::<4>::new()
//! .num_trees(100)
//! .sample_size(256)
//! .z_factor(3.0)
//! .min_observations(32)
//! .seed(42)
//! .build()?;
//!
//! for packet in stream_of_feature_vectors {
//! let verdict = detector.process(packet)?;
//! if verdict.is_anomaly() {
//! eprintln!(
//! "anomaly: grade={:.2} score={} threshold={:.3}",
//! verdict.grade(),
//! verdict.score(),
//! verdict.threshold(),
//! );
//! }
//! }
//! # Ok::<(), anomstream_core::RcfError>(())
//! ```
pub use ;
pub use ThresholdedForest;
pub use AnomalyGrade;
pub use EmaStats;