############################################################################# ## ## 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("H5A") read_write_roundtrip <- function(h5attr, robj) { h5attr$write(robj) res <- h5attr$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) attr_int64 <- file.h5$create_attr(attr_name="int64", dtype=dtype_int64, space=dspace) ## test out the basic functions dspace_new <- attr_int64$get_space() expect_true(inherits(dspace_new, "H5S")) expect_equal(dspace_new$get_simple_extent_dims()$dims, 20) expect_true(attr_int64$get_type()$equal(h5types$H5T_NATIVE_LLONG)) expect_equal(attr_int64$get_storage_size(), 160) res_int64 <- read_write_roundtrip(attr_int64, 1:20) file.h5$flush() expect_equal(attr_int64$get_storage_size(), 160) ## rename the attributes; get info by name and by idx; ## try out the various functions that originate from the file or the group file.h5$create_group("sub") attr_int64_sub <- file.h5$create_attr_by_name("int64", "sub", dtype=dtype_int64, space=dspace) expect_equal(attr_int64_sub$attr_name(), "int64") attr_int64_sub_name <- file.h5$attr_open_by_name("int64", "sub") expect_equal(attr_int64_sub_name$attr_name(), "int64") attr_int64_sub_index <- file.h5$attr_open_by_idx(0, "sub") expect_equal(attr_int64_sub_index$attr_name(), "int64") ## check the exists function expect_true(file.h5$attr_exists_by_name("int64", "sub")) expect_true(file.h5$open("sub")$attr_exists("int64")) ## rename the attribute and then back again file.h5$attr_rename_by_name("int64", "int64_new", "sub") expect_true(file.h5$attr_exists_by_name("int64_new", "sub")) expect_true(!file.h5$attr_exists_by_name("int64", "sub")) file.h5$open("sub")$attr_rename("int64_new", "int64") expect_true(file.h5$attr_exists_by_name("int64", "sub")) expect_true(!file.h5$attr_exists_by_name("int64_new", "sub")) ## get attribute info by various ways attr_info_direct <- attr_int64_sub$get_info() attr_info_name <- file.h5$attr_info_by_name("int64", "sub") attr_info_idx <- file.h5$open("sub")$attr_info_by_idx(0, ".") expect_equal(attr_info_direct, attr_info_name) expect_equal(attr_info_direct, attr_info_idx) ## delete the attribute in various ways ## for that we first need to create a few more file.h5$create_attr_by_name("int64_copy_1", "sub", dtype=dtype_int64, space=dspace) file.h5$create_attr_by_name("int64_copy_2", "sub", dtype=dtype_int64, space=dspace) expect_equal(file.h5$obj_info_by_name("sub")$num_attrs, 3) ## check the attribute names by idx expect_equal(file.h5$attr_name_by_idx(0, "sub"), "int64") expect_equal(file.h5$attr_name_by_idx(1, "sub"), "int64_copy_1") expect_equal(file.h5$attr_name_by_idx(2, "sub"), "int64_copy_2") ## check that from the group we can retrieve the correct number of attributes group_sub <- file.h5[["sub"]] expect_equal(group_sub$attr_get_number(), 3) ## now delete each of them in one of the 3 possible ways file.h5$open("sub")$attr_delete("int64") file.h5$attr_delete_by_name("int64_copy_1", "sub") file.h5$attr_delete_by_idx(0, "sub") ## now check that there are no attributes left expect_equal(file.h5$obj_info_by_name("sub")$num_attrs, 0) ## cleanup file.h5$close_all() file.remove(test_file) }) test_that("Creating attributes 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 attrspace <- H5S$new(type="simple", dims=20, maxdims=20) ## create named datasets for all these types attr_int64 <- file.h5$create_attr(attr_name="int64", dtype=dtype_int64, space=attrspace) attr_int32 <- file.h5$create_attr(attr_name="int32", dtype=dtype_int32, space=attrspace) attr_float <- file.h5$create_attr(attr_name="float", dtype=dtype_float, space=attrspace) attr_double <- file.h5$create_attr(attr_name="double", dtype=dtype_double, space=attrspace) attr_logical <- file.h5$create_attr(attr_name="enum_logical", dtype=enum_logical, space=attrspace) attr_factor <- file.h5$create_attr(attr_name="enum_factor", dtype=enum_factor, space=attrspace) attr_string_short <- file.h5$create_attr(attr_name="string_short", dtype=dtype_string_short_utf8, space=attrspace) attr_string_variable <- file.h5$create_attr(attr_name="string_variable", dtype=dtype_string_variable_utf8, space=attrspace) attr_cpd <- file.h5$create_attr(attr_name="cpd", dtype=dtype_cpd, space=attrspace) ## now write data into the dataset, and read it back out again res_int32 <- read_write_roundtrip(attr_int32, 1:20) expect_equal(res_int32$input, res_int32$output) res_int64 <- read_write_roundtrip(attr_int64, 1:20) expect_equal(res_int64$input, res_int64$output) res_float <- read_write_roundtrip(attr_float, 1:20/4) expect_equal(res_float$input, res_float$output) res_double <- read_write_roundtrip(attr_double, 1:20/4) expect_equal(res_double$input, res_double$output) res_logical <- read_write_roundtrip(attr_logical, rep(c(FALSE, TRUE), 10)) expect_equal(res_logical$input, res_logical$output) res_factor <- read_write_roundtrip(attr_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(attr_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(attr_string_variable, rep(paste("teststring", 1:20, sep=""))) expect_equal(res_string_variable$input, res_string_variable$output) res_cpd <- read_write_roundtrip(attr_cpd, data.frame(a=1:20, b=21:40)) expect_equal(res_cpd$input, res_cpd$output) file.h5$close_all() file.remove(test_file) }) test_that("Creating attributes of different types of length 0", { 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 0 attrspace <- H5S$new(type="simple", dims=0, maxdims=0) ## create named datasets for all these types attr_int64 <- file.h5$create_attr(attr_name="int64", dtype=dtype_int64, space=attrspace) attr_int32 <- file.h5$create_attr(attr_name="int32", dtype=dtype_int32, space=attrspace) attr_float <- file.h5$create_attr(attr_name="float", dtype=dtype_float, space=attrspace) attr_double <- file.h5$create_attr(attr_name="double", dtype=dtype_double, space=attrspace) attr_logical <- file.h5$create_attr(attr_name="enum_logical", dtype=enum_logical, space=attrspace) attr_factor <- file.h5$create_attr(attr_name="enum_factor", dtype=enum_factor, space=attrspace) attr_string_short <- file.h5$create_attr(attr_name="string_short", dtype=dtype_string_short_utf8, space=attrspace) attr_string_variable <- file.h5$create_attr(attr_name="string_variable", dtype=dtype_string_variable_utf8, space=attrspace) attr_cpd <- file.h5$create_attr(attr_name="cpd", dtype=dtype_cpd, space=attrspace) ## now write data into the dataset, and read it back out again res_int32 <- read_write_roundtrip(attr_int32, integer(0)) expect_equal(res_int32$input, res_int32$output) res_int64 <- read_write_roundtrip(attr_int64, integer(0)) expect_equal(res_int64$input, res_int64$output) res_float <- read_write_roundtrip(attr_float, numeric(0)) expect_equal(res_float$input, res_float$output) res_double <- read_write_roundtrip(attr_double, numeric(0)) expect_equal(res_double$input, res_double$output) res_logical <- read_write_roundtrip(attr_logical, logical(0)) expect_equal(res_logical$input, res_logical$output) res_factor <- read_write_roundtrip(attr_factor, factor(character(0), levels=paste("test", 1:10, sep=""))) expect_equal(res_factor$input, res_factor$output) res_string_short <- read_write_roundtrip(attr_string_short, character(0)) expect_equal(substr(res_string_short$input, 1,10), res_string_short$output) res_string_variable <- read_write_roundtrip(attr_string_variable, character(0)) expect_equal(res_string_variable$input, res_string_variable$output) res_cpd <- read_write_roundtrip(attr_cpd, data.frame(a = numeric(0), b = numeric(0))) expect_equal(res_cpd$input, res_cpd$output) file.h5$close_all() file.remove(test_file) })