Proposed Dataset for GFZ Hackathon

CO2 in air

Background

Nearly all geoscientists know the “Keeling Curve”, the graph of the accumulation of carbon dioxide in the Earth’s atmosphere based on continuous measurements taken in Hawaii from 1958 to the present day. (See https://en.wikipedia.org/wiki/Keeling_Curve ; or open an R session and type co2).

plot(co2, main="The Keeling Curve\nppmv CO2 in air", sub="(year)")

However this is a highly aggregated curve from a remote location taken at 3400m above sea level, and as such perhaps represents the entire troposphere at 0°C, but still might paint a rosy picture.

For starters, I expect CO2 concentrations at sea level to be higher than on a mountaintop in Hawaii.

Thus, I think it would be insightful to have a closer look at “real” air-CO2 measurements taken in Europe.

Of course there are many alternative data sources for air CO2 data. Here is one I came across in 2017 when I wanted to learn what NetCDF files are and how they can be used.

Objectives

Designed for Simplicity

Play with this CO2 dataset if you do not have the time, the equipment, or the mindset to work on a big-data project during the GFZ hackathon.

Objectives

  • learn something about daily ambient CO2 fluctuations
  • refresh basics of Physical Chemistry
  • explore real-world environmental sensor data (already curated, pretty clean)
  • check out AWI‘s Pangaea.de data repository
  • learn what NetCDF files are and how they can be used

Augment the dataset if you want to, or if there‘s a better one

Citation

CSV Format

Here the data is downloadable as Tab-Separated Text format, very similar to CSV. This webpage has a short abstract.

Lammert, Andrea; Ament, Felix; Krupski, Michael (2013): Long-term eddy-covariance measurements from FINO2 platform above the Baltic Sea. PANGAEA, https://doi.org/10.1594/PANGAEA.809058

Alternatively, this very similar webpage offers the same datasets, but in a self-documenting format, as NetCDF Files. There is no abstract, though.

NetCDF Format

Lammert, Andrea; Ament, Felix; Krupski, Michael (2013): Long-term eddy-covariance measurements from FINO2 platform above the Baltic Sea (NetCDF format). PANGAEA, https://doi.org/10.1594/PANGAEA.808714, In: Lammert, A et al. (2013): Long-term eddy-covariance measurements from FINO2 platform above the Baltic Sea. PANGAEA, https://doi.org/10.1594/PANGAEA.809058

The data was collected during the German “SOPRAN - Surface Ocean Processes in the Anthropocene” research project which ended in 2015.

I was never affiliated with the project and I don’t know the dataset author(s).

The dataset

This is a time-series dataset of 29 NetCDF Files, < 10 MB in total size, measured from 2008 to 2012, each with ~30 parameters. Some column names are self-explanatory, others are a bit obscure (“Monin-Obukhov-length”). Still, this is a rather clean dataset with most parameters understandable to non-specialists.

I think such CO2 measurements are still worth re-investigating, just as a personal learning experience. Have a look at daily/weekly/… fluctuations, gaps, sensor specifics, etc.

For machine learning, perhaps model this as a regression problem. Predict “CO2” from of Temperature, Pressure, …

Of course Hackathon Participants could pick other datasets from other locations (e.g. indoor measurements), but this CO2 dataset is something to start with. For details, please read the abstract at above-mentioned link.

Dataset Parameters

  • DATE/TIME (Date/Time) * Geocode
  • HEIGHT above ground [m] (height) * Geocode
  • Valid values per 30min interval (max. 18000) [-] (Val)
  • Error flag, 0=no error, 1-3=unreliable data: 1=less than half of interval valid , 2=LICOR sensor not reliable, 3=ship transit at platform [-] (Flag)
  • Mean wind speed over 30 min from USAT [m/s] (FF)
  • Mean Wind direction over 30 min from USAT [deg] (DD)
  • Mean Wind in east-west direction over 30 min from USAT [m/s] (U)
  • Mean Wind in north-south direction over 30 min from USAT [m/s] (V)
  • Mean Vertical wind speed over 30 min from USAT [m/s] (W)
  • Mean Air temperature over 30 min from USAT [°C] (T)
  • Mean Humidity, absolute over 30 min from LICOR 7500 [g/m^3] (AH)
  • Mean CO2 concentration over 30 min from LICOR 7500 [g/m^3] (CO2)
  • Mean Humidity, relative over 30 min from ROTRONIC [%] (RH_rot)
  • Mean Humidity, absolute over 30 min from ROTRONIC [g/m^3] (AH_rot)
  • Mean Air temperature over 30 min from PT100 [°C] (T_pt100)
  • Variance of wind speed FF in 30 min time interval [m^2/s^2] (var_FF)
  • Variance of east-west wind U in 30 min time interval [m^2/s^2] (var_U)
  • Variance of north-south wind V in 30 min time interval [m^2/s^2] (var_V)
  • Variance of vertical wind speed W in 30 min time interval [m^2/s^2] (var_W)
  • Variance of air temperature in 30 min time interval [K^2] (var_T)
  • Variance of Humidity, absolute in 30 min time interval [g^2/m^6] (var_AH)
  • Variance of CO2 concentration in 30 min time interval [g^2/m^6] (var_CO2)
  • Shearing stress [m/s] (Ustar)
  • Monin-Obukhov-length [m] (MOS)
  • Roughness length [m] (Z0)
  • Upward momentum flux in air [kg/m/s^2] (QI)
  • Upward sensible heat flux with Schotanus correction [W/m^2] (QH)
  • Upward latent heat flux with Webb correction [W/m^2] (QE)
  • Upward CO2 flux with Webb correction [mg/m^2/s] (QC)

Preprocessing

Setup R

Check that required R packages are installed:

want <- c("tidyverse", "lubridate", "here", "janitor", "RNetCDF","ncdf4","gridExtra", "GGally", "kableExtra")
have <- want %in% rownames(installed.packages())
if ( any(!have) ) { install.packages( want[!have] ) }

Load R packages

library(downloader)

library(tidyverse)
theme_set(theme_bw())
library(kableExtra) # table styling (stripes)
library(lubridate)

library(RNetCDF)
library(ncdf4)     # higher-level API

library(gridExtra) # 2 plots side-by-side
library(GGally)    # ggpairs

Set working directory to a new subdirectory of “pangaea”. If it does not exist, enter it.

getwd()
working_dir <- here::here(path="pangaea")
if(! dir.exists(working_dir)){
  dir.create(working_dir)
}
setwd(working_dir)
getwd()

Downloading NetCDF Files

Download the doi: link:

Lammert, A et al. (2013): Long-term eddy-covariance measurements from FINO2 platform above the Baltic Sea (NetCDF format). doi:10.1594/PANGAEA.808714

This retrieves just file metadata about the 29 datafiles, in particular the download links. Results see further below

zf <- "balticsea-data.tsv"
if (!file.exists(zf)) {
  download("http://doi.pangaea.de/10.1594/PANGAEA.808714?format=textfile", zf)
}
zf
## [1] "balticsea-data.tsv"

Automatic download of the NetCDF Files after parsing of the balticsea-data.tsv file:

con <- file(zf, open = "r")
lines <- readLines(con)
skipn <- match("*/", lines) # gets the row index of the close comment
close.connection(con)

filelist <- read_delim(zf, skip = skipn, delim = "\t")
## Parsed with column specification:
## cols(
##   `Date/time start` = col_datetime(format = ""),
##   `Date/time end` = col_datetime(format = ""),
##   `URL file` = col_character(),
##   `File name` = col_character(),
##   `File size [kByte]` = col_double(),
##   `File format` = col_character()
## )
outdir <- "netcdf-files"
if (!dir.exists(outdir)) {
  system(sprintf("mkdir '%s'", outdir))
}
# NetCDF Files found on local hard disc

filelist %>%
  select(`File name`) %>%
  pull()
filelist <- filelist %>%
  nest(data = c(`File name`, `URL file`)) %>%
  mutate(dl_result = map_chr(data, ~ my_download(., outdir = outdir))) %>%
  unnest(data)

There are 29 monthly datafiles in the balticsea-data.tsv file.

knitr::kable(filelist) %>% 
   kable_styling(bootstrap_options = "striped",
                full_width = TRUE) %>%
  #add_header_above(c(" ", "Group 1" = 2, "Group 2[note]" = 2)) %>%
  add_footnote(c("loc ok = 'file already existed locally'"))
Date/time start Date/time end File size [kByte] File format File name URL file dl_result
2008-06-01 2008-06-30 23:30:00 344 application/x-netcdf fino2_flux_200806.nc http://hdl.handle.net/10013/epic.41173.d030 loc ok
2008-07-01 2008-07-31 23:30:00 355 application/x-netcdf fino2_flux_200807.nc http://hdl.handle.net/10013/epic.41173.d031 loc ok
2008-08-01 2008-08-31 23:30:00 355 application/x-netcdf fino2_flux_200808.nc http://hdl.handle.net/10013/epic.41173.d032 loc ok
2008-09-01 2008-09-30 23:30:00 344 application/x-netcdf fino2_flux_200809.nc http://hdl.handle.net/10013/epic.41173.d033 loc ok
2008-10-01 2008-10-31 23:30:00 355 application/x-netcdf fino2_flux_200810.nc http://hdl.handle.net/10013/epic.41173.d034 loc ok
2008-11-01 2008-11-30 23:30:00 344 application/x-netcdf fino2_flux_200811.nc http://hdl.handle.net/10013/epic.41173.d035 loc ok
2008-12-01 2008-12-31 23:30:00 355 application/x-netcdf fino2_flux_200812.nc http://hdl.handle.net/10013/epic.41173.d036 loc ok
2009-01-01 2009-01-31 23:30:00 355 application/x-netcdf fino2_flux_200901.nc http://hdl.handle.net/10013/epic.41173.d037 loc ok
2009-02-01 2009-02-28 23:30:00 321 application/x-netcdf fino2_flux_200902.nc http://hdl.handle.net/10013/epic.41173.d038 loc ok
2009-03-01 2009-03-31 23:30:00 355 application/x-netcdf fino2_flux_200903.nc http://hdl.handle.net/10013/epic.41173.d039 loc ok
2009-04-01 2009-04-29 23:00:00 332 application/x-netcdf fino2_flux_200904.nc http://hdl.handle.net/10013/epic.41173.d040 loc ok
2009-05-01 2009-05-31 23:30:00 355 application/x-netcdf fino2_flux_200905.nc http://hdl.handle.net/10013/epic.41173.d041 loc ok
2009-06-01 2009-06-30 23:30:00 344 application/x-netcdf fino2_flux_200906.nc http://hdl.handle.net/10013/epic.41173.d042 loc ok
2009-07-01 2009-07-31 23:30:00 355 application/x-netcdf fino2_flux_200907.nc http://hdl.handle.net/10013/epic.41173.d043 loc ok
2009-08-01 2009-08-31 23:30:00 355 application/x-netcdf fino2_flux_200908.nc http://hdl.handle.net/10013/epic.41173.d044 loc ok
2009-09-01 2009-09-30 23:30:00 344 application/x-netcdf fino2_flux_200909.nc http://hdl.handle.net/10013/epic.41173.d045 loc ok
2009-10-01 2009-10-31 23:30:00 355 application/x-netcdf fino2_flux_200910.nc http://hdl.handle.net/10013/epic.41173.d046 loc ok
2009-11-01 2009-11-30 23:30:00 344 application/x-netcdf fino2_flux_200911.nc http://hdl.handle.net/10013/epic.41173.d047 loc ok
2009-12-01 2009-12-30 23:00:00 343 application/x-netcdf fino2_flux_200912.nc http://hdl.handle.net/10013/epic.41173.d048 loc ok
2011-11-10 2011-11-30 23:30:00 242 application/x-netcdf fino2_flux_201111.nc http://hdl.handle.net/10013/epic.41173.d049 loc ok
2011-12-01 2011-12-31 23:30:00 355 application/x-netcdf fino2_flux_201112.nc http://hdl.handle.net/10013/epic.41173.d050 loc ok
2012-01-01 2012-01-31 23:30:00 355 application/x-netcdf fino2_flux_201201.nc http://hdl.handle.net/10013/epic.41173.d051 loc ok
2012-02-01 2012-02-29 23:30:00 332 application/x-netcdf fino2_flux_201202.nc http://hdl.handle.net/10013/epic.41173.d052 loc ok
2012-03-01 2012-03-31 23:30:00 355 application/x-netcdf fino2_flux_201203.nc http://hdl.handle.net/10013/epic.41173.d053 loc ok
2012-04-01 2012-04-30 23:30:00 344 application/x-netcdf fino2_flux_201204.nc http://hdl.handle.net/10013/epic.41173.d054 loc ok
2012-05-01 2012-05-31 23:30:00 355 application/x-netcdf fino2_flux_201205.nc http://hdl.handle.net/10013/epic.41173.d055 loc ok
2012-06-01 2012-06-30 23:30:00 344 application/x-netcdf fino2_flux_201206.nc http://hdl.handle.net/10013/epic.41173.d056 loc ok
2012-07-01 2012-07-31 23:30:00 355 application/x-netcdf fino2_flux_201207.nc http://hdl.handle.net/10013/epic.41173.d057 loc ok
2012-08-01 2012-08-31 23:30:00 355 application/x-netcdf fino2_flux_201208.nc http://hdl.handle.net/10013/epic.41173.d058 loc ok
a loc ok = ‘file already existed locally’

Science data - first look

Consider only the first netCDF File, from 2008.

Reminder, these are the column names:

netcdf.file <- filelist %>%
  slice(1) %>%
  pull(`File name`)

# RNetCDF provides a  low-level API
conn <- RNetCDF::open.nc(file.path(outdir, netcdf.file, fsep = "/"))
dat <- read.nc(conn)  # the only higher-level function, returns nested list
close.nc(conn)

names(dat)
##  [1] "time"        "base_time"   "height"      "isotime"     "valid"       "ff"          "dd"          "u"          
##  [9] "v"           "w"           "T"           "AH"          "CO2"         "T_pt100"     "RH_rotronic" "AH_rotronic"
## [17] "var_ff"      "var_u"       "var_v"       "var_w"       "var_T"       "var_AH"      "var_CO2"     "ustar"      
## [25] "MOS"         "z0"          "QI"          "QH"          "QE"          "QC"          "flag"        "lon"        
## [33] "lat"

Convert ppmv to gram

Convert “ppmv” to \(g/m³\), see this page for a long forum thread with people “peer-reviewing” the conversion formula.

There are many other conversion sites online, e.g. this one.

# by default at 25 deg C
ppm2g <- function(ppm, T = 298.15, P = 101325){
  # P = 1 atm = 101325 Pa
  M <- 44.01 # g/mol
  R <- 8.3145 # J / (mol * K)
  V <- ppm * 10^-6
  # Mass of CO2  in grams = (44.01)(101,325)(380 x 10-6)/(8.31441)(298.15) = 0.684 g
  M * P * V / (R * T) # g / m³
}


ppm2g(380)
## [1] 0.6836

So 380 ppm CO2 = 684 mg/m3 CO2 at 1 atm and 298.15 K (25 °C)

# Define a constant for convenience for back-of-the-envelope reverse calculation
g2ppm <- 0.684     # gram to ppm C02 at 380ppm C02/m³
# rowSums(dat$flag)

# plot a single data series
co2_curve <- function(idx = 1) {
  co2_fino <- data.frame(day = fast_strptime(dat$isotime, "%Y-%m-%dT%H:%M:%S"),
                    co2 = dat$CO2[idx, ]) %>%
    mutate(hour = hour(day))
  # summary(co2)
  # colnames(co2)
  yr <- co2_fino %>% select(day) %>% slice(1) %>% pull(day) %>% year()
  ggplot(co2_fino, aes(x = day, y = co2 * g2ppm * 1000)) +
    geom_point(alpha = 0.4) +
    geom_line(alpha = 0.4) +
    geom_smooth(method = "loess", se = FALSE) +
    # facet_wrap(~hour) +
    labs(title = "FINO Measurements of Air CO2",
         subtitle = "1 Measurement/Day",
         x = sprintf("%s", yr),
         y = "PPM CO2")
}

plots <- map(1:2, co2_curve)
#plots[[1]]

grid.arrange(grobs = plots, labels = c("", ""), rows = 2, cols = 1)

The CO2 concentration at the FINO2 platform in the Baltic Sea seems indeed to be higher than in Hawaii. However the unit conversion might be wrong or imprecise.

Consider all netCDF Files

Read in all, keep only valid data (NULL values are a problem).

data_simple <- dat
data_simple[ c("flag", "lon", "lat", "time", "base_time", "height")] <- NULL
# data_simple$isotime <- fast_strptime(data_simple$isotime,  "%Y-%m-%dT%H:%M:%S")

data_simple2 <- lapply(data_simple[2:length(data_simple)], function(el) el[1, ])
data_simple2 <- lapply(c(data_simple[1], data_simple2), cbind) 
# data_simple[1:2] %>% lapply(as.data.frame) %>% bind_rows()
data_simple2 <- as.data.frame(data_simple2)
data_simple2 <- data_simple2 %>%
  filter(valid > 0)
colnames(data_simple2)
##  [1] "isotime"     "valid"       "ff"          "dd"          "u"           "v"           "w"           "T"          
##  [9] "AH"          "CO2"         "T_pt100"     "RH_rotronic" "AH_rotronic" "var_ff"      "var_u"       "var_v"      
## [17] "var_w"       "var_T"       "var_AH"      "var_CO2"     "ustar"       "MOS"         "z0"          "QI"         
## [25] "QH"          "QE"          "QC"
data_simple3 <- data_simple2 %>%
  select(-valid)

# summary(data_simple2)
colnames(data_simple3)
##  [1] "isotime"     "ff"          "dd"          "u"           "v"           "w"           "T"           "AH"         
##  [9] "CO2"         "T_pt100"     "RH_rotronic" "AH_rotronic" "var_ff"      "var_u"       "var_v"       "var_w"      
## [17] "var_T"       "var_AH"      "var_CO2"     "ustar"       "MOS"         "z0"          "QI"          "QH"         
## [25] "QE"          "QC"

Read in a netcdf file

nc <- ncdf4::nc_open(paste0("netcdf-files/",netcdf.file))
# variables = names(nc[['var']])
for (i in 2:(nc$nvars)) {
  varinfo <- nc[["var"]][[i]]

  cat("        ", varinfo$name, " ", varinfo$units, sep = "")
  if (varinfo$name %in% colnames(data_simple2) & nchar(varinfo$units) > 0) {
    colnames(data_simple2)[
      which(colnames(data_simple2) == varinfo$name)] <- paste0(varinfo$name, " [",                                                                                        varinfo$units, "] ",
                                                               varinfo$longname)
  }
}
#colnames(data_simple2)
ncdf4::nc_close(nc)

Create a plot-matrix of 3 easy-to-understand parameters

co2.sensor.data <- data_simple2 %>%
  gather(Param, Value, 2:(ncol(data_simple2)))


# Plot each graph with appropriately scaled y-axis and
# as a function of isodate


#ml <- marrangeGrob(pl, nrow = 5, ncol = 1)
## interactive use; open new devices
#ml
unique(co2.sensor.data$Param)
ggplot(co2.sensor.data[co2.sensor.data$Param == "T [K] Air temperature from USAT", ], aes(x = day(isotime), y = Value)) +
  geom_boxplot(fill = "#2b2b2b", alpha = 0.25, width = 0.75, size = 0.25) +
  scale_x_discrete(expand = c(0, 0)) +
  scale_y_continuous(expand = c(0, 0)) +
  coord_flip() +
  #theme_tufte(base_family = "Helvetica") +
  theme(axis.ticks = element_blank()) +
  labs(x = NULL, y = NULL)
# For details, see the output of `` at the end of this file.
#ggsave("multipage-2008-co2sensordata-balticsea-v2.pdf", ml)

# make plot matrix (xyplots, correlations)

data_simple2$isoday <- day(fast_strptime(as.character(data_simple2$isotime), "%Y-%m-%dT%H:%M:%S"))
data_simple3 <- data_simple2 %>% 
  janitor::clean_names()
data_simple3[, "isotime"] <- NULL

# remove columns with variances
var_ <- colnames(data_simple3[which(grepl("var_", colnames(data_simple3)))])
mycolumns <- setdiff(colnames(data_simple3), c("dd", "u", "v", "w", var_))

#colnames(data_simple3)[which(colnames(data_simple3) %in% mycolumns)] <- mycolumns.ok
GGally::ggpairs(data_simple3[, mycolumns[6:8]], size = 0.1)

Full parameter list

Output of command ncdump -h fino2_flux_201208.nc.

All parameters with comprehensive documentation.

ncdump -h fino2_flux_201208.nc  
netcdf fino2_flux_201208 {
dimensions:
    height = 2 ;
    isotime_length = 19 ;
    time = UNLIMITED ; // (1488 currently)
variables:
    int time(time) ;
        time:standard_name = "time" ;
        time:long_name = "Time offset from base_time" ;
        time:units = "seconds since  1-Aug-2012,00:00:00 UTC" ;
    int base_time ;
        base_time:string = " 1-Aug-2012,00:00:00 UTC" ;
        base_time:long_name = "Start in Epoch time" ;
        base_time:units = "seconds since 1970-1-1 0:00:00 0:00" ;
    float height(height) ;
        height:standard_name = "Altitude" ;
        height:long_name = "Altitude of instrument above sea level" ;
        height:units = "m" ;
    char isotime(time, isotime_length) ;
        isotime:long_name = "Date/Time in ISO-format (YYYY-MM-DDThh:mm:ss)" ;
    int valid(time, height) ;
        valid:long_name = "Number of valid 10Hz measurements in 30min interval (max 18000)" ;
        valid:units = "-" ;
    float ff(time, height) ;
        ff:standard_name = "wind_speed" ;
        ff:long_name = "Wind speed from USAT" ;
        ff:units = "m s-1" ;
        ff:_FillValue = -2.e+20f ;
    float dd(time, height) ;
        dd:standard_name = "wind_from_direction" ;
        dd:long_name = "Wind from direction from USAT" ;
        dd:units = "degree" ;
        dd:_FillValue = -2.e+20f ;
    float u(time, height) ;
        u:standard_name = "eastward_wind" ;
        u:long_name = "Wind in east-west direction from USAT" ;
        u:units = "m s-1" ;
        u:_FillValue = -2.e+20f ;
    float v(time, height) ;
        v:standard_name = "northward_wind" ;
        v:long_name = "Wind in south-north direction from USAT" ;
        v:units = "m s-1" ;
        v:_FillValue = -2.e+20f ;
    float w(time, height) ;
        w:standard_name = "vertical_wind_speed" ;
        w:long_name = "Vertical wind speed from USAT" ;
        w:units = "m s-1" ;
        w:_FillValue = -2.e+20f ;
    float T(time, height) ;
        T:standard_name = "air_temperature" ;
        T:long_name = "Air temperature from USAT" ;
        T:units = "K" ;
        T:_FillValue = -2.e+20f ;
    float AH(time, height) ;
        AH:standard_name = "absolute_humidity" ;
        AH:long_name = "Absolute humidity from LICOR 7500" ;
        AH:units = "g m-3" ;
        AH:_FillValue = -2.e+20f ;
    float CO2(time, height) ;
        CO2:standard_name = "mass_concentration_of_carbon_dioxide_in_air" ;
        CO2:long_name = "CO2 concentration from LICOR 7500" ;
        CO2:units = "g m-3" ;
        CO2:_FillValue = -2.e+20f ;
    float T_pt100(time, height) ;
        T_pt100:long_name = "Air temperature from slow sensor(PT100)" ;
        T_pt100:units = "K" ;
        T_pt100:_FillValue = -2.e+20f ;
    float RH_rotronic(time, height) ;
        RH_rotronic:long_name = "Relative humidity from slow sensor(Rotronic)" ;
        RH_rotronic:units = "%" ;
        RH_rotronic:_FillValue = -2.e+20f ;
    float AH_rotronic(time, height) ;
        AH_rotronic:long_name = "Absolute humidity from slow sensor(Rotronic)" ;
        AH_rotronic:units = "g m-3" ;
        AH_rotronic:_FillValue = -2.e+20f ;
    float var_ff(time, height) ;
        var_ff:long_name = "Variance of wind speed" ;
        var_ff:units = "m2 s-2" ;
        var_ff:_FillValue = -2.e+20f ;
    float var_u(time, height) ;
        var_u:long_name = "Variance of wind in east-west direction" ;
        var_u:units = "m2 s-2" ;
        var_u:_FillValue = -2.e+20f ;
    float var_v(time, height) ;
        var_v:long_name = "Variance of wind in south-north direction" ;
        var_v:units = "m2 s-2" ;
        var_v:_FillValue = -2.e+20f ;
    float var_w(time, height) ;
        var_w:long_name = "Variance of vertical wind speed" ;
        var_w:units = "m2 s-2" ;
        var_w:_FillValue = -2.e+20f ;
    float var_T(time, height) ;
        var_T:long_name = "Variance of air temperature" ;
        var_T:units = "K2" ;
        var_T:_FillValue = -2.e+20f ;
    float var_AH(time, height) ;
        var_AH:long_name = "Variance of absolute humidity" ;
        var_AH:units = "g2 m-6" ;
        var_AH:_FillValue = -2.e+20f ;
    float var_CO2(time, height) ;
        var_CO2:long_name = "Variance of CO2 concentration" ;
        var_CO2:units = "g2 m-6" ;
        var_CO2:_FillValue = -2.e+20f ;
    float ustar(time, height) ;
        ustar:standard_name = "shearing_stress" ;
        ustar:long_name = "Shearing stress" ;
        ustar:units = "m s-1" ;
        ustar:_FillValue = -2.e+20f ;
    float MOS(time, height) ;
        MOS:long_name = "Monin-Obukhov-length" ;
        MOS:units = "m" ;
        MOS:_FillValue = -2.e+20f ;
    float z0(time, height) ;
        z0:standard_name = "surface_roughness_length" ;
        z0:long_name = "Roughness length" ;
        z0:units = "m" ;
        z0:_FillValue = -2.e+20f ;
    float QI(time, height) ;
        QI:standard_name = "upward_momentum_flux_in_air" ;
        QI:long_name = "Momentum flux" ;
        QI:units = "kg m-1 s-2" ;
        QI:_FillValue = -2.e+20f ;
    float QH(time, height) ;
        QH:standard_name = "upward_sensible_heat_flux_in_air" ;
        QH:long_name = "Sensible heat flux with Schotanus correction" ;
        QH:units = "W m-2" ;
        QH:_FillValue = -2.e+20f ;
    float QE(time, height) ;
        QE:standard_name = "upward_latent_heat_flux_in_air" ;
        QE:long_name = "Latent heat flux with Webb correction" ;
        QE:units = "W m-2" ;
        QE:_FillValue = -2.e+20f ;
    float QC(time, height) ;
        QC:standard_name = "upward_mass_flux_of_carbon_dioxide_in_air" ;
        QC:long_name = "CO2 flux with Webb correction" ;
        QC:units = "mg m-2 s-1" ;
        QC:_FillValue = -2.e+20f ;
    float flag(time, height) ;
        flag:long_name = "error flag, 0=no error, 1-3=unreliable data: 1=less than half of interval valid , 2=LICOR sensor not reliable, 3=shipping traffic at platform" ;
        flag:units = "-" ;
    float lon ;
        lon:standard_name = "longitude" ;
        lon:long_name = "East longitude of FINO2-platform" ;
        lon:units = "degree" ;
    float lat ;
        lat:standard_name = "latitude" ;
        lat:long_name = "North latitude of FINO2-platform" ;
        lat:units = "degree" ;

// global attributes:
        :Project = "Surface Ocean Processes in the Anthropocene" ;
        :Project_acronym = "SOPRAN" ;
        :Typ = "Meteorological Long-Term Observations" ;
        :Institute = "Meteorological Institute, University Hamburg" ;
        :Author = "Andrea Lammert" ;
        :Station = "FINO2" ;
        :Coordinate = "N 55.007, E 13.154" ;
        :Sample_int = "0.1 secondes" ;
        :Averaging_int = "30 minutes" ;
        :Time_stamp_details = "The time stamp currently reflects the _start_ of the 30 minute sampling interval." ;
        :Instruments = "Anemometer: USAT, IRGA: LICOR 7500, Slow humidity sensor: ROTRONIC, Slow temperature sensor: PT100" ;
        :Date = "Thu Mar 28 09:54:09 2013" ;
}