##
## Copyright (c) 2009-2011 Brandon Whitcher and Volker Schmid
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
##
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above
## copyright notice, this list of conditions and the following
## disclaimer in the documentation and/or other materials provided
## with the distribution.
## * The names of the authors may not be used to endorse or promote
## products derived from this software without specific prior
## written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## $Id: niftiS4.R 332 2010-01-29 16:54:07Z bjw34032 $
##
#############################################################################
## setClass("niftiExtensionSection")
#############################################################################
#' @title Class "niftiExtensionSection"
#'
#' @description A \code{niftiExtensionSection} contains the fields that conform
#' to the NIfTI standard regarding header extensions. A \code{niftiExtension}
#' is composed of one or more of these objects.
#'
#' @name niftiExtensionSection-class
#' @docType class
#' @section Objects from the Class: Objects can be created by calls of the form
#' \code{new("niftiExtensionSection", data, dim, dimnames, ...)}.
#' @author Brandon Whitcher \email{bwhitcher@@gmail.com},\cr Andrew Thornton
#' \email{zeripath@@users.sourcefore.net}
#' @seealso \code{\linkS4class{niftiExtension}}, \code{\linkS4class{nifti}}
#' @references NIfTI-1\cr \url{http://nifti.nimh.nih.gov/}
#' @keywords classes
#' @examples
#'
#' showClass("niftiExtensionSection")
#' @export
setClass("niftiExtensionSection",
representation(esize="numeric",
ecode="numeric",
edata="character"),
prototype(esize=numeric(1),
ecode=numeric(1),
edata=""))
#############################################################################
## setClass("nifti")
#############################################################################
#' @name nifti-class
#' @title Class "nifti"
#'
#' @description The NIfTI class for medical imaging data.
#'
#' @aliases nifti-class show,nifti-method
#' @param object An object of class \code{nifti}.
#' @docType class
#' @section Objects from the Class: Objects can be created by calls of the form
#' \code{new("nifti", data, dim, dimnames, ...)} or by calling the \code{nifti}
#' function.
#' @author Brandon Whitcher \email{bwhitcher@@gmail.com},\cr Andrew Thornton
#' \email{zeripath@@users.sourcefore.net}
#' @seealso \code{\linkS4class{anlz}}, \code{\linkS4class{niftiExtension}},
#' \code{\linkS4class{niftiAuditTrail}}
#' @references NIfTI-1\cr \url{http://nifti.nimh.nih.gov/}
#' @keywords classes
#' @examples
#'
#' showClass("nifti")
#' @section Slots:
#' \describe{
#' \item{\code{.Data}:}{Object of class \code{"array"} contains the
#' imaging data}
#' \item{\code{sizeof_hdr}:}{Object of class \code{"numeric"} contains
#' the size of the header (= 348)}
#' \item{\code{data_type}:}{Object of class \code{"character"}}
#' \item{\code{db_name}:}{Object of class \code{"character"}}
#' \item{\code{extents}:}{Object of class \code{"numeric"}}
#' \item{\code{session_error}:}{Object of class \code{"numeric"}}
#' \item{\code{regular}:}{Object of class \code{"character"}}
#' \item{\code{dim_info}:}{Object of class \code{"numeric"} contains
#' MRI slice ordering}
#' \item{\code{dim_}:}{Object of class \code{"vector"} contains the
#' dimensions of the imaging data}
#' \item{\code{intent_p1}:}{Object of class \code{"numeric"}}
#' \item{\code{intent_p2}:}{Object of class \code{"numeric"}}
#' \item{\code{intent_p3}:}{Object of class \code{"numeric"}}
#' \item{\code{intent_code}:}{Object of class \code{"numeric"}}
#' \item{\code{datatype}:}{Object of class \code{"numeric"}}
#' \item{\code{bitpix}:}{Object of class \code{"numeric"} contains the
#' number of bits per voxel (pixel)}
#' \item{\code{slice_start}:}{Object of class \code{"numeric"}}
#' \item{\code{pixdim}:}{Object of class \code{"vector"} contains the
#' real-world dimensions of the imaging data}
#' \item{\code{vox_offset}:}{Object of class \code{"numeric"} contains
#' the voxel offset (= 352 when no extensions exist)}
#' \item{\code{scl_slope}:}{Object of class \code{"numeric"}}
#' \item{\code{scl_inter}:}{Object of class \code{"numeric"}}
#' \item{\code{slice_end}:}{Object of class \code{"numeric"}}
#' \item{\code{slice_code}:}{Object of class \code{"numeric"}}
#' \item{\code{xyzt_units}:}{Object of class \code{"numeric"}}
#' \item{\code{cal_max}:}{Object of class \code{"numeric"} contains the
#' maximum display intensity}
#' \item{\code{cal_min}:}{Object of class \code{"numeric"} contains the
#' minimum display intensity}
#' \item{\code{slice_duration}:}{Object of class \code{"numeric"}}
#' \item{\code{toffset}:}{Object of class \code{"numeric"}}
#' \item{\code{glmax}:}{Object of class \code{"numeric"}}
#' \item{\code{glmin}:}{Object of class \code{"numeric"}}
#' \item{\code{descrip}:}{Object of class \code{"character"}}
#' \item{\code{aux_file}:}{Object of class \code{"character"}}
#' \item{\code{qform_code}:}{Object of class \code{"numeric"}}
#' \item{\code{sform_code}:}{Object of class \code{"numeric"}}
#' \item{\code{quatern_b}:}{Object of class \code{"numeric"}}
#' \item{\code{quatern_c}:}{Object of class \code{"numeric"}}
#' \item{\code{quatern_d}:}{Object of class \code{"numeric"}}
#' \item{\code{qoffset_x}:}{Object of class \code{"numeric"}}
#' \item{\code{qoffset_y}:}{Object of class \code{"numeric"}}
#' \item{\code{qoffset_z}:}{Object of class \code{"numeric"}}
#' \item{\code{srow_x}:}{Object of class \code{"vector"}}
#' \item{\code{srow_y}:}{Object of class \code{"vector"}}
#' \item{\code{srow_z}:}{Object of class \code{"vector"}}
#' \item{\code{intent_name}:}{Object of class \code{"character"}}
#' \item{\code{magic}:}{Object of class \code{"character"}}
#' \item{\code{extender}:}{Object of class \code{"vector"}}
#' \item{\code{reoriented}:}{Object of class \code{"logical"}}
#' }
#' @section Extends:
#' Class \code{"\linkS4class{array}"}, from data part.\cr
#' Class \code{"\linkS4class{matrix}"}, by class \dQuote{array}, distance 2,
#' with explicit test and coerce.\cr
#' Class \code{"\linkS4class{structure}"}, by class \dQuote{array}, distance
#' 2.\cr
#' Class \code{"\linkS4class{vector}"}, by class \dQuote{array}, distance 3,
#' with explicit coerce.\cr
#' Class \code{"\linkS4class{vector}"}, by class \dQuote{array}, distance 5,
#' with explicit test and coerce.
#'
#' @section Methods:
#' \describe{
#' \item{image}{\code{signature(x = "nifti")}: displays the image(s).}
#' \item{orthographic}{\code{signature(x = "nifti")}: displays the image(s).}
#' \item{overlay}{\code{signature(x = "nifti", y = "nifti")}: displays
#' the image(s).}
#' \item{show}{\code{signature(object = "nifti")}: prints out a summary
#' of the imaging data.}
#' }
#' @export
setClass("nifti",
representation("sizeof_hdr"="numeric",
"data_type"="character",
"db_name"="character",
"extents"="numeric",
"session_error"="numeric",
"regular"="character",
"dim_info"="character",
"dim_"="vector",
"intent_p1"="numeric",
"intent_p2"="numeric",
"intent_p3"="numeric",
"intent_code"="numeric",
"datatype"="numeric",
"bitpix"="numeric",
"slice_start"="numeric",
"pixdim"="vector",
"vox_offset"="numeric",
"scl_slope"="numeric",
"scl_inter"="numeric",
"slice_end"="numeric",
"slice_code"="numeric", # character?
"xyzt_units"="numeric", # character?
"cal_max"="numeric",
"cal_min"="numeric",
"slice_duration"="numeric",
"toffset"="numeric",
"glmax"="numeric",
"glmin"="numeric",
"descrip"="character",
"aux_file"="character",
"qform_code"="numeric",
"sform_code"="numeric",
"quatern_b"="numeric",
"quatern_c"="numeric",
"quatern_d"="numeric",
"qoffset_x"="numeric",
"qoffset_y"="numeric",
"qoffset_z"="numeric",
"srow_x"="vector",
"srow_y"="vector",
"srow_z"="vector",
"intent_name"="character",
"magic"="character",
"extender"="vector",
"reoriented"="logical"),
prototype("sizeof_hdr"=348,
"data_type"="",
"db_name"="",
"extents"=numeric(1),
"session_error"=numeric(1),
"regular"="",
"dim_info"="",
"dim_"=numeric(8),
"intent_p1"=numeric(1),
"intent_p2"=numeric(1),
"intent_p3"=numeric(1),
"intent_code"=numeric(1),
"datatype"=2,
"bitpix"=8,
"slice_start"=numeric(1),
"pixdim"=numeric(8),
"vox_offset"=352,
"scl_slope"=numeric(1),
"scl_inter"=numeric(1),
"slice_end"=numeric(1),
"slice_code"=numeric(1),
"xyzt_units"=numeric(1),
"cal_max"=numeric(1),
"cal_min"=numeric(1),
"slice_duration"=numeric(1),
"toffset"=numeric(1),
"glmax"=numeric(1),
"glmin"=numeric(1),
"descrip"="",
"aux_file"="",
"qform_code"=numeric(1),
"sform_code"=numeric(1),
"quatern_b"=numeric(1),
"quatern_c"=numeric(1),
"quatern_d"=numeric(1),
"qoffset_x"=numeric(1),
"qoffset_y"=numeric(1),
"qoffset_z"=numeric(1),
"srow_x"=numeric(4),
"srow_y"=numeric(4),
"srow_z"=numeric(4),
"intent_name"="",
"magic"="n+1",
"extender"=numeric(4),
"reoriented"=FALSE),
contains="array")
#############################################################################
## setMethod("show", "nifti")
#############################################################################
#' @aliases show,nifti-method
#' @rdname nifti-class
setMethod("show", "nifti", function(object) {
cat("NIfTI-1 format", fill=TRUE)
cat(" Type :", class(object), fill=TRUE)
cat(" Data Type : ", object@"datatype",
" (", convert.datatype(object@datatype), ")", sep="", fill=TRUE)
cat(" Bits per Pixel :", object@bitpix, fill=TRUE)
cat(" Slice Code : ", object@"slice_code",
" (", convert.slice(object@"slice_code"), ")", sep="", fill=TRUE)
cat(" Intent Code : ", object@"intent_code",
" (", convert.intent(object@"intent_code"), ")", sep="", fill=TRUE)
cat(" Qform Code : ", object@"qform_code",
" (", convert.form(object@"qform_code"), ")", sep="", fill=TRUE)
cat(" Sform Code : ", object@"sform_code",
" (", convert.form(object@"sform_code"), ")", sep="", fill=TRUE)
cat(" Dimension :",
paste(object@"dim_"[2:(1+object@"dim_"[1])], collapse=" x "),
fill=TRUE)
cat(" Pixel Dimension :",
paste(round(pixdim(object)[2:(1+object@"dim_"[1])],2), collapse=" x "),
fill=TRUE)
cat(" Voxel Units :", convert.units(xyzt2space(object@"xyzt_units")),
fill=TRUE)
cat(" Time Units :", convert.units(xyzt2time(object@"xyzt_units")),
fill=TRUE)
})
#############################################################################
## setValidity("nifti")
#############################################################################
setValidity("nifti", function(object) {
retval <- NULL
indices <- 1 + 1:object@"dim_"[1]
## sizeof_hdr must be 348
if (object@"sizeof_hdr" != 348) {
retval <- c(retval, "sizeof_hdr != 348\n")
}
## datatype needed to specify type of image data
if (! object@datatype %in% convert.datatype()) {
retval <- c(retval, "datatype not recognized\n")
}
## bitpix should correspond correctly to datatype
if (object@bitpix != convert.bitpix()[[convert.datatype(object@datatype)]]) {
retval <- c(retval, "bitpix does not match the datatype\n")
}
## dim should be non-zero for dim[1] dimensions
if (! all(object@"dim_"[indices] > 0)) {
retval <- c(retval, "dim[1]/dim mismatch\n")
}
## dim should be one for all >dim[1] dimensions
if (! all(object@"dim_"[(max(indices) + 1):8] == 1)) {
retval <- c(retval, "all dim elements > dim[1] must be 1\n")
}
## number of data dimensions should match dim[1]
if (length(indices) != length(dim(object@.Data))) {
retval <- c(retval, "dim[1]/img mismatch\n")
}
##
if (object@"cal_min" != min(object@.Data, na.rm=TRUE) ||
object@"cal_max" != max(object@.Data, na.rm=TRUE)) {
retval <- c(retval, "range(img) != c(cal_min,cal_max)\n")
}
## pixdim[0] is required when qform_code != 0
if (object@"qform_code" != 0 && pixdim(object)[1] == 0) {
retval <- c(retval, "pixdim[1] is required\n")
}
## pixdim[n] required when dim[n] is required
if (! all(object@"dim_"[indices] > 0 & pixdim(object)[indices] > 0)) {
retval <- c(retval, "dim/pixdim mismatch\n")
}
## data dimensions should match dim
if (! isTRUE(all.equal(object@"dim_"[indices], dim(object@.Data)))) {
retval <- c(retval, "dim/img mismatch\n")
}
## vox_offset required for an "n+1" header
if (object@"magic" == "n+1" && object@"vox_offset" == 0) {
retval <- c(retval, "vox_offset required when magic=\"n+1\"\n")
}
## magic must be "ni1\0" or "n+1\0"
if (! (object@"magic" == "n+1" || object@"magic" == "ni1")) {
retval <- c(retval, "magic != \"n+1\" and magic != \"ni1\"\n")
}
if (is.null(retval)) {
return(TRUE)
} else {
return(retval)
}
})
#############################################################################
## setClass("niftiExtension")
#############################################################################
#' @title Class "niftiExtension"
#'
#' @description An extension of the NIfTI class that allows \dQuote{extensions}
#' that conform to the NIfTI data standard.
#'
#' @name niftiExtension-class
#' @docType class
#' @section Objects from the Class: Objects can be created by calls of the form
#' \code{new("niftiExtension", data, dim, dimnames, ...)}.
#' @author Andrew Thornton \email{zeripath@@users.sourceforge.net}
#' @seealso \code{\linkS4class{nifti}}, \code{\linkS4class{niftiAuditTrail}}
#' @references NIfTI-1\cr \url{http://nifti.nimh.nih.gov/}
#' @keywords classes
#' @examples
#' showClass("niftiExtension")
#' @export
setClass("niftiExtension",
representation(extensions="list"),
prototype(extensions=list()),
contains="nifti")
#############################################################################
## setClass("niftiAuditTrail")
#############################################################################
#' @title Class "niftiAuditTrail"
#'
#' @description An extension of the NIfTI class that adds an audit trail in XML format.
#'
#' @name niftiAuditTrail-class
#' @docType class
#' @section Objects from the Class: Objects can be created by calls of the form
#' \code{new("niftiAuditTrail", data, dim, dimnames, ...)}.
#' @author Andrew Thornton \email{zeripath@@users.sourceforge.net}
#' @seealso \code{\linkS4class{nifti}}, \code{\linkS4class{niftiExtension}}
#' @references NIfTI-1\cr \url{http://nifti.nimh.nih.gov/}
#' @section Methods:
#' \describe{
#' \item{show}{\code{signature(object = "niftiAuditTrail")}: prints out a
#' summary of the imaging data.}
#' }
#' @keywords classes
#' @examples
#'
#' showClass("niftiAuditTrail")
#'
#' @rdname niftiAuditTrail-class
#' @export
setClass("niftiAuditTrail",
representation(trail="ANY"),
prototype(trail=newAuditTrail()),
contains="niftiExtension")
#############################################################################
## setValidity("niftiExtension")
#############################################################################
setValidity("niftiExtension", function(object) {
## Allegedly setValidity will always check for superclasses.
## So we need only check that the list is empty or only contains
## niftiExtensionSections and check the validity of each of those
retval <- NULL
validSection <- getValidity(getClassDef("niftiExtensionSection"))
lapply(object@"extensions",
function(x) {
if (! is(x, "niftiExtensionSection")) {
retval <<- c(retval, paste("@extensions list contains non-niftiExtensionSection element:", class(x)))
} else {
if (! validSection(x)) {
retval <<- c(retval, validSection(x))
}
}
})
if (is.null(retval)) {
return(TRUE)
} else {
return(retval)
}
})
#############################################################################
## setValidity("niftiExtensionSection")
#############################################################################
setValidity("niftiExtensionSection", function(object) {
retval <- NULL
if (object@esize %% 16 != 0) {
retval <- c(retval, "esize is not a multiple of 16")
}
if ((object@esize - 8) < nchar(object@edata, type="bytes")) {
retval <- c(retval, "esize is too small for the data contained within the section")
}
if (is.null(retval)) {
return(TRUE)
} else {
return(retval)
}
})
## setGeneric("img", function(object) { standardGeneric("img") })
## setMethod("img", "nifti", function(object) { object@.Data })
## setGeneric("img<-", function(x, value) { standardGeneric("img<-") })
## setReplaceMethod("img", signature(x="nifti", value="array"),
## function(x, value) {
## x@.Data <- value
## x
## })
## setGeneric("hdr", function(object) { standardGeneric("hdr") })
## setMethod("hdr", "nifti", # signature(object="nifti", name="ANY"),
## function(object) { object@"descrip" })
## setGeneric("hdr<-", function(x, name, value) { standardGeneric("hdr<-") })
## setReplaceMethod("hdr", signature(x="nifti", name="character", value="ANY"),
## function(x, name, value) {
## x@name <- value
## validNIfTI <- getValidity(getClassDef("nifti"))
## validNIfTI(x)
## x
## })
#############################################################################
## nifti()
#############################################################################
#' @name nifti
#' @title Constructor for NIfTI
#'
#' @description Constructor for NIfTI class objects.
#'
#' @aliases nifti
#' @param img is a multidimensional array of data.
#' @param dim is the dimension of the data (default = \code{missing}).
#' @param datatype is an integer that denotes the type of data contained in
#' each voxel. See \code{convert.datatype} or the NIfTI documentation for more
#' details.
#' @param cal.min allows user-specified minimum value in the array
#' (visualization purposes only).
#' @param cal.max allows user-specified minimum value in the array
#' (visualization purposes only).
#' @param pixdim allows user-specified pixel dimension vector (length = 8).
#' @param \dots allows for additional \sQuote{slots} to be specified.
#' @return An object of class \code{nifti}.
#' @author Brandon Whitcher \email{bwhitcher@@gmail.com}
#' @seealso \code{\linkS4class{nifti}}, \code{\link{anlz}},
#' \code{\link{convert.datatype}}
#' @references NIfTI-1\cr \url{http://nifti.nimh.nih.gov/}
#' @examples
#'
#' options("niftiAuditTrail"=FALSE)
#'
#' nim <- nifti() # default
#' nim
#' nim <- nifti(datatype=4) # 2-byte integers
#' nim
#' @export
nifti <- function(img=array(0, dim=rep(1,4)), dim, datatype=2,
cal.min=NULL, cal.max=NULL, pixdim=NULL, ...) {
## Set dimensions
if (missing(dim)) {
if (is.array(img)) {
dim <- base::dim(img)
} else {
dim <- c(1, length(img))
}
}
ld <- length(dim)
## Create "dim" and "pixdim" slots
x <- rep(1, 8)
x[1] <- length(dim)
y <- rep(0.0, 8)
for (i in 2:length(x)) {
x[i] <- ifelse(is.na(dim(img)[i-1]), 1, dim(img)[i-1])
y[i] <- ifelse(is.na(dim(img)[i-1]) || is.null(pixdim), 1.0, pixdim[i])
}
## min/max values for visualization
if (is.null(cal.max)) {
cal.max <- as.numeric(max(img, na.rm=TRUE))
}
if (is.null(cal.min)) {
cal.min <- as.numeric(min(img, na.rm=TRUE))
}
## Set datatype
switch(as.character(datatype),
"2" = bitpix <- 8,
"4" = bitpix <- 16,
"8" = bitpix <- 32,
"16" = bitpix <- 32,
"64" = bitpix <- 64,
"512" = bitpix <- 16,
stop(paste("Data type", datatype, "unsupported."))
)
## Create the object
niftiClass <- "nifti"
if (getOption("niftiAuditTrail")) {
niftiClass <- "niftiAuditTrail"
}
obj <- new(niftiClass, .Data=array(img, dim=dim), "dim_"=x, "pixdim"=y,
"cal_max"=cal.max, "cal_min"=cal.min, "datatype"=datatype,
"bitpix"=bitpix, ...)
if (getOption("niftiAuditTrail")) {
audit.trail(obj) <- niftiAuditTrailCreated(call=match.call())
}
validNIfTI <- getValidity(getClassDef("nifti"))
validNIfTI(obj)
return(obj)
}
#' @title Extract or Replace NIfTI Audit Trail
#'
#' @description Operators that act on the audit trail (XML) in the NIfTI header.
#'
#' @name audit.trail-methods
#' @aliases audit.trail-methods audit.trail,nifti-method audit.trail
#' audit.trail<-,nifti-method audit.trail<-
#' @docType methods
#' @param object is of class \code{nifti}.
#' @param value Value to assign to trail slot
#' @section Methods:
#' \describe{
#' \item{object = "nifti"}{Extract or replace NIfTI audit trail.}
#' }
#' @author Andrew Thornton \email{zeripath@@users.sourceforge.net}
#' @keywords methods
#' @export
#' @rdname audit_trail-methods
setGeneric("audit.trail", function(object) standardGeneric("audit.trail"))
#' @export
#' @rdname audit_trail-methods
#' @aliases audit.trail,nifti-method
setMethod("audit.trail", "nifti",
function(object) {
if (getOption("niftiAuditTrail") &&
is(object, "niftiAuditTrail")) {
object@"trail"
} else {
NULL
}
})
#' @export
#' @rdname audit_trail-methods
setGeneric("audit.trail<-",
function(object, value) standardGeneric("audit.trail<-") )
#' @export
#' @rdname audit_trail-methods
setReplaceMethod("audit.trail", "nifti",
function(object, value) {
if (getOption("niftiAuditTrail")) {
if (!is(object, "niftiAuditTrail")) {
object <- as(object, "niftiAuditTrail")
}
object@"trail" <- value
}
return(object)
})
#' @export
setReplaceMethod("[",
signature(x="nifti", i="missing", j="missing", value="array"),
function(x, value) {
x <- as.nifti(value, x)
validNIfTI <- getValidity(getClassDef("nifti"))
validNIfTI(x)
return(x)
})
#' @export
setReplaceMethod("[", signature(x="nifti", i="ANY", j="missing", value="ANY"),
function(x, i, value) {
## For some reason this line is slow; I don't understand it
x@.Data[i] <- value
if (any(value < x@"cal_min", na.rm=TRUE)) {
x@"cal_min" <- min(value, na.rm=TRUE)
}
if (any(value > x@"cal_max", na.rm=TRUE)) {
x@"cal_max" <- max(value, na.rm=TRUE)
}
audit.trail(x) <-
niftiAuditTrailEvent(x, "modification", call=sys.call(-3),
comment=paste("Non-numeric replace ["))
return(x)
})
#' @export
setReplaceMethod("[",
signature(x="nifti", i="numeric", j="missing", value="ANY"),
function(x, i, value) {
## For some reason this line is slow; I don't understand it
x@.Data[i] <- value
if (any(value < x@"cal_min", na.rm=TRUE)) {
x@"cal_min" <- min(value, na.rm=TRUE)
}
if (any(value > x@"cal_max", na.rm=TRUE)) {
x@"cal_max" <- max(value, na.rm=TRUE)
}
audit.trail(x) <- niftiAuditTrailEvent(x, "modification",
call=sys.call(-3))
return(x)
})
#' @export
setReplaceMethod("[", signature(x="nifti", i="ANY", j="ANY", value="ANY"),
function(x, i, j, ..., value) {
## For some reason this line is slow; I don't understand it
x@.Data[i,j,...] <- value
audit.trail(x) <-
niftiAuditTrailEvent(x, "modification", call=sys.call(-3),
comment=paste("Non-numeric replace ["))
return(x)
})
#' @export
setReplaceMethod("[",
signature(x="nifti", i="numeric", j="numeric", value="ANY"),
function(x, i, j, ..., value) {
## For some reason this line is slow; I don't understand it
x@.Data[i,j,...] <- value
if (any(value < x@"cal_min", na.rm=TRUE)) {
x@"cal_min" <- min(value, na.rm=TRUE)
}
if (any(value > x@"cal_max", na.rm=TRUE)) {
x@"cal_max" <- max(value, na.rm=TRUE)
}
audit.trail(x) <-
niftiAuditTrailEvent(x, "modification",
comment=paste("[", paste(i, j, ..., sep=", "), "] <- ", value, sep=""))
return(x)
})
#############################################################################
## sform() accessor function to srow_*
#############################################################################
#' @title Extract NIfTI 3D Image Orientation
#'
#' @description Methods that act on the \dQuote{qform} and \dQuote{sform} information in the
#' NIfTI header.
#'
#' @name orientation-methods
#' @aliases qform-methods qform,nifti-method qform sform-methods
#' sform,nifti-method sform
#' @docType methods
#' @param object is an object of class \code{nifti}.
#' @section Methods:
#' \describe{
#' \item{object = "nifti"}{Extract or replace NIfTI description.}
#' }
#' @author Brandon Whitcher \email{bwhitcher@@gmail.com}
#' @keywords methods
#' @examples
#'
#' \dontrun{
#' url <- "http://nifti.nimh.nih.gov/nifti-1/data/avg152T1_LR_nifti.nii.gz"
#' urlfile <- file.path(system.file("nifti", package="oro.nifti"),
#' "mniLR.nii.gz")
#' download.file(url, urlfile, quiet=TRUE)
#' }
#' urlfile <- file.path(system.file("nifti", package="oro.nifti"),
#' "mniLR.nii.gz")
#' mniLR <- readNIfTI(urlfile)
#' sform(mniLR)
#' @export
#' @rdname orientation-methods
setGeneric("sform", function(object) standardGeneric("sform"))
#' @export
#' @rdname orientation-methods
setMethod("sform", "nifti",
function(object) {
matrix(c(object@"srow_x", object@"srow_y", object@"srow_z"),
ncol=4, byrow=TRUE)
})
#############################################################################
## qform() accessor function to quatern_*, qoffset_*
#############################################################################
#' @export
#' @rdname orientation-methods
setGeneric("qform", function(object) standardGeneric("qform"))
#' @export
#' @rdname orientation-methods
setMethod("qform", "nifti", function(object) { quaternion2mat44(object) })
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.