makeWeights.R 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. #' Extract Bit-Encoded Information and Create Weights Raster
  2. #'
  3. #' @description
  4. #' This function applies \code{\link{bitAnd}} and \code{\link{bitShiftR}}
  5. #' from \strong{bitops} to convert bit-encoded information. It is also possible
  6. #' to convert this information to a scale from 0 to 1 in order to use it as
  7. #' weighting information in functions like \code{\link{whittaker.raster}} or
  8. #' \code{\link{smooth.spline.raster}}.
  9. #'
  10. #' @param x \code{matrix}, vector or \code{Raster*} object.
  11. #' @param X \code{Raster*} object.
  12. #' @param bitShift \code{integer}. Bit starting point, see examples and
  13. #' \code{\link{detectBitInfo}}.
  14. #' @param bitMask \code{integer}. Bit mask size, see examples and
  15. #' \code{\link{detectBitInfo}}.
  16. #' @param threshold \code{integer}. Threshold for valid quality.
  17. #' @param filename \code{character} passed to \code{\link{writeRaster}}. If not
  18. #' specified, output is written to a temporary file.
  19. #' @param decodeOnly \code{logical}. If \code{FALSE} (default), convert bits to
  20. #' weights from 0 (not used) to 1 (best quality). If \code{TRUE}, only extract
  21. #' selected bits and convert to decimal system.
  22. #' @param keep If \code{NULL} (default), bits are only encoded, else an
  23. #' \code{integer} vector of values you want to keep (becomes \code{TRUE}), the
  24. #' rest becomes \code{NA}. See examples.
  25. #' @param datatype \code{character}. Output datatype, see
  26. #' \code{\link{writeRaster}}.
  27. #' @param ... Other arguments passed to \code{\link{writeRaster}}.
  28. #'
  29. #' @return
  30. #' A \code{Raster*} object.
  31. #'
  32. #' @note
  33. #' \code{\link{makeWeights}} and \code{\link{extractBits}} are identical with
  34. #' the only difference that \code{\link{makeWeights}} does additionally convert
  35. #' the data into weighting information.
  36. #'
  37. #' @seealso
  38. #' \code{\link{detectBitInfo}}.
  39. #'
  40. #' @author
  41. #' Matteo Mattiuzzi
  42. #'
  43. #' @examples
  44. #' \dontrun{
  45. #'
  46. #' # example MOD13Q1 see https://lpdaac.usgs.gov/products/modis_products_table/mod13q1
  47. #' # enter in Layers
  48. #' # See in TABLE 2: MOD13Q1 VI Quality
  49. #' # column 1 (bit) row 2 VI usefulness
  50. #' bitShift = 2
  51. #' bitMask = 15 # ('15' is the decimal of the binary '1111')
  52. #' # or try to use
  53. #' detectBitInfo("MOD13Q1") # not all products are available!
  54. #' viu <- detectBitInfo("MOD13Q1","VI usefulness") # not all products are available!
  55. #' viu
  56. #'
  57. #' # simulate bit info
  58. #' bit <- round(runif(10*10,1,65536))
  59. #'
  60. #' # extract from vector
  61. #' makeWeights(bit,bitShift,bitMask,decodeOnly=TRUE)
  62. #' # the same as
  63. #' extractBits(bit,bitShift,bitMask)
  64. #'
  65. #' # create a Raster object
  66. #' VIqual <- raster(ncol=10,nrow=10)
  67. #' VIqual[] <- bit
  68. #'
  69. #' # extract from Raster object
  70. #' a <- makeWeights(VIqual,bitShift,bitMask,decodeOnly=TRUE)
  71. #'
  72. #' # linear conversion of 0 (0000) to 15 (1111) to 1 fo 0
  73. #' b <- makeWeights(VIqual,bitShift,bitMask,decodeOnly=FALSE)
  74. #'
  75. #' threshold=6 # every thing < threshold becomes a weight = 0
  76. #' c <- makeWeights(VIqual,bitShift,bitMask,threshold,decodeOnly=FALSE)
  77. #'
  78. #' res <- round(cbind(a[],b[],c[]),2)
  79. #' colnames(res) <- c("ORIG","Weight","WeightThreshold")
  80. #' res
  81. #'
  82. #' #####
  83. #' # water mask
  84. #' tif = runGdal(product="MOD13A2",begin="2009001",end="2009001", extent=extent(c(-9,-3 ,54,58)),
  85. #' SDSstring="001",job="delme") # 6.4 MB
  86. #' x <- raster(unlist(tif))
  87. #'
  88. #' res1 <- maskWater(x)
  89. #' plot(res1)
  90. #'
  91. #' res2 <- maskWater(x,keep=1) # 1 = Land (nothing else)
  92. #' x11()
  93. #' plot(res2)
  94. #'
  95. #' # Land (Nothing else but land) + Ocean coastlines and lake shorelines + shallow inland Water,
  96. #' # the rest becomes NA
  97. #' x11()
  98. #' res3 <- maskWater(x,keep=c(1,2,3))
  99. #' plot(res3)
  100. #'
  101. #' ###############
  102. #'
  103. #' # as on Linux you can read HDF4 directly you can also do:
  104. #' if(.Platform$OS.type=="unix")
  105. #' {
  106. #' x <- getHdf(HdfName="MOD13A2.A2009001.h17v03.005.2009020044109.hdf", wait=0) # 6.4 MB
  107. #'
  108. #' detectBitInfo(x) # just info
  109. #' getSds(x) # just info
  110. #'
  111. #' x <- getSds(x)$SDS4gdal[3] # you need 'VI Quality'
  112. #' x <- raster(x)
  113. #' # plot(x)
  114. #' # ex <- drawExtent()
  115. #' ex <- extent(c(-580779,-200911,5974929,6529959))
  116. #' x <- crop(x,ex) # just for speed-up
  117. #'
  118. #' res1 <- maskWater(x)
  119. #' plot(res1)
  120. #'
  121. #' res2 <- maskWater(x,keep=1) # 1 = Land (Nothing else but land), the rest becomes NA
  122. #' x11()
  123. #' plot(res2)
  124. #'
  125. #' # Land (Nothing else but land) + Ocean coastlines and lake shorelines + shallow inland Water,
  126. #' # the rest becomes NA
  127. #' res3 <- maskWater(x,keep=c(1,2,3))
  128. #' x11()
  129. #' plot(res3)
  130. #' }
  131. #' }
  132. #'
  133. #' @describeIn makeWeights Extract bit-encoded information from \code{Raster*} file
  134. #' @aliases extractBits
  135. #' @export extractBits
  136. extractBits <- function(x, bitShift=2, bitMask=15, filename='',...)
  137. {
  138. if (inherits(x,"Raster"))
  139. {
  140. out <- brick(x, values=FALSE)
  141. if(nlayers(out)==1)
  142. {
  143. out <- raster(x)
  144. }
  145. out <- writeStart(out, filename=filename,...)
  146. tr <- blockSize(out)
  147. for (i in 1:tr$n)
  148. {
  149. v <- getValues(x, row=tr$row[i], nrows=tr$nrows[i])
  150. ve <- dim(v)
  151. v[v==0] <- NA
  152. # decode bits
  153. v <- bitAnd(bitShiftR(v, bitShift ), bitMask)
  154. v[is.na(v)] <- bitMask
  155. if (!is.null(ve))
  156. {
  157. v <- matrix(v,ncol=ve[2],nrow=ve[1],byrow=FALSE)
  158. }
  159. out <- writeValues(out, v, tr$row[i])
  160. }
  161. out <- writeStop(out)
  162. return(out)
  163. } else
  164. {
  165. ve <- dim(x)
  166. x[x==0] <- NA
  167. # decode bits
  168. x <- bitAnd(bitShiftR(x, bitShift ), bitMask)
  169. x[is.na(x)] <- bitMask
  170. if (!is.null(ve))
  171. {
  172. x <- matrix(x,ncol=ve[2],nrow=ve[1],byrow=FALSE)
  173. }
  174. return(x)
  175. }
  176. }
  177. #' @export makeWeights
  178. #' @name makeWeights
  179. makeWeights <- function(x, bitShift=2, bitMask=15, threshold=NULL, filename='', decodeOnly=FALSE,...)
  180. {
  181. if (inherits(x,"Raster"))
  182. {
  183. out <- brick(x, values=FALSE)
  184. if(nlayers(out)==1)
  185. {
  186. out <- raster(x)
  187. }
  188. out <- writeStart(out, filename=filename,...)
  189. tr <- blockSize(out)
  190. for (i in 1:tr$n)
  191. {
  192. v <- getValues(x, row=tr$row[i], nrows=tr$nrows[i])
  193. ve <- dim(v)
  194. v[v==0] <- NA
  195. # decode bits
  196. v <- bitAnd(bitShiftR(v, bitShift ), bitMask)
  197. v[is.na(v)] <- bitMask
  198. if (!is.null(threshold))
  199. {
  200. v[v > threshold] <- bitMask
  201. }
  202. if (!decodeOnly)
  203. {
  204. # turn up side down and scale bits for weighting
  205. v <- ((-1) * (v - bitMask))/bitMask
  206. v[v > 1] <- 1
  207. v[v < 0] <- 0
  208. }
  209. if (!is.null(ve))
  210. {
  211. v <- matrix(v,ncol=ve[2],nrow=ve[1],byrow=FALSE)
  212. }
  213. out <- writeValues(out, v, tr$row[i])
  214. }
  215. out <- writeStop(out)
  216. return(out)
  217. } else
  218. {
  219. ve <- dim(x)
  220. x[x==0] <- NA
  221. # decode bits
  222. x <- bitAnd(bitShiftR(x, bitShift ), bitMask)
  223. x[is.na(x)] <- bitMask
  224. if (!is.null(threshold))
  225. {
  226. x[x > threshold] <- bitMask
  227. }
  228. if (!decodeOnly)
  229. {
  230. # turn up side down and scale bits for weighting
  231. # theoretically best is 0 but the lowest value I have ever noticed is 1! So: (x-1)
  232. x <- ((-1) * (x - bitMask))/bitMask
  233. x[x > 1] <- 1
  234. x[x < 0] <- 0
  235. }
  236. if (!is.null(ve))
  237. {
  238. x <- matrix(x,ncol=ve[2],nrow=ve[1],byrow=FALSE)
  239. }
  240. return(x)
  241. }
  242. }
  243. ### maskWater (experimental)
  244. #' @describeIn makeWeights Masks water (additional information required)
  245. #' @aliases maskWater
  246. #' @export maskWater
  247. maskWater <- function(X, bitShift=NULL, bitMask = NULL, keep = NULL, datatype="INT1U",...)
  248. {
  249. if (!inherits(X,"Raster"))
  250. {
  251. stop("'maskWater' requires a raster* object")
  252. }
  253. if (is.null(bitShift) | is.null(bitMask))
  254. {
  255. cat("'bitShift', 'bitMask' not defined, trying to autodetect 'Land/Water Flag'!...\n")
  256. fname <- basename(names(X)[1])
  257. prodinfo <- strsplit(fname,"\\.")[[1]][1]
  258. bits <- detectBitInfo(prodinfo, what='Land/Water Flag',warn=FALSE)
  259. bitShift <- bits$bitShift
  260. bitMask <- bits$bitMask
  261. if(is.null(bits))
  262. {
  263. stop(paste("No 'Land/Water Flag' found, please set 'bitShift', 'bitMask' manualy. See: https://lpdaac.usgs.gov/products/modis_products_table/",tolower(prodinfo),sep=""))
  264. } else
  265. {
  266. message("Ok 'Land/Water Flag' found!")
  267. }
  268. }
  269. result <- extractBits(X, bitShift = bitShift, bitMask = bitMask,...)
  270. if (!is.null(keep))
  271. {
  272. eval(parse(text=paste("result <- result %in% ", paste0("c(",paste(keep,collapse=","),")"))))
  273. NAvalue(result) <- 0
  274. }
  275. return(result)
  276. }