[chronojump] Encoder util.R calcules work and impulse



commit d56596d727ee4db8f0fd5418126b7b79446438ed
Author: Xavier de Blas <xaviblas gmail com>
Date:   Thu Oct 31 13:59:37 2019 +0100

    Encoder util.R calcules work and impulse

 encoder/capture.R           |  2 ++
 encoder/graph.R             | 13 +++++--
 encoder/util.R              | 39 +++++++++++++++++++--
 src/encoder.cs              | 20 ++++++++---
 src/gui/encoder.cs          |  6 ++--
 src/gui/encoderTreeviews.cs | 83 +++++++++++++++++++++++++++++++++++++++------
 6 files changed, 141 insertions(+), 22 deletions(-)
---
diff --git a/encoder/capture.R b/encoder/capture.R
index d49f859e..3b1ca027 100644
--- a/encoder/capture.R
+++ b/encoder/capture.R
@@ -96,6 +96,8 @@ calcule <- function(displacement, op, curveNum, startInSet)
                  paf$meanSpeed, paf$maxSpeed, paf$maxSpeedT, 
                  paf$meanPower, paf$peakPower, paf$peakPowerT, paf$pp_ppt, 
                  paf$meanForce, paf$maxForce, paf$maxForceT, paf$maxForce_maxForceT,
+                 paf$workJ,            # C# will convert to Kcal if needed
+                 paf$impulse,
                  sep=", "), file = con)
        close(con)
        #if(debug)
diff --git a/encoder/graph.R b/encoder/graph.R
index 58349df6..33f149d1 100644
--- a/encoder/graph.R
+++ b/encoder/graph.R
@@ -1491,10 +1491,14 @@ findPosInPaf <- function(var, option) {
                 pos = 13
         else if(var == "MassExtra")
                 pos = 14
-        else if(var == "Laterality")
+        else if(var == "workJ")
                 pos = 15
-        else if(var == "Inertia")
+        else if(var == "impulse")
                 pos = 16
+        else if(var == "Laterality")
+                pos = 17
+        else if(var == "Inertia")
+                pos = 18
         
         if( ( var == "Speed" || var == "Power" || var == "Force") & option == "max")
                 pos=pos+1
@@ -3827,10 +3831,10 @@ doProcess <- function(options)
                                                 "pp_ppt",
                                                 "meanForce", "maxForce", "maxForceT",
                                                 "maxForce_maxForceT",
+                                               "workJ", "impulse",
                                                 "laterality", "inertiaM"
                         )
                         
-                        
                         #Add "Max", "AVG" and "SD" when analyzing, not on "curves", not on "curvesAC"
                         if(op$Analysis != "curves" && op$Analysis != "curvesAC") {
                                 addSD = FALSE
@@ -3846,6 +3850,7 @@ doProcess <- function(options)
                                                          max(pafCurves$pp_ppt),
                                                          max(pafCurves$meanForce), max(pafCurves$maxForce), 
max(pafCurves$maxForceT),
                                                          max(pafCurves$maxForce_maxForceT),
+                                                        max(pafCurves$workJ), max(pafCurves$impulse),
                                                          "", max(pafCurves$inertiaM)
                                         )
                                         
@@ -3857,6 +3862,7 @@ doProcess <- function(options)
                                                          mean(pafCurves$pp_ppt),
                                                          mean(pafCurves$meanForce), 
mean(pafCurves$maxForce), mean(pafCurves$maxForceT),
                                                          mean(pafCurves$maxForce_maxForceT),
+                                                        mean(pafCurves$workJ), mean(pafCurves$impulse),
                                                          "", mean(pafCurves$inertiaM)
                                         )
                                         
@@ -3869,6 +3875,7 @@ doProcess <- function(options)
                                                                 sd(pafCurves$pp_ppt),
                                                                 sd(pafCurves$meanForce), 
sd(pafCurves$maxForce), sd(pafCurves$maxForceT),
                                                                sd(pafCurves$maxForce_maxForceT),
+                                                               sd(pafCurves$workJ), sd(pafCurves$impulse),
                                                                 "", sd(pafCurves$inertiaM)
                                                 )
                                         
diff --git a/encoder/util.R b/encoder/util.R
index dd428f04..c5ec01da 100644
--- a/encoder/util.R
+++ b/encoder/util.R
@@ -658,6 +658,13 @@ kinematicsF <- function(displacement, repOp, smoothingOneEC, smoothingOneC, g, i
        #write("kinematicsF speed length and mean,", stderr())
        #write(length(speed$y[start:end]), stderr())
        #write(mean(speed$y[start:end]), stderr())
+       write("kinematicsF displacement length, displ length", stderr())
+       write(length(displacement), stderr())
+       write(length(displacement[start:end]), stderr())
+
+       speedyangular = 0
+       if(isInertial(repOp$econfName))
+               speedyangular = dynamics$angleSpeed[start:end]
 
        return(list(
                    displ = displacement[start:end], 
@@ -665,7 +672,9 @@ kinematicsF <- function(displacement, repOp, smoothingOneEC, smoothingOneC, g, i
                    accely = accel$y[start:end], 
                    force = force[start:end], 
                    power = power[start:end], 
-                   mass = mass))
+                   mass = mass,
+                   speedyangular = speedyangular
+                   ))
 }
 
 findECPhases <- function(displacement,speed) {
@@ -775,6 +784,30 @@ pafGenerate <- function(eccon, kinematics, massBody, massExtra, laterality, iner
        maxForceT <- min(which(abs(kinematics$force) == maxForce))
        maxForce_maxForceT <- maxForce / (maxForceT/1000)       # ms->s
 
+       #work calculation
+       #calculating with mean force has the problem that the displacement is not always the same
+       #so is not correct and has to be (at each ms): force * displ
+       #workJ <- meanForce * max(abs(kinematics$displ))        #F * displ # TODO: maybe calculate by phases 
with a distance always positive
+
+       #work by difference of energy (Joules)
+       #W = m[g(hf - hi) + 1/2 (vf^2 - Vi^2)] + 1/2 I(wf^2 - wi^2)
+       #                                      <--  on inertial -->
+       #hi, hf: height initial/final
+       #vi, vf: speed initial/final
+       #wi, wf: angular speed initial/final
+       lastValue = length(kinematics$displ)
+       workJ <- kinematics$mass * ( g * (kinematics$displ[lastValue] - kinematics$displ[1]) + 
.5*((kinematics$speedy[lastValue])^2 - (kinematics$speedy[1])^2) )
+       if(inertiaMomentum > 0) #if is not inertial Roptions has a -1
+               workJ = workJ + .5 * inertiaMomentum * ( (kinematics$speedyangular[lastValue])^2 - 
(kinematics$speedyangular[1]^2) )
+
+       #impulse
+       impulse <- meanForce * length(kinematics$displ)/1000    #F * time in s
+
+       print("meanForce: ")
+       print(meanForce)
+       print("displ: ")
+       print(length(kinematics$displ)/1000)
+
        #here paf is generated
        #mass is not used by pafGenerate, but used by Kg/W (loadVSPower)
        #meanForce and maxForce are not used by pafGenerate, but used by F/S (forceVSSpeed)
@@ -785,7 +818,9 @@ pafGenerate <- function(eccon, kinematics, massBody, massExtra, laterality, iner
                          meanPower, peakPower, peakPowerT, pp_ppt,
                          meanForce, maxForce, maxForceT, maxForce_maxForceT,
                          mass, massBody, massExtra,            #kinematics$mass is Load
-                         laterality, inertiaMomentum)) 
+                         workJ, impulse,
+                         laterality, inertiaMomentum
+                         ))
 }
 
 isInertial <- function(encoderConfigurationName) {
diff --git a/src/encoder.cs b/src/encoder.cs
index 0149309d..1f0cb634 100644
--- a/src/encoder.cs
+++ b/src/encoder.cs
@@ -248,6 +248,8 @@ public class EncoderCurve
        public string MaxForce;
        public string MaxForceT;
        public string MaxForce_MaxForceT;
+       public string WorkJ;
+       public string Impulse;
 
        public EncoderCurve () {
        }
@@ -259,7 +261,8 @@ public class EncoderCurve
                        string meanPower, string peakPower, string peakPowerT, 
                        string PP_PPT,
                        string meanForce, string maxForce, string maxForceT,
-                       string maxForce_maxForceT
+                       string maxForce_maxForceT,
+                       string workJ, string impulse
                        )
        {
                this.Record = record;
@@ -278,6 +281,8 @@ public class EncoderCurve
                this.MaxForce = maxForce;
                this.MaxForceT = maxForceT;
                this.MaxForce_MaxForceT = maxForce_maxForceT;
+               this.WorkJ = workJ;
+               this.Impulse = impulse;
        }
 
        //used on TreeView analyze
@@ -290,7 +295,8 @@ public class EncoderCurve
                        string meanPower, string peakPower, string peakPowerT, 
                        string PP_PPT,
                        string meanForce, string maxForce, string maxForceT,
-                       string maxForce_maxForceT)
+                       string maxForce_maxForceT,
+                       string workJ, string impulse)
        {
                this.N = n;
                this.Series = series;
@@ -313,6 +319,8 @@ public class EncoderCurve
                this.MaxForce = maxForce;
                this.MaxForceT = maxForceT;
                this.MaxForce_MaxForceT = maxForce_maxForceT;
+               this.WorkJ = workJ;
+               this.Impulse = impulse;
        }
 
        public EncoderCurve Copy()
@@ -323,7 +331,8 @@ public class EncoderCurve
                                MeanPower, PeakPower, PeakPowerT,
                                PP_PPT,
                                MeanForce, MaxForce, MaxForceT,
-                               MaxForce_MaxForceT);
+                               MaxForce_MaxForceT,
+                               WorkJ, Impulse);
                return curveCopy;
        }
 
@@ -415,7 +424,8 @@ public class EncoderCurve
                                MeanPower + sep + PeakPower + sep + PeakPowerT + sep + 
                                PP_PPT + sep +
                                MeanForce + sep + MaxForce + sep + MaxForceT + sep +
-                               MaxForce_MaxForceT;
+                               MaxForce_MaxForceT + sep +
+                               WorkJ + sep + Impulse;
                
                if(decimalSeparator == "COMMA")
                        str = Util.ConvertToComma(str);
@@ -435,6 +445,8 @@ public class EncoderCurve
        public double MeanForceD { get { return Convert.ToDouble(MeanForce); } }
        public double MaxForceD  { get { return Convert.ToDouble(MaxForce);  } }
 
+       public double WorkJD  { get { return Convert.ToDouble(WorkJ);  } }
+       public double WorkKcalD  { get { return Convert.ToDouble(WorkJ) * 0.000239006;  } }
        
        ~EncoderCurve() {}
 }
diff --git a/src/gui/encoder.cs b/src/gui/encoder.cs
index 3a6983f3..9eee089e 100644
--- a/src/gui/encoder.cs
+++ b/src/gui/encoder.cs
@@ -5448,7 +5448,8 @@ public partial class ChronoJumpWindow
                                                ",series,exercise,mass,start,width,height," + 
                                                "meanSpeed,maxSpeed,maxSpeedT," +
                                                "meanPower,peakPower,peakPowerT,pp_ppt," +
-                                               "meanForce, maxForce, maxForceT, maxForce_maxForceT");
+                                               "meanForce, maxForce, maxForceT, maxForce_maxForceT," +
+                                               "workJ, impulse");
 
                                string filename = UtilEncoder.GetEncoderCaptureTempFileName();
                                if(File.Exists(filename))
@@ -5835,7 +5836,8 @@ public partial class ChronoJumpWindow
                                        strs[7], strs[8], strs[9],      //powers
                                        strs[10],                       //pp/ppt
                                        strs[11], strs[12], strs[13],   //forces
-                                       strs[14]                        //maxForce_maxForceT
+                                       strs[14],                       //maxForce_maxForceT
+                                       strs[15], strs[16]              //workJ, impulse
                                        ));
 
                        //LogB.Debug("encoderCaptureStringR");
diff --git a/src/gui/encoderTreeviews.cs b/src/gui/encoderTreeviews.cs
index d10d261a..d1d681c6 100644
--- a/src/gui/encoderTreeviews.cs
+++ b/src/gui/encoderTreeviews.cs
@@ -64,6 +64,12 @@ public partial class ChronoJumpWindow
 
                bool showStartAndDuration = preferences.encoderShowStartAndDuration;
 
+               string workString = Catalog.GetString("Work");
+               if(preferences.encoderWorkKcal)
+                       workString += "\n (KCal)";
+               else
+                       workString += "\n (J)";
+
                string [] columnsString = {
                        Catalog.GetString("n") + "\n",
                        Catalog.GetString("Start") + "\n (s)",
@@ -79,7 +85,9 @@ public partial class ChronoJumpWindow
                        "F" + "\n (N)",
                        "Fmax" + "\n (N)",
                        "t->Fmax" + "\n (s)",
-                       "RFD" + "\n (N/s)"
+                       "RFD" + "\n (N/s)",
+                       workString,
+                       Catalog.GetString("Impulse") + "\n (N*s)"
                };
 
                encoderCaptureCurves = new ArrayList ();
@@ -131,7 +139,8 @@ public partial class ChronoJumpWindow
                                                cells[11], cells[12], cells[13],//meanPower, peakPower, 
peakPowerT
                                                cells[14],                      //peakPower / peakPowerT
                                                cells[15], cells[16], cells[17], //meanForce, maxForce 
maxForceT
-                                               cells[18]                       //meanForce / meanForceT
+                                               cells[18],                      //meanForce / meanForceT
+                                               cells[19], cells[20]            //work, impulse
                                                ));
 
                }
@@ -232,6 +241,12 @@ public partial class ChronoJumpWindow
                                case 14:
                                        aColumn.SetCellDataFunc (aCell, new Gtk.TreeCellDataFunc 
(RenderMaxForce_maxForceT));
                                        break;
+                               case 15:
+                                       aColumn.SetCellDataFunc (aCell, new Gtk.TreeCellDataFunc 
(RenderWork));
+                                       break;
+                               case 16:
+                                       aColumn.SetCellDataFunc (aCell, new Gtk.TreeCellDataFunc 
(RenderImpulse));
+                                       break;
                        }
                                        
                        if( ! ( (i == 1 || i == 2) && ! showStartAndDuration ) )
@@ -568,6 +583,12 @@ public partial class ChronoJumpWindow
                        distanceUnits = "(mm)";
                }
 
+               string workString = Catalog.GetString("Work");
+               if(preferences.encoderWorkKcal)
+                       workString += "\n (KCal)";
+               else
+                       workString += "\n (J)";
+
                string [] treeviewEncoderAnalyzeHeaders = {
                        Catalog.GetString("Repetition") + "\n",
                        Catalog.GetString("Series") + "\n",
@@ -589,7 +610,9 @@ public partial class ChronoJumpWindow
                        "F" + "\n(N)",
                        "Fmax" + "\n(N)",
                        "t->Fmax" + "\n" + timeUnits,
-                       "RFD" + "\n(N/s)"
+                       "RFD" + "\n(N/s)",
+                       workString,
+                       Catalog.GetString("Impulse") + "\n (N*s)"
                };
                return treeviewEncoderAnalyzeHeaders;
        }
@@ -666,16 +689,17 @@ public partial class ChronoJumpWindow
                                                        cells[0], 
                                                        cells[1],       //seriesName 
                                                        exerciseName,
-                                                       cells[19],      //laterality
+                                                       cells[21],      //laterality
                                                        
Convert.ToDouble(Util.ChangeDecimalSeparator(cells[4])),        //extraWeight
                                                        totalMass,                                            
          //displaceWeight
-                                                       Convert.ToInt32(cells[20]),                           
          //inertia
+                                                       Convert.ToInt32(cells[22]),                           
          //inertia
                                                        cells[5], cells[6], cells[7], 
                                                        cells[8], cells[9], cells[10], 
                                                        cells[11], cells[12], cells[13],
                                                        cells[14],
                                                        cells[15], cells[16], cells[17], //meanForce, 
maxSForce maxForceT
-                                                       cells[18]
+                                                       cells[18],
+                                                       cells[19], cells[20]
                                                        ));
 
                        } while(true);
@@ -771,6 +795,12 @@ public partial class ChronoJumpWindow
                                case 20:
                                        aColumn.SetCellDataFunc (aCell, new Gtk.TreeCellDataFunc 
(RenderMaxForce_maxForceT));
                                        break;
+                               case 21:
+                                       aColumn.SetCellDataFunc (aCell, new Gtk.TreeCellDataFunc 
(RenderWork));
+                                       break;
+                               case 22:
+                                       aColumn.SetCellDataFunc (aCell, new Gtk.TreeCellDataFunc 
(RenderImpulse));
+                                       break;
                        }
                        
                        treeview_encoder_analyze_curves.AppendColumn (aColumn);
@@ -1355,6 +1385,29 @@ public partial class ChronoJumpWindow
                renderBoldIfNeeded(cell, curve, str);
        }
        
+       private void RenderWork (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, 
Gtk.TreeIter iter)
+       {
+               EncoderCurve curve = (EncoderCurve) model.GetValue (iter, 0);
+
+               double workValueD = curve.WorkJD;
+               int decimals = 1;
+               if(preferences.encoderWorkKcal)
+               {
+                       workValueD = curve.WorkKcalD;
+                       decimals = 3;
+               }
+
+               string str = String.Format(UtilGtk.TVNumPrint(workValueD.ToString(),6, decimals), workValueD);
+               renderBoldIfNeeded(cell, curve, str);
+       }
+
+       private void RenderImpulse (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, 
Gtk.TreeIter iter)
+       {
+               EncoderCurve curve = (EncoderCurve) model.GetValue (iter, 0);
+               string str = 
String.Format(UtilGtk.TVNumPrint(curve.Impulse,6,3),Convert.ToDouble(curve.Impulse));
+               renderBoldIfNeeded(cell, curve, str);
+       }
+
        /* end of rendering capture and analyze cols */
 
        /* start rendering neuromuscular cols */
@@ -1468,9 +1521,9 @@ public partial class ChronoJumpWindow
        private bool fixDecimalsWillWork(bool captureOrAnalyze, string [] cells)
        {
                LogB.Information(string.Format("captureOrAnalyze: {0}, cells.Length: {1}", captureOrAnalyze, 
cells.Length));
-               if(captureOrAnalyze && cells.Length < 19)               //from 0 to 18
+               if(captureOrAnalyze && cells.Length < 21)               //from 0 to 20
                        return false;
-               else if(! captureOrAnalyze && cells.Length < 21)        //from 0 to 20
+               else if(! captureOrAnalyze && cells.Length < 23)        //from 0 to 22
                        return false;
 
                return true;
@@ -1478,6 +1531,8 @@ public partial class ChronoJumpWindow
        //captureOrAnalyze is true on capture, false on analyze
        private string [] fixDecimals(bool captureOrAnalyze, string [] cells) 
        {
+               LogB.Information("fixDecimals: ");
+               LogB.Information(Util.StringArrayToString(cells, ";"));
                //start, width, height
                for(int i=5; i <= 7; i++)
                        cells[i] = 
Util.TrimDecimals(Convert.ToDouble(Util.ChangeDecimalSeparator(cells[i])),1);
@@ -1498,13 +1553,19 @@ public partial class ChronoJumpWindow
                int maxForce_maxForceT = 18;
                cells[maxForce_maxForceT] = 
Util.TrimDecimals(Convert.ToDouble(Util.ChangeDecimalSeparator(cells[maxForce_maxForceT])),1);
 
-               //cells[19] laterality
+               LogB.Information("cells19: " + cells[19]);
+               LogB.Information("cells20: " + cells[20]);
+               //work, impulse
+               cells[19] = Util.TrimDecimals(Convert.ToDouble(Util.ChangeDecimalSeparator(cells[19])),3);
+               cells[20] = Util.TrimDecimals(Convert.ToDouble(Util.ChangeDecimalSeparator(cells[20])),3);
+
+               //cells[21] laterality
 
                //capture does not return inerta
                //analyze returns inertia (can be different on "saved curves") comes as Kg*m^2, convert it to 
Kg*cm^2
                if(! captureOrAnalyze) {
-                       double inertiaInM = Convert.ToDouble(Util.ChangeDecimalSeparator(cells[20]));
-                       cells[20] = (Convert.ToInt32(inertiaInM * 10000)).ToString();
+                       double inertiaInM = Convert.ToDouble(Util.ChangeDecimalSeparator(cells[22]));
+                       cells[22] = (Convert.ToInt32(inertiaInM * 10000)).ToString();
                }
 
                return cells;


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