#############################################
# R Codes for paper "Modelling finger force produced from different tasks 
# using linear mixed models with lme R function"
# Caroline Bazzoli, Frédérique Letué, Marie-José Martinez
# Université de Grenoble, LJK
# Conforme Latex, 27/05/2014
#############################################
library(nlme)
###################
# 2. The data     #
###################

#loading the data
read.table("data.txt",header=TRUE)-> Data
attach(Data)
summary(Data)

# Defining the variables
F<-c(I.ExtP3,M.ExtP3,R.ExtP3,L.ExtP3,I.FlexP3,M.FlexP3,R.FlexP3,
     L.FlexP3,I.ExtP1,M.ExtP1,R.ExtP1,L.ExtP1)
location <- gl(3,180,540,labels=c("ExtP3","FlexP3","ExtP1"))
finger <- gl(4,45,540,labels=c("I","M","R","L"))
individual <- as.factor(rep(rep(1:15,each=3),12))
trial <- as.factor(c(rep(1:45,4),rep(1:45,4)+45,rep(1:45,4)+90))
Data.new<-data.frame(F,location,finger,individual,trial)
head(Data.new,200)
###############################
# 3.Preliminary study         #
#################################
# 3.1 Exploratory data analysis #
#################################
# raw data by location, finger and individual
# ***Figure 1***
op<-par(mfrow=c(1,3))
plot(I.ExtP3~as.numeric(individual)[(location=="ExtP3")&(finger=="I")],
     col="blue",pch=1,
     ylim=c(0,50),main="Location ExtP3",
     xlab="individual",ylab="Finger force intensity")
points(M.ExtP3~individual[(location=="ExtP3")&(finger=="M")],
       col="red",pch=2)
points(R.ExtP3~individual[(location=="ExtP3")&(finger=="R")],
       col="green",pch=3)
points(L.ExtP3~individual[(location=="ExtP3")&(finger=="L")],
       col="magenta",pch=4)
legend("topleft",c("I","M","R","L"),pch=1:4,
       col=c("blue","red","green","magenta"))

plot(I.FlexP3~as.numeric(individual)[(location=="FlexP3")&(finger=="I")],
     col="blue",pch=1,
     ylim=c(0,50),main="Location FlexP3",
     xlab="individual",ylab="Finger force intensity")
points(M.FlexP3~individual[(location=="ExtP3")&(finger=="M")],
       col="red",pch=2)
points(R.FlexP3~individual[(location=="ExtP3")&(finger=="R")],
       col="green",pch=3)
points(L.FlexP3~individual[(location=="ExtP3")&(finger=="L")],
       col="magenta",pch=4)
legend("topleft",c("I","M","R","L"),pch=1:4,
       col=c("blue","red","green","magenta"))

plot(I.ExtP1~as.numeric(individual)[(location=="ExtP1")&(finger=="I")],
     col="blue",pch=1,
     ylim=c(0,50),main="Location ExtP1",
     xlab="individual",ylab="Finger force intensity")
points(M.ExtP1~individual[(location=="ExtP3")&(finger=="M")],
       col="red",pch=2)
points(R.ExtP1~individual[(location=="ExtP3")&(finger=="R")],
       col="green",pch=3)
points(L.ExtP1~individual[(location=="ExtP3")&(finger=="L")],
       col="magenta",pch=4)
legend("topleft",c("I","M","R","L"),pch=1:4,
       col=c("blue","red","green","magenta"))
#***
# finger correlation 
#***Figure 2***
op<-par(mfrow=c(1,1))
index<-c(I.ExtP3,I.FlexP3,I.ExtP1)
middle<-c(M.ExtP3,M.FlexP3,M.ExtP1)
ring<-c(R.ExtP3,R.FlexP3,R.ExtP1)
little<-c(L.ExtP3,L.FlexP3,L.ExtP1)
cor(cbind(index,middle,ring,little))
plot(data.frame(index,middle,ring,little),pch=rep(1:3,each=60),
     col=rep(1:3,each=60))
#***
#######################################
# 3.2 Two-factor ANOVA and its limits #
#######################################
fit<-lm(F~location*finger)
anova(fit)
summary(fit)
plot(fit)

# residuals
#***Figure 3***
res <- fit$residuals
col <- as.numeric(finger)
pch <- as.numeric(finger)
op<-par(mfrow=c(1,3))
plot(res[location=="ExtP3"]~as.numeric(individual)[location=="ExtP3"],
     col=col,pch=pch,
     ylim=c(-21,21), main="Location ExtP3",
     xlab="Individual",ylab="residuals")
legend("topright",c("I","M","R","L"),pch=1:4,
       col=c("blue","red","green","magenta"))

plot(res[location=="FlexP3"]~as.numeric(individual)[location=="FlexP3"],
     col=col,pch=pch,
     ylim=c(-21,21), main="Location FlexP3",
     xlab="Individual",ylab="residuals")
legend("topleft",c("I","M","R","L"),pch=1:4,
       col=c("blue","red","green","magenta"))

plot(res[location=="ExtP1"]~as.numeric(individual)[location=="ExtP1"],
     col=col,pch=pch,
     ylim=c(-21,21),main="Location ExtP1",
     xlab="Individual",ylab="residuals")
legend("topright",c("I","M","R","L"),pch=1:4,
       col=c("blue","red","green","magenta"))
#***
# residuals correlation
#***Figure 4***
op<-par(mfrow=c(1,1))
index.res<-res[finger=="I"]
middle.res<-res[finger=="M"]
ring.res<-res[finger=="R"]
little.res<-res[finger=="L"]
cor(cbind(index.res,middle.res,ring.res,little.res))
plot(data.frame(index.res,middle.res,ring.res,little.res),
     pch=rep(1:3,each=60),col=rep(1:3,each=60))
#***
#############################################################
# 4. Model specification using a linear mixed-effects model #
#############################################################
# 4.1 Modelling the random effect structure #
#############################################
#***Table 1***
library(nlme)
fitM0 <- lme(F ~ finger*location, random=~1|individual, method="ML")
summary(fitM0)
resM0.std<-residuals(fitM0,type="pearson")
#***Figure 5***
plot(fitM0,individual~resM0.std|location,abline=0,xlim=c(-5,5),
     xlab="Standardized residuals")
#***Figure 6***
plot(fitM0,individual~resM0.std|finger,abline=0,xlim=c(-5,5),
     xlab="Standardized residuals")
#***
# individual random effects with identical variances
#***Table 2***
fitM1 <- lme(F ~ finger*location, 
            random=list(individual=pdBlocked(list(pdIdent(~1),
                                                  pdIdent(~location-1),
                                                  pdIdent(~finger-1),
                                                  pdIdent(~location:finger-1)))),
            method="ML")
resM1.std<-residuals(fitM1,type="pearson")
#***Figure 7***
plot(fitM1,individual~resM1.std|location,abline=0,xlim=c(-5,5),
     xlab="Standardized residuals")
#***Figure 8***
plot(fitM1,individual~resM1.std|finger,abline=0,xlim=c(-5,5),
     xlab="Standardized residuals")
#***
#***Table 3***
fitM2 <- lme(F ~ finger*location, 
               random=list(individual=pdBlocked(list(pdIdent(~1),
                                                     pdDiag(~location-1),
                                                     pdIdent(~finger-1),
                                                     pdIdent(~location:finger-1)))),
               method="ML",control=lmeControl(msMaxIter=1000))

resM2.std<-residuals(fitM2,type="pearson")
#***Table 4***
anova(fitM0,fitM1,fitM2)
# residuals correlation from model M2
#***Figure 9***
op<-par(mfrow=c(1,1))
index.resM2.std<-resM2.std[finger=="I"]
middle.resM2.std<-resM2.std[finger=="M"]
ring.resM2.std<-resM2.std[finger=="R"]
little.resM2.std<-resM2.std[finger=="L"]
cor(cbind(index.resM2.std,middle.resM2.std,ring.resM2.std,little.resM2.std))
plot(data.frame(index.resM2.std,middle.resM2.std,ring.resM2.std,little.resM2.std),
     pch=rep(1:3,each=60),col=rep(1:3,each=60))
#***
############################################################
# 4.2 Modelling the residual variance-covariance structure #
############################################################
# 4.2.1  Modelling the variance matrix for each location #
##########################################################
#***Table 5***
fitM2.1 <- lme(F ~ finger*location, 
             random=list(individual=pdBlocked(list(pdIdent(~1),
                                                   pdDiag(~location-1),
                                                   pdIdent(~finger-1),
                                                   pdIdent(~location:finger-1)))),
             weights=varIdent(form=~1|location),
             method="ML",control=lmeControl(msMaxIter=1000))
#***Table 6***
anova(fitM2,fitM2.1)
resM2.1.std<-residuals(fitM2.1,type="pearson")
#***Figure 10***
op<-par(mfrow=c(1,2))
boxplot(resM2.std~location,xlab="Location",
        ylab="Standardized residuals",
        main="Standardized residuals vs Location for M2",
        ylim=c(-4,4))
boxplot(resM2.std~finger,xlab="Finger",
        ylab="Standardized residuals",
        main="Standardized residuals vs Finger for M2",
        ylim=c(-4,4))
#***Figure 11***
op<-par(mfrow=c(1,2))
boxplot(resM2.1.std~location,xlab="Location",
        ylab="Standardized residuals",
        main="Standardized residuals vs Location for M2.1",
        ylim=c(-4,4))
boxplot(resM2.1.std~finger,xlab="Finger",
        ylab="Standardized residuals",
        main="Standardized residuals vs Finger for M2.1",
        ylim=c(-4,4))
#***
Index<-(finger=="I")
Index[Index==TRUE]<-"I"
Index[Index==FALSE]<-"other"
fitM2.2 <- lme(F ~ finger*location, 
               random=list(individual=pdBlocked(list(pdIdent(~1),
                                                     pdDiag(~location-1),
                                                     pdIdent(~finger-1),
                                                     pdIdent(~location:finger-1)))),
               weights=varIdent(form=~1|location*Index),
               method="ML",control=lmeControl(msMaxIter=1000))
anova(fitM2.1,fitM2.2)
resM2.2.std<-residuals(fitM2.2,type="pearson")
#***Figure 12***
op<-par(mfrow=c(1,2))
boxplot(resM2.2.std~location,xlab="Location",
        ylab="Standardized residuals",
        main="Standardized residuals vs Location for M2.2",
        ylim=c(-4,4))
boxplot(resM2.2.std~finger,xlab="Finger",
        ylab="Standardized residuals",
        main="Standardized residuals vs Finger for M2.2",
        ylim=c(-4,4))
#***
# residuals correlation from model M2.2
#***Table 7***
op<-par(mfrow=c(1,1))
index.resM2.2.std<-resM2.2.std[finger=="I"]
middle.resM2.2.std<-resM2.2.std[finger=="M"]
ring.resM2.2.std<-resM2.2.std[finger=="R"]
little.resM2.2.std<-resM2.2.std[finger=="L"]
cor(cbind(index.resM2.2.std,middle.resM2.2.std,ring.resM2.2.std,little.resM2.2.std))
plot(data.frame(index.resM2.2.std,middle.resM2.2.std,ring.resM2.2.std,little.resM2.2.std),
     pch=rep(1:3,each=60),
     main="Residuals correlation by finger",col=rep(1:3,each=60))
#***

#############################################
# 4.2.2  Modelling the correlation matrix   #
#############################################
fitM2.3 <- lme(F ~ finger*location, 
                         random=list(individual=pdBlocked(list(pdIdent(~1),
                                                               pdDiag(~location-1),
                                                               pdIdent(~finger-1),
                                                               pdIdent(~location:finger-1)))),                             
                         weights=varIdent(form=~1|location*Index),
                         correlation=corSymm(form=~1|individual/trial),
                         method="ML", control=lmeControl(msMaxIter=1000))
#***Table 8***
anova(fitM2.2, fitM2.3)

resM2.3.norm<-residuals(fitM2.3,type="normalized")
#***Figure 13***
op<-par(mfrow=c(1,2))
boxplot(resM2.3.norm~location,xlab="Location",
        ylab="Normalized residuals",
        main="Normalized residuals vs Location for M2.3")
boxplot(resM2.3.norm~finger,xlab="Finger",
        ylab="Normalized residuals",
        main="Normalized residuals vs Finger for M2.3")
#***
# residuals correlation from model M2.3
#***Table 9***
op<-par(mfrow=c(1,1))
index.resM2.3.norm<-resM2.3.norm[finger=="I"]
middle.resM2.3.norm<-resM2.3.norm[finger=="M"]
ring.resM2.3.norm<-resM2.3.norm[finger=="R"]
little.resM2.3.norm<-resM2.3.norm[finger=="L"]
cor(cbind(index.resM2.3.norm,middle.resM2.3.norm,ring.resM2.3.norm,little.resM2.3.norm))
plot(data.frame(index.resM2.3.norm,middle.resM2.3.norm,ring.resM2.3.norm,little.resM2.3.norm),
     pch=rep(1:3,each=60),
     main="Residuals correlation by finger from model M2.3",col=rep(1:3,each=60))
#***
# finger correlation location by location  
#***Table 10***
index.ExtP3<-resM2.3.norm[finger=="I"&location=="ExtP3"]
middle.ExtP3<-resM2.3.norm[finger=="M"&location=="ExtP3"]
ring.ExtP3<-resM2.3.norm[finger=="R"&location=="ExtP3"]
little.ExtP3<-resM2.3.norm[finger=="L"&location=="ExtP3"]

index.FlexP3<-resM2.3.norm[finger=="I"&location=="FlexP3"]
middle.FlexP3<-resM2.3.norm[finger=="M"&location=="FlexP3"]
ring.FlexP3<-resM2.3.norm[finger=="R"&location=="FlexP3"]
little.FlexP3<-resM2.3.norm[finger=="L"&location=="FlexP3"]

index.ExtP1<-resM2.3.norm[finger=="I"&location=="ExtP1"]
middle.ExtP1<-resM2.3.norm[finger=="M"&location=="ExtP1"]
ring.ExtP1<-resM2.3.norm[finger=="R"&location=="ExtP1"]
little.ExtP1<-resM2.3.norm[finger=="L"&location=="ExtP1"]

print("ExtP3")
cor(cbind(index.ExtP3,middle.ExtP3,ring.ExtP3,little.ExtP3))
print("FlexP3")
cor(cbind(index.FlexP3,middle.FlexP3,ring.FlexP3,little.FlexP3))
print("ExtP1")
cor(cbind(index.ExtP1,middle.ExtP1,ring.ExtP1,little.ExtP1))
#***
############################################################
# 5  Results  #
############################################################
fitM2.3.REML <- lme(F ~ finger*location, 
                    random=list(individual=pdBlocked(list(pdIdent(~1),
                                                          pdDiag(~location-1),
                                                          pdIdent(~finger-1),
                                                          pdIdent(~location:finger-1)))),                             
                    weights=varIdent(form=~1|location*Index),
                    correlation=corSymm(form=~1|individual/trial),
                    method="REML", control=lmeControl(msMaxIter=1000))
#############################################
# 5.1  Residual analysis of the final model #
#############################################
resM2.3.REML<-residuals(fitM2.3.REML,type="normalized")
#***Figure 14***
op<-par(mfrow=c(2,2))
hist(resM2.3.REML,freq=FALSE,xlab="Normalized residuals",
     main="Histogram of the normalized residuals")
lines((-400:400)/100,dnorm((-400:400)/100))
qqnorm(resM2.3.REML)            
qqline(resM2.3.REML)            
plot(resM2.3.REML~fitted(fitM2.3.REML),xlab="Fitted values",
     ylab="Normalized residuals",
     main="Normalized residuals vs fitted values")
plot(resM2.3.REML~F,xlab="Observed values",
     ylab="Normalized residuals",
     main="Normalized residuals vs observed values")
#***
#########################
# 5.2  Results analysis #
#########################
#***Table 11***
summary(fitM2.3.REML)
# Residual standard deviation
#***Table 12***
fitM2.3.REML$sigma*unique(1/varWeights(fitM2.3.REML$modelStruct$varStruct))
# estimated means levels of the finger-location crossing groups
#***Table 13***
fitM2.3.REML$coefficients$fixed
fitM2.3.REML$coefficients$fixed[1] # ExtP3:I
fitM2.3.REML$coefficients$fixed[1]+fitM2.3.REML$coefficients$fixed[2] #ExtP3:M
fitM2.3.REML$coefficients$fixed[1]+fitM2.3.REML$coefficients$fixed[3] #ExtP3:R
fitM2.3.REML$coefficients$fixed[1]+fitM2.3.REML$coefficients$fixed[4] #ExtP3:L

fitM2.3.REML$coefficients$fixed[1]+fitM2.3.REML$coefficients$fixed[5] # FlexP3:I
fitM2.3.REML$coefficients$fixed[1]+fitM2.3.REML$coefficients$fixed[2]+
  fitM2.3.REML$coefficients$fixed[5] +fitM2.3.REML$coefficients$fixed[7]#FlexP3:M
fitM2.3.REML$coefficients$fixed[1]+fitM2.3.REML$coefficients$fixed[3]+
  fitM2.3.REML$coefficients$fixed[5] +fitM2.3.REML$coefficients$fixed[8]#FlexP3:R
fitM2.3.REML$coefficients$fixed[1]+fitM2.3.REML$coefficients$fixed[4]+
  fitM2.3.REML$coefficients$fixed[5] + fitM2.3.REML$coefficients$fixed[9]#FlexP3:L

fitM2.3.REML$coefficients$fixed[1]+fitM2.3.REML$coefficients$fixed[6] # ExtP1:I
fitM2.3.REML$coefficients$fixed[1]+fitM2.3.REML$coefficients$fixed[2]+
  fitM2.3.REML$coefficients$fixed[6] +fitM2.3.REML$coefficients$fixed[10]# ExtP1:M
fitM2.3.REML$coefficients$fixed[1]+fitM2.3.REML$coefficients$fixed[3]+
  fitM2.3.REML$coefficients$fixed[6] +fitM2.3.REML$coefficients$fixed[11]# ExtP1:R
fitM2.3.REML$coefficients$fixed[1]+fitM2.3.REML$coefficients$fixed[4]+
  fitM2.3.REML$coefficients$fixed[6] + fitM2.3.REML$coefficients$fixed[12] # ExtP1:L

# contrastes
#***Table 14***
group <- gl(12,45,540,labels=c("ExtP3:I","ExtP3:M","ExtP3:R","ExtP3:L",
                               "FlexP3:I","FlexP3:M","FlexP3:R","FlexP3:L",
                               "ExtP1:I","ExtP1:M","ExtP1:R","ExtP1:L"))

library(MASS)
M.location<-cbind(
  c(1,0,0,0,-1,0,0,0,0,0,0,0), # ExtP3/FlexP3,I
  c(0,1,0,0,0,-1,0,0,0,0,0,0), # ExtP3/FlexP3,M
  c(0,0,1,0,0,0,-1,0,0,0,0,0), # ExtP3/FlexP3,R
  c(0,0,0,1,0,0,0,-1,0,0,0,0), # ExtP3/FlexP3,L
  c(1,0,0,0,0,0,0,0,-1,0,0,0), # ExtP3/ExtP1,I
  c(0,1,0,0,0,0,0,0,0,-1,0,0), # ExtP3/ExtP1,M
  c(0,0,1,0,0,0,0,0,0,0,-1,0), # ExtP3/ExtP1,R
  c(0,0,0,1,0,0,0,0,0,0,0,-1) # ExtP3/ExtP1,L
  )
contrasts(group)<-t(ginv(M.location))
fitM2.3.REML.location <- lme(F ~ group,
random=list(individual=pdBlocked(list(pdIdent(~1),
pdDiag(~location-1),
pdIdent(~finger-1),
pdIdent(~location:finger-1)))),
weights=varIdent(form=~1|location*Index),
correlation=corSymm(form=~1|individual/trial),
method="REML", control=lmeControl(msMaxIter=1000))
#***Table 15***
summary(fitM2.3.REML.location)

M.finger<-cbind(
  c(1,-1,0,0,0,0,0,0,0,0,0,0), # I/M, ExtP3
  c(0,0,0,0,1,-1,0,0,0,0,0,0), # I/M, FlexP3
  c(0,0,0,0,0,0,0,0,1,-1,0,0), # I/M, ExtP1
  c(0,1,-1,0,0,0,0,0,0,0,0,0), # M/R, ExtP3
  c(0,0,0,0,0,1,-1,0,0,0,0,0), # M/R, FlexP3
  c(0,0,0,0,0,0,0,0,0,1,-1,0), # M/R, ExtP1
  c(0,0,1,-1,0,0,0,0,0,0,0,0), # R/L, ExtP3
  c(0,0,0,0,0,0,1,-1,0,0,0,0), # R/L, FlexP3
  c(0,0,0,0,0,0,0,0,0,0,1,-1) # R/L, ExtP1
)
contrasts(group)<-t(ginv(M.finger))
fitM2.3.REML.finger <- lme(F ~ group,
                             random=list(individual=pdBlocked(list(pdIdent(~1),
                                                                   pdDiag(~location-1),
                                                                   pdIdent(~finger-1),
                                                                   pdIdent(~location:finger-1)))),
                             weights=varIdent(form=~1|location*Index),
                             correlation=corSymm(form=~1|individual/trial),
                             method="REML", control=lmeControl(msMaxIter=1000))
#***Table 16***
summary(fitM2.3.REML.finger)
#***

