-1

I need to create a function to interpolate noise values on a landsat image time series by the mean on a time span of 2 (xt+1 and xt-1).

I´m using the fmask product to detect cloud and shadow, then interpolation is applied.

For one time series:

Since c2 is the vector of fmask time series (2 for cloud and 4 for shadow), and t2 the vector of evi time series:

    for (i in 2:(length(t2)-1)){ 
         if (c2[i]==2 | c2[i]==4) 
         t2[i]<-mean(c(t2[i-1], t2[i+1]))}

But it is not possible to do this using the calc function of raster package, because it does not works with functions with 2 parameters.

Any suggestion about how to deal with this and apply this interpolation for all the pixels of the raster time series?

I´m trying this, but it is still not working:

for (i in 2:(length(stacklist)-1)){ 
re<-raster(stacklist[i]) 
re1<-raster(stacklist[i+1]) 
re0<-raster(stacklist[i-1]) 
rc<-raster(stacklist2[i]) 
if (rc[i]==2 | rc[i]==4) re[i]<-mean(c(re0[i],re1[i])) 
writeRaster(re,filename =paste0(substr(stacklist[i], 48, 59),"_filtered.tif"))}  
Bindini
  • 189
  • 10
  • In your first block of code, is `t2` a RasterStack and you want to compute per-cell (per pixel) `mean` between the `i-1` layer and the `i+1`layer under the condition of cloud or shadow? What if there is no cloud and no shadow for a pixel? What gets output? – aichao Aug 08 '16 at 15:58
  • @aichao, actually t2 is one pixel time series of a rasterstack. The idea it is to apply that function for all the pixels time series. If there is no cloud and shadow, the value must be the same as the original. – Bindini Aug 08 '16 at 16:13
  • OK, I'm trying to think in terms of the input to `raster::calc`. In that case, `t2` is the `RasterStack` (stack of images in time) and you want to perform the function in your first block of code for each pixel in the `RasterStack`. If this is correct, to you really want such a "rolling" mean in which you overwrite `t2[i]` as you go down the stack? – aichao Aug 08 '16 at 17:16
  • Yes, but I think that is not possible to use calc function, because I will need to parameters. So, I´m trying this, but it is still not working (error in the line of condition): for (i in 2:(length(stacklist)-1)){ re<-raster(stacklist[i]) re1<-raster(stacklist[i+1]) re0<-raster(stacklist[i-1]) rc<-raster(stacklist2[i]) rm<-mean(re0,re1) if(isTRUE(rc[rc==2 | rc==4])) re[(rc==2) | (rc==4)]<-rm[rc[rc==2 | rc==4]] writeRaster(re,filename =paste0(substr(stacklist[i], 80, 86),"_filtered.tif"), overwrite=TRUE)} – Bindini Aug 08 '16 at 20:36
  • see if my answer fits your needs. – aichao Aug 08 '16 at 20:46

1 Answers1

0

I believe the following will meet your needs. I'm assuming:

  1. Each image in time is a raster. These are placed in a RasterStack named t2.stack ordered in increasing time. The image at the i-th time period in the stack is referenced by t2.stack[[i]].
  2. For each image in time there is an fmask. This allows for different fmasks for different times (although they can also all be the same). These are placed in a RasterStack named c2.stack. These are correspondingly ordered in time as t2.stack. The fmask at the i-th time period in the stack is referenced by c2.stack[[i]].
  3. All rasters (both images and fmasks) are of the same size (same number of rows, columns, and therefore, pixels).

We first simulate some data to illustrate:

library(raster)
set.seed(42)     ## This is for repeatable results

## Simulate some stacks of rasters over a time period [1,nT=3], yours will be longer
## 1. Each raster is 10 x 10, yours will be larger
## 2. Each c2 raster contains integers uniformly distributed in [0, 5]
## 3. Each t2 raster contains reals unformly distributed in [0,1]
## 4. c2.stack is a stack of c2 rasters over time period, c2.raster[[i]] is c2 at time i
## 5. t2.stack is a stack of t2 rasters over time period, t2.raster[[i]] is t2 at time i
nT <- 3
c2 <- raster(ncol=10, nrow=10)                  
c2[] <- floor(runif(ncell(c2), min=1, max=6))   
c2.stack <- stack(x=c2)
for (i in 2:nT) {
  c2[] <- floor(runif(ncell(c2), min=1, max=6))
  c2.stack <- addLayer(c2.stack, c2)
}

t2 <- raster(ncol=10, nrow=10)
t2[] <- runif(ncell(t2), min=0, max=1)
t2.stack <- stack(x=t2)
for (i in 2:nT) {
  t2[] <- runif(ncell(t2), min=0, max=1)
  t2.stack <- addLayer(t2.stack, t2)
}

## Here is the t2.stack data
print(head(t2.stack[[1]]))
##            1           2          3          4          5          6          7         8          9         10
##1  0.48376814 0.444569528 0.06038559 0.32750602 0.87842905 0.93060489 0.39217846 0.1588468 0.31994760 0.30696562
##2  0.10781125 0.979334303 0.49690343 0.09307467 0.21177366 0.93050075 0.29684641 0.6532182 0.90107048 0.99079579
##3  0.43033322 0.393776922 0.14190890 0.27980670 0.56482222 0.93513951 0.35840015 0.8420072 0.72240921 0.75073599
##4  0.92398845 0.002378107 0.16042991 0.39927295 0.67531958 0.48037202 0.53382878 0.3169502 0.81475759 0.29221952
##5  0.40913209 0.090918308 0.79859664 0.35978525 0.04048758 0.04108634 0.95443424 0.3733412 0.80641967 0.91005901
##6  0.44007621 0.576336503 0.07366780 0.16462739 0.73989078 0.47571101 0.68552095 0.9515149 0.49746449 0.47050063
##7  0.56019195 0.652510121 0.27957350 0.97990759 0.64386411 0.58257844 0.61587103 0.9251403 0.39002290 0.28791969
##8  0.09073596 0.322033904 0.75827011 0.10441293 0.71027785 0.96647738 0.20149123 0.1084887 0.05540218 0.82972352
##9  0.58119776 0.470092375 0.36501412 0.28012463 0.59971585 0.81856961 0.09783228 0.9636895 0.16873644 0.08608341
##10 0.86121070 0.524790602 0.65681088 0.22951937 0.72122603 0.49075039 0.96525559 0.9069425 0.55125053 0.07559910

print(head(t2.stack[[2]]))
##        1           2         3          4         5          6         7         8          9         10
##1  0.02270001 0.513239528 0.6307262 0.41877162 0.8792659 0.10798707 0.9802787 0.2649666 0.08427752 0.38590718
##2  0.12489583 0.581554222 0.2401496 0.72188789 0.1459287 0.15283877 0.2592227 0.7778863 0.42646630 0.06004834
##3  0.11483254 0.482756897 0.9791736 0.81151679 0.5429128 0.07236709 0.4664852 0.3399056 0.68991861 0.51415737
##4  0.51492302 0.545514354 0.4474573 0.08388484 0.9301337 0.01644819 0.4140924 0.2269761 0.09964059 0.48292388
##5  0.65012867 0.921329778 0.3626018 0.85513499 0.3009062 0.46566243 0.1427307 0.8077190 0.66580763 0.06194098
##6  0.43092557 0.396855081 0.6969568 0.65931965 0.4073507 0.30692022 0.2551073 0.6725682 0.89439343 0.84573616
##7  0.39290186 0.079050540 0.8284231 0.07289182 0.1147627 0.63998427 0.3205662 0.1887495 0.39382964 0.86202602
##8  0.34791141 0.001433898 0.9112845 0.95172345 0.4909190 0.46365172 0.5964720 0.9060510 0.17300118 0.78588108
##9  0.23293438 0.577048209 0.8408770 0.13220378 0.8958912 0.45013734 0.8941425 0.2485452 0.08369529 0.04864107
##10 0.97981587 0.484167741 0.8453930 0.41629360 0.4893425 0.18328782 0.7591615 0.3051433 0.16567825 0.03280914

print(head(t2.stack[[3]]))
##           1         2          3            4         5          6           7          8         9        10
##1  0.1365052 0.1771364 0.51956045 0.8111207851 0.1153620 0.89342179 0.575352881 0.14657239 0.9028058 0.2530025
##2  0.1505976 0.7685472 0.23012333 0.3053993280 0.5185696 0.33459967 0.154434968 0.26636957 0.3507546 0.5784584
##3  0.8086018 0.9332703 0.83386334 0.1270027745 0.6494540 0.69035166 0.032044824 0.92048915 0.4784689 0.2665206
##4  0.8565107 0.2291465 0.79194687 0.6467748603 0.4243347 0.09506827 0.003467704 0.53113367 0.5243071 0.2131856
##5  0.7169321 0.9613436 0.51826660 0.1745280223 0.5625401 0.75925817 0.666971338 0.22487292 0.3458498 0.3198318
##6  0.9048984 0.1991984 0.68096302 0.1375177586 0.1069947 0.09285940 0.916448955 0.27706044 0.8857939 0.7728646
##7  0.7950512 0.2056736 0.04819332 0.0388159312 0.2845741 0.34880983 0.737453325 0.25166358 0.5174370 0.7594447
##8  0.6360845 0.2039407 0.99304528 0.0004050434 0.2065700 0.63402809 0.017291825 0.02673547 0.6078406 0.5705414
##9  0.2458533 0.9195251 0.67221620 0.6454504393 0.2082855 0.48061774 0.986518583 0.99311985 0.4507740 0.7148488
##10 0.3165616 0.8336876 0.43397558 0.9959922582 0.8058112 0.48624217 0.538772001 0.34103991 0.0520156 0.4587231

## and the fmask product at time 2 (c2.stack[[2]])
print(head(c2.stack[[2]]))
##   1 2 3 4 5 6 7 8 9 10
##1  4 2 2 2 5 5 4 4 3  1
##2  4 5 4 3 3 3 1 2 4  5
##3  2 3 3 3 4 2 5 5 2  4
##4  5 4 4 5 5 3 5 1 4  4
##5  1 1 3 4 4 5 1 5 2  1
##6  4 2 4 2 4 4 1 1 1  4
##7  5 3 4 1 3 1 3 2 1  1
##8  4 3 3 3 3 1 5 3 4  4
##9  5 5 2 2 4 4 5 4 1  2
##10 1 4 1 1 1 1 3 1 4  4

## Make a copy of the t2.stack so that we can compare results using overlay later
t3.stack <- t2.stack

The key to the processing is to use masks in place of the conditional statement. The code is as follows:

for (i in 2:(nlayers(t2.stack)-1)) { 
  cloud.shadow.mask <- (c2.stack[[i]]==2 | c2.stack[[i]]==4)
  the.mean <- mask((t2.stack[[i-1]] + t2.stack[[i+1]])/2, cloud.shadow.mask, 
           maskvalue=FALSE, updatevalue=0.)
  the.middle <- mask(t2.stack[[i]], cloud.shadow.mask, 
         maskvalue=TRUE, updatevalue=0.)
  t2.stack[[i]] <- the.mean + the.middle
}

Notes:

  1. cloud.shadow.mask is a raster that is TRUE when there is cloud or shadow at the pixel and false otherwise.
  2. Use mask on the raster that is the mean between t2.stack[[i-1]] and t2.stack[[i+1]] to set those pixels for which cloud.shadow.mask is FALSE to zero.
  3. Conversely, mask the raster t2.stack[[i]] to set those pixels for which cloud.shadow.mask is TRUE to zero.
  4. Then add these two rasters to update t2.stack[[i]].

Here is the result for nT=3 where only t2.stack[[2]] is computed:

print(head(t2.stack[[2]]))
##           1           2         3          4         5          6         7         8          9         10
##1  0.3101367 0.310852970 0.2899730 0.56931340 0.8792659 0.10798707 0.4837657 0.1527096 0.08427752 0.38590718
##2  0.1292044 0.581554222 0.3635134 0.72188789 0.1459287 0.15283877 0.2592227 0.4597939 0.62591255 0.06004834
##3  0.6194675 0.482756897 0.9791736 0.81151679 0.6071381 0.81274558 0.4664852 0.3399056 0.60043905 0.50862828
##4  0.5149230 0.115762292 0.4761884 0.08388484 0.9301337 0.01644819 0.4140924 0.2269761 0.66953235 0.25270254
##5  0.6501287 0.921329778 0.3626018 0.26715664 0.3015139 0.46566243 0.1427307 0.8077190 0.57613471 0.06194098
##6  0.6724873 0.387767442 0.3773154 0.15107258 0.4234427 0.28428520 0.2551073 0.6725682 0.89439343 0.62168264
##7  0.3929019 0.079050540 0.1638834 0.07289182 0.1147627 0.63998427 0.3205662 0.5884019 0.39382964 0.86202602
##8  0.3634102 0.001433898 0.9112845 0.95172345 0.4909190 0.46365172 0.5964720 0.9060510 0.33162139 0.70013243
##9  0.2329344 0.577048209 0.5186152 0.46278753 0.4040007 0.64959367 0.8941425 0.9784047 0.08369529 0.40046610
##10 0.9798159 0.679239081 0.8453930 0.41629360 0.4893425 0.18328782 0.7591615 0.3051433 0.30163307 0.26716111

For large images that may not fit into memory, use overlay instead of calc for efficiency. Here we repeat the computation using the original t2.stack that was copied to t3.stack

for (i in 2:(nlayers(t3.stack)-1)) { 
  cloud.shadow.mask <- overlay(c2.stack[[i]], fun = function(x) x == 2 | x == 4)
  the.mean <- overlay(t3.stack[[i-1]], t3.stack[[i+1]], fun = function(x,y) (x+y)/2)
  the.mean <- mask(the.mean, cloud.shadow.mask, maskvalue=FALSE, updatevalue=0.)
  the.middle <- mask(t3.stack[[i]], cloud.shadow.mask, maskvalue=TRUE, updatevalue=0.)
  t3.stack[[i]] <- overlay(the.mean, the.middle, fun=sum)
}

The results are the same.

print(all.equal(t2.stack[[2]],t3.stack[[2]]))
##[1] TRUE
aichao
  • 7,375
  • 3
  • 16
  • 18
  • Very useful tips! Thanks! I have done like this, and it also works: for (i in 2:(length(stacklist)-1)){ re<-raster(stacklist[i]) re1<-raster(stacklist[i+1]) re0<-raster(stacklist[i-1]) rc<-raster(stacklist2[i]) rm<-mean(re0,re1) re[which(rc[]==2 | rc[]==4)]<-rm[which(rc[]==2 | rc[]==4)] writeRaster(re,filename =paste0(substr(stacklist[i], 80, 86),"_filtered.tif"), overwrite=TRUE)} – Bindini Aug 08 '16 at 21:59
  • @HugoBendini: If you like your own answer better, please consider writing it as another answer, instead of inline of a comment, so that others can readily see it, and then accept that answer. Otherwise, if you find my answer useful, please consider accepting it so as to help close the question. – aichao Aug 10 '16 at 11:17