r3.out.netcdf(1grass)

πŸ’– r3.out.netcdf πŸ’–

okay bestie, welcome to r3.out.netcdf from the GRASS User's Manual β€” say it with me, "r-three-out-net-c-d-f" πŸŽ€ it's a GRASS module and it's literally the plug that gets your 3D raster map out of GRASS and into a netCDF file. no cap.


✨ NAME ✨

r3.out.netcdf β€” Export a 3D raster map as netCDF file. that's it, that's the whole job, and it does it gorgeously πŸ¦‹


🌈 KEYWORDS 🌈

raster3d, export, output, netCDF, voxel

iykyk, those are the searchable tags. type them into the module search and this baby pops right up πŸ’…


πŸ‘‘ SYNOPSIS πŸ‘‘

r3.out.netcdf
r3.out.netcdf --help
r3.out.netcdf [-pm] input=name output=name  [null=float]   [--overwrite]
[--help]  [--verbose]  [--quiet]  [--ui]

πŸŽ€ Flags:

  • -p β€” Export projection information as wkt and proj4 parameter. so like, she's bringing the receipts of where your data lives on the planet ✨
  • -m β€” Use 3D raster mask (if exists) with input map. only if there is one, bestie, she's not making it up πŸ’«
  • --overwrite β€” Allow output files to overwrite existing files. (danger-adjacent, she will absolutely clobber that thing you already had 😭)
  • --help β€” Print usage summary. the "help me pls" button 🫢
  • --verbose β€” Verbose module output. she will tell you everything she's doing πŸ’¬
  • --quiet β€” Quiet module output. she goes silent-mode 🧘
  • --ui β€” Force launching GUI dialog. pops the whole thing open in a window, very main character πŸ‘‘

πŸ“ Parameters:

  • input=name [required] β€” Name of input 3D raster map. you gotta tell her which map, no guessing games 🌸
  • output=name [required] β€” Name for netCDF output file. and what you want the file to be called πŸ’–
  • null=float β€” The value to be used for null values, default is the netCDF standard. so like, what number means "nothing here" β€” if you don't say, netCDF's own standard gets used πŸ•³οΈ

✨ DESCRIPTION ✨

so the module r3.out.netcdf exports a 3D raster map as a netCDF file. periodt. πŸŽ€

the maps it works with are valid 3D raster maps that live in the current mapset search path. she's not importing from your random Downloads folder, she's looking where GRASS looks, ok?

the output parameter is the name of the netCDF file, and β€” heads up β€” it gets written into the current working directory. that's where it lands, so know where you're standing when you run her πŸ’…

also? she is sensitive. to the mapset region settings (the ones you set with g.region) and to the vertical unit settings of the 3D raster map. that vertical unit? you set it with r3.support. so if the vibes are off, check those two first, bestie πŸ”


πŸ¦‹ NOTES πŸ¦‹

okay this is the part where she gets specific, listen up.

the resulting netCDF file will have time as the third dimension in case a temporal vertical unit is specified for the input map. otherwise, that third dimension is assumed as spatial. two totally different vibes depending on one setting, wild.

if the 3D raster map has a time stamp with absolute time, then the start time will be used as the starting point for the netCDF time series. and if that absolute time stamp is missing? the date "Jan. 01. 1900 00:00:00" gets used as the default. yes, 1900. she's vintage like that πŸ•°οΈ

in case of relative time stamp, no start time is set in the netCDF file at all. nothing. she leaves it blank πŸ«₯

the number of depths of the 3D raster map are the number of time slices in the netCDF file. that's the mapping, memorize it fr fr.

and here's a little combo for you β€” you can use t.rast.to.rast3 to convert a space time raster dataset into a 3D raster map representing a space time voxel cube, and then export the raster time series as a netCDF file. slay, ate, no crumbs 🍽️


spatial coordinates are exported as cell centered coordinates. important. don't @ me about corners.

the projection can optionally be stored in the metadata as crs attributes. πŸ’–

the netCDF projection metadata storage follows the spatial_ref GDAL/netCDF suggestion here, and the netCDF CF 1.6 convention here, using WKT projection information. additionally, a PROJ string is stored in the crs attribute section. so she's thorough, she's giving professional 🌟

and the export of projection parameters is suppressed when the XY-projection is set. no projection info for you if there's no projection to speak of, makes sense 🧚


the range of the 3D raster map is set in the netCDF output file. πŸ“

optionally, a the netCDF missing value and _FillValue can be set using the null option. as default, the netCDF floating point _FillValues are used to fill empty cells. so empty cells get the standard fill, unless you say otherwise ✨

last thing, and it's a real one: the netCDF library must be installed on the system and activated at configuration time to compile this module. no library, no module, no slay. πŸ’€

more coming bestie, hold on πŸ’œ

✨ EXAMPLES ✨

ok bestie this is the fun part, we're gonna actually do the thing πŸ’…

First up, set your region β€” this is literally the same region the whole example runs on, so don't skip it:

g.region s=-90 n=90 w=-180 e=180 b=0 t=5 res=10 res3=10 tbres=1 -p3
#####################################################################
# We create a simple volume map with floating point values
#####################################################################
r3.mapcalc --o expr="volume_float = float(col() + row() + depth())"
r3.info volume_float

so we made a lil 3D volume map with floating point values (FCELL, no cap) where every cell is just col() + row() + depth() β€” iconic. And r3.info spills all the tea about it:

 +----------------------------------------------------------------------------+
 | Layer:    volume_float                   Date: Thu Jun 14 08:40:56 2012    |
 | Mapset:   PERMANENT                      Login of Creator: soeren          |
 | Project:  TestLL                                                           |
 | DataBase: /1/soeren/grassdata                                              |
 | Title:    volume_float                                                     |
 | Units:    none                                                             |
 | Vertical unit: units                                                       |
 | Timestamp: none                                                            |
 |----------------------------------------------------------------------------|
 |                                                                            |
 |   Type of Map:  3d cell              Number of Categories: 0               |
 |   Data Type:    FCELL                                                      |
 |   Rows:         18                                                         |
 |   Columns:      36                                                         |
 |   Depths:       5                                                          |
 |   Total Cells:  3240                                                       |
 |   Total size:           10114 Bytes                                        |
 |   Number of tiles:      1                                                  |
 |   Mean tile size:       10114 Bytes                                        |
 |   Tile size in memory:  12960 Bytes                                        |
 |   Number of tiles in x, y and  z:   1, 1, 1                                |
 |   Dimension of a tile in x, y, z:   36, 18, 5                              |
 |                                                                            |
 |        Projection: Latitude-Longitude (zone 0)                             |
 |            N:        90N    S:        90S   Res:    10                     |
 |            E:       180E    W:       180W   Res:    10                     |
 |            T:          5    B:          0   Res:     1                     |
 |   Range of data:   min =          3 max =         59                       |
 |                                                                            |
 |   Data Source:                                                             |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |   Data Description:                                                        |
 |    generated by r3.mapcalc                                                 |
 |                                                                            |
 |   Comments:                                                                |
 |    r3.mapcalc expression="volume_float = float(col() + row() + depth())"   |
 |                                                                            |
 +----------------------------------------------------------------------------+

πŸ¦‹ peeking at the header with ncdump

Next, we export that volume to netCDF and let ncdump show us the goods β€” headers, coordinates, the whole vibe check:

#####################################################################
# We use the netCDF ncdump tool to have a look at the header
# and coordinates of the exported netCDF file
#####################################################################
r3.out.netcdf --o input=volume_float output=test_float.nc
ncdump -c test_float.nc

and it gives us this:

netcdf test_float {
dimensions:
        longitude = 36 ;
        latitude = 18 ;
        z = 5 ;
variables:
        float longitude(longitude) ;
                longitude:units = "degrees_east" ;
                longitude:long_name = "Longitude values" ;
                longitude:standard_name = "longitude" ;
                longitude:axis = "X" ;
        float latitude(latitude) ;
                latitude:units = "degrees_north" ;
                latitude:long_name = "Latitude values" ;
                latitude:standard_name = "latitude" ;
                latitude:axis = "Y" ;
        float z(z) ;
                z:units = "meter" ;
                z:long_name = "z coordinate of projection" ;
                z:standard_name = "projection_z_coordinate" ;
                z:positive = "up" ;
                z:axis = "Z" ;
        float volume_float(z, latitude, longitude) ;
                volume_float:valid_min = 3.f ;
                volume_float:valid_max = 59.f ;
// global attributes:
                :Conventions = "CF-1.5" ;
                :history = "GRASS GIS netCDF export of r3.out.netcdf" ;
data:
 longitude = -175, -165, -155, -145, -135, -125, -115, -105, -95, -85, -75,
    -65, -55, -45, -35, -25, -15, -5, 5, 15, 25, 35, 45, 55, 65, 75, 85, 95,
    105, 115, 125, 135, 145, 155, 165, 175 ;
 latitude = 85, 75, 65, 55, 45, 35, 25, 15, 5, -5, -15, -25, -35, -45, -55,
    -65, -75, -85 ;
 z = 0.5, 1.5, 2.5, 3.5, 4.5 ;
}

look at those units, long_name, standard_name and axis attributes β€” that's the map metadata getting carried over, fr fr ✨


🌈 exporting projection settings and a null value

now we add the projection-specific stuff and tell it what a null value looks like, using -p and null=-1:

#####################################################################
# Exporting the projection specific settings and a null value
#####################################################################
r3.out.netcdf --o -p null=-1 input=volume_float output=test_float.nc
ncdump -c test_float.nc

and boom, we gained a whole crs variable plus missing_value, _FillValue and grid_mapping:

netcdf test_float {
dimensions:
        longitude = 36 ;
        latitude = 18 ;
        z = 5 ;
variables:
        char crs ;
                crs:crs_wkt = "GEOGCS[\"wgs84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS_1984\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]" ;
                crs:spatial_ref = "GEOGCS[\"wgs84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS_1984\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]" ;
                crs:crs_proj4 = " +proj=longlat +no_defs +a=6378137 +rf=298.257223563 +towgs84=0.000,0.000,0.000" ;
        float longitude(longitude) ;
                longitude:units = "degrees_east" ;
                longitude:long_name = "Longitude values" ;
                longitude:standard_name = "longitude" ;
                longitude:axis = "X" ;
        float latitude(latitude) ;
                latitude:units = "degrees_north" ;
                latitude:long_name = "Latitude values" ;
                latitude:standard_name = "latitude" ;
                latitude:axis = "Y" ;
        float z(z) ;
                z:units = "meter" ;
                z:long_name = "z coordinate of projection" ;
                z:standard_name = "projection_z_coordinate" ;
                z:positive = "up" ;
                z:axis = "Z" ;
        float volume_float(z, latitude, longitude) ;
                volume_float:valid_min = 3.f ;
                volume_float:valid_max = 59.f ;
                volume_float:missing_value = -1.f ;
                volume_float:_FillValue = -1.f ;
                volume_float:grid_mapping = "crs" ;
// global attributes:
                :Conventions = "CF-1.5" ;
                :history = "GRASS GIS netCDF export of r3.out.netcdf" ;
data:
 longitude = -175, -165, -155, -145, -135, -125, -115, -105, -95, -85, -75,
    -65, -55, -45, -35, -25, -15, -5, 5, 15, 25, 35, 45, 55, 65, 75, 85, 95,
    105, 115, 125, 135, 145, 155, 165, 175 ;
 latitude = 85, 75, 65, 55, 45, 35, 25, 15, 5, -5, -15, -25, -35, -45, -55,
    -65, -75, -85 ;
 z = 0.5, 1.5, 2.5, 3.5, 4.5 ;
}

πŸŽ€ time as the vertical unit + an absolute time stamp

okay now we're getting fancy πŸ’… we stamp the map with actual dates, set the vertical unit to days, and export again:

#####################################################################
# Assigning time as vertical unit and setting an absolute time stamp
#####################################################################
r3.timestamp map=volume_float date=’1 Jan 2001/5 Jan 2001’
r3.support map=volume_float vunit="days"
r3.out.netcdf --o -p null=-1 input=volume_float output=test_float.nc
ncdump -c test_float.nc

and now the z dimension straight up becomes time, with units, long_name, calendar, positive and axis all set:

netcdf test_float {
dimensions:
        longitude = 36 ;
        latitude = 18 ;
        time = 5 ;
variables:
        char crs ;
                crs:crs_wkt = "GEOGCS[\"wgs84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS_1984\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]" ;
                crs:spatial_ref = "GEOGCS[\"wgs84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS_1984\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]" ;
                crs:crs_proj4 = " +proj=longlat +no_defs +a=6378137 +rf=298.257223563 +towgs84=0.000,0.000,0.000" ;
        float longitude(longitude) ;
                longitude:units = "degrees_east" ;
                longitude:long_name = "Longitude values" ;
                longitude:standard_name = "longitude" ;
                longitude:axis = "X" ;
        float latitude(latitude) ;
                latitude:units = "degrees_north" ;
                latitude:long_name = "Latitude values" ;
                latitude:standard_name = "latitude" ;
                latitude:axis = "Y" ;
        int time(time) ;
                time:units = "days since 2001-01-01 00:00:00" ;
                time:long_name = "Time in days" ;
                time:calendar = "gregorian" ;
                time:positive = "up" ;
                time:axis = "T" ;
        float volume_float(time, latitude, longitude) ;
                volume_float:valid_min = 3.f ;
                volume_float:valid_max = 59.f ;
                volume_float:missing_value = -1.f ;
                volume_float:_FillValue = -1.f ;
                volume_float:grid_mapping = "crs" ;
// global attributes:
                :Conventions = "CF-1.5" ;
                :history = "GRASS GIS netCDF export of r3.out.netcdf" ;
data:
 longitude = -175, -165, -155, -145, -135, -125, -115, -105, -95, -85, -75,
    -65, -55, -45, -35, -25, -15, -5, 5, 15, 25, 35, 45, 55, 65, 75, 85, 95,
    105, 115, 125, 135, 145, 155, 165, 175 ;
 latitude = 85, 75, 65, 55, 45, 35, 25, 15, 5, -5, -15, -25, -35, -45, -55,
    -65, -75, -85 ;
 time = 0, 1, 2, 3, 4 ;
}

periodt. five depths in, five time steps out 🫢


πŸ‘€ SEE ALSO

  • t.rast.to.rast3
  • r3.in.ascii
  • g.region

πŸ‘‘ AUTHORS

SΓΆren Gebbert

✨ SOURCE CODE ✨

ok so if you wanna go look at the actual code (and honestly? slay, do it) it's right here:

  • Available at: r3.out.netcdf source code (history)

Latest change: Monday Dec 08 21:47:55 2025 in commit:

d3c6479bef77a58e3b5d85259303dbfb9c1babe8

and then there's the lil index fam, all of them linking you deeper into the docs β€” collect them all like they're pokΓ©mon bestie πŸ’–

  • Main index
  • 3D raster index
  • Topics index
  • Keywords index
  • Graphical index
  • Full index

Β© 2003-2026 GRASS Development Team, GRASS 8.5.0 Reference Manual


okay that's the whole page, you made it, I'm so proud of you 🫢 This absolute icon of a manpage is straight outta the GRASS 8.5.0 reference manual, and the last glow-up on it was that Monday Dec 08 21:47:55 2025 commit β€” so it's fresh, it's current, it's giving maintained. Now go write some netCDF files, bestie. no cap. πŸ’…βœ¨

πŸ“¦ where this page comes from