rmarkdown::render("oisst_to_grid26.Rmd")
knitr::opts_chunk$set(echo = TRUE)
This is for Philina's request (issue
https://github.com/pbs-assess/pacea/issues/60 ) to project the OISST data onto
the same grid (grid26
) as used for the BCCM model results. Can adapt some of
this into functions if needed later. Doing this quickly here for now.
The OISST data are saved on the original 1/4° grid that NOAA provides them as. So we have not done any projection to get them into pacea; so try that here.
Basing this on approach used in data-raw/roms/roms-data-interpolation.R
for
the BCCM model results, and recently adopted in
data-raw/hotssea/hotssea-data-interpolation.R
for the HOTSSea model results.
Specifically, want to transform the oisst_month
data, which is an sf
object of monthly means in
the original spatial 1/4° longitude x 1/4° latitude grid and WGS 84 projection
and masked to show only the BC Exclusive Economic Zone area, onto the grid26
grid. The coordinates in the geometry column of the oisst_month
object are the centroid of each grid cell.
This means that exactly the same spatiotemporal analyses can be done on both datasets.
load_all() # library(pacea) # or load_all() when developing library(dplyr) library(sf) library(ggplot2)
In addition to the mean temperature value (weekly or monthly mean) for each grid cell, there are also other statistical measures, such as the standard deviation and number of observations. There is also a start- and end-date column that indicates the temporal period for which the mean is calculated from. Focussing here just on the monthly values.
oisst_month # plot(oisst_month) bccm_sst <- bccm_surface_temperature() bccm_sst
Need to convert the former (means only) into the format of the latter, so with:
year-month headings
different co-ordinate system
and POLYGON instead of POINT geometry:
head(oisst_month$geometry) head(bccm_sst$geometry)
First generate a subset of data to use, filtering is for speed (now ignoring), selecting here is just what we need:
# sub <- dplyr::filter(oisst_month, # year == 1981) %>% sub <- dplyr::select(oisst_month, year, month, sst, geometry) # plot.pacea_oi(sub) this works
sub_wide <- sub %>% tidyr::pivot_wider(names_from = c("year", "month"), values_from = "sst") sub_wide
sub_trans <- sf::st_transform(sub_wide, crs = "EPSG:3005")
Attempt 1.
This would be ideal, but requires data to be a terra spatraster. TODO ask Kelsey
when she's back. Copying from Kelsey's code in depth.R
and editing as
necessary.
So this is not run:
#template raster to transform bathy data to match pacea grid ext2 <- st_bbox(grid26) temp <- terra::rast(resolution = c(500, 500), #have to resample to lower res than input data xmin = ext2[1] - 500, #match extent + buffer of pacea grid ymin = ext2[2] - 500, xmax = ext2[3] + 500, ymax = ext2[4] + 500, crs = paste0(terra::crs(grid26, describe=TRUE)[,2], ":", terra::crs(grid26, describe=TRUE)[,3])) #crs of pacea grid for zonal statistics #reproject to new crs, using bilinear for continuous data sub_trans_proj <- terra::project(sub_trans, temp, method="bilinear") # Error in (function (classes, fdef, mtable) : # unable to find an inherited method for function 'project' for signature '"sf"' sub_trans_proj
Attempt 2:
Copying from roms-data-interpolation.R
and editing:
# interpolate data # 2 km res sub_2 <- point2rast(data = sub_trans, spatobj = inshore_poly, loc = c("x", "y"), cellsize = 2000, as = "SpatRast") # 6 km res sub_6 <- point2rast(data = sub_trans, spatobj = offshore_poly, loc = c("x", "y"), cellsize = 6000, as = "SpatRast") # crop out grid cells with polygon masks sub_sf2 <- sub_2 %>% terra::mask(bccm_eez_poly) %>% terra::mask(inshore_poly) %>% stars::st_as_stars() %>% ## check here for converting to points (not raster) st_as_sf() sub_sf6 <- sub_6 %>% terra::mask(bccm_eez_poly) %>% terra::mask(offshore_poly) %>% stars::st_as_stars() %>% st_as_sf() # mask 2k grid with 6k grid, then combine grids sub_sf26a <- sub_sf2[!st_intersects(st_union(sub_sf6), sub_sf2, sparse=FALSE, prepared=TRUE),] %>% rbind(sub_sf2[st_intersects(st_union(sub_sf6), sub_sf2, sparse=FALSE, prepared=TRUE),]) %>% rbind(sub_sf6) # Ideally want to make it bigger? For now Philina just wants same as BCCM. # Need to use same outline as for bccm values, i.e. roms_cave: ## snc_lat <- as.vector(ncvar_get(snc_dat, "lat_rho")) ## svar <- as.vector(ncvar_get(snc_dat, "temp", count = c(-1, -1, 1))) ## sdat <- data.frame(x = snc_lon, y = snc_lat, value = svar) %>% ## st_as_sf(coords = c("x", "y"), crs = "EPSG:4326") %>% ## st_transform(crs = "EPSG:3005") ## sroms_cave <- sdat %>% ## na.omit() %>% ## concaveman::concaveman() ## sroms_buff <- sdat %>% ## na.omit() %>% ## st_geometry() %>% ## st_buffer(dist = 2000) %>% ## st_union() %>% ## st_as_sf() # Think can ignore roms_buff and roms_cave, which were data-specific # (e.g. bottom temperature), and we're already using the surface values sub_sf26b <- sub_sf26a[roms_cave,] # 2. use roms_buff to get haida gwaii outline and shore sub_sf26b <- sub_sf26b[roms_buff,] # TODO may need these if domains don't match # 3. use default surface roms_cave # sub_sf26b <- sub_sf26b[sroms_cave,] # 4. use default surface roms_buff # sub_sf26 <- sub_sf26b[sroms_buff,] expect_equal(nrow(sub_sf26b), 41288) # Passes! # data should have 41,288 grid cells # assign column names as year_month. TODO seems to already be there, might # be formatted slightly differently? # names(sub_sf26)[1:(ncol(sub_sf26) - 1)] <- cnames # covert to long format data - Don't do long format as it is too big # t3_sf26 <- t2_sf26 %>% # tidyr::pivot_longer(cols = !last_col(), cols_vary = "slowest", names_to = "date", values_to = "value") %>% # mutate(year = substr(date, 1, 4), # month = substr(date, 6, 7)) %>% # dplyr::select(-date) %>% # relocate(value, .after = last_col()) %>% # relocate(geometry, .after = last_col()) # round to 6 decimal places to reduce file size # t3_sf26[, "value"] <- t3_sf26$value %>% # for long format # round(digits = 6) oisst_month_grid26 <- sub_sf26b %>% st_drop_geometry() %>% round(digits = 6) %>% st_as_sf(geometry = st_geometry(sub_sf26b)) # assign pacea class class(oisst_month_grid26) <- c("pacea_st", "sf", "tbl_df", "tbl", "data.frame") # assign units attribute attr(oisst_month_grid26, "units") <- attr(oisst_month, "units") save(oisst_month_grid26, file = "oisst_month_grid26.rds", compress = "xz") # To load (anywhere) before I've saved into package: # load(paste0(here::here(), "/vignettes/oisst_month_grid26.rds")) # TODO use_data # filename <- paste0("../pacea-data/data/",objname, "_", version, ".rds") #filename <- paste0("../pacea-data/data/",objname, ".rds") #assign(objname, t3_sf26) #do.call("save", list(as.name(objname), file = filename, compress = "xz"))
Test the values. Compare with oisst_month
.
Plots look different but I don't know how to fix the colour scales:
plot.pacea_st(oisst_month_grid26, # being explicit about plot here, to help understanding year = 1981, month = 10)
Original:
plot.pacea_oi(oisst_month, year = 1981, month = 10)
Figures come out differently.
Figuring out ranges for colour bars, as done slightly differently in each function, but actually the global ranges are a bit different.
c(floor(min(st_drop_geometry(oisst_month_grid26))), ceiling(max(st_drop_geometry(oisst_month_grid26)))) # 3 19 c(floor(min(st_drop_geometry(oisst_month$sst))), ceiling(max(st_drop_geometry(oisst_month$sst)))) # 0 21
Makes sense that interpolated one covers a narrow range, but it also covers a smaller area.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.