% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/method-map.R
\name{fmap}
\alias{fmap}
\alias{fmap2}
\alias{fmap_element_wise}
\title{Map multiple file arrays and save results}
\usage{
fmap(
  x,
  fun,
  .y = NULL,
  .buffer_count = NA_integer_,
  .output_size = NA_integer_,
  ...
)

fmap2(x, fun, .buffer_count = NA, .simplify = TRUE, ...)

fmap_element_wise(x, fun, .y, ..., .input_size = NA)
}
\arguments{
\item{x}{a list of file arrays to map; each element of \code{x} must 
share the same dimensions.}

\item{fun}{function that takes one list}

\item{.y}{a file array object, used to save results}

\item{.buffer_count}{number of total buffers (chunks) to run}

\item{.output_size}{\code{fun} output vector length}

\item{...}{other arguments passing to \code{fun}}

\item{.simplify}{whether to apply \code{\link[base]{simplify2array}} to 
the result}

\item{.input_size}{number of elements to read from each array of \code{x}}
}
\value{
File array instance \code{.y}
}
\description{
Advanced mapping function for multiple file arrays. \code{fmap}
runs the mapping functions and stores the results in file arrays. 
\code{fmap2} stores results in memory. This 
feature is experimental. There are several constraints to the input. 
Failure to meet these constraints may result in undefined results, or 
even crashes. Please read Section 'Details' carefully before using 
this function.
}
\details{
Denote the first argument of \code{fun} as \code{input}, The length 
of \code{input} equals the length of \code{x}. The size of each
element of \code{input} is defined by \code{.input_size}, except for the
last loop. For example, given dimension of each input array as 
\eqn{10x10x10x10}, if \code{.input_size=100}, then 
\code{length(input[[1]])=100}. The total number of runs equals to
\code{length(x[[1]])/100}. If \code{.input_size=300}, then 
\code{length(input[[1]])} will be \code{300} except for the last run. 
This is because \eqn{10000} cannot be divided by \code{300}. 
The element length of the last run will be \code{100}. 

The returned variable length of \code{fun} will be checked by 
\code{.output_size}. If the output length exceed \code{.output_size}, 
an error will be raised.

Please make sure that \code{length(.y)/length(x[[1]])} equals to 
\code{.output_size/.input_size}.

For \code{fmap_element_wise}, the \code{input[[1]]} and output length 
must be the consistent.
}
\examples{


set.seed(1)
x1 <- filearray_create(tempfile(), dimension = c(100,20,3))
x1[] <- rnorm(6000)
x2 <- filearray_create(tempfile(), dimension = c(100,20,3))
x2[] <- rnorm(6000)

# Add two arrays
output <- filearray_create(tempfile(), dimension = c(100,20,3))
fmap(list(x1, x2), function(input) {
    input[[1]] + input[[2]]
}, output)

# check
range(output[] - (x1[] + x2[]))

output$delete()

# Calculate the maximum of x1/x2 for every 100 elements
# total 60 batches/loops (`.buffer_count`)
output <- filearray_create(tempfile(), dimension = c(20,3))
fmap(list(x1, x2), function(input) {
    max(input[[1]] / input[[2]])
}, .y = output, .buffer_count = 60)

# check
range(output[] - apply(x1[] / x2[], c(2,3), max))

output$delete()

# A large array example
if(interactive()) {
    x <- filearray_create(tempfile(), dimension = c(287, 100, 301, 4))
    dimnames(x) <- list(
        Trial = 1:287,
        Marker = 1:100,
        Time = 1:301,
        Location = 1:4
    )

    for (i in 1:4) {
        x[,,,i] <- runif(8638700)
    }
    # Step 1:
    # for each location, trial, and marker, calibrate (baseline)
    # according to first 50 time-points

    output <- filearray_create(tempfile(), dimension = dim(x))

    # baseline-percentage change
    fmap(
        list(x),
        function(input) {
            # get locational data
            location_data <- input[[1]]
            dim(location_data) <- c(287, 100, 301)

            # collapse over first 50 time points for
            # each trial, and marker
            baseline <- apply(location_data[,,1:50], c(1,2), mean)

            # calibrate
            calibrated <- sweep(location_data, c(1,2), baseline,
                                FUN = function(data, bl) {
                                    (data / bl - 1) * 100
                                })
            return(calibrated)
        },

        .y = output,

        # input dimension is 287 x 100 x 301 for each location
        # hence 4 loops in total
        .buffer_count = 4
    )

    # cleanup
    x$delete()

}

# cleanup
x1$delete()
x2$delete()
output$delete()
}
