NetCDF4 library compiled to WebAssembly with JavaScript/TypeScript bindings.
This project provides a complete WebAssembly port of the NetCDF4 C library, enabling NetCDF file operations in browser and Node.js environments. It includes:
- Complete NetCDF4 C library compiled to WASM using Emscripten
- High-level TypeScript/JavaScript API
- Support for reading and writing NetCDF4 files
- Comprehensive test suite
npm install netcdf4-wasmFor building from source, you'll need:
- Emscripten SDK
- CMake
- Make
- wget or curl
Check dependencies:
npm run check-depsInstall Emscripten locally:
npm run install-emscriptenThe JavaScript API is modeled closely on the netcdf4-python API.
import { Dataset } from "netcdf4-wasm";
// or: import { NetCDF4 } from 'netcdf4-wasm';
async function example() {
// Create a new NetCDF file (similar to Python netCDF4.Dataset)
const nc = await Dataset("example.nc", "w", { format: "NETCDF4" });
// or: const nc = await NetCDF4.Dataset('example.nc', 'w', { format: 'NETCDF4' });
// Create dimensions
const lat = await nc.createDimension("lat", 73);
const lon = await nc.createDimension("lon", 144);
const time = await nc.createDimension("time", null); // unlimited dimension
// Create variables
const temp = await nc.createVariable("temperature", "f4", [
"time",
"lat",
"lon",
]);
const times = await nc.createVariable("time", "f8", ["time"]);
// Set variable attributes
temp.units = "Kelvin";
temp.long_name = "surface temperature";
times.units = "hours since 0001-01-01 00:00:00.0";
times.calendar = "gregorian";
// Set global attributes
nc.setncattr("description", "bogus example script");
nc.setncattr("history", "Created " + new Date().toISOString());
nc.setncattr("source", "netCDF4-wasm example");
// Write data
const tempData = new Float64Array(73 * 144);
tempData.fill(288.0); // Fill with 288K
await temp.setValue(tempData);
// Close the file
await nc.close();
}import { Dataset } from "netcdf4-wasm";
async function readExample() {
// Open existing file for reading
const nc = await Dataset("data.nc", "r");
// Access dimensions
console.log("Dimensions:", Object.keys(nc.dimensions));
console.log("Time dimension size:", nc.dimensions.time.size);
// Access variables
console.log("Variables:", Object.keys(nc.variables));
const temp = nc.variables.temperature;
// Read variable attributes
console.log("Temperature units:", temp.units);
console.log("Temperature long name:", temp.long_name);
// Read data
const data = await temp.getValue();
console.log("Temperature data shape:", data.length);
console.log("First few values:", data.slice(0, 5));
// Access global attributes
console.log("Global attributes:", nc.ncattrs());
console.log("Description:", nc.getncattr("description"));
await nc.close();
}import { NetCDF4 } from "netcdf4-wasm";
async function directExample() {
// Direct instantiation (requires manual initialization)
const nc = new NetCDF4("example.nc", "w", { format: "NETCDF4" });
await nc.initialize();
// Use same API as above...
const lat = await nc.createDimension("lat", 10);
const temp = await nc.createVariable("temperature", "f8", ["lat"]);
await nc.close();
}async function groupExample() {
const nc = await Dataset("grouped.nc", "w", { format: "NETCDF4" });
// Create a group
const forecasts = nc.createGroup("forecasts");
// Create dimensions and variables in the group
const time = await forecasts.createDimension("time", 24);
const temp = await forecasts.createVariable("temperature", "f4", ["time"]);
// Set group attributes
forecasts.setncattr("description", "Forecast data");
await nc.close();
}The API closely follows netcdf4-python conventions for ease of use by scientists familiar with Python.
Main class for NetCDF file operations, similar to netCDF4.Dataset in Python.
Constructor
new NetCDF4(filename?: string, mode?: string, options?: NetCDF4WasmOptions)Static Methods
NetCDF4.Dataset(filename: string, mode?: string, options?: object): Promise<NetCDF4>- Factory method (Python-like)
Module Functions
Dataset(filename: string, mode?: string, options?: object): Promise<NetCDF4>- Convenience function (import directly)
Properties
dimensions: {[name: string]: Dimension}- Dictionary of dimensionsvariables: {[name: string]: Variable}- Dictionary of variablesgroups: {[name: string]: Group}- Dictionary of groupsfile_format: string- File format (e.g., 'NETCDF4')filepath: string- Path to the fileisopen: boolean- Whether file is currently open
Methods
File Operations
initialize(): Promise<void>- Initialize the WASM moduleclose(): Promise<void>- Close the filesync(): Promise<void>- Flush data to disk
Structure Definition
createDimension(name: string, size: number): Promise<Dimension>- Create dimensioncreateVariable(name: string, datatype: string, dimensions: string[], options?: object): Promise<Variable>- Create variablecreateGroup(name: string): Group- Create hierarchical group
Attribute Access
setncattr(name: string, value: any): void- Set global attributegetncattr(name: string): any- Get global attributencattrs(): string[]- List all global attributes
Represents a NetCDF variable, similar to Python's Variable class.
Properties
name: string- Variable namedatatype: string- Data type ('f4', 'f8', 'i4', etc.)dimensions: string[]- Dimension namesunits: string- Units attribute (convenience property)long_name: string- Long name attribute (convenience property)standard_name: string- Standard name attribute (convenience property)
Methods
getValue(): Promise<Float64Array>- Read variable datasetValue(data: Float64Array): Promise<void>- Write variable datasetncattr(name: string, value: any): void- Set variable attributegetncattr(name: string): any- Get variable attributencattrs(): string[]- List variable attributes
Represents a NetCDF dimension.
Properties
name: string- Dimension namesize: number- Dimension sizeisUnlimited: boolean- Whether dimension is unlimited
Methods
__len__(): number- Get dimension size (Python-like)
The NC_CONSTANTS object provides NetCDF constants:
NC_CONSTANTS.NC_NOERR; // No error
NC_CONSTANTS.NC_NOWRITE; // Read-only access
NC_CONSTANTS.NC_WRITE; // Write access
NC_CONSTANTS.NC_CLOBBER; // Overwrite existing file
NC_CONSTANTS.NC_NETCDF4; // NetCDF4 format
NC_CONSTANTS.NC_DOUBLE; // Double data type
NC_CONSTANTS.NC_UNLIMITED; // Unlimited dimensionnpm installnpm run check-depsnpm run buildThis will:
- Download and compile zlib, HDF5, and NetCDF4 C libraries
- Create the WASM module with Emscripten
- Compile TypeScript bindings
npm run cleanRun tests:
npm testRun tests with coverage:
npm run test:coverageWatch mode:
npm run test:watchnetcdf4-wasm/
├── src/ # TypeScript source code
│ ├── index.ts # Main API exports
│ ├── types.ts # Type definitions
│ ├── constants.ts # NetCDF constants
│ ├── netcdf4.ts # Main NetCDF4 class
│ ├── group.ts # Group class
│ ├── variable.ts # Variable class
│ ├── dimension.ts # Dimension class
│ ├── wasm-module.ts # WASM module loader
│ └── __tests__/ # Test files
├── scripts/ # Build scripts
│ ├── build-wasm.sh # Main WASM build script
│ ├── check-dependencies.sh
│ └── install-emscripten.sh
├── bindings/ # WASM bindings
│ ├── pre.js # Pre-run JavaScript
│ └── post.js # Post-run JavaScript
├── build/ # Build artifacts (generated)
├── dist/ # Distribution files (generated)
└── package.json
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Run the test suite
- Submit a pull request
MIT License - see LICENSE file for details.
For more information about NetCDF4, visit: https://docs.unidata.ucar.edu/netcdf-c/current/
Make sure the WASM files are properly built and accessible:
npm run build:wasmInstall Emscripten:
npm run install-emscripten
source build/emsdk/emsdk_env.shIf you encounter memory-related errors, try increasing the initial memory:
const netcdf = new NetCDF4({ memoryInitialPages: 512 });