[chronojump] ForceSensor can export session modelized RFDs (1st code working)
- From: Xavier de Blas <xaviblas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [chronojump] ForceSensor can export session modelized RFDs (1st code working)
- Date: Wed, 3 Feb 2021 12:26:42 +0000 (UTC)
commit 4d9adab7a3db94a3122ff51d2333fa5e8149bc05
Author: Xavier de Blas <xaviblas gmail com>
Date: Wed Feb 3 13:25:24 2021 +0100
ForceSensor can export session modelized RFDs (1st code working)
glade/app1.glade | 48 +++++++---
src/forceSensor.cs | 17 ++++
src/gui/app1/forceSensorAnalyze.cs | 189 ++++++++++++++++++++++++++++++++++++-
src/utilEncoder.cs | 3 +
4 files changed, 241 insertions(+), 16 deletions(-)
---
diff --git a/glade/app1.glade b/glade/app1.glade
index 94846efd..018bd514 100644
--- a/glade/app1.glade
+++ b/glade/app1.glade
@@ -21049,9 +21049,6 @@ Concentric</property>
<property name="column_spacing">16</property>
<property name="row_spacing">2</property>
<child>
- <placeholder/>
- </child>
- <child>
<widget class="GtkButton"
id="button_force_sensor_analyze_load">
<property name="visible">True</property>
<property name="can_focus">True</property>
@@ -21747,6 +21744,21 @@ Concentric</property>
<property name="y_options"/>
</packing>
</child>
+ <child>
+ <widget class="GtkButton"
id="button_force_sensor_export_session">
+ <property name="label">Export session</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_export_session_clicked" swapped="no"/>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options"/>
+ <property name="y_options"/>
+ </packing>
+ </child>
</widget>
<packing>
<property name="expand">False</property>
@@ -23610,6 +23622,9 @@ Concentric</property>
<child>
<placeholder/>
</child>
+ <child>
+ <placeholder/>
+ </child>
</widget>
<packing>
<property name="expand">False</property>
@@ -28456,6 +28471,18 @@ Concentric</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
+ <widget class="GtkLabel"
id="label_video_encoder_tests_will_be_filmed">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Tests
will be filmed</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
<widget class="GtkHBox"
id="hbox_video_encoder_capturing">
<property name="can_focus">False</property>
<property name="spacing">4</property>
@@ -28492,18 +28519,6 @@ Concentric</property>
</packing>
</child>
<child>
- <widget class="GtkLabel"
id="label_video_encoder_tests_will_be_filmed">
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Tests
will be filmed</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
<widget class="GtkHBox"
id="hbox_video_encoder_no_capturing">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -36780,6 +36795,9 @@ then click this button.</property>
<child>
<placeholder/>
</child>
+ <child>
+ <placeholder/>
+ </child>
</widget>
<packing>
<property name="expand">False</property>
diff --git a/src/forceSensor.cs b/src/forceSensor.cs
index bd442cdd..515e32c3 100644
--- a/src/forceSensor.cs
+++ b/src/forceSensor.cs
@@ -306,6 +306,10 @@ public class ForceSensor
get { return uniqueID; }
set { uniqueID = value; }
}
+ public int PersonID
+ {
+ get { return personID; }
+ }
public int ExerciseID
{
get { return exerciseID; }
@@ -1263,6 +1267,19 @@ public class ForceSensorRFD
return function.ToString() + ";" + type.ToString() + ";" + num1.ToString() + ";" +
num2.ToString();
}
+ public string ToExport(bool translated, string sep)
+ {
+ return FunctionPrint(translated) + sep +
+ TypePrint(translated) + sep +
+ num1 + sep +
+ num2;
+ }
+
+ public bool Active
+ {
+ get { return active; }
+ }
+
public static string Function_RAW_name
{
get { return function_RAW_name; }
diff --git a/src/gui/app1/forceSensorAnalyze.cs b/src/gui/app1/forceSensorAnalyze.cs
index 9e230e19..78d8f8ed 100644
--- a/src/gui/app1/forceSensorAnalyze.cs
+++ b/src/gui/app1/forceSensorAnalyze.cs
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * Copyright (C) 2018-2020 Xavier de Blas <xaviblas gmail com>
+ * Copyright (C) 2018-2021 Xavier de Blas <xaviblas gmail com>
*/
using System;
@@ -24,6 +24,7 @@ using Gtk;
using Gdk;
using Glade;
using System.Text; //StringBuilder
+using System.Collections; //ArrayList
using System.Collections.Generic; //List<T>
using Mono.Unix;
@@ -680,6 +681,192 @@ public partial class ChronoJumpWindow
bool force_sensor_ai_drawingareaShown = false;
+ //TODO: separate in thread
+ private void on_button_force_sensor_export_session_clicked (object o, EventArgs args)
+ {
+ // 1) Select force sensor files and force sensor exercises
+ List<ForceSensor> fs_l = SqliteForceSensor.Select(false, -1, -1, currentSession.UniqueID);
+ ArrayList personSession_l =
SqlitePersonSession.SelectCurrentSessionPersons(currentSession.UniqueID, true);
+ ArrayList fsEx_l = SqliteForceSensorExercise.Select (false, -1, false);
+ List<string> exportedRFDs = new List<string>();
+
+ foreach(ForceSensor fs in fs_l)
+ {
+ //check fs is ok
+ if(fs == null || ! Util.FileExists(fs.FullURL))
+ continue;
+
+ //check fs has data
+ List<string> contents = Util.ReadFileAsStringList(fs.FullURL);
+ if(contents.Count < 3)
+ {
+ new DialogMessage(Constants.MessageTypes.WARNING, Constants.FileEmptyStr());
+ return;
+ }
+
+ //get the person
+ string personName = "";
+ double personWeight = 0;
+ bool found = false;
+ foreach(PersonAndPS paps in personSession_l)
+ {
+ if(paps.p.UniqueID == fs.PersonID)
+ {
+ personName = paps.p.Name;
+ personWeight = paps.ps.Weight;
+ found = true;
+ break;
+ }
+ }
+ if(! found)
+ continue;
+
+ //get the exercise
+ found = false;
+ ForceSensorExercise fsEx = new ForceSensorExercise();
+ foreach(ForceSensorExercise fsExTemp in fsEx_l)
+ if(fsExTemp.UniqueID == fs.ExerciseID)
+ {
+ fsEx = fsExTemp;
+ found = true;
+ break;
+ }
+ if(! found)
+ continue;
+
+ double eccMinDispl = fsEx.GetEccOrConMinMaybePreferences(true,
+ preferences.forceSensorElasticEccMinDispl,
+ preferences.forceSensorNotElasticEccMinForce);
+ double conMinDispl = fsEx.GetEccOrConMinMaybePreferences(false,
+ preferences.forceSensorElasticConMinDispl,
+ preferences.forceSensorNotElasticConMinForce);
+
+ // 3) create fsAI (includes the repetitions
+ fsAI = new ForceSensorAnalyzeInstant(
+ fs.FullURL,
+ force_sensor_ai_drawingarea.Allocation.Width,
+ force_sensor_ai_drawingarea.Allocation.Height,
+ -1, -1,
+ fsEx, personWeight,
+ fs.CaptureOption, fs.Stiffness,
+ eccMinDispl, conMinDispl
+ );
+
+ // 4) call R
+ int imageWidth = UtilGtk.WidgetWidth(viewport_force_sensor_graph);
+ int imageHeight = UtilGtk.WidgetHeight(viewport_force_sensor_graph);
+ if(imageWidth < 300)
+ imageWidth = 300; //Not crash R with a png height of -1 or "figure margins
too large"
+ if(imageHeight < 300)
+ imageHeight = 300; //Not crash R with a png height of -1 or "figure margins
too large"
+
+ int duration = -1;
+ if(radio_force_duration_seconds.Active)
+ duration = Convert.ToInt32(spin_force_duration_seconds.Value);
+
+ //string title = lastForceSensorFile;
+ string title = personName;
+ string exercise = fsEx.Name;
+ if (UtilAll.IsWindows()) {
+ title = Util.ConvertToUnicode(title);
+ exercise = Util.ConvertToUnicode(exercise);
+ }
+ if (title == null || title == "")
+ title = "unnamed";
+
+ //copy file to tmp to be written readed by R
+ File.Copy(fs.FullURL, UtilEncoder.GetmifCSVFileName(), true); //can be overwritten
+
+ //delete result file
+ Util.FileDelete(UtilEncoder.GetmifExportFileName());
+
+ //TODO: només les concèntriques
+ foreach(ForceSensorRepetition rep in fsAI.ForceSensorRepetition_l)
+ {
+ ForceSensorGraph fsg = new ForceSensorGraph(fs.CaptureOption, rfdList,
impulse,
+ duration,
Convert.ToInt32(spin_force_rfd_duration_percent.Value),
+ title, exercise, fs.DateTimePublic, new TriggerList(),
+ rep.sampleStart, rep.sampleEnd,
preferences.forceSensorStartEndOptimized,
+ Util.CSVDecimalColumnIsPoint(UtilEncoder.GetmifCSVFileName(),
1) // (*)
+ );
+
+ bool success = fsg.CallR(imageWidth -5, imageHeight -5);
+ }
+
+ //TODO: or check cancel when there is a thread, also R should write something blank
if there is any problem
+ //also the problem with this code is: if R code fails for any reason (bad data), will
exit R code and this file will never be created
+ /*
+ LogB.Information("Waiting creation of file... ");
+ while ( ! ( Util.FileReadable(UtilEncoder.GetmifExportFileName())))
+ ;
+ */
+
+ if(File.Exists(UtilEncoder.GetmifExportFileName()))
+ {
+ List<string> repRFDs =
Util.ReadFileAsStringList(UtilEncoder.GetmifExportFileName());
+ int countRep = 0; //0 will be the header
+ foreach(string row in repRFDs)
+ {
+ //discard header
+ if(countRep == 0)
+ {
+ countRep ++;
+ continue;
+ }
+ //TODO: respect latin/not latin (decimal character, column separator)
+ exportedRFDs.Add(personName + ";" + fs.DateTimePublic + ";" +
+ fsEx.Name + ";" + (countRep++).ToString() + ";" +
fs.Laterality + ";" +
+ row);
+ }
+ }
+ }
+
+ string destination = UtilEncoder.GetmifExportFileName();
+ Util.FileDelete(destination);
+ try {
+ //this overwrites if needed
+ TextWriter writer = File.CreateText(destination);
+
+ string sep = " ";
+ if (preferences.CSVExportDecimalSeparator == "COMMA")
+ sep = ";";
+ else
+ sep = ",";
+
+ //write header
+ string [] headers = { "Person", "date", "Exercise", "Repetition", "Laterality"};
+ int i = 0;
+ foreach(ForceSensorRFD rfd in rfdList)
+ {
+ if(rfdList[i].Active)
+ headers = Util.AddArrayString(headers,
+ string.Format("RFD{0}", i+1) + "_" +
rfd.ToExport(true, "_"),
+ false);
+ i ++;
+ }
+ ForceSensorImpulse tempImpulse = getImpulseValue ();
+ if(tempImpulse.Active)
+ headers = Util.AddArrayString(headers,
+ Catalog.GetString("Impulse") + "_" +
tempImpulse.ToExport(true, "_"),
+ false);
+
+ writer.WriteLine(Util.RemoveNewLine(Util.StringArrayToString(headers, sep), false));
+
+ //write data
+ foreach(string str in exportedRFDs)
+ writer.WriteLine(str);
+
+ writer.Flush();
+ writer.Close();
+ ((IDisposable)writer).Dispose();
+ } catch {
+ string myString = string.Format(
+ Catalog.GetString("Cannot save file {0} "), destination);
+ new DialogMessage(Constants.MessageTypes.WARNING, myString);
+ }
+
+ }
+
private void forceSensorDoGraphAI(bool windowResizedAndZoom)
{
if(lastForceSensorFullPath == null || lastForceSensorFullPath == "")
diff --git a/src/utilEncoder.cs b/src/utilEncoder.cs
index 2f30dd25..df190554 100644
--- a/src/utilEncoder.cs
+++ b/src/utilEncoder.cs
@@ -263,6 +263,9 @@ public class UtilEncoder
public static string GetmifTempFileName() {
return Path.Combine(Path.GetTempPath(), "cj_mif_Graph.png");
}
+ public static string GetmifExportFileName() {
+ return Path.Combine(Path.GetTempPath(), "cj_mif_export.csv");
+ }
/********** end of r-scripts paths ************/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]