# hic-straw

> Utilities for reading .hic contact matrix files

Latest version **4.0.1** (published 2026-09-27) · MIT license · 0 weekly downloads

## Install

```sh
npm install hic-straw
pnpm add hic-straw
yarn add hic-straw
bun add hic-straw
```

Provides the command `straw`.

## Health

**Score 50/100 (C)** — status: active.

Positive: esm support; no vulnerabilities; recently updated; high maintenance score.

Warnings: low downloads; no types.

Negative: insecure dependencies.

## Facts

| | |
|---|---|
| Version | 4.0.1 |
| Published | 2026-09-27 |
| First published | 2019-01-21 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | ESM + CommonJS |
| Node | ^20.19.0 \|\| >=22.12.0 |
| Dependencies | 2 |
| Unpacked size | 2 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 10 |
| Author | Jim Robinson |
| Maintainers | igvteam, aidenlab |
| Keywords | hic, contact-matrix, juicebox |

## Links

- npm: https://www.npmjs.com/package/hic-straw
- Repository: https://github.com/aidenlab/hic-straw
- Homepage: https://github.com/aidenlab/hic-straw#readme
- Issues: https://github.com/aidenlab/hic-straw/issues
- npm.io page: https://npm.io/package/hic-straw

## Dependencies (2)

- [node-fetch](https://npm.io/package/node-fetch.md) ^3.3.2
- [hdf5-indexed-reader](https://npm.io/package/hdf5-indexed-reader.md) github:aidenlab/hdf5-indexed-reader#v1.0.3

## Recent versions

- 4.0.1 (latest) — 2026-09-27
- 2.1.4 — 2025-12-01
- 2.1.3 — 2025-02-03
- 2.1.2 — 2024-07-09
- 2.1.1 — 2023-04-22
- 2.1.0 — 2023-04-05
- 2.0.6 — 2022-09-01
- 2.0.5 — 2022-06-23
- 2.0.4 — 2022-03-02
- 2.0.3 — 2021-02-05
- 2.0.2 — 2020-12-19
- 2.0.1 — 2020-12-08
- 2.0.0 — 2020-09-04
- 1.2.2 — 2020-06-28
- 1.2.1 — 2020-06-28
- … 13 more at https://npm.io/package/hic-straw/versions

## README

# hic-straw

[![CI](https://github.com/igvteam/hic-straw/actions/workflows/ci.yml/badge.svg)](https://github.com/igvteam/hic-straw/actions/workflows/ci.yml)

Command line and web utilities for reading .hic contact matrix files, with support for creating
live contact and distance maps from 3D chromatin structure data for
[Spacewalk](https://github.com/aidenlab/spacewalk)

## Installation

Requires Node 18+ (https://nodejs.org)

```
npm install hic-straw
```

## API

#### getContactRecords

Return a collection of binned contact counts.

Arguments
* normalization - string indicating normalization scheme
* region 1  {chr, start, end} - genomic region in base pair or fragment units.  Interval convention is zero based 1/2 open
* region 2  {chr, start, end}
* units -- "BP" for base pairs.  Currently this is the only unit supported
* binSize -- size of each bin in base pair or fragment units.  Bins are square


## Configuration

The object passed to `new Straw({...})` names the file to read — `url`, `file`, or
`blob` — and may carry the following optional properties. Everything here applies
to remote (URL) reads only.

| Property | Type | Purpose |
| --- | --- | --- |
| `headers` | object | Extra request headers. Not modified; `Range` is added to a copy per read. |
| `oauthToken` | string, or a function returning one (or a promise for one) | Sent as `Authorization: Bearer …`. |
| `mapUrl` | `(url: string) => string` | Rewrites the URL before it is fetched. See below. |

### mapUrl

Dropbox share links and NCBI `ftp://` URLs are always rewritten into a form that
supports byte-range GETs. `mapUrl` runs **after** those built-in rules and cannot
switch them off:

```javascript
const straw = new Straw({
    url: 'https://www.encodeproject.org/files/ENCFF464WXY/@@download/ENCFF464WXY.hic',
    mapUrl: url => url.replace('https://www.encodeproject.org', 'http://localhost:9000/encode')
})
```

It must be synchronous and pure — URL in, URL out. It cannot set headers, inspect
responses, or alter Range semantics.

`mapUrl` exists for **development**: it lets you route reads through a local proxy
when a host refuses requests from `localhost`, without patching global `fetch`. It
is not intended as a production routing mechanism. Any proxy it points at must
forward the `Range` request header and return the upstream `206` and
`Content-Range` unchanged, or every read will be silently wrong.

### Read errors

A response with status `>= 400` rejects with an `Error` carrying:

* `code` — the HTTP status
* `url` — the URL actually fetched, after mapping
* `headers` — the response `Headers`

In a browser, `headers` contains only the CORS-safelisted headers plus whatever
the server names in `Access-Control-Expose-Headers`. All three are absent when the
failure precedes a response, so read defensively:

```javascript
try {
    await straw.getMetaData()
} catch (e) {
    if (e.headers?.get('x-amzn-waf-action') === 'captcha') {
        // the host is challenging automated requests; e.code is likely to be misleading
    }
}
```

## Examples

### Development

Run the examples dashboard with hot reload:

```bash
npm run dev
```

Then open http://localhost:5173 in your browser. The dashboard links to each example.

### Browser usage

ES module — see examples/straw.html

```javascript
import Straw from 'hic-straw'

const straw = new Straw({
    url: "https://s3.amazonaws.com/igv.broadinstitute.org/data/hic/intra_nofrag_30.hic"
})

straw.getContactRecords(
    "KR",
    { chr: "8", start: 50000000, end: 60000000 },
    { chr: "8", start: 50000000, end: 60000000 },
    "BP",
    1000000
)
    .then(function (contactRecords) { ... })
```

### Node

**local file**

To use hic-straw with a local file, use the NodeLocalFile class:

```javascript
import Straw from 'hic-straw'
import NodeLocalFile from 'hic-straw/node'

const nodeLocalFile = new NodeLocalFile({ path: "test/data/test_chr22.hic" })
const straw = new Straw({ file: nodeLocalFile })
```

**remote file**

Node 18+ includes native `fetch`. For remote files:

```javascript
import Straw from 'hic-straw'

const straw = new Straw({ url: "https://foo.bar/test.hic" })
```


### Command line

Note: "straw" is installed in node_modules/.bin/straw.  This should be added to the path automatically upon installing
hic-straw, however if you get the error ```straw: command not found``` try running straw explicitly as

```node_modules/.bin/straw...```

#### Extract file metadata (genome identifier, sequences,  resolutions)

```bash
straw --meta test/data/test_chr22.hic
```

#### Extract normalization options.

```
straw --norms test/data/test_chr22.hic

```

#### Extract contact records from a local hic file


```bash

straw KR test/data/test_chr22.hic 22:40,000,000-50,000,000 22:40,000,000-50,000,000 BP 100,000

```
#### Extract contact records from a remote hic file

```bash
straw KR https://s3.amazonaws.com/igv.broadinstitute.org/data/hic/intra_nofrag_30.hic 8:48,700,000-48,900,000 8:48700000-48900000 BP 10,000
```

---

## LiveContactMap — Synthetic Contact Maps from 3D Structure Data

LiveContactMap is an adapter that accepts 3D chromosome vertex data and produces contact maps
fully compatible with the hic-straw / Juicebox.js pipeline. It implements the same interface as
HicFile, so downstream consumers (Straw, Juicebox) cannot distinguish it from a real `.hic` file.

This is designed for [Spacewalk](https://github.com/aidenlab/spacewalk), which visualizes
3D chromatin tracing data and needs to display live contact and distance maps alongside the
3D structure.

### How it works

1. **Parse** 3D vertex data from a Spacewalk Text (SWT) file or provide traces directly
2. **Compute** a pairwise Euclidean distance matrix, averaged across all traces in an ensemble
3. **Derive** contact records by applying a distance threshold — pairs closer than the threshold
   are "in contact". In frequency mode, the count reflects the fraction of traces where the
   pair is in contact (0.0 to 1.0)
4. **Serve** contact records through the standard HicFile interface

### Supported input formats

- **SWT** (`.swt`) — text ball-and-stick format, see below.
- **SW / SWB** (`.sw`, `.swb`) — binary HDF5 ball-and-stick format used by Spacewalk.
  V1 supports SINGLE_POINT files with a single ensemble group and a single genomic region.
  Pointcloud (MULTI_POINT) files are not yet supported.

### Input: SWT file format

Spacewalk Text files (`.swt`) describe ball-and-stick models of chromatin fiber. Each file
contains multiple traces (independent 3D conformations) of the same genomic region.

```
##format=sw1 name=IMR90 genome=hg38
chromosome	start	end	x	y	z
trace 0
chr21 18000000 18030000 117803 58446 1733
chr21 18030000 18060000 117726 58747 1680
chr21 18060000 18090000 117747 58607 1872
...
trace 1
chr21 18000000 18030000 ...
...
```

See `resources/spacewalk-swt-text-file-format.md` for the full format specification.

### API

#### Construction

There are three ways to create a LiveContactMap:

**From SWT text** (simplest — parses the file for you):

```javascript
import LiveContactMap from 'hic-straw/src/liveContactMap.js'

const swtText = fs.readFileSync('data/ball-and-stick.swt', 'utf-8')
const lcm = new LiveContactMap({
    swtText: swtText,
    distanceThreshold: 500,   // 3D distance cutoff; omit to derive from the data
    contactMode: 'frequency'  // 'frequency' (0-1) or 'contact' (binary 0/1)
})
await lcm.init()
```

**From a binary SW / SWB (HDF5) file** — browser File, remote URL, or Node path:

```javascript
// Browser — File picker or drag-drop
const lcm = new LiveContactMap({ swFile: fileObject, distanceThreshold: 500 })

// Remote URL (uses HTTP range requests — no full download required)
const lcm = new LiveContactMap({ swUrl: 'https://host/data.sw', distanceThreshold: 500 })

// Node
const lcm = new LiveContactMap({ swPath: 'data/ball-and-stick.sw', distanceThreshold: 500 })

await lcm.init()
```

**From raw trace data** (when Spacewalk already has parsed vertex arrays):

```javascript
const lcm = new LiveContactMap({
    traces: ensembleManager.getTraces(),   // Array<Array<{x, y, z}>>
    genomeId: 'hg38',
    chr: 'chr21',
    genomicStart: 18000000,
    genomicEnd: 19950000,
    binSize: 30000,
    distanceThreshold: 500
})
await lcm.init()
```

**From pre-parsed SWT data** (if you've already called `parseSWT()`):

```javascript
import { parseSWT } from 'hic-straw/src/swtParser.js'

const parsed = parseSWT(swtText)
const lcm = new LiveContactMap({
    parsedData: parsed,
    distanceThreshold: 500
})
await lcm.init()
```

#### Querying contact records

After initialization, use the standard hic-straw interface:

```javascript
const records = await lcm.getContactRecords(
    'NONE',
    { chr: 'chr21', start: 18000000, end: 19950000 },
    { chr: 'chr21', start: 18000000, end: 19950000 },
    'BP',
    30000
)

for (const rec of records) {
    console.log(`bin ${rec.bin1} x ${rec.bin2}: ${rec.counts}`)
}
```

#### Using with Straw (for Juicebox compatibility)

To plug a LiveContactMap into the Straw/Juicebox pipeline:

```javascript
import Straw from 'hic-straw'

const straw = new Straw({ liveContactMap: lcm })

// Now use straw exactly like a normal .hic file:
const meta = await straw.getMetaData()
const records = await straw.getContactRecords('NONE', region1, region2, 'BP', 30000)
```

Juicebox's `HiCDataset` can wrap this Straw instance and all controls
(resolution selector, normalization widget, color scale) work natively.

#### Dynamic threshold adjustment

Changing the distance threshold re-derives contacts without recomputing the
expensive distance matrix:

```javascript
lcm.setDistanceThreshold(300)    // fewer contacts
lcm.setDistanceThreshold(800)    // more contacts
```

#### Accessing the distance matrix

For distance map visualization:

```javascript
const { distances, maxDistance, traceLength } = lcm.getDistanceMatrix()
// distances: Float32Array (N x N, row-major, symmetric)
// maxDistance: largest distance in the matrix
// traceLength: N (number of bins)
```

### Node.js example

```javascript
import fs from 'fs'
import Straw from 'hic-straw'
import LiveContactMap from 'hic-straw/src/liveContactMap.js'

const swtText = fs.readFileSync('resources/ball-and-stick.swt', 'utf-8')

const lcm = new LiveContactMap({
    swtText,
    distanceThreshold: 500,
    contactMode: 'frequency'
})
await lcm.init()

const meta = await lcm.getMetaData()
console.log(`Genome: ${meta.genome}`)
console.log(`Chromosomes: ${meta.chromosomes.map(c => c.name).join(', ')}`)
console.log(`Resolution: ${meta.resolutions[0]} bp`)

const records = await lcm.getContactRecords(
    'NONE',
    { chr: 'chr21', start: 18000000, end: 19950000 },
    { chr: 'chr21', start: 18000000, end: 19950000 },
    'BP',
    30000
)
console.log(`Contact records: ${records.length}`)
```

### Visual test page

A browser-based test page is provided at `examples/live-contact-map.html`. It renders
both a contact map and a distance map side by side from any `.swt` file, with interactive
controls for distance threshold and contact mode.

Run `npm run dev` and open the examples dashboard, then click "LiveContactMap" — or navigate
directly to http://localhost:5173/examples/live-contact-map.html. Load an SWT file using the file picker.

---
_Source: https://npm.io/package/hic-straw · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
