[chronojump] WIP: MIF. bestFit function.



commit 208015c4f7751fba6bc239bbeae7e09a2f0d25cc
Author: Xavier Padullés <testing chronojump org>
Date:   Tue Nov 17 09:29:01 2020 +0100

    WIP: MIF. bestFit function.

 r-scripts/maximumIsometricForce.R | 1650 ++++++++++++++++++++-----------------
 1 file changed, 911 insertions(+), 739 deletions(-)
---
diff --git a/r-scripts/maximumIsometricForce.R b/r-scripts/maximumIsometricForce.R
index 9d1ae88f..ea10c5d4 100644
--- a/r-scripts/maximumIsometricForce.R
+++ b/r-scripts/maximumIsometricForce.R
@@ -26,38 +26,38 @@
 
 assignOptions <- function(options)
 {
-        drawRfdOptions = rep(NA, 4)
-        drawRfdOptions[1]      = options[12]
-        drawRfdOptions[2]      = options[13]
-        drawRfdOptions[3]      = options[14]
-        drawRfdOptions[4]      = options[15]
-        
-        return(list(
-                os                     = options[1],
-                decimalChar            = options[2],
-                graphWidth             = as.numeric(options[3]),
-                graphHeight            = as.numeric(options[4]),
-                averageLength          = as.numeric(options[5]),
-                percentChange          = as.numeric(options[6]),
-                vlineT0                = options[7],
-                vline50fmax.raw        = options[8],
-                vline50fmax.fitted     = options[9],
-                hline50fmax.raw        = options[10],
-                hline50fmax.fitted     = options[11],
-                drawRfdOptions          = drawRfdOptions,
-                drawImpulseOptions      = options[16],
-               testLength              = as.numeric(options[17]),
-               captureOptions          = options[18],
-               title                   = options[19],
-               exercise                = options[20],
-               datetime                = options[21],
-                scriptsPath            = options[22],
-               triggersOnList  = as.numeric(unlist(strsplit(options[23], "\\;"))),
-               triggersOffList  = as.numeric(unlist(strsplit(options[24], "\\;"))),
-               startSample = as.numeric(options[25]),
-               endSample = as.numeric(options[26]),
-               startEndOptimized = options[27] #bool
-        ))
+    drawRfdOptions = rep(NA, 4)
+    drawRfdOptions[1]      = options[12]
+    drawRfdOptions[2]      = options[13]
+    drawRfdOptions[3]      = options[14]
+    drawRfdOptions[4]      = options[15]
+    
+    return(list(
+        os                     = options[1],
+        decimalChar            = options[2],
+        graphWidth             = as.numeric(options[3]),
+        graphHeight            = as.numeric(options[4]),
+        averageLength          = as.numeric(options[5]),
+        percentChange          = as.numeric(options[6]),
+        vlineT0                = options[7],
+        vline50fmax.raw        = options[8],
+        vline50fmax.fitted     = options[9],
+        hline50fmax.raw        = options[10],
+        hline50fmax.fitted     = options[11],
+        drawRfdOptions          = drawRfdOptions,
+        drawImpulseOptions      = options[16],
+        testLength             = as.numeric(options[17]),
+        captureOptions                 = options[18],
+        title                  = options[19],
+        exercise               = options[20],
+        datetime               = options[21],
+        scriptsPath            = options[22],
+        triggersOnList  = as.numeric(unlist(strsplit(options[23], "\\;"))),
+        triggersOffList  = as.numeric(unlist(strsplit(options[24], "\\;"))),
+        startSample = as.numeric(options[25]),
+        endSample = as.numeric(options[26]),
+        startEndOptimized = options[27] #bool
+    ))
 }
 
 
@@ -86,662 +86,683 @@ op$datetime = fixDatetime(op$datetime)
 
 
 #Fits the data to the model f = fmax*(1 - exp(-K*t))
-#Important! It fits the data with the axes moved to initf and startTime. The real maximum force is fmax + 
initf
+#Important! It fits the data with the axes moved to previousForce and startTime. The real maximum force is 
fmax + previousForce
 getForceModel <- function(time, force, startTime, # startTime is the instant when the force start to increase
                           fmaxi,           # fmaxi is the initial value for the fmax. For numeric purpouses
-                          initf)              # initf is the sustained force before the increase
+                          previousForce)              # previousForce is the sustained force before the 
increase
 {
-        print("Entered in getForceModel() function")
-        #We force that the function crosses the (0,0) to better fit the monoexponential
-        force = force
-        time = time - startTime
-        
-        data = data.frame(time = time, force = force)
-        print(data)
-        model = nls( force ~ fmax*(1-exp(-K*time)), data, start=list(fmax=fmaxi, K=1), 
control=nls.control(warnOnly=TRUE))
-        print(model)
-        fmax = summary(model)$coeff[1,1]
-        K = summary(model)$coeff[2,1]
-        return(list(fmax = fmax, K = K, error = 100*residuals(model)/data$force))
+    print("Entered in getForceModel() function")
+    #We force that the function crosses the (0,0) to better fit the monoexponential
+    force = force
+    time = time - startTime
+    
+    data = data.frame(time = time, force = force)
+    # print(data)
+    model = nls( force ~ fmax*(1-exp(-K*time)), data, start=list(fmax=fmaxi, K=1), 
control=nls.control(warnOnly=TRUE))
+    # print(model)
+    fmax = summary(model)$coeff[1,1]
+    K = summary(model)$coeff[2,1]
+    # print(summary(model))
+    return(list(fmax = fmax, K = K, error = 100*residuals(model)/data$force))
 }
 
 getDynamicsFromLoadCellFile <- function(captureOptions, inputFile, averageLength = 0.1, percentChange = 5, 
bestFit = TRUE, testLength = -1)
 {
-  # op$startSample = 529
-  # op$endSample = 1145
-  print(paste("bestFit =", bestFit))
-  originalTest = read.csv(inputFile, header = F, dec = op$decimalChar, sep = ";", skip = 2)
-  colnames(originalTest) <- c("time", "force")
-  originalTest$time = as.numeric(originalTest$time / 1000000)  # Time is converted from microseconds to 
seconds
-
-       if(captureOptions == "ABS")
-               originalTest$force = abs(originalTest$force)
-       else if(captureOptions == "INVERTED")
-               originalTest$force = -1 * originalTest$force
-
-        #The start and end samples are manualy selected
-        print(paste("op$startSample: ", op$startSample))
-        print(paste("op$endtSample: ", op$endSample))
+    # op$startSample = 529
+    # op$endSample = 1145
+    print(paste("bestFit =", bestFit))
+    originalTest = read.csv(inputFile, header = F, dec = op$decimalChar, sep = ";", skip = 2)
+    colnames(originalTest) <- c("time", "force")
+    originalTest$time = as.numeric(originalTest$time / 1000000)  # Time is converted from microseconds to 
seconds
+    
+    if(captureOptions == "ABS")
+        originalTest$force = abs(originalTest$force)
+    else if(captureOptions == "INVERTED")
+        originalTest$force = -1 * originalTest$force
+    
+    #The start and end samples are manualy selected
+    print(paste("op$startSample: ", op$startSample))
+    print(paste("op$endtSample: ", op$endSample))
+    
+    #Just in case the Roptions.txt don't have the parameters
+    if(is.na(op$startSample) || is.na(op$endSample))
+    {
+        op$startSample = 0
+        op$endSample = 0
+    }
+    
+    #If Roptions.txt does have startSample and endSample values greater than 0
+    if( op$startSample != op$endSample && (op$startSample > 0 && op$endSample > 0) && op$startSample <= 
length(originalTest$time) )
+    {
+        print("Type of startEndOptimized")
+        print(typeof(op$startEndOptimized))
+        print(op$startEndOptimized)
+        print("originalTest without trimming")
+        print(originalTest)
         
-        #Just in case the Roptions.txt don't have the parameters
-        if(is.na(op$startSample) || is.na(op$endSample))
-        {
-                op$startSample = 0
-                op$endSample = 0
-        }
+        originalTest = originalTest[op$startSample:op$endSample,]
+        row.names(originalTest) <- 1:nrow(originalTest)
+        originalTest$time = originalTest$time - originalTest$time[1]
+        print("originalTest trimmed")
+        print(originalTest)
         
-        #If Roptions.txt does have startSample and endSample values greater than 0
-        if( op$startSample != op$endSample && (op$startSample > 0 && op$endSample > 0) && op$startSample <= 
length(originalTest$time) )
+        if( op$startEndOptimized == "FALSE")
         {
-                print("Type of startEndOptimized")
-                print(typeof(op$startEndOptimized))
-                print(op$startEndOptimized)
-                print("originalTest without trimming")
-                print(originalTest)
-                
-                originalTest = originalTest[op$startSample:op$endSample,]
-                row.names(originalTest) <- 1:nrow(originalTest)
-                originalTest$time = originalTest$time - originalTest$time[1]
-                print("originalTest trimmed")
-                print(originalTest)
-                
-                if( op$startEndOptimized == "FALSE")
-                {
-                        print("A")
-                        startSample = op$startSample
-                        endSample = op$endSample
-                        print("B")
-                } else if( op$startEndOptimized == "TRUE")
-                {
-                        print("Entering in startEndOptimized mode")
-                        #Finding the increase and decrease of the force to detect the start and end of the 
maximum voluntary force test
-                        
-                        #Instantaneous RFD
-                        rfd = getRFD(originalTest)
-                        analysisRange = getAnalysisRange(originalTest, rfd, averageLength = averageLength, 
percentChange = percentChange,
-                                                             testLength = op$testLength, 
startDetectingMethod = "RFD")
-                        
-                        startSample = analysisRange$startSample
-                        endSample = analysisRange$endSample
-                        
-                        testTrimmed = originalTest[startSample:endSample,]
-                }
-                
-                print("start and end sample:")
-                print(startSample)
-                print(endSample)
-        } else
-        #The start and end samples are automatically selected
-        {
-                
-                #Finding the increase and decrease of the force to detect the start and end of the maximum 
voluntary force test
-                
-                #Instantaneous RFD
-                rfd = getRFD(originalTest)
-                analysisRange = getAnalysisRange(originalTest, rfd, averageLength = averageLength, 
percentChange = percentChange,
-                                                     testLength = op$testLength, startDetectingMethod = "SD")
-                
-                startSample = analysisRange$startSample
-                endSample = analysisRange$endSample
-                
-                #Trimming the data before and after contraction
-                #TODO: Check the row.names
-                testTrimmed = originalTest[startSample:endSample,]
-        }
-       #print(paste("startSample: ", startSample))
-       #print(paste("endtSample: ", endSample))
-        startTime = originalTest$time[startSample]
-        
-        endTime = originalTest$time[endSample]
-        
-        # Initial force. It is needed to perform an initial steady force to avoid jerks and great peaks in 
the force
-        if(startSample <= 20)
+            print("A")
+            startSample = op$startSample
+            endSample = op$endSample
+            print("B")
+        } else if( op$startEndOptimized == "TRUE")
         {
-                #TODO. Manage the situation where the signal starts once the force has begun to increase
-                print("Not previos steady tension applied before performing the test")
-                return(NA)
+            print("Entering in startEndOptimized mode")
+            #Finding the increase and decrease of the force to detect the start and end of the maximum 
voluntary force test
+            
+            #Instantaneous RFD
+            rfd = getRFD(originalTest)
+            analysisRange = getAnalysisRange(originalTest, rfd, averageLength = averageLength, percentChange 
= percentChange,
+                                             testLength = op$testLength, startDetectingMethod = "RFD")
+            
+            startSample = analysisRange$startSample
+            endSample = analysisRange$endSample
+            
+            trimmedTest = originalTest[startSample:endSample,]
         }
         
-
-        initf = mean(originalTest$force[(startSample - 20):(startSample - 10)]) #ATENTION. This value is 
different from f0.raw
-        fmax.raw = max(originalTest$force[startSample:endSample])
+        print("start and end sample:")
+        print(startSample)
+        print(endSample)
+    } else
+        #The start and end samples are automatically selected
+    {
         
-        f.smoothed = getMovingAverageForce(originalTest, averageLength = averageLength) #Running average 
with equal weight averageLength seconds
-        fmax.smoothed = max(f.smoothed, na.rm = TRUE)
-        lastmeanError = 1E16
+        #Finding the increase and decrease of the force to detect the start and end of the maximum voluntary 
force test
         
-        model = getForceModel(testTrimmed$time, testTrimmed$force, startTime, fmax.smoothed, initf)
-        meanError = mean(abs(model$error))
+        #Instantaneous RFD
+        rfd = getRFD(originalTest)
+        analysisRange = getAnalysisRange(originalTest, rfd, averageLength = averageLength, percentChange = 
percentChange,
+                                         testLength = op$testLength, startDetectingMethod = "SD")
         
-        # print(paste("Error:", model$error))
-        # print(paste("length:", length(testTrimmed$force)))
-        # print(paste("Relative Error:", meanError))
-        # print("--------")
-        
-        #If bestFit is TRUE, this overrides the startSample calculus and find the startSample that makes the 
best fit of the curve  
-        if(bestFit)
-        {
-          print("bestFit Mode--------")
-                while(meanError < lastmeanError)
-                {
-                        lastmeanError = meanError
-                        
-                        startSample = startSample + 1
-                        startTime = originalTest$time[startSample]
-                        
-                        #If the lenght of the test is fixed, moving the startSample implies moving the 
endSample also
-                        if (testLength != -1){
-                                endSample = endSample + 1
-                                endTime = originalTest$time[endSample]
-                        }
-                        
-                        
-                        #Trimming the data before and after contraction
-                        testTrimmed = originalTest[startSample:endSample,]
-                        
-                        model = getForceModel(testTrimmed$time, testTrimmed$force, startTime, fmax.smoothed, 
initf)
-                        meanError = mean(abs(model$error))
-                        
-                        print(paste("Error:", model$error))
-                        print(paste("length:", length(testTrimmed$force)))
-                        print(paste("Relative Error:", model$error / length(testTrimmed$force)))
-                        print("--------")
-                }
-                
-                #going back to the last sample
-                startSample = startSample - 1
-                startTime = originalTest$time[startSample]
-                
-                endTime = originalTest$time[endSample]
-                
-                
-                #Trimming the data before and after contraction
-                testTrimmed = originalTest[startSample:endSample,]
-                
-                model = getForceModel(testTrimmed$time, testTrimmed$force, startTime, fmax.smoothed, initf)
-        }
+        startSample = analysisRange$startSample
+        endSample = analysisRange$endSample
         
+        #Trimming the data before and after contraction
+        #TODO: Check the row.names
+        trimmedTest = originalTest[startSample:endSample,]
+    }
+    #print(paste("startSample: ", startSample))
+    #print(paste("endtSample: ", endSample))
+    startTime = originalTest$time[startSample]
+    
+    endTime = originalTest$time[endSample]
+    
+    # Initial force. It is needed to perform an initial steady force to avoid jerks and great peaks in the 
force
+    if(startSample <= 20)
+    {
+        #TODO. Manage the situation where the signal starts once the force has begun to increase
+        print("Not previos steady tension applied before performing the test")
+        return(NA)
+    }
+    
+    
+    previousForce = mean(originalTest$force[(startSample - 20):(startSample - 10)]) #ATENTION. This value is 
different from f0.raw
+    fmax.raw = max(originalTest$force[startSample:endSample])
+    
+    f.smoothed = getMovingAverageForce(originalTest, averageLength = averageLength) #Running average with 
equal weight averageLength seconds
+    fmax.smoothed = max(f.smoothed, na.rm = TRUE)
+    lastmeanError = 1E16
+    
+    model = getForceModel(trimmedTest$time, trimmedTest$force, startTime, fmax.smoothed, previousForce)
+    meanError = mean(abs(model$error))
+    
+    # print(paste("Error:", model$error))
+    # print(paste("length:", length(trimmedTest$force)))
+    # print(paste("Relative Error:", meanError))
+    # print("--------")
+    
+    #If bestFit is TRUE, this overrides the startSample calculus and find the startSample that makes the 
best fit of the curve  
+    if(bestFit)
+    {
+        # print("bestFit Mode--------")
+        #       while(meanError < lastmeanError)
+        #       {
+        #               lastmeanError = meanError
+        #               
+        #               startSample = startSample + 1
+        #               startTime = originalTest$time[startSample]
+        #               
+        #               #If the lenght of the test is fixed, moving the startSample implies moving the 
endSample also
+        #               if (testLength != -1){
+        #                       endSample = endSample + 1
+        #                       endTime = originalTest$time[endSample]
+        #               }
+        #               
+        #               
+        #               #Trimming the data before and after contraction
+        #               trimmedTest = originalTest[startSample:endSample,]
+        #               
+        #               model = getForceModel(trimmedTest$time, trimmedTest$force, startTime, fmax.smoothed, 
previousForce)
+        #               meanError = mean(abs(model$error))
+        #               
+        #               print(paste("Error:", model$error))
+        #               print(paste("length:", length(trimmedTest$force)))
+        #               print(paste("Relative Error:", model$error / length(trimmedTest$force)))
+        #               print("--------")
+        #       }
+        #       
+        #       #going back to the last sample
+        #       startSample = startSample - 1
+        #       startTime = originalTest$time[startSample]
+        #       
+        #       endTime = originalTest$time[endSample]
+        #       
+        #       
+        #       #Trimming the data before and after contraction
+        #       trimmedTest = originalTest[startSample:endSample,]
+        #       
+        #       model = getForceModel(trimmedTest$time, trimmedTest$force, startTime, fmax.smoothed, 
previousForce)
+        bestFit = getBestFit(inputFile = 
"/home/xpadulles/.local/share/Chronojump/forceSensor/39/100_Carmelo_2019-09-26_12-49-09.csv"
+                             , averageLength = averageLength
+                             , percentChange = percentChange
+                             # , percentChange = -1
+                             , testLength = testLength
+        )
+        print(bestFit)
+        startSample = bestFit$startSample
+        startTime = bestFit$startTime
+        endSample = bestFit$endSample
+        endTime = bestFit$endTime
+        model = bestFit$model
+        print(originalTest)
         
-        f.fitted =model$fmax*(1-exp(-model$K*(originalTest$time - startTime)))
         
-        f0.raw = testTrimmed$force[1]                                                  # Force at t=0ms. 
ATENTION. This value is different than initf
-        rfd0.fitted = model$fmax * model$K                                      # RFD at t=0ms using the 
exponential model
-        tfmax.raw = testTrimmed$time[which.min(abs(testTrimmed$force - fmax.raw))]            # Time needed 
to reach the Fmax
         
-        return(list(nameOfFile = inputFile, time = originalTest[, "time"],
-                    fmax.fitted = model$fmax, k.fitted = model$K, tau.fitted = 1/model$K,
-                    startTime = startTime, endTime = endTime,
-                    startSample = startSample, endSample = endSample,
-                    totalSample = length(originalTest$time),
-                    initf = initf,
-                    f0.raw = f0.raw,
-                    fmax.raw = fmax.raw, fmax.smoothed = fmax.smoothed,
-                    tfmax.raw = tfmax.raw,
-                    rfd = rfd,
-                    f.raw = originalTest$force, f.smoothed = f.smoothed, f.fitted = f.fitted,
-                    endTime = endTime,
-                    meanError = meanError))
+    }
+    print("####### model ######")
+    print(model)
+    f.fitted =model$fmax*(1-exp(-model$K*(originalTest$time - startTime)))
+    
+    f0.raw = originalTest$force[startSample]                              # Force at startTime. ATENTION. 
This value is different than previousForce
+    rfd0.fitted = model$fmax * model$K                                  # RFD at t=0ms using the exponential 
model
+    tfmax.raw = originalTest$time[which.min(abs(originalTest$force - fmax.raw))] - startTime            # 
Time needed to reach the Fmax
+    
+    return(list(nameOfFile = inputFile, time = originalTest[, "time"],
+                fmax.fitted = model$fmax, k.fitted = model$K, tau.fitted = 1/model$K,
+                startTime = startTime, endTime = endTime,
+                startSample = startSample, endSample = endSample,
+                totalSample = length(originalTest$time),
+                previousForce = previousForce,
+                f0.raw = f0.raw,
+                fmax.raw = fmax.raw, fmax.smoothed = fmax.smoothed,
+                tfmax.raw = tfmax.raw,
+                rfd = rfd,
+                f.raw = originalTest$force, f.smoothed = f.smoothed, f.fitted = f.fitted,
+                endTime = endTime,
+                meanError = meanError))
 }
 
 drawDynamicsFromLoadCell <- function(
-        dynamics, captureOptions, vlineT0=T, vline50fmax.raw=F, vline50fmax.fitted=F,
-        hline50fmax.raw=F, hline50fmax.fitted=F,
-        rfdDrawingOptions, triggersOn = "", triggersOff = "", xlimits = NA)
+    dynamics, captureOptions, vlineT0=T, vline50fmax.raw=F, vline50fmax.fitted=F,
+    hline50fmax.raw=F, hline50fmax.fitted=F,
+    rfdDrawingOptions, triggersOn = "", triggersOff = "", xlimits = NA)
 {
-        dynamics$time = dynamics$time - dynamics$startTime
-        dynamics$tfmax.raw = dynamics$tfmax.raw - dynamics$startTime
-        dynamics$endTime = dynamics$endTime - dynamics$startTime
-        dynamics$startTime = 0
-        if(is.na(dynamics$time[1]))
+    dynamics$time = dynamics$time - dynamics$startTime
+    dynamics$tfmax.raw = dynamics$tfmax.raw - dynamics$startTime
+    dynamics$endTime = dynamics$endTime - dynamics$startTime
+    dynamics$startTime = 0
+    if(is.na(dynamics$time[1]))
+    {
+        print("Dynamics not available:")
+        return(NA)
+    }
+    par(mar = c(6, 4, 6, 4))
+    
+    #Detecting if the duration of the sustained force enough
+    print("f.raw")
+    print(dynamics$f.raw)
+    print(paste("samples:", dynamics$startSample, dynamics$endSample))
+    meanForce = mean(dynamics$f.raw[dynamics$startSample:dynamics$endSample])
+    print(paste("meanForce: ", meanForce, "fmax.raw: ", dynamics$fmax.raw))
+    if( meanForce < dynamics$fmax.raw*0.75 ){
+        sustainedForce = F
+        yHeight = dynamics$fmax.raw
+    } else if( meanForce >= dynamics$fmax.raw*0.75 ){
+        sustainedForce = T
+        yHeight = max(dynamics$fmax.raw, dynamics$fmax.fitted) * 1.1
+    }
+    
+    par(mar=c(4,4,3,1))
+    #Plotting raw data from startTime to endTime (Only the analysed data)
+    if (!is.na(xlimits[1])){
+        xWidth = xlimits[2] - xlimits[1]
+        plot(dynamics$time[dynamics$startSample:dynamics$endSample], 
dynamics$f.raw[dynamics$startSample:dynamics$endSample],
+             type="l", xlab="Time[s]", ylab="Force[N]",
+             xlim = xlimits, ylim=c(0, yHeight),
+             #main = dynamics$nameOfFile,
+             main = paste(parse(text = paste0("'", titleFull, "'"))), #process unicode, needed paste because 
its an expression. See graph.R
+             yaxs= "i", xaxs = "i")
+        mtext(op$datetime, line = 0)
+        xmin = xlimits[1]
+        xmax = xlimits[2]
+        #points(dynamics$time[dynamics$startSample:dynamics$endSample] , 
dynamics$f.raw[dynamics$startSample:dynamics$endSample])
+    } else if (is.na(xlimits[1])){
+        xmin = -0.2
+        xmax = dynamics$endTime*1.1 - dynamics$startTime*0.1
+        xWidth = xmax - xmin
+        plot(dynamics$time[dynamics$startSample:dynamics$endSample], 
dynamics$f.raw[dynamics$startSample:dynamics$endSample],
+             type="l", xlab="Time[s]", ylab="Force[N]",
+             xlim = c(xmin, xmax),
+             ylim=c(0, yHeight),
+             #main = dynamics$nameOfFile,
+             main = paste(parse(text = paste0("'", titleFull, "'"))), #process unicode, needed paste because 
its an expression. See graph.R
+             yaxs= "i", xaxs = "i")
+        mtext(op$datetime, line = 0)
+    }
+    
+    
+    if(!sustainedForce){
+        text(x = (xmax + xmin)/2, y = yHeight/2, labels = "Bad execution. Probably not sustained force", adj 
= c(0.5, 0.5), cex = 2, col = "red")
+        #Plotting not analysed data
+        lines(dynamics$time[1:dynamics$startSample] , dynamics$f.raw[1:dynamics$startSample], col = "grey") 
#Pre-analysis
+        lines(dynamics$time[dynamics$endSample: dynamics$totalSample] , dynamics$f.raw[dynamics$endSample: 
dynamics$totalSample], col = "grey") #Post-analysis
+        return()
+    }
+    
+    #Plotting Impulse
+    
+    print("--------Impulse-----------")
+    print(op$drawImpulseOptions)
+    impulseOptions = readImpulseOptions(op$drawImpulseOptions)
+    
+    impulseLegend = ""
+    
+    if(impulseOptions$impulseFunction != "-1")
+    {
+        print(impulseOptions)
+        if(impulseOptions$type == "IMP_RANGE")
         {
-                print("Dynamics not available:")
-                return(NA)
-        }
-        par(mar = c(6, 4, 6, 4))
-        
-        #Detecting if the duration of the sustained force enough
-        meanForce = mean(dynamics$f.raw[dynamics$startSample:dynamics$endSample])
-        if( meanForce < dynamics$fmax.raw*0.75 ){
-                sustainedForce = F
-                yHeight = dynamics$fmax.raw
-        } else if( meanForce >= dynamics$fmax.raw*0.75 ){
-                sustainedForce = T
-                yHeight = max(dynamics$fmax.raw, dynamics$fmax.fitted) * 1.1
-        }
+            startImpulseSample = which.min(abs(dynamics$time - impulseOptions$start/1000))
+            endImpulseSample = which.min(abs(dynamics$time - impulseOptions$end/1000))
+        } else if(impulseOptions$type == "IMP_UNTIL_PERCENT_F_MAX")
+        {
+            startImpulseSample = dynamics$startSample
+            
+            #Finding the sample at which the force is greater that percentage of fmax
+            endImpulseSample = startImpulseSample
+            while(dynamics$f.raw[endImpulseSample + 1] < dynamics$fmax.raw*impulseOptions$end/100)
+            {
+                endImpulseSample = endImpulseSample +1
                 
-       par(mar=c(4,4,3,1))
-        #Plotting raw data from startTime to endTime (Only the analysed data)
-        if (!is.na(xlimits[1])){
-                xWidth = xlimits[2] - xlimits[1]
-                plot(dynamics$time[dynamics$startSample:dynamics$endSample], 
dynamics$f.raw[dynamics$startSample:dynamics$endSample],
-                     type="l", xlab="Time[s]", ylab="Force[N]",
-                     xlim = xlimits, ylim=c(0, yHeight),
-                     #main = dynamics$nameOfFile,
-                    main = paste(parse(text = paste0("'", titleFull, "'"))), #process unicode, needed paste 
because its an expression. See graph.R
-                    yaxs= "i", xaxs = "i")
-               mtext(op$datetime, line = 0)
-                xmin = xlimits[1]
-                xmax = xlimits[2]
-                #points(dynamics$time[dynamics$startSample:dynamics$endSample] , 
dynamics$f.raw[dynamics$startSample:dynamics$endSample])
-        } else if (is.na(xlimits[1])){
-                xmin = -0.2
-                xmax = dynamics$endTime*1.1 - dynamics$startTime*0.1
-                xWidth = xmax - xmin
-                plot(dynamics$time[dynamics$startSample:dynamics$endSample], 
dynamics$f.raw[dynamics$startSample:dynamics$endSample],
-                     type="l", xlab="Time[s]", ylab="Force[N]",
-                     xlim = c(xmin, xmax),
-                     ylim=c(0, yHeight),
-                     #main = dynamics$nameOfFile,
-                    main = paste(parse(text = paste0("'", titleFull, "'"))), #process unicode, needed paste 
because its an expression. See graph.R
-                    yaxs= "i", xaxs = "i")
-               mtext(op$datetime, line = 0)
+            }
         }
         
-
-        if(!sustainedForce){
-                text(x = (xmax + xmin)/2, y = yHeight/2, labels = "Bad execution. Probably not sustained 
force", adj = c(0.5, 0.5), cex = 2, col = "red")
-                #Plotting not analysed data
-                lines(dynamics$time[1:dynamics$startSample] , dynamics$f.raw[1:dynamics$startSample], col = 
"grey") #Pre-analysis
-                lines(dynamics$time[dynamics$endSample: dynamics$totalSample] , 
dynamics$f.raw[dynamics$endSample: dynamics$totalSample], col = "grey") #Post-analysis
-                return()
+        if(impulseOptions$impulseFunction == "RAW")
+        {
+            impulseColor = "black"
+            
+            #Drawing the area under the force curve (Impulse)
+            polygon(c(dynamics$time[startImpulseSample:endImpulseSample], dynamics$time[endImpulseSample] , 
dynamics$time[startImpulseSample]),
+                    c(dynamics$f.raw[startImpulseSample:endImpulseSample], 0, 0), col = "grey")
+            
+            #Calculation of the impulse
+            impulse = getAreaUnderCurve(dynamics$time[startImpulseSample:endImpulseSample], 
dynamics$f.raw[startImpulseSample:endImpulseSample])
+            
+        } else if(impulseOptions$impulseFunction == "FITTED")
+        {
+            impulseColor = "blue"
+            
+            #Drawing the area under the force curve (Impulse)
+            polygon(c(dynamics$time[startImpulseSample:endImpulseSample], dynamics$time[endImpulseSample] , 
dynamics$time[startImpulseSample]),
+                    c(dynamics$f.fitted[startImpulseSample:endImpulseSample], 0, 0), col = "grey")
+            #Redraw the raw force
+            lines(x = dynamics$time[startImpulseSample:endImpulseSample] , y = 
dynamics$f.raw[startImpulseSample:endImpulseSample])
+            
+            #Calculation of the impulse
+            #Sum of the area of all the triangles formed with a vertex in the origin and the other vertex in 
the
+            #n-th and (n+1)-th point of the polygon
+            # impulse = 0
+            # for(n in startImpulseSample:(endImpulseSample - 1))
+            # {
+            #         #Area of the paralelograms, not the triangle
+            #         area = ((dynamics$time[n+1] - dynamics$time[dynamics$startSample]) * 
dynamics$f.fitted[n] - (dynamics$time[n] - dynamics$time[dynamics$startSample]) * dynamics$f.fitted[n+1])
+            #         impulse = impulse + area
+            # }
+            # 
+            # area = (dynamics$time[endImpulseSample] - dynamics$time[dynamics$startSample]) * 
dynamics$f.fitted[endImpulseSample]
+            # impulse = impulse + area
+            #Area under the curve is one half of the sum of the area of paralelograms
+            #impulse = impulse / 2
+            impulse = getAreaUnderCurve(dynamics$time[startImpulseSample:endImpulseSample], 
dynamics$f.fitted[startImpulseSample:endImpulseSample])
+            
+            
         }
         
-        #Plotting Impulse
+        text(x = (dynamics$startTime + (dynamics$time[endImpulseSample] - 
dynamics$time[startImpulseSample])*0.66), y = mean(dynamics$f.raw[startImpulseSample:endImpulseSample])*0.66,
+             labels = paste("Impulse =", round(impulse, digits = 2), "N\u00B7s"), pos = 4, cex = 1.5)
         
-        print("--------Impulse-----------")
-        print(op$drawImpulseOptions)
-        impulseOptions = readImpulseOptions(op$drawImpulseOptions)
-
-       impulseLegend = ""
+        impulseLegend = paste("Impulse", impulseOptions$start, "-", impulseOptions$end, " = ", 
round(impulse, digits = 2), " N\u00B7s", sep = "") #\u00B7 is ·
+    }
+    
+    #Plotting not analysed data
+    lines(dynamics$time[1:dynamics$startSample] , dynamics$f.raw[1:dynamics$startSample], col = "grey") 
#Pre-analysis
+    lines(dynamics$time[dynamics$endSample: dynamics$totalSample] , dynamics$f.raw[dynamics$endSample: 
dynamics$totalSample], col = "grey") #Post-analysis
+    
+    
+    #Plotting fitted data
+    lines(dynamics$time, dynamics$f.fitted, col="blue")
+    abline(h = dynamics$fmax.fitted, lty = 2, col = "blue")
+    text(x = xmax, y = dynamics$fmax.fitted,
+         labels = paste("Fmax =", round(dynamics$fmax.fitted,digits = 2), "N"),
+         col = "blue", cex = 1.5, adj=c(1,0))
+    
+    #Plottting smoothed data
+    #lines(dynamics$time, dynamics$f.smoothed, col="grey")
+    
+    #Plotting RFD
+    #lines(dynamics$time, dynamics$rfd/100, col = "red")
+    
+    #Plotting tau
+    abline(v = dynamics$tau.fitted, col = "green4", lty = 3)
+    abline(h = dynamics$fmax.fitted*0.6321206, col = "green4", lty = 3)
+    points(dynamics$tau.fitted, dynamics$fmax.fitted*0.6321206, col = "green4")
+    arrows(x0 = 0, y0 = dynamics$f0.raw,
+           x1 = dynamics$tau.fitted, y1 = dynamics$f0.raw)
+    text(x = (dynamics$tau.fitted / 2), y = dynamics$f0.raw,
+         labels = paste(round(dynamics$tau.fitted, digits = 2), "s"), pos = 3, cex = 1.5, col = "blue")
+    # text(x = (dynamics$tau.fitted / 2), y = -20,
+    #      labels = paste(round(dynamics$tau.fitted, digits = 2), "s"), pos = 3, cex = 1.5, xpd = TRUE)
+    
+    arrows(x0 = 0, y0 = 0,
+           x1 = 0, y1 = dynamics$fmax.fitted*0.6321206)
+    
+    text(x = 0, y = dynamics$fmax.fitted*0.6321206 / 2,
+         labels = "63% of fmax", pos = 2, cex = 1.5, srt = 90, col = "blue")
+    
+    #Plotting fmax.raw
+    text( x = dynamics$tfmax.raw, y = dynamics$fmax.raw,
+          labels = paste("Fmax = ", round(dynamics$fmax.raw, digits=2), " N", sep=""), pos = 3, cex = 1.5)
+    points(x = dynamics$tfmax.raw, y = dynamics$fmax.raw)
+    
+    if(vlineT0){
+        abline(v = dynamics$startTime, lty = 2)
+        axis(3, at = dynamics$startTime, labels = dynamics$startTime)
+    }
+    if(hline50fmax.raw){
+        abline(h = dynamics$fmax.raw/2, lty = 2)
+        text( x = dynamics$t50fmax.raw + 0.5, y = dynamics$fmax.raw/2, labels = paste("Fmax/2 =", 
round(dynamics$fmax.raw/2, digits=2), "N", sep=""), pos = 3)
+    }
+    if(hline50fmax.fitted){
+        abline( h = (dynamics$fmax.fitted)/2, lty = 2, col = "blue")
+        text( x =dynamics$t50fmax.fitted + 0.5, y = (dynamics$fmax.fitted)/2, labels = paste("Fmax/2 =", 
round((dynamics$fmax.fitted)/2, digits=2), "N", sep=""), pos = 1, col="blue")
+    }
+    if(vline50fmax.raw){
+        abline(v = dynamics$t50fmax.raw, lty = 2)
+        axis(3, at = dynamics$t50fmax.raw, labels = dynamics$t50fmax.raw)
+    }
+    if(vline50fmax.fitted){
+        abline(v = dynamics$t50fmax.fitted, lty = 2)
+        axis(3, at = dynamics$t50fmax.fitted, labels = dynamics$t50fmax.fitted)
+    }
+    
+    #The angle in the srt parameter of the text is an absolute angle seen in the window, not the angle in 
the coordinates system of the plot area.
+    pixelsPerLine = 14    #This value has been found with test and error.
+    
+    # 72 dpi is the default resolutions for pdf. Margins units are text hight
+    plotWidth = dev.size()[1]*72 - (par()$mar[2] + par()$mar[4])*pixelsPerLine      
+    plotHeight = dev.size()[2]*72 - (par()$mar[1] + par()$mar[3])*pixelsPerLine
+    
+    #Drawing the RFD data
+    print("-----------RFD-----------")
+    print(paste("op$drawRfdOptions =", op$drawRfdOptions))
+    
+    #triggers
+    abline(v=triggersOn, col="green")
+    abline(v=triggersOff, col="red")
+    
+    
+    legendText = c(
+        paste("Fmax =", round(dynamics$fmax.fitted, digits = 2), "N"),
+        paste("K = ", round(dynamics$k.fitted, digits = 2),"s\u207B\u00B9"),
+        paste("\u03C4 = ", round(dynamics$tau.fitted, digits = 2),"s")
+    )
+    legendColor = c("blue", "blue", "blue")
+    
+    #The coordinates where the lines and dots are plotted are calculated with the sampled data in raw and 
fitted data.
+    #The slopes are calculated in that points
+    for (n in 1:length(rfdDrawingOptions))
+    {
+        RFDoptions = readRFDOptions(op$drawRfdOptions[n])
         
-        if(impulseOptions$impulseFunction != "-1")
+        print(paste("---- RFD number", n, "--------"))
+        print(options)
+        if(RFDoptions$type == "AVERAGE" & (RFDoptions$start == RFDoptions$end)){
+            RFDoptions$type = "INSTANTANEOUS"
+        }
+        if(RFDoptions$rfdFunction == "-1")        
         {
-                print(impulseOptions)
-                if(impulseOptions$type == "IMP_RANGE")
+            next
+        } else
+        {
+            
+            RFD = NULL
+            pointForce1 = NULL
+            color = ""
+            
+            #Needed when only one point is plotted
+            sample2 = NULL
+            pointForce2 = NULL
+            time2 = NULL
+            force2 = NULL
+            
+            if(RFDoptions$rfdFunction == "FITTED")
+            {
+                color = "blue"
+            } else if(RFDoptions$rfdFunction == "RAW")
+            {
+                color = "black"
+            }
+            
+            if(RFDoptions$type == "INSTANTANEOUS") # TODO: || percent ...(all except AVG)
+            {
+                #Converting RFDoptions$start to seconds
+                RFDoptions$start = RFDoptions$start/1000
+                
+                time1 = RFDoptions$start
+                
+                if (RFDoptions$rfdFunction == "FITTED")
                 {
-                        startImpulseSample = which.min(abs(dynamics$time - impulseOptions$start/1000))
-                        endImpulseSample = which.min(abs(dynamics$time - impulseOptions$end/1000))
-                } else if(impulseOptions$type == "IMP_UNTIL_PERCENT_F_MAX")
+                    #Slope of the line. Deriving the model:
+                    RFD = dynamics$fmax.fitted * dynamics$k.fitted * exp(-dynamics$k.fitted * time1)
+                    #Y coordinate of a point of the line
+                    force1 = dynamics$fmax.fitted * (1 - exp(-dynamics$k.fitted * RFDoptions$start))
+                    
+                    legendText = c(legendText, paste("RFD", RFDoptions$start*1000, " = ", round(RFD, digits 
= 1), " N/s", sep = ""))
+                    legendColor = c(legendColor, "blue")
+                    
+                } else if(RFDoptions$rfdFunction == "RAW")
                 {
-                        startImpulseSample = dynamics$startSample
-                        
-                        #Finding the sample at which the force is greater that percentage of fmax
-                        endImpulseSample = startImpulseSample
-                        while(dynamics$f.raw[endImpulseSample + 1] < 
dynamics$fmax.raw*impulseOptions$end/100)
-                        {
-                                endImpulseSample = endImpulseSample +1
-                                
-                        }
+                    #Slope of the line of the sampled point.
+                    RFD = interpolateXAtY(dynamics$rfd, dynamics$time, time1)
+                    
+                    #Y coordinate of a point of the line
+                    force1 = interpolateXAtY(dynamics$f.raw, dynamics$time, RFDoptions$start)
+                    
+                    legendText = c(legendText, paste("RFD", RFDoptions$start*1000, " = ", round(RFD, digits 
= 1), " N/s", sep = ""))
+                    legendColor = c(legendColor, "black")
                 }
-
-                if(impulseOptions$impulseFunction == "RAW")
+            } else if(RFDoptions$type == "AVERAGE")
+            {
+                #Converting RFDoptions to seconds
+                RFDoptions$start = RFDoptions$start/1000
+                RFDoptions$end = RFDoptions$end/1000
+                
+                time1 = RFDoptions$start
+                time2 = RFDoptions$end
+                
+                if (RFDoptions$rfdFunction == "FITTED")
                 {
-                        impulseColor = "black"
-                        
-                        #Drawing the area under the force curve (Impulse)
-                        polygon(c(dynamics$time[startImpulseSample:endImpulseSample], 
dynamics$time[endImpulseSample] , dynamics$time[startImpulseSample]),
-                                c(dynamics$f.raw[startImpulseSample:endImpulseSample], 0, 0), col = "grey")
-                        
-                        #Calculation of the impulse
-                        impulse = getAreaUnderCurve(dynamics$time[startImpulseSample:endImpulseSample], 
dynamics$f.raw[startImpulseSample:endImpulseSample])
-             
-                } else if(impulseOptions$impulseFunction == "FITTED")
+                    #Y axis of the points
+                    force1 = dynamics$fmax.fitted * (1 - exp(-dynamics$k.fitted * RFDoptions$start))
+                    force2 = dynamics$fmax.fitted * (1 - exp(-dynamics$k.fitted * RFDoptions$end))
+                    
+                    #Slope of the line
+                    RFD = (force2 - force1) / (time2 - time1)
+                    
+                    legendText = c(legendText, paste("RFD", RFDoptions$start*1000, "-", RFDoptions$end*1000, 
" = ", round(RFD, digits = 1), " N/s", sep = ""))
+                    legendColor = c(legendColor, "blue")
+                    
+                } else if(RFDoptions$rfdFunction == "RAW")
                 {
-                        impulseColor = "blue"
-                        
-                        #Drawing the area under the force curve (Impulse)
-                        polygon(c(dynamics$time[startImpulseSample:endImpulseSample], 
dynamics$time[endImpulseSample] , dynamics$time[startImpulseSample]),
-                                c(dynamics$f.fitted[startImpulseSample:endImpulseSample], 0, 0), col = 
"grey")
-                        #Redraw the raw force
-                        lines(x = dynamics$time[startImpulseSample:endImpulseSample] , y = 
dynamics$f.raw[startImpulseSample:endImpulseSample])
-                        
-                        #Calculation of the impulse
-                        #Sum of the area of all the triangles formed with a vertex in the origin and the 
other vertex in the
-                        #n-th and (n+1)-th point of the polygon
-                        # impulse = 0
-                        # for(n in startImpulseSample:(endImpulseSample - 1))
-                        # {
-                        #         #Area of the paralelograms, not the triangle
-                        #         area = ((dynamics$time[n+1] - dynamics$time[dynamics$startSample]) * 
dynamics$f.fitted[n] - (dynamics$time[n] - dynamics$time[dynamics$startSample]) * dynamics$f.fitted[n+1])
-                        #         impulse = impulse + area
-                        # }
-                        # 
-                        # area = (dynamics$time[endImpulseSample] - dynamics$time[dynamics$startSample]) * 
dynamics$f.fitted[endImpulseSample]
-                        # impulse = impulse + area
-                        #Area under the curve is one half of the sum of the area of paralelograms
-                        #impulse = impulse / 2
-                        impulse = getAreaUnderCurve(dynamics$time[startImpulseSample:endImpulseSample], 
dynamics$f.fitted[startImpulseSample:endImpulseSample])
-                        
-                        
+                    force1 = interpolateXAtY(dynamics$f.raw, dynamics$time, RFDoptions$start)
+                    force2 = interpolateXAtY(dynamics$f.raw, dynamics$time, RFDoptions$end)
+                    
+                    #Slope of the line
+                    RFD = (force2 - force1) / (time2 - time1)
+                    
+                    legendText = c(legendText, paste("RFD", RFDoptions$start*1000, "-", RFDoptions$end*1000, 
" = ", round(RFD, digits = 1), " N/s", sep = ""))
+                    legendColor = c(legendColor, "black")
                 }
                 
-                text(x = (dynamics$startTime + (dynamics$time[endImpulseSample] - 
dynamics$time[startImpulseSample])*0.66), y = mean(dynamics$f.raw[startImpulseSample:endImpulseSample])*0.66,
-                     labels = paste("Impulse =", round(impulse, digits = 2), "N\u00B7s"), pos = 4, cex = 1.5)
-
-               impulseLegend = paste("Impulse", impulseOptions$start, "-", impulseOptions$end, " = ", 
round(impulse, digits = 2), " N\u00B7s", sep = "") #\u00B7 is ·
-        }
-        
-        #Plotting not analysed data
-        lines(dynamics$time[1:dynamics$startSample] , dynamics$f.raw[1:dynamics$startSample], col = "grey") 
#Pre-analysis
-        lines(dynamics$time[dynamics$endSample: dynamics$totalSample] , dynamics$f.raw[dynamics$endSample: 
dynamics$totalSample], col = "grey") #Post-analysis
-        
-        
-        #Plotting fitted data
-        lines(dynamics$time, dynamics$f.fitted, col="blue")
-        abline(h = dynamics$fmax.fitted, lty = 2, col = "blue")
-       text(x = xmax, y = dynamics$fmax.fitted,
-            labels = paste("Fmax =", round(dynamics$fmax.fitted,digits = 2), "N"),
-             col = "blue", cex = 1.5, adj=c(1,0))
-        
-        #Plottting smoothed data
-        #lines(dynamics$time, dynamics$f.smoothed, col="grey")
-        
-        #Plotting RFD
-        #lines(dynamics$time, dynamics$rfd/100, col = "red")
-        
-        #Plotting tau
-        abline(v = dynamics$tau.fitted, col = "green4", lty = 3)
-        abline(h = dynamics$fmax.fitted*0.6321206, col = "green4", lty = 3)
-        points(dynamics$tau.fitted, dynamics$fmax.fitted*0.6321206, col = "green4")
-        arrows(x0 = 0, y0 = dynamics$f0.raw,
-               x1 = dynamics$tau.fitted, y1 = dynamics$f0.raw)
-        text(x = (dynamics$tau.fitted / 2), y = dynamics$f0.raw,
-              labels = paste(round(dynamics$tau.fitted, digits = 2), "s"), pos = 3, cex = 1.5, col = "blue")
-        # text(x = (dynamics$tau.fitted / 2), y = -20,
-        #      labels = paste(round(dynamics$tau.fitted, digits = 2), "s"), pos = 3, cex = 1.5, xpd = TRUE)
-        
-        arrows(x0 = 0, y0 = 0,
-               x1 = 0, y1 = dynamics$fmax.fitted*0.6321206)
-        
-        text(x = 0, y = dynamics$fmax.fitted*0.6321206 / 2,
-              labels = "63% of fmax", pos = 2, cex = 1.5, srt = 90, col = "blue")
-        
-        #Plotting fmax.raw
-        text( x = dynamics$tfmax.raw, y = dynamics$fmax.raw,
-              labels = paste("Fmax = ", round(dynamics$fmax.raw, digits=2), " N", sep=""), pos = 3, cex = 
1.5)
-        points(x = dynamics$tfmax.raw, y = dynamics$fmax.raw)
-        
-        if(vlineT0){
-                abline(v = dynamics$startTime, lty = 2)
-                axis(3, at = dynamics$startTime, labels = dynamics$startTime)
-        }
-        if(hline50fmax.raw){
-                abline(h = dynamics$fmax.raw/2, lty = 2)
-                text( x = dynamics$t50fmax.raw + 0.5, y = dynamics$fmax.raw/2, labels = paste("Fmax/2 =", 
round(dynamics$fmax.raw/2, digits=2), "N", sep=""), pos = 3)
-        }
-        if(hline50fmax.fitted){
-                abline( h = (dynamics$fmax.fitted)/2, lty = 2, col = "blue")
-                text( x =dynamics$t50fmax.fitted + 0.5, y = (dynamics$fmax.fitted)/2, labels = paste("Fmax/2 
=", round((dynamics$fmax.fitted)/2, digits=2), "N", sep=""), pos = 1, col="blue")
-        }
-        if(vline50fmax.raw){
-                abline(v = dynamics$t50fmax.raw, lty = 2)
-                axis(3, at = dynamics$t50fmax.raw, labels = dynamics$t50fmax.raw)
-        }
-        if(vline50fmax.fitted){
-                abline(v = dynamics$t50fmax.fitted, lty = 2)
-                axis(3, at = dynamics$t50fmax.fitted, labels = dynamics$t50fmax.fitted)
-        }
-        
-        #The angle in the srt parameter of the text is an absolute angle seen in the window, not the angle 
in the coordinates system of the plot area.
-        pixelsPerLine = 14    #This value has been found with test and error.
-        
-        # 72 dpi is the default resolutions for pdf. Margins units are text hight
-        plotWidth = dev.size()[1]*72 - (par()$mar[2] + par()$mar[4])*pixelsPerLine      
-        plotHeight = dev.size()[2]*72 - (par()$mar[1] + par()$mar[3])*pixelsPerLine
-        
-        #Drawing the RFD data
-        print("-----------RFD-----------")
-        print(paste("op$drawRfdOptions =", op$drawRfdOptions))
-
-       #triggers
-       abline(v=triggersOn, col="green")
-       abline(v=triggersOff, col="red")
-
-        
-        legendText = c(
-                      paste("Fmax =", round(dynamics$fmax.fitted, digits = 2), "N"),
-                      paste("K = ", round(dynamics$k.fitted, digits = 2),"s\u207B\u00B9"),
-                      paste("\u03C4 = ", round(dynamics$tau.fitted, digits = 2),"s")
-                      )
-        legendColor = c("blue", "blue", "blue")
-        
-        #The coordinates where the lines and dots are plotted are calculated with the sampled data in raw 
and fitted data.
-        #The slopes are calculated in that points
-        for (n in 1:length(rfdDrawingOptions))
-        {
-                RFDoptions = readRFDOptions(op$drawRfdOptions[n])
+            } else if(RFDoptions$type == "PERCENT_F_MAX")
+            {
+                percent = RFDoptions$start
                 
-                print(paste("---- RFD number", n, "--------"))
-                print(options)
-                if(RFDoptions$type == "AVERAGE" & (RFDoptions$start == RFDoptions$end)){
-                        RFDoptions$type = "INSTANTANEOUS"
+                if (RFDoptions$rfdFunction == "FITTED")
+                {
+                    time1 = - log(1 - percent/100) / dynamics$k.fitted
+                    
+                    #RFD at the point with a % of the fmax.fitted
+                    RFD = dynamics$fmax.fitted * dynamics$k.fitted * exp(-dynamics$k.fitted * time1)
+                    
+                    #Y coordinate of a point of the line
+                    
+                    force1 = dynamics$fmax.fitted * (1 - exp(-dynamics$k.fitted * time1))
+                    
+                    legendText = c(legendText, paste("RFD", percent, "%Fmax", " = ", round(RFD, digits = 1), 
" N/s", sep = ""))
+                    legendColor = c(legendColor, "blue")
+                    
+                } else if(RFDoptions$rfdFunction == "RAW")
+                {
+                    time1 = interpolateXAtY(dynamics$time, dynamics$f.raw, dynamics$fmax.raw * percent / 100)
+                    
+                    #Slope of the line
+                    RFD = interpolateXAtY(dynamics$rfd, dynamics$time, time1)
+                    
+                    #Y coordinate of a point of the line
+                    force1 = interpolateXAtY(dynamics$f.raw, dynamics$time, time1)
+                    
+                    legendText = c(legendText, paste("RFD", percent, "%", "Fmax", " = ", round(RFD, digits = 
1), " N/s", sep = ""))
+                    legendColor = c(legendColor, "black")
+                    
                 }
-                if(RFDoptions$rfdFunction == "-1")        
+            } else if(RFDoptions$type == "RFD_MAX")
+            {
+                
+                if (RFDoptions$rfdFunction == "FITTED")
                 {
-                        next
-                } else
+                    #max is always in the initial point.
+                    time1 = 0
+                    
+                    #Slope of the line. Deriving the model:
+                    RFD = dynamics$fmax.fitted * dynamics$k.fitted
+                    
+                    #Y coordinate of a point of the line
+                    pointForce1 = 0
+                    
+                    force1 = 0
+                    
+                    legendText = c(legendText, paste("RFDMax", " = ", round(RFD, digits = 1), " N/s", sep = 
""))
+                    legendColor = c(legendColor, "blue")
+                    
+                } else if(RFDoptions$rfdFunction == "RAW")
                 {
-                        
-                        RFD = NULL
-                        pointForce1 = NULL
-                        color = ""
-                        
-                        #Needed when only one point is plotted
-                        sample2 = NULL
-                        pointForce2 = NULL
-                        time2 = NULL
-                        force2 = NULL
-                        
-                        if(RFDoptions$rfdFunction == "FITTED")
-                        {
-                                color = "blue"
-                        } else if(RFDoptions$rfdFunction == "RAW")
-                        {
-                                color = "black"
-                        }
-                        
-                        if(RFDoptions$type == "INSTANTANEOUS") # TODO: || percent ...(all except AVG)
-                        {
-                                #Converting RFDoptions$start to seconds
-                                RFDoptions$start = RFDoptions$start/1000
-                                
-                                time1 = RFDoptions$start
-                                
-                                if (RFDoptions$rfdFunction == "FITTED")
-                                {
-                                        #Slope of the line. Deriving the model:
-                                        RFD = dynamics$fmax.fitted * dynamics$k.fitted * 
exp(-dynamics$k.fitted * time1)
-                                        #Y coordinate of a point of the line
-                                        force1 = dynamics$fmax.fitted * (1 - exp(-dynamics$k.fitted * 
RFDoptions$start))
-                                        
-                                        legendText = c(legendText, paste("RFD", RFDoptions$start*1000, " = 
", round(RFD, digits = 1), " N/s", sep = ""))
-                                        legendColor = c(legendColor, "blue")
-                                        
-                                } else if(RFDoptions$rfdFunction == "RAW")
-                                {
-                                        #Slope of the line of the sampled point.
-                                        RFD = interpolateXAtY(dynamics$rfd, dynamics$time, time1)
-                                        
-                                        #Y coordinate of a point of the line
-                                        force1 = interpolateXAtY(dynamics$f.raw, dynamics$time, 
RFDoptions$start)
-                                        
-                                        legendText = c(legendText, paste("RFD", RFDoptions$start*1000, " = 
", round(RFD, digits = 1), " N/s", sep = ""))
-                                        legendColor = c(legendColor, "black")
-                                }
-                        } else if(RFDoptions$type == "AVERAGE")
-                        {
-                                #Converting RFDoptions to seconds
-                                RFDoptions$start = RFDoptions$start/1000
-                                RFDoptions$end = RFDoptions$end/1000
-                                
-                                time1 = RFDoptions$start
-                                time2 = RFDoptions$end
-                                
-                                if (RFDoptions$rfdFunction == "FITTED")
-                                {
-                                        #Y axis of the points
-                                        force1 = dynamics$fmax.fitted * (1 - exp(-dynamics$k.fitted * 
RFDoptions$start))
-                                        force2 = dynamics$fmax.fitted * (1 - exp(-dynamics$k.fitted * 
RFDoptions$end))
-                                        
-                                        #Slope of the line
-                                        RFD = (force2 - force1) / (time2 - time1)
-                                        
-                                        legendText = c(legendText, paste("RFD", RFDoptions$start*1000, "-", 
RFDoptions$end*1000, " = ", round(RFD, digits = 1), " N/s", sep = ""))
-                                        legendColor = c(legendColor, "blue")
-                                        
-                                } else if(RFDoptions$rfdFunction == "RAW")
-                                {
-                                        force1 = interpolateXAtY(dynamics$f.raw, dynamics$time, 
RFDoptions$start)
-                                        force2 = interpolateXAtY(dynamics$f.raw, dynamics$time, 
RFDoptions$end)
-                                        
-                                        #Slope of the line
-                                        RFD = (force2 - force1) / (time2 - time1)
-                                        
-                                        legendText = c(legendText, paste("RFD", RFDoptions$start*1000, "-", 
RFDoptions$end*1000, " = ", round(RFD, digits = 1), " N/s", sep = ""))
-                                        legendColor = c(legendColor, "black")
-                                }
-                                
-                        } else if(RFDoptions$type == "PERCENT_F_MAX")
-                        {
-                                percent = RFDoptions$start
-                                
-                                if (RFDoptions$rfdFunction == "FITTED")
-                                {
-                                        time1 = - log(1 - percent/100) / dynamics$k.fitted
-                                        
-                                        #RFD at the point with a % of the fmax.fitted
-                                        RFD = dynamics$fmax.fitted * dynamics$k.fitted * 
exp(-dynamics$k.fitted * time1)
-                                        
-                                        #Y coordinate of a point of the line
-                                        
-                                        force1 = dynamics$fmax.fitted * (1 - exp(-dynamics$k.fitted * time1))
-                                        
-                                        legendText = c(legendText, paste("RFD", percent, "%Fmax", " = ", 
round(RFD, digits = 1), " N/s", sep = ""))
-                                        legendColor = c(legendColor, "blue")
-                                        
-                                } else if(RFDoptions$rfdFunction == "RAW")
-                                {
-                                        time1 = interpolateXAtY(dynamics$time, dynamics$f.raw, 
dynamics$fmax.raw * percent / 100)
-                                        
-                                        #Slope of the line
-                                        RFD = interpolateXAtY(dynamics$rfd, dynamics$time, time1)
-                                        
-                                        #Y coordinate of a point of the line
-                                        force1 = interpolateXAtY(dynamics$f.raw, dynamics$time, time1)
-                                        
-                                        legendText = c(legendText, paste("RFD", percent, "%", "Fmax", " = ", 
round(RFD, digits = 1), " N/s", sep = ""))
-                                        legendColor = c(legendColor, "black")
-                                        
-                                }
-                        } else if(RFDoptions$type == "RFD_MAX")
-                        {
-                                
-                                if (RFDoptions$rfdFunction == "FITTED")
-                                {
-                                        #max is always in the initial point.
-                                        time1 = 0
-                                        
-                                        #Slope of the line. Deriving the model:
-                                        RFD = dynamics$fmax.fitted * dynamics$k.fitted
-                                        
-                                        #Y coordinate of a point of the line
-                                        pointForce1 = 0
-                                        
-                                        force1 = 0
-                                        
-                                        legendText = c(legendText, paste("RFDMax", " = ", round(RFD, digits 
= 1), " N/s", sep = ""))
-                                        legendColor = c(legendColor, "blue")
-                                        
-                                } else if(RFDoptions$rfdFunction == "RAW")
-                                {
-                                        #Calculing the sample at which the rfd is max. Using only the initial
-                                        sample1 = dynamics$startSample + 
which.max(dynamics$rfd[dynamics$startSample:dynamics$endSample]) -1
-                                        
-                                        time1 = dynamics$time[sample1]
-                                        
-                                        #Translating RFDoptions$start to time in seconds
-                                        RFDoptions$start = dynamics$time[sample1]
-                                        
-                                        #Slope of the line
-                                        RFD = dynamics$rfd[sample1]
-                                        
-                                        #Y coordinate of a point of the line
-                                        force1 = dynamics$f.raw[sample1]
-                                        
-                                        legendText = c(legendText, paste("RFDmax = ", round(RFD, digits = 
1), " N/s", sep = ""))
-                                        legendColor = c(legendColor, "black")
-                                        
-                                }
-                                
-                        }
-                        
-                        #The Y coordinate of the line when it crosses the Y axis
-                        intercept = force1 - RFD * time1
-                        
-                        #The slope of the line seen in the screen(pixels units), NOT in the time-force units
-                        windowSlope = RFD*(plotHeight/yHeight)/(plotWidth/xWidth)
-                        
-                        #Drawing the line
-                        text(x = (yHeight - 5 - intercept)/RFD, y = yHeight - 5,
-                             label = paste(round(RFD, digits=0), "N/s"),
-                             srt=atan(windowSlope)*180/pi, pos = 2, col = color)
-                        #Drawing the points where the line touch the function
-                        points(x = c(time1, time2), y = c(force1, force2), col = color)
-                        abline(a = intercept, b = RFD, lty = 2, col = color)
+                    #Calculing the sample at which the rfd is max. Using only the initial
+                    sample1 = dynamics$startSample + 
which.max(dynamics$rfd[dynamics$startSample:dynamics$endSample]) -1
+                    
+                    time1 = dynamics$time[sample1]
+                    
+                    #Translating RFDoptions$start to time in seconds
+                    RFDoptions$start = dynamics$time[sample1]
+                    
+                    #Slope of the line
+                    RFD = dynamics$rfd[sample1]
+                    
+                    #Y coordinate of a point of the line
+                    force1 = dynamics$f.raw[sample1]
+                    
+                    legendText = c(legendText, paste("RFDmax = ", round(RFD, digits = 1), " N/s", sep = ""))
+                    legendColor = c(legendColor, "black")
+                    
                 }
+                
+            }
+            
+            #The Y coordinate of the line when it crosses the Y axis
+            intercept = force1 - RFD * time1
+            
+            #The slope of the line seen in the screen(pixels units), NOT in the time-force units
+            windowSlope = RFD*(plotHeight/yHeight)/(plotWidth/xWidth)
+            
+            #Drawing the line
+            text(x = (yHeight - 5 - intercept)/RFD, y = yHeight - 5,
+                 label = paste(round(RFD, digits=0), "N/s"),
+                 srt=atan(windowSlope)*180/pi, pos = 2, col = color)
+            #Drawing the points where the line touch the function
+            points(x = c(time1, time2), y = c(force1, force2), col = color)
+            abline(a = intercept, b = RFD, lty = 2, col = color)
         }
-       if(impulseLegend != ""){
-               legendText = c(legendText, impulseLegend)
-                legendColor = c(legendColor, impulseColor)
-       }
-        
-        legendText = c(legendText, paste("MeanError = ", round(dynamics$meanError, digits = 2), "%", sep 
=""))
-        if (dynamics$meanError >= 5){
-                legendColor = c(legendColor, "red")
-                text(x = xmax, y = dynamics$fmax.fitted*0.01, labels = "The mean error is larger than 5%. 
Possible bad execution", col = "red", pos = 2)
-        } else {
-                legendColor = c(legendColor, "grey40")
-        }
-
-       legend(x = xmax, y = dynamics$fmax.fitted/2, legend = legendText, xjust = 1, yjust = 0.1, text.col = 
legendColor)
+    }
+    if(impulseLegend != ""){
+        legendText = c(legendText, impulseLegend)
+        legendColor = c(legendColor, impulseColor)
+    }
+    
+    legendText = c(legendText, paste("MeanError = ", round(dynamics$meanError, digits = 2), "%", sep =""))
+    if (dynamics$meanError >= 5){
+        legendColor = c(legendColor, "red")
+        text(x = xmax, y = dynamics$fmax.fitted*0.01, labels = "The mean error is larger than 5%. Possible 
bad execution", col = "red", pos = 2)
+    } else {
+        legendColor = c(legendColor, "grey40")
+    }
+    
+    legend(x = xmax, y = dynamics$fmax.fitted/2, legend = legendText, xjust = 1, yjust = 0.1, text.col = 
legendColor)
 }
 
 getDynamicsFromLoadCellFolder <- function(folderName, resultFileName, export2Pdf)
 {
-        originalFiles = list.files(path=folderName, pattern="*")
-        nFiles = length(originalFiles)
-        results = matrix(rep(NA, 16*nFiles), ncol = 16)
-        colnames(results)=c("fileName", "fmax.fitted", "k.fitted", "fmax.raw", "startTime", "initf", 
"fmax.smoothed",
-                            "rfd0.fitted", "rfd100.raw", "rfd0_100.raw", "rfd0_100.fitted",
-                            "rfd200.raw", "rfd0_200.raw", "rfd0_200.fitted",
-                            "rfd50pfmax.raw", "rfd50pfmax.fitted")
-        
-        results[,"fileName"] = originalFiles
-        
-        for(i in 1:nFiles)
-        {
-                dynamics = getDynamicsFromLoadCellFile(op$captureOptions, paste(folderName,originalFiles[i], 
sep = ""))
-                
-                results[i, "fileName"] = dynamics$nameOfFile
-                results[i, "fmax.fitted"] = dynamics$fmax.fitted
-                results[i, "k.fitted"] = dynamics$k.fitted
-                results[i, "fmax.raw"] = dynamics$fmax.raw
-                results[i, "startTime"] = dynamics$startTime
-                results[i, "initf"] = dynamics$initf
-                results[i, "fmax.smoothed"] = dynamics$fmax.smoothed
-                results[i, "rfd0.fitted"] = dynamics$rfd0.fitted
-                results[i, "rfd100.raw"] = dynamics$rfd100.raw
-                results[i, "rfd0_100.raw"] = dynamics$rfd0_100.raw
-                results[i, "rfd0_100.fitted"] = dynamics$rfd0_100.fitted
-                results[i, "rfd200.raw"] = dynamics$rfd200.raw
-                results[i, "rfd0_200.raw"] = dynamics$rfd0_200.raw
-                results[i, "rfd0_200.fitted"] = dynamics$rfd0_200.fitted
-                results[i, "rfd50pfmax.raw"] = dynamics$rfd50pfmax.rawfilter(test$force, rep(1/19, 19), 
sides = 2)
-                results[i, "rfd50pfmax.fitted"] = dynamics$rfd50pfmax.fitted
-        }
-        write.table(results, file = resultFileName, sep = ";", dec = ",", col.names = NA)
-        return(results)
+    originalFiles = list.files(path=folderName, pattern="*")
+    nFiles = length(originalFiles)
+    results = matrix(rep(NA, 16*nFiles), ncol = 16)
+    colnames(results)=c("fileName", "fmax.fitted", "k.fitted", "fmax.raw", "startTime", "previousForce", 
"fmax.smoothed",
+                        "rfd0.fitted", "rfd100.raw", "rfd0_100.raw", "rfd0_100.fitted",
+                        "rfd200.raw", "rfd0_200.raw", "rfd0_200.fitted",
+                        "rfd50pfmax.raw", "rfd50pfmax.fitted")
+    
+    results[,"fileName"] = originalFiles
+    
+    for(i in 1:nFiles)
+    {
+        dynamics = getDynamicsFromLoadCellFile(op$captureOptions, paste(folderName,originalFiles[i], sep = 
""))
         
+        results[i, "fileName"] = dynamics$nameOfFile
+        results[i, "fmax.fitted"] = dynamics$fmax.fitted
+        results[i, "k.fitted"] = dynamics$k.fitted
+        results[i, "fmax.raw"] = dynamics$fmax.raw
+        results[i, "startTime"] = dynamics$startTime
+        results[i, "previousForce"] = dynamics$previousForce
+        results[i, "fmax.smoothed"] = dynamics$fmax.smoothed
+        results[i, "rfd0.fitted"] = dynamics$rfd0.fitted
+        results[i, "rfd100.raw"] = dynamics$rfd100.raw
+        results[i, "rfd0_100.raw"] = dynamics$rfd0_100.raw
+        results[i, "rfd0_100.fitted"] = dynamics$rfd0_100.fitted
+        results[i, "rfd200.raw"] = dynamics$rfd200.raw
+        results[i, "rfd0_200.raw"] = dynamics$rfd0_200.raw
+        results[i, "rfd0_200.fitted"] = dynamics$rfd0_200.fitted
+        results[i, "rfd50pfmax.raw"] = dynamics$rfd50pfmax.rawfilter(test$force, rep(1/19, 19), sides = 2)
+        results[i, "rfd50pfmax.fitted"] = dynamics$rfd50pfmax.fitted
+    }
+    write.table(results, file = resultFileName, sep = ";", dec = ",", col.names = NA)
+    return(results)
+    
 }
 
 #Finds the sample in which the force start incresing with two optional methods
@@ -756,130 +777,281 @@ getDynamicsFromLoadCellFolder <- function(folderName, resultFileName, export2Pdf
 #The maximum force is calculed from the moving average of averageLength seconds
 getAnalysisRange <- function(test, rfd, movingAverageForce, averageLength = 0.1, percentChange = 5, 
testLength = -1, startDetectingMethod = "SD")
 {
-        print("Entering getAnalysisRange")
-        print("test:")
-        print(test)
-        movingAverageForce = getMovingAverageForce(test, averageLength = 0.1)
-        maxRFD = max(rfd[2:(length(rfd) - 1)])
-        maxRFDSample = which.max(rfd[2:(length(rfd) - 1)])
-        print(maxRFDSample)
+    print("Entering getAnalysisRange")
+    print("test:")
+    print(test)
+    movingAverageForce = getMovingAverageForce(test, averageLength = 0.1)
+    maxRFD = max(rfd[2:(length(rfd) - 1)])
+    maxRFDSample = which.max(rfd[2:(length(rfd) - 1)])
+    print(maxRFDSample)
+    
+    #Detecting when the force is greater than (mean of 20 samples) + 3*SD
+    #If in various sample the force are greater, the last one before the maxRFD are taken
+    #See Rate of force development: physiological and methodological considerations. Nicola A. Maffiuletti1 
et al.
+    
+    startSample = NULL
+    if (startDetectingMethod == "SD"){
         
-        #Detecting when the force is greater than (mean of 20 samples) + 3*SD
-        #If in various sample the force are greater, the last one before the maxRFD are taken
-        #See Rate of force development: physiological and methodological considerations. Nicola A. 
Maffiuletti1 et al.
-        
-        startSample = NULL
-        if (startDetectingMethod == "SD"){
+        for(currentSample in 21:maxRFDSample)
+        {
+            print(paste(currentSample, test$time[currentSample], test$force[currentSample]))
             
-                for(currentSample in 21:maxRFDSample)
-                {
-                        print(paste(currentSample, test$time[currentSample], test$force[currentSample]))
-                        
-                        if(test$force[currentSample] < mean(test$force[currentSample:(currentSample - 20)]) 
+ 3*sd(test$force[currentSample:(currentSample - 20)]))
-                                startSample = currentSample
-                }
-                
-                while(test$force[startSample] - test$force[startSample -1] >= 0){ #Going back to the last 
sample that decreased
-                        startSample = startSample - 1
-                }
+            if(test$force[currentSample] < mean(test$force[currentSample:(currentSample - 20)]) + 
3*sd(test$force[currentSample:(currentSample - 20)]))
+                startSample = currentSample
+        }
+        
+        while(test$force[startSample] - test$force[startSample -1] >= 0){ #Going back to the last sample 
that decreased
+            startSample = startSample - 1
+        }
         #Detecting when accurs a great growth of the force (great RFD)
-        } else if (startDetectingMethod == "RFD"){
-                for(currentSample in 2:maxRFDSample)
-                {
-                        if(rfd[currentSample] <= maxRFD*0.2)
-                                startSample = currentSample
-                }
+    } else if (startDetectingMethod == "RFD"){
+        for(currentSample in 2:maxRFDSample)
+        {
+            if(rfd[currentSample] <= maxRFD*0.2)
+                startSample = currentSample
         }
-        #Using the decrease of the force to detect endingSample
-        if (testLength <= -1){
-                endSample = startSample + 1
-                maxAverageForce = movingAverageForce[endSample]
-                while(movingAverageForce[endSample] > maxAverageForce*(100 - percentChange) / 100 &
-                      endSample < length(test$time))
-                {
-                        if(movingAverageForce[endSample] > maxAverageForce)
-                        {
-                                maxAverageForce = movingAverageForce[endSample]
-                        }
-                        endSample = endSample + 1
-                }
-        } else if(testLength >= 0 && testLength < 0.1){
-                print("Test interval too short")
-                
-        #Using the fixed time to detect endSample
-        } else {
-                endSample = which.min(abs(test$time[startSample] + testLength - test$time))
+    }
+    #Using the decrease of the force to detect endingSample
+    if (testLength <= -1){
+        endSample = startSample + 1
+        maxMovingAverageForce = movingAverageForce[endSample]
+        while(movingAverageForce[endSample] > maxMovingAverageForce*(100 - percentChange) / 100 &
+              endSample < length(test$time))
+        {
+            if(movingAverageForce[endSample] > maxMovingAverageForce)
+            {
+                maxMovingAverageForce = movingAverageForce[endSample]
+            }
+            endSample = endSample + 1
         }
-        print(paste("startSample:", startSample, "endSample:", endSample))
-
-        return(list(startSample = startSample, endSample = endSample))
+    } else if(testLength >= 0 && testLength < 0.1){
+        print("Test interval too short")
+        
+        #Using the fixed time to detect endSample
+    } else {
+        endSample = which.min(abs(test$time[startSample] + testLength - test$time))
+    }
+    print(paste("startSample:", startSample, "endSample:", endSample))
+    
+    return(list(startSample = startSample, endSample = endSample))
 }
 
 getRFD <- function(test)
 {
-        #Instantaneous RFD
-        rfd = rep(NA, length(test$time))
-        for (n in 2:(length(test$time) - 1))
-        {
-                rfd[n] = (test$force[n + 1] - test$force[n - 1])/(test$time[n + 1] - test$time[n - 1])
-        }
-        return(rfd)
+    #Instantaneous RFD
+    rfd = rep(NA, length(test$time))
+    for (n in 2:(length(test$time) - 1))
+    {
+        rfd[n] = (test$force[n + 1] - test$force[n - 1])/(test$time[n + 1] - test$time[n - 1])
+    }
+    return(rfd)
 }
 getMovingAverageForce <- function(test, averageLength = 0.1)
 {
-        sampleRate = (length(test$time) - 1) / (test$time[length(test$time)] - test$time[1])
-        lengthSamples = round(averageLength * sampleRate, digits = 0)
-        movingAverageForce = filter(test$force, rep(1/lengthSamples, lengthSamples), sides = 2)
-        return(movingAverageForce)
+    sampleRate = (length(test$time) - 1) / (test$time[length(test$time)] - test$time[1])
+    lengthSamples = round(averageLength * sampleRate, digits = 0)
+    movingAverageForce = filter(test$force, rep(1/lengthSamples, lengthSamples), sides = 2)
+    return(movingAverageForce)
+}
+
+#estrapolate a function to extend the line joining the two first samples until it cross the horizontal axe
+extrapolateToZero <- function(x, y)
+{
+    #t0 is the x at which an extrapolation of the two first samples would cross the horizontal axis
+    t0 = y[1] * (x[2] - x[1]) / (y[2] - y[1])
+    print(paste("t0: ", t0))
+    
+    
+    #Adding the (0,0)
+    x = c(x[1] - t0, x)
+    y = c(0, y)
+    
+    return(list(x = x, y = y))
+}
+
+getBestFit <- function(inputFile = 
"/home/xpadulles/.local/share/Chronojump/forceSensor/39/100_Carmelo_2019-09-26_12-49-09.csv"
+                       , averageLength = 0.1, percentChange = 5, testLength = -1)
+{
+    originalTest = read.csv2(inputFile)
+    colnames(originalTest) <- c("time", "force")
+    originalTest$time = as.numeric(originalTest$time / 1000000)  # Time is converted from microseconds to 
seconds
+    
+    rfd = getRFD(originalTest)
+    maxRFDSample = which.max(rfd)
+    
+    maxForce = max(originalTest$force)
+    
+    #Going back from maxRFD sample until the force increase
+    startSample = maxRFDSample -1
+    while(originalTest$force[startSample] < originalTest$force[startSample + 1])
+    {
+        startSample = startSample - 1
+    }
+    
+    startSample = startSample + 1
+    
+    #Calculing the end sample of the analysis
+    if(testLength > 0)      #The user selected the fixed length of the test
+    {
+        print("End detection by test length")
+        endSample = which.min(abs(originalTest$time - (originalTest$time[startSample] + testLenght)))
+    } else if (testLength <= -1)    #The user selected to detect a decrease in the force
+    {
+        print("End detection by decrease in the force")
+        print(paste("percentChange: ", percentChange))
+        movingAverageForce = getMovingAverageForce(originalTest, averageLength)
+        endSample = maxRFDSample
+        maxMovingAverageForce = max(movingAverageForce[startSample:endSample])
+        print(paste("MaxMovingAverageForce: ", maxMovingAverageForce, "Current Limit: ", 
maxMovingAverageForce*(100 - percentChange) / 100))
+        print(paste("Current movingAverageForce: ", movingAverageForce[endSample]))
+        while(movingAverageForce[endSample] >= maxMovingAverageForce*(100 - percentChange) / 100 &
+              endSample < length(originalTest$time))
+        {
+            print(paste("Current movingAverageForce: ", movingAverageForce[endSample]))
+            if(movingAverageForce[endSample] > maxMovingAverageForce)
+            {
+                print("New max")
+                maxMovingAverageForce = movingAverageForce[endSample]
+            }
+            endSample = endSample + 1
+        }
+    }
+    
+    #Moving all the sample to make the fisrt sample of the trimmed test the (t0, f0)
+    trimmedTest = originalTest[startSample:endSample,]
+    
+    #Extrapolating the test
+    trimmedTest = extrapolateToZero(trimmedTest$time, trimmedTest$force)
+    names(trimmedTest) <- c("time", "force")
+    trimmedTest$time = trimmedTest$time - trimmedTest$time[1]
+    print("trimmedTest:")
+    print(trimmedTest)
+    
+    print(paste("startTime: ", trimmedTest$time[1], "fmaxi: ", maxForce, "previousForce: ", 
originalTest$force[1]))
+    forceModel <- getForceModel(time = trimmedTest$time
+                                , force = trimmedTest$force
+                                , startTime = trimmedTest$time[1]
+                                , fmaxi = maxForce
+                                , previousForce = originalTest$force[1])
+    currentMeanError = mean(abs(forceModel$error[!is.nan(forceModel$error)]))
+    
+    lastMeanError = 1E6
+    
+    
+    print(paste("currentMeanError: ", currentMeanError, "lastMeanError: ", lastMeanError))
+    print(paste(startSample, ":", endSample, sep = ""))
+    print("Entering the while")
+    
+    while(currentMeanError <= lastMeanError & endSample < length(originalTest$time))
+    {
+        startSample = startSample +1
+        endSample = endSample +1
+        
+        lastMeanError = currentMeanError
+        
+        trimmedTest = originalTest[startSample:endSample,]
+        
+        #Extrapolating the test
+        trimmedTest = extrapolateToZero(trimmedTest$time, trimmedTest$force)
+        names(trimmedTest) <- c("time", "force")
+        trimmedTest$time = trimmedTest$time - trimmedTest$time[1]
+        
+        forceModel <- getForceModel(trimmedTest$time, trimmedTest$force, trimmedTest$time[1], maxForce, 
trimmedTest$force[1])
+        currentMeanError = mean(abs(forceModel$error[!is.nan(forceModel$error)]))
+        print("----------")
+        print(paste("currentMeanError: ", currentMeanError, "lastMeanError: ", lastMeanError))
+        print(paste(startSample, ":", endSample, sep = ""))
+    }
+    
+    print("--------------")
+    print("|while exited|")
+    print("--------------")
+    
+    startSample = startSample -1
+    endSample = endSample -1
+    
+    lastMeanError = currentMeanError
+    
+    trimmedTest = originalTest[startSample:endSample,]
+    
+    #Extrapolating the test
+    trimmedTest = extrapolateToZero(trimmedTest$time, trimmedTest$force)
+    names(trimmedTest) <- c("time", "force")
+    trimmedTest$time = trimmedTest$time - trimmedTest$time[1]
+    
+    #Saving the time of startSample and endSample before all the times are adjusted to the onset
+    startTime = originalTest$time[startSample]
+    endTime = originalTest$time[endSample]
+    #Moving the original test to match the times in trimmedTest
+    originalTest$time = originalTest$time - originalTest$time[startSample] + trimmedTest$time[2]
+    
+    forceModel <- getForceModel(trimmedTest$time, trimmedTest$force, trimmedTest$time[1], 
maxMovingAverageForce, trimmedTest$force[1])
+    currentMeanError = mean(abs(forceModel$error[!is.nan(forceModel$error)]))
+    
+    print(paste("currentMeanError: ", currentMeanError, "lastMeanError: ", lastMeanError))
+    print(paste("samples: ", startSample, ":", endSample, sep = ""))
+    print(paste("time: ", startTime, ":", endTime))
+    
+    # plot(originalTest$time[(startSample - 10):(endSample +10)], originalTest$force[(startSample - 
10):(endSample +10)], type = "l", col = "grey")
+    # lines(trimmedTest$time, trimmedTest$force)
+    # print(paste("forceModel$K: ", forceModel$K))
+    # 
+    # fittedTime = seq(0, 10, by = 0.01)
+    # fittedForce = forceModel$fmax*(1-exp(-forceModel$K*fittedTime))
+    # lines(fittedTime, fittedForce, lty = 2)
+    return(list(model = forceModel
+                , startSample = startSample, startTime = startTime - trimmedTest$time[2]
+                , endSample = endSample, endTime = endTime
+    ))
 }
 
 #Converts the drawRfdOptions string to a list of parameters
 readRFDOptions <- function(optionsStr)
 {
-        if(optionsStr == "-1")          #Not drawing
-        {
-                return(list(
-                        rfdFunction     = "-1",
-                        type            = "-1",
-                        start           = -1,
-                        end             = -1
-                ))
-        } else
-        {
-                options = unlist(strsplit(optionsStr, "\\;"))
-                
-                return(list(
-                        rfdFunction     = options[1],            # raw or fitted
-                        type            = options[2],            # instantaeous, average, %fmax, rfdmax
-                        #start and end can be in milliseconds (instant and average RFD), percentage (%fmax) 
or -1 if not needed
-                        start           = as.numeric(options[3]),            # instant at which the analysis 
starts
-                        end             = as.numeric(options[4])             # instant at which the analysis 
ends
-                ))
-        } 
+    if(optionsStr == "-1")          #Not drawing
+    {
+        return(list(
+            rfdFunction     = "-1",
+            type            = "-1",
+            start           = -1,
+            end             = -1
+        ))
+    } else
+    {
+        options = unlist(strsplit(optionsStr, "\\;"))
+        
+        return(list(
+            rfdFunction     = options[1],            # raw or fitted
+            type            = options[2],            # instantaeous, average, %fmax, rfdmax
+            #start and end can be in milliseconds (instant and average RFD), percentage (%fmax) or -1 if not 
needed
+            start           = as.numeric(options[3]),            # instant at which the analysis starts
+            end             = as.numeric(options[4])             # instant at which the analysis ends
+        ))
+    } 
 }
 
 #Converts the line string of Roptions to a list of parameters
 readImpulseOptions <- function(optionsStr)
 {
-        if(optionsStr == "-1")          #Not drawing
-        {
-                return(list(
-                        impulseFunction     = "-1",
-                        type            = "-1",
-                        start           = -1,
-                        end             = -1
-                ))
-        } else
-        {
-                options = unlist(strsplit(optionsStr, "\\;"))
-                
-                return(list(
-                        impulseFunction     = options[1],                    # RAW or FITTED
-                        type            = options[2],                        # IMP_RANGE or 
IMP_UNTIL_PERCENT_F_MAX
-                        start           = as.numeric(options[3]),            # instant at which the analysis 
starts in ms
-                        end             = as.numeric(options[4])             # instant at which the analysis 
ends in ms
-                ))
-        } 
+    if(optionsStr == "-1")          #Not drawing
+    {
+        return(list(
+            impulseFunction     = "-1",
+            type            = "-1",
+            start           = -1,
+            end             = -1
+        ))
+    } else
+    {
+        options = unlist(strsplit(optionsStr, "\\;"))
+        
+        return(list(
+            impulseFunction     = options[1],                    # RAW or FITTED
+            type            = options[2],                        # IMP_RANGE or IMP_UNTIL_PERCENT_F_MAX
+            start           = as.numeric(options[3]),            # instant at which the analysis starts in ms
+            end             = as.numeric(options[4])             # instant at which the analysis ends in ms
+        ))
+    } 
 }
 
 prepareGraph(op$os, pngFile, op$graphWidth, op$graphHeight)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]