Search code examples
rrasternetcdf4

Query raster brick layer based on another raster in R


I have a NetCDF file of global oceanographic (OmegaA) data at relatively coarse spatial resolution with 33 depth levels. I also have a global bathymetry raster at much finer resolution. My goal is to use get the seabed OmegaA data from the NetCDF file, using the bathymetry data to determine the desired depth. My code so far;

    library(raster)
    library(rgdal)
    library(ncdf4)

# Aragonite data. Defaults to CRS WGS84
ncin <- nc_open("C:/..../GLODAPv2.2016b.OmegaA.nc")
ncin.depth <- ncvar_get(ncin, "Depth")# 33 depth levels  

omegaA.brk  <- brick("C:/.../GLODAPv2.2016b.OmegaA.nc")
omegaA.brk  <-rotate(omegaA.bkr)# because netCDF is in Lon 0-360. 

# depth raster.  CRS WGS84
r<-raster("C:/....GEBCO.tif") 

# resample the raster brick to the resolution that matches the bathymetry raster
omegaA.brk  <-resample(omegaA.brk, r, method="bilinear")

# create blank final raster 
omegaA.rast         <- raster(ncol = r@ncols, nrow = r@nrows)
extent(omegaA.rast) <- extent(r)
omegaA.rast[]       <- NA_real_

#  create vector of indices of desired depth values
depth.values<-getValues(r)
depth.values.index<-which(!is.na(depth.values))


# loop to find appropriate raster brick layer, and extract the value at the desired index, and insert into blank raster

for (p in depth.values.index) { 
  dep.index         <-which(abs(ncin.depth+depth.values[p]) == min(abs(ncin.depth+depth.values[p]))) ## this sometimes results in multiple levels being selected

  brk.level         <-omegaA.brk[[dep.index]]  # can be more than on level if multiple layers selected above. 
  omegaA.rast[p]    <-omegaA.brk[[1]][p] ## here I choose the first level if multiple levels have been selected above

  print(paste(p, "of", length(depth.values.index))) # counter to look at progress. 
}

The problem: The result is a raster with massive gaps (NAs) in it where there should be data. The gaps often take a distinctive shape - eg, follow a contour, or along a long straight line. I've pasted a cropped example.

enter image description here

I think this could be because either 1) for some reason the 'which' statement in the loop is not finding a match or 2) a misalignment of the projections is created which I've read can happen when using 'Rotate'.

I've tried to make sure all the extents, resolutions, number of cells, and CRS's are all the same, which they seem to be.

To speed up the process I've cropped the global brick and bathy raster to my area of interest, again checking that all the spatial resolutions, etc etc match - I've not included those steps here for simplicity.

At a loss. Any help welcome!


Solution

  • Without a reproducible example, this kind of problems is hard to solve. I can't tell where your problem is but I'll present to you the approach I would try. Maybe it's good, maybe it's bad, I don't know but it may inspire you to find a way to go around your problem.

    To my understanding, you have a brick of OmegaA (33 layers/depth) and a bathymetry raster. You want to get the OmegaA value at the bottom of the sea. Here is how I would do:

    1. Make OmegaA raster to the same resolution and extent to the bathymetry one
    2. Transforme the bathymetry raster into a raster brick of 33 three layers of 0-1. e.g. If the sea bottom is at 200m for one particular pixel, than this pixel on all depth layer other than 200 is 0 and 1 for the 200. To program this, I would go the long way, something like

    :

    r_1 <- r
    values(r_1) <- values(r)==10  # where 10 is the depth (it could be a range with < or >)
    r_2 <- r
    values(r_2) <- values(r)==20
    ...
    r_33 <- r
    values(r_33) <- values(r)==250
    r_brick <- brick(r_1, r_2, ..., r_33)
    
    1. then you multiple both your raster bricks. They have the same dimension, it should be easy. The output should be a raster brick of 33 layers with 0 everywhere where it isn't the bottom of the sea and the value of OmegaA anywhere else.
    2. Combine all the layer of the brick obtained previously into a simple raster with a sum.

    This should work. If you have problem with dealing with raster brick, you could make the data into base R arrays, it could be simpler.

    Good luck.