# h5wasm
**Repository Path**: shudingbo/h5wasm
## Basic Information
- **Project Name**: h5wasm
- **Description**: hdf5
- **Primary Language**: C++
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2024-07-20
- **Last Updated**: 2024-07-20
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# h5wasm
a zero-dependency WebAssembly-powered library for [reading](#reading) and [writing](#writing) HDF5 files from javascript
(built on the [HDF5 C API](http://portal.hdfgroup.org/pages/viewpage.action?pageId=50073943))
The built binaries (esm and node) will be attached to the [latest release](https://github.com/usnistgov/h5wasm/releases/latest/) as h5wasm-{version}.tgz
The wasm-compiled libraries `libhdf5.a`, `libhdf5_cpp.a` ... and the related `include/` folder are retrieved from [libhdf5-wasm](https://github.com/usnistgov/libhdf5-wasm) during the build.
Instead of importing a namespace "*", it is now possible to import the important h5wasm components in an object, from the default export:
```js
// in hdf5_hl.ts:
export const h5wasm = {
File,
Group,
Dataset,
ready,
ACCESS_MODES
}
```
The Emscripten filesystem is important for operations, and it can be accessed after the WASM is loaded as below.
## Browser (no-build)
```js
import h5wasm from "https://cdn.jsdelivr.net/npm/h5wasm@0.4.9/dist/esm/hdf5_hl.js";
// the WASM loads asychronously, and you can get the module like this:
const Module = await h5wasm.ready;
// then you can get the FileSystem object from the Module:
const { FS } = Module;
// Or, you can directly get the FS if you don't care about the rest
// of the module:
// const { FS } = await h5wasm.ready;
let response = await fetch("https://ncnr.nist.gov/pub/ncnrdata/vsans/202003/24845/data/sans59510.nxs.ngv");
let ab = await response.arrayBuffer();
FS.writeFile("sans59510.nxs.ngv", new Uint8Array(ab));
// use mode "r" for reading. All modes can be found in h5wasm.ACCESS_MODES
let f = new h5wasm.File("sans59510.nxs.ngv", "r");
// File {path: "/", file_id: 72057594037927936n, filename: "data.h5", mode: "r"}
```
### Worker usage
Since ESM is not supported in all web worker contexts (e.g. Firefox), an additional ```./dist/iife/h5wasm.js``` is provided in the package for `h5wasm>=0.4.8`; it can be loaded in a worker and used as in the example below (which uses the WORKERFS file system for random access on local files):
```js
// worker.js
onmessage = async function(e) {
const { FS } = await h5wasm.ready;
// send in a file opened from an
const f_in = e.data[0];
FS.mkdir('/work');
FS.mount(FS.filesystems.WORKERFS, { files: [f_in] }, '/work');
const f = new h5wasm.File(`/work/${f_in.name}`, 'r');
console.log(f);
}
self.importScripts('../dist/iife/h5wasm.js');
```
## Browser target (build system)
```npm i h5wasm``` or ```yarn add h5wasm```
then in your file
```js
// index.js
import h5wasm from "h5wasm";
const { FS } = await h5wasm.ready;
let f = new h5wasm.File("test.h5", "w");
f.create_dataset({name: "text_data", data: ["this", "that"]});
// ...
```
__note__: you must configure your build system to target >= ES2020 (for bigint support)
## nodejs
The host filesystem is made available through Emscripten "NODERAWFS=1".
Enabling BigInt support may be required for nodejs < 16
```bash
npm i h5wasm
node --experimental-wasm-bigint
```
```js
const h5wasm = await import("h5wasm/node");
await h5wasm.ready;
let f = new h5wasm.File("/home/brian/Downloads/sans59510.nxs.ngv", "r");
/*
File {
path: '/',
file_id: 72057594037927936n,
filename: '/home/brian/Downloads/sans59510.nxs.ngv',
mode: 'r'
}
*/
```
## Usage
_(all examples are written in ESM - for Typescript some type casting is probably required, as `get` returns either Group or Dataset)_
### Reading
```js
let f = new h5wasm.File("sans59510.nxs.ngv", "r");
// list keys:
f.keys()
// ["entry"]
f.get("entry/instrument").keys()
// ["attenuator","beam","beam_monitor_low","beam_monitor_norm","beam_stop_C2","beam_stop_C3","collimator","converging_pinholes","detector_B","detector_FB","detector_FL","detector_FR","detector_FT","detector_MB","detector_ML","detector_MR","detector_MT","lenses","local_contact","name","sample_aperture","sample_aperture_2","sample_table","source","source_aperture","type"]
let data = f.get("entry/instrument/detector_MR/data")
// Dataset {path: "/entry/instrument/detector_MR/data", file_id: 72057594037927936n}
data.metadata
/*
{
"signed": true,
"vlen": false,
"littleEndian": true,
"type": 0,
"size": 4,
"shape": [
48,
128
],
"total_size": 6144
}
*/
// for convenience, these are extracted from metadata:
data.dtype
// " i);
new_file.get("entry").create_dataset({name: "compressed", data: long_data, shape: [1000, 1000], dtype: ' {console.log(e)});
// to push all current files in /home/web_user to IndexedDB, e.g. when closing your application:
FS.syncfs(false, (e) => {console.log(e)})
```