############################################################################# ## ## Copyright 2016 Novartis Institutes for BioMedical Research Inc. ## Licensed under the Apache License, Version 2.0 (the "License"); ## you may not use this file except in compliance with the License. ## You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, software ## distributed under the License is distributed on an "AS IS" BASIS, ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ## See the License for the specific language governing permissions and ## limitations under the License. ## ############################################################################# context("H5D") read_write_roundtrip <- function(ds, robj) { ds$write_low_level(robj) res <- ds$read() return(list(input=robj, output=res)) } test_that("Basic dataset function", { test_file <- tempfile(fileext=".h5") ## open a new one, truncate if it exists file.h5 <- H5File$new(test_file, mode="w") dtype_int64 <- h5types$H5T_NATIVE_LLONG dspace <- H5S$new(type="simple", dims=20, maxdims=20) ds_int64_chunked <- file.h5$create_dataset(name="int64_chunked", dtype=dtype_int64, space=dspace) ## test out the basic functions dspace_new <- ds_int64_chunked$get_space() expect_true(inherits(dspace_new, "H5S")) expect_equal(dspace_new$get_simple_extent_dims()$dims, 20) expect_equal(as.character(ds_int64_chunked$get_space_status()), "H5D_SPACE_STATUS_NOT_ALLOCATED") expect_equal(ds_int64_chunked$dims, 20) expect_equal(ds_int64_chunked$maxdims, 20) expect_equal(ds_int64_chunked$chunk_dims, 20) expect_true(ds_int64_chunked$get_type()$equal(h5types$H5T_NATIVE_LLONG)) expect_equal(ds_int64_chunked$get_storage_size(), 0) expect_equal(ds_int64_chunked$vlen_get_buf_size(ds_int64_chunked$get_type(), ds_int64_chunked$get_space()), 0) res_int64 <- read_write_roundtrip(ds_int64_chunked, 1:20) file.h5$flush() expect_equal(ds_int64_chunked$get_storage_size(), 49) expect_true(inherits(try(ds_int64_chunked$get_offset(), silent=TRUE), "try-error")) ## vlen is still 0, as it is not variable length data expect_equal(ds_int64_chunked$vlen_get_buf_size(ds_int64_chunked$get_type(), ds_int64_chunked$get_space()), 0) ## now try the same, unchunked ds_int64_unchunked <- file.h5$create_dataset(name="int64_unchunked", dtype=dtype_int64, space=dspace, chunk_dim=NULL) res_int64_unchunked <- read_write_roundtrip(ds_int64_unchunked, 1:20) expect_equal(ds_int64_unchunked$get_storage_size(), 160) expect_equal(ds_int64_unchunked$chunk_dims, NA) ## now write a dataset directly ds_int64_robj <- file.h5$create_dataset(name="int64_robj", 1:20) ## check that we can read the data out expect_equal(ds_int64_robj$read_low_level(), 1:20) ## also try it with a 2-dimensional space; and a version with a one-dimensional space and an internal array array_type <- H5T_ARRAY$new(4, h5types$H5T_NATIVE_INT) ds_array <- file.h5$create_dataset(name="int_array", dtype=array_type, space=H5S$new(dims=5)) res_array <- read_write_roundtrip(ds_array, matrix(1:20, ncol=4)) expect_equal(res_array$input, res_array$output) ds_2_dim <- file.h5$create_dataset(name="int_2_dim", dtype=h5types$H5T_NATIVE_INT, space=H5S$new(dims=c(5, 4))) res_2_dim <- read_write_roundtrip(ds_2_dim, matrix(1:20, ncol=4)) expect_equal(res_2_dim$input, res_2_dim$output) ## do a read and a write using NULL as an argument ds_2_dim$write(args=list(1:5, NULL), value=numeric(0)) expect_equal(ds_2_dim$read(args=list(1:5, NULL)), matrix(numeric(0), nrow=5, ncol=0)) ## cleanup file.h5$close_all() file.remove(test_file) }) test_that("Creating datasets of different types", { test_file <- tempfile(fileext=".h5") ## open a new one, truncate if it exists file.h5 <- H5File$new(test_file, mode="w") ## now create different types ## integer, long integer, float, enum, compound, strings ## create a dataset for each of them dtype_int64 <- h5types$H5T_NATIVE_LLONG dtype_int32 <- h5types$H5T_NATIVE_INT dtype_float <- h5types$H5T_NATIVE_FLOAT dtype_double <- h5types$H5T_NATIVE_DOUBLE ## enums enum_logical <- H5T_LOGICAL$new() factor_levels <- paste("test", 1:10, sep="") enum_factor <- H5T_ENUM$new(labels=factor_levels) ## strings dtype_string_variable_utf8 <- H5T_STRING$new()$set_size(Inf)$set_cset(h5const$H5T_CSET_UTF8) dtype_string_short_utf8 <- H5T_STRING$new()$set_size(10)$set_cset(h5const$H5T_CSET_UTF8) ## compound dtype_cpd <- H5T_COMPOUND$new(dtypes=list(dtype_int32, dtype_int32), labels=c("a", "b")) ## now create a simple dataspace for the new objects; ## will be the same for all, single dimension of size 20 dspace <- H5S$new(type="simple", dims=20, maxdims=20) ## create named datasets for all these types ds_int64 <- file.h5$create_dataset(name="int64", dtype=dtype_int64, space=dspace) ds_int32 <- file.h5$create_dataset(name="int32", dtype=dtype_int32, space=dspace) ds_float <- file.h5$create_dataset(name="float", dtype=dtype_float, space=dspace) ds_double <- file.h5$create_dataset(name="double", dtype=dtype_double, space=dspace) ds_logical <- file.h5$create_dataset(name="enum_logical", dtype=enum_logical, space=dspace) ds_factor <- file.h5$create_dataset(name="enum_factor", dtype=enum_factor, space=dspace) ds_string_short <- file.h5$create_dataset(name="string_short", dtype=dtype_string_short_utf8, space=dspace) ds_string_variable <- file.h5$create_dataset(name="string_variable", dtype=dtype_string_variable_utf8, space=dspace) ds_cpd <- file.h5$create_dataset(name="cpd", dtype=dtype_cpd, space=dspace) ## also create an anonymous dataset ds_anon <- file.h5$create_dataset(dtype=dtype_int64, space=dspace) ## now write data into the dataset, and read it back out again res_int32 <- read_write_roundtrip(ds_int32, 1:20) expect_equal(res_int32$input, res_int32$output) res_int64 <- read_write_roundtrip(ds_int64, 1:20) expect_equal(res_int64$input, res_int64$output) res_float <- read_write_roundtrip(ds_float, 1:20/4) expect_equal(res_float$input, res_float$output) res_double <- read_write_roundtrip(ds_double, 1:20/4) expect_equal(res_double$input, res_double$output) res_logical <- read_write_roundtrip(ds_logical, rep(c(FALSE, TRUE), 10)) expect_equal(res_logical$input, res_logical$output) res_factor <- read_write_roundtrip(ds_factor, factor(rep(paste("test", 1:10, sep=""), 2), levels=paste("test", 1:10, sep=""))) expect_equal(res_factor$input, res_factor$output) res_string_short <- read_write_roundtrip(ds_string_short, rep(paste("teststring", 1:20, sep=""))) expect_equal(substr(res_string_short$input, 1,10), res_string_short$output) res_string_variable <- read_write_roundtrip(ds_string_variable, rep(paste("teststring", 1:20, sep=""))) expect_equal(res_string_variable$input, res_string_variable$output) res_cpd <- read_write_roundtrip(ds_cpd, data.frame(a=1:20, b=21:40)) expect_equal(res_cpd$input, res_cpd$output) ## check that the fill-value can be retrieved expect_equal(ds_int32$get_fill_value(), 0) expect_equal(ds_string_short$get_fill_value(), "") expect_equal(ds_cpd$get_fill_value(), data.frame(a=0, b=0)) ## check other ways of creating a dataset ## using the dims parameter ds_dimsparam <- file.h5$create_dataset(name="dims_param", dtype=dtype_int32, dims=c(2,3,4)) expect_equal(ds_dimsparam$dims, c(2,3,4)) res_dimsparam <- read_write_roundtrip(ds_dimsparam, array(1:24 * 2, dim=c(2,3,4))) expect_equal(res_dimsparam$input, res_dimsparam$output) file.h5$close_all() file.remove(test_file) }) test_that("Chunking failures as intended", { test_file <- tempfile(fileext=".h5") ## open a new one, truncate if it exists file.h5 <- H5File$new(test_file, mode="w") ## create a dataset with a chunk-size that is larger than the dataset itself res1 <- try({file.h5$create_dataset("test", dtype=h5types$H5T_NATIVE_INT, space=H5S$new(dims=c(10), maxdims=c(Inf)), chunk_dim=c(20))}, silent=TRUE) expect_true(!inherits(res1, "try-error")) res2 <- try({file.h5$create_dataset("test2", dtype=h5types$H5T_NATIVE_INT, space=H5S$new(dims=c(10, 10), maxdims=c(Inf, 10)), chunk_dim=c(20, 10))}, silent=TRUE) expect_true(!inherits(res2, "try-error")) suppressWarnings({res3 <- try({file.h5$create_dataset("test3", dtype=h5types$H5T_NATIVE_INT, space=H5S$new(dims=c(10, 10), maxdims=c(Inf, 10)), chunk_dim=c(20, 20))}, silent=TRUE)}) expect_true(inherits(res3, "try-error")) file.h5$close_all() file.remove(test_file) })