[chronojump] Initial Implementation of Encoder 1RM Indirect on program
- From: Xavier de Blas <xaviblas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [chronojump] Initial Implementation of Encoder 1RM Indirect on program
- Date: Wed, 11 Nov 2015 20:12:46 +0000 (UTC)
commit 3701249265cc3229ee7769b22b83690bc19ab4ed
Author: Xavier de Blas <xaviblas gmail com>
Date: Wed Nov 11 21:12:08 2015 +0100
Initial Implementation of Encoder 1RM Indirect on program
encoder/RM.R | 107 ----------------------------------------------------
encoder/graph.R | 97 ++++++++++++++++++++++++++++++++++++++++++++++-
src/gui/encoder.cs | 74 ++++++++++++++++++++++++++++-------
3 files changed, 155 insertions(+), 123 deletions(-)
---
diff --git a/encoder/graph.R b/encoder/graph.R
index d6b4e9c..7fb9e4e 100644
--- a/encoder/graph.R
+++ b/encoder/graph.R
@@ -2067,6 +2067,91 @@ paint1RMBadillo2010 <- function (paf, title, outputData1) {
write(paste("1RM;",round(predicted1RM,2),sep=""), SpecialData)
}
+#---- RM Indirect start ----
+
+RMIndirect <- function(Q, nrep, nRM) {
+#Q = load in Kg
+#nrep = number of maximum repetitions
+#n = the number of nRM you want to know
+
+ rm = matrix(rep(c(0,0,0,0,0,0,0,0), nRM), ncol=8)
+ colnames(rm) = c("Brzycki", "Epley", "Lander", "Lombardi", "Mayhew", "Oconner", "Wathan", "AVG")
+ rm = as.data.frame(rm)
+ rm[1,1] = Q * (36 / (37 - nrep)) #Brzycki
+ rm[1,2] = Q * (1 + 0.0333 * nrep) #Epley
+ rm[1,3] = (100 * Q) / (101.3 - 2.67123 * nrep) #Lander
+ rm[1,4] = Q * nrep^0.1 #Lombardi
+ rm[1,5] = (100 * Q) / (52.2 + (41.9 * exp(-0.055 * nrep))) #Mayhew
+ rm[1,6] = Q * (1 + 0.025 * nrep) #O'Conner
+ rm[1,7] = (100 * Q) / (48.8 + (53.8 * exp(-0.075 * nrep))) #Wathan
+ rm[1,8] = mean(as.numeric(rm[1,1:7]))
+
+ if(nRM < 2) return(rm)
+ for(i in 2:nRM) {
+ rm[i,1] = rm[1,1] * (37 - i) / 36 #Brzycki
+ rm[i,2] = rm[1,2] / (1 + (i / 30)) #Epley
+ rm[i,3] = rm[1,3] * (101.3 - 2.67123 * i) / 100 #Lander
+ rm[i,4] = rm[1,4] / (i ^ (1 / 10)) #Lombardi
+ rm[i,5] = rm[1,5] * (52.2 + (41.9 * exp(-1 * (i * 0.055)))) / 100 #Mayhew
+ rm[i,6] = rm[1,6] / (1 + i * 0.025) #O'Conner
+ rm[i,7] = rm[1,7]* (48.8 + (53.8 * exp(-1 * (i * 0.075)))) / 100 #Wathan
+ rm[i,8] = mean(as.numeric(rm[i,1:7]))
+ }
+ return(rm)
+}
+plotRMIndirect <- function (RMIMatrix, Q, nrep)
+{
+ nRM = length(RMIMatrix[,1])
+
+ ntests = length(RMIMatrix[1,]) -1 #-1 because we don't count the AVG
+ uniqueColors=rainbow(ntests)
+
+ par(mar=c(5,4,7,2)) #more space on the top
+
+ #Create an empty plot
+ plot(1, xlim=c(1,nRM),ylim=c(min(RMIMatrix),max(RMIMatrix)), type="n",
+ xlab="Repetitions", ylab="Mass (Kg)", xaxt="n")
+ axis(1,1:10) #plot xaxis ensuring 1:10 is written
+
+ #Draw grid
+ abline(h=seq(0,max(RMIMatrix),by=5), lty=2, col="gray")
+ abline(v=nrep, lty=2, col="gray")
+
+ #Draw all points except AVG (all the tests)
+ # Note: this is fine tuned to have points at X:
+ # -0.12, -0.8, -0.4, 0, 0.4, 0.8, 0.12
+ # if there are more tests than 7, this need to be adjusted
+ xmov = -0.12
+ for(i in 1:ntests) {
+ points((1:10)+xmov, RMIMatrix[,i], type="p", pch=19, col=uniqueColors[i])
+ xmov = xmov +.04
+ }
+
+ #Draw AVG line
+ lines(RMIMatrix$AVG, type="l", lwd=2)
+
+ #Title
+ mtext(paste("Indirect RM prediction with", nrep, "repetitions and", Q, "Kg"),
+ side=3, at=5, adj=0.5, cex=1, line=5, font=2)
+
+ #AVGs on top. Note ntests is the AVG column
+ font = 2 #first column will be bold
+ for(i in 1:nRM) {
+ mtext(paste(i,"RM",sep=""), side=3, at=i, adj=0.5, cex=.8, line=2.5, font=font)
+ mtext(round(RMIMatrix[i,(ntests+1)],1), side=3, at=i, adj=0.5, cex=.8, line=1.5, font=font)
+ font = 1 #rest of the columns will not be bold
+ }
+ mtext("AVG", side=3, at=0, adj=.5, cex=.8, line=1.5)
+
+ legend("topright", legend=names(RMIMatrix), col=c(uniqueColors,"Black"), lwd=1,
+ lty=c(rep(0,ntests),1), pch=c(rep(19,ntests),NA), cex=.8, bg="White") #legend
+
+ par(mar=c(5,4,4,2))
+
+ write(paste("1RM;",round(RMIMatrix[1,(ntests+1)],2),sep=""), SpecialData)
+}
+
+#---- RM Indirect end ----
find.mfrow <- function(n) {
if(n<=3) return(c(1,n))
@@ -2720,7 +2805,7 @@ doProcess <- function(options)
#when an analysis is done, curves file has to be written
writeCurves = TRUE
#but don't writeCurves on exportCSV because outputfile is the same
- if(op$Analysis == "exportCSV")
+ if(op$Analysis == "exportCSV" || op$Analysis=="1RMIndirect")
writeCurves = FALSE
if(
@@ -3035,6 +3120,16 @@ doProcess <- function(options)
#print("curves written")
}
}
+
+ if(op$Analysis=="1RMIndirect") {
+ Q <- 80
+ nrep <- 3
+ plotRMIndirect( RMIndirect(Q, nrep, 10), Q, nrep )
+
+ #write this file to allow C# process finish
+ write("", op$OutputData1)
+ }
+
if(op$Analysis=="exportCSV") {
print("Starting export...")
write("starting export", stderr())
diff --git a/src/gui/encoder.cs b/src/gui/encoder.cs
index eb50f50..6c8258e 100644
--- a/src/gui/encoder.cs
+++ b/src/gui/encoder.cs
@@ -2137,6 +2137,7 @@ public partial class ChronoJumpWindow
crossNameTemp == Catalog.GetString("1RM Bench Press") ||
crossNameTemp == "1RM Any exercise" ||
crossNameTemp == Catalog.GetString("1RM Any exercise")
+ //no 1RM Indirect because cannot be done with saved curves
)) {
new DialogMessage(Constants.MessageTypes.WARNING,
Catalog.GetString("Sorry, this graph is not supported yet.") +
@@ -2144,6 +2145,7 @@ public partial class ChronoJumpWindow
"\n- Speed,Power / Load" +
"\n- 1RM Bench Press" +
"\n- 1RM Any exercise"
+ //no 1RM Indirect because cannot be done with saved curves
);
return;
@@ -2155,6 +2157,7 @@ public partial class ChronoJumpWindow
crossNameTemp == Catalog.GetString("1RM Bench Press") ||
crossNameTemp == "1RM Any exercise" ||
crossNameTemp == Catalog.GetString("1RM Any exercise")
+ //no 1RM Indirect because cannot be done with saved curves
))
{
bool differentExercises = false;
@@ -2686,7 +2689,11 @@ public partial class ChronoJumpWindow
if(crossName == "1RM Bench Press") {
sendAnalysis = "1RMBadillo2010";
analysisOptions = "p";
- } else {
+ } else if(
+ crossName == "Speed / Load" || crossName == "Force / Load" ||
+ crossName == "Power / Load" || crossName == "Speed,Power / Load" ||
+ crossName == "Force / Speed" || crossName == "Power / Speed")
+ {
//convert: "Force / Speed" in: "cross.Force.Speed.mean"
string [] crossNameFull = crossName.Split(new char[] {' '});
analysisVariables = crossNameFull[0] + ";" + crossNameFull[2]; //[1]=="/"
@@ -2908,15 +2915,20 @@ public partial class ChronoJumpWindow
Sqlite.Close();
} else { //current signal
- if(encoderAnalysis == "cross" && crossName == "1RM Any exercise") {
- //get speed1RM (from combo)
- EncoderExercise ex = (EncoderExercise) SqliteEncoder.SelectEncoderExercises(
- false, getExerciseIDFromCombo(), false)[0];
-
- sendAnalysis = "1RMAnyExercise";
- analysisVariables = Util.ConvertToPoint(ex.speed1RM) + ";" +
- SqlitePreferences.Select("encoder1RMMethod");
- analysisOptions = "p";
+ if(encoderAnalysis == "cross") {
+ if(crossName == "1RM Any exercise") {
+ //get speed1RM (from combo)
+ EncoderExercise ex = (EncoderExercise)
SqliteEncoder.SelectEncoderExercises(
+ false, getExerciseIDFromCombo(), false)[0];
+
+ sendAnalysis = "1RMAnyExercise";
+ analysisVariables = Util.ConvertToPoint(ex.speed1RM) + ";" +
+ SqlitePreferences.Select("encoder1RMMethod");
+ analysisOptions = "p";
+ }
+ else if(crossName == "1RM Indirect") {
+ sendAnalysis = "1RMIndirect";
+ }
}
ep = new EncoderParams(
@@ -3392,15 +3404,16 @@ public partial class ChronoJumpWindow
//create combo analyze cross (variables)
string [] comboAnalyzeCrossOptions = {
"Speed / Load", "Force / Load", "Power / Load", "Speed,Power / Load", "Force /
Speed", "Power / Speed",
- "1RM Bench Press", "1RM Any exercise"};
+ "1RM Bench Press", "1RM Any exercise", "1RM Indirect"};
string [] comboAnalyzeCrossOptionsTranslated = {
Catalog.GetString("Speed / Load"), Catalog.GetString("Force / Load"),
Catalog.GetString("Power / Load"), Catalog.GetString("Speed,Power / Load"),
Catalog.GetString("Force / Speed"), Catalog.GetString("Power / Speed"),
- Catalog.GetString("1RM Bench Press"), Catalog.GetString("1RM Any exercise")
+ Catalog.GetString("1RM Bench Press"), Catalog.GetString("1RM Any exercise"),
+ Catalog.GetString("1RM Indirect")
}; //if added more, change the int in the 'for' below
encoderAnalyzeCrossTranslation = new String [comboAnalyzeCrossOptions.Length];
- for(int j=0; j < 8 ; j++)
+ for(int j=0; j < 9 ; j++)
encoderAnalyzeCrossTranslation[j] =
comboAnalyzeCrossOptions[j] + ":" + comboAnalyzeCrossOptionsTranslated[j];
combo_encoder_analyze_cross = ComboBox.NewText ();
@@ -3519,7 +3532,10 @@ public partial class ChronoJumpWindow
if(Util.FindOnArray(':',1,0,UtilGtk.ComboGetActive(combo_encoder_analyze_cross),
encoderAnalyzeCrossTranslation) == "1RM Bench Press" ||
Util.FindOnArray(':',1,0,UtilGtk.ComboGetActive(combo_encoder_analyze_cross),
- encoderAnalyzeCrossTranslation) == "1RM Any exercise" ) {
+ encoderAnalyzeCrossTranslation) == "1RM Any exercise" ||
+ Util.FindOnArray(':',1,0,UtilGtk.ComboGetActive(combo_encoder_analyze_cross),
+ encoderAnalyzeCrossTranslation) == "1RM Indirect" )
+ {
check_encoder_analyze_mean_or_max.Active = true;
check_encoder_analyze_mean_or_max.Sensitive = false;
check_encoder_analyze_eccon_together.Active = false;
@@ -3529,6 +3545,17 @@ public partial class ChronoJumpWindow
check_encoder_analyze_eccon_together.Sensitive = true;
block_check_encoder_analyze_eccon_together_if_needed();
}
+
+ //1RM Indirect can only be used with current signal
+ if(Util.FindOnArray(':',1,0,UtilGtk.ComboGetActive(combo_encoder_analyze_cross),
+ encoderAnalyzeCrossTranslation) == "1RM Indirect" &&
+ ! check_encoder_analyze_signal_or_curves.Active) { //saved curves
+ button_encoder_analyze.Sensitive = false;
+ new DialogMessage(Constants.MessageTypes.WARNING,
+ "1RM Indirect prediction can only be done with current set.");
+ }
+
+ button_encoder_analyze_sensitiveness();
}
void on_button_encoder_analyze_image_save_clicked (object o, EventArgs args)
@@ -4105,6 +4132,13 @@ public partial class ChronoJumpWindow
analyze_sensitive = curvesNumOkToSideCompare();
label_encoder_analyze_side_max.Visible = ! analyze_sensitive;
}
+
+ //1RM Indirect only works on current set
+ if(
+ radiobutton_encoder_analyze_cross.Active &&
+
Util.FindOnArray(':',1,0,UtilGtk.ComboGetActive(combo_encoder_analyze_cross),
+ encoderAnalyzeCrossTranslation) == "1RM Indirect")
+ analyze_sensitive = false;
}
button_encoder_analyze.Sensitive = analyze_sensitive;
}
@@ -5497,7 +5531,17 @@ public partial class ChronoJumpWindow
encoderAnalyzeCrossTranslation);
button_encoder_analyze_1RM_save.Sensitive =
(radiobutton_encoder_analyze_cross.Active &&
- (crossName == "1RM Bench Press" || crossName == "1RM Any exercise") );
+ (crossName == "1RM Bench Press" || crossName == "1RM Any exercise") );
+ // || crossName == "1RM Indirect") );
+ /*
+ * TODO: currently disabled because
+ * on_button_encoder_analyze_1RM_save_clicked () reads getExerciseNameFromTable()
+ * and encoderAnalyzeListStore is not created because "1RM Indirect"
+ * currently prints no data on OutputData1
+ *
+ * Solution will be to print data there with a new format
+ * (new columns) like neuromuscular has done
+ */
}
treeview_encoder_capture_curves.Sensitive = true;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]