Skip to content

Commit

Permalink
version 0.11.1
Browse files Browse the repository at this point in the history
  • Loading branch information
jonclayden authored and cran-robot committed Aug 1, 2019
1 parent b7d2e8f commit 2c17d1f
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 20 deletions.
10 changes: 5 additions & 5 deletions DESCRIPTION
@@ -1,6 +1,6 @@
Package: RNifti
Version: 0.11.0
Date: 2019-06-17
Version: 0.11.1
Date: 2019-08-01
Title: Fast R and C++ Access to NIfTI Images
Authors@R: c(person("Jon","Clayden",role=c("cre","aut"),email="code@clayden.org"),
person("Bob","Cox",role="aut"),
Expand All @@ -23,9 +23,9 @@ License: GPL-2
URL: https://github.com/jonclayden/RNifti
BugReports: https://github.com/jonclayden/RNifti/issues
Encoding: UTF-8
RoxygenNote: 6.1.0
RoxygenNote: 6.1.1
NeedsCompilation: yes
Packaged: 2019-06-17 16:12:34 UTC; jon
Packaged: 2019-08-01 11:55:51 UTC; jon
Author: Jon Clayden [cre, aut],
Bob Cox [aut],
Mark Jenkinson [aut],
Expand All @@ -36,4 +36,4 @@ Author: Jon Clayden [cre, aut],
Mark Adler [cph]
Maintainer: Jon Clayden <code@clayden.org>
Repository: CRAN
Date/Publication: 2019-06-17 17:33:52 UTC
Date/Publication: 2019-08-01 13:50:02 UTC
12 changes: 6 additions & 6 deletions MD5
@@ -1,8 +1,8 @@
1729446baa38402bb213b6cbf2ea846e *DESCRIPTION
7f2c2c370d8036be3433773e051ed65f *DESCRIPTION
71e1864c43d94f41f7f63c18e9ae8cda *NAMESPACE
a29dfe42c8afb074183e26b9a5b569fa *NEWS
09929df008da7421ccb1d89baa7d673c *NEWS
00bc4d732df7f933b8a094d9bca96121 *R/image.R
6f45f332ebb3b8d7301855dbe56021e4 *R/nifti.R
5c142e1b93b7124caa5b1b8c1b995ac2 *R/nifti.R
e7c27c62aa974a6fbd9346047edbe594 *R/xform.R
33e5b97691485f83c60e3d5c3f3a2cdc *R/zzz.R
02333c6755ae5cc8e1e4905e6f11a32e *README.md
Expand Down Expand Up @@ -198,7 +198,7 @@ e8547f4bc7609814adfbab6fe9c1c288 *inst/extdata/example_4d.nii.gz
816d01b64d9bc794466a072cc5ead530 *inst/include/RNifti.h
a6090d4b3725e70fdb112698709ab5b3 *inst/include/RNiftiAPI.h
35bdd693300c11e88bb00f59236dd6b1 *inst/include/lib/NiftiImage.h
51f8047d0aa9922af6825dd103b4979b *inst/include/lib/NiftiImage_impl.h
edea42a31845b27e17aa8f2c735e5162 *inst/include/lib/NiftiImage_impl.h
d4ea2b20c60ba81754992897151fb731 *inst/include/lib/NiftiImage_print.h
a34af6ec4b25ecc1a68459bbb5dc76c9 *inst/include/niftilib/nifti1.h
89d96efa2e6e8587e5a3be6b30b4d9dd *inst/include/niftilib/nifti1_io.h
Expand All @@ -213,7 +213,7 @@ a79629a9e25d6a36607bd5931381b507 *man/niftiHeader.Rd
20c181da31a24521475e83eff3927f90 *man/pixdim.Rd
78be72030ed44baf6effc222757aa110 *man/readNifti.Rd
bcc1ccf809fa0dc89846cf93b945aca2 *man/retrieveNifti.Rd
6dd432db7d2d02e94d4367ca061da1da *man/updateNifti.Rd
0222842fd160b34b41ddb09a6b8627f6 *man/updateNifti.Rd
7f366aa4296dae452fb39f3131e3cf38 *man/voxelToWorld.Rd
7abc3deb7077c2b30d9ff1716b3310e5 *man/writeNifti.Rd
efa8f9381c03660c3a86224285f5af76 *man/xform.Rd
Expand Down Expand Up @@ -246,6 +246,6 @@ fff257bc1656eb60fc585a7dc35f963d *src/zlib/zutil.c
de91a463004fd5b944c3d37eab0c1794 *src/zlib/zutil.h
2edcf5344601d3f03e1688de10acbefd *src/znzlib/znzlib.c
d4a2abbb6217055b8900c8d86ac6aa53 *tests/testthat.R
9cf843e32001eba37da0ccd08966f123 *tests/testthat/test-05-nifti.R
51c76842b8ad0306cb034435f7072527 *tests/testthat/test-05-nifti.R
699f654cbb6052138b7f5980a55a2401 *tests/testthat/test-10-xform.R
4606a69410277f4f5b4c2a9228eb941c *tests/testthat/test-15-foreign.R
8 changes: 8 additions & 0 deletions NEWS
Expand Up @@ -2,6 +2,14 @@ Significant changes to the RNifti package are laid out below for each release.

===============================================================================

VERSION 0.11.1

- Attempting to update image header fields with values of the wrong length
(e.g. through `updateNifti`) now results in a warning or error. See the
documentation for that R function for further details.

===============================================================================

VERSION 0.11.0

R interface
Expand Down
11 changes: 10 additions & 1 deletion R/nifti.R
Expand Up @@ -117,6 +117,11 @@ retrieveNifti <- function (object)
#' This allows users to selectively update certain fields while leaving others
#' alone (but see the note below).
#'
#' If multiple values are passed for a field that expects a scalar (which is
#' most of them), the first element of the vector will be used, with a warning.
#' An empty vector will be ignored, also with a warning. If a value of the
#' wrong length is passed to a vector-valued field, an error will be generated.
#'
#' Datatype information in a list \code{template} is ignored. The datatype can
#' only be changed using the \code{datatype} argument, but in this case the
#' internal object gets out of sync with the R array, so an internal image is
Expand All @@ -141,9 +146,13 @@ retrieveNifti <- function (object)
#' interpretation of the pixel data, so it is impossible in general to change
#' them without also changing the array values on both the C and the R side.
#' Therefore, to avoid unexpected side-effects, these fields are not affected
#' by this function.
#' by this function. The \code{dim} and \code{pixdim} fields can be changed,
#' but for most users the accessor functions of the same name are much safer,
#' and should be used in preference.
#'
#' @author Jon Clayden <code@@clayden.org>
#' @seealso \code{\link{$.niftiImage}}, \code{\link{dim.internalImage}},
#' \code{\link{pixdim}}, \code{\link{xform}}
#' @export
updateNifti <- function (image, template = NULL, datatype = "auto")
{
Expand Down
46 changes: 39 additions & 7 deletions inst/include/lib/NiftiImage_impl.h
Expand Up @@ -123,15 +123,37 @@ template <typename TargetType>
inline void copyIfPresent (const Rcpp::List &list, const std::set<std::string> names, const std::string &name, TargetType &target)
{
if (names.count(name) == 1)
target = Rcpp::as<TargetType>(list[name]);
{
const Rcpp::RObject object = list[name];
const int length = Rf_length(object);
if (length == 0)
{
std::ostringstream message;
message << "Field \"" << name << "\" is empty and will be ignored";
Rf_warning(message.str().c_str());
}
else if (length > 1)
{
std::ostringstream message;
message << "Field \"" << name << "\" has " << length << "elements, but only the first will be used";
Rf_warning(message.str().c_str());
target = Rcpp::as< std::vector<TargetType> >(object)[0];
}
else
target = Rcpp::as<TargetType>(object);
}
}

// Special case for char, because Rcpp tries to be too clever and convert it to a string
template <>
inline void copyIfPresent (const Rcpp::List &list, const std::set<std::string> names, const std::string &name, char &target)
{
if (names.count(name) == 1)
target = static_cast<char>(Rcpp::as<int>(list[name]));
{
int intValue = 0;
copyIfPresent<int>(list, names, name, intValue);
target = static_cast<char>(intValue);
}
}

inline void updateHeader (nifti_1_header *header, const Rcpp::List &list, const bool ignoreDatatype = false)
Expand All @@ -150,7 +172,9 @@ inline void updateHeader (nifti_1_header *header, const Rcpp::List &list, const
if (names.count("dim") == 1)
{
std::vector<short> dim = list["dim"];
for (size_t i=0; i<std::min(dim.size(),size_t(8)); i++)
if (dim.size() != 8)
throw std::runtime_error("Field \"dim\" must contain 8 elements");
for (size_t i=0; i<8; i++)
header->dim[i] = dim[i];
}

Expand All @@ -169,7 +193,9 @@ inline void updateHeader (nifti_1_header *header, const Rcpp::List &list, const
if (names.count("pixdim") == 1)
{
std::vector<float> pixdim = list["pixdim"];
for (size_t i=0; i<std::min(pixdim.size(),size_t(8)); i++)
if (pixdim.size() != 8)
throw std::runtime_error("Field \"pixdim\" must contain 8 elements");
for (size_t i=0; i<8; i++)
header->pixdim[i] = pixdim[i];
}
copyIfPresent(list, names, "vox_offset", header->vox_offset);
Expand Down Expand Up @@ -200,19 +226,25 @@ inline void updateHeader (nifti_1_header *header, const Rcpp::List &list, const
if (names.count("srow_x") == 1)
{
std::vector<float> srow_x = list["srow_x"];
for (size_t i=0; i<std::min(srow_x.size(),size_t(4)); i++)
if (srow_x.size() != 4)
throw std::runtime_error("Field \"srow_x\" must contain 4 elements");
for (size_t i=0; i<4; i++)
header->srow_x[i] = srow_x[i];
}
if (names.count("srow_y") == 1)
{
std::vector<float> srow_y = list["srow_y"];
for (size_t i=0; i<std::min(srow_y.size(),size_t(4)); i++)
if (srow_y.size() != 4)
throw std::runtime_error("Field \"srow_y\" must contain 4 elements");
for (size_t i=0; i<4; i++)
header->srow_y[i] = srow_y[i];
}
if (names.count("srow_z") == 1)
{
std::vector<float> srow_z = list["srow_z"];
for (size_t i=0; i<std::min(srow_z.size(),size_t(4)); i++)
if (srow_z.size() != 4)
throw std::runtime_error("Field \"srow_z\" must contain 4 elements");
for (size_t i=0; i<4; i++)
header->srow_z[i] = srow_z[i];
}

Expand Down
13 changes: 12 additions & 1 deletion man/updateNifti.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions tests/testthat/test-05-nifti.R
Expand Up @@ -109,6 +109,18 @@ test_that("image objects can be manipulated", {
image <- updateNifti(image, datatype="float")
expect_equal(image$datatype, 16L)

# Empty values are ignored (with a warning)
expect_warning(image$intent_code <- integer(0))

# Only the first value will be used (with a warning)
expect_warning(image$intent_code <- 1002:1005)
expect_equal(image$intent_code, 1002L)

# Vector-valued fields must have the right length
expect_error(image$srow_x <- 1.0)
image$srow_x[1] <- 1.0
expect_equal(image$srow_x[1], 1.0)

image <- readNifti(imagePath, internal=TRUE)
image <- RNifti:::rescaleNifti(image, c(0.5,0.5,0.5))
expect_equal(pixdim(image), c(5,5,5))
Expand Down

0 comments on commit 2c17d1f

Please sign in to comment.