Commit ae317b94 authored by Nicolau Manubens Gil's avatar Nicolau Manubens Gil
Browse files

Merge branch 'develop-bugfixes-0.0.2' into 'master'

Develop bugfixes 0.0.2



See merge request !5
parents 55c6ff58 f2a0707b
......@@ -3,7 +3,8 @@ Title: Tools to Easily Read/Write NetCDF Files into/from Multidimensional R Arra
Version: 0.0.2
Authors@R: c(
person("BSC-CNS", role = c("aut", "cph")),
person("Nicolau", "Manubens", , "nicolau.manubens@bsc.es", role = c("aut", "cre")))
person("Nicolau", "Manubens", , "nicolau.manubens@bsc.es", role = c("aut", "cre")),
person("David", "Pierce", , "david.pierce@ucsd.edu", role = c("ctb")))
Description: Set of wrappers for the 'ncdf4' package to simplify and extend its reading/writing capabilities into/from multidimensional R arrays.
Depends:
R (>= 2.14.1)
......@@ -15,3 +16,4 @@ URL: https://earth.bsc.es/gitlab/es/easyNCDF/wikis/home
BugReports: https://earth.bsc.es/gitlab/es/easyNCDF/issues
LazyData: true
SystemRequirements: netcdf development libraries
NeedsCompilation: yes
useDynLib(easyNCDF)
exportPattern("^[^\\.]")
import(ncdf4, abind)
importFrom("stats", "setNames")
......@@ -44,6 +44,11 @@ NcReadDims <- function(file_to_read, var_names = NULL) {
}
found_dims <- file_object$var[[var_name]]$size
names(found_dims) <- sapply(file_object$var[[var_name]]$dim, '[[', 'name')
# Support for character strings
if ((file_object$var[[var_name]]$prec == 'char') &&
(length(file_object$var[[var_name]][['dim']]) > 1)) {
found_dims <- found_dims[-1]
}
new_dim <- c(var = 1)
found_dims <- c(new_dim, found_dims)
if (!is.null(dims)) {
......
......@@ -72,7 +72,6 @@ NcToArray <- function(file_to_read, dim_indices = NULL, vars_to_read = NULL,
# if (!is.character(vars_to_read) && !is.numeric(vars_to_read)) {
# stop("Parameter 'vars_to_read' must be a numeric vector or vector of character strings.")
# }
result_list <- NULL
for (vars_to_read_vector in vars_to_read) {
result <- NULL
......@@ -94,12 +93,11 @@ NcToArray <- function(file_to_read, dim_indices = NULL, vars_to_read = NULL,
}
#file_object$var[extra_dimvars] <- extra_dimvars_list
#file_object$nvars <- file_object$nvars + length(extra_dimvars)
nmv <- numeric_var_indices <- which(is.numeric(vars_to_read_vector))
if (length(nmv) > 0) {
if (any(vars_to_read_vector[nmv] > (length(file_object$var) + length(extra_dimvars)))) {
if (is.numeric(vars_to_read_vector)) {
if (any(vars_to_read_vector > (length(file_object$var) + length(extra_dimvars)))) {
stop("Provided numerical variable indices out of bounds in 'vars_to_read'.")
}
vars_to_read_vector[nmv] <- c(sapply(file_object$var, '[[', 'name'), extra_dimvars)[vars_to_read_vector[nmv]]
vars_to_read_vector <- c(sapply(file_object$var, '[[', 'name'), extra_dimvars)[vars_to_read_vector]
}
for (var_name in vars_to_read_vector) {
if (var_name %in% extra_dimvars) {
......@@ -160,11 +158,6 @@ NcToArray <- function(file_to_read, dim_indices = NULL, vars_to_read = NULL,
}
}
}
if (expect_all_indices) {
extra_dims <- names(extra_dims)
} else {
extra_dims <- NULL
}
any_empty_selectors <- FALSE
# Here we are allowing for indices out of range (simply discarding them).
for (inner_dim in names(indices_to_take)) {
......@@ -203,33 +196,50 @@ NcToArray <- function(file_to_read, dim_indices = NULL, vars_to_read = NULL,
# }
# missing_dims <- missing_dim_names
#}
start <- sapply(indices_to_take, function(x) if (is_single_na(x)) 1 else min(x))
count <- sapply(indices_to_take, function(x) if (is_single_na(x)) -1 else max(x) - min(x) + 1)
# Support for character strings
if ((file_object[['var']][[var_name]][['prec']] == 'char') &&
(length(file_object[['var']][[var_name]][['dim']]) > 1)) {
start <- c(1, start)
count <- c(-1, count)
##original_ncvar_get_inner <- ncdf4:::ncvar_get_inner
##assignInNamespace('ncvar_get_inner', .ncvar_get_inner, 'ncdf4')
}
var_result <- do.call('[', c(list(.ncvar_get(file_object, var_name, start, count, collapse_degen = FALSE)),
lapply(indices_to_take, function(x) if (is_single_na(x)) TRUE else x - min(x) + 1), list(drop = FALSE)))
### Support for character strings
##if ((file_object[['var']][[var_name]][['prec']] == 'char') &&
## (length(file_object[['var']][[var_name]][['dim']]) > 1)) {
## assignInNamespace('ncvar_get_inner', original_ncvar_get_inner, 'ncdf4')
##}
#metadata <- c(metadata, structure(list(file_object$var[[var_name]]), .Names = var_name))
names(dim(var_result)) <- names(indices_to_take)
# Drop extra dims
if (!is.null(extra_dims) && expect_all_indices) {
dim(var_result) <- dim(var_result)[-which(names(indices_to_take) %in% names(extra_dims))]
}
# Reorder if needed
reorder_back <- NULL
indices_dims <- names(dim_indices)[which(names(dim_indices) %in% names(found_dims))]
indices_dims <- names(dim_indices)[which(names(dim_indices) %in% names(dim(var_result)))]
if (length(indices_dims) > 0) {
if (any(names(found_dims) != indices_dims)) {
#reorder <- sapply(names(found_dims), function(x) which(indices_dims == x))
reorder_back <- sapply(indices_dims, function(x) which(names(found_dims) == x))
if (any(names(dim(var_result))[-which(names(dim(var_result)) %in% names(extra_dims))] != indices_dims)) {
reorder_back <- 1:length(dim(var_result))
dims_to_reorder <- which(!(names(dim(var_result)) %in% names(extra_dims)))
reorder_back[dims_to_reorder] <- dims_to_reorder[sapply(indices_dims,
function(x) {
which(names(dim(var_result))[dims_to_reorder] == x)
})]
dimname_bk <- names(dim(var_result))
var_result <- aperm(var_result, reorder_back)
names(dim(var_result)) <- dimname_bk[reorder_back]
#indices_to_take <- indices_to_take[reorder]
}
}
start <- sapply(indices_to_take, function(x) if (is_single_na(x)) 1 else min(x))
count <- sapply(indices_to_take, function(x) if (is_single_na(x)) -1 else max(x) - min(x) + 1)
var_result <- do.call('[', c(list(ncvar_get(file_object, var_name, start, count, collapse_degen = FALSE)),
lapply(indices_to_take, function(x) if (is_single_na(x)) TRUE else x - min(x) + 1), list(drop = FALSE)))
#metadata <- c(metadata, structure(list(file_object$var[[var_name]]), .Names = var_name))
## TODO: Crop dimensions in attributes
if (!is.null(reorder_back)) {
var_result <- aperm(var_result, reorder_back)
names(dim(var_result)) <- names(indices_to_take)[reorder_back]
} else {
names(dim(var_result)) <- names(indices_to_take)
}
#if (!is.null(missing_dims)) {
# dim(var_result) <- original_dims
#}
if (!is.null(extra_dims)) {
dim(var_result) <- dim(var_result)[-which(names(indices_to_take) %in% extra_dims)]
}
#attr(var_result, 'variables') <- metadata
}
atts <- file_object$var[[var_name]]
......@@ -246,7 +256,7 @@ NcToArray <- function(file_to_read, dim_indices = NULL, vars_to_read = NULL,
#names(dim(var_result)) <- sapply(file_object$var[[var_name]]$dim, '[[', 'name')
}
if (!is.null(var_result)) {
if (!drop_var_dim || (length(vars_to_read_vector) == 1)) {
if (!(drop_var_dim && (length(vars_to_read_vector) == 1))) {
dim(var_result) <- c(setNames(1, var_tag), dim(var_result))
}
attr(var_result, 'variables') <- structure(list(atts), .Names = var_name)
......
This diff is collapsed.
#! /bin/sh
rm -f config.* R/load.R src/Makevars
rm -rf autom4te.cache
This diff is collapsed.
......@@ -5,7 +5,7 @@
Read a NetCDF File Into an R Array
}
\description{
Reads one or a set of variables together with metadata items from a NetCDF file into an R array. Indices to retrieve (not necessarily consecutive) can be specified for each of the dimensions. Depending on the format of the request, the variables will be merged in into a single extended array or returned in a list with an array for each variable. The different variables in the file are considered to be stored along a dimension called 'var', so reading a variable 'foo' with dimensions 'lat' and 'lon' would result in an array with the dimensions c('var' = 1, 'lat' = n_lats, 'lon' = n_lons).
Reads one or a set of variables together with metadata items from a single NetCDF file into an R array (see package 'startR' to read data from multiple files/data sets). Indices to retrieve (not necessarily consecutive) can be specified for each of the dimensions. Depending on the format of the request, the variables will be merged in into a single extended array or returned in a list with an array for each variable. The different variables in the file are considered to be stored along a dimension called 'var', so reading a variable 'foo' with dimensions 'lat' and 'lon' would result in an array with the dimensions c('var' = 1, 'lat' = n_lats, 'lon' = n_lons).
}
\usage{
NcToArray(file_to_read, dim_indices = NULL, vars_to_read = NULL,
......@@ -17,7 +17,7 @@ nc2a(file_to_read, dim_indices = NULL, vars_to_read = NULL,
}
\arguments{
\item{file_to_read}{
Path to the file to be read or a NetCDF object as returned by \code{easyNCDF::NcOpen} or \code{ncdf4::nc_open}.
Path to the file to be read or a NetCDF object as returned by \code{easyNCDF::NcOpen} or \code{ncdf4::nc_open}. See package 'startR' if need to read data from multiple files/data sets.
}
\item{dim_indices}{
Named list with numeric vectors of indices to take for each dimension. The names should correspond to the dimension names which to take the indices for. Non-consecutive indices can be specified. If \code{expect_all_indices = FALSE} (default), it is not mandatory to specify the indices for all (or even any of) the dimensions. In that case all the indices along such dimensions will be read in. If \code{expect_all_indices = TRUE}, then indices for all the dimensions have to be specified for the function to return a data array. In that case, \code{NA} can be used to request all indices for a dimension if desired.
......@@ -39,7 +39,7 @@ Whether to drop the 'var' dimension this function assumes (read description). If
Whether to merge the resulting array variables into a single array if possible (default) or not. Otherwise a list with as many arrays as requested variables is returned.
}
\item{expect_all_indices}{
Whether the function should stop if indices are not provided for all the dimensions of any of the requested variables rather than assuming that all the indices are requested for the unspecified dimensions. By default the later is done.
Whether the function should stop if indices are not provided for all the dimensions of any of the requested variables (TRUE) rather than assuming that all the indices are requested for the unspecified dimensions (FALSE). By default the later is done (FALSE).
}
\item{allow_out_of_range}{
Whether to allow indices out of range (simply disregard them) or to stop if indices out of range are found.
......@@ -64,6 +64,26 @@ NcClose(fnc)
# Check the obtained array matches the original array
print(a)
print(a_from_file[1, , ])
# Example with extra dimensions of length 1
# Creating sample data with singleton dimensions. Only dimensions 'a', 'b' and
# 'c' are of length > 1.
test_var <- array(1:24, dim = c(1, 1, 2, 1, 1, 3, 1, 4, 1, 1))
names(dim(test_var)) <- c('x', 'y', 'a', 'z', 't', 'b', 'u', 'c', 'v', 'w')
# Storing the data into a NetCDF file
a2nc(list(test_var = test_var), file_path)
# Reading the data back
fff <- nc2a(file_path, list(a = NA, b = NA, c = NA), vars_to_read = 'test_var')
# By default, if no indices are provided for the singleton dimensions, they are
# automatically read in and preserved
dim(fff)
# Reading the data back with expect_all_indices = TRUE
fff <- nc2a(file_path, list(a = NA, b = NA, c = NA), vars_to_read = 'test_var',
expect_all_indices = TRUE)
# If indices for all dimensions are not provided and expect_all_indices = TRUE,
# the function crashes, except if those dimensions are of length 1. In that
# case, the function ignores those (those are dropped)
dim(fff)
}
\author{
History:\cr
......
##PKG_CPPFLAGS=-I/path/to/netcdf/header
##PKG_LIBS=-L/path/to/netcdf/lib -lnetcdf
PKG_LIBS=@NETCDF_LDFLAGS@
PKG_CPPFLAGS=@NETCDF_CPPFLAGS@
PKG_LIBS = -lnetcdf4 -L$(LIB_HDF5)/lib${R_ARCH} -lhdf5_hl -lhdf5 -lz
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment