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

@qe-libs/rena-wasm

v0.1.0

Published

JavaScript/WebAssembly ENA pipeline — thin orchestration layer over @qe-libs/libqe-wasm

Readme

@qe-libs/rena-wasm

JavaScript/WebAssembly ENA pipeline — thin orchestration layer over @qe-libs/libqe-wasm.

Handles data parsing, unit/conversation grouping, and the full accumulate → normalize → center → rotate → project → node-positions pipeline. All math is delegated to the libqe WASM module; no C++ compilation required here.


Installation

npm install @qe-libs/rena-wasm

Quick Start

import loadENA from '@qe-libs/rena-wasm';

const ena = await loadENA();

const model = ena.fit(rows, {
  codes:         ['Data', 'Technical.Constraints', 'Performance.Parameters'],
  units:         ['UserName', 'Condition'],
  conversations: ['Condition', 'GroupName'],
  window:        4,
  dims:          2,
});

model.centroids        // Float64Array  nUnits × dims
model.networks         // Float64Array  nUnits × nConnections (normed)
model.positions        // Float64Array  nCodes × dims
model.connectionNames  // ['Data & Technical.Constraints', ...]
model.unitLabels       // ['UserName1_ConditionA', ...]
model.columnNames      // ['SVD1', 'SVD2']

// Per-unit helpers
model.centroid('Alice_A')  // number[]  length = dims
model.network('Alice_A')   // number[]  length = nConnections

Rotation Methods

| Method | rotation option | Extra options | |---|---|---| | SVD (default) | 'svd' | — | | Means | 'mean' | groupA: [unitIdx, ...], groupB: [unitIdx, ...] |

// Means rotation — groupA/groupB are unit indices (position in unitLabels)
const model = ena.fit(rows, {
  codes, units, conversations,
  rotation: 'mean',
  groupA: [0, 1, 2],
  groupB: [3, 4, 5],
});

Accumulation Only

Returns raw (un-normalised) network vectors without running the full pipeline.

const { networks, unitLabels, connectionNames, nUnits, nConnections } =
  ena.accumulate(rows, { codes, units, conversations, window: 4 });

Advanced: Context Tensor Accumulation

Context tensors give per-factor-combination control over window sizes and weights — the JS equivalent of tma::accumulate_contexts() with HOO rules.

The tensor is a multi-dimensional array whose last axis is always size 2 (index 0 = weight, index 1 = window). Earlier axes correspond to factor columns in the data.

// Example: sender role (T=Teacher, S=Student) controls the window size.
// dims = [nRoleValues, 2]  →  Teacher uses window=4, Student uses window=2.
const model = ena.fit(rows, {
  codes, units, conversations,
  ordered: true,   // directed (n² connections) when using tensors
  tensor: {
    dims:         [2, 2],   // [nRoleValues=2, weight/window=2]
    dimsSender:   [0],      // axis 0 is a sender factor
    dimsReceiver: [],
    dimsMode:     [],
    factors:      ['Role'], // column in the data
    // Optional: explicit value → index mapping.  Inferred automatically if omitted.
    factorLevels: { Role: { 'Teacher': 0, 'Student': 1 } },
    // Flat column-major: [weight_T, weight_S, window_T, window_S]
    data: Float64Array.of(1, 1, 4, 2),
  },
});

Tensor layout

The data array is column-major with shape dims. The last axis selects weight (0) or window (1). For dims = [nA, nB, 2]:

data[a + nA*b + nA*nB*0]  →  weight for factor combination (a, b)
data[a + nA*b + nA*nB*1]  →  window for factor combination (a, b)

Factor axis roles

| Option | Meaning | |---|---| | dimsSender | These axes use the ground row's factor values when looking up the window | | dimsReceiver | These axes use the response row's factor values (overrides ground) | | dimsMode | These axes use a shared mode value |

defaultTensor helper

Express simple windowed accumulation as a tensor (IS_DEFAULT path):

import { defaultTensor } from '@qe-libs/rena-wasm/src/tensor.js';

const tensor = defaultTensor(4);        // window=4, weight=1
const tensor = defaultTensor(4, 0.5);  // window=4, weight=0.5

Input Format

rows is an array of plain objects — one per utterance/event.

const rows = [
  { UserName: 'Alice', Condition: 'A', GroupName: 'G1', Role: 'Teacher', Data: 1, Reasoning: 0 },
  ...
];

Code column values should be numeric (0/1 for binary codes). Factor column values can be any string or number — they are mapped to 0-based indices automatically unless factorLevels is provided explicitly.


Testing

npm install
npm test

Tests cover the simple windowed pipeline (test/ena.test.js) and the context-tensor path (test/tensor.test.js).