pub struct ThresholdedForest<const D: usize> { /* private fields */ }Expand description
Adaptive-threshold detector composed of a RandomCutForest plus
a running EMA of the anomaly-score stream.
Instantiate via crate::ThresholdedForestBuilder. The type
parameter D is the per-point dimensionality, pinned at compile
time exactly like the bare RandomCutForest.
§Examples
use anomstream_core::ThresholdedForestBuilder;
let mut detector = ThresholdedForestBuilder::<2>::new()
.num_trees(50)
.sample_size(64)
.min_observations(4)
.seed(42)
.build()
.unwrap();
for i in 0..64 {
let v = f64::from(i) * 0.01;
let _ = detector.process([v, v + 0.5]).unwrap();
}
let verdict = detector.process([10.0, 10.0]).unwrap();
assert!(verdict.ready());Implementations§
Source§impl<const D: usize> ThresholdedForest<D>
impl<const D: usize> ThresholdedForest<D>
Sourcepub fn attribution_stability(
&self,
point: &[f64; D],
) -> RcfResult<AttributionStability>
pub fn attribution_stability( &self, point: &[f64; D], ) -> RcfResult<AttributionStability>
Inter-tree dispersion of the attribution on point. Delegates
to the underlying forest — the threshold layer does not
influence attribution.
§Errors
Source§impl<const D: usize> ThresholdedForest<D>
impl<const D: usize> ThresholdedForest<D>
Sourcepub fn bootstrap<I>(&mut self, points: I) -> RcfResult<BootstrapReport>
pub fn bootstrap<I>(&mut self, points: I) -> RcfResult<BootstrapReport>
Replay historical points through the thresholded detector,
folding each one into the forest and the score-stream EMA
so the adaptive threshold is hot before the first live point.
Graded verdicts produced during the replay are discarded —
they would be misleading for historical data. The detector
is ready for live traffic as soon as
BootstrapReport::final_observations passes the configured
min_observations threshold.
Non-finite points are skipped and tallied in the report.
§Errors
Propagates Self::process failures other than
RcfError::NaNValue (absorbed and counted as a skip).
Source§impl<const D: usize> ThresholdedForest<D>
impl<const D: usize> ThresholdedForest<D>
Sourcepub fn group_scores(
&self,
point: &[f64; D],
groups: &FeatureGroups,
) -> RcfResult<GroupScores>
pub fn group_scores( &self, point: &[f64; D], groups: &FeatureGroups, ) -> RcfResult<GroupScores>
Decompose the anomaly attribution of point over groups.
Delegates to the underlying forest’s attribution — the
adaptive threshold layer does not influence the
decomposition.
§Errors
Same as crate::RandomCutForest::group_scores.
Source§impl<const D: usize> ThresholdedForest<D>
impl<const D: usize> ThresholdedForest<D>
Sourcepub fn to_bytes(&self) -> RcfResult<Vec<u8>>
pub fn to_bytes(&self) -> RcfResult<Vec<u8>>
Serialise the thresholded detector into a versioned binary blob.
The payload carries the underlying forest, the threshold configuration, and the EMA statistics — enough for a receiver to resume scoring and emitting graded verdicts without a warmup gap.
§Errors
Returns RcfError::SerializationFailed when the underlying
postcard encoder rejects the payload.
Sourcepub fn from_bytes(bytes: &[u8]) -> RcfResult<Self>
pub fn from_bytes(bytes: &[u8]) -> RcfResult<Self>
Reload a thresholded detector previously produced by
to_bytes.
§Errors
RcfError::DeserializationFailedwhen the byte slice is too short to hold the version prefix, longer thanMAX_DESERIALIZE_BYTES, or thepostcardpayload is malformed.RcfError::IncompatibleVersionwhen the embedded version does not matchTHRESHOLDED_PERSISTENCE_VERSION.
§Security
Designed for trusted checkpoints — see the module-level
# Security section. Use Self::from_bytes_with_max_size
when the deployment’s expected payload exceeds
MAX_DESERIALIZE_BYTES.
Sourcepub fn from_bytes_with_max_size(bytes: &[u8], max: usize) -> RcfResult<Self>
pub fn from_bytes_with_max_size(bytes: &[u8], max: usize) -> RcfResult<Self>
Variant of Self::from_bytes with a caller-supplied
byte-length cap.
§Errors
Same as Self::from_bytes with max replacing
MAX_DESERIALIZE_BYTES.
§Security
See module-level # Security notes.
Sourcepub fn to_path(&self, path: impl AsRef<Path>) -> RcfResult<()>
pub fn to_path(&self, path: impl AsRef<Path>) -> RcfResult<()>
Atomically serialise the thresholded detector to path. Same
atomic write discipline as RandomCutForest::to_path.
§Errors
RcfError::SerializationFailedfor any filesystem or encoder failure.
Sourcepub fn from_path(path: impl AsRef<Path>) -> RcfResult<Self>
pub fn from_path(path: impl AsRef<Path>) -> RcfResult<Self>
Reload a thresholded detector from path.
§Errors
RcfError::DeserializationFailedwhen the file cannot be read, exceedsMAX_DESERIALIZE_BYTES, or the payload is malformed.RcfError::IncompatibleVersionwhen the embedded version does not matchTHRESHOLDED_PERSISTENCE_VERSION.
§Security
Inherits the trust model of Self::from_bytes.
Source§impl<const D: usize> ThresholdedForest<D>
impl<const D: usize> ThresholdedForest<D>
Sourcepub fn from_parts(
forest: RandomCutForest<D>,
thresholded: ThresholdedConfig,
) -> RcfResult<Self>
pub fn from_parts( forest: RandomCutForest<D>, thresholded: ThresholdedConfig, ) -> RcfResult<Self>
Low-level constructor used by crate::ThresholdedForestBuilder::build.
Both forest and thresholded are expected to have been
validated upstream; this function only wires them together and
constructs the EMA.
§Errors
Propagates EmaStats::new failures (non-finite decay etc.).
Sourcepub fn with_metrics_sink(self, sink: Arc<dyn MetricsSink>) -> Self
pub fn with_metrics_sink(self, sink: Arc<dyn MetricsSink>) -> Self
Install a crate::MetricsSink — every subsequent
process / score_only call emits counters and histograms
into it. Does not propagate to the underlying forest;
install on the forest separately if you also want low-level
rcf_updates_total / rcf_score / rcf_deletes_total
events.
Sourcepub fn metrics_sink(&self) -> &Arc<dyn MetricsSink>
pub fn metrics_sink(&self) -> &Arc<dyn MetricsSink>
Read-only handle to the installed threshold-layer sink.
Sourcepub fn forest(&self) -> &RandomCutForest<D>
pub fn forest(&self) -> &RandomCutForest<D>
Read-only access to the underlying forest.
Sourcepub fn forest_config(&self) -> &RcfConfig
pub fn forest_config(&self) -> &RcfConfig
Read-only access to the forest configuration.
Sourcepub fn thresholded_config(&self) -> &ThresholdedConfig
pub fn thresholded_config(&self) -> &ThresholdedConfig
Threshold-layer configuration.
Sourcepub fn current_threshold(&self) -> f64
pub fn current_threshold(&self) -> f64
Current adaptive threshold. Clamped to the configured floor
whenever the detector has not yet accumulated enough
observations to trust the running statistic (stddev under
ZSigma, quantile under Quantile).
Sourcepub fn process(&mut self, point: [f64; D]) -> RcfResult<AnomalyGrade>
pub fn process(&mut self, point: [f64; D]) -> RcfResult<AnomalyGrade>
Score point against the current forest, grade it against
the adaptive threshold, insert it into the forest, then fold
the score into the running statistics.
The first call returns a warming-up verdict (ready = false,
is_anomaly = false) because the forest holds no leaves yet.
Subsequent calls within the min_observations warmup window
also return ready = false.
§Errors
RcfError::NaNValuewhen the point contains a non-finite component.- Any error bubbled up from
RandomCutForest::updateorRandomCutForest::score.
Sourcepub fn score_only(&self, point: &[f64; D]) -> RcfResult<AnomalyGrade>
pub fn score_only(&self, point: &[f64; D]) -> RcfResult<AnomalyGrade>
Score point and grade it without touching the forest or the
running statistics. Useful for re-evaluating a point against a
snapshot of the model without contaminating the training
stream.
On an empty forest (no points have been inserted yet), returns
a warming-up verdict (ready = false, is_anomaly = false)
rather than an error — mirrors Self::process’s cold-start
handling so callers can query the detector during the warmup
window without special-casing the empty case.
§Errors
RcfError::NaNValuewhen the point contains a non-finite component.- Any other error bubbled up from
RandomCutForest::score.
Sourcepub fn attribution(&self, point: &[f64; D]) -> RcfResult<DiVector>
pub fn attribution(&self, point: &[f64; D]) -> RcfResult<DiVector>
Compute the per-feature attribution of point’s anomaly score
against the underlying forest. Forwarded to
RandomCutForest::attribution; the threshold layer has no
bearing on attribution.
§Errors
Same as RandomCutForest::attribution.
Sourcepub fn score_only_many(
&self,
points: &[[f64; D]],
) -> RcfResult<Vec<AnomalyGrade>>
pub fn score_only_many( &self, points: &[[f64; D]], ) -> RcfResult<Vec<AnomalyGrade>>
Bulk-score a batch of points without touching the threshold
layer’s stats. Returns AnomalyGrades graded against the
current adaptive threshold — identical to what
Self::score_only would emit per point, but parallelised
across the batch via rayon when the parallel feature is
enabled.
§Errors
Propagates any Self::score_only error hit while
processing the batch.
Sourcepub fn attribution_many(&self, points: &[[f64; D]]) -> RcfResult<Vec<DiVector>>
pub fn attribution_many(&self, points: &[[f64; D]]) -> RcfResult<Vec<DiVector>>
Bulk per-feature attribution. Delegates to
RandomCutForest::attribution_many.
§Errors
Same as RandomCutForest::attribution_many.
Sourcepub fn forensic_baseline(
&self,
point: &[f64; D],
) -> RcfResult<ForensicBaseline<D>>
pub fn forensic_baseline( &self, point: &[f64; D], ) -> RcfResult<ForensicBaseline<D>>
Imputation-like forensic baseline. Delegates to
RandomCutForest::forensic_baseline.
§Errors
Same as RandomCutForest::forensic_baseline.
Sourcepub fn score_many_early_term(
&self,
points: &[[f64; D]],
config: EarlyTermConfig,
) -> RcfResult<Vec<EarlyTermScore>>
pub fn score_many_early_term( &self, points: &[[f64; D]], config: EarlyTermConfig, ) -> RcfResult<Vec<EarlyTermScore>>
Bulk early-termination scoring. Delegates to
RandomCutForest::score_many_early_term — the threshold
layer does not alter the scoring path.
§Errors
Sourcepub fn score_early_term(
&self,
point: &[f64; D],
config: EarlyTermConfig,
) -> RcfResult<EarlyTermScore>
pub fn score_early_term( &self, point: &[f64; D], config: EarlyTermConfig, ) -> RcfResult<EarlyTermScore>
Early-termination variant of the scoring path — delegates to
RandomCutForest::score_early_term. Does not update the
thresholded layer’s stats (this is a read path, not a
training path).
§Errors
Same as RandomCutForest::score_early_term.
Sourcepub fn reset_stats(&mut self)
pub fn reset_stats(&mut self)
Drop every statistic and warm-up sample. The underlying forest is left untouched — callers who want a full reset should rebuild via the builder. Used by tests and by callers that want to re-enter a warmup phase after a major regime change.
Sourcepub fn delete(&mut self, point_idx: usize) -> RcfResult<bool>
pub fn delete(&mut self, point_idx: usize) -> RcfResult<bool>
Retract a previously-observed point from the underlying forest
by its point_idx. Delegates to
RandomCutForest::delete — the threshold layer’s stats are
left untouched (they already reflect the score that was
emitted when the point was processed).
§Errors
Same as RandomCutForest::delete.
Sourcepub fn delete_by_value(&mut self, point: &[f64; D]) -> RcfResult<usize>
pub fn delete_by_value(&mut self, point: &[f64; D]) -> RcfResult<usize>
Retract every point whose stored value bit-matches point.
Delegates to RandomCutForest::delete_by_value.
§Errors
Same as RandomCutForest::delete_by_value.
Sourcepub fn process_indexed(
&mut self,
point: [f64; D],
) -> RcfResult<(usize, AnomalyGrade)>
pub fn process_indexed( &mut self, point: [f64; D], ) -> RcfResult<(usize, AnomalyGrade)>
Same as Self::process but returns the point_idx the
underlying forest assigned to the fresh observation, paired
with the usual graded verdict. Callers that want to later
retract the observation via Self::delete should store the
index from this call.
§Errors
Same as Self::process.
Sourcepub fn process_at(
&mut self,
point: [f64; D],
timestamp: u64,
) -> RcfResult<AnomalyGrade>
pub fn process_at( &mut self, point: [f64; D], timestamp: u64, ) -> RcfResult<AnomalyGrade>
Timestamped variant of Self::process — tags the freshly
inserted point with timestamp so callers can later prune
history via RandomCutForest::delete_before. Returns the
same graded verdict as Self::process.
§Errors
Same as Self::process.
Sourcepub fn process_indexed_at(
&mut self,
point: [f64; D],
timestamp: u64,
) -> RcfResult<(usize, AnomalyGrade)>
pub fn process_indexed_at( &mut self, point: [f64; D], timestamp: u64, ) -> RcfResult<(usize, AnomalyGrade)>
Timestamped variant of Self::process_indexed — records
the caller-supplied timestamp against the fresh point_idx.
§Errors
Same as Self::process_indexed.
Sourcepub fn delete_before(&mut self, cutoff: u64) -> RcfResult<usize>
pub fn delete_before(&mut self, cutoff: u64) -> RcfResult<usize>
Retract every point whose timestamp is strictly less than
cutoff. Forwards to RandomCutForest::delete_before.
§Errors
Propagates RandomCutForest::delete_before failures.
Trait Implementations§
Source§impl<const D: usize> Debug for ThresholdedForest<D>
impl<const D: usize> Debug for ThresholdedForest<D>
Source§impl<'de, const D: usize> Deserialize<'de> for ThresholdedForest<D>
impl<'de, const D: usize> Deserialize<'de> for ThresholdedForest<D>
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl<const D: usize> ForestSnapshot for ThresholdedForest<D>
impl<const D: usize> ForestSnapshot for ThresholdedForest<D>
Source§fn snapshot_num_trees(&self) -> usize
fn snapshot_num_trees(&self) -> usize
Source§fn snapshot_sample_size(&self) -> usize
fn snapshot_sample_size(&self) -> usize
Source§fn snapshot_dimension(&self) -> usize
fn snapshot_dimension(&self) -> usize
Source§fn snapshot_live_points(&self) -> usize
fn snapshot_live_points(&self) -> usize
Source§fn snapshot_updates_seen(&self) -> u64
fn snapshot_updates_seen(&self) -> u64
update calls observed since construction.Source§fn snapshot_memory_estimate(&self) -> usize
fn snapshot_memory_estimate(&self) -> usize
Auto Trait Implementations§
impl<const D: usize> Freeze for ThresholdedForest<D>
impl<const D: usize> !RefUnwindSafe for ThresholdedForest<D>
impl<const D: usize> Send for ThresholdedForest<D>
impl<const D: usize> Sync for ThresholdedForest<D>
impl<const D: usize> Unpin for ThresholdedForest<D>
impl<const D: usize> UnsafeUnpin for ThresholdedForest<D>
impl<const D: usize> !UnwindSafe for ThresholdedForest<D>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more