@iyulab/u-insight
v0.29.1
Published
Statistical analysis and data profiling engine with C FFI bindings.
Readme
u-insight
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 theu-analyticscrate's own surface, carried to .NET byUAnalyticsand to JavaScript by@iyulab/u-analytics, which already had every function and newer versions of them (Phase II limits, structured refusals).CHANGELOG.mdlists 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-numflow0.6).
What's New in 0.18.0
- Univariate time-series primitives, pure Rust on every transport
(
u-analytics0.11 /u-numflow0.5):insight_estimate_period— the dominant period of a series (AutoPeriod: permutation-thresholded periodogram peaks refined on the autocorrelation function, deterministic) — andinsight_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?); WASMestimate_period/spectral_residual.
What's New in 0.14.0
- 26 new FFI functions exposing
u-analyticsdomains 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 andCHANGELOG.mdfor 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/fromNaNonly at the P/Invoke boundary.
What's New in 0.9.1
- BREAKING — Rust:
InsightError::NonNumericColumnvariant removed. The 0.9.0 audit redirected all internal call sites toDegenerateData, leaving the variant unused. Removed perDelete over deprecatepolicy. Externalmatcharms overInsightErrormust 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 inputvif_analysis()andcondition_number()standalone multicollinearity diagnostics- WASM:
correlation_matrixaccepts optional_methodfield ("pearson"|"spearman"|"kendall"); newdetect_univariate_outliers,vif_diagnostic,condition_number_diagnostic - C#:
CorrelationMethodKindenum +Correlate(data, method)parameter - BREAKING — Rust: Non-finite numeric inputs now return
InsightError::DegenerateData(wasNonNumericColumn); audit covered 11 call sites - BREAKING — Rust:
OutlierResultgained 4 new fields (exhaustive pattern matches must be updated) - BREAKING — FFI:
insight_correlationsignature gained amethod: u32parameter (useINSIGHT_CORR_PEARSON= 0 to keep prior behaviour) - BREAKING — C#:
Correlate(...)now takes an optionalCorrelationMethodKindparameter (defaultPearsonkeeps 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 UInsightusing 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 callsInterop/NativeStructs.cs—[StructLayout]mappings for the C structs they exchangeInsightClient.cs— High-level managed API (automatic memory management)InsightException.cs— Error code to exception conversion;Categoryclassifies the error,Parameternames the argument or option an invalid-parameter error is about, andReason/Detailscarry the samecodeand fields as the WebAssemblyError
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-insightQuick 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; defaulttrue, the same default as the C# binding). Setfalsefor covariance-matrix PCA, where a column in large units dominates the leading components.stdsin the output are the scales used (all1whenfalse).
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 withdistance_threshold).distance_threshold— dendrogram cut height (mutually exclusive withn_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); set0to 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 withoutbins.bins(optional, integer >= 1): explicit histogram bin count. When set it takes precedence overbin_method, and the histogrammethodfield 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-insightThe 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
- u-analytics -- Statistical analytics
- u-numflow -- Mathematical primitives
License
MIT License
