Raster analysis in Julia#

In this lesson, we discuss cover the basics of Raster analysis data structures in Julia.

Authors & Contributors#

Notebook#

  • Felix Cremer, Max Planck Institute for Biogeochemistry (Germany), @felixcremer

  • Anshul Singhvi, Columbia University (USA), @asinghvi17

  • Rafael Schouten, Center for Macroecology, Evolution and Climate (Denmark), @rafaqz

  • spaette, @spaette

Contributors#

  • Anne Fouilloux, Simula (Norway), @annefou

This tutorial is based on the xarray in 45 minutes https://tutorial.xarray.dev/overview/xarray-in-45-min.html and the Julia notebook JuliaGeo/JuliaGeoTutorials from the JuliaGeoTutorials Github repository.

Overview

Questions
  • What are the basic data structures in Julia to manipulate raster data?
  • How can I read and write netCDF data in Julia?
  • How can I analyse raster data in Julia?
  • How can I plot raster data in Julia?
Objectives
  • Understand the basic data structures in Julia
  • Inspect `DimArray` and `DimStack` objects
  • Read and write netCDF files using Rasters.jl

Context#

We will use the same example that is used in the xarray tutorial.

Data#

As example data we use the data in the data repository.

Here we’ll use air temperature from the National Center for Environmental Prediction.

Setup#

This episode uses the following main Python packages:

Please install these packages if not already available in your Julia environment. Also note that Julia standard libraries such as Statistics Julia standard Library are already installed by default with the julia kernel.

Packages#

In this episode, some Julia packages are imported when we start to use them. However, for best software practices, we recommend you to install and import all the necessary libraries at the top of your Jupyter notebook.

Before we can start we need to activate the current environment to install all the necessary dependencies (see Project.toml file in the current directory.

using Pkg
Pkg.activate(".")
Pkg.instantiate()
  Activating project at `~/JuliaGeoTutorials/Raster-in-45-min`
using Rasters
using NCDatasets

path = "./data/air_temperature.nc"

# Now we can open the data as a RasterStack
ds = RasterStack(path)
╭────────────────────────╮
│ 53×25×2920 RasterStack │
├────────────────────────┴─────────────────────────────────────────────── dims ┐
  ↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  ↗ Ti Sampled{Dates.DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points
├────────────────────────────────────────────────────────────────────── layers ┤
  :air eltype: Float64 dims: X, Y, Ti size: 53×25×2920
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 5 entries:
  "references"  => "http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly…
  "platform"    => "Model"
  "title"       => "4x daily NMC reanalysis (1948)"
  "description" => "Data is from NMC initialized reanalysis\n(4x/day).  These a…
  "Conventions" => "COARDS"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0), Ti = (Dates.DateTime("2013-01-01T00:00:00"), Dates.DateTime("2014-12-31T18:00:00")))
  missingval: missing
  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘

What’s in a DimStack?#

Many DimArrays!

DimStacks are dictionary-like containers of “DimArray”s. They are a mapping of variable name to DimArray. The RasterStack is a special case of a DimStack with some geospatial information. The DimArray s in the DimStack can share dimensions butdon’t have all the same dimensionality. If layers share a dimension name, this dimension is only stored once for the whole DimStack.

# pull out "air" dataarray with dictionary syntax
ds["air"]
╭──────────────────────────────────╮
│ 53×25×2920 Raster{Float64,3} air │
├──────────────────────────────────┴───────────────────────────────────── dims ┐
  ↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  ↗ Ti Sampled{Dates.DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 12 entries:
  "long_name"    => "4xDaily Air temperature at sigma level 995"
  "scale_factor" => 0.01
  "GRIB_name"    => "TMP"
  "precision"    => 2
  "var_desc"     => "Air temperature"
  "actual_range" => Float32[185.16, 322.1]
  "statistic"    => "Individual Obs"
  "GRIB_id"      => 11
  "dataset"      => "NMC Reanalysis"
  "units"        => "degK"
  "parent_stat"  => "Other"
  "level_desc"   => "Surface"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0), Ti = (Dates.DateTime("2013-01-01T00:00:00"), Dates.DateTime("2014-12-31T18:00:00")))

  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
[:, :, 1]
 ⋮      ⋱  

You can save some typing by using the “attribute” or “dot” notation and using tab completion.

# pull out dataarray using dot notation
ds.air
╭──────────────────────────────────╮
│ 53×25×2920 Raster{Float64,3} air │
├──────────────────────────────────┴───────────────────────────────────── dims ┐
  ↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  ↗ Ti Sampled{Dates.DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 12 entries:
  "long_name"    => "4xDaily Air temperature at sigma level 995"
  "scale_factor" => 0.01
  "GRIB_name"    => "TMP"
  "precision"    => 2
  "var_desc"     => "Air temperature"
  "actual_range" => Float32[185.16, 322.1]
  "statistic"    => "Individual Obs"
  "GRIB_id"      => 11
  "dataset"      => "NMC Reanalysis"
  "units"        => "degK"
  "parent_stat"  => "Other"
  "level_desc"   => "Surface"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0), Ti = (Dates.DateTime("2013-01-01T00:00:00"), Dates.DateTime("2014-12-31T18:00:00")))

  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
[:, :, 1]
 ⋮      ⋱  

What’s in a DimArray?#

data + (a lot of) metadata

Name (optional)#

da = ds.air

Rasters.name(da)
:air

Named dimensions#

dims(da) correspond to the axes of your data.

In this case we have 2 spatial dimensions (X and Y) and one temporal dimension (Ti).

dims(da)
(↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
→ Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
↗ Ti Sampled{Dates.DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points)

You can also extract a single dimension.

# extracting coordinate variables
dims(da, X)
X Mapped{Float32} ForwardOrdered Regular DimensionalData.Dimensions.Lookups.Points
wrapping: 53-element Vector{Float32}:
 200.0
 202.5
 205.0
 207.5
 210.0
 212.5
 215.0
 217.5
 220.0
 222.5
 225.0
 227.5
 230.0
   ⋮
 302.5
 305.0
 307.5
 310.0
 312.5
 315.0
 317.5
 320.0
 322.5
 325.0
 327.5
 330.0

It is useful to think of the values in the dimensions as axis “labels” such as “tick labels” in a figure. These are coordinate locations on a grid at which you have data.

Arbitrary attributes#

metadata is a metadata object that can hold arbitrary attributes that describe the underlying data.

metadata(da)
Metadata{Rasters.NCDsource} of Dict{String, Any} with 12 entries:
  "long_name"    => "4xDaily Air temperature at sigma level 995"
  "scale_factor" => 0.01
  "GRIB_name"    => "TMP"
  "precision"    => 2
  "var_desc"     => "Air temperature"
  "actual_range" => Float32[185.16, 322.1]
  "statistic"    => "Individual Obs"
  "GRIB_id"      => 11
  "dataset"      => "NMC Reanalysis"
  "units"        => "degK"
  "parent_stat"  => "Other"
  "level_desc"   => "Surface"
# assign your own attributes!
metadata(da)["myattrs"] = "Mine"
"Mine"

Underlying data#

A DimensionalData data structures wrap underlying simpler array-like data structures. These arrays have to fit into the Julia Array interface but can be either in memory arrays or DiskArray.jl arrays for lazy access or part of Xarray is quite extensible allowing for distributed array, GPU arrays, sparse arrays, arrays with units etc. We’ll briefly look at this later in this tutorial.

To access the underlying data use the parent function:

parent(da)
53×25×2920 Array{Float64, 3}:
[:, :, 1] =
 241.2   243.8   250.0   266.5   274.5   …  297.0   296.6   295.9   296.29
 242.5   244.5   249.8   267.1   274.29     296.7   296.2   296.2   296.79
 243.5   244.7   248.89  267.1   274.1      296.1   296.4   296.79  297.1
 244.0   244.2   247.5   266.7   274.0      295.9   296.5   296.5   297.0
 244.1   243.39  246.0   265.9   273.79     294.9   295.5   296.1   296.9
 243.89  242.39  244.39  264.7   273.0   …  293.4   294.0   295.1   296.4
 243.6   241.7   243.1   263.1   271.79     292.79  293.6   294.6   296.0
 243.1   241.3   242.39  261.6   270.6      292.4   293.4   294.4   295.7
 242.5   241.1   242.2   260.6   270.0      292.2   292.79  293.79  295.5
 241.89  241.1   242.5   260.1   269.9      292.2   292.9   293.79  295.4
 241.2   241.0   243.1   260.0   270.0   …  291.5   292.6   293.79  295.2
 240.3   240.5   243.5   259.9   269.9      291.1   292.2   293.29  295.2
 239.5   239.7   243.5   259.29  269.2      290.9   292.2   292.79  295.0
   ⋮                                     ⋱                          
 238.5   247.6   254.1   261.2   266.4      297.1   298.1   298.6   299.2
 234.7   245.89  256.0   264.2   268.79     297.5   298.1   298.4   299.79
 231.3   243.39  254.3   260.0   262.6      297.79  298.4   298.4   299.7
 228.8   240.39  249.6   250.6   251.1      297.9   298.79  298.9   299.1
 227.3   237.5   243.7   240.8   241.3   …  297.4   298.0   298.6   298.7
 227.0   235.0   238.3   235.2   239.3      297.0   297.29  297.9   298.6
 227.5   233.2   234.5   235.2   245.89     296.9   297.2   297.4   298.0
 228.8   232.0   232.39  239.3   256.8      296.29  296.7   296.9   297.79
 230.6   231.8   231.89  244.6   266.4      295.6   295.79  296.29  297.6
 232.8   232.8   233.2   249.2   271.4   …  295.1   295.4   295.9   296.9
 235.5   235.3   236.39  253.1   272.4      295.1   295.1   295.9   296.79
 238.6   239.3   241.7   256.9   271.9      294.9   294.7   295.2   296.6

[:, :, 2] =
 242.1   243.6   253.2   269.7   272.5   …  295.79  296.4   296.2   296.29
 242.7   244.1   252.89  269.4   271.5      295.79  295.9   296.7   297.2
 243.1   244.2   252.1   268.6   270.4      296.1   296.2   296.79  297.4
 243.39  244.1   250.8   267.4   269.4      296.0   296.1   296.4   297.4
 243.6   243.7   249.3   266.0   268.5      294.79  295.1   296.1   297.1
 243.8   243.3   247.5   264.4   268.0   …  293.2   294.1   295.6   296.7
 244.0   242.8   245.5   262.6   267.9      292.6   293.79  295.1   296.4
 244.1   242.39  243.6   260.79  268.1      292.6   293.6   294.5   295.79
 244.3   242.2   242.1   259.1   268.1      292.29  293.0   294.2   295.79
 244.3   242.0   241.1   257.7   267.79     292.0   292.9   294.1   295.6
 244.0   241.8   240.89  256.9   267.1   …  291.5   292.79  294.0   295.1
 243.39  241.5   241.3   256.7   266.6      291.2   292.4   293.6   295.29
 242.5   240.89  242.0   257.0   266.6      291.1   292.2   293.1   295.2
   ⋮                                     ⋱                          
 238.1   247.6   254.8   262.1   266.2      296.79  297.7   298.4   298.79
 234.7   245.6   256.0   264.4   268.4      297.2   297.9   298.2   299.29
 231.7   242.89  253.6   259.79  262.5      297.6   298.4   298.29  299.29
 229.6   239.89  248.6   250.6   252.0      297.6   298.5   298.5   298.6
 228.5   237.3   242.8   241.5   243.1   …  297.5   298.0   298.29  298.2
 228.39  235.1   237.7   236.3   241.3      297.29  297.4   297.7   298.1
 228.89  233.3   234.0   236.1   247.2      297.0   297.0   297.2   297.5
 229.7   231.89  231.6   239.39  257.1      296.5   296.7   297.1   297.1
 230.7   231.0   230.39  243.5   266.0      295.9   296.1   296.4   296.9
 232.0   231.0   230.8   247.2   270.9   …  295.2   295.4   295.6   296.4
 233.6   232.5   233.39  250.5   272.29     294.9   295.1   295.5   296.4
 235.8   235.7   238.5   254.39  272.29     294.7   294.79  295.1   296.6

[:, :, 3] =
 242.3   244.6   256.2   269.29  271.9   …  295.0   295.6   296.2   296.4
 242.2   244.39  255.5   268.5   271.79     295.0   295.4   296.5   296.29
 242.3   244.0   254.2   267.0   271.6      294.9   295.4   296.29  296.4
 242.5   243.39  252.3   265.0   270.7      295.0   295.2   295.5   296.29
 242.89  242.8   250.2   262.7   269.4      294.0   294.1   295.1   296.29
 243.6   242.39  248.1   260.29  267.79  …  292.4   293.1   294.5   295.79
 244.5   242.3   246.3   258.5   266.6      292.1   293.1   294.1   295.2
 245.7   242.3   244.89  257.29  266.2      292.2   292.9   293.5   295.1
 246.8   242.39  243.7   256.8   266.2      292.0   292.29  293.0   295.0
 247.7   242.5   242.6   256.39  265.9      291.4   292.2   293.2   294.5
 248.2   242.3   241.7   255.8   265.1   …  290.6   291.7   293.2   294.29
 248.0   241.8   240.8   255.2   264.0      290.7   291.4   292.79  294.7
 247.2   241.1   240.3   254.89  263.4      290.9   291.79  292.7   294.9
   ⋮                                     ⋱                          
 240.2   248.1   253.7   260.9   266.5      297.1   297.9   298.29  298.9
 237.89  247.39  256.6   264.2   269.1      297.6   298.1   298.2   299.5
 235.7   245.7   256.1   261.29  264.29     298.0   298.7   298.5   299.2
 233.89  243.1   252.7   254.0   254.8      298.4   299.0   299.0   298.7
 232.6   240.2   247.7   246.1   246.5   …  298.29  298.29  298.79  298.79
 232.0   237.3   242.6   241.2   244.2      297.7   297.6   298.0   298.7
 231.89  234.39  238.0   240.39  249.2      297.0   297.4   297.6   297.9
 232.2   232.0   234.3   242.39  258.0      296.6   297.0   297.7   297.9
 233.0   230.39  231.8   245.3   266.0      296.29  296.7   297.1   297.6
 234.3   230.3   231.2   247.89  270.5   …  295.6   296.29  296.4   297.0
 236.1   232.0   233.2   250.6   271.79     294.9   295.29  296.0   297.0
 238.7   235.7   238.2   254.2   271.79     294.79  295.0   295.6   296.79

;;; … 

[:, :, 2918] =
 243.49  249.09  262.69  273.49  273.89  …  292.99  294.79  296.79  298.19
 242.99  248.99  262.19  272.99  274.19     293.49  295.29  297.89  299.19
 242.09  248.59  261.69  272.49  274.29     295.99  297.49  298.29  298.79
 240.69  247.79  260.89  271.89  274.39     297.39  298.49  298.19  298.69
 239.19  246.49  259.79  271.09  274.49     297.09  297.99  298.59  299.29
 237.69  244.99  258.09  270.19  274.69  …  296.59  297.49  298.49  298.99
 236.59  243.59  255.99  269.09  274.99     295.69  297.29  298.19  298.59
 235.99  242.49  253.69  267.89  275.19     294.79  296.79  297.79  298.19
 235.99  241.89  251.29  266.29  274.99     294.59  296.29  297.69  298.29
 236.39  241.69  249.19  264.49  274.09     294.49  296.19  297.79  298.29
 237.09  241.79  247.39  262.29  272.39  …  293.99  295.69  297.39  297.49
 237.79  241.89  245.99  260.19  270.49     293.99  295.39  296.89  297.69
 238.39  241.89  245.09  258.39  268.79     294.19  295.29  295.99  297.49
   ⋮                                     ⋱                          
 254.49  255.29  258.79  263.99  267.29     297.99  298.59  298.59  299.19
 252.39  256.09  262.19  267.39  269.59     297.89  298.59  298.29  299.69
 249.99  254.99  261.69  263.69  262.69     297.09  298.29  297.59  298.79
 247.79  252.49  257.49  254.89  250.99     296.49  297.89  297.69  297.89
 245.89  249.09  251.39  245.59  241.79  …  295.89  296.99  297.39  297.79
 244.59  245.79  245.39  240.09  241.09     295.79  296.89  296.79  297.69
 243.89  243.09  241.09  240.09  249.19     295.59  296.79  296.79  297.29
 243.69  241.39  238.79  243.89  261.29     295.09  296.19  297.09  297.19
 243.89  240.59  238.39  248.99  271.29     295.09  295.69  296.39  297.09
 244.19  240.59  239.39  253.49  276.49  …  294.69  295.49  295.49  296.09
 244.49  241.29  241.69  257.39  277.89     294.69  295.39  295.49  295.79
 244.89  242.69  245.19  261.39  278.29     294.79  294.69  294.79  295.79

[:, :, 2919] =
 245.79  249.89  262.39  273.29  273.59  …  291.59  293.69  296.29  297.79
 244.79  249.29  261.79  272.89  273.99     291.69  293.89  297.19  298.39
 243.49  248.49  261.29  272.49  274.19     293.59  295.39  297.59  298.49
 241.89  247.29  260.59  272.09  274.49     295.89  297.19  297.89  298.59
 240.29  245.69  259.39  271.59  274.69     296.89  297.79  298.29  298.79
 238.89  243.99  257.69  270.99  274.99  …  296.79  297.49  298.09  298.69
 237.79  242.29  255.49  270.29  275.29     296.09  297.49  297.79  298.49
 237.19  240.89  252.99  269.29  275.59     294.99  297.29  297.79  297.99
 237.09  239.89  250.29  267.89  275.79     294.69  296.49  297.89  298.29
 237.29  239.29  247.59  265.89  275.59     294.69  295.99  297.69  298.19
 237.59  239.09  244.99  262.99  274.69  …  294.49  295.99  297.49  297.39
 237.89  238.99  242.59  259.49  272.99     294.39  295.79  296.99  297.69
 238.09  238.99  240.59  255.69  270.49     294.39  295.49  295.89  297.59
   ⋮                                     ⋱                          
 255.49  256.19  258.69  262.69  267.19     298.09  298.39  298.49  298.69
 253.19  256.59  262.09  265.99  269.59     297.49  297.89  297.89  299.09
 250.69  255.39  261.79  263.19  263.99     296.69  297.89  297.69  298.89
 248.19  252.79  257.99  255.69  253.99     296.19  297.59  297.69  297.79
 246.09  249.39  252.09  247.59  246.29  …  295.69  296.59  297.59  297.99
 244.39  245.89  246.29  242.79  245.99     295.69  296.39  296.99  297.99
 243.39  243.09  241.89  242.79  253.39     295.29  296.29  296.49  296.79
 242.89  241.39  239.59  246.29  264.19     294.59  295.49  296.79  296.89
 242.89  240.79  239.19  250.79  272.99     294.49  294.89  295.89  296.59
 243.29  241.29  240.49  254.89  277.29  …  294.49  295.09  295.29  295.69
 243.99  242.49  243.09  258.29  277.99     294.29  294.69  295.09  295.49
 244.79  244.29  246.89  261.79  277.59     294.49  294.29  294.39  295.19

[:, :, 2920] =
 245.09  249.89  262.99  272.19  271.19  …  292.89  293.79  296.09  297.69
 244.29  249.29  262.19  272.09  271.89     292.09  293.69  296.89  298.09
 243.29  248.39  261.39  271.99  272.59     292.99  295.09  297.19  298.09
 242.19  246.99  259.99  271.59  273.09     295.09  296.69  297.49  298.49
 241.09  245.09  257.79  270.69  273.09     296.09  297.29  298.19  298.89
 240.09  243.09  254.99  269.29  272.89  …  296.59  297.29  298.09  298.69
 239.39  241.09  251.99  267.69  272.99     296.49  297.39  297.79  298.39
 238.99  239.59  249.09  266.19  273.39     295.79  297.49  297.79  298.09
 238.89  238.59  246.59  264.79  273.99     295.59  297.19  297.69  298.09
 239.09  238.29  244.49  263.19  274.19     295.39  296.49  297.59  297.99
 239.39  238.39  242.59  260.89  273.69  …  294.89  296.09  297.39  297.49
 239.49  238.59  240.89  257.89  272.29     294.89  296.19  296.79  297.49
 239.49  238.89  239.29  254.19  270.09     294.59  296.09  296.39  297.49
   ⋮                                     ⋱                          
 256.09  255.49  257.29  262.39  266.69     298.59  299.39  299.99  299.89
 254.29  255.99  260.79  266.49  269.39     298.39  299.09  299.69  300.49
 252.49  255.19  261.29  264.99  264.79     297.49  299.09  298.99  299.99
 250.59  253.29  258.49  258.89  255.89     296.49  298.69  298.69  299.09
 248.69  250.29  253.39  251.69  248.59  …  296.09  297.59  298.69  299.29
 246.79  246.99  247.69  246.79  247.69     296.19  297.09  298.19  299.29
 245.09  243.79  242.89  245.69  253.69     295.79  296.69  297.39  297.89
 243.59  241.39  239.89  247.89  263.19     294.99  295.79  297.29  297.39
 242.39  239.99  238.99  251.59  271.49     294.59  295.19  296.49  297.19
 241.69  239.59  239.89  255.39  276.09  …  294.59  295.29  295.69  296.49
 241.49  240.29  242.59  258.99  277.39     294.19  295.09  295.69  296.19
 241.79  241.69  246.29  262.49  277.29     294.29  294.69  295.19  295.69
# what is the type of the underlying data
typeof(parent(da))
Array{Float64, 3}

We can change the underlying data type by using the lazy keyword for opening the data. This is especially helpful for very large data or data that is hosted online where we would not want to download the whole dataset before starting the analysis.

dsl = RasterStack(path, lazy=true)
╭────────────────────────╮
│ 53×25×2920 RasterStack │
├────────────────────────┴─────────────────────────────────────────────── dims ┐
  ↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  ↗ Ti Sampled{Dates.DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points
├────────────────────────────────────────────────────────────────────── layers ┤
  :air eltype: Union{Missing, Float64} dims: X, Y, Ti size: 53×25×2920
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 5 entries:
  "references"  => "http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly…
  "platform"    => "Model"
  "title"       => "4x daily NMC reanalysis (1948)"
  "description" => "Data is from NMC initialized reanalysis\n(4x/day).  These a…
  "Conventions" => "COARDS"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0), Ti = (Dates.DateTime("2013-01-01T00:00:00"), Dates.DateTime("2014-12-31T18:00:00")))
  missingval: missing
  crs: EPSG:4326
  mappedcrs: EPSG:4326
  filename: 
└──────────────────────────────────────────────────────────────────────────────┘
dal = dsl.air
╭──────────────────────────────────────────────────╮
│ 53×25×2920 Raster{Union{Missing, Float64},3} air │
├──────────────────────────────────────────────────┴───────────────────── dims ┐
  ↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  ↗ Ti Sampled{Dates.DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 12 entries:
  "long_name"    => "4xDaily Air temperature at sigma level 995"
  "scale_factor" => 0.01
  "GRIB_name"    => "TMP"
  "precision"    => 2
  "var_desc"     => "Air temperature"
  "actual_range" => Float32[185.16, 322.1]
  "statistic"    => "Individual Obs"
  "GRIB_id"      => 11
  "dataset"      => "NMC Reanalysis"
  "units"        => "degK"
  "parent_stat"  => "Other"
  "level_desc"   => "Surface"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0), Ti = (Dates.DateTime("2013-01-01T00:00:00"), Dates.DateTime("2014-12-31T18:00:00")))
  missingval: missing
  crs: EPSG:4326
  mappedcrs: EPSG:4326
  filename: 
└──────────────────────────────────────────────────────────────────────────────┘
typeof(parent(dal))
Rasters.FileArray{Rasters.NCDsource, Union{Missing, Float64}, 3, Symbol, Nothing, DiskArrays.GridChunks{3, Tuple{DiskArrays.RegularChunks, DiskArrays.RegularChunks, DiskArrays.RegularChunks}}, DiskArrays.Unchunked}

Review#

DimensionalData provides two main data structures:

  1. DimArrays that wrap underlying data containers and contain associated metadata in the

  2. DimStacks that are dictionary-like containers of DataArrays

DimArrays contain underlying arrays and associated metadata:

  1. Name

  2. Dimension names

  3. Lookup values

  4. Metadata


Why named dimensions and labeled dimensions?#

Metadata provides context and provides code that is more legible. This reduces the likelihood of errors from typos and makes analysis more intuitive and fun!

Analysis without named dimensions:#

# plot the first timestep
lon = ds.air.dims[1].val.data  # Vector
lat = ds.air.dims[2].val.data  # Vector
temp = parent(da)  # vector
53×25×2920 Array{Float64, 3}:
[:, :, 1] =
 241.2   243.8   250.0   266.5   274.5   …  297.0   296.6   295.9   296.29
 242.5   244.5   249.8   267.1   274.29     296.7   296.2   296.2   296.79
 243.5   244.7   248.89  267.1   274.1      296.1   296.4   296.79  297.1
 244.0   244.2   247.5   266.7   274.0      295.9   296.5   296.5   297.0
 244.1   243.39  246.0   265.9   273.79     294.9   295.5   296.1   296.9
 243.89  242.39  244.39  264.7   273.0   …  293.4   294.0   295.1   296.4
 243.6   241.7   243.1   263.1   271.79     292.79  293.6   294.6   296.0
 243.1   241.3   242.39  261.6   270.6      292.4   293.4   294.4   295.7
 242.5   241.1   242.2   260.6   270.0      292.2   292.79  293.79  295.5
 241.89  241.1   242.5   260.1   269.9      292.2   292.9   293.79  295.4
 241.2   241.0   243.1   260.0   270.0   …  291.5   292.6   293.79  295.2
 240.3   240.5   243.5   259.9   269.9      291.1   292.2   293.29  295.2
 239.5   239.7   243.5   259.29  269.2      290.9   292.2   292.79  295.0
   ⋮                                     ⋱                          
 238.5   247.6   254.1   261.2   266.4      297.1   298.1   298.6   299.2
 234.7   245.89  256.0   264.2   268.79     297.5   298.1   298.4   299.79
 231.3   243.39  254.3   260.0   262.6      297.79  298.4   298.4   299.7
 228.8   240.39  249.6   250.6   251.1      297.9   298.79  298.9   299.1
 227.3   237.5   243.7   240.8   241.3   …  297.4   298.0   298.6   298.7
 227.0   235.0   238.3   235.2   239.3      297.0   297.29  297.9   298.6
 227.5   233.2   234.5   235.2   245.89     296.9   297.2   297.4   298.0
 228.8   232.0   232.39  239.3   256.8      296.29  296.7   296.9   297.79
 230.6   231.8   231.89  244.6   266.4      295.6   295.79  296.29  297.6
 232.8   232.8   233.2   249.2   271.4   …  295.1   295.4   295.9   296.9
 235.5   235.3   236.39  253.1   272.4      295.1   295.1   295.9   296.79
 238.6   239.3   241.7   256.9   271.9      294.9   294.7   295.2   296.6

[:, :, 2] =
 242.1   243.6   253.2   269.7   272.5   …  295.79  296.4   296.2   296.29
 242.7   244.1   252.89  269.4   271.5      295.79  295.9   296.7   297.2
 243.1   244.2   252.1   268.6   270.4      296.1   296.2   296.79  297.4
 243.39  244.1   250.8   267.4   269.4      296.0   296.1   296.4   297.4
 243.6   243.7   249.3   266.0   268.5      294.79  295.1   296.1   297.1
 243.8   243.3   247.5   264.4   268.0   …  293.2   294.1   295.6   296.7
 244.0   242.8   245.5   262.6   267.9      292.6   293.79  295.1   296.4
 244.1   242.39  243.6   260.79  268.1      292.6   293.6   294.5   295.79
 244.3   242.2   242.1   259.1   268.1      292.29  293.0   294.2   295.79
 244.3   242.0   241.1   257.7   267.79     292.0   292.9   294.1   295.6
 244.0   241.8   240.89  256.9   267.1   …  291.5   292.79  294.0   295.1
 243.39  241.5   241.3   256.7   266.6      291.2   292.4   293.6   295.29
 242.5   240.89  242.0   257.0   266.6      291.1   292.2   293.1   295.2
   ⋮                                     ⋱                          
 238.1   247.6   254.8   262.1   266.2      296.79  297.7   298.4   298.79
 234.7   245.6   256.0   264.4   268.4      297.2   297.9   298.2   299.29
 231.7   242.89  253.6   259.79  262.5      297.6   298.4   298.29  299.29
 229.6   239.89  248.6   250.6   252.0      297.6   298.5   298.5   298.6
 228.5   237.3   242.8   241.5   243.1   …  297.5   298.0   298.29  298.2
 228.39  235.1   237.7   236.3   241.3      297.29  297.4   297.7   298.1
 228.89  233.3   234.0   236.1   247.2      297.0   297.0   297.2   297.5
 229.7   231.89  231.6   239.39  257.1      296.5   296.7   297.1   297.1
 230.7   231.0   230.39  243.5   266.0      295.9   296.1   296.4   296.9
 232.0   231.0   230.8   247.2   270.9   …  295.2   295.4   295.6   296.4
 233.6   232.5   233.39  250.5   272.29     294.9   295.1   295.5   296.4
 235.8   235.7   238.5   254.39  272.29     294.7   294.79  295.1   296.6

[:, :, 3] =
 242.3   244.6   256.2   269.29  271.9   …  295.0   295.6   296.2   296.4
 242.2   244.39  255.5   268.5   271.79     295.0   295.4   296.5   296.29
 242.3   244.0   254.2   267.0   271.6      294.9   295.4   296.29  296.4
 242.5   243.39  252.3   265.0   270.7      295.0   295.2   295.5   296.29
 242.89  242.8   250.2   262.7   269.4      294.0   294.1   295.1   296.29
 243.6   242.39  248.1   260.29  267.79  …  292.4   293.1   294.5   295.79
 244.5   242.3   246.3   258.5   266.6      292.1   293.1   294.1   295.2
 245.7   242.3   244.89  257.29  266.2      292.2   292.9   293.5   295.1
 246.8   242.39  243.7   256.8   266.2      292.0   292.29  293.0   295.0
 247.7   242.5   242.6   256.39  265.9      291.4   292.2   293.2   294.5
 248.2   242.3   241.7   255.8   265.1   …  290.6   291.7   293.2   294.29
 248.0   241.8   240.8   255.2   264.0      290.7   291.4   292.79  294.7
 247.2   241.1   240.3   254.89  263.4      290.9   291.79  292.7   294.9
   ⋮                                     ⋱                          
 240.2   248.1   253.7   260.9   266.5      297.1   297.9   298.29  298.9
 237.89  247.39  256.6   264.2   269.1      297.6   298.1   298.2   299.5
 235.7   245.7   256.1   261.29  264.29     298.0   298.7   298.5   299.2
 233.89  243.1   252.7   254.0   254.8      298.4   299.0   299.0   298.7
 232.6   240.2   247.7   246.1   246.5   …  298.29  298.29  298.79  298.79
 232.0   237.3   242.6   241.2   244.2      297.7   297.6   298.0   298.7
 231.89  234.39  238.0   240.39  249.2      297.0   297.4   297.6   297.9
 232.2   232.0   234.3   242.39  258.0      296.6   297.0   297.7   297.9
 233.0   230.39  231.8   245.3   266.0      296.29  296.7   297.1   297.6
 234.3   230.3   231.2   247.89  270.5   …  295.6   296.29  296.4   297.0
 236.1   232.0   233.2   250.6   271.79     294.9   295.29  296.0   297.0
 238.7   235.7   238.2   254.2   271.79     294.79  295.0   295.6   296.79

;;; … 

[:, :, 2918] =
 243.49  249.09  262.69  273.49  273.89  …  292.99  294.79  296.79  298.19
 242.99  248.99  262.19  272.99  274.19     293.49  295.29  297.89  299.19
 242.09  248.59  261.69  272.49  274.29     295.99  297.49  298.29  298.79
 240.69  247.79  260.89  271.89  274.39     297.39  298.49  298.19  298.69
 239.19  246.49  259.79  271.09  274.49     297.09  297.99  298.59  299.29
 237.69  244.99  258.09  270.19  274.69  …  296.59  297.49  298.49  298.99
 236.59  243.59  255.99  269.09  274.99     295.69  297.29  298.19  298.59
 235.99  242.49  253.69  267.89  275.19     294.79  296.79  297.79  298.19
 235.99  241.89  251.29  266.29  274.99     294.59  296.29  297.69  298.29
 236.39  241.69  249.19  264.49  274.09     294.49  296.19  297.79  298.29
 237.09  241.79  247.39  262.29  272.39  …  293.99  295.69  297.39  297.49
 237.79  241.89  245.99  260.19  270.49     293.99  295.39  296.89  297.69
 238.39  241.89  245.09  258.39  268.79     294.19  295.29  295.99  297.49
   ⋮                                     ⋱                          
 254.49  255.29  258.79  263.99  267.29     297.99  298.59  298.59  299.19
 252.39  256.09  262.19  267.39  269.59     297.89  298.59  298.29  299.69
 249.99  254.99  261.69  263.69  262.69     297.09  298.29  297.59  298.79
 247.79  252.49  257.49  254.89  250.99     296.49  297.89  297.69  297.89
 245.89  249.09  251.39  245.59  241.79  …  295.89  296.99  297.39  297.79
 244.59  245.79  245.39  240.09  241.09     295.79  296.89  296.79  297.69
 243.89  243.09  241.09  240.09  249.19     295.59  296.79  296.79  297.29
 243.69  241.39  238.79  243.89  261.29     295.09  296.19  297.09  297.19
 243.89  240.59  238.39  248.99  271.29     295.09  295.69  296.39  297.09
 244.19  240.59  239.39  253.49  276.49  …  294.69  295.49  295.49  296.09
 244.49  241.29  241.69  257.39  277.89     294.69  295.39  295.49  295.79
 244.89  242.69  245.19  261.39  278.29     294.79  294.69  294.79  295.79

[:, :, 2919] =
 245.79  249.89  262.39  273.29  273.59  …  291.59  293.69  296.29  297.79
 244.79  249.29  261.79  272.89  273.99     291.69  293.89  297.19  298.39
 243.49  248.49  261.29  272.49  274.19     293.59  295.39  297.59  298.49
 241.89  247.29  260.59  272.09  274.49     295.89  297.19  297.89  298.59
 240.29  245.69  259.39  271.59  274.69     296.89  297.79  298.29  298.79
 238.89  243.99  257.69  270.99  274.99  …  296.79  297.49  298.09  298.69
 237.79  242.29  255.49  270.29  275.29     296.09  297.49  297.79  298.49
 237.19  240.89  252.99  269.29  275.59     294.99  297.29  297.79  297.99
 237.09  239.89  250.29  267.89  275.79     294.69  296.49  297.89  298.29
 237.29  239.29  247.59  265.89  275.59     294.69  295.99  297.69  298.19
 237.59  239.09  244.99  262.99  274.69  …  294.49  295.99  297.49  297.39
 237.89  238.99  242.59  259.49  272.99     294.39  295.79  296.99  297.69
 238.09  238.99  240.59  255.69  270.49     294.39  295.49  295.89  297.59
   ⋮                                     ⋱                          
 255.49  256.19  258.69  262.69  267.19     298.09  298.39  298.49  298.69
 253.19  256.59  262.09  265.99  269.59     297.49  297.89  297.89  299.09
 250.69  255.39  261.79  263.19  263.99     296.69  297.89  297.69  298.89
 248.19  252.79  257.99  255.69  253.99     296.19  297.59  297.69  297.79
 246.09  249.39  252.09  247.59  246.29  …  295.69  296.59  297.59  297.99
 244.39  245.89  246.29  242.79  245.99     295.69  296.39  296.99  297.99
 243.39  243.09  241.89  242.79  253.39     295.29  296.29  296.49  296.79
 242.89  241.39  239.59  246.29  264.19     294.59  295.49  296.79  296.89
 242.89  240.79  239.19  250.79  272.99     294.49  294.89  295.89  296.59
 243.29  241.29  240.49  254.89  277.29  …  294.49  295.09  295.29  295.69
 243.99  242.49  243.09  258.29  277.99     294.29  294.69  295.09  295.49
 244.79  244.29  246.89  261.79  277.59     294.49  294.29  294.39  295.19

[:, :, 2920] =
 245.09  249.89  262.99  272.19  271.19  …  292.89  293.79  296.09  297.69
 244.29  249.29  262.19  272.09  271.89     292.09  293.69  296.89  298.09
 243.29  248.39  261.39  271.99  272.59     292.99  295.09  297.19  298.09
 242.19  246.99  259.99  271.59  273.09     295.09  296.69  297.49  298.49
 241.09  245.09  257.79  270.69  273.09     296.09  297.29  298.19  298.89
 240.09  243.09  254.99  269.29  272.89  …  296.59  297.29  298.09  298.69
 239.39  241.09  251.99  267.69  272.99     296.49  297.39  297.79  298.39
 238.99  239.59  249.09  266.19  273.39     295.79  297.49  297.79  298.09
 238.89  238.59  246.59  264.79  273.99     295.59  297.19  297.69  298.09
 239.09  238.29  244.49  263.19  274.19     295.39  296.49  297.59  297.99
 239.39  238.39  242.59  260.89  273.69  …  294.89  296.09  297.39  297.49
 239.49  238.59  240.89  257.89  272.29     294.89  296.19  296.79  297.49
 239.49  238.89  239.29  254.19  270.09     294.59  296.09  296.39  297.49
   ⋮                                     ⋱                          
 256.09  255.49  257.29  262.39  266.69     298.59  299.39  299.99  299.89
 254.29  255.99  260.79  266.49  269.39     298.39  299.09  299.69  300.49
 252.49  255.19  261.29  264.99  264.79     297.49  299.09  298.99  299.99
 250.59  253.29  258.49  258.89  255.89     296.49  298.69  298.69  299.09
 248.69  250.29  253.39  251.69  248.59  …  296.09  297.59  298.69  299.29
 246.79  246.99  247.69  246.79  247.69     296.19  297.09  298.19  299.29
 245.09  243.79  242.89  245.69  253.69     295.79  296.69  297.39  297.89
 243.59  241.39  239.89  247.89  263.19     294.99  295.79  297.29  297.39
 242.39  239.99  238.99  251.59  271.49     294.59  295.19  296.49  297.19
 241.69  239.59  239.89  255.39  276.09  …  294.59  295.29  295.69  296.49
 241.49  240.29  242.59  258.99  277.39     294.19  295.09  295.69  296.19
 241.79  241.69  246.29  262.49  277.29     294.29  294.69  295.19  295.69
using WGLMakie
heatmap(lon, lat, temp[1, :, :])
using Statistics
mean(temp, dims=3)# On what dimensions did we apply the reduction? I can't tell by looking at this line.
53×25×1 Array{Float64, 3}:
[:, :, 1] =
 260.376  262.734  264.769  267.683  …  297.326  297.65   298.129  298.366
 260.183  262.794  264.327  267.287     296.869  296.953  297.937  298.386
 259.887  262.749  264.062  267.136     296.537  296.629  297.47   298.114
 259.483  262.538  263.88   267.073     296.626  296.862  297.259  298.053
 259.017  262.159  263.695  266.948     296.387  296.893  297.455  297.943
 258.572  261.691  263.494  266.764  …  295.934  296.305  297.113  297.607
 258.245  261.246  263.324  266.644     295.617  296.062  296.9    297.539
 258.101  260.933  263.247  266.7       295.086  295.847  296.685  297.432
 258.155  260.795  263.263  266.897     294.632  295.358  296.232  297.394
 258.362  260.802  263.307  267.06      294.26   295.113  296.205  297.233
 258.625  260.867  263.295  267.037  …  293.616  294.714  296.16   297.108
 258.839  260.896  263.173  266.841     293.276  294.478  295.847  297.375
 258.919  260.829  262.956  266.617     292.893  294.489  295.684  297.335
   ⋮                                 ⋱                             
 260.526  264.603  266.153  268.031     298.577  299.104  299.383  299.594
 258.087  263.368  267.242  270.214     298.446  298.789  298.897  299.656
 255.691  261.447  266.561  269.183     298.091  298.659  298.679  299.268
 253.582  258.987  263.948  265.031     297.81   298.463  298.744  298.672
 251.907  256.238  259.97   259.666  …  297.692  297.918  298.563  298.651
 250.731  253.527  255.641  255.585     297.603  297.736  298.097  298.693
 250.056  251.213  251.99   254.337     297.24   297.695  297.752  297.994
 249.86   249.644  249.745  255.839     296.826  297.258  297.796  297.891
 250.118  249.103  249.263  258.904     296.666  296.857  297.307  297.818
 250.816  249.756  250.608  262.341  …  296.421  296.811  296.86   297.338
 251.938  251.586  253.584  265.62      295.877  296.288  296.777  297.281
 253.438  254.359  257.716  268.701     295.71   295.816  296.444  297.305

Analysis with DimensionalData#

How readable is this code?

plot(ds.air[Ti=1])

Use dimension names instead of axis numbers

plot((mean(ds.air, dims=Ti)[Ti=1]))

Extracting data or “indexing”#

DimensionalData supports

  • label-based indexing using Selectors

  • position-based indexing using Integer

See the Documentation about Selectors for more.

Label-based indexing#

DimensionalData implements label based indexing where you can use the name of the dimension and also the labels for the entries in the dimension.

# here's what our dataset looks like
ds
╭────────────────────────╮
│ 53×25×2920 RasterStack │
├────────────────────────┴─────────────────────────────────────────────── dims ┐
  ↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  ↗ Ti Sampled{Dates.DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points
├────────────────────────────────────────────────────────────────────── layers ┤
  :air eltype: Float64 dims: X, Y, Ti size: 53×25×2920
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 5 entries:
  "references"  => "http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly…
  "platform"    => "Model"
  "title"       => "4x daily NMC reanalysis (1948)"
  "description" => "Data is from NMC initialized reanalysis\n(4x/day).  These a…
  "Conventions" => "COARDS"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0), Ti = (Dates.DateTime("2013-01-01T00:00:00"), Dates.DateTime("2014-12-31T18:00:00")))
  missingval: missing
  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
# We can extract the Time dimension
dims(ds, Ti)
Ti Sampled{Dates.DateTime} ForwardOrdered Irregular DimensionalData.Dimensions.Lookups.Points
wrapping: 2920-element Vector{Dates.DateTime}:
 2013-01-01T00:00:00
 2013-01-01T06:00:00
 2013-01-01T12:00:00
 2013-01-01T18:00:00
 2013-01-02T00:00:00
 2013-01-02T06:00:00
 2013-01-02T12:00:00
 2013-01-02T18:00:00
 2013-01-03T00:00:00
 2013-01-03T06:00:00
 2013-01-03T12:00:00
 2013-01-03T18:00:00
 2013-01-04T00:00:00
 ⋮
 2014-12-29T00:00:00
 2014-12-29T06:00:00
 2014-12-29T12:00:00
 2014-12-29T18:00:00
 2014-12-30T00:00:00
 2014-12-30T06:00:00
 2014-12-30T12:00:00
 2014-12-30T18:00:00
 2014-12-31T00:00:00
 2014-12-31T06:00:00
 2014-12-31T12:00:00
 2014-12-31T18:00:00
# pull out data for all of 2013-May
ds[Ti=Where(x->yearmonth(x) == (2013, 5))]
╭───────────────────────╮
│ 53×25×124 RasterStack │
├───────────────────────┴──────────────────────────────────────────────── dims ┐
  ↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  ↗ Ti Sampled{Dates.DateTime} [2013-05-01T00:00:00, …, 2013-05-31T18:00:00] ForwardOrdered Irregular Points
├────────────────────────────────────────────────────────────────────── layers ┤
  :air eltype: Float64 dims: X, Y, Ti size: 53×25×124
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 5 entries:
  "references"  => "http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly…
  "platform"    => "Model"
  "title"       => "4x daily NMC reanalysis (1948)"
  "description" => "Data is from NMC initialized reanalysis\n(4x/day).  These a…
  "Conventions" => "COARDS"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0), Ti = (Dates.DateTime("2013-05-01T00:00:00"), Dates.DateTime("2013-05-31T18:00:00")))
  missingval: missing
  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
using Dates
# demonstrate slicing, extract all time slices between to given dates
ds[Ti=Date(2013,5,1)..Date(2013,8,1)]
╭───────────────────────╮
│ 53×25×369 RasterStack │
├───────────────────────┴──────────────────────────────────────────────── dims ┐
  ↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  ↗ Ti Sampled{DateTime} [2013-05-01T00:00:00, …, 2013-08-01T00:00:00] ForwardOrdered Irregular Points
├────────────────────────────────────────────────────────────────────── layers ┤
  :air eltype: Float64 dims: X, Y, Ti size: 53×25×369
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 5 entries:
  "references"  => "http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly…
  "platform"    => "Model"
  "title"       => "4x daily NMC reanalysis (1948)"
  "description" => "Data is from NMC initialized reanalysis\n(4x/day).  These a…
  "Conventions" => "COARDS"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0), Ti = (DateTime("2013-05-01T00:00:00"), DateTime("2013-08-01T00:00:00")))
  missingval: missing
  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
# demonstrate "nearest" indexing
ds[X=Near(240.2)]
╭─────────────────────╮
│ 25×2920 RasterStack │
├─────────────────────┴────────────────────────────────────────────────── dims ┐
  ↓ Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  → Ti Sampled{DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points
├────────────────────────────────────────────────────────────────────── layers ┤
  :air eltype: Float64 dims: Y, Ti size: 25×2920
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 5 entries:
  "references"  => "http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly…
  "platform"    => "Model"
  "title"       => "4x daily NMC reanalysis (1948)"
  "description" => "Data is from NMC initialized reanalysis\n(4x/day).  These a…
  "Conventions" => "COARDS"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(Y = (15.0f0, 75.0f0), Ti = (DateTime("2013-01-01T00:00:00"), DateTime("2014-12-31T18:00:00")))
  missingval: missing
  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
# "nearest indexing at multiple points"
ds[X=Near([240.125, 234]), Y=Near([40.1, 50.1])]
╭──────────────────────╮
│ 2×2×2920 RasterStack │
├──────────────────────┴───────────────────────────────────────────────── dims ┐
  ↓ X  Mapped{Float32} [240.0f0, 235.0f0] ForwardOrdered Irregular Points,
  → Y  Mapped{Float32} [40.0f0, 50.0f0] ReverseOrdered Irregular Points,
  ↗ Ti Sampled{DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points
├────────────────────────────────────────────────────────────────────── layers ┤
  :air eltype: Float64 dims: X, Y, Ti size: 2×2×2920
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 5 entries:
  "references"  => "http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly…
  "platform"    => "Model"
  "title"       => "4x daily NMC reanalysis (1948)"
  "description" => "Data is from NMC initialized reanalysis\n(4x/day).  These a…
  "Conventions" => "COARDS"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (240.0f0, 235.0f0), Y = (50.0f0, 40.0f0), Ti = (DateTime("2013-01-01T00:00:00"), DateTime("2014-12-31T18:00:00")))
  missingval: missing
  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘

These selectors can be mixed for different dimensions. So that we could have a Where selection for time and a nearest neighbor selection in space.

Position-based indexing#

This is similar to usual array indexing array[1, 2, 3] but with the power of named dimensions!

# pull out time index 0, lat index 2, and lon index 3
ds.air[Ti=1, Y=2, X=3]  #  much better than ds.air[3, 2, 1]
244.70000000000002
# demonstrate slicing
ds.air[X=1:10]
╭──────────────────────────────────╮
│ 10×25×2920 Raster{Float64,3} air │
├──────────────────────────────────┴───────────────────────────────────── dims ┐
  ↓ X  Mapped{Float32} [200.0, 202.5, …, 220.0, 222.5] ForwardOrdered Regular Points,
  → Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  ↗ Ti Sampled{DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 13 entries:
  "long_name"    => "4xDaily Air temperature at sigma level 995"
  "scale_factor" => 0.01
  "GRIB_name"    => "TMP"
  "precision"    => 2
  "var_desc"     => "Air temperature"
  "actual_range" => Float32[185.16, 322.1]
  "statistic"    => "Individual Obs"
  "GRIB_id"      => 11
  "myattrs"      => "Mine"
  "dataset"      => "NMC Reanalysis"
  "units"        => "degK"
  "parent_stat"  => "Other"
  "level_desc"   => "Surface"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 222.5f0), Y = (15.0f0, 75.0f0), Ti = (DateTime("2013-01-01T00:00:00"), DateTime("2014-12-31T18:00:00")))

  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
[:, :, 1]
 ⋮      ⋱  

Concepts for computation#

Consider calculating the mean air temperature per unit surface area for this dataset. Because latitude and longitude correspond to spherical coordinates for Earth’s surface, each 2.5x2.5 degree grid cell actually has a different surface area as you move away from the equator! This is because latitudinal length is fixed (\( \delta Lat = R \delta \phi \)), but longitudinal length varies with latitude (\( \delta Lon = R \delta \lambda \cos(\phi) \))

So the area element for lat-lon coordinates is

\[ \delta A = R^2 \delta\phi \, \delta\lambda \cos(\phi) \]

where \(\phi\) is latitude, \(\delta \phi\) is the spacing of the points in latitude, \(\delta \lambda\) is the spacing of the points in longitude, and \(R\) is Earth’s radius. (In this formula, \(\phi\) and \(\lambda\) are measured in radians)

lon
53-element Vector{Float32}:
 200.0
 202.5
 205.0
 207.5
 210.0
 212.5
 215.0
 217.5
 220.0
 222.5
 225.0
 227.5
 230.0
   ⋮
 302.5
 305.0
 307.5
 310.0
 312.5
 315.0
 317.5
 320.0
 322.5
 325.0
 327.5
 330.0
# Earth's average radius in meters
R = 6.371e6

# Coordinate spacing for this dataset is 2.5 x 2.5 degrees
 = deg2rad(2.5)
 = deg2rad(2.5)

dlat = fill(R * , dims(ds,X))
╭──────────────────────────────╮
│ 53-element Raster{Float64,1} │
├──────────────────────────────┴───────────────────────────────────────── dims ┐
  ↓ X Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0),)

  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
 200.0  2.77987e5
 202.5  2.77987e5
 205.0  2.77987e5
 207.5  2.77987e5
 210.0  2.77987e5
 212.5  2.77987e5
 215.0  2.77987e5
 217.5  2.77987e5
 220.0  2.77987e5
   ⋮    
 312.5  2.77987e5
 315.0  2.77987e5
 317.5  2.77987e5
 320.0  2.77987e5
 322.5  2.77987e5
 325.0  2.77987e5
 327.5  2.77987e5
 330.0  2.77987e5
dlonval = R .*  .* cos.(deg2rad.(dims(ds.air, Y)))
dlon = DimArray(reshape(dlonval, (1, length(dlonval))), (X,dims(ds, Y)))
╭──────────────────────────╮
│ 1×25 DimArray{Float64,2} │
├──────────────────────────┴───────────────────────────────────────────── dims ┐
  ↓ X,
  → Y Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points
└──────────────────────────────────────────────────────────────────────────────┘
    75.0     72.5     70.0  67.520.0        17.5        15.0
 71948.4  83592.4  95077.3   1.06381e5      2.61223e5   2.65121e5   2.68515e5
cell_area = dlat .* dlon
╭─────────────────────────╮
│ 53×25 Raster{Float64,2} │
├─────────────────────────┴────────────────────────────────────────────── dims ┐
  ↓ X Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0))

  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
      75.0         72.5         70.017.5         15.0
 200.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 202.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 205.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 207.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 210.0   2.00007e10   2.32376e10   2.64303e10  …   7.37003e10   7.46438e10
 212.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 215.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
   ⋮                                           ⋱                ⋮
 312.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 315.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 317.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 320.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 322.5   2.00007e10   2.32376e10   2.64303e10  …   7.37003e10   7.46438e10
 325.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 327.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 330.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10

You can apply functions like cos and deg2rad elementwise on array types by using broadcasting in Julia.

Broadcasting: expanding data#

In DimensionalData the broadcast does not automatically expand the data therefore we have to reshape the underlying data into a row vector to get a 2D array from the two 1D vectors.

cell_area = dlon .* dlat
cell_area
╭───────────────────────────╮
│ 53×25 DimArray{Float64,2} │
├───────────────────────────┴──────────────────────────────────────────── dims ┐
  ↓ X Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points
└──────────────────────────────────────────────────────────────────────────────┘
      75.0         72.5         70.017.5         15.0
 200.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 202.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 205.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 207.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 210.0   2.00007e10   2.32376e10   2.64303e10  …   7.37003e10   7.46438e10
 212.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 215.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
   ⋮                                           ⋱                ⋮
 312.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 315.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 317.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 320.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 322.5   2.00007e10   2.32376e10   2.64303e10  …   7.37003e10   7.46438e10
 325.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 327.5   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10
 330.0   2.00007e10   2.32376e10   2.64303e10      7.37003e10   7.46438e10

Alignment: putting data on the same grid#

When broadcasting arithmetic operations DimensionalData automatically “aligns” i.e. puts the data on the same grid. In this case cell_area and ds.air are at the same lat, lon points we end up with a result with the same shape (25x53):

ds.air[Ti=1] ./ cell_area
╭─────────────────────────╮
│ 53×25 Raster{Float64,2} │
├─────────────────────────┴────────────────────────────────────────────── dims ┐
  ↓ X Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 13 entries:
  "long_name"    => "4xDaily Air temperature at sigma level 995"
  "scale_factor" => 0.01
  "GRIB_name"    => "TMP"
  "precision"    => 2
  "var_desc"     => "Air temperature"
  "actual_range" => Float32[185.16, 322.1]
  "statistic"    => "Individual Obs"
  "GRIB_id"      => 11
  "myattrs"      => "Mine"
  "dataset"      => "NMC Reanalysis"
  "units"        => "degK"
  "parent_stat"  => "Other"
  "level_desc"   => "Surface"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0))

  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
 ⋮      ⋱  

DimensionalData only compares the dimension name and would currently broadcast two arrays with the same size along each dimension together.

# make a copy of cell_area
# then add 1e-5 degrees to latitude
cell_area_bad = similar(cell_area)
╭───────────────────────────╮
│ 53×25 DimArray{Float64,2} │
├───────────────────────────┴──────────────────────────────────────────── dims ┐
  ↓ X Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points
└──────────────────────────────────────────────────────────────────────────────┘
      75.0           72.517.5            15.0
 200.0   1.36424e-315   0.0                1.49669e-316    6.93638e-310
 202.5   1.50155e-315   1.50155e-315       6.93638e-310    1.51745e-316
 205.0   1.6976e-313    1.50155e-315       1.46636e-316  NaN
 207.5   6.93638e-310   4.24399e-314       6.93638e-310    4.0e-323
 210.0   6.93638e-310   0.0           …    1.46732e-316  NaN
 212.5   0.0            0.0                6.93638e-310    1.08072e-315
 215.0   1.50155e-315   1.50155e-315       1.46648e-316    6.93638e-310
   ⋮                                  ⋱                    ⋮
 312.5   1.50155e-315   0.0                6.93638e-310    1.5175e-316
 315.0   1.6976e-313    1.50155e-315       1.5156e-316     6.93638e-310
 317.5   6.93638e-310   4.24399e-314     NaN               1.46633e-316
 320.0   1.50155e-315   0.0                2.16183e-315    6.93638e-310
 322.5   8.48798e-314   2.3342e-313   …    6.93638e-310    1.46591e-316
 325.0   0.0            2.18585e-315       1.51958e-316    6.93638e-310
 327.5   0.0            6.57819e-313       6.93638e-310    0.0
 330.0   0.0            1.52696e-315       1.46604e-316    6.93638e-310
set(cell_area_bad, set(dims(cell_area_bad, X), 1:53))
╭───────────────────────────╮
│ 53×25 DimArray{Float64,2} │
├───────────────────────────┴──────────────────────────────────────────── dims ┐
  ↓ X Mapped{Int64} 1:53 ForwardOrdered Regular Points,
  → Y Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points
└──────────────────────────────────────────────────────────────────────────────┘
     75.0           72.517.5            15.0
  1     1.36424e-315   0.0                1.49669e-316    6.93638e-310
  2     1.50155e-315   1.50155e-315       6.93638e-310    1.51745e-316
  3     1.6976e-313    1.50155e-315       1.46636e-316  NaN
  4     6.93638e-310   4.24399e-314       6.93638e-310    4.0e-323
  5     6.93638e-310   0.0           …    1.46732e-316  NaN
  6     0.0            0.0                6.93638e-310    1.08072e-315
  7     1.50155e-315   1.50155e-315       1.46648e-316    6.93638e-310
  ⋮                                  ⋱                    ⋮
 46     1.50155e-315   0.0                6.93638e-310    1.5175e-316
 47     1.6976e-313    1.50155e-315       1.5156e-316     6.93638e-310
 48     6.93638e-310   4.24399e-314     NaN               1.46633e-316
 49     1.50155e-315   0.0                2.16183e-315    6.93638e-310
 50     8.48798e-314   2.3342e-313   …    6.93638e-310    1.46591e-316
 51     0.0            2.18585e-315       1.51958e-316    6.93638e-310
 52     0.0            6.57819e-313       6.93638e-310    0.0
 53     0.0            1.52696e-315       1.46604e-316    6.93638e-310
cell_area_bad .* ds.air[Ti=1]
╭───────────────────────────╮
│ 53×25 DimArray{Float64,2} │
├───────────────────────────┴──────────────────────────────────────────── dims ┐
  ↓ X Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points
└──────────────────────────────────────────────────────────────────────────────┘
      75.0           72.517.5            15.0
 200.0   3.29055e-313   0.0                4.4287e-314     2.05518e-307
 202.5   3.64125e-313   3.67128e-313       2.05455e-307    4.50365e-314
 205.0   4.13365e-311   3.67429e-313       4.35201e-314  NaN
 207.5   1.69248e-307   1.03638e-311       2.05664e-307    1.174e-320
 210.0   1.69317e-307   0.0           …    4.34474e-314  NaN
 212.5   0.0            0.0                2.04692e-307    3.20327e-313
 215.0   3.65777e-313   3.62924e-313       4.32025e-314    2.05317e-307
   ⋮                                  ⋱                    ⋮
 312.5   3.41302e-313   0.0                2.0712e-307     4.53278e-314
 315.0   3.85354e-311   3.52864e-313       4.51498e-314    2.0712e-307
 317.5   1.57803e-307   9.89699e-312     NaN               4.36965e-314
 320.0   3.43554e-313   0.0                6.41847e-313    2.06558e-307
 322.5   1.95733e-311   5.41066e-311  …    2.05518e-307    4.36255e-314
 325.0   0.0            5.08866e-313       4.49643e-314    2.05941e-307
 327.5   0.0            1.54785e-310       2.05247e-307    0.0
 330.0   0.0            3.65401e-313       4.32775e-314    2.05733e-307

This results in the same values but the dimensions are different.


High level computation#

(groupby, resample, rolling, coarsen, weighted)

Xarray has some very useful high level objects that let you do common computations:

  1. groupby : Bin data in to groups and reduce

  2. resample : Groupby specialized for time axes. Either downsample or upsample your data.

  3. rolling : Operate on rolling windows of your data e.g. running mean

  4. coarsen : Downsample your data

  5. weighted : Weight your data before reducing

Below we quickly demonstrate these patterns. See the user guide links above and the tutorial for more.

groupby#

# here's ds
ds
╭────────────────────────╮
│ 53×25×2920 RasterStack │
├────────────────────────┴─────────────────────────────────────────────── dims ┐
  ↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  ↗ Ti Sampled{DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points
├────────────────────────────────────────────────────────────────────── layers ┤
  :air eltype: Float64 dims: X, Y, Ti size: 53×25×2920
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 5 entries:
  "references"  => "http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly…
  "platform"    => "Model"
  "title"       => "4x daily NMC reanalysis (1948)"
  "description" => "Data is from NMC initialized reanalysis\n(4x/day).  These a…
  "Conventions" => "COARDS"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0), Ti = (DateTime("2013-01-01T00:00:00"), DateTime("2014-12-31T18:00:00")))
  missingval: missing
  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
groups = groupby(ds, Ti=>seasons())
╭──────────────────────────────────────────────────────────────────────────────╮
│ 4-element DimGroupByArray{RasterStack{(:air,), @NamedTuple{air::Float64}, 2, @NamedTuple{air::SubArray{Float64, 2, Array{Float64, 3}, Tuple{Base.Slice{Base.OneTo{Int64}}, Base.Slice{Base.OneTo{Int64}}, Int64}, true}}, Tuple{X{Mapped{Float32, Vector{Float32}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, X{Colon}}}, Y{Mapped{Float32, Vector{Float32}, DimensionalData.Dimensions.Lookups.ReverseOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, Y{Colon}}}}, Tuple{Ti{DimensionalData.Dimensions.Lookups.Sampled{DateTime, SubArray{DateTime, 1, Vector{DateTime}, Tuple{UnitRange{Int64}}, true}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Irregular{Tuple{DateTime, DateTime}}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}}}}, @NamedTuple{air::Tuple{X{Colon}, Y{Colon}}}, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}, @NamedTuple{air::DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}}, Missing},1} groupby │
├──────────────────────────────────────────────────────────────────────── dims ┤
  ↓ Ti Categorical{Symbol} [:Dec_Jan_Feb, :Mar_Apr_May, :Jun_Jul_Aug, :Sep_Oct_Nov] Unordered
├──────────────────────────────────────────────────────────────────── metadata ┤
  Dict{Symbol, Any} with 1 entry:
  :groupby => :Ti=>CyclicBins(month; cycle=12, step=3, start=12)…
├────────────────────────────────────────────────────────────────── group dims ┤
  ↓ X, → Y, ↗ Ti
└──────────────────────────────────────────────────────────────────────────────┘
 :Dec_Jan_Feb  53×25×720 RasterStack
 :Mar_Apr_May  53×25×736 RasterStack
 :Jun_Jul_Aug  53×25×736 RasterStack
 :Sep_Oct_Nov  53×25×728 RasterStack
# make a seasonal mean
seasonal_mean = mean.(groups, dims=Ti)
seasonal_mean
╭──────────────────────────────────────────────────────────────────────────────╮
│ 4-element DimArray{RasterStack{(:air,), @NamedTuple{air::Float64}, 3, @NamedTuple{air::Array{Float64, 3}}, Tuple{X{Mapped{Float32, Vector{Float32}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, X{Colon}}}, Y{Mapped{Float32, Vector{Float32}, DimensionalData.Dimensions.Lookups.ReverseOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, Y{Colon}}}, Ti{DimensionalData.Dimensions.Lookups.Sampled{DateTime, Vector{DateTime}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Irregular{Tuple{DateTime, DateTime}}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}}}}, Tuple{}, @NamedTuple{air::Tuple{X{Colon}, Y{Colon}, Ti{Colon}}}, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}, @NamedTuple{air::DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}}, Nothing},1} │
├──────────────────────────────────────────────────────────────────────── dims ┤
  ↓ Ti Categorical{Symbol} [:Dec_Jan_Feb, :Mar_Apr_May, :Jun_Jul_Aug, :Sep_Oct_Nov] Unordered
├──────────────────────────────────────────────────────────────────── metadata ┤
  Dict{Symbol, Any} with 1 entry:
  :groupby => :Ti=>CyclicBins(month; cycle=12, step=3, start=12)…
└──────────────────────────────────────────────────────────────────────────────┘
 :Dec_Jan_Feb  …  RasterStack{(:air,), @NamedTuple{air::Float64}, 3, @NamedTuple{air::Array{Float64, 3}}, Tuple{X{Mapped{Float32, Vector{Float32}, ForwardOrdered, Regular{Float64}, Points, Metadata{NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, X{Colon}}}, Y{Mapped{Float32, Vector{Float32}, ReverseOrdered, Regular{Float64}, Points, Metadata{NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, Y{Colon}}}, Ti{Sampled{DateTime, Vector{DateTime}, ForwardOrdered, Irregular{Tuple{DateTime, DateTime}}, Points, Metadata{NCDsource, Dict{String, Any}}}}}, Tuple{}, @NamedTuple{air::Tuple{X{Colon}, Y{Colon}, Ti{Colon}}}, Metadata{NCDsource, Dict{String, Any}}, @NamedTuple{air::Metadata{NCDsource, Dict{String, Any}}}, Nothing}((air = [247.01 248.83 … 296.938 297.447; 246.955 248.982 … 296.835 297.489; … ; 242.694 242.246 … 295.421 296.137; 244.233 245.321 … 294.959 296.056;;;],), (↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
→ Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
↗ Ti Sampled{DateTime} [DateTime("2013-12-31T21:00:00")] ForwardOrdered Irregular Points), (), (air = (↓ X, → Y, ↗ Ti),), Metadata{NCDsource, Dict{String, Any}}(Dict{String, Any}("references"=>"http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanalysis.html", "platform"=>"Model", "title"=>"4x daily NMC reanalysis (1948)", "description"=>"Data is from NMC initialized reanalysis\n(4x/day).  These are the 0.9950 sigma level values.", "Conventions"=>"COARDS")), (air = Metadata{NCDsource, Dict{String, Any}}(Dict{String, Any}("long_name"=>"4xDaily Air temperature at sigma level 995", "scale_factor"=>0.01, "GRIB_name"=>"TMP", "precision"=>2, "var_desc"=>"Air temperature", "actual_range"=>Float32[185.16, 322.1], "statistic"=>"Individual Obs", "GRIB_id"=>11, "myattrs"=>"Mine", "dataset"=>"NMC Reanalysis"…)),), nothing)
 :Mar_Apr_May     RasterStack{(:air,), @NamedTuple{air::Float64}, 3, @NamedTuple{air::Array{Float64, 3}}, Tuple{X{Mapped{Float32, Vector{Float32}, ForwardOrdered, Regular{Float64}, Points, Metadata{NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, X{Colon}}}, Y{Mapped{Float32, Vector{Float32}, ReverseOrdered, Regular{Float64}, Points, Metadata{NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, Y{Colon}}}, Ti{Sampled{DateTime, Vector{DateTime}, ForwardOrdered, Irregular{Tuple{DateTime, DateTime}}, Points, Metadata{NCDsource, Dict{String, Any}}}}}, Tuple{}, @NamedTuple{air::Tuple{X{Colon}, Y{Colon}, Ti{Colon}}}, Metadata{NCDsource, Dict{String, Any}}, @NamedTuple{air::Metadata{NCDsource, Dict{String, Any}}}, Nothing}((air = [258.864 260.276 … 297.437 297.893; 258.692 260.374 … 297.301 297.9; … ; 249.096 249.081 … 295.314 295.746; 250.379 251.569 … 294.914 295.722;;;],), (↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
→ Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
↗ Ti Sampled{DateTime} [DateTime("2013-10-15T09:00:00")] ForwardOrdered Irregular Points), (), (air = (↓ X, → Y, ↗ Ti),), Metadata{NCDsource, Dict{String, Any}}(Dict{String, Any}("references"=>"http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanalysis.html", "platform"=>"Model", "title"=>"4x daily NMC reanalysis (1948)", "description"=>"Data is from NMC initialized reanalysis\n(4x/day).  These are the 0.9950 sigma level values.", "Conventions"=>"COARDS")), (air = Metadata{NCDsource, Dict{String, Any}}(Dict{String, Any}("long_name"=>"4xDaily Air temperature at sigma level 995", "scale_factor"=>0.01, "GRIB_name"=>"TMP", "precision"=>2, "var_desc"=>"Air temperature", "actual_range"=>Float32[185.16, 322.1], "statistic"=>"Individual Obs", "GRIB_id"=>11, "myattrs"=>"Mine", "dataset"=>"NMC Reanalysis"…)),), nothing)
 :Jun_Jul_Aug     RasterStack{(:air,), @NamedTuple{air::Float64}, 3, @NamedTuple{air::Array{Float64, 3}}, Tuple{X{Mapped{Float32, Vector{Float32}, ForwardOrdered, Regular{Float64}, Points, Metadata{NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, X{Colon}}}, Y{Mapped{Float32, Vector{Float32}, ReverseOrdered, Regular{Float64}, Points, Metadata{NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, Y{Colon}}}, Ti{Sampled{DateTime, Vector{DateTime}, ForwardOrdered, Irregular{Tuple{DateTime, DateTime}}, Points, Metadata{NCDsource, Dict{String, Any}}}}}, Tuple{}, @NamedTuple{air::Tuple{X{Colon}, Y{Colon}, Ti{Colon}}}, Metadata{NCDsource, Dict{String, Any}}, @NamedTuple{air::Metadata{NCDsource, Dict{String, Any}}}, Nothing}((air = [273.39 274.331 … 298.916 298.903; 273.202 274.489 … 298.577 298.882; … ; 266.199 265.93 … 297.437 297.869; 267.946 268.566 … 297.175 297.965;;;],), (↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
→ Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
↗ Ti Sampled{DateTime} [DateTime("2014-01-15T09:00:00")] ForwardOrdered Irregular Points), (), (air = (↓ X, → Y, ↗ Ti),), Metadata{NCDsource, Dict{String, Any}}(Dict{String, Any}("references"=>"http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanalysis.html", "platform"=>"Model", "title"=>"4x daily NMC reanalysis (1948)", "description"=>"Data is from NMC initialized reanalysis\n(4x/day).  These are the 0.9950 sigma level values.", "Conventions"=>"COARDS")), (air = Metadata{NCDsource, Dict{String, Any}}(Dict{String, Any}("long_name"=>"4xDaily Air temperature at sigma level 995", "scale_factor"=>0.01, "GRIB_name"=>"TMP", "precision"=>2, "var_desc"=>"Air temperature", "actual_range"=>Float32[185.16, 322.1], "statistic"=>"Individual Obs", "GRIB_id"=>11, "myattrs"=>"Mine", "dataset"=>"NMC Reanalysis"…)),), nothing)
 :Sep_Oct_Nov     RasterStack{(:air,), @NamedTuple{air::Float64}, 3, @NamedTuple{air::Array{Float64, 3}}, Tuple{X{Mapped{Float32, Vector{Float32}, ForwardOrdered, Regular{Float64}, Points, Metadata{NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, X{Colon}}}, Y{Mapped{Float32, Vector{Float32}, ReverseOrdered, Regular{Float64}, Points, Metadata{NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, Y{Colon}}}, Ti{Sampled{DateTime, Vector{DateTime}, ForwardOrdered, Irregular{Tuple{DateTime, DateTime}}, Points, Metadata{NCDsource, Dict{String, Any}}}}}, Tuple{}, @NamedTuple{air::Tuple{X{Colon}, Y{Colon}, Ti{Colon}}}, Metadata{NCDsource, Dict{String, Any}}, @NamedTuple{air::Metadata{NCDsource, Dict{String, Any}}}, Nothing}((air = [261.969 267.247 … 299.211 299.212; 261.61 267.077 … 299.023 299.262; … ; 249.537 248.854 … 298.93 299.371; 250.967 251.757 … 298.721 299.474;;;],), (↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
→ Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
↗ Ti Sampled{DateTime} [DateTime("2014-04-16T21:00:00")] ForwardOrdered Irregular Points), (), (air = (↓ X, → Y, ↗ Ti),), Metadata{NCDsource, Dict{String, Any}}(Dict{String, Any}("references"=>"http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanalysis.html", "platform"=>"Model", "title"=>"4x daily NMC reanalysis (1948)", "description"=>"Data is from NMC initialized reanalysis\n(4x/day).  These are the 0.9950 sigma level values.", "Conventions"=>"COARDS")), (air = Metadata{NCDsource, Dict{String, Any}}(Dict{String, Any}("long_name"=>"4xDaily Air temperature at sigma level 995", "scale_factor"=>0.01, "GRIB_name"=>"TMP", "precision"=>2, "var_desc"=>"Air temperature", "actual_range"=>Float32[185.16, 322.1], "statistic"=>"Individual Obs", "GRIB_id"=>11, "myattrs"=>"Mine", "dataset"=>"NMC Reanalysis"…)),), nothing)

resample#

# Reduce the time dimension to monthly means 
monthlymeans = dropdims.(mean.(groupby(ds.air, Ti=>yearmonth), dims=Ti), dims=Ti)
╭──────────────────────────────────────────────────────────────────────────────╮
│ 24-element DimArray{Raster{Float64, 2, Tuple{X{Mapped{Float32, Vector{Float32}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, X{Colon}}}, Y{Mapped{Float32, Vector{Float32}, DimensionalData.Dimensions.Lookups.ReverseOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, Y{Colon}}}}, Tuple{Ti{DimensionalData.Dimensions.Lookups.Sampled{DateTime, Vector{DateTime}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Irregular{Tuple{DateTime, DateTime}}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}}}}, Matrix{Float64}, Symbol, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}, Nothing},1} │
├──────────────────────────────────────────────────────────────────────── dims ┤
  ↓ Ti Sampled{Tuple{Int64, Int64}} [(2013, 1), (2013, 2), …, (2014, 11), (2014, 12)] ForwardOrdered Irregular Points
├──────────────────────────────────────────────────────────────────── metadata ┤
  Dict{Symbol, Any} with 1 entry:
  :groupby => :Ti=>yearmonth
└──────────────────────────────────────────────────────────────────────────────┘
 (2013, 1)   …  [244.467 247.073 … 296.47 297.053; 244.664 247.022 … 296.317 297.042; … ; 243.406 242.045 … 295.341 296.097; 244.676 244.707 … 294.866 296.039]
 (2013, 2)      [240.734 241.933 … 296.045 296.491; 240.701 242.069 … 295.693 296.344; … ; 242.72 242.325 … 294.972 295.651; 243.945 244.728 … 294.454 295.532]
 (2013, 3)      [248.276 250.656 … 296.351 297.129; 247.73 250.291 … 296.26 297.135; … ; 244.767 244.84 … 295.492 296.061; 245.82 246.77 … 295.202 295.962]
 (2013, 4)      [257.663 257.547 … 297.143 297.582; 257.427 257.638 … 297.031 297.631; … ; 247.538 247.999 … 295.369 295.852; 248.714 250.155 … 295.026 295.899]
 (2013, 5)      [266.618 267.72 … 298.258 298.46; 266.764 268.126 … 298.051 298.357; … ; 255.749 255.387 … 296.974 297.146; 257.301 258.284 … 296.403 297.059]
 (2013, 6)   …  [273.854 274.752 … 298.39 298.502; 273.642 274.865 … 297.985 298.349; … ; 266.193 265.568 … 296.57 296.939; 268.082 268.486 … 296.271 296.944]
 (2013, 7)      [275.639 276.828 … 298.741 298.798; 275.336 276.918 … 298.352 298.785; … ; 267.558 267.721 … 297.573 298.053; 269.246 270.199 … 297.44 298.257]
 ⋮           ⋱  
 (2014, 7)      [273.369 273.838 … 299.233 299.196; 273.18 274.007 … 298.937 299.161; … ; 268.579 267.94 … 297.112 297.44; 270.077 270.048 … 296.771 297.525]
 (2014, 8)      [272.422 273.695 … 299.558 299.471; 272.357 273.875 … 299.314 299.556; … ; 264.575 264.75 … 298.208 298.65; 266.4 267.489 … 297.892 298.75]
 (2014, 9)   …  [271.723 274.044 … 299.979 299.926; 271.532 274.246 … 299.823 299.949; … ; 254.788 255.056 … 299.26 299.606; 256.205 258.14 … 299.166 299.805]
 (2014, 10)     [261.715 268.75 … 300.068 299.885; 260.801 268.422 … 299.856 299.922; … ; 249.509 248.945 … 299.323 299.642; 251.204 252.24 … 299.062 299.751]
 (2014, 11)     [255.22 259.621 … 298.965 299.173; 254.954 258.669 … 298.812 299.218; … ; 246.959 246.869 … 298.221 298.742; 248.031 249.4 … 297.886 298.78]
 (2014, 12)     [246.802 247.73 … 297.446 298.047; 246.889 248.301 … 297.436 298.226; … ; 241.082 240.322 … 297.058 297.723; 242.282 242.97 … 296.729 297.71]

weighted#

# weight by cell_area and take mean over (time, lon)
#ds.weighted(cell_area).mean(["lon", "time"]).air.plot(y="lat");
weightedmean = dropdims(mean(ds.air, dims=(X, Ti)), dims=(X,Ti))
weightedmean
╭──────────────────────────────────╮
│ 25-element Raster{Float64,1} air │
├──────────────────────────────────┴───────────────────────────────────── dims ┐
  ↓ Y Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 13 entries:
  "long_name"    => "4xDaily Air temperature at sigma level 995"
  "scale_factor" => 0.01
  "GRIB_name"    => "TMP"
  "precision"    => 2
  "var_desc"     => "Air temperature"
  "actual_range" => Float32[185.16, 322.1]
  "statistic"    => "Individual Obs"
  "GRIB_id"      => 11
  "myattrs"      => "Mine"
  "dataset"      => "NMC Reanalysis"
  "units"        => "degK"
  "parent_stat"  => "Other"
  "level_desc"   => "Surface"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(Y = (15.0f0, 75.0f0),)

  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
 75.0  257.822
  ⋮    
y = dims(weightedmean, Y)
@show y
y = Y{Mapped{Float32, Vector{Float32}, DimensionalData.Dimensions.Lookups.ReverseOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.Metadata{Rasters.NCDsource, Dict{String, Any}}, EPSG{1}, EPSG{1}, Y{Colon}}}(Float32[75.0, 72.5, 70.0, 67.5, 65.0, 62.5, 60.0, 57.5, 55.0, 52.5, 50.0, 47.5, 45.0, 42.5, 40.0, 37.5, 35.0, 32.5, 30.0, 27.5, 25.0, 22.5, 20.0, 17.5, 15.0])
Y Mapped{Float32} ReverseOrdered Regular DimensionalData.Dimensions.Lookups.Points
wrapping: 25-element Vector{Float32}:
 75.0
 72.5
 70.0
 67.5
 65.0
 62.5
 60.0
 57.5
 55.0
 52.5
 50.0
 47.5
 45.0
 42.5
 40.0
 37.5
 35.0
 32.5
 30.0
 27.5
 25.0
 22.5
 20.0
 17.5
 15.0
nx = X(reverse(Float32[75.0, 72.5, 70.0, 67.5, 65.0, 62.5, 60.0, 57.5, 55.0, 52.5, 50.0, 47.5, 45.0, 42.5, 40.0, 37.5, 35.0, 32.5, 30.0, 27.5, 25.0, 22.5, 20.0, 17.5, 15.0]))
ny = Y(reverse(Float32[75.0, 72.5, 70.0, 67.5, 65.0, 62.5, 60.0, 57.5, 55.0, 52.5, 50.0, 47.5, 45.0, 42.5, 40.0, 37.5, 35.0, 32.5, 30.0, 27.5, 25.0, 22.5, 20.0, 17.5, 15.0]))

narr = DimArray(rand(25,25), (ny, nx))
fig, ax, pl = plot(narr)
nsingle = DimArray(rand(25), ny)
╭────────────────────────────────╮
│ 25-element DimArray{Float64,1} │
├────────────────────────────────┴─────────────────────────────────────── dims ┐
  ↓ Y Sampled{Float32} [15.0, 17.5, …, 72.5, 75.0] ForwardOrdered Irregular Points
└──────────────────────────────────────────────────────────────────────────────┘
 15.0  0.576262
 17.5  0.187905
 20.0  0.639093
 22.5  0.0721588
 25.0  0.100157
 27.5  0.989034
 30.0  0.518152
 32.5  0.113321
 35.0  0.940554
  ⋮    
 57.5  0.210949
 60.0  0.106669
 62.5  0.705384
 65.0  0.235972
 67.5  0.153585
 70.0  0.207338
 72.5  0.785304
 75.0  0.684262
fig, ax, pl = plot(nsingle)
ax.finallimits
Observable(GeometryBasics.HyperRectangle{2, Float64}([11.999999955296516, 0.011514742094208469], [66.00000008940697, 1.0240680768311485]))
    0 => map((::Makie.var"#1557#1558")(bbox, limits, aspect) @ Makie /opt/julia/packages/Makie/8h0bl/src/makielayout/helpers.jl:16)
    0 => map(Makie.xlimits)
    0 => map(Makie.ylimits)
    0 => map(_selection_vertices(ax_scene, outer, inner) @ Makie /opt/julia/packages/Makie/8h0bl/src/makielayout/interactions.jl:124)
    -2 => onany((::Makie.var"#1658#1689")(args...) @ Makie /opt/julia/packages/Makie/8h0bl/src/makielayout/blocks/axis.jl:255)

For more see the user guide, the gallery, and the tutorial material.


Reading and Writing files to netCDF#

write("my-example-dataset.nc", ds, force=true)
"my-example-dataset.nc"
# read from disk
fromdisk = RasterStack("my-example-dataset.nc")
fromdisk
╭────────────────────────╮
│ 53×25×2920 RasterStack │
├────────────────────────┴─────────────────────────────────────────────── dims ┐
  ↓ X  Mapped{Float32} [200.0, 202.5, …, 327.5, 330.0] ForwardOrdered Regular Points,
  → Y  Mapped{Float32} [75.0, 72.5, …, 17.5, 15.0] ReverseOrdered Regular Points,
  ↗ Ti Sampled{DateTime} [2013-01-01T00:00:00, …, 2014-12-31T18:00:00] ForwardOrdered Irregular Points
├────────────────────────────────────────────────────────────────────── layers ┤
  :air eltype: Float64 dims: X, Y, Ti size: 53×25×2920
├──────────────────────────────────────────────────────────────────── metadata ┤
  Metadata{Rasters.NCDsource} of Dict{String, Any} with 5 entries:
  "references"  => "http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly…
  "platform"    => "Model"
  "title"       => "4x daily NMC reanalysis (1948)"
  "description" => "Data is from NMC initialized reanalysis\n(4x/day).  These a…
  "Conventions" => "COARDS"
├────────────────────────────────────────────────────────────────────── raster ┤
  extent: Extent(X = (200.0f0, 330.0f0), Y = (15.0f0, 75.0f0), Ti = (DateTime("2013-01-01T00:00:00"), DateTime("2014-12-31T18:00:00")))
  missingval: missing
  crs: EPSG:4326
  mappedcrs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────┘
# check that the two are identical
ds == fromdisk
true

Welcome!#

DimensionalData and the whole Julia data analysis ecosystem is an open-source project and gladly welcomes all kinds of contributions. This could include reporting bugs, discussing new enhancements, contributing code, helping answer user questions, contributing documentation (even small edits like fixing spelling mistakes or rewording to make the text clearer). Welcome!