Matching points to raster in different projections - raster

I'm mapping occurrence data for a species of interest to rasters of climate data from DAYMET, but I'm having trouble matching the points to the rasters.
Basically, I have a raster of daymet climate data (tmin) which has no projection when downloaded but is in Lambert conformal conic (https://daac.ornl.gov/DAYMET/guides/Daymet_mosaics.html), so I set the CRS:
#import daymet raster
tmin=raster("Tmin.tif")
#set projection for daymet data -> Lambert conformal
proj4string(tmin)<-CRS("+proj=lcc +lon_0=-100 +lat_0=42.5 +x_0=0 +y_0=0 +a=6378137 +rf=298.257223563 +lat_1=25 +lat_2=60")
And then I import the occurrence data which is in WGS84 lat/long(x,y), project, and transform to match tmin:
#import occurrences -> sp points
species<- read.csv("species_sites.csv", header=T)
coordinates(species)=~X+Y
#project occurences
projection(species) <- CRS("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0 ")
species <- spTransform(species, crs(tmin)) #transform to match daymet raster
The problem is they don't match when you plot together, and if you look at the extents they are off by a couple orders of magnitude:
> species
class : SpatialPointsDataFrame
features : 219
extent : 658883.2, 687373.3, 398524.3, 441106.2 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
variables : 3
names : Site, Species, Season
min values : 1, 0, -
max values : 219, 1, 2014
> tmin
class : RasterLayer
dimensions : 126, 138, 17388 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 591.25, 729.25, 355.5, 481.5 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=lcc +lon_0=-100 +lat_0=42.5 +x_0=0 +y_0=0 +a=6378137 +rf=298.257223563 +lat_1=25 +lat_2=60
names : Tmin
values : -9.410258, -7.011579 (min, max)
So I matched extents:
species#bbox<-as.matrix(extent(tmin))
but the points still don't match the raster. Not sure what else to do. Any suggestions or people with more detailed knowledge of the daymet data that might know whats going on?

Thanks #rar, figured that out last night...doh.
just needed to change CRS to:
CRS("+proj=lcc +lon_0=-100 +lat_0=42.5 +x_0=0 +y_0=0 +lat_1=25 +lat_2=60 +datum=WGS84 +units=km")

Related

Estimate grid cell area from satelite data using a Stereographic polar projection

I am trying to work with satelite data from polar regions. They can be download as .nc (netcdf, see below).
They are in polar stereographic projection in a regular grid (https://nsidc.org/data/polar-stereo/ps_grids.html).
I would like to estimate each cell area to calculate the area of ice cover by multiplying the fraction of ice cover in each cell with the area of the cell.
I am able to extract cell area using "area" from {raster} only when the uniform grid is in geographical coordinates (lat-lon). However I could not find any R function to do this when the grid is uniform in stereographic coordinates.
I am very new to spatial data and projections and perhaps I am missing something important.
Below some relevant information and a piece of code with two trials.
RELEVANT DATA AND INFORMATION SOURCES
Polar Watch
https://polarwatch.noaa.gov/erddap/
Sea Ice concentration data
url to downoald data
https://polarwatch.noaa.gov/erddap/griddap/nsidcCDRiceSQnhmday.nc?seaice_conc_monthly_cdr[(2019-12-16T00:00:00Z):1:(2019-12-16T00:00:00Z)][(5837500.0):1:(-5337500.0)][(-3837500.0):1:(3737500.0)]
Can be download in R using
url1<- "https://polarwatch.noaa.gov/erddap/griddap/nsidcCDRiceSQnhmday.nc?seaice_conc_monthly_cdr[(2019-12-16T00:00:00Z):1:(2019-12-16T00:00:00Z)][(5837500.0):1:(-5337500.0)][(-3837500.0):1:(3737500.0)]"
download.file(url1, destfile='nsidcCDRiceSQnhmday_935c_47bd_a147.nc')
Data for the grid
Sea Ice Concentration Lat-Lon Grid, NOAA/NSIDC Climate Data Record V3,
Antarctic, 25km
Dataset ID: nsidcCDRice_sh_grid
url
https://polarwatch.noaa.gov/erddap/griddap/nsidcCDRice_sh_grid.nc?latitude[(4337500.0):1:(-3937500.0)][(-3937500.0):1:(3937500.0)],longitude[(4337500.0):1:(-3937500.0)][(-3937500.0):1:(3937500.0)]
url2<- "https://polarwatch.noaa.gov/erddap/griddap/nsidcCDRice_sh_grid.nc?latitude[(4337500.0):1:(-3937500.0)][(-3937500.0):1:(3937500.0)],longitude[(4337500.0):1:(-3937500.0)][(-3937500.0):1:(3937500.0)]"
download.file(url2, destfile="nsidcCDRice_sh_grid_c513_9d75_76c1.nc")
https://nsidc.org/data/polar-stereo/ps_grids.html
Table 4. Southern Hemisphere Projection Based on WGS 1984
Latitude of True Origin -70
SOME R TRIALS
require(raster)
require(ncdf4)
br<-brick("nsidcCDRiceSQnhmday_935c_47bd_a147.nc")
projection(br)<- CRS("+init=epsg:3976 +proj=stere +lat_0=-90 +lat_ts=-70 +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs") #https://polarwatch.noaa.gov/tools-training/code-gallery/
br
res(br)
area(br)
which gives
Warning message:
In .local(x, ...) :
This function is only useful for Raster* objects with a longitude/latitude coordinates
Using the grid provided in the data sources
IceFgrid<-nc_open("nsidcCDRice_sh_grid_c513_9d75_76c1.nc")
ygridLatLon <- ncvar_get(IceFgrid, varid="ygrid")
xgridLatLon <- ncvar_get(IceFgrid, varid="xgrid")
longitude <- ncvar_get(IceFgrid, varid="longitude")
latitude <- ncvar_get(IceFgrid, varid="latitude")
nc_close(IceFgrid)
dim(longitude) # Matrix with Longitude of each grid point.
length(xgridLatLon)
length(ygridLatLon)
## Try to convert to data frame and the to raster.
dims <- dim(longitude)
icemap.df <- data.frame(Longitude=array(longitude,dims[1]*dims[2]),
Latitude=array(latitude,dims[1]*dims[2]))
icemap.df$Seaice <- array(1,dims[1]*dims[2])# Here I use 1 for ice cover just
rast<-rasterFromXYZ(icemap.df, crs="+proj=stere +lat_0=-90 +lat_ts=-70 +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m +no_defs")
But gives
Error in rasterFromXYZ(icemap.df, crs = "+proj=stere +lat_0=-90 +lat_ts=-70 +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m +no_defs") :
x cell sizes are not regular
Any help will be appreciated.
Thanks in advance
Angel
Here I use terra the replacement for raster
url1 <- "https://polarwatch.noaa.gov/erddap/griddap/nsidcCDRiceSQnhmday.nc?seaice_conc_monthly_cdr[(2019-12-16T00:00:00Z):1:(2019-12-16T00:00:00Z)][(5837500.0):1:(-5337500.0)][(-3837500.0):1:(3737500.0)]"
f <- 'nsidcCDRiceSQnhmday_935c_47bd_a147.nc'
download.file(url1, destfile='nsidcCDRiceSQnhmday_935c_47bd_a147.nc', mode="wb")
library(terra)
#terra version 1.3.4
r <- rast(f)
crs(r) <- "epsg:3976"
r
class : SpatRaster
dimensions : 448, 304, 1 (nrow, ncol, nlyr)
resolution : 25000, 25000 (x, y)
extent : -3850000, 3750000, -5350000, 5850000 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=stere +lat_0=-90 +lat_ts=-70 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs
source : nsidcCDRiceSQnhmday_935c_47bd_a147.nc
varname : seaice_conc_monthly_cdr (NOAA/NSIDC Climate Data Record of Passive Microwave Monthly Northern Hemisphere Sea Ice Concentration)
name : seaice_conc_monthly_cdr
unit : 1
time : 2019-12-16
As you can see, the nominal cell resolution is 25000 x 25000
res(r)
[1] 25000 25000
Because it is constant, raster does not want to compute it for you. But terra will give you either the naïve area (based on the constant the nominal resolution):
na <- cellSize(r, transform=FALSE)
minmax(na)
# area
#[1,] 6.25e+08
#[2,] 6.25e+08
Or the the true area. That is, accounting for distortion:
a <- cellSize(r, mask=F, unit="m", transform=TRUE)
a <- mask(a, r)
a
#class : SpatRaster
#dimensions : 448, 304, 1 (nrow, ncol, nlyr)
#resolution : 25000, 25000 (x, y)
#extent : -3850000, 3750000, -5350000, 5850000 (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=stere +lat_0=-90 +lat_ts=-70 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs
#source : memory
#name : area
#min value : 385538624
#max value : 664449196
#time : 2019-12-16
plot(a)
To get the sea-ice area in km2
x <- r * a / 1000000
global(x, "sum", na.rm=TRUE)
# sum
#_conc_monthly_cdr 11312232
The naïve estimate yields
n <- r * prod(res(r)) / 1000000
global(n, "sum", na.rm=TRUE)
# sum
#seaice_conc_monthly_cdr 11134025
That is about 1.5% lower
round(11134025 / 11312232, 3)
#[1] 0.984
This is not that different, because there is no ice at the edges, in the areas of severe distortion. And there is also some compensation in the central area (both smaller and larger areas) than 25*25 km2

Raster extent is no longer correct after using projectRaster in R

I have one elevation raster and one set of data points that I would like to be in the same projected coordinate system. When I use projectRaster, the extent of the layer becomes completely different and no longer lines up with the other data points.
dat <- read.csv(file = "ebd.csv")
elev <- raster("elev30mpa2.tif")
#Turning points into spatial object
ebdpoint <- st_as_sf(dat, coords=c("longitude","latitude"))
#Set coordinate system
ebdpoint <- st_set_crs(ebdpoint, "+proj=utm +zone=18 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")
> head(ebdpoint)
Simple feature collection with 6 features and 35 fields
geometry type: POINT
dimension: XY
bbox: xmin: -78.1582 ymin: 40.4502 xmax: -76.7758 ymax: 41.96633
CRS: +proj=utm +zone=18 +ellps=GRS80 +datum=NAD83 +units=m +no_defs
#This is the extent and CRS of the raster before projecting
> elev
class : RasterLayer
dimensions : 14412, 25212, 363355344 (nrow, ncol, ncell)
resolution : 0.0002777778, 0.0002777778 (x, y)
extent : -81.00167, -73.99833, 38.99833, 43.00167 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=NAD83 +no_defs
names : elev30mpa2
values : -86, 1332 (min, max)
#Project Raster
elev <- projectRaster(elev, crs = "+proj=utm +zone=18 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")
class : RasterLayer
dimensions : 15007, 25939, 389266573 (nrow, ncol, ncell)
resolution : 23.4, 30.8 (x, y)
extent : -20069.59, 586903, 4316447, 4778663 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=18 +datum=NAD83 +units=m +no_defs
names : elev30mpa2
values : -86, 1332 (min, max)
I desperately need my data to be in the same projected coordinate system. I am not sure if the issue has to do with the fact that it extends across 2 UTM zones (17 and 18) or because I am shifting the elevation layer from a geographic to projected coordinate system (I need it to be projected so I can use later functions in meters).

Crop raster with polygon in R: Error extent does not overlap

I want to crop a raster stack using a polygon shapefile i made in ArcGIS, however I get error that extent does not overlap.
First I create the raster stack:
test1 < stack("C:/mydir/test1.tif")
define projection
myCRS <- test1#crs
then read shapefile
myExtent <- readShapePoly("C:/mydir/loc1.shp", verbose=TRUE, proj4string=myCRS)
Crop
myCrop <- crop(test1, myExtent)
Error in .local(x, y, ...) : extents do not overlap
I have searched for a solution, but i only find that projection can be the problem, however they are definetly both in the same CRS:
> test1$test1.1
class : RasterLayer
band : 1 (of 4 bands)
dimensions : 10980, 10980, 120560400 (nrow, ncol, ncell)
resolution : 10, 10 (x, y)
extent : 6e+05, 709800, 5690220, 5800020 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=utm +zone=31 +datum=WGS84 +units=m +no_defs +ellps=WGS84
+towgs84=0,0,0
data source : C:\mydir\test1.tif
names : test1.1
values : 0, 65535 (min, max)
> myExtent
class : SpatialPolygonsDataFrame
features : 1
extent : 499386.6, 517068.2, 6840730, 6857271 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=utm +zone=31 +datum=WGS84 +units=m +no_defs +ellps=WGS84
+towgs84=0,0,0
variables : 2
names : Shape_Leng, Shape_Area
min values : 67444.6461177, 283926851.657
max values : 67444.6461177, 283926851.657
The message is pretty self explanatory. Your extent do not overlap... here how to check it:
library(raster)
ext.ras <- extent(6e+05, 709800, 5690220, 5800020)
ext.pol <- extent(499386.6, 517068.2, 6840730, 6857271)
plot(ext.ras, xlim = c( 499386.6,709800), ylim= c(5690220,6857271), col="red")
plot(ext.pol, add=T, col="blue")
I've created extent object from data in your question. You see one extent in the top left corner and the other in the bottom right. Have you tried reading both files in QGIS, you could probably easily see it.
If they really are suppose to overlap, than I would suspect the way you read your shapefile. Instead of
myExtent <- readShapePoly("C:/mydir/loc1.shp", verbose=TRUE, proj4string=myCRS)
use :
library(rgdal)
myExtent <- readOGR("C:/mydir","loc1.shp")
myExtent <- spTRansform(myExtent, CRS(proj4string(test1)))

Worldclim database is not working for random samples

I have a raster with a forest cover of one area
class : RasterLayer
dimensions : 5436, 2633, 14312988 (nrow, ncol, ncell)
resolution : 100, 100 (x, y)
extent : -109346.5, 153953.5, -290837.1, 252762.9 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=tmerc +lat_0=39.66825833333333 +lon_0=-8.133108333333334 +k=1 +x_0=0 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
data source : c://Total_Forest_cove
names : Total_Forest_cove
with values from 0 to 3 I want to create a dataset with random samples from the pixels with values higher than 0.
For that I do
library(dismo)
Forestcover[Forestcover < 1] <- NA
randompoints <- sampleRandom(Forestcover, size = 10, sp=TRUE, na.rm=TRUE)
plot(Forestcover, axes=FALSE, legend=FALSE)
randompoints <- coordinates(randompoints)
when I try to pull out the enviromental variables form worldclim
randpoints_wc <- extract(worldclim, randompoints)
randpoints_wc <- cbind(randompoints, randpoints_wc)
My dataset is always empty
Not sure if there is other method to extract random that can be apply here.
Regards
Your forest cover data set has a Mercator coordinate reference system
coord. ref. : +proj=tmerc
You do not show your WorldClim data, but presumably it has
coord. ref. : +proj=longlat
So, it is no surprise (and a good thing) that you get an empty result set. You can use rgadl::spTransform to make the coordinates match the raster.
For example:
fc <- reclassify(ForestCover, cbind(1, Inf, NA))
randompoints <- sampleRandom(fc, size = 10, sp=TRUE, na.rm=TRUE)
library(rgdal)
rp <- spTransform(randompoints, CRS("+proj=longlat +datum=WGS84"))
rp_wc <- extract(worldclim, rp)
rp_wc <- cbind(coordinates(randompoints), coordinates(rp), rp_wc)

R Assigning x or y coordinate to cells of a raster to perform calculations

Is there any solution to assign to assign X or Y coordinate to all of the cells of a raster image using R?
For example, suppose I have a raster with 3x3 cells. The lower left coordinate is X=7,Y=15 (in meters), and resolution is +10 m for both, X and Y direction (X increases rightward, and Y upward). Then, I would like to generate raster surfaces where each cell has the X and Y value, like these ones:
X raster
7 17 27
7 17 27
7 17 27
Y surface
35 35 35
25 25 25
15 15 15
UPDATE: this is the actual raster object.
Is there any way to do this?
I tried the package 'raster', but couldn't find a solution.
Any help would be appreciated.
This is the solution that I found, inspired in the comment submitted by #Carl.
Suppose my raster is called d, with these characteristics:
class : RasterLayer
dimensions : 59, 67, 3953 (nrow, ncol, ncell)
resolution : 90, 90 (x, y)
extent : 482855.6, 488885.6, 4763517, 4768827 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=tmerc +lat_0=0 +lon_0=-3 +k=1 +x_0=500000 +y_0=0 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : in memory
names : subset
values : 328, 1120 (min, max)
I first generated a matrix with the x coordinates values:
xm<-matrix(xFromCell(d,c(1:3953)),nrow=59,byrow=TRUE)
Then created a raster with the matrix:
x<-raster(xm,xmn=482855.6, xmx=488885.6,ymn=4763517,ymx=4768827)
And finally, assigned its projection:
projection(x)<-"+proj=tmerc +lat_0=0 +lon_0=-3 +k=1 +x_0=500000 +y_0=0 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0"
I also displayed the raster, to see if results where OK...
plot(x)
...and read the raster description
x
class : RasterLayer
dimensions : 59, 67, 3953 (nrow, ncol, ncell)
resolution : 90, 90 (x, y)
extent : 482855.6, 488885.6, 4763517, 4768827 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=tmerc +lat_0=0 +lon_0=-3 +k=1 +x_0=500000 +y_0=0 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : in memory
names : layer
values : 482900.6, 488840.6 (min, max)
I repeated these steps, but using yFromCell in the first step.

Resources