Read array blocks
read_block.Rd
Use read_block
to read a block of data from an array-like object.
Note that this function is typically used in the context of block processing
of on-disk objects (e.g. DelayedArray objects), often
in combination with write_block
.
Usage
read_block(x, viewport, as.sparse=NA)
## Internal generic function used by read_block() when is_sparse(x)
## is FALSE:
read_block_as_dense(x, viewport)
Arguments
- x
An array-like object.
This can be an ordinary array, a SparseArray object from the SparseArray package, a dgCMatrix object from the Matrix package, a DelayedArray object from the DelayedArray package, or any object with an array semantic (i.e. an object for which
dim(x)
is notNULL
).- viewport
An ArrayViewport object compatible with
x
, that is, such thatrefdim(viewport)
is identical todim(x)
.- as.sparse
Can be
FALSE
,TRUE
, orNA
.If
FALSE
, the block is returned as an ordinary array (a.k.a. dense array).If
TRUE
, it's returned as a SparseArray object.If
NA
(the default), the block is returned as an ordinary array ifis_sparse(x)
isFALSE
and as a SparseArray object otherwise. In other words, usingas.sparse=NA
is equivalent to usingas.sparse=is_sparse(x)
. This preserves sparsity and is the most efficient way to read a block.Note that when returned as a 2D SparseArray object with numeric or logical data, a block can easily and efficiently be coerced to a sparseMatrix derivative from the Matrix package with
as(block, "sparseMatrix")
. This will return a dgCMatrix object iftype(block)
is"double"
or"integer"
, and a lgCMatrix object if it's"logical"
.
Details
read_block()
delegates to 2 internal generic functions for
reading a block:
read_block_as_dense
: used whenis_sparse(x)
isFALSE
.read_block_as_sparse
(defined in the SparseArray package): used whenis_sparse(x)
isTRUE
.
Note that these 2 internal generic functions are not meant to be
called directly by the end user. The end user should always call
the higher-level user-facing read_block()
function instead.
Value
A block of data. More precisely, the data from x
that belongs to the
block delimited by the specified viewport.
The block of data is returned either as an ordinary (dense) array or as a SparseArray object from the SparseArray package.
Note that the returned block of data is guaranteed to have the same type
as x
and the same dimensions as the viewport
.
More formally, if block
is the value returned by
read_block(x, viewport)
, then:
and
are always TRUE
.
See also
ArrayGrid for ArrayGrid and ArrayViewport objects.
is_sparse
to check whether an object uses a sparse representation of the data or not.SparseArray objects implemented in the SparseArray package.
S4Arrays::type
to get the type of the elements of an array-like object.The
read_block_as_sparse
internal generic function defined in the SparseArray package and used byread_block()
whenis_sparse(x)
isTRUE
.write_block
to write a block of data to an array-like object.blockApply
and family, in the DelayedArray package, for convenient block processing of an array-like object.dgCMatrix and lgCMatrix objects implemented in the Matrix package.
DelayedArray objects implemented in the DelayedArray package.
Examples
## Please note that, although educative, the examples below are somewhat
## artificial and do not illustrate real-world usage of read_block().
## See '?RealizationSink' in the DelayedArray package for more realistic
## read_block/write_block examples.
## ---------------------------------------------------------------------
## BASIC EXAMPLE 1: READ A BLOCK FROM AN ORDINARY MATRIX (DENSE)
## ---------------------------------------------------------------------
m1 <- matrix(1:30, ncol=5)
m1
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 1 7 13 19 25
#> [2,] 2 8 14 20 26
#> [3,] 3 9 15 21 27
#> [4,] 4 10 16 22 28
#> [5,] 5 11 17 23 29
#> [6,] 6 12 18 24 30
## Define the viewport on 'm1' to read the data from:
block1_dim <- c(4, 3)
viewport1 <- ArrayViewport(dim(m1), IRanges(c(3, 2), width=block1_dim))
viewport1
#> 4 x 3 ArrayViewport object on a 6 x 5 array: [3-6,2-4]
## Read the block:
block1 <- read_block(m1, viewport1) # same as m1[3:6, 2:4, drop=FALSE]
block1
#> [,1] [,2] [,3]
#> [1,] 9 15 21
#> [2,] 10 16 22
#> [3,] 11 17 23
#> [4,] 12 18 24
## Use 'as.sparse=TRUE' to read the block as sparse object:
block1b <- read_block(m1, viewport1, as.sparse=TRUE)
block1b
#> <4 x 3 SparseMatrix> of type "integer" [nzcount=12 (100%)]:
#> [,1] [,2] [,3]
#> [1,] 9 15 21
#> [2,] 10 16 22
#> [3,] 11 17 23
#> [4,] 12 18 24
is_sparse(block1b) # TRUE
#> [1] TRUE
class(block1b) # an SVT_SparseArray object
#> [1] "SVT_SparseMatrix"
#> attr(,"package")
#> [1] "SparseArray"
## Sanity checks:
stopifnot(identical(type(m1), type(block1)))
stopifnot(identical(dim(viewport1), dim(block1)))
stopifnot(identical(m1[3:6, 2:4, drop=FALSE], block1))
stopifnot(is(block1b, "SparseArray"))
stopifnot(identical(type(m1), type(block1b)))
stopifnot(identical(dim(viewport1), dim(block1b)))
stopifnot(identical(block1, as.array(block1b)))
## ---------------------------------------------------------------------
## BASIC EXAMPLE 2: READ A BLOCK FROM A SPARSE MATRIX
## ---------------------------------------------------------------------
m2 <- rsparsematrix(12, 20, density=0.2,
rand.x=function(n) sample(25, n, replace=TRUE))
m2
#> 12 x 20 sparse Matrix of class "dgCMatrix"
#>
#> [1,] 19 . . . . . . . . . . . . . . . 12 4 . 16
#> [2,] . . . 19 2 . . . . 10 3 . . 2 16 . . . . .
#> [3,] . . . 3 3 . . 9 . . . 6 3 . . 19 17 5 10 12
#> [4,] . . 8 . . 17 22 24 . . . . . . . . . . . .
#> [5,] . . . . . . . 6 13 . . . . . . . 7 . . .
#> [6,] . . . . . . 2 . 20 . . . . 18 . . . . . .
#> [7,] . . . . . . . . . . . . . 19 21 . . . 3 .
#> [8,] . . . . . . . . . . . . . 22 . . 15 . 18 .
#> [9,] . . 8 . . . . 23 . . . . . . . . . . . .
#> [10,] . 16 . 24 . . . . 1 . . . . . . . . . 19 .
#> [11,] . 12 . . 25 25 . . . . . . . . 24 . . . . .
#> [12,] . . . . . . . . . . . . . . . . 4 15 . .
is_sparse(m2) # TRUE
#> [1] TRUE
## Define the viewport on 'm2' to read the data from:
block2_dim <- c(2, 20)
viewport2 <- ArrayViewport(dim(m2), IRanges(c(1, 1), width=block2_dim))
viewport2
#> 2 x 20 ArrayViewport object on a 12 x 20 array: [1-2, ]
## By default, read_block() preserves sparsity:
block2 <- read_block(m2, viewport2)
block2
#> <2 x 20 SparseMatrix> of type "double" [nzcount=10 (25%)]:
#> [,1] [,2] [,3] ... [,19] [,20]
#> [1,] 19 0 0 . 0 16
#> [2,] 0 0 0 . 0 0
is_sparse(block2) # TRUE
#> [1] TRUE
class(block2) # an SVT_SparseArray object
#> [1] "SVT_SparseMatrix"
#> attr(,"package")
#> [1] "SparseArray"
## Use 'as.sparse=FALSE' to force read_block() to return an ordinary
## matrix or array:
block2b <- read_block(m2, viewport2, as.sparse=FALSE)
block2b
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
#> [1,] 19 0 0 0 0 0 0 0 0 0 0 0 0 0
#> [2,] 0 0 0 19 2 0 0 0 0 10 3 0 0 2
#> [,15] [,16] [,17] [,18] [,19] [,20]
#> [1,] 0 0 12 4 0 16
#> [2,] 16 0 0 0 0 0
as(block2b, "sparseMatrix")
#> 2 x 20 sparse Matrix of class "dgCMatrix"
#>
#> [1,] 19 . . . . . . . . . . . . . . . 12 4 . 16
#> [2,] . . . 19 2 . . . . 10 3 . . 2 16 . . . . .
## Sanity checks:
stopifnot(is(block2, "SparseArray"))
stopifnot(identical(type(m2), type(block2)))
stopifnot(identical(dim(viewport2), dim(block2)))
stopifnot(identical(type(m2), type(block2b)))
stopifnot(identical(dim(viewport2), dim(block2b)))
stopifnot(identical(block2b, as.array(block2)))
## ---------------------------------------------------------------------
## BASIC EXAMPLE 3: READ A BLOCK FROM A 3D ARRAY
## ---------------------------------------------------------------------
a3 <- array(1:60, dim=5:3)
## Define the viewport on 'a3' to read the data from:
block3_dim <- c(2, 4, 1)
viewport3 <- ArrayViewport(dim(a3), IRanges(c(1, 1, 3), width=block3_dim))
viewport3
#> 2 x 4 x 1 ArrayViewport object on a 5 x 4 x 3 array: [1-2, ,3]
## Read the block:
block3 <- read_block(a3, viewport3) # same as a3[1:2, 1:4, 3, drop=FALSE]
block3
#> , , 1
#>
#> [,1] [,2] [,3] [,4]
#> [1,] 41 46 51 56
#> [2,] 42 47 52 57
#>
## Note that unlike [, read_block() never drops dimensions.
## Sanity checks:
stopifnot(identical(type(a3), type(block3)))
stopifnot(identical(dim(viewport3), dim(block3)))
stopifnot(identical(a3[1:2, 1:4, 3, drop=FALSE], block3))
## ---------------------------------------------------------------------
## BASIC EXAMPLE 4: READ AND PROCESS BLOCKS DEFINED BY A GRID
## ---------------------------------------------------------------------
a4 <- array(runif(120), dim=6:4)
## Define a grid of 2x3x2 blocks on 'a4':
grid4 <- RegularArrayGrid(dim(a4), spacings=c(2,3,2))
grid4
#> 3 x 2 x 2 RegularArrayGrid object on a 6 x 5 x 4 array:
#> , , 1
#>
#> [,1] [,2]
#> [1,] [1-2,1-3,1-2] [1-2,4-5,1-2]
#> [2,] [3-4,1-3,1-2] [3-4,4-5,1-2]
#> [3,] [5-6,1-3,1-2] [5-6,4-5,1-2]
#>
#> , , 2
#>
#> [,1] [,2]
#> [1,] [1-2,1-3,3-4] [1-2,4-5,3-4]
#> [2,] [3-4,1-3,3-4] [3-4,4-5,3-4]
#> [3,] [5-6,1-3,3-4] [5-6,4-5,3-4]
#>
nblock <- length(grid4) # number of blocks
## Walk on the grid and print the corresponding blocks:
for (bid in seq_len(nblock)) {
viewport <- grid4[[bid]]
block <- read_block(a4, viewport)
cat("====== Block ", bid, "/", nblock, " ======\n", sep="")
print(block)
}
#> ====== Block 1/12 ======
#> , , 1
#>
#> [,1] [,2] [,3]
#> [1,] 0.1643128 0.08913212 0.1811009
#> [2,] 0.2640501 0.59415278 0.2613958
#>
#> , , 2
#>
#> [,1] [,2] [,3]
#> [1,] 0.67892519 0.3847271 0.5595619
#> [2,] 0.08921005 0.2209603 0.7945691
#>
#> ====== Block 2/12 ======
#> , , 1
#>
#> [,1] [,2] [,3]
#> [1,] 0.1367880 0.9355461 0.2176147
#> [2,] 0.8186852 0.5279085 0.7419253
#>
#> , , 2
#>
#> [,1] [,2] [,3]
#> [1,] 0.2735122 0.7344064 0.2344230
#> [2,] 0.9809206 0.5754316 0.8146486
#>
#> ====== Block 3/12 ======
#> , , 1
#>
#> [,1] [,2] [,3]
#> [1,] 0.8184448 0.09140646 0.09216687
#> [2,] 0.9301954 0.84103377 0.10202040
#>
#> , , 2
#>
#> [,1] [,2] [,3]
#> [1,] 0.1480539 0.9153057 0.2136135
#> [2,] 0.9223779 0.3595852 0.9239933
#>
#> ====== Block 4/12 ======
#> , , 1
#>
#> [,1] [,2]
#> [1,] 0.6414651 0.3489492
#> [2,] 0.6115148 0.4602708
#>
#> , , 2
#>
#> [,1] [,2]
#> [1,] 0.4863859 0.01912152
#> [2,] 0.4911664 0.87108763
#>
#> ====== Block 5/12 ======
#> , , 1
#>
#> [,1] [,2]
#> [1,] 0.2849895 0.4786769
#> [2,] 0.3863133 0.2111403
#>
#> , , 2
#>
#> [,1] [,2]
#> [1,] 0.6137289 0.6728525
#> [2,] 0.5510851 0.4301806
#>
#> ====== Block 6/12 ======
#> , , 1
#>
#> [,1] [,2]
#> [1,] 0.2579461 0.7996218
#> [2,] 0.7379283 0.9757371
#>
#> , , 2
#>
#> [,1] [,2]
#> [1,] 0.35819272 0.9896227
#> [2,] 0.05208194 0.1939586
#>
#> ====== Block 7/12 ======
#> , , 1
#>
#> [,1] [,2] [,3]
#> [1,] 0.2838033 0.07399575 0.4666175
#> [2,] 0.5179243 0.91674234 0.5206536
#>
#> , , 2
#>
#> [,1] [,2] [,3]
#> [1,] 0.2977952 0.5108113 0.4760332
#> [2,] 0.1915760 0.4933940 0.4841309
#>
#> ====== Block 8/12 ======
#> , , 1
#>
#> [,1] [,2] [,3]
#> [1,] 0.2912383 0.8475760 0.2771244
#> [2,] 0.8217359 0.9114949 0.1177274
#>
#> , , 2
#>
#> [,1] [,2] [,3]
#> [1,] 0.3110062 0.7887316 0.7046952
#> [2,] 0.1945139 0.9955700 0.1649773
#>
#> ====== Block 9/12 ======
#> , , 1
#>
#> [,1] [,2] [,3]
#> [1,] 0.4170493 0.01737873 0.3498396
#> [2,] 0.9273508 0.91189900 0.9159486
#>
#> , , 2
#>
#> [,1] [,2] [,3]
#> [1,] 0.6789809 0.4578903 0.7713527
#> [2,] 0.2678041 0.6839380 0.6778281
#>
#> ====== Block 10/12 ======
#> , , 1
#>
#> [,1] [,2]
#> [1,] 0.17952045 0.4620082
#> [2,] 0.07359943 0.3224309
#>
#> , , 2
#>
#> [,1] [,2]
#> [1,] 0.7556081 0.3233760
#> [2,] 0.5083458 0.6447728
#>
#> ====== Block 11/12 ======
#> , , 1
#>
#> [,1] [,2]
#> [1,] 0.5311769 0.9608709
#> [2,] 0.4636399 0.8160373
#>
#> , , 2
#>
#> [,1] [,2]
#> [1,] 0.3184555 0.7132648
#> [2,] 0.6553045 0.4425990
#>
#> ====== Block 12/12 ======
#> , , 1
#>
#> [,1] [,2]
#> [1,] 0.02575581 0.7598830
#> [2,] 0.18494167 0.6364802
#>
#> , , 2
#>
#> [,1] [,2]
#> [1,] 0.8809271 0.9632998
#> [2,] 0.9177464 0.4759873
#>
## Walk on the grid and compute the sum of each block:
block_sums <- sapply(grid4,
function(viewport) sum(read_block(a4, viewport))
)
block_sums
#> [1] 4.282098 6.991810 6.358197 3.929961 3.628967 4.365089 5.233477 6.426391
#> [9] 7.077260 3.269662 4.901349 4.845021
## Sanity checks:
stopifnot(identical(length(block_sums), nblock))
stopifnot(all.equal(sum(block_sums), sum(a4)))
## ---------------------------------------------------------------------
## THE read_block/write_block COMBO
## ---------------------------------------------------------------------
## See '?write_block' for examples that use the read_block/write_block
## combo.