stars_proxy objects

Created on 29 Aug 2018  路  22Comments  路  Source: r-spatial/stars

Brought up by @adrfantini in #48.

This is a first and very rough shot at proxy objects in stars. They contain only the dimension table and a pointer to the data (now: the file name, we could add the GDALDataset pointer if this helps perfomance-wise). Based on this we can do subsetting, cropping, and thinning; only when we plot those cells that we can see as pixels are read. The speedup for an Sentinel-2 image (4 10-m bands, 10000 x 10000) over complete reading and thinning in memory is a factor 100 or so (at thinning factor 43).

library(stars)
# Loading required package: abind
# Loading required package: sf
# Linking to GEOS 3.6.2, GDAL 2.2.3, proj.4 4.9.3

tif = system.file("tif/L7_ETMs.tif", package = "stars")
s2 = "SENTINEL2_L1C:/vsizip/S2A_MSIL1C_20180220T105051_N0206_R051_T32ULE_20180221T134037.zip/S2A_MSIL1C_20180220T105051_N0206_R051_T32ULE_20180221T134037.SAFE/MTD_MSIL1C.xml:10m:EPSG_32632"

p = read_stars(s2, proxy = TRUE)
p
# stars_proxy object with 1 attribute in file:
# $`MTD_MSIL1C.xml:10m:EPSG_32632`
# [1] "SENTINEL2_L1C:/vsizip/S2A_MSIL1C_20180220T105051_N0206_R051_T32ULE_20180221T134037.zip/S2A_MSIL1C_20180220T105051_N0206_R051_T32ULE_20180221T134037.SAFE/MTD_MSIL1C.xml:10m:EPSG_32632"

# dimension(s):
#       from    to offset delta                       refsys point values
# x        1 10980  3e+05    10 +proj=utm +zone=32 +datum...    NA   NULL
# y        1 10980  6e+06   -10 +proj=utm +zone=32 +datum...    NA   NULL
# bands    1     4     NA    NA                           NA    NA   NULL
st_crs(p)
# Coordinate Reference System:
#   EPSG: 32632 
#   proj4string: "+proj=utm +zone=32 +datum=WGS84 +units=m +no_defs"
st_dimensions(p)
#       from    to offset delta                       refsys point values
# x        1 10980  3e+05    10 +proj=utm +zone=32 +datum...    NA   NULL
# y        1 10980  6e+06   -10 +proj=utm +zone=32 +datum...    NA   NULL
# bands    1     4     NA    NA                           NA    NA   NULL

#p2 = p[,1:4000, 40:4060,]
p2 = p

stars:::get_downsample(dim(p2))
# [1] 43
png("s2.png", 1000, 1000)
system.time(plot(p2, rgb = 2:4))
#    user  system elapsed 
#   0.970   0.208   0.942 
system.time(plot(read_stars(s2), rgb = 2:4))
#    user  system elapsed 
#  82.905   5.385  36.679 

s2

All 22 comments

The idea is that when we do for instance an st_apply, we can choose a read-write strategy to go through the array without completely reading, or keeping complete results, in memory.

Lazy evaluation means that an st_apply call would do nothing, only when we plot we would carry out the functions for those pixels shown, only when we do a write / download call would the st_apply be carried out to all the cells.

I did not test yet and can't do so until monday, but this looks spot on. Does this already work with stars objects which are collages of multiple files?

I think not.

This now works with e.g. multiple netcdf files forming a time series, but not with spatial collages (mosaics?) of files; maybe GDAL VRT is the way to go here, if we work from disk?

See here for a new vignette showcasing the proxy objects, @mdsumner - comments very welcome, planning to do an r-spatial blog in this soon, and then make remote objects work over http connections (with R on both sides).

The vignette is now runnable if you download starsdata, a 1 Gb package in my drat repo (instructions in vignette).

Ah, I also interfaced the GDAL resampling methods; see vignette.

@appelmar

Thanks! Awesome to have starsdata too

Yes, and I'd be happy to add examples to that. Too bad it doesn't fit on github, with those bulky files (although, TBH I didn't try, so far).

Might be an idea to bump sf and depend on the version? It caught me out briefly so may affect other early adopters

I just noted that I hadn't committed my latest sf changes to github, you have to reinstall it once more. I now bumped the sf version, and required version of sf by stars.

Stars happily reads in full and plots a 25m Tasmania DEM in less than 30s fwiw ;)

Did you read in the foll dataset first, or plot the proxy object? I wonder because the S2 image took 1s to plot.

Oh I meant full, before I realized my sf was old - I know the proxy will be instant!

On Windows I see a problem, I can't even find where that "extent" code occurs? On Ubuntu all is well :)

library(stars)
tif = system.file("tif/L7_ETMs.tif", package = "stars")
rasterio = list(nXOff = 6, nYOff = 6, nXSize = 100, nYSize = 100, bands = c(1,3,4))
(x = read_stars(tif, RasterIO = rasterio))

Error in CPL_read_gdal(as.character(x), as.character(options), as.character(driver),  : 
  Expecting a single value: [extent=0].

session_info fwiw

Session info ------------------------------------------------------------------------------------------------------------------------
 setting  value                                      
 version  R version 3.5.1 Patched (2018-08-31 r75224)
 system   x86_64, mingw32                            
 ui       RStudio (1.1.456)                          
 language (EN)                                       
 collate  English_Australia.1252                     
 tz       Australia/Hobart                           
 date     2018-09-11                                 

Packages ----------------------------------------------------------------------------------------------------------------------------
 package    * version date       source                       
 abind      * 1.4-5   2016-07-21 CRAN (R 3.5.0)               
 assertthat   0.2.0   2017-04-11 CRAN (R 3.5.1)               
 base       * 3.5.1   2018-09-02 local                        
 bindr        0.1.1   2018-03-13 CRAN (R 3.5.1)               
 bindrcpp     0.2.2   2018-03-29 CRAN (R 3.5.1)               
 class        7.3-14  2015-08-30 CRAN (R 3.5.1)               
 classInt     0.2-3   2018-04-16 CRAN (R 3.5.1)               
 compiler     3.5.1   2018-09-02 local                        
 crayon       1.3.4   2017-09-16 CRAN (R 3.5.1)               
 datasets   * 3.5.1   2018-09-02 local                        
 DBI          1.0.0   2018-05-02 CRAN (R 3.5.1)               
 devtools     1.13.6  2018-06-27 CRAN (R 3.5.1)               
 digest       0.6.16  2018-08-22 CRAN (R 3.5.1)               
 dplyr        0.7.6   2018-06-29 CRAN (R 3.5.1)               
 e1071        1.7-0   2018-07-28 CRAN (R 3.5.1)               
 glue         1.3.0   2018-07-17 CRAN (R 3.5.1)               
 graphics   * 3.5.1   2018-09-02 local                        
 grDevices  * 3.5.1   2018-09-02 local                        
 grid         3.5.1   2018-09-02 local                        
 magrittr     1.5     2014-11-22 CRAN (R 3.5.1)               
 memoise      1.1.0   2017-04-21 CRAN (R 3.5.1)               
 methods    * 3.5.1   2018-09-02 local                        
 ncdf4        1.16    2017-04-01 CRAN (R 3.5.0)               
 ncmeta       0.0.2   2018-02-13 CRAN (R 3.5.1)               
 pillar       1.3.0   2018-07-14 CRAN (R 3.5.1)               
 pkgconfig    2.0.2   2018-08-16 CRAN (R 3.5.1)               
 purrr        0.2.5   2018-05-29 CRAN (R 3.5.1)               
 R6           2.2.2   2017-06-17 CRAN (R 3.5.1)               
 Rcpp         0.12.18 2018-07-23 CRAN (R 3.5.1)               
 rlang        0.2.2   2018-08-16 CRAN (R 3.5.1)               
 RNetCDF      1.9-1   2017-10-08 CRAN (R 3.5.0)               
 rstudioapi   0.7     2017-09-07 CRAN (R 3.5.1)               
 sf         * 0.7-0   2018-09-10 Github (r-spatial/sf@7c94ca6)
 spData       0.2.9.3 2018-08-01 CRAN (R 3.5.1)               
 stars      * 0.1-1   2018-09-10 local                        
 stats      * 3.5.1   2018-09-02 local                        
 tibble       1.4.2   2018-01-22 CRAN (R 3.5.1)               
 tidyselect   0.2.4   2018-02-26 CRAN (R 3.5.1)               
 tools        3.5.1   2018-09-02 local                        
 units        0.6-0   2018-06-09 CRAN (R 3.5.1)               
 utils      * 3.5.1   2018-09-02 local                        
 withr        2.1.2   2018-03-15 CRAN (R 3.5.1)               
 yaml         2.2.0   2018-07-25 CRAN (R 3.5.1)

CPL_read_gdal resides in sf. Have you tried reinstalling sf from github on Windows?

Sorry, got caught two commits behind - it's fine!

Is there any feasible way to make it behave more like raster, in which calls modifying the dimensions get immediately reflected on the dataset? One example will explain this better.
stars workflow:

library(stars)
(s = read_stars(somefile, proxy=TRUE))
#stars_proxy object with 1 attribute in file:
#$hmr.nc
#[1] "/home/clima-archive4-b/afantini/chym_simulations/analysis/rain/hmr/hmr.nc"
#
#dimension(s):
#       from   to     offset  delta  refsys point values    
#x         1  223         NA     NA      NA    NA   NULL [x]
#y         1  248         NA     NA      NA    NA   NULL [y]
#height    1    1        0 m     NA      NA    NA   NULL                                                                                                                                                         
#time      1 5114 2000-01-01 1 days POSIXct    NA   NULL                                                                                                                                                         
#affine parameters: NA NA

# Say I want to remove one redundant dimension, then slice on time, then check the dimensions:
(s %>% adrop)[,,,1:10] %>% st_dimensions
#       from   to     offset  delta  refsys point values    
#x         1  223         NA     NA      NA    NA   NULL [x]
#y         1  248         NA     NA      NA    NA   NULL [y]
#height    1    1        0 m     NA      NA    NA   NULL    
#time      1 5114 2000-01-01 1 days POSIXct    NA   NULL    
#affine parameters: NA NA

As you can see it's not showing the currently selected dimensions.
With raster:

library(raster)
(r = brick(somefile))
#class       : RasterBrick 
#dimensions  : 248, 223, 55304, 5114  (nrow, ncol, ncell, nlayers)
#resolution  : 1, 1  (x, y)
#extent      : 0.5, 223.5, 0.5, 248.5  (xmin, xmax, ymin, ymax)
#coord. ref. : NA 
#data source : /home/clima-archive4-b/afantini/chym_simulations/analysis/rain/hmr/hmr.nc 
#names       : X2000.01.01.00.00.00, X2000.01.02.00.00.00, X2000.01.03.00.00.00, X2000.01.04.00.00.00, X2000.01.05.00.00.00, X2000.01.06.00.00.00, X2000.01.07.00.00.00, X2000.01.08.00.00.00, X2000.01.09.00.00.00, X2000.01.10.00.00.00, X2000.01.11.00.00.00, X2000.01.12.00.00.00, X2000.01.13.00.00.00, X2000.01.14.00.00.00, X2000.01.15.00.00.00, ... 
#Date/time   : 2000-01-01 00:00:00, 2013-12-31 00:00:00 (min, max)
#varname     : pr 
#level       : 1

r[[1:10]]
#class       : RasterStack 
#dimensions  : 248, 223, 55304, 10  (nrow, ncol, ncell, nlayers)
#resolution  : 1, 1  (x, y)
#extent      : 0.5, 223.5, 0.5, 248.5  (xmin, xmax, ymin, ymax)
#coord. ref. : NA 
#names       : X2000.01.01.00.00.00, X2000.01.02.00.00.00, X2000.01.03.00.00.00, X2000.01.04.00.00.00, X2000.01.05.00.00.00, X2000.01.06.00.00.00, X2000.01.07.00.00.00, X2000.01.08.00.00.00, X2000.01.09.00.00.00, X2000.01.10.00.00.00

Seems the raster approach is a bit more user-friendly there.

I think it is conceptually different, and it might not harm to understand the concepts behind what you are doing.

(s %>% adrop)[,,,1:10] %>% st_as_stars %>% st_dimensions

should tell you the dimensions of the data when fetched by st_as_stars.

Did you remove read_stars_meta as a result of the introduction of this feature? Just to be sure.

Yes.

Ok, thanks.

To verify https://github.com/r-spatial/stars/issues/63, otherwise to be closed.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kendonB picture kendonB  路  6Comments

noamross picture noamross  路  10Comments

michaeldorman picture michaeldorman  路  11Comments

edzer picture edzer  路  12Comments

adrfantini picture adrfantini  路  10Comments