modern-netcdf
Version:
Modern NetCDF file reader and utilities
169 lines (124 loc) โข 4.59 kB
Markdown
# Modern NetCDF
A modern JavaScript implementation for reading and working with NetCDF files. This library provides an efficient, async/await-based API for handling NetCDF v3.x files with support for partial reads, slicing, and memory-efficient operations.
## Features
- ๐ Full NetCDF-3 classic & 64-bit offset support
- ๐ Promise-based, await-friendly API
- ๐ช Hyperslab slicing with range + stride
- ๐ก **Lazy** HTTP-Range streaming for remote files
- โ๏ธ Zero-copy views & memory-efficient decoding
- ๐งต WebWorker shim auto-selects Node vs Browser
- ๐ Smart formatting for large arrays and strings
- ๐ ๏ธ Command-line `netcdf-dump` utility
- ๐ช TypeScript declarations included
## Installation
```bash
npm install modern-netcdf
```
## Usage
### Basic Usage
```javascript
const { NetCDFReader } = require('modern-netcdf');
// From a file
const reader = await NetCDFReader.open('path/to/file.nc');
// From an ArrayBuffer
const buffer = fs.readFileSync('path/to/file.nc');
const reader = await NetCDFReader.open(buffer);
// From a URL (download header only; streams data on-demand)
const reader = await NetCDFReader.open('https://example.com/data.nc', { lazy: true });
// The first call to getData() will issue HTTP Range requests automatically.
// Access metadata
console.log(reader.dimensions); // { time: 72, y: 1040, x: 1077 }
console.log(reader.globalAttributes); // Array of global attributes
console.log(reader.variables); // Object of variable metadata
// Read entire variable
const data = await reader.getData('temperature');
// Clean up when done
reader.close();
```
### Advanced Data Slicing
The library supports sophisticated data slicing with start, end, and stride parameters:
```javascript
// Read a specific time index
const timeSlice = await reader.getData('temperature', {
time: 0 // Select first time step
});
// Read a range of latitudes and longitudes
const spatialSlice = await reader.getData('temperature', {
lat: [100, 200], // Select indices 100-199
lon: [400, 600] // Select indices 400-599
});
// Use stride to read every other point
const strided = await reader.getData('temperature', {
lat: [0, 100, 2], // Start: 0, End: 100, Stride: 2
lon: [0, 200, 2] // Start: 0, End: 200, Stride: 2
});
```
### Working with Variables
```javascript
// Get a specific variable
const tempVar = reader.getVariable('temperature');
// Access variable metadata
console.log(tempVar.name); // Variable name
console.log(tempVar.type); // Data type (float, double, etc.)
console.log(tempVar.dimensions); // Array of dimension names
console.log(tempVar.attributes); // Array of variable attributes
```
## Command-line Tool
The package includes a `netcdf-dump` utility for inspecting NetCDF files:
```bash
# Install globally
npm install -g modern-netcdf
# Use the command-line tool
netcdf-dump path/to/file.nc
# Or use with npx
npx netcdf-dump path/to/file.nc
```
The output format is similar to the standard `ncdump` utility:
```
netcdf input {
dimensions:
time = 72 ;
y = 1040 ;
x = 1077 ;
variables:
float temperature(time, y, x) ;
units = "K" ;
long_name = "Temperature" ;
...
}
```
## Error Handling
The library provides detailed error messages for common issues:
```javascript
try {
const reader = await NetCDFReader.open('file.nc');
const data = await reader.getData('nonexistent');
} catch (error) {
if (error.message.includes('Variable not found')) {
console.error('The requested variable does not exist');
}
}
```
## Memory Considerations
For large datasets, the library implements smart memory management:
- Only loads requested data portions into memory
- Automatically summarizes large arrays in output
- Provides clean-up method via `reader.close()`
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
ISC
### Using in a WebWorker (browser)
```javascript
// worker.js
importScripts('modern-netcdf/dist/worker.js');
// main thread (app.js)
const worker = new Worker('worker.js');
worker.postMessage({ id: 1, cmd: 'open', payload: { source: 'https://example.com/data.nc', options: { lazy: true } } });
worker.onmessage = (e) => {
const { id, result, error } = e.data;
if (error) console.error(error);
else console.log('Worker response', result);
};
```
The same worker entry automatically routes to `worker_threads` when bundled for Node.js, so you can reuse the identical message protocol in server-side environments.