Skip to content

Commit

Permalink
Add facility to include ostensibly unused fields in NIfTI header objects
Browse files Browse the repository at this point in the history
  • Loading branch information
jonclayden committed Feb 13, 2024
1 parent 2540b2d commit 2b6b124
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 9 deletions.
9 changes: 6 additions & 3 deletions R/nifti.R
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ updateNifti <- function (image, template = NULL, datatype = "auto")
#' @param image An image, in any acceptable form (see \code{\link{asNifti}}).
#' A list containing partial header information is acceptable, including an
#' empty list, which returns defaults for every field.
#' @param unused Logical value. If \code{TRUE}, legacy ANALYZE and padding
#' fields that are unused by the relevant NIfTI standard are included in the
#' return value. These are occasionally used by software packages.
#' @param x A \code{"niftiHeader"} object.
#' @param ... Ignored.
#' @return For \code{niftiHeader}, a list of class \code{"niftiHeader"}, with
Expand Down Expand Up @@ -246,13 +249,13 @@ updateNifti <- function (image, template = NULL, datatype = "auto")
#' @references The NIfTI-1 standard (\url{https://www.nitrc.org/docman/view.php/26/64/nifti1.h}).
#' @aliases dumpNifti
#' @export niftiHeader dumpNifti
niftiHeader <- dumpNifti <- function (image = list())
niftiHeader <- dumpNifti <- function (image = list(), unused = FALSE)
{
# Special case to avoid expensively reading image data from file when only metadata is needed
if (is.character(image) && length(image) == 1 && !inherits(image,"internalImage"))
.Call("niftiHeader", image, PACKAGE="RNifti")
.Call("niftiHeader", image, unused, PACKAGE="RNifti")
else
.Call("niftiHeader", asNifti(image,internal=TRUE), PACKAGE="RNifti")
.Call("niftiHeader", asNifti(image,internal=TRUE), unused, PACKAGE="RNifti")
}

#' @rdname niftiHeader
Expand Down
6 changes: 5 additions & 1 deletion man/niftiHeader.Rd

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

42 changes: 37 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,36 @@ END_RCPP
}

template <typename Header>
static List niftiHeaderToList (const Header &header)
static void insertUnusedFields (const Header &header, List &result);

template <>
void insertUnusedFields (const nifti_1_header &header, List &result)
{
// For NIfTI-1 the unused fields are in two blocks. We insert them in the
// logical places for convenience
List firstBlock, secondBlock;

firstBlock["data_type"] = std::string(header.data_type, 10);
firstBlock["db_name"] = std::string(header.db_name, 18);
firstBlock["extents"] = header.extents;
firstBlock["session_error"] = header.session_error;
firstBlock["regular"] = header.regular;
result.insert(result.begin() + 1, firstBlock);

secondBlock["glmax"] = header.glmax;
secondBlock["glmin"] = header.glmin;
result.insert(result.begin() + 26, secondBlock);
}

template <>
void insertUnusedFields (const nifti_2_header &header, List &result)
{
// For NIfTI-2 the only unused field is at the end, which is simple
result["unused_str"] = std::string(header.unused_str, 15);
}

template <typename Header>
static List niftiHeaderToList (const Header &header, const bool includeUnused = false)
{
List result;

Expand Down Expand Up @@ -296,6 +325,9 @@ static List niftiHeaderToList (const Header &header)
result["intent_name"] = std::string(header.intent_name, 16);
result["magic"] = std::string(header.magic, 4);

if (includeUnused)
insertUnusedFields(header, result);

List strings;
strings["datatype"] = nifti_datatype_string(header.datatype);
strings["intent_code"] = nifti_intent_string(header.intent_code);
Expand All @@ -309,7 +341,7 @@ static List niftiHeaderToList (const Header &header)
return result;
}

RcppExport SEXP niftiHeader (SEXP _image)
RcppExport SEXP niftiHeader (SEXP _image, SEXP _unused)
{
BEGIN_RCPP
const NiftiImage image(_image, false, true);
Expand All @@ -323,13 +355,13 @@ BEGIN_RCPP
{
nifti_1_header header;
nifti_convert_nim2n1hdr(image, &header);
result = niftiHeaderToList(header);
result = niftiHeaderToList(header, as<bool>(_unused));
}
else if (version == 2)
{
nifti_2_header header;
nifti_convert_nim2n2hdr(image, &header);
result = niftiHeaderToList(header);
result = niftiHeaderToList(header, as<bool>(_unused));
}

RNifti::internal::addAttributes(result, image, false, false);
Expand Down Expand Up @@ -832,7 +864,7 @@ R_CallMethodDef callMethods[] = {
{ "readNifti", (DL_FUNC) &readNifti, 3 },
{ "readNiftiBlob", (DL_FUNC) &readNiftiBlob, 6 },
{ "writeNifti", (DL_FUNC) &writeNifti, 5 },
{ "niftiHeader", (DL_FUNC) &niftiHeader, 1 },
{ "niftiHeader", (DL_FUNC) &niftiHeader, 2 },
{ "analyzeHeader", (DL_FUNC) &analyzeHeader, 1 },
{ "getXform", (DL_FUNC) &getXform, 2 },
{ "setXform", (DL_FUNC) &setXform, 3 },
Expand Down

0 comments on commit 2b6b124

Please sign in to comment.