Skip to content

Quick start

Installation

Install the packages used in this tutorial:

julia
using Pkg
Pkg.add(["Rasters", "Dates", "RasterDataSources", "CairoMakie", "ArchGDAL"])

Creating a Raster

Using Rasters to read GeoTiff or NetCDF files will output something similar to the following toy examples. This is possible because Rasters.jl extends DimensionalData.jl so that spatial data can be indexed using named dimensions like X and Y (coordinates) and Ti (time).

julia
using Rasters, Dates

lon, lat = X(25:1:30), Y(25:1:30)
ti = Ti(DateTime(2001):Month(1):DateTime(2002))
ras = Raster(rand(lon, lat, ti)) # this generates random numbers with the dimensions given
6×6×13 Raster{Float64, 3}
├───────────────────────────┴──────────────────────────────────────────── dims ┐
X Sampled{Int64} 25:1:30 ForwardOrdered Regular Points,
Y Sampled{Int64} 25:1:30 ForwardOrdered Regular Points,
Ti Sampled{DateTime} DateTime("2001-01-01T00:00:00"):Month(1):DateTime("2002-01-01T00:00:00") ForwardOrdered Regular Points
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (25, 30), Y = (25, 30), Ti = (DateTime("2001-01-01T00:00:00"), DateTime("2002-01-01T00:00:00")))
└──────────────────────────────────────────────────────────────────────────────┘
[:, :, 1]
  25         26         27          28         29         30
 25     0.61387    0.988239   0.9995      0.4737     0.809226   0.146347
 26     0.177892   0.43791    0.816345    0.4739     0.76391    0.0885219
 27     0.510756   0.842596   0.852934    0.215464   0.505636   0.019502
 28     0.333711   0.622969   0.399384    0.707726   0.147902   0.1399
 29     0.622872   0.185492   0.984605    0.67335    0.849558   0.0796227
 30     0.326132   0.792873   0.0814852   0.705141   0.700919   0.58536

Getting the lookup array from dimensions

Lookups are ranges assigned to each dimension axis, letting us refer to data within our Raster by its real-world values (like longitude, latitude, or time) instead of integer index positions.

julia
lon = lookup(ras, X) # if X is longitude
lat = lookup(ras, Y) # if Y is latitude
Sampled{Int64} ForwardOrdered Regular Points
wrapping: 25:1:30

Dimensions

Rasters uses X, Y, and Z dimensions from DimensionalData to represent spatial directions like longitude, latitude and the vertical dimension, and subset data with them. Ti is used for time, and Band represents bands. Other dimensions can have arbitrary names, but will be treated generically. See DimensionalData for more details on how they work.

Select by index

Select a time slice by its integer index:

julia
ras[Ti(1)]
6×6 Raster{Float64, 2}
├────────────────────────┴───────────────────────────── dims ┐
X Sampled{Int64} 25:1:30 ForwardOrdered Regular Points,
Y Sampled{Int64} 25:1:30 ForwardOrdered Regular Points
├──────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (25, 30), Y = (25, 30))
└────────────────────────────────────────────────────────────┘
  25         26         27          28         29         30
 25     0.61387    0.988239   0.9995      0.4737     0.809226   0.146347
 26     0.177892   0.43791    0.816345    0.4739     0.76391    0.0885219
 27     0.510756   0.842596   0.852934    0.215464   0.505636   0.019502
 28     0.333711   0.622969   0.399384    0.707726   0.147902   0.1399
 29     0.622872   0.185492   0.984605    0.67335    0.849558   0.0796227
 30     0.326132   0.792873   0.0814852   0.705141   0.700919   0.58536

The same slice can also be selected with keyword syntax:

julia
ras[Ti=1]
6×6 Raster{Float64, 2}
├────────────────────────┴───────────────────────────── dims ┐
X Sampled{Int64} 25:1:30 ForwardOrdered Regular Points,
Y Sampled{Int64} 25:1:30 ForwardOrdered Regular Points
├──────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (25, 30), Y = (25, 30))
└────────────────────────────────────────────────────────────┘
  25         26         27          28         29         30
 25     0.61387    0.988239   0.9995      0.4737     0.809226   0.146347
 26     0.177892   0.43791    0.816345    0.4739     0.76391    0.0885219
 27     0.510756   0.842596   0.852934    0.215464   0.505636   0.019502
 28     0.333711   0.622969   0.399384    0.707726   0.147902   0.1399
 29     0.622872   0.185492   0.984605    0.67335    0.849558   0.0796227
 30     0.326132   0.792873   0.0814852   0.705141   0.700919   0.58536

A range of indices can also be selected using the syntax = a:b or (a:b):

julia
ras[Ti(1:10)]
6×6×10 Raster{Float64, 3}
├───────────────────────────┴──────────────────────────────────────────── dims ┐
X Sampled{Int64} 25:1:30 ForwardOrdered Regular Points,
Y Sampled{Int64} 25:1:30 ForwardOrdered Regular Points,
Ti Sampled{DateTime} DateTime("2001-01-01T00:00:00"):Month(1):DateTime("2001-10-01T00:00:00") ForwardOrdered Regular Points
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (25, 30), Y = (25, 30), Ti = (DateTime("2001-01-01T00:00:00"), DateTime("2001-10-01T00:00:00")))
└──────────────────────────────────────────────────────────────────────────────┘
[:, :, 1]
  25         26         27          28         29         30
 25     0.61387    0.988239   0.9995      0.4737     0.809226   0.146347
 26     0.177892   0.43791    0.816345    0.4739     0.76391    0.0885219
 27     0.510756   0.842596   0.852934    0.215464   0.505636   0.019502
 28     0.333711   0.622969   0.399384    0.707726   0.147902   0.1399
 29     0.622872   0.185492   0.984605    0.67335    0.849558   0.0796227
 30     0.326132   0.792873   0.0814852   0.705141   0.700919   0.58536

Select by value

Instead of integer positions, we can select using the actual coordinate values with At:

julia
ras[Ti=At(DateTime(2001))]
6×6 Raster{Float64, 2}
├────────────────────────┴───────────────────────────── dims ┐
X Sampled{Int64} 25:1:30 ForwardOrdered Regular Points,
Y Sampled{Int64} 25:1:30 ForwardOrdered Regular Points
├──────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (25, 30), Y = (25, 30))
└────────────────────────────────────────────────────────────┘
  25         26         27          28         29         30
 25     0.61387    0.988239   0.9995      0.4737     0.809226   0.146347
 26     0.177892   0.43791    0.816345    0.4739     0.76391    0.0885219
 27     0.510756   0.842596   0.852934    0.215464   0.505636   0.019502
 28     0.333711   0.622969   0.399384    0.707726   0.147902   0.1399
 29     0.622872   0.185492   0.984605    0.67335    0.849558   0.0796227
 30     0.326132   0.792873   0.0814852   0.705141   0.700919   0.58536

Lookup Arrays

These specify properties of the index associated with e.g. the X and Y dimension. Rasters.jl defines additional lookup arrays: Projected to handle dimensions with projections, and Mapped where the projection is mapped to another projection like EPSG(4326). Mapped is largely designed to handle NetCDF dimensions, especially with Explicit spans.

Subsetting an object

Regular getindex (e.g. A[1:100, :]) and view work on all objects, just as with an Array. view is always lazy, and reads from disk are deferred until getindex is used.

DimensionalData.jl's Dimensions and Selectors are another way to subset an object, using the object's lookups to find values at specific X/Y coordinates (or any other dimensions). The available selectors are listed here:

SelectorsDescription
At(x)get the index exactly matching the passed in value(s).
Near(x)get the closest index to the passed in value(s).
Where(f::Function)filter the array axis by a function of the dimension index values.
a..b/Between(a, b)get all indices between two values, excluding the high value.
Contains(x)get indices where the value x falls within an interval.

The next example uses some real world data. To download data you will need to specify a folder to put it in. You can do this by assigning the environment variable RASTERDATASOURCES_PATH:

julia
ENV["RASTERDATASOURCES_PATH"] = joinpath(homedir(), "RasterDataSources") # or "/your/path/here"

Use the .. selector to take a view of Madagascar:

julia
import ArchGDAL
using Rasters, RasterDataSources
using CairoMakie
CairoMakie.activate!()

A = Raster(WorldClim{BioClim}, 5)
madagascar = view(A, X(43.25 .. 50.48), Y(-25.61 .. -12.04))
# Note the space between .. -12
Makie.plot(madagascar)