[chronojump] triggers done!



commit 8ba61bd71fe73ad6e42e4d8a3986663a66af7f1a
Author: Xavier de Blas <xaviblas gmail com>
Date:   Sat Apr 29 15:15:51 2017 +0200

    triggers done!

 encoder/call_capture.R |    8 +++-
 encoder/capture.R      |   21 +++++++--
 encoder/graph.R        |  103 ++++++++++++++++++++++++++++++++----------------
 encoder/util.R         |    6 ++-
 src/encoder.cs         |    7 ++-
 src/encoderCapture.cs  |   55 ++++++++++++++++++++++++-
 src/encoderRProc.cs    |   35 ++++++++++++++--
 src/gui/encoder.cs     |   61 ++++++++++++++++++++++++-----
 src/gui/preferences.cs |    6 ++-
 src/trigger.cs         |   79 ++++++++++++++++++++++++++++++++++++
 src/utilEncoder.cs     |    4 +-
 11 files changed, 322 insertions(+), 63 deletions(-)
---
diff --git a/encoder/call_capture.R b/encoder/call_capture.R
index a034402..2fc54c4 100644
--- a/encoder/call_capture.R
+++ b/encoder/call_capture.R
@@ -20,7 +20,7 @@ scriptCaptureR = options[1]
 
 #comes ".../chronojump-captured"
 #will be ".../chronojump-captured-000.txt", 001 ... 999
-filenameBegins = options[2] 
+filenameBegins = options[2]
 
 source(scriptCaptureR)
 
@@ -29,6 +29,12 @@ DebugFileName <- paste(options[5], "/chronojump-debug.txt", sep="")
 
 CROSSVALIDATESMOOTH <- FALSE
 
+if(options[33] == 1) {
+       cutByTriggers <- TRUE
+} else {
+       cutByTriggers <- FALSE
+}
+
 
 f <- file("stdin")
 open(f)
diff --git a/encoder/capture.R b/encoder/capture.R
index 5bec050..2b46719 100644
--- a/encoder/capture.R
+++ b/encoder/capture.R
@@ -15,7 +15,9 @@ write("Arriving at capture.R", stderr())
 g = 9.81
 
 #debug = FALSE
-                   
+
+cutByTriggers <- NULL
+
 filenameCompose <- function(curveNum)
 {
        if(curveNum > 99)
@@ -41,7 +43,8 @@ calcule <- function(displacement, op, curveNum, startInSet)
        if(length(displacement) < 4)
                return (curveNum)
 
-       if(abs(sum(displacement)) < op$MinHeight)
+       #minHeight is checked when ! cutByTriggers
+       if(! cutByTriggers && abs(sum(displacement)) < op$MinHeight)
                return (curveNum)
 
 
@@ -221,13 +224,21 @@ doProcess <- function(options)
                
                #cut curve by reduceCurveBySpeed ---->
 
-               reduceTemp = reduceCurveBySpeed(op$Eccon, 
+               start = NULL
+               end = NULL
+               if(cutByTriggers)
+               {
+                       start = 1
+                       end = length(displacement)
+               } else {
+                       reduceTemp = reduceCurveBySpeed(op$Eccon,
                                                        1, 0, #startT, startH
                                                        displacement, #displacement
                                                        op$SmoothingOneC #SmoothingOneC
                                                        )
-               start = reduceTemp[1]
-               end = reduceTemp[2]
+                       start = reduceTemp[1]
+                       end = reduceTemp[2]
+               }
 
                #reduceCurveBySpeed reduces the curve. Then startInSet has to change:
                print(paste("start:",start))
diff --git a/encoder/graph.R b/encoder/graph.R
index dd2d1e3..ef1252a 100644
--- a/encoder/graph.R
+++ b/encoder/graph.R
@@ -124,11 +124,32 @@ translateVector <- function(englishVector) {
        return(translatedVector)
 }
 
+#this function is called if there are two or more triggersOn
+findCurvesByTriggers <- function(displacement, triggersOn)
+{
+       position <- cumsum(displacement)
+
+       start  <- 0
+       end    <- 0
+       startH <- 0
+
+       #TODO: check problems if there's only on triggerOn
+       print(c("triggersOn:", triggersOn))
+
+       for( i in 1:(length(triggersOn) -1) )
+       {
+               start[i]  <- triggersOn[i]
+               startH[i] <- position[triggersOn[i]]
+               end[i]    <- (triggersOn[i+1] -1)
+       }
+
+       return(as.data.frame(cbind(start, end, startH)))
+}
 
 #this is equal to runEncoderCaptureCsharp()
 #but note getDisplacement hapens before this function, so no need getDisplacement here
 #also don't need byteReadedRaw, and encoderReadedRaw. encoderReaded is 'displacement' here
-findCurvesNew <- function(displacement, eccon, inertial, min_height, draw, title) 
+findCurvesNew <- function(displacement, eccon, inertial, min_height)
 {
        #---- 1) declare variables ----
        
@@ -404,24 +425,26 @@ findCurvesNew <- function(displacement, eccon, inertial, min_height, draw, title
                }
        }
 
-       if(draw) {
-               lty=1
-               col="black"
-               plot((1:length(position))/1000                  #ms -> s
-                    ,position/10,                              #mm -> cm
-                    type="l",
-                    xlim=c(1,length(position))/1000,           #ms -> s
-                    xlab="",ylab="",axes=T,
-                    lty=lty,col=col) 
-
-               title(title, cex.main=1, font.main=1)
-               mtext(paste(translateToPrint("time"),"(s)"),side=1,adj=1,line=-1)
-               mtext(paste(translateToPrint("displacement"),"(cm)"),side=2,adj=1,line=-1)
-       }
        
        return(as.data.frame(cbind(startStored,endStored,startHStored)))
 }
 
+startCurvesPlot <- function(position, title)
+{
+       lty=1
+       col="black"
+       plot((1:length(position))/1000                  #ms -> s
+            ,position/10,                              #mm -> cm
+            type="l",
+            xlim=c(1,length(position))/1000,           #ms -> s
+            xlab="",ylab="",axes=T,
+            lty=lty,col=col)
+
+       title(title, cex.main=1, font.main=1)
+       mtext(paste(translateToPrint("time"),"(s)"),side=1,adj=1,line=-1)
+       mtext(paste(translateToPrint("displacement"),"(cm)"),side=2,adj=1,line=-1)
+}
+
 kinematicRanges <- function(singleFile, displacement, curves,
                            massBody, massExtra, exercisePercentBodyWeight,
                            
encoderConfigurationName,diameter,diameterExt,anglePush,angleWeight,inertiaMomentum,gearedDown,
@@ -2556,9 +2579,16 @@ doProcess <- function(options)
                        
                position=cumsum(displacement)
 
-               curves=findCurvesNew(displacement, op$Eccon, isInertial(op$EncoderConfigurationName), 
-                                    op$MinHeight, curvesPlot, op$Title)
-               
+               if(length(op$TriggersOn) >= 2)
+                       curves <- findCurvesByTriggers(displacement, op$TriggersOn)
+               else
+                       curves <- findCurvesNew(displacement, op$Eccon,
+                                               isInertial(op$EncoderConfigurationName), op$MinHeight)
+
+               if(curvesPlot)
+                       startCurvesPlot(position, op$Title)
+
+
                if(op$Analysis == "curves" || op$Analysis == "curvesAC")
                        curvesPlot = TRUE
 
@@ -2572,22 +2602,27 @@ doProcess <- function(options)
                #what reduceCurveBySpeed is doing in inertial is adding a value at right, and this value is a 
descending value
                #and this produces a high acceleration there
                        
-               for(i in 1:n) {
-                       reduceTemp=reduceCurveBySpeed(op$Eccon,
-                                                     curves[i,1], curves[i,3], #startT, startH
-                                                     displacement[curves[i,1]:curves[i,2]], #displacement
-                                                     op$SmoothingOneC
-                                                     )
-
-                       #reduceCurveBySpeed, on inertial doesn't do a good right adjust on changing phase,
-                       #it adds a value at right, and this value is a descending value that can produce a 
high acceleration there
-                       #delete that value
-                       if( isInertial(op$EncoderConfigurationName))
-                               reduceTemp[2] = reduceTemp[2] -1
-
-                       curves[i,1] = reduceTemp[1]
-                       curves[i,2] = reduceTemp[2]
-                       curves[i,3] = reduceTemp[3]
+               for(i in 1:n)
+               {
+                       #reduceCurveBySpeed only when ! triggers
+                       if(length(op$TriggersOn) < 2)
+                       {
+                               reduceTemp = reduceCurveBySpeed(op$Eccon,
+                                                               curves[i,1], curves[i,3], #startT, startH
+                                                               displacement[curves[i,1]:curves[i,2]], 
#displacement
+                                                               op$SmoothingOneC
+                                                               )
+
+                               #reduceCurveBySpeed, on inertial doesn't do a good right adjust on changing 
phase,
+                               #it adds a value at right, and this value is a descending value that can 
produce a high acceleration there
+                               #delete that value
+                               if( isInertial(op$EncoderConfigurationName))
+                                       reduceTemp[2] = reduceTemp[2] -1
+
+                               curves[i,1] = reduceTemp[1]
+                               curves[i,2] = reduceTemp[2]
+                               curves[i,3] = reduceTemp[3]
+                       }
                        
                        myPosition = cumsum(displacement[curves[i,1]:curves[i,2]])
                        if(op$Eccon == "ec")
diff --git a/encoder/util.R b/encoder/util.R
index 0199b7e..70811ce 100644
--- a/encoder/util.R
+++ b/encoder/util.R
@@ -79,7 +79,11 @@ assignOptions <- function(options) {
                    Title               = options[27],
                    OperatingSystem     = options[28],  #if this changes, change it also at call_graph.R
                    Debug               = options[31],
-                   CrossValidate       = options[32]
+                   CrossValidate       = options[32],
+                   TriggersOn          = as.numeric(unlist(strsplit(options[33], "\\;")))
+                   #TriggerOn on capture is +1/-1 to indicate use or not.
+                   #On analyze is first ms where trigger is pressed at each repetition, or -1 if they are 
not going to be used
+
                    #Unassigned here:
                    #   englishWords [29]
                    #   translatedWords [30]
diff --git a/src/encoder.cs b/src/encoder.cs
index db143a3..9a15542 100644
--- a/src/encoder.cs
+++ b/src/encoder.cs
@@ -159,6 +159,7 @@ public class EncoderGraphROptions
        public string translatedWords;
        public bool debug;
        public bool crossValidate;
+       private string triggerList;
        
        public EncoderGraphROptions(
                        string inputData, string outputGraph, string outputData1, 
@@ -166,7 +167,7 @@ public class EncoderGraphROptions
                        EncoderParams ep,
                        string title, string operatingSystem,
                        string englishWords, string translatedWords,
-                       bool debug, bool crossValidate)
+                       bool debug, bool crossValidate, string triggerList)
        {
                this.inputData = inputData;
                this.outputGraph = outputGraph;
@@ -180,6 +181,7 @@ public class EncoderGraphROptions
                this.translatedWords = translatedWords;
                this.debug = debug;
                this.crossValidate = crossValidate;
+               this.triggerList = triggerList;
        }
 
        public override string ToString() {
@@ -195,7 +197,8 @@ public class EncoderGraphROptions
                        "#englishWords\n" +     englishWords + "\n" +
                        "#translatedWords\n" +  translatedWords + "\n" +
                        "#debug\n" +            Util.BoolToRBool(debug) + "\n" +
-                       "#crossValidate\n" +    Util.BoolToRBool(crossValidate) + "\n";
+                       "#crossValidate\n" +    Util.BoolToRBool(crossValidate) + "\n" +
+                       "#triggerList\n" +      triggerList + "\n";
        }
        
 
diff --git a/src/encoderCapture.cs b/src/encoderCapture.cs
index 84740e5..579169e 100644
--- a/src/encoderCapture.cs
+++ b/src/encoderCapture.cs
@@ -58,6 +58,8 @@ public abstract class EncoderCapture
 
        //private BoolMsList boolMsList;
        private TriggerList triggerList;
+
+       private int lastTriggerOn;
        
        /*
         * sum: sum ob byteReaded, it's the vertical position
@@ -215,7 +217,7 @@ public abstract class EncoderCapture
                inertialCalibrated = false;
        }
 
-       public bool Capture(string outputData1, EncoderRProcCapture encoderRProcCapture, bool compujump)
+       public bool Capture(string outputData1, EncoderRProcCapture encoderRProcCapture, bool compujump, bool 
cutByTriggers)
        {
                /*
                 * removed at 1.7.0
@@ -226,6 +228,7 @@ public abstract class EncoderCapture
                }
                */
 
+               lastTriggerOn = 0;
                inertialCalibratedFirstCross0Pos = 0;
 
                if(capturingInertialBG)
@@ -238,6 +241,7 @@ public abstract class EncoderCapture
                }
 
                do {
+                       //1 read data
                        try {
                                byteReaded = readByte();
                        } catch {
@@ -249,17 +253,54 @@ public abstract class EncoderCapture
                                break;
                        }
 
+                       //2 check if readed data is a trigger
                        if(byteReaded == TRIGGER_ON)
                        {
-                               triggerList.Add(new Trigger(Trigger.Modes.ENCODER, i, true));
+                               Trigger trigger = new Trigger(Trigger.Modes.ENCODER, i, true);
+                               if(triggerList.IsSpurious(trigger))
+                               {
+                                       triggerList.RemoveLastOff();
+                                       continue;
+                               }
+
+                               if(cutByTriggers)
+                               {
+                                       ecc = new EncoderCaptureCurve(lastTriggerOn, i);
+                                       lastTriggerOn = i;
+
+                                       double [] curve = new double[ecc.endFrame - ecc.startFrame];
+                                       //int mySum = 0;
+                                       for(int k=0, j=ecc.startFrame; j < ecc.endFrame ; j ++) {
+                                               curve[k] = encoderReaded[j];
+                                               k ++;
+                                               //mySum += encoderReaded[j];
+                                       }
+                                       //ecc.up = (mySum >= 0);
+                                       ecc.up = true; //make all concentric for the swimming application
+                                       LogB.Debug("curve stuff" + ecc.startFrame + ":" + ecc.endFrame + ":" 
+ encoderReaded.Count);
+
+                                       bool success = encoderRProcCapture.SendCurve(
+                                                       ecc.startFrame,
+                                                       UtilEncoder.CompressData(curve, 25)     //compressed
+                                                       );
+                                       if(! success)
+                                               cancel = true;
+
+                                       Ecca.curvesAccepted ++;
+                                       Ecca.ecc.Add(ecc);
+                                       LogB.Information(ecc.ToString());
+                               }
+                               triggerList.Add(trigger);
                                continue;
                        }
                        else if(byteReaded == TRIGGER_OFF)
                        {
-                               triggerList.Add(new Trigger(Trigger.Modes.ENCODER, i, false));
+                               Trigger trigger  = new Trigger(Trigger.Modes.ENCODER, i, false);
+                               triggerList.Add(trigger);
                                continue;
                        }
 
+                       //3 if is not trigger: convertByte
                        byteReaded = convertByte(byteReaded);
                        //LogB.Information(" byte: " + byteReaded);
 
@@ -396,6 +437,10 @@ public abstract class EncoderCapture
                                if(inertialCalibrated && inertialCalibratedFirstCross0Pos == 0)
                                        sendCurveMaybe = false;
 
+                               //if cutByTriggers, triggers send the curve at the beginning of this method
+                               if(cutByTriggers)
+                                       sendCurveMaybe = false;
+
                                if(sendCurveMaybe)
                                {
                                        //int startFrame = previousFrameChange - directionChangeCount;  
//startFrame
@@ -758,6 +803,10 @@ public abstract class EncoderCapture
                return false;
        }
 
+       public string Eccon {
+               get { return eccon; }
+       }
+
        public void Cancel() {
                cancel = true;
        }
diff --git a/src/encoderRProc.cs b/src/encoderRProc.cs
index 2f15f76..08f7061 100644
--- a/src/encoderRProc.cs
+++ b/src/encoderRProc.cs
@@ -37,6 +37,7 @@ public abstract class EncoderRProc
        protected string optionsFile;   
        protected EncoderStruct es;
 
+
        public bool StartOrContinue(EncoderStruct es)
        {
                status = Status.RUNNING;
@@ -67,6 +68,11 @@ public abstract class EncoderRProc
        {
        }
 
+       protected virtual string printTriggers()
+       {
+               return TriggerList.TriggersNotFoundString;
+       }
+
        protected virtual bool startProcess() {
                return true;
        }
@@ -137,7 +143,10 @@ public abstract class EncoderRProc
 
 public class EncoderRProcCapture : EncoderRProc 
 {
-       public EncoderRProcCapture() {
+       public bool CutByTriggers;
+
+       public EncoderRProcCapture()
+       {
        }
        
        protected override bool startProcess() 
@@ -246,7 +255,8 @@ public class EncoderRProcCapture : EncoderRProc
                                false,  //neuromuscularProfile
                                false,  //translate (graphs)
                                Debug,
-                               false   //crossValidate (unactive on capture at the moment)
+                               false,  //crossValidate (unactive on capture at the moment)
+                               printTriggers()
                                ).ToString();
 
                TextWriter writer = File.CreateText(optionsFile);
@@ -256,6 +266,15 @@ public class EncoderRProcCapture : EncoderRProc
                ((IDisposable)writer).Dispose();
        }
 
+       protected override string printTriggers()
+       {
+               //just use triggeres tp cut sets into repetitions, or not.
+               //Cut is done in C# but this will change minHeight behaviour and reduceCurveBySpeed
+               if(CutByTriggers)
+                       return "1";
+               else
+                       return TriggerList.TriggersNotFoundString;
+       }
 
 }
 
@@ -264,6 +283,7 @@ public class EncoderRProcAnalyze : EncoderRProc
        private string title;
        private bool neuromuscularProfileDo;
        private bool translate;
+       private TriggerList triggerList;
 
        /*
         * to avoid problems on some windows. R exports csv to Util.GetEncoderExportTempFileName()
@@ -276,10 +296,11 @@ public class EncoderRProcAnalyze : EncoderRProc
        public EncoderRProcAnalyze() {
        }
 
-       public void SendData(string title, bool neuromuscularProfileDo, bool translate) {
+       public void SendData(string title, bool neuromuscularProfileDo, bool translate, TriggerList 
triggerList) {
                this.title = title;
                this.neuromuscularProfileDo = neuromuscularProfileDo;
                this.translate = translate;
+               this.triggerList = triggerList;
                
                CancelRScript = false;
        }
@@ -486,7 +507,8 @@ public class EncoderRProcAnalyze : EncoderRProc
                                neuromuscularProfileDo,
                                translate,
                                Debug,
-                               CrossValidate
+                               CrossValidate,
+                               printTriggers()
                                ).ToString();
 
                TextWriter writer = File.CreateText(optionsFile);
@@ -495,6 +517,11 @@ public class EncoderRProcAnalyze : EncoderRProc
                writer.Close();
                ((IDisposable)writer).Dispose();
        }
+
+       protected override string printTriggers()
+       {
+               return triggerList.ToRCurvesString();
+       }
                
        private void deleteFile(string filename)
        {
diff --git a/src/gui/encoder.cs b/src/gui/encoder.cs
index 32399b6..d2d36f6 100644
--- a/src/gui/encoder.cs
+++ b/src/gui/encoder.cs
@@ -1101,6 +1101,18 @@ public partial class ChronoJumpWindow
 
        void on_button_encoder_recalculate_clicked (object o, EventArgs args)
        {
+               if(triggerList != null && triggerList.Count() > 0 && findEccon(false) != "c")
+               {
+                       ConfirmWindow confirmWin = ConfirmWindow.Show(
+                                       Catalog.GetString("Recalculate this set will remove existing 
triggers."),
+                                       Catalog.GetString("Are you sure!"), "");
+                       confirmWin.Button_accept.Clicked += new 
EventHandler(on_button_encoder_recalculate_clicked_do);
+               }
+               else
+                       on_button_encoder_recalculate_clicked_do (o, args);
+       }
+       void on_button_encoder_recalculate_clicked_do (object o, EventArgs args)
+       {
                //record this encoderConfiguration to SQL for next Chronojump open
                SqliteEncoderConfiguration.UpdateActive(false, currentEncoderGI, encoderConfigurationCurrent);
                encoderCalculeCurves(encoderActions.CURVES);
@@ -1221,6 +1233,7 @@ public partial class ChronoJumpWindow
        //this is called by non gtk thread. Don't do gtk stuff here
        //I suppose reading gtk is ok, changing will be the problem
        //called on calculatecurves, recalculate and load
+       //analysisSent can be "curves" or "curvesAC"
        private void encoderDoCurvesGraphR(string analysisSent)
        {
                LogB.Debug("encoderDoCurvesGraphR() start");
@@ -1264,10 +1277,20 @@ public partial class ChronoJumpWindow
                else
                        title += "-(" + Util.ConvertToPoint(findMass(Constants.MassType.DISPLACED)) + "Kg)";
 
+               //triggers stuff
+               if(analysisSent == "curvesAC")
+                       triggerList = eCapture.GetTriggers();
+
+               //triggers only on concentric
+               if(triggerList == null || findEccon(false) != "c")
+                       triggerList = new TriggerList();
+
+               //send data to encoderRProcAnalyze
                encoderRProcAnalyze.SendData(
                                title,
                                false,  //do not use neuromuscularProfile script
-                               preferences.RGraphsTranslate
+                               preferences.RGraphsTranslate,
+                               triggerList
                                ); 
                bool result = encoderRProcAnalyze.StartOrContinue(es);
                                
@@ -1605,7 +1628,8 @@ public partial class ChronoJumpWindow
                genericWin.ShowEditRow(false);
        }
        
-       protected void on_encoder_load_signal_row_delete_pre (object o, EventArgs args) {
+       protected void on_encoder_load_signal_row_delete_pre (object o, EventArgs args)
+       {
                if(preferences.askDeletion) {
                        ConfirmWindow confirmWin = ConfirmWindow.Show(Catalog.GetString(
                                                "Are you sure you want to delete this set?"), 
Catalog.GetString("Saved repetitions related to this set will also be deleted."), "");
@@ -1613,8 +1637,8 @@ public partial class ChronoJumpWindow
                } else
                        on_encoder_load_signal_row_delete (o, args);
        }
-       
-       protected void on_encoder_load_signal_row_delete (object o, EventArgs args) {
+       protected void on_encoder_load_signal_row_delete (object o, EventArgs args)
+       {
                LogB.Information("row delete at load signal");
 
                int signalID = genericWin.TreeviewSelectedUniqueID;
@@ -1763,7 +1787,8 @@ public partial class ChronoJumpWindow
                                Util.ChangeSpaceAndMinusForUnderscore(lastEncoderSQLSignal.exerciseName) + 
                                        "-(" + displacedMass + "Kg)",
                                false,                  //do not use neuromuscularProfile script
-                               preferences.RGraphsTranslate
+                               preferences.RGraphsTranslate,
+                               new TriggerList()
                                );
                encoderRProcAnalyze.StartOrContinue(encoderStruct);
 
@@ -2021,7 +2046,6 @@ public partial class ChronoJumpWindow
                                UtilGtk.ComboMakeActive(combo_encoder_analyze_curve_num_combo, 
activeCurvesList[0].ToString());
        }
 
-
        string encoderSaveSignalOrCurve (bool dbconOpened, string mode, int selectedID) 
        {
                //mode is different than type. 
@@ -2331,10 +2355,19 @@ public partial class ChronoJumpWindow
        //I suppose reading gtk is ok, changing will be the problem
        private void encoderDoCaptureCsharp () 
        {
+               bool cutByTriggers = false;
+               //triggers only work on gravitatory, concentric
+               if(preferences.encoderCaptureCutByTriggers &&
+                               currentEncoderGI == Constants.EncoderGI.GRAVITATORY && eCapture.Eccon == "c")
+                       cutByTriggers = true;
+
+               encoderRProcCapture.CutByTriggers = cutByTriggers;
+
                bool capturedOk = eCapture.Capture(
                                UtilEncoder.GetEncoderDataTempFileName(),
                                encoderRProcCapture,
-                               configChronojump.Compujump
+                               configChronojump.Compujump,
+                               cutByTriggers
                                );
 
                //wait to ensure capture thread has ended
@@ -2370,10 +2403,13 @@ public partial class ChronoJumpWindow
        //I suppose reading gtk is ok, changing will be the problem
        private void encoderDoCaptureCsharpIM () 
        {
+               encoderRProcCapture.CutByTriggers = false; //do not cutByTriggers on inertial, yet.
+
                bool capturedOk = eCapture.Capture(
                                UtilEncoder.GetEncoderDataTempFileName(),
                                encoderRProcCapture,
-                               false
+                               false,  //compujump
+                               false   //cutByTriggers
                                );
 
                //wait to ensure capture thread has ended
@@ -2745,10 +2781,16 @@ public partial class ChronoJumpWindow
                                titleStr += "-" + 
Util.ChangeSpaceAndMinusForUnderscore(UtilGtk.ComboGetActive(combo_encoder_exercise_capture));
                }
 
+               //triggers only on concentric
+               if(triggerList == null || findEccon(false) != "c")
+                       triggerList = new TriggerList();
+
                encoderRProcAnalyze.SendData(
                                titleStr, 
                                encoderAnalysis == "neuromuscularProfile",
-                               preferences.RGraphsTranslate);
+                               preferences.RGraphsTranslate,
+                               triggerList
+                               );
 
                encoderRProcAnalyze.StartOrContinue(encoderStruct);
        }
@@ -5902,7 +5944,6 @@ public partial class ChronoJumpWindow
                                        if(action == encoderActions.CURVES_AC)
                                        {
                                                
eCapture.SaveTriggers(Convert.ToInt32(encoderSignalUniqueID)); //dbcon is closed
-                                               triggerList = eCapture.GetTriggers();
                                                showTriggersAndTab();
                                        }
 
diff --git a/src/gui/preferences.cs b/src/gui/preferences.cs
index 7779ebc..5b3542f 100644
--- a/src/gui/preferences.cs
+++ b/src/gui/preferences.cs
@@ -488,7 +488,11 @@ public class PreferencesWindow
                new DialogMessage(Constants.MessageTypes.WARNING,
                                "If active, repetitions will be cut from set using triggers." + "\n" +
                                "Triggers will be produced by a button connected to the Chronopic." + "\n\n" +
-                               "This will be only used on gravitatory (not on inertial).");
+                               "This will be only used on gravitatory mode, concentric contraction.");
+               /*
+                * not on ecc-con because we cannot guaranteee that there will be an ecc and con phase,
+                * and then R findECPhases() will fail
+                */
        }
        
        private void createComboEncoderCaptureMainVariable(string v) {
diff --git a/src/trigger.cs b/src/trigger.cs
index 0d9f4f4..1f5b848 100644
--- a/src/trigger.cs
+++ b/src/trigger.cs
@@ -91,6 +91,14 @@ public class Trigger
                get { return uniqueID; }
        }
 
+       public int Ms {
+               get { return ms; }
+       }
+
+       public bool InOut {
+               get { return inOut; }
+       }
+
        public int ModeID {
                set { modeID = value; }
        }
@@ -98,6 +106,7 @@ public class Trigger
 
 public class TriggerList
 {
+       public const string TriggersNotFoundString = "-1";
        private List<Trigger> l;
 
        //constructors
@@ -144,6 +153,23 @@ public class TriggerList
                return s;
        }
 
+       public string ToRCurvesString()
+       {
+               if(l.Count == 0)
+                       return TriggersNotFoundString;
+
+               string s = "";
+               string sep = "";
+               foreach(Trigger trigger in l)
+               {
+                       if(trigger.InOut) {
+                               s += sep + trigger.Ms.ToString();
+                               sep = ";";
+                       }
+               }
+               return s;
+       }
+
        public int Count()
        {
                return l.Count;
@@ -162,6 +188,59 @@ public class TriggerList
                LogB.Debug("runEncoderCaptureCsharp SQL inserting triggers");
                SqliteTrigger.InsertList(false, l);
        }
+
+
+       /*
+        * start of spurious management
+        */
+       private int countOn()
+       {
+               int countOn = 0;
+               foreach(Trigger t in l)
+                       if(t.InOut)
+                               countOn ++;
+
+               return countOn;
+       }
+
+       //if inOut == true will return last "in"
+       private Trigger last(bool inOut)
+       {
+               int i = 0;
+               int lastPos = 0;
+               foreach(Trigger t in l)
+               {
+                       if(t.InOut == inOut)
+                               lastPos = i;
+                       i ++;
+               }
+
+               return l[lastPos];
+       }
+
+       //this newTrigger is an On trigger, compare with last On
+       public bool IsSpurious(Trigger newTrigger)
+       {
+               //cannot be spurious if is the first On
+               if(countOn() == 0)
+                       return false;
+
+               //last(true) will check last On trigger
+               if( (newTrigger.Ms - last(true).Ms) < 50 )
+                       return true;
+
+               return false;
+       }
+
+       public void RemoveLastOff()
+       {
+               l.Remove(last(false));
+       }
+       /*
+        * end of spurious management
+        */
+
+
        /*
        public void Write()
        {
diff --git a/src/utilEncoder.cs b/src/utilEncoder.cs
index bdf1494..c08c92a 100644
--- a/src/utilEncoder.cs
+++ b/src/utilEncoder.cs
@@ -328,7 +328,7 @@ public class UtilEncoder
                return operatingSystem;
        }
 
-       public static EncoderGraphROptions PrepareEncoderGraphOptions(string title, EncoderStruct es, bool 
neuromuscularProfileDo, bool translate, bool debug, bool crossValidate)
+       public static EncoderGraphROptions PrepareEncoderGraphOptions(string title, EncoderStruct es, bool 
neuromuscularProfileDo, bool translate, bool debug, bool crossValidate, string triggerStr)
        {
                string operatingSystem = OperatingSystemForRGraphs();
                        
@@ -383,7 +383,7 @@ public class UtilEncoder
                                title, operatingSystem,
                                Util.StringArrayToString(Constants.EncoderEnglishWords,";"),
                                Util.StringArrayToString(encoderTranslatedWordsOK,";"),
-                               debug, crossValidate
+                               debug, crossValidate, triggerStr
                                );
        }
 


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