REOF <- function(ano, lon, lat, ntrunc) {
  nlat <- length(lat)
  nlon <- length(lon)
  ntimes <- dim(ano)[1]
  
  if (is.null(ntrunc) || ntrunc %% 1!=0 || ntrunc <= 0) stop("Parameter 'ntrunc' must be an integer positive number greater than zero")
  if (ntrunc > min(ntimes, nlat * nlon)) stop(paste0("Parameter 'ntrunc' must be equal or smaller than ", min(ntimes,nlat*nlon))) 

  ## Get the first ntrunc EOFs:
  eofs <- EOF(ano = ano, lon = lon, lat = lat, neofs = ntrunc)

  ## Recover loadings (with norm 1), weighting the EOFs by the weigths, then put them as a two-dimensional array
  Loadings <- eofs$EOFs * InsertDim(eofs$wght, 1, ntrunc)
  dim(Loadings) <- c(ntrunc, nlat * nlon)

  ## Rotate the loadings:
  varim <- varimax(t(Loadings))

  ## Weight back the rotated loadings (REOFs):
  REOFs <- varim$loadings
  dim(REOFs) <- c(nlat, nlon, ntrunc)
  REOFs <- REOFs / InsertDim(eofs$wght, 3, ntrunc)

  ## Reorder dimensions to match EOF conventions: (ntrunc,nlat,nlon)
  REOFs <- aperm(REOFs,c(3,1,2))

  ## Compute the rotated PCs (RPCs): just multiply the weigthed anomalies by the loading patterns.
  ano.wght <- ano * InsertDim(eofs$wght, 1, ntimes)
  dim(ano.wght) <- c(ntimes, nlat * nlon)
  RPCs <- ano.wght %*% varim$loadings

  ## Alternative methods suggested here:
  ## https://stats.stackexchange.com/questions/59213/how-to-compute-varimax-rotated-principal-components-in-r/137003#137003
  ## gives same results as pinv is just transpose in this case, as loadings are ortonormal!
  # invLoadings <- t(pracma::pinv(varim$loadings)) ## invert and traspose the rotated loadings. pinv uses a SVD again (!)
  # RPCs <- ano.wght %*% invLoadings

  ## Compute explained variance fraction:
  var <- apply(RPCs,2, function(x) { sum (x*x) } ) * 100 / eofs$tot_var
  dim(var) <- c(reofs = length(var))
  dim(RPCs) <- dim(eofs$PCs)
  names(dim(RPCs))[2] <- 'rpc'
  dim(REOFs) <- dim(eofs$EOFs)
  names(dim(REOFs))[1] <- 'reof'
  return(list(REOFs = REOFs, RPCs = RPCs, wght = eofs$wght, var = var))
}
