Getting Started with netcdf4-wasm

This guide will help you get up and running with netcdf4-wasm in just a few minutes.

Installation

NPM/Yarn

1
2
3
4
5
# Using npm
npm install netcdf4-wasm

# Using yarn
yarn add netcdf4-wasm

CDN (Browser)

1
2
<!-- Include via CDN -->
<script src="https://unpkg.com/netcdf4-wasm@latest/dist/netcdf4.js"></script>

Basic Concepts

NetCDF (Network Common Data Form) is a format designed for scientific data. Understanding these key concepts will help you work effectively with netcdf4-wasm:

Datasets

A NetCDF dataset is like a container that holds:

  • Dimensions: Define the size of data arrays (e.g., time=100, latitude=180)
  • Variables: Multidimensional data arrays (e.g., temperature, pressure)
  • Attributes: Metadata describing the data (e.g., units, descriptions)
  • Groups: Hierarchical organization (NetCDF4 only)

Example Structure

1
2
3
4
5
6
7
8
9
10
11
12
Dataset: weather_data.nc
├── Dimensions:
│   ├── time (unlimited)
│   ├── latitude (180)
│   └── longitude (360)
├── Variables:
│   ├── temperature [time, latitude, longitude]
│   ├── pressure [time, latitude, longitude]
│   └── time [time]
└── Global Attributes:
    ├── title: "Global Weather Data"
    └── institution: "Weather Service"

Your First NetCDF File

Reading an Existing File

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { Dataset } from 'netcdf4-wasm';

async function readNetCDFFile() {
    // Open file for reading
    const dataset = await Dataset('weather_data.nc', 'r');
    
    try {
        // Explore the file structure
        console.log('Dimensions:', Object.keys(dataset.dimensions));
        console.log('Variables:', Object.keys(dataset.variables));
        
        // Access a variable
        const temperature = dataset.variables.temperature;
        console.log('Temperature dimensions:', temperature.dimensions);
        console.log('Temperature units:', temperature.units);
        
        // Read the data
        const tempData = await temperature.getValue();
        console.log('Temperature data length:', tempData.length);
        console.log('First 5 values:', tempData.slice(0, 5));
        
        // Read global attributes
        console.log('Title:', dataset.getAttr('title'));
        
    } finally {
        // Always close the dataset
        await dataset.close();
    }
}

readNetCDFFile().catch(console.error);

Creating a New File

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { Dataset } from 'netcdf4-wasm';

async function createNetCDFFile() {
    // Create new file
    const dataset = await Dataset('my_data.nc', 'w', { format: 'NETCDF4' });
    
    try {
        // Set global attributes
        dataset.setAttr('title', 'My First NetCDF File');
        dataset.setAttr('created', new Date().toISOString());
        
        // Create dimensions
        const timeDim = await dataset.createDimension('time', 10);
        const locationDim = await dataset.createDimension('location', 5);
        
        // Create variables
        const temperature = await dataset.createVariable('temperature', 'f8', ['time', 'location']);
        const time = await dataset.createVariable('time', 'f8', ['time']);
        
        // Set variable attributes
        temperature.units = 'degrees_Celsius';
        temperature.long_name = 'Air Temperature';
        time.units = 'hours since 2023-01-01 00:00:00';
        
        // Create some sample data
        const tempData = new Float64Array(10 * 5); // 10 times × 5 locations
        const timeData = new Float64Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
        
        // Fill temperature data with realistic values
        for (let t = 0; t < 10; t++) {
            for (let loc = 0; loc < 5; loc++) {
                const index = t * 5 + loc;
                // Temperature varies by time and location
                tempData[index] = 20 + Math.sin(t * 0.5) * 10 + loc * 2;
            }
        }
        
        // Write data to variables
        await temperature.setValue(tempData);
        await time.setValue(timeData);
        
        console.log('NetCDF file created successfully!');
        
    } finally {
        await dataset.close();
    }
}

createNetCDFFile().catch(console.error);

Working with Different Sources

File System (Node.js)

1
2
3
4
import { Dataset } from 'netcdf4-wasm';

// Read from local file system
const dataset = await Dataset('/path/to/data.nc', 'r');

Browser File Input

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<input type="file" id="netcdfFile" accept=".nc" />
<script>
document.getElementById('netcdfFile').addEventListener('change', async (event) => {
    const file = event.target.files[0];
    if (file) {
        // File is a Blob - can be used directly
        const dataset = await Dataset(file, 'r');
        
        // Process the file...
        console.log('Variables:', Object.keys(dataset.variables));
        
        await dataset.close();
    }
});
</script>

Remote Files (Fetch)

1
2
3
4
5
6
7
8
9
10
async function loadRemoteFile() {
    const response = await fetch('https://example.com/data.nc');
    const arrayBuffer = await response.arrayBuffer();
    
    const dataset = await Dataset(arrayBuffer, 'r');
    
    // Process remote data...
    
    await dataset.close();
}

In-Memory Data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Create dataset entirely in memory
const dataset = await Dataset(new ArrayBuffer(0), 'w');

// ... add dimensions, variables, data ...

// Export as blob for download
const blob = await dataset.toBlob();
const url = URL.createObjectURL(blob);

// Create download link
const link = document.createElement('a');
link.href = url;
link.download = 'generated_data.nc';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);

await dataset.close();

Common Patterns

Error Handling

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
async function safeNetCDFOperation() {
    let dataset = null;
    
    try {
        dataset = await Dataset('data.nc', 'r');
        
        // Your operations here...
        const data = await dataset.variables.temperature.getValue();
        
        return data;
        
    } catch (error) {
        console.error('NetCDF operation failed:', error.message);
        throw error;
        
    } finally {
        // Always clean up resources
        if (dataset && dataset.isopen) {
            await dataset.close();
        }
    }
}

Exploring Unknown Files

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
async function exploreNetCDFFile(source) {
    const dataset = await Dataset(source, 'r');
    
    try {
        console.log('=== File Information ===');
        console.log('Format:', dataset.file_format);
        console.log('Global attributes:', dataset.attrs());
        
        console.log('\n=== Dimensions ===');
        for (const [name, dim] of Object.entries(dataset.dimensions)) {
            console.log(`${name}: ${dim.size}${dim.isUnlimited ? ' (unlimited)' : ''}`);
        }
        
        console.log('\n=== Variables ===');
        for (const [name, variable] of Object.entries(dataset.variables)) {
            console.log(`${name}:`);
            console.log(`  Type: ${variable.datatype}`);
            console.log(`  Dimensions: [${variable.dimensions.join(', ')}]`);
            console.log(`  Shape: [${variable.shape.join(', ')}]`);
            
            // Common attributes
            if (variable.units) console.log(`  Units: ${variable.units}`);
            if (variable.long_name) console.log(`  Description: ${variable.long_name}`);
        }
        
    } finally {
        await dataset.close();
    }
}

Data Processing Pipeline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
async function processTemperatureData(inputSource) {
    const input = await Dataset(inputSource, 'r');
    const output = await Dataset(new ArrayBuffer(0), 'w');
    
    try {
        // Copy structure
        for (const [name, dim] of Object.entries(input.dimensions)) {
            await output.createDimension(name, dim.isUnlimited ? null : dim.size);
        }
        
        // Process temperature variable
        if (input.variables.temperature) {
            const inputTemp = input.variables.temperature;
            const outputTemp = await output.createVariable(
                'temperature_celsius', 
                'f4', 
                inputTemp.dimensions
            );
            
            // Convert Kelvin to Celsius
            const tempK = await inputTemp.getValue();
            const tempC = tempK.map(t => t - 273.15);
            
            await outputTemp.setValue(new Float64Array(tempC));
            
            // Update metadata
            outputTemp.units = 'degrees_Celsius';
            outputTemp.long_name = 'Air Temperature in Celsius';
            outputTemp.setAttr('conversion', 'Converted from Kelvin');
        }
        
        // Export processed data
        return await output.toBlob();
        
    } finally {
        await input.close();
        await output.close();
    }
}

Next Steps

Now that you’ve mastered the basics, explore these topics:

  1. File Operations - Advanced file handling techniques
  2. Variables - Working with multidimensional data
  3. Browser Integration - Building web applications
  4. Examples - Real-world use cases and patterns

TypeScript Support

netcdf4-wasm includes full TypeScript definitions:

1
2
3
4
5
6
7
8
9
10
11
import { Dataset, NetCDF4, Variable, Dimension } from 'netcdf4-wasm';

async function typedExample() {
    const dataset: NetCDF4 = await Dataset('data.nc', 'r');
    const variable: Variable = dataset.variables.temperature;
    const dimension: Dimension = dataset.dimensions.time;
    
    const data: Float64Array = await variable.getValue();
    
    await dataset.close();
}

Troubleshooting

Common Issues

“NetCDF4Module not found”

  • Make sure the WASM files are properly loaded
  • Check network connectivity for CDN usage
  • Verify build process completed successfully

“Failed to open NetCDF file”

  • Verify file exists and is accessible
  • Check file permissions
  • Ensure file is valid NetCDF format

Memory errors

  • Large files may exceed browser memory limits
  • Consider processing data in chunks
  • Use appropriate data types to minimize memory usage

Getting Help


Ready to build something amazing? Check out our examples for inspiration and complete code samples.