npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@iyulab/u-insight

v0.29.1

Published

Statistical analysis and data profiling engine with C FFI bindings.

Readme

u-insight

Crates.io NuGet docs.rs CI

A statistical analysis and data profiling engine in Rust with C FFI bindings.

What's New (unreleased)

  • SPC control charts, process capability, sigma ↔ PPM and Weibull reliability are no longer in the C ABI or in UInsight. They are the u-analytics crate's own surface, carried to .NET by UAnalytics and to JavaScript by @iyulab/u-analytics, which already had every function and newer versions of them (Phase II limits, structured refusals). CHANGELOG.md lists each removed method with its replacement.

What's New in 0.20.0

  • Box-Cox capability reports when its λ search hit a range limit (lambda_at_bound), searches [-5, 5] by default or a range you pass, and runs without specification limits (λ only). C# BoxCoxCapability(data, usl, lsl, lambdaRange).
  • Normal tail probabilities (Anderson-Darling, rank-test p-values, sigma ↔ PPM) are tail-precise (u-numflow 0.6).

What's New in 0.18.0

  • Univariate time-series primitives, pure Rust on every transport (u-analytics 0.11 / u-numflow 0.5): insight_estimate_period — the dominant period of a series (AutoPeriod: permutation-thresholded periodogram peaks refined on the autocorrelation function, deterministic) — and insight_spectral_residual — one-shot anomaly scoring by spectral residual saliency (Ren et al. 2019) with an expected value and a coverage band per point. C# EstimatePeriod / SpectralResidual(data, options?); WASM estimate_period / spectral_residual.

What's New in 0.14.0

  • 26 new FFI functions exposing u-analytics domains that were already a dependency but not previously reachable from outside this crate: Mann-Kendall trend test, kernel density estimation, the full SPC control chart family (X-bar-R/S, Individual-MR, P/NP/C/U, Laney P'/U', G/T), process capability (Cp/Cpk/Pp/Ppk/Cpm, Box-Cox, percentile-based, sigma↔PPM), and Weibull reliability analysis (MLE/MRR fitting, survival, hazard, MTBF, B-life). See the C FFI section below and CHANGELOG.md for the full function list.
  • Matching C# bindings for all of the above, including the binding's first double?-based optional parameters/return values (ProcessCapability, PpmToSigma, etc.), converting to/from NaN only at the P/Invoke boundary.

What's New in 0.9.1

  • BREAKING — Rust: InsightError::NonNumericColumn variant removed. The 0.9.0 audit redirected all internal call sites to DegenerateData, leaving the variant unused. Removed per Delete over deprecate policy. External match arms over InsightError must drop the corresponding branch.

What's New in 0.9.0

  • Kendall tau-b correlation added to CorrelationMethod (Pearson / Spearman / Kendall)
  • Outlier fences exposed on OutlierResult — lower_fence, upper_fence, center, spread
  • detect_outliers_slice(&[f64], method) helper for raw-slice input
  • vif_analysis() and condition_number() standalone multicollinearity diagnostics
  • WASM: correlation_matrix accepts optional _method field ("pearson" | "spearman" | "kendall"); new detect_univariate_outliers, vif_diagnostic, condition_number_diagnostic
  • C#: CorrelationMethodKind enum + Correlate(data, method) parameter
  • BREAKING — Rust: Non-finite numeric inputs now return InsightError::DegenerateData (was NonNumericColumn); audit covered 11 call sites
  • BREAKING — Rust: OutlierResult gained 4 new fields (exhaustive pattern matches must be updated)
  • BREAKING — FFI: insight_correlation signature gained a method: u32 parameter (use INSIGHT_CORR_PEARSON = 0 to keep prior behaviour)
  • BREAKING — C#: Correlate(...) now takes an optional CorrelationMethodKind parameter (default Pearson keeps existing call-sites compiling)

Overview

u-insight transforms raw tabular data into actionable statistical insights. It operates in two distinct layers with opposite assumptions about input data quality:

CSV (raw)
  │
  ├─→ Profiling ─→ "What is the state of this data?"
  │     Tolerates dirty data (missing values, type mismatches expected)
  │
  │   (external preprocessing)
  │
  └─→ Analysis  ─→ "What can we learn from this data?"
        Requires clean numeric data (no NaN, no missing)

Built on u-analytics (statistical algorithms), u-numflow (math primitives).

Modules

Data Layer

| Module | Description | |--------|-------------| | dataframe | Column-major tabular data model (DataFrame, Column, DataType) | | csv_parser | CSV parsing with automatic type inference | | error | Error types (InsightError) |

Profiling Layer (dirty data tolerated)

| Module | Description | |--------|-------------| | profiling | Column-level and dataset-level data profiling — descriptive stats, missing analysis, outlier flagging (IQR/Z-score/Modified Z-score), diagnostic flags |

Analysis Layer (clean data required)

| Module | Description | |--------|-------------| | analysis | Correlation (Pearson/Spearman), regression (simple/multiple OLS), Cramer's V contingency analysis | | clustering | K-Means++ (auto-K, Gap Statistic), Mini-Batch K-Means, DBSCAN, Hierarchical Agglomerative (Single/Complete/Average/Ward), HDBSCAN | | distribution | ECDF, histogram bins (Sturges/Scott/FD), QQ-plot, normality tests (KS, Jarque-Bera, Shapiro-Wilk, Anderson-Darling), Grubbs test, distribution fitting | | pca | Principal Component Analysis with auto-scaling option | | isolation_forest | Isolation Forest anomaly detection (Liu et al. 2008) | | lof | Local Outlier Factor (LOF) density-based anomaly detection | | mahalanobis | Mahalanobis distance multivariate outlier detection | | feature_importance | Variance threshold, correlation filter, VIF, condition number, composite importance, ANOVA F-test selection, Mutual Information, Permutation Importance |

FFI Layer

| Module | Description | |--------|-------------| | ffi | C FFI bindings — 46 functions, 30 #[repr(C)] structs, auto-generated C header via cbindgen |

Quick Start

use u_insight::csv_parser::CsvParser;
use u_insight::profiling::profile_dataframe;

// 1. Parse CSV
let csv = "name,value,active\nAlice,1.5,true\nBob,2.3,false\nCharlie,3.1,true\n";
let df = CsvParser::new().parse_str(csv).unwrap();

// 2. Profile
let profiles = profile_dataframe(&df);

Clustering

use u_insight::clustering::{kmeans, dbscan, KMeansConfig, DbscanConfig};

let data = vec![
    vec![0.0, 0.0], vec![0.5, 0.5],
    vec![10.0, 10.0], vec![10.5, 10.5],
];

// K-Means
let km = kmeans(&data, &KMeansConfig::new(2)).unwrap();
assert_eq!(km.k, 2);

// DBSCAN
let db = dbscan(&data, &DbscanConfig::new(1.5, 2)).unwrap();
assert_eq!(db.n_clusters, 2);

Distribution Analysis

use u_insight::distribution::{distribution_analysis, DistributionConfig};

let data: Vec<f64> = (0..50).map(|i| (i as f64 - 25.0) * 0.2).collect();
let result = distribution_analysis(&data, &DistributionConfig::default()).unwrap();
println!("Normal: {}", result.normality.is_normal);

C FFI

u-insight builds as cdylib + staticlib for cross-language interop. A C header (u_insight.h) is auto-generated by cbindgen at build time.

Profiling

| Function | Description | |----------|-------------| | insight_profile_csv | Profile a CSV string → opaque context | | insight_profile_json | Profile a JSON string → opaque context | | insight_profile_free | Free profile context | | insight_profile_row_count | Row count from profile | | insight_profile_col_count | Column count from profile | | insight_profile_column | Get column summary |

Clustering

| Function | Description | |----------|-------------| | insight_kmeans | K-Means++ clustering | | insight_mini_batch_kmeans | Mini-Batch K-Means clustering | | insight_dbscan | DBSCAN density-based clustering | | insight_hierarchical | Hierarchical Agglomerative clustering (4 linkages) | | insight_hdbscan | HDBSCAN clustering with membership probabilities | | insight_gap_statistic | Gap statistic for optimal K selection | | insight_silhouette | Silhouette score for cluster validation |

Dimensionality Reduction

| Function | Description | |----------|-------------| | insight_pca | Principal Component Analysis |

Anomaly Detection

| Function | Description | |----------|-------------| | insight_isolation_forest | Isolation Forest anomaly detection | | insight_lof | Local Outlier Factor detection | | insight_mahalanobis | Mahalanobis distance outlier detection |

Statistical Analysis

| Function | Description | |----------|-------------| | insight_correlation | Pearson correlation matrix | | insight_regression | Simple linear regression | | insight_cramers_v | Cramer's V contingency analysis |

Distribution

| Function | Description | |----------|-------------| | insight_distribution | Normality testing (KS, JB, SW, AD) |

Changepoint Detection

| Function | Description | |----------|-------------| | insight_pelt | PELT changepoint detection (univariate) | | insight_pelt_multi | PELT changepoint detection (multivariate) |

Time Series

| Function | Description | |----------|-------------| | insight_estimate_period | Dominant period of a series (AutoPeriod); period 0 = none, candidates listed | | insight_free_period_estimate | Frees the candidates of a CPeriodEstimate | | insight_spectral_residual | Spectral residual anomaly scoring (Ren et al. 2019); null options = paper defaults | | insight_free_spectral_residual_result | Frees the points of a CSpectralResidualResult |

Trend & Density Estimation

| Function | Description | |----------|-------------| | insight_mann_kendall | Mann-Kendall trend test with Sen's slope | | insight_kde | Gaussian kernel density estimation (Silverman/Scott/manual bandwidth) |

SPC, process capability and Weibull reliability

Control charts, process capability (normal, Box-Cox, percentile), sigma ↔ PPM and Weibull fitting and reliability are not part of this library's C ABI. They come from u-analytics — over its own C ABI and the UAnalytics NuGet package, and over @iyulab/u-analytics for JavaScript — which is the one place they are implemented and kept current.

Feature Importance

| Function | Description | |----------|-------------| | insight_feature_importance | Composite feature importance scores | | insight_anova_select | ANOVA F-test feature selection | | insight_mutual_info | Mutual information feature ranking | | insight_permutation_importance | Permutation importance for regression |

Memory Management

| Function | Description | |----------|-------------| | insight_free_labels | Free u32 label arrays | | insight_free_i32_array | Free i32 arrays | | insight_free_f64_array | Free f64 arrays | | insight_free_anova_features | Free ANOVA feature arrays | | insight_free_mi_features | Free MI feature arrays | | insight_free_perm_features | Free permutation importance arrays | | insight_free_pelt_result | Free PELT changepoint results | | insight_free_kde_result | Free KDE results | | insight_free_variables_chart_result | Free variables control chart results | | insight_free_attribute_chart_result | Free attributes control chart results | | insight_free_laney_chart_result | Free Laney P'/U' chart results | | insight_free_rare_event_chart_result | Free G/T chart results |

Error & Version

| Function | Description | |----------|-------------| | insight_last_error | Last error message (thread-local) | | insight_last_error_parameter | Name of the argument or option the last INSIGHT_ERR_INVALID_PARAM is about (chi2_quantile, threshold, …), or null (thread-local) | | insight_last_error_json | The last refusal as JSON — {"error", "code", …fields}, the same code and fields as the WebAssembly Error (see Errors below), or null (thread-local) | | insight_clear_error | Clear error state | | insight_version | Library version string |

All FFI functions that accept data pointers use catch_unwind to prevent panics from crossing the FFI boundary.

C# Binding (UInsight)

Install via NuGet — native libraries are bundled automatically:

dotnet add package UInsight
using UInsight;

using var client = new InsightClient();
Console.WriteLine(client.GetVersion());

var data = new double[,] { {0,0}, {1,1}, {10,10}, {11,11} };
var result = client.KMeans(data, k: 2);
Console.WriteLine($"K={result.K}, WCSS={result.Wcss:F2}");

The binding is in bindings/csharp/UInsight/ with:

  • Interop/NativeLibrary.cs — [LibraryImport] declarations for the FFI functions the client calls
  • Interop/NativeStructs.cs — [StructLayout] mappings for the C structs they exchange
  • InsightClient.cs — High-level managed API (automatic memory management)
  • InsightException.cs — Error code to exception conversion; Category classifies the error, Parameter names the argument or option an invalid-parameter error is about, and Reason / Details carry the same code and fields as the WebAssembly Error

Test Status

474 lib tests + 53 doc-tests = 527 total
0 clippy warnings
Build: lib + cdylib + staticlib
C header: auto-generated via cbindgen (40 structs, 73 functions)

Scope & Non-Goals

In Scope:

  • Data profiling (dirty data → quality report + diagnostic flags)
  • Statistical analysis (clean data → patterns + relationships)
  • Correlation, regression, clustering, PCA, anomaly detection
  • Feature importance and selection (ANOVA, MI, Permutation)
  • Distribution analysis and normality testing
  • C FFI for cross-language use
  • C# binding (UInsight NuGet package)

Out of Scope:

  • Visualization / charting
  • Data cleaning / transformation / imputation
  • ML model training / deployment
  • Deep learning

Requirements

  • Rust 1.85+
  • Dependencies: u-analytics, u-numflow

WebAssembly / npm

Available as an npm package via wasm-pack.

npm install @iyulab/u-insight

Quick Start

import { describe, kmeans } from '@iyulab/u-insight';

const stats = describe({ col1: [1, 2, 3], col2: [4, 5, 6] });

TypeScript

Every exported function declares its parameter and return types, and the declarations are generated from the same structs the binding reads and serialises, so they cannot drift from what it actually accepts and returns:

export function isolation_forest(data: number[][], config: IsolationForestConfigDto): IsolationForestDto;

export interface IsolationForestDto {
    scores: number[];
    anomalies: boolean[];   // a per-point mask, not a list of indices
    threshold: number;
    anomaly_count: number;
    anomaly_fraction: number;
}

An optional field is declared T | undefined, which is what the binding sends. Nothing needs an as cast -- and a wrong assumption about a result's shape is a compile error rather than something that renders incorrectly.

The same holds on the way in: a misspelt option (linkage: "centroid", method: "mutual-info", bin_method: "sturgess"), a field a configuration does not have, or a flat array where a matrix belongs does not compile. Column-major inputs are declared by hand, since their keys are your column names: DescribeInput, CorrelationInput (with _method), VifInput (with _threshold) and Record<string, number[]>.

The binding still validates every input at the boundary, for JavaScript callers and for values that reach it through a cast.

Errors

A refusal throws an Error whose message is readable text and which carries a code naming the reason, next to the values behind it — so a program can point at what to change without parsing the message. The C ABI reports the same code and fields from insight_last_error_json, and .NET as InsightException.Reason and InsightException.Details:

import { hierarchical } from '@iyulab/u-insight';

try {
  hierarchical([[0, 0], [1, 1], [5, 5]], { linkage: 'centroid', n_clusters: 2 });
} catch (err) {
  console.log(err.code, err.parameter, err.got, err.expected);
  // unknown_option linkage centroid [ 'single', 'complete', 'average', 'ward' ]
}

| code | Fields | Meaning | |---|---|---| | unknown_option | parameter, got, expected | A linkage, method, bin_method or _method that names none of the supported values | | missing_option | parameter, expected | A hierarchical config with neither n_clusters nor distance_threshold | | invalid_option | parameter | An option value the analysis refuses (a non-positive threshold, a _threshold that is not a number, config.distance_threshold given with n_clusters, …) | | parameter_out_of_range | parameter (and index, min, max, got where they apply) | A spectral_residual option outside its domain, or a silhouette label ≥ k | | insufficient_data | min, got (and parameter) | Fewer rows or observations than the method needs | | value_not_finite | parameter, index | A NaN or ±Infinity anywhere in an argument — parameter is the path to it (data.b), index its position in that array, or null. describe reads NaN as a missing value, like null | | dimension_mismatch | expected, got (and parameter, index) | Lengths that have to agree do not — a row shorter than the first (index is that row), labels vs data rows, … | | empty_input | parameter | An input with no columns | | missing_values | column, count | A column with missing values where the analysis needs complete data | | not_a_class_label | parameter, index, got | A classification target (feature_importance anova / mutual_info) value that is not a whole number ≥ 0 | | degenerate_data | — | Constant columns, a singular matrix, … | | column_not_found | column | A column name the data does not have | | computation_failed | operation | A numerical step that did not converge or produced no result | | malformed_input | parameter (and column, index) | An argument of the wrong shape or type, a non-numeric column entry (index is its position), or a JSON string |

Functions

describe(data) -> [ColumnResult]

Descriptive statistics per column. Input: column-major { "col1": [1,2,3] }. null and NaN are both counted as missing (null_count); ±Infinity is refused.

Output: Array of { name, data_type, numeric: { count, min, max, mean, median, std_dev, variance, skewness, kurtosis, q1, q3, iqr, p5, p95, ... } }.

correlation_matrix(data) -> CorrelationResult

Pearson correlation matrix. Input: column-major { "col1": [1,2,3], "col2": [4,5,6] }.

Output:

{ "names": ["col1","col2"], "matrix": [1,0.99,0.99,1], "n": 2, "high_pairs": [{ "col_a": "col1", "col_b": "col2", "r": 0.99, "p_value": 0.01 }] }

kmeans(data, k) -> KMeansResult

K-Means++ clustering on row-major data [[x,y,...], ...].

Output:

{ "k": 3, "labels": [0,0,1,1,2,2], "centroids": [[...]], "wcss": 5.2, "iterations": 12, "cluster_sizes": [2,2,2] }

Clusters are numbered by first appearance — the first point is in cluster 0, the first point outside it in cluster 1, and so on; centroids and cluster_sizes follow that numbering. dbscan and hierarchical number their clusters the same way, so the same group gets the same number whichever method found it.

silhouette(data, labels, k) -> SilhouetteResult

Silhouette analysis for an existing clustering assignment. Works with any clustering output (kmeans, dbscan, hierarchical, etc.). data is row-major [[x,y,...], ...], labels is one cluster id per row (each < k), k is the number of distinct clusters. O(n²) — use sparingly on very large inputs.

Output:

{ "avg": 0.74, "per_sample": [0.81, 0.79, 0.62, ...] }

avg ranges from -1 (wrong cluster) to +1 (well-separated); singleton-cluster points report 0.0 in per_sample.

pca(data, config) -> PcaResult

Principal Component Analysis on row-major data. config: { "n_components": 2 } or { "n_components": 2, "auto_scale": false }.

Config fields:

  • n_components — number of components to keep.
  • auto_scale — standardise each column before the decomposition (correlation-matrix PCA; default true, the same default as the C# binding). Set false for covariance-matrix PCA, where a column in large units dominates the leading components. stds in the output are the scales used (all 1 when false).

Output:

{ "n_components": 2, "n_features": 4, "eigenvalues": [3.1,0.9], "explained_variance_ratio": [0.77,0.23], "cumulative_variance_ratio": [0.77,1.0], "loadings": [[...]], "scores": [[...]], "means": [...], "stds": [...] }

dbscan(data, config) -> DbscanResult

DBSCAN density-based clustering. config: { "epsilon": 1.5, "min_samples": 3 }.

Output:

{ "labels": [0,0,null,1,1], "n_clusters": 2, "noise_count": 1, "cluster_sizes": [2,2], "core_points": [true,true,false,true,true] }

hierarchical(data, config) -> HierarchicalResult

Hierarchical agglomerative clustering (nearest-neighbor-chain, O(n²) time / O(n²) memory). config: { "linkage": "ward", "n_clusters": 3 } or { "linkage": "single", "distance_threshold": 5.0 }.

Config fields:

  • linkage — "single" | "complete" | "average" | "ward" (default "ward"). Any other name is refused.
  • n_clusters — flat clusters to extract (mutually exclusive with distance_threshold).
  • distance_threshold — dendrogram cut height (mutually exclusive with n_clusters).
  • max_points — memory guard; inputs with more points are rejected before allocating the O(n²) distance matrix. Omit for the default (10000, ≈400 MB matrix); set 0 to disable. Raise it for large native batches; lower it for tight memory (e.g. a browser tab).
// large dataset on a memory-constrained page: cap it explicitly
hierarchical(data, { linkage: "ward", n_clusters: 3, max_points: 5000 });

Output:

{ "merges": [{ "cluster_a": 0, "cluster_b": 1, "distance": 1.2, "size": 2 }], "labels": [0,0,1,1,2], "n_clusters": 3 }

isolation_forest(data, config) -> IsolationForestResult

Isolation Forest anomaly detection. config: { "n_estimators": 100, "contamination": 0.1, "seed": 42 }.

Output:

{ "scores": [0.45, 0.82], "anomalies": [false, true], "threshold": 0.65, "anomaly_count": 1, "anomaly_fraction": 0.5 }

lof(data, config) -> LofResult

Local Outlier Factor anomaly detection. config: { "k": 20, "threshold": 1.5 }.

Output:

{ "scores": [1.0, 2.3], "anomalies": [false, true], "threshold": 1.5, "anomaly_count": 1, "anomaly_fraction": 0.5 }

distribution_analysis(data, config) -> DistributionResult

Distribution analysis on a 1-D array. config: { "bin_method": "freedman_diaconis", "bins": null, "significance_level": 0.05, "compute_ecdf": true, "compute_histogram": true, "compute_qq_plot": true, "fit_distributions": false }.

  • bin_method: "sturges" | "scott" | "freedman_diaconis" — automatic bin count rule (default "freedman_diaconis"). Any other name is refused, with or without bins.
  • bins (optional, integer >= 1): explicit histogram bin count. When set it takes precedence over bin_method, and the histogram method field echoes "Fixed(n)".

Output:

{ "n": 100, "ecdf": { "values": [...], "probabilities": [...] }, "histogram": { "n_bins": 10, "bin_width": 0.5, "edges": [...], "counts": [...] }, "qq_plot": { "theoretical": [...], "sample": [...] }, "normality": { "shapiro_wilk": { "statistic": 0.98, "p_value": 0.45, "rejected": false }, "is_normal": true }, "fits": [] }

regression(data) -> RegressionResult

OLS regression analysis.

Input:

{ "predictors": { "x1": [1,2,3,4,5] }, "target": [2.1, 3.9, 6.1, 7.9, 10.1], "target_name": "y" }

Output:

{ "target_name": "y", "predictor_names": ["x1"], "r_squared": 0.99, "adj_r_squared": 0.99, "coefficients": [0.1, 2.0], "p_values": [0.9, 0.0001], "vif": [1.0], "f_p_value": 0.0001 }

feature_importance(data) -> FeatureImportanceResult

Feature importance via permutation, ANOVA, or mutual information.

Input:

{ "features": { "f1": [1,2,3], "f2": [5,4,3] }, "target": [0,0,1], "method": "permutation", "n_repeats": 5, "seed": 42 }

Output:

{ "method": "permutation", "features": [{ "name": "f1", "index": 0, "score": 0.8, "std_dev": 0.1 }], "baseline_score": 0.5 }

estimate_period(data) -> PeriodEstimate

Dominant period of a univariate series — AutoPeriod (Vlachos, Yu & Castelli 2005): peaks of the detrended, zero-padded periodogram above a permutation threshold (100 seeded shuffles, so the estimate is deterministic), each refined on the autocorrelation function to the integer lag that is a local maximum above the 1.96/√n bound. At least 8 finite values.

Input: { "data": [0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1] }

Output:

{ "period": 7, "candidates": [{ "period": 7, "acf": 0.71, "bin": 18, "power": 21.3, "power_share": 0.62 }],
  "n": 16, "acf_threshold": 0.49, "power_threshold": 6.8 }
// `acf` has the (n - lag)/n bias of the estimator undone, so it is comparable
// against `acf_threshold`. The period is exact whether or not the series is a
// whole number of cycles long.

period is null — explicitly, not an error — when no periodicity passes both stages (a constant, a pure trend, white noise). Only periods from 2 to n/2 are admissible.

spectral_residual(data) -> SpectralResidualResult

Score every point for anomalies by spectral residual saliency (Ren et al. 2019) — spikes, steps and dropouts, without a trained model and without assuming a period. At least 12 finite values; the options default to the paper's.

Input:

{ "data": [1, 1.1, 0.9, 1, 6, 1, 1.1, 0.9, 1, 1, 1.1, 0.9],
  "averaging_window": 3, "judgement_window": 40, "threshold": 3.0,
  "min_zscore": 1.5, "sensitivity": 70, "batch_size": null }

Output:

{ "points": [{ "index": 4, "value": 6, "saliency": 2.1, "score": 5.3,
               "expected": 1.0, "lower": 0.9, "upper": 1.1, "is_anomaly": true, "near_edge": false }],
  "anomalies": [4] }

expected is the low-frequency reconstruction of the series with its anomalies replaced by their neighbours and lower/upper the band of sensitivity percent coverage around it — chart information; the anomaly decision is the score against threshold, gated by min_zscore against the level of the window before the point.

npm (WebAssembly)

npm install @iyulab/u-insight

The package resolves per environment via a conditional exports map:

| Environment | Entry | |---|---| | Bundlers (webpack, Vite, …) | ESM + WebAssembly ESM-integration (default condition) | | Node.js — require(), ESM import, CJS TS runners (tsx, ts-node) | CJS glue loading the wasm from the filesystem (node condition) — no loader hooks or flags |

A browser without a bundler is not supported: the package loads its .wasm file with an ES module import, which browsers refuse (application/wasm is not a module script type), so <script type="module"> from a CDN fails, and CDN re-bundling services fail on the same import. Use a bundler or Node.

Related

License

MIT License