---
title: "How to perform a kfino outlier detection on multiple individuals"
author: "B. Cloez & I. Sanchez"
date:  "`r format(Sys.time(), '%B %d, %Y')`"
output:
  html_document:
    toc: yes
    toc_float: true
    number_sections: true
vignette: >
  %\VignetteIndexEntry{How to perform a kfino outlier detection on multiple individuals}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

```{r setup}
library(kfino)
library(dplyr)
library(foreach)
library(parallel)
library(doParallel)
```

This vignette shows how to use parallelization on a data set containing a set of animals weighted over time with the walk-over-weighing system. 
The `lambs` data set is included in the **kfino** package and can be loaded using the `data()` function. 

We use the **parallel** and **doParallel** libraries to accelerate the computing time.

```{r}
data(lambs)
myIDE<-unique(lambs$IDE)

print(myIDE)
```

# Without parallelization

```{r,error=TRUE}
param=list(m0=NULL,
             mm=NULL,
             pp=NULL,
             aa=0.001,
             expertMin=10,
             expertMax=45,
             sigma2_m0=1,
             sigma2_mm=0.05,
             sigma2_pp=5,
             K=15,
             seqp=seq(0.4,0.7,0.1))

t0 <- Sys.time()
resu1<-list()

for (i in seq_along(myIDE)){
  print(myIDE[i])
  tp.test<-filter(lambs,IDE == myIDE[i])
  print(dim(tp.test))
  resu1[[i]]<-kfino_fit(datain=tp.test,
              Tvar="dateNum",Yvar="Poids",
              param=param,
              doOptim=TRUE)
}
Sys.time() - t0

print(length(resu1))

```

# Parallel execution

An example improving the computation time of a run on a complete dataset by parallelizing the call.

```{r,error=TRUE}

param=list(m0=NULL,
             mm=NULL,
             pp=NULL,
             aa=0.001,
             expertMin=10,
             expertMax=45,
             sigma2_m0=1,
             sigma2_mm=0.05,
             sigma2_pp=5,
             K=15,
             seqp=seq(0.4,0.7,0.1))

t0<-Sys.time()

simpleCall<-function(datain,Index,Tvar,Yvar,param){
  datain<-as.data.frame(datain)
  ici<-unique(datain[,"IDE"])
  tp.data<-datain[ datain[,"IDE"] == ici[Index],]

  tp.resu<-kfino::kfino_fit(datain=tp.data,
              Tvar=Tvar,Yvar=Yvar,
              param=param,
              doOptim=TRUE)
  return(tp.resu)
}

ncores<-parallel::detectCores()
myCluster<-parallel::makeCluster(ncores - 1)
doParallel::registerDoParallel(myCluster)

resu2<-foreach(i=seq_along(myIDE), .packages="kfino") %dopar% 
            simpleCall(datain=lambs,
                       Index=i,
                       Tvar="dateNum",
                       Yvar="Poids",
                       param=param)

parallel::stopCluster(myCluster)
Sys.time() - t0

print(length(resu2))

```

```{r}
identical(resu1,resu2)
```

# References

1. E.González-García *et. al.* (2018) A mobile and automated walk-over-weighing system for a close and remote monitoring of liveweight in sheep. vol 153: 226-238. https://doi.org/10.1016/j.compag.2018.08.022
2. Corporation M, Weston S (2022). _doParallel: Foreach Parallel Adaptor for the 'parallel' Package_. R package version 1.0.17,
  <https://CRAN.R-project.org/package=doParallel>.


# session info
```{r}
sessionInfo()
```
