[chronojump] Force sensor graph working



commit 2b6daf8a2bfef9f265e7fa18591d31480fffcfe2
Author: Xavier de Blas <xaviblas gmail com>
Date:   Tue Apr 25 00:19:03 2017 +0200

    Force sensor graph working

 glade/app1.glade                  |   60 +++++++++++++++++++-
 r-scripts/maximumIsometricForce.R |   59 ++++++++++---------
 src/forceSensor.cs                |  112 +++++++++++++++++++++++++++++++++++++
 src/gui/chronojump.cs             |    6 ++
 src/gui/forceSensor.cs            |   58 ++++++++++++++++---
 src/utilEncoder.cs                |    2 +-
 6 files changed, 256 insertions(+), 41 deletions(-)
---
diff --git a/glade/app1.glade b/glade/app1.glade
index 47994b2..49b1529 100644
--- a/glade/app1.glade
+++ b/glade/app1.glade
@@ -1224,6 +1224,12 @@
                                                             <placeholder/>
                                                             </child>
                                                             <child>
+                                                            <placeholder/>
+                                                            </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
+                                                            <child>
                                                             <widget class="GtkLabel" 
id="label_start_selector_jumps">
                                                             <property name="visible">True</property>
                                                             <property name="can_focus">False</property>
@@ -4085,6 +4091,21 @@ EncoderInertialCapture</property>
                                                             </packing>
                                                             </child>
                                                             <child>
+                                                            <widget class="GtkButton" 
id="button_force_sensor_graph">
+                                                            <property name="label" 
translatable="yes">Graph</property>
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">True</property>
+                                                            <property name="receives_default">True</property>
+                                                            <signal name="clicked" 
handler="on_button_force_sensor_graph_clicked" swapped="no"/>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="padding">20</property>
+                                                            <property name="position">3</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
                                                             <widget class="GtkButton" 
id="button_force_sensor_data_folder">
                                                             <property name="label" translatable="yes">Open 
data folder</property>
                                                             <property name="visible">True</property>
@@ -4096,7 +4117,7 @@ EncoderInertialCapture</property>
                                                             <property name="expand">False</property>
                                                             <property name="fill">False</property>
                                                             <property name="padding">20</property>
-                                                            <property name="position">3</property>
+                                                            <property name="position">4</property>
                                                             </packing>
                                                             </child>
                                                             </widget>
@@ -4416,7 +4437,7 @@ EncoderInertialCapture</property>
                                                         <property name="can_focus">False</property>
                                                         <property name="top_padding">8</property>
                                                         <child>
-                                                          <widget class="GtkHBox" id="hbox75">
+                                                          <widget class="GtkHBox" 
id="hbox_chronopics_and_threshold">
                                                             <property name="visible">True</property>
                                                             <property name="can_focus">False</property>
                                                             <property name="spacing">8</property>
@@ -10411,9 +10432,36 @@ after time</property>
                                                             </child>
                                                             </widget>
                                                             <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">1</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
+                                                            <widget class="GtkScrolledWindow" 
id="scrolledwindow5">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">True</property>
+                                                            <property 
name="hscrollbar_policy">automatic</property>
+                                                            <property 
name="vscrollbar_policy">automatic</property>
+                                                            <child>
+                                                            <widget class="GtkViewport" 
id="viewport_force_sensor_graph">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="shadow_type">none</property>
+                                                            <child>
+                                                            <widget class="GtkImage" 
id="image_force_sensor_graph">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property 
name="stock">gtk-missing-image</property>
+                                                            </widget>
+                                                            </child>
+                                                            </widget>
+                                                            </child>
+                                                            </widget>
+                                                            <packing>
                                                             <property name="expand">True</property>
                                                             <property name="fill">True</property>
-                                                            <property name="position">1</property>
+                                                            <property name="position">2</property>
                                                             </packing>
                                                             </child>
                                                             </widget>
@@ -20242,6 +20290,12 @@ then click this button.</property>
                                                             <child>
                                                             <placeholder/>
                                                             </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
                                                             </widget>
                                                             <packing>
                                                             <property name="expand">False</property>
diff --git a/r-scripts/maximumIsometricForce.R b/r-scripts/maximumIsometricForce.R
index 45794c9..86bd313 100644
--- a/r-scripts/maximumIsometricForce.R
+++ b/r-scripts/maximumIsometricForce.R
@@ -37,22 +37,23 @@ endGraph <- function()
 
 assignOptions <- function(options)
 {
-        drawRfdOptions = rep(NA, length(options) - 10)
-        for(n in 11:length(options))
+        drawRfdOptions = rep(NA, length(options) - 11)
+        for(n in 12:length(options))
         {
-                drawRfdOptions[n-10]      = options[n] 
+                drawRfdOptions[n-11]      = options[n]
         }
         return(list(
-                os             = options[1],
-                graphWidth     = as.numeric(options[2]),
-                graphHeight    = as.numeric(options[3]),
-                averageLength = as.numeric(options[4]),
-                percentChange = as.numeric(options[5]),
-                vlineT0        = as.numeric(options[6]),
-                vline50fmax.raw        = as.numeric(options[7]),
-                vline50fmax.fitted     = as.numeric(options[8]),
-                hline50fmax.raw        = as.numeric(options[9]),
-                hline50fmax.fitted     = as.numeric(options[10]),
+                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
         ))
 }
@@ -91,7 +92,7 @@ getForceModel <- function(time, force, startTime, # startTime is the instant whe
 
 getDynamicsFromLoadCellFile <- function(inputFile, averageLength = 0.1, percentChange = 5)
 {
-        originalTest = read.csv(inputFile, header = F, dec = ".", sep = ";", skip = 2)
+        originalTest = read.csv(inputFile, header = F, dec = op$decimalChar, sep = ";", skip = 2)
         colnames(originalTest) <- c("time", "force")
         originalTest$time = as.numeric(originalTest$time)
         
@@ -263,26 +264,28 @@ drawDynamicsFromLoadCell <- function(
                 
                 RFD = NULL
                 sample2 = NA
+                pointForce1 = NA
                 pointForce2 = NA
+                color = ""
                 
-                if(options$rfdFunction == "fitted")
+                if(options$rfdFunction == "FITTED")
                 {
                         color = "blue"
-                } else if(options$rfdFunction == "raw")
+                } else if(options$rfdFunction == "RAW")
                 {
                         color = "black"
                 }
                 
-                if(options$type == "instant") # TODO: || percent ...(all except AVG)
+                if(options$type == "INSTANTANEOUS") # TODO: || percent ...(all except AVG)
                 {
-                        if (options$rfdFunction == "fitted")
+                        if (options$rfdFunction == "FITTED")
                         {
                                 #Slope of the line
                                 RFD = dynamics$fmax.fitted * dynamics$k.fitted * exp(-dynamics$k.fitted * 
options$start) 
                                 #Y coordinate of a point of the line
                                 pointForce1 = dynamics$fmax.fitted*(1 - exp(-dynamics$k.fitted * 
options$start)) + dynamics$initf
                                 
-                        } else if(options$rfdFunction == "raw")
+                        } else if(options$rfdFunction == "RAW")
                         {
                                 color = "black"
                                 sample1 =  which.min(abs(dynamics$time - dynamics$startTime - options$start))
@@ -293,15 +296,15 @@ drawDynamicsFromLoadCell <- function(
                                 #Y coordinate of a point of the line
                                 pointForce1 = dynamics$f.raw[sample1]
                         }
-                } else if(options$type == "avg")
+                } else if(options$type == "AVERAGE")
                 {
-                        if (options$rfdFunction == "fitted")
+                        if (options$rfdFunction == "FITTED")
                         {
                                 #Slope of the line
                                 RFD = dynamics$fmax.fitted*(exp( -dynamics$k.fitted * options$start) - exp( 
-dynamics$k.fitted * options$end)) / (options$end - options$start)
                                 #Y coordinate of a point of the line
                                 pointForce1 = dynamics$fmax.fitted*(1 - exp( -dynamics$k.fitted * 
options$start)) + dynamics$initf
-                        } else if(options$rfdFunction == "raw")
+                        } else if(options$rfdFunction == "RAW")
                         {
                                 sample1 =  which.min(abs(dynamics$time - dynamics$startTime - options$start))
                                 sample2 = which.min(abs(dynamics$time - dynamics$startTime - options$end))
@@ -313,10 +316,10 @@ drawDynamicsFromLoadCell <- function(
                                 pointForce1 = dynamics$f.raw[sample1]
                         }
                         
-                } else if(options$type == "%fmax")
+                } else if(options$type == "PERCENT_F_MAX")
                 {
                         
-                        if (options$rfdFunction == "fitted")
+                        if (options$rfdFunction == "FITTED")
                         {
                                 #Force that is the % of the raw fmax
                                 fpfmax = dynamics$fmax.raw*options$start/100
@@ -330,7 +333,7 @@ drawDynamicsFromLoadCell <- function(
                                 #Y coordinate of a point of the line
                                 pointForce1 = dynamics$fmax.fitted*(1 - exp(-dynamics$k.fitted * 
options$start)) + dynamics$initf
                                 
-                        } else if(options$rfdFunction == "raw")
+                        } else if(options$rfdFunction == "RAW")
                         {
                                 #Calculing at which sample force is equal to the percent of fmax specified 
in options$start
                                 sample1 = which.min(abs(dynamics$f.raw - 
dynamics$fmax.raw*options$start/100))
@@ -344,13 +347,13 @@ drawDynamicsFromLoadCell <- function(
                                 #Y coordinate of a point of the line
                                 pointForce1 = dynamics$f.raw[sample1]
                         }
-                } else if(options$type == "rfdmax")
+                } else if(options$type == "RFD_MAX")
                 {
-                        if (options$rfdFunction == "fitted")
+                        if (options$rfdFunction == "FITTED")
                         {
                                 #max is always in the initial point.
                                 
-                        } else if(options$rfdFunction == "raw")
+                        } else if(options$rfdFunction == "RAW")
                         {
                                 #Calculing the sample at which the rfd is max
                                 sample1 = which.max(dynamics$rfd)
diff --git a/src/forceSensor.cs b/src/forceSensor.cs
index a5b7b64..8d404be 100644
--- a/src/forceSensor.cs
+++ b/src/forceSensor.cs
@@ -140,6 +140,11 @@ public class ForceSensorRFD
                        num2.ToString();
        }
 
+       public string ToR()
+       {
+               return function.ToString() + ";" + type.ToString() + ";" + num1.ToString() + ";" + 
num2.ToString();
+       }
+
        public static string Function_RAW_name
        {
                get { return function_RAW_name; }
@@ -167,6 +172,113 @@ public class ForceSensorRFD
        }
 }
 
+public class ForceSensorGraph
+{
+       List<ForceSensorRFD> rfdList;
+       double averageLength;
+       double percentChange;
+       bool vlineT0;
+       bool vline50fmax_raw;
+       bool vline50fmax_fitted;
+       bool hline50fmax_raw;
+       bool hline50fmax_fitted;
+
+       public ForceSensorGraph(List<ForceSensorRFD> rfdList)
+       {
+               this.rfdList = rfdList;
+
+               averageLength = 0.1;
+               percentChange = 5;
+               vlineT0 = false;
+               vline50fmax_raw = false;
+               vline50fmax_fitted = false;
+               hline50fmax_raw = false;
+               hline50fmax_fitted = false;
+       }
+
+       public bool CallR(int graphWidth, int graphHeight)
+       {
+               string executable = UtilEncoder.RProcessBinURL();
+               List<string> parameters = new List<string>();
+
+               //A) mifcript
+               string mifScript = UtilEncoder.GetmifScript();
+               if(UtilAll.IsWindows())
+                       mifScript = mifScript.Replace("\\","/");
+
+               parameters.Insert(0, "\"" + mifScript + "\"");
+
+               //B) tempPath
+               string tempPath = Path.GetTempPath();
+               if(UtilAll.IsWindows())
+                       tempPath = tempPath.Replace("\\","/");
+
+               parameters.Insert(1, "\"" + tempPath + "\"");
+
+               //C) writeOptions
+               writeOptionsFile(graphWidth, graphHeight);
+
+               LogB.Information("\nCalling mif R file ----->");
+
+               //D) call process
+               //ExecuteProcess.run (executable, parameters);
+               ExecuteProcess.Result execute_result = ExecuteProcess.run (executable, parameters);
+               //LogB.Information("Result = " + execute_result.stdout);
+
+               LogB.Information("\n<------ Done calling mif R file.");
+               return execute_result.success;
+       }
+
+       private void writeOptionsFile(int graphWidth, int graphHeight)
+       {
+               string scriptsPath = UtilEncoder.GetSprintPath();
+               if(UtilAll.IsWindows())
+                       scriptsPath = scriptsPath.Replace("\\","/");
+
+               System.Globalization.NumberFormatInfo localeInfo = new 
System.Globalization.NumberFormatInfo();
+               localeInfo = System.Globalization.NumberFormatInfo.CurrentInfo;
+
+               string scriptOptions =
+                       "#os\n" +                       UtilEncoder.OperatingSystemForRGraphs() + "\n" +
+                       "#decimalChar\n" +              localeInfo.NumberDecimalSeparator + "\n" +
+                       "#graphWidth\n" +               graphWidth.ToString() + "\n" +
+                       "#graphHeight\n" +              graphHeight.ToString() + "\n" +
+                       "#averageLength\n" +            Util.ConvertToPoint(averageLength) + "\n" +
+                       "#percentChange\n" +            Util.ConvertToPoint(percentChange) + "\n" +
+                       "#vlineT0\n" +                  Util.BoolToRBool(vlineT0) + "\n" +
+                       "#vline50fmax.raw\n" +          Util.BoolToRBool(vline50fmax_raw) + "\n" +
+                       "#vline50fmax.fitted\n" +       Util.BoolToRBool(vline50fmax_fitted) + "\n" +
+                       "#hline50fmax.raw\n" +          Util.BoolToRBool(hline50fmax_raw) + "\n" +
+                       "#hline50fmax.fitted\n" +       Util.BoolToRBool(hline50fmax_fitted) + "\n" +
+                       "#RFDs";
+
+               foreach(ForceSensorRFD rfd in rfdList)
+                       if(rfd.active)
+                               scriptOptions += "\n" + rfd.ToR();
+
+               TextWriter writer = File.CreateText(Path.GetTempPath() + "Roptions.txt");
+               writer.Write(scriptOptions);
+               writer.Flush();
+               writer.Close();
+               ((IDisposable)writer).Dispose();
+       }
+
+       public static string GetDataDir(int sessionID)
+       {
+               System.IO.DirectoryInfo folderSession =
+                       new System.IO.DirectoryInfo(Util.GetForceSensorSessionDir(sessionID));
+               System.IO.DirectoryInfo folderGeneric =
+                       new System.IO.DirectoryInfo(Util.GetForceSensorDir());
+
+               if(folderSession.Exists)
+                       return Util.GetForceSensorSessionDir(sessionID);
+               else if(folderGeneric.Exists)
+                       return Util.GetForceSensorDir();
+               else
+                       return "";
+       }
+}
+
 /*
 public class ForceSensor
 {
diff --git a/src/gui/chronojump.cs b/src/gui/chronojump.cs
index 742252e..a896981 100644
--- a/src/gui/chronojump.cs
+++ b/src/gui/chronojump.cs
@@ -270,6 +270,7 @@ public partial class ChronoJumpWindow
 
        [Widget] Gtk.Box vbox_execute_test;
        [Widget] Gtk.Button button_execute_test;
+       [Widget] Gtk.HBox hbox_chronopics_and_threshold;
        [Widget] Gtk.Viewport viewport_chronopics;
        //[Widget] Gtk.Label label_chronopic_encoder;
        //[Widget] Gtk.Image image_chronopic_encoder_no;
@@ -780,6 +781,7 @@ public partial class ChronoJumpWindow
                notebooks_change(Constants.Menuitem_modes.FORCESENSOR);
                //on_extra_window_force_sensor_test_changed(obj, args);
                hbox_results_legend.Visible = false;
+               notebook_capture_graph_table.CurrentPage = 1; //"Show table"
        }
 
        public void on_radio_menuitem_mode_rt_toggled (object obj, EventArgs args)
@@ -2808,6 +2810,7 @@ public partial class ChronoJumpWindow
 
                hbox_other.Visible = false;
                vbox_last_test_buttons.Sensitive = false;
+               hbox_chronopics_and_threshold.Visible = true;
 
                if(m == Constants.Menuitem_modes.JUMPSSIMPLE || m == Constants.Menuitem_modes.JUMPSREACTIVE)
                {
@@ -2997,6 +3000,9 @@ public partial class ChronoJumpWindow
                        //notebook_capture_analyze.ShowTabs = false; //only capture tab is shown (only valid 
for "OTHER" tests)
                        hbox_contacts_sup_capture_analyze_two_buttons.Visible = false;
                        //notebook_capture_analyze.GetNthPage(2).Hide(); //hide jumpsProfile on other tests
+                       hbox_chronopics_and_threshold.Visible = false;
+                       hbox_results_legend.Visible = false;
+                       notebook_capture_graph_table.CurrentPage = 1; //"Show table"
                }
                else if(m == Constants.Menuitem_modes.RT)
                {
diff --git a/src/gui/forceSensor.cs b/src/gui/forceSensor.cs
index 510896c..0398e72 100644
--- a/src/gui/forceSensor.cs
+++ b/src/gui/forceSensor.cs
@@ -35,6 +35,8 @@ public partial class ChronoJumpWindow
        [Widget] Gtk.Label label_force_sensor_value;
        [Widget] Gtk.Label label_force_sensor_value_min;
        [Widget] Gtk.VScale vscale_force_sensor;
+       [Widget] Gtk.Viewport viewport_force_sensor_graph;
+       [Widget] Gtk.Image image_force_sensor_graph;
        
        CjComboForceSensorPorts comboForceSensorPorts;
 
@@ -227,17 +229,55 @@ public partial class ChronoJumpWindow
                return true;
        }
 
+       private void on_button_force_sensor_graph_clicked (object o, EventArgs args)
+       {
+               Gtk.FileChooserDialog filechooser = new Gtk.FileChooserDialog ("Choose file",
+                                                                              app1, FileChooserAction.Open,
+                                                                              "Cancel",ResponseType.Cancel,
+                                                                              "Choose",ResponseType.Accept);
+               string dataDir = ForceSensorGraph.GetDataDir(currentSession.UniqueID);
+               filechooser.SetCurrentFolder(dataDir);
+
+               FileFilter file_filter = new FileFilter();
+               file_filter.AddPattern ("*.csv");
+
+               if (filechooser.Run () == (int)ResponseType.Accept)
+               {
+                       File.Copy(filechooser.Filename,
+                                       Path.GetTempPath() + Path.DirectorySeparatorChar + "cj_mif_Data.csv",
+                                       true); //can be overwritten
+
+                       string imagePath = Path.GetTempPath() + Path.DirectorySeparatorChar + 
"cj_mif_Graph.png";
+                       Util.FileDelete(imagePath);
+                       image_force_sensor_graph.Sensitive = false;
+
+                       ForceSensorGraph fsg = new ForceSensorGraph(rfdList);
+                       bool success = fsg.CallR(
+                                       viewport_force_sensor_graph.Allocation.Width -5,
+                                       viewport_force_sensor_graph.Allocation.Height -5);
+
+                       if(! success)
+                       {
+                               new DialogMessage(Constants.MessageTypes.WARNING, "Error doing graph.");
+                               filechooser.Destroy ();
+                               return;
+                       }
+
+                       while ( ! Util.FileReadable(imagePath));
+
+                       image_force_sensor_graph = UtilGtk.OpenImageSafe(
+                                       imagePath,
+                                       image_force_sensor_graph);
+                       image_force_sensor_graph.Sensitive = true;
+               }
+               filechooser.Destroy ();
+       }
+
        private void on_button_force_sensor_data_folder_clicked (object o, EventArgs args)
        {
-               System.IO.DirectoryInfo folderSession =
-                       new System.IO.DirectoryInfo(Util.GetForceSensorSessionDir(currentSession.UniqueID));
-               System.IO.DirectoryInfo folderGeneric =
-                       new System.IO.DirectoryInfo(Util.GetForceSensorDir());
-
-               if(folderSession.Exists)
-                       
System.Diagnostics.Process.Start(Util.GetForceSensorSessionDir(currentSession.UniqueID));
-               else if(folderGeneric.Exists)
-                       System.Diagnostics.Process.Start(Util.GetForceSensorDir());
+               string dataDir = ForceSensorGraph.GetDataDir(currentSession.UniqueID);
+               if(dataDir != "")
+                       System.Diagnostics.Process.Start(dataDir);
                else
                        new DialogMessage(Constants.MessageTypes.WARNING, Constants.DirectoryCannotOpen);
        }
diff --git a/src/utilEncoder.cs b/src/utilEncoder.cs
index a29780f..bdf1494 100644
--- a/src/utilEncoder.cs
+++ b/src/utilEncoder.cs
@@ -251,7 +251,7 @@ public class UtilEncoder
                return System.IO.Path.Combine(Util.GetDataDir(), "r-scripts");
        }
        public static string GetmifScript() {
-               return System.IO.Path.Combine(GetSprintPath(), "maximumisometricForce.R");
+               return System.IO.Path.Combine(GetSprintPath(), "maximumIsometricForce.R");
        }
 
        /********** end of r-scripts paths ************/


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