UNPKG

modern-netcdf

Version:
169 lines (124 loc) โ€ข 4.59 kB
# 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.