How can I find the pixel-wise maximum of multiple rasters? - r

I have hundreds of rasters with same resolution and extent. It's a time series and each raster represent one point of time.
I know how to find the absolute maximum value in a raster.
But how can I find the maximum value in each cell in the entire time series of rasters?
If a1,a2,......a1000 are rasters, I want to create a raster x where each pixel is the maximum of all corresponding pixels of a1-a1000.

If you first put the rasters in a stack, you can then simply apply min() or max() to the stack to get the summary RasterLayer you're after
## Example rasters and stack
r1 <- raster(matrix(1:4,ncol=4))
r2 <- -2*r1
r3 <- 2*r1
rr <- list(r1,r2,r3)
s <- stack(rr)
## Extract the pixel-wise min and max values
min(s)
max(s)
(To apply some other, more complicated function that returns a scalar for each pixel in the stack, you may want to use calc(), as demonstrated (for example) here.)

Related

R - How exactly does resampling work with "bilinear interpolation" with different cell sizes?

When using the raster package, are resample's or projectRaster's bilinear interpolation always taking the four nearest centroids, or does it account for differences in cell sizes?
In the explanation for bilinear interpolation in resampling found at http://desktop.arcgis.com/en/arcmap/latest/extensions/spatial-analyst/performing-analysis/cell-size-and-resampling-in-analysis.htm, it says the four nearest centroids are used. In the example here, the cell sizes are similar. This explanation is not directly for the raster package in R, but it appeared to be the most accessible explanation for how bilinear interpolation might work in these cases.
Are a different amount of centroids used when the cell sizes differ by more than a factor of 2 in either (or both) dimensions?
For example, here is a raster with a higher resolution than what it is going to be resampled to:
library(raster)
R1 <- raster(resolution = 13, vals = sample(x = 1:5, size = 392, replace = TRUE))
plot(R1)
High Resolution Raster
Created here is the raster to be projectRaster to, and then R1 after projectRaster to match the new raster:
R2 <- raster(resolution = 50)
R3 <- projectRaster(from = R1, to = R2, method = "bilinear")
plot(R3)
New Low Resolution Raster
Which cells from the high resolution raster are being taken into consideration when projectRaster is being used to create the fewer, larger cells? Since the cells in the high resolution raster are more than four times as small as the cells in the low resolution one, if bilinear interpolation just used the four closest centroids, it may not be as accurately representative as it could be if more cells were taken into consideration.
Prior to the actual resampling with bilinear interpolation, the raster package first aggregates the values to create cells with an approximately equal resolution as the target. It is from this aggregated raster that the four cells are taken.
This is not done with projectRaster. Tis will be added in a future version, but for now you could first aggregate the input data yourself.

R raster: extent conditional on cell value

I would like to obtain the extent of raster layer conditional on certain cell values. Consider the following example:
raster1 is a large raster object, filled with values between 1 and 1000. However, I only want to obtain the extent for pixels with value 100. Since this subset of cells should crowd in a small region, the extent should be rather narrow. Once I know the coordinates of that box, I can crop this minor area.
My approach so far is to replace all values != 100 with NA - as suggested in related questions. Considering the raster object's overall size, this step takes an enormous amount of time and invests a lot of computational capacity in regions that I would like to crop anyways.
Does anyone know how to obtain the extent conditional on a certain pixel value which does not require to reclassify the entire object beforehand?
Here is an alternative way to do that
Example data:
library(raster)
r <- raster(ncol=18,nrow=18)
values(r) <- 1
r[39:45] <- 100
r[113:115] <- 100
r[200] <- 100
"Standard" way:
x <- r == 100
s <- trim(x, values=FALSE)
Alternate route by creating an extent:
xy <- rasterToPoints(r, function(x){ x ==100 })
e <- extent(xy[,1:2])
e <- alignExtent(e, r, snap='out')
v <- crop(r, e)
Either way, all cells need to be looked at, but at least you do not need to create another large raster.

R understanding raster's corLocal neighborhood size parameter

I am calculating the Pearson correlation between two rasters (identical in dimensions and cell size) in a moving window with the corLocal from the raster package. It is not clear (to me) from the manual what the neighborhood size parameter (ngb) actually means. E.g., does a ngb = 5 mean that the correlation is calculated for the focal cell plus the top-bottom-right-left cells?
I looked at the code and corLocal calls getValuesFocal():
getValuesFocal(x, 1, nrow(x), ngb=ngb)
but I couldn't understand what getValuesFocal actually does.
Thanks,
Ilik
The ngb parameter defines the neighborhood size. For example, I believe ngb=5 defines a 5 x 5 neighborhood. This should be equivalent to ngb=c(5,5) which is a vector of two integers defining the numbers of rows and cols in the neighborhood or focal window. In this example, an individual cell in the output raster would represent the correlation calculated from a 5 x 5 cell neighborhood in the two input rasters.
The raster library documentation on p. 118 might help too.

DistanceFromPoints with multiple XY coordinates

I'm trying to use distanceFromPoints function in raster package as:
distanceFromPoints(object,xy,...)
Where, object is raster and xy is matrix of x and y coordinates
Now, if my raster has, for example, 1000 cells and xy represents one point, I get 1000 values representing distances between xy and each raster cell. my problem is when xy has multiple coordinates, e.g., 10 points. the function description indicates that xy can be multiple points but when I run this function with multiple XY points, I still get only 1000 values while I'm expecting 1000 values for each coordinate in XY. How does this work?
Thanks!
using distanceFromPoints on multiple points gives a single value for each raster cell, which is the distance to the nearest point to that cell.
To create raster layers giving the distance to each point separately, you can use apply
a reproducible example:
r = raster(matrix(nrow = 10, ncol = 10))
p = data.frame(x=runif(5), y=runif(5))
dp = apply(p, 1, function(p) distanceFromPoints(r,p))
This gives a list of raster layers, each having the distance to one point
# for example, 1st raster in the list has the distance to the 1st point
plot(dp[[1]])
points(p[1,])
For convenience, you can convert this list into a raster stack
st = stack(dp)
plot(st)
A final word of caution:
It should be noted that the raster objects thus created do not really contain any more information than the list of points from which they are generated. As such, they are a computationally- and memory-expensive way to store that information. I can't easily think of any situation in which this would be a sensible way to solve a specific question. Therefore, it may be worth thinking again about the reasons you want these raster layers, and asking whether there may be a more efficient way to solve you overall problem.

Fitting a line to an image

I am trying to fit a line to an image based on the intensity (or color) of the pixels. The figure below shows a typical test image in panel 1 with a line manually drawn in panel 2. The test image (matrix) can be downloaded here: .RData from dropbox .
I would like to use a regression analysis to produce something similar to the manually drawn line in panel 2. However, I can not use a simple linear regression because, as with all images, there are errors in both the x and y axes.
I am open to algorithm descriptions with relevant equations, links, etc... and not necessarily code that I can copy and paste.
METHODS I WANT TO AVOID
Correlating a series synthetic binary images of pixels drawn at various slopes with the actual data image. For example the correlation of the two images below would be quite good, but again, I want to avoid this method.
Using a skeletonization algorithm to reduce the image such that a simple linear regression can be used.
Seismologists, interestingly enough, deal with similar problems where they correct reflection data based on the distance between a seismic source and a receiver with a process known as normal move out (Normal Moveout). I used a similar process.
The general algorithm is:
load in the image
define a series of slopes to investigate
define a window length that is < number of image columns
loop over the series of slopes and...
define index locations (x,y) over the image based on the slope and the size of the window (gray points in row one of image below).
build a matrix from those original matrix indexed at the x,y locations from above (plots in row two of image below).
sum the matrix then normalize the sum by dividing by the length of the summed matrix.
save the each sum (there will be 1 sum for every velocity you loop over)
The velocity vector corresponding to the max (or min) index of the sum vector is the best slope/velocity of the image at that current pixel column (row three in image below).
Perform the above steps along the columns of the image.
The algorithm is visually described in the image below.
The code to perform the above procedure is on one column of the test data given in the question is:
load('test.RData')
## INPUTS ##
img=test
vel.min=1 ## minimum velocity (or slope) to test
vel.max=20 ## max velocity to test
vel.number=100 ## how many velocities to test
win=10 ## size of window to investigate
## define a time index
ti=nrow(img)/2
## set up a vector to hold the velocity correlation values
vel.corrs <- rep(NA,vel.number)
## define the set of velocities to search over
vels <- seq(vel.min,vel.max,length.out=vel.number)
## define a velocity index
vi=1
while(vi<=length(vels)) {
## build a binary matrix with corresponding to the window and velocity
bin.mat <- matrix(0,ncol=ncol(img),nrow=nrow(img))
slope.line <- seq(0,ncol(bin.mat)/vels[vi],length.out=ncol(bin.mat))
bin.mat[(ti-win/2):(ti+win/2),]=1
## define the offeset
offset <- rep(slope.line,each=win+1)
## define the indices of array points according to velocity and window
win.vel.ind <- cbind(which(bin.mat==1,arr.ind=TRUE)[,1]+offset,which(bin.mat==1,arr.ind=TRUE)[,2])
## limit the points to the dimensions of the image
if(any(floor(win.vel.ind[,1]) > nrow(img))){
win.vel.ind[(which(floor(win.vel.ind[,1])>nrow(img))),]=NA
##win.vel.ind <- win.vel.ind[-(which(floor(win.vel.ind[,1])>nrow(img))),]
}
## pluck the values of the image associated with those non-NA indices
slice <- img[win.vel.ind]
## build a matrix of the slice vector with nrow=win+1
slice.mat <- matrix(slice,nrow=win+1,ncol=ncol(img),byrow=FALSE)
## apply a hamming window
##ham.mat <- matrix(hamming(win+1),ncol=ncol(slice.mat),nrow=nrow(slice.mat))
##slice.ham <- slice.mat*ham.mat
## sum this 'slice' and normalize and store
vel.corrs[vi] <- sum(slice,na.rm=TRUE)/length(na.omit(slice))
vi=vi+1
}

Resources