# Excdf
[](https://hex.pm/packages/excdf)
[](https://hexdocs.pm/excdf)
Elixir NIF bindings for the [netCDF](https://www.unidata.ucar.edu/software/netcdf/) C library.
Read and write netCDF files — the standard format for array-oriented scientific data
(climate, ocean, atmospheric, geospatial, and more).
## Prerequisites
The netCDF C library must be installed on your system:
```bash
# macOS
brew install netcdf
# Ubuntu / Debian
sudo apt-get install libnetcdf-dev
# Fedora / RHEL
sudo dnf install netcdf-devel
```
The `nc-config` tool (installed alongside libnetcdf) is used at compile time
to locate headers and libraries automatically.
## Installation
Add `excdf` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:excdf, "~> 0.1.0"}
]
end
```
## Quick start
### Writing a netCDF file
```elixir
# Create a new netCDF-4 file
{:ok, nc} = Excdf.create("weather.nc", :netcdf4)
# Define dimensions
{:ok, x_dim} = Excdf.def_dim(nc, "x", 10)
{:ok, y_dim} = Excdf.def_dim(nc, "y", 20)
{:ok, time_dim} = Excdf.def_dim(nc, "time", :unlimited)
# Define a variable with its dimensions
{:ok, temp_var} = Excdf.def_var(nc, "temperature", :double, [time_dim, y_dim, x_dim])
# Add metadata as attributes
:ok = Excdf.put_att(nc, temp_var, "units", "kelvin")
:ok = Excdf.put_att(nc, temp_var, "long_name", "Surface Temperature")
:ok = Excdf.put_att_global(nc, "title", "Example weather dataset")
# Switch to data mode and write values
:ok = Excdf.enddef(nc)
:ok = Excdf.put_var(nc, temp_var, :double, List.duplicate(293.15, 10 * 20))
:ok = Excdf.close(nc)
```
### Reading a netCDF file
```elixir
{:ok, nc} = Excdf.open("weather.nc")
# Get a summary of everything in the file
{:ok, info} = Excdf.info(nc)
# => %{
# dimensions: %{"x" => 10, "y" => 20, "time" => 1},
# variables: [%{name: "temperature", type: :double, ...}],
# global_attributes: %{"title" => "Example weather dataset"}
# }
# Read variable data by name or ID
{:ok, {:double, shape, data}} = Excdf.get_var(nc, "temperature")
# Read a slice (hyperslab)
{:ok, {:double, slice}} = Excdf.get_vara(nc, 0, [0, 0, 0], [1, 5, 5])
# Read attributes
{:ok, "kelvin"} = Excdf.get_att(nc, 0, "units")
{:ok, "Example weather dataset"} = Excdf.get_att_global(nc, "title")
:ok = Excdf.close(nc)
```
## Supported data types
| Atom | netCDF type | Elixir values |
|------------|-------------|------------------|
| `:byte` | `NC_BYTE` | integers |
| `:ubyte` | `NC_UBYTE` | integers |
| `:char` | `NC_CHAR` | strings |
| `:short` | `NC_SHORT` | integers |
| `:ushort` | `NC_USHORT` | integers |
| `:int` | `NC_INT` | integers |
| `:uint` | `NC_UINT` | integers |
| `:int64` | `NC_INT64` | integers |
| `:uint64` | `NC_UINT64` | integers |
| `:float` | `NC_FLOAT` | floats |
| `:double` | `NC_DOUBLE` | floats/integers |
## Supported file formats
| Atom | Format |
|--------------------|---------------------------|
| `:classic` | netCDF Classic |
| `:classic64` | netCDF 64-bit Offset |
| `:netcdf4` | netCDF-4 (HDF5-backed) |
| `:netcdf4_classic` | netCDF-4 Classic Model |
## API reference
See the full API documentation on [HexDocs](https://hexdocs.pm/excdf).
## License
MIT License. See [LICENSE](LICENSE) for details.