# 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)}) ```