[chronojump] force sensor analyze: variability, better zoom, ...



commit c344e43c25ef40ed1fff1071c49568bb8428797c
Author: Xavier de Blas <xaviblas gmail com>
Date:   Sun Jun 2 21:44:30 2019 -0300

    force sensor analyze: variability, better zoom, ...

 src/forceSensor.cs            | 66 ++++++++++++++++++++++++++++++++++++++++++-
 src/gui/forceSensor.cs        | 35 ++++++++++++-----------
 src/gui/forceSensorAnalyze.cs | 33 +++++++++++++++++++++-
 3 files changed, 115 insertions(+), 19 deletions(-)
---
diff --git a/src/forceSensor.cs b/src/forceSensor.cs
index a83b67cc..8ef65f92 100644
--- a/src/forceSensor.cs
+++ b/src/forceSensor.cs
@@ -98,6 +98,8 @@ public class ForceSensorCapturePoints
        //used to redo all points if change RealWidthG or RealHeightG
        private List<int> times;
        private List<double> forces;
+       private double forceMax;
+       private double forceMin;
 
        public int RealWidthG; //width of graph in microseconds (will be upgraded if needed)
 
@@ -121,6 +123,8 @@ public class ForceSensorCapturePoints
                NumPainted = 0;         //-1 means delete screen
                times = new List<int>();
                forces = new List<double>();
+               forceMax = 0;
+               forceMin = 10000;
 
                InitRealWidthHeight();
 
@@ -140,6 +144,11 @@ public class ForceSensorCapturePoints
                times.Add(time);
                forces.Add(force);
                Points.Add(new Gdk.Point(GetTimeInPx(time), GetForceInPx(force)));
+
+               if(force > forceMax)
+                       forceMax = force;
+               if(force < forceMin)
+                       forceMin = force;
        }
 
        public int GetTimeInPx(int time)
@@ -238,6 +247,33 @@ public class ForceSensorCapturePoints
                double elapsedSeconds = times[countB]/1000000.0 - times[countA]/1000000.0;
                return sum * Util.DivideSafe(elapsedSeconds, samples);
        }
+       public void GetVariabilityAndAccuracy(int countA, int countB, int feedbackN, out double variability, 
out double feedbackDifference)
+       {
+               if(countA == countB)
+               {
+                       variability = 0;
+                       feedbackDifference = 0;
+                       return;
+               }
+
+               // 1) get average
+               double sum = 0;
+               for(int i = countA; i <= countB; i ++)
+                       sum += forces[i];
+
+
+               double avg = sum / ((countB - countA) +1);
+
+               // 2) move all the forces to 0 (substracting from average)
+               //    and have them in absolute value
+               double sumAt0 = 0;
+               for(int i = countA; i <= countB; i ++)
+                       sumAt0 += Math.Abs(forces[i]-avg);
+
+               variability = Util.DivideSafe(sumAt0, ((countB - countA) +1));
+               feedbackDifference = Math.Abs(feedbackN - avg);
+       }
+
        public int MarginLeft
        {
                get { return marginLeft; }
@@ -283,7 +319,11 @@ public class ForceSensorCapturePoints
                        RealWidthG = lastTime + GetTimeInPx(marginLeft) + GetTimeInPx(marginRight);
 
                        RealHeightG = Convert.ToInt32(maxForce);
-                       RealHeightGNeg = Convert.ToInt32(Math.Abs(minForce));
+                       //RealHeightGNeg = Convert.ToInt32(Math.Abs(minForce));
+                       if(minForce < 0)
+                               RealHeightGNeg = Convert.ToInt32(Math.Abs(minForce));
+                       else
+                               RealHeightGNeg = 0;
 
                        return true;
                }
@@ -293,7 +333,17 @@ public class ForceSensorCapturePoints
 
        public void Zoom(int lastTime) //on zoom adjust width
        {
+               //X
                RealWidthG = lastTime + GetTimeInPx(marginLeft) + GetTimeInPx(marginRight);
+
+               //Y
+               RealHeightG = Convert.ToInt32(forceMax);
+               if(forceMin < 0)
+                       RealHeightGNeg = Convert.ToInt32(Math.Abs(forceMin));
+               else
+                       RealHeightGNeg = -1 * Convert.ToInt32(forceMin);
+
+               //LogB.Information(string.Format("RealHeightG: {0}; RealHeightGNeg: {1}", RealHeightG, 
RealHeightGNeg));
        }
 
        public void Redo()
@@ -311,6 +361,15 @@ public class ForceSensorCapturePoints
        {
                set { heightG = value; }
        }
+
+       public double ForceMax
+       {
+               get { return forceMax; }
+       }
+       public double ForceMin
+       {
+               get { return forceMin; }
+       }
 }
 
 public class ForceSensorRFD
@@ -807,6 +866,11 @@ public class ForceSensorAnalyzeInstant
                return fscAIPoints.GetImpulse(countA, countB);
        }
 
+       public void CalculateVariabilityAndAccuracy(int countA, int countB,
+                       int feedbackN, out double variability, out double feedbackDifference)
+       {
+               fscAIPoints.GetVariabilityAndAccuracy(countA, countB, feedbackN, out variability, out 
feedbackDifference);
+       }
        /*
         * Calculates RFD in a point using previous and next point
         */
diff --git a/src/gui/forceSensor.cs b/src/gui/forceSensor.cs
index b3c32a54..5307b729 100644
--- a/src/gui/forceSensor.cs
+++ b/src/gui/forceSensor.cs
@@ -627,7 +627,7 @@ public partial class ChronoJumpWindow
 
                forcePaintHVLines(ForceSensorGraphs.CAPTURE, ForceSensorCapturePoints.DefaultRealHeightG, 
ForceSensorCapturePoints.DefaultRealHeightGNeg, 10);
                //draw horizontal rectangle of feedback
-               forceSensorSignalPlotFeedbackRectangle();
+               forceSensorSignalPlotFeedbackRectangle(fscPoints, force_capture_drawingarea, 
force_capture_pixmap);
 
 
                event_execute_ButtonFinish.Clicked -= new EventHandler(on_finish_clicked);
@@ -1003,8 +1003,9 @@ LogB.Information(" re I ");
                                fscPoints.NumPainted = 0;
 
                                forcePaintHVLines(ForceSensorGraphs.CAPTURE, forceSensorValues.ForceMax * 2, 
forceSensorValues.ForceMin * 2, fscPoints.RealWidthG);
+                               //forcePaintHVLines(ForceSensorGraphs.CAPTURE, fscPoints.ForceMax * 2, 
fscPoints.ForceMin * 2, fscPoints.RealWidthG);
                                //draw horizontal rectangle of feedback
-                               forceSensorSignalPlotFeedbackRectangle();
+                               forceSensorSignalPlotFeedbackRectangle(fscPoints, force_capture_drawingarea, 
force_capture_pixmap);
 
                        }
 
@@ -1321,7 +1322,7 @@ LogB.Information(" re R ");
                forcePaintHVLines(ForceSensorGraphs.CAPTURE, forceSensorValues.ForceMax, 
forceSensorValues.ForceMin, forceSensorValues.TimeLast);
 
                //draw horizontal rectangle of feedback
-               forceSensorSignalPlotFeedbackRectangle();
+               forceSensorSignalPlotFeedbackRectangle(fscPoints, force_capture_drawingarea, 
force_capture_pixmap);
 
 
                Gdk.Point [] paintPoints = new Gdk.Point[fscPoints.Points.Count];
@@ -1349,7 +1350,7 @@ LogB.Information(" re R ");
                button_force_sensor_analyze_recalculate.Sensitive = true;
        }
 
-       private void forceSensorSignalPlotFeedbackRectangle()
+       private void forceSensorSignalPlotFeedbackRectangle(ForceSensorCapturePoints points, Gtk.DrawingArea 
drawingarea, Gdk.Pixmap pixmap)
        {
                //draw horizontal rectangle of feedback
                int fbkNValue = Convert.ToInt32(spin_force_sensor_capture_feedback_at.Value); //feedback 
Newtons value
@@ -1357,27 +1358,27 @@ LogB.Information(" re R ");
 
                if(fbkNValue > 0 && fbkNRange > 0)
                {
-                       int fbkGraphCenter = fscPoints.GetForceInPx(fbkNValue);
-                       int fbkGraphRectHeight = fscPoints.GetForceInPx(0) - 
fscPoints.GetForceInPx(fbkNRange);
+                       int fbkGraphCenter = points.GetForceInPx(fbkNValue);
+                       int fbkGraphRectHeight = points.GetForceInPx(0) - points.GetForceInPx(fbkNRange);
                        int fbkGraphRectHalfHeight = Convert.ToInt32( fbkGraphRectHeight /2);
-                       int fbkGraphTop = fscPoints.GetForceInPx(fbkNValue) - fbkGraphRectHalfHeight;
+                       int fbkGraphTop = points.GetForceInPx(fbkNValue) - fbkGraphRectHalfHeight;
 
-                       Rectangle rect = new Rectangle(fscPoints.GetTimeInPx(0) +1, fbkGraphTop,
-                                       force_capture_drawingarea.Allocation.Width -1, fbkGraphRectHeight);
-                       force_capture_pixmap.DrawRectangle(pen_yellow_force_capture, true, rect);
+                       Rectangle rect = new Rectangle(points.GetTimeInPx(0) +1, fbkGraphTop,
+                                       drawingarea.Allocation.Width -1, fbkGraphRectHeight);
+                       pixmap.DrawRectangle(pen_yellow_force_capture, true, rect);
 
                        /*
-                       force_capture_pixmap.DrawLine(pen_yellow_dark_force_capture,
-                                       fscPoints.GetTimeInPx(0), fbkGraphCenter, 
force_capture_drawingarea.Allocation.Width, fbkGraphCenter);
+                       pixmap.DrawLine(pen_yellow_dark_force_capture,
+                                       points.GetTimeInPx(0), fbkGraphCenter, drawingarea.Allocation.Width, 
fbkGraphCenter);
                                        */
 
                        int fbkGraphRectThirdHeight = Convert.ToInt32( fbkGraphRectHeight /3);
                        int fbkGraphInnerTop = fbkGraphTop + fbkGraphRectThirdHeight;
-                       //rect = new Rectangle(fscPoints.GetTimeInPx(0), fbkGraphInnerTop,
-                       //              force_capture_drawingarea.Allocation.Width -1, 
fbkGraphRectThirdHeight);
-                       //force_capture_pixmap.DrawRectangle(pen_orange_dark_force_capture, true, rect);
-                       force_capture_pixmap.DrawLine(pen_orange_dark_force_capture,
-                                       fscPoints.GetTimeInPx(0), fbkGraphCenter, 
force_capture_drawingarea.Allocation.Width, fbkGraphCenter);
+                       //rect = new Rectangle(points.GetTimeInPx(0), fbkGraphInnerTop,
+                       //              drawingarea.Allocation.Width -1, fbkGraphRectThirdHeight);
+                       //pixmap.DrawRectangle(pen_orange_dark_force_capture, true, rect);
+                       pixmap.DrawLine(pen_orange_dark_force_capture,
+                                       points.GetTimeInPx(0), fbkGraphCenter, drawingarea.Allocation.Width, 
fbkGraphCenter);
                }
        }
 
diff --git a/src/gui/forceSensorAnalyze.cs b/src/gui/forceSensorAnalyze.cs
index e8e63e50..a38ac4cb 100644
--- a/src/gui/forceSensorAnalyze.cs
+++ b/src/gui/forceSensorAnalyze.cs
@@ -821,13 +821,18 @@ public partial class ChronoJumpWindow
                if(checkbutton_force_sensor_ai_b.Active)
                        button_force_sensor_analyze_AB_save.Visible = true;
 
-               forcePaintHVLines(ForceSensorGraphs.ANALYSIS_GENERAL, forceSensorValues.ForceMax, 
forceSensorValues.ForceMin, forceSensorValues.TimeLast);
+//             forcePaintHVLines(ForceSensorGraphs.ANALYSIS_GENERAL, forceSensorValues.ForceMax, 
forceSensorValues.ForceMin, forceSensorValues.TimeLast);
+
+               //draw horizontal rectangle of feedback
+               forceSensorSignalPlotFeedbackRectangle(fsAI.FscAIPoints, force_sensor_ai_drawingarea, 
force_sensor_ai_pixmap);
 
                // 1) create paintPoints
                Gdk.Point [] paintPoints = new Gdk.Point[fsAI.FscAIPoints.Points.Count];
                for(int i = 0; i < fsAI.FscAIPoints.Points.Count; i ++)
                        paintPoints[i] = fsAI.FscAIPoints.Points[i];
 
+               forcePaintHVLines(ForceSensorGraphs.ANALYSIS_GENERAL, fsAI.FscAIPoints.ForceMax, 
fsAI.FscAIPoints.ForceMin, forceSensorValues.TimeLast);
+
                // 2) draw horizontal 0 line
                force_sensor_ai_pixmap.DrawLine(pen_gray_discont_force_ai,
                                0, fsAI.GetPxAtForce(0), allocation.Width, fsAI.GetPxAtForce(0));
@@ -995,6 +1000,32 @@ public partial class ChronoJumpWindow
                                        allocation.Width -textWidth -10, allocation.Height/2,
                                        layout_force_ai_text);
 
+                       // 11) calculate and paint variability
+                       double variability = 0;
+                       double feedbackDiff = 0;
+                       int feedbackN = Convert.ToInt32(spin_force_sensor_capture_feedback_at.Value);
+
+                       fsAI.CalculateVariabilityAndAccuracy(hscaleLower, hscaleHigher, feedbackN, out 
variability, out feedbackDiff);
+
+                       layout_force_ai_text.SetMarkup(string.Format("Variability: {0:0.#} N",
+                                               Math.Round(variability, 1) ));
+
+                       layout_force_ai_text.GetPixelSize(out textWidth, out textHeight);
+                       force_sensor_ai_pixmap.DrawLayout (pen_black_force_ai,
+                                       allocation.Width -textWidth -10, allocation.Height/2 + 20,
+                                       layout_force_ai_text);
+
+                       // 12) calculate and paint Accuracy (Feedback difference)
+                       if(feedbackN > 0)
+                       {
+                               layout_force_ai_text.SetMarkup(string.Format("Accuracy (vs Feedback): {0:0.#} 
N",
+                                                       Math.Round(feedbackDiff, 1) ));
+
+                               layout_force_ai_text.GetPixelSize(out textWidth, out textHeight);
+                               force_sensor_ai_pixmap.DrawLayout (pen_black_force_ai,
+                                               allocation.Width -textWidth -10, allocation.Height/2 + 40,
+                                               layout_force_ai_text);
+                       }
 
                }
                LogB.Information("forceSensorAnalyzeManualGraphDo() END");


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