[chronojump] Pushing up encoder stuff
- From: Xavier de Blas <xaviblas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [chronojump] Pushing up encoder stuff
- Date: Fri, 30 Mar 2012 04:54:24 +0000 (UTC)
commit e5f814eec23042f2eba89c15c08413774deec70c
Author: Xavier de Blas <xaviblas gmail com>
Date: Fri Mar 30 12:53:29 2012 +0800
Pushing up encoder stuff
chronojump_server/Makefile.am | 1 +
encoder/call_graph.py | 27 ++
encoder/graph.R | 449 +++++++++++++++++++
encoder/pyserial_pyper.py | 335 ++++++++++++++
glade/chronojump.glade | 984 +++++++++++++++++++++++++++++++++++++++--
src/Makefile.am | 2 +
src/chronojump.cs | 12 +-
src/constants.cs | 13 +
src/encoder.cs | 92 ++++
src/gui/chronojump.cs | 22 +-
src/gui/encoder.cs | 168 +++++++
src/gui/eventExecute.cs | 4 +-
src/util.cs | 111 +++++-
src/utilGtk.cs | 7 +
14 files changed, 2192 insertions(+), 35 deletions(-)
---
diff --git a/chronojump_server/Makefile.am b/chronojump_server/Makefile.am
index 0b9569e..1d323a6 100644
--- a/chronojump_server/Makefile.am
+++ b/chronojump_server/Makefile.am
@@ -24,6 +24,7 @@ FILES = \
../src/sqlite/*.cs\
../src/util.cs\
../src/utilDate.cs\
+ ../src/encoder.cs\
../src/event.cs\
../src/jump.cs\
../src/run.cs\
diff --git a/encoder/call_graph.py b/encoder/call_graph.py
new file mode 100644
index 0000000..8e1a97c
--- /dev/null
+++ b/encoder/call_graph.py
@@ -0,0 +1,27 @@
+import sys
+import subprocess
+
+print(sys.argv)
+
+#R CMD BATCH --no-save
+
+subprocess.Popen([
+ r"Rscript","/home/xavier/informatica/progs_meus/chronojump/chronojump/encoder/graph.R",
+ sys.argv[1], #input data
+ sys.argv[2], #output graph
+ sys.argv[3],sys.argv[4], #output data1, output data2
+ sys.argv[5], #ep.isJump
+ sys.argv[6], #ep.contractionEC
+ sys.argv[7], #ep.analysis
+ sys.argv[8], #ep.smooth
+ sys.argv[9], #ep.curve
+ sys.argv[10],sys.argv[11] #ep.width, ep.height
+ ]).wait()
+
+
+
+
+#subprocess.Popen([r"R","CMD BATCH --no-save ","/home/xavier/informatica/progs_meus/chronojump/chronojump/encoder/graph.R",sys.argv[1],sys.argv[2],sys.argv[3]]).wait()
+
+print "Python done"
+
diff --git a/encoder/graph.R b/encoder/graph.R
new file mode 100644
index 0000000..0e5ca36
--- /dev/null
+++ b/encoder/graph.R
@@ -0,0 +1,449 @@
+library("EMD")
+#argv <-commandArgs(TRUE); xmin <- as.numeric(argv[1]); xmax <- as.numeric(argv[2])
+
+
+#this will replace below methods: findPics1ByMinindex, findPics2BySpeed
+findCurves <- function(rawdata, eccon, min_height, draw) {
+ a=cumsum(rawdata)
+ b=extrema(a)
+ start=0; end=0; startH=0
+ tempStart=0; tempEnd=0;
+ #TODO: fer algo per si no es detecta el minindex previ al salt
+ if(eccon=="c") {
+ if(length(b$minindex)==0) { b$minindex=cbind(1,1) }
+ if(length(b$maxindex)==0) { b$maxindex=cbind(length(a),length(a)) }
+ #fixes if 1st minindex is after 1st maxindex
+ if(b$maxindex[1] < b$minindex[1]) { b$minindex = rbind(c(1,1),b$minindex) }
+ row=1; i=1; j=1
+ while(max(c(i,j)) <= min(c(length(b$minindex[,1]),length(b$maxindex[,1])))) {
+ tempStart = mean(c(b$minindex[i,1],b$minindex[i,2]))
+ tempEnd = mean(c(b$maxindex[j,1],b$maxindex[j,2]))
+ height=a[tempEnd]-a[tempStart]
+# print(paste(height,i,j))
+ if(height >= min_height) {
+ start[row] = tempStart
+ end[row] = tempEnd
+ startH[row]= a[b$minindex[i,1]] #height at start
+ row=row+1;
+# if(eccon=="c") { break } #c only needs one result
+ }
+ i=i+1; j=j+1
+ }
+ } else { #ec-con, and ec-con-rep
+ row=1; i=1; j=2
+ while(j <= length(b$maxindex[,1])) {
+ tempStart = mean(c(b$maxindex[i,1],b$maxindex[i,2]))
+ tempEnd = mean(c(b$maxindex[j,1],b$maxindex[j,2]))
+ bottom=min(a[tempStart:tempEnd]) #find min value between the two tops
+ mintop=min(c(a[tempStart],a[tempEnd])) #find wich top is lower
+ height=mintop-bottom
+# print(paste(height,i,j))
+ if(height >= min_height) {
+ start[row] = tempStart
+ end[row] = tempEnd
+ startH[row] = a[b$maxindex[i,1]] #height at start
+ row=row+1; i=j;
+# if(eccon=="ec-con") { break } #ec-con only needs one result
+ }
+ j=j+1
+ }
+ }
+ if(draw) {
+ plot(a,type="l",xlim=c(1,length(a)),xlab="",ylab="",axes=T)
+ abline(v=b$maxindex,lty=3); abline(v=b$minindex,lty=3)
+ if(eccon=="c")
+ segments(x0=start,y0=min(a),x1=end,y1=min(a),col="red")
+ else
+ arrows(x0=start,y0=min(a),x1=end,y1=min(a),col="red",code=3)
+ for(i in 1:length(start))
+ text(x=(start[i]+end[i])/2,y=min(a),labels=i, adj=c(0.5,0),cex=1,col="red")
+ }
+ return(as.data.frame(cbind(start,end,startH)))
+}
+
+
+#based on findPics2BySpeed
+#only used in eccon "c"
+reduceCurveBySpeed <- function(startT, rawdata, smoothing) {
+ a=rawdata
+ speed <- smooth.spline( 1:length(a), a, spar=smoothing)
+ b=extrema(speed$y)
+ xmin=1
+ for(i in b$cross[,2]) { if(i < length(a)-20) { xmin = i; } } #left adjust
+# for(i in rev(b$cross[,2])) { if(i > xtop2) { xmax = i; } } #right adjust
+# return (data.frame(ini=xmin, end=xmax)) #return data related to all pics (initial timer count)
+ return(xmin+startT)
+}
+
+#go here with every single jump
+kinematics <- function(a, mass, g) {
+ speed <- smooth.spline( 1:length(a), a, spar=smoothingOne)
+ accel <- predict( speed, deriv=1 )
+ accel$y <- accel$y * 1000 #input data is in mm, conversion to m
+
+ force <- mass*accel$y
+ if(isJump)
+ force <- mass*(accel$y+g) #g:9.81 (used when movement is against gravity)
+
+ power <- force*speed$y
+ return(list(speedy=speed$y, accely=accel$y, force=force, power=power))
+}
+
+powerBars <- function(kinematics) {
+ #meanSpeed <- mean(abs(kinematics$speedy))
+ #maxSpeed <- max(abs(kinematics$speedy))
+ meanPower <- mean(abs(kinematics$power))
+ peakPower <- max(kinematics$power)
+ peakPowerT <- which(kinematics$power == peakPower)
+ return(data.frame(meanPower,peakPower,peakPowerT))
+}
+
+kinematicRanges <- function(rawdata,curves,mass,g) {
+ n=length(curves[,1])
+ maxSpeedy=0;maxForce=0;maxPower=0
+ for(i in 1:n) {
+ kn=kinematics(rawdata[curves[i,1]:curves[i,2]],mass,g)
+ if(max(abs(kn$speedy)) > maxSpeedy)
+ maxSpeedy = max(abs(kn$speedy))
+ if(max(abs(kn$force)) > maxForce)
+ maxForce = max(abs(kn$force))
+ if(max(abs(kn$power)) > maxPower)
+ maxPower = max(abs(kn$power))
+ }
+ return(list(
+ speedy=c(-maxSpeedy,maxSpeedy),
+ force=c(-maxForce,maxForce),
+ power=c(-maxPower,maxPower)))
+}
+
+paint <- function(rawdata, eccon, xmin, xmax, yrange, knRanges, superpose, highlight,
+ startX, startH, smoothing, mass, title, draw, labels, axesAndTitle, legend) {
+ #eccons ec-con and ec-con-rep is the same here (only show one curve)
+ #receive data as cumulative sum
+ lty=c(1,1,1)
+ rawdata=rawdata[xmin:xmax]
+ a=cumsum(rawdata)
+ a=a+startH
+
+ if(draw) {
+ #three vertical axis inspired on http://www.r-bloggers.com/multiple-y-axis-in-a-r-plot/
+ par(mar=c(5, 4, 4, 8))
+
+ #plot distance
+ #plot(a,type="h",xlim=c(xmin,xmax),xlab="time (ms)",ylab="Left: distance (mm); Right: speed (m/s), accelration (m/s^2)",col="gray", axes=F) #this shows background on distance (nice when plotting distance and speed, but confusing when there are more variables)
+ xlab="";ylab="";
+ if(labels) {
+ xlab="time (ms)"
+ ylab="Left: distance (mm); Right: speed (m/s), force (N), power (W)"
+ }
+ ylim=yrange
+ if(ylim[1]=="undefined") { ylim=NULL }
+ if(!axesAndTitle)
+ title=""
+ plot(a,type="n",xlim=c(1,length(a)),ylim=ylim,xlab=xlab, ylab=ylab, col="gray", axes=F, main=title)
+ if(axesAndTitle) {
+ axis(1) #can be added xmin
+ axis(2)
+ }
+ par(new=T)
+ colNormal="black"
+ if(superpose)
+ colNormal="gray30"
+ if(highlight==FALSE)
+ plot(startX:length(a),a[startX:length(a)],type="l",xlim=c(1,length(a)),ylim=ylim,xlab="",ylab="",col="black",lty=lty[1],lwd=1,axes=F)
+ else
+ plot(startX:length(a),a[startX:length(a)],type="l",xlim=c(1,length(a)),ylim=ylim,xlab="",ylab="",col=colNormal,lty=2,lwd=3,axes=F)
+ abline(h=0,lty=3,col="black")
+
+ abline(v=seq(from=0,to=length(a),by=500),lty=3,col="gray")
+ }
+
+ #speed
+ #scan file again (raw data: mm displaced every ms, no cumulative sum)
+ a=rawdata
+ speed <- smooth.spline( 1:length(a), a, spar=smoothing)
+ if(draw) {
+ ylim=c(-max(abs(range(a))),max(abs(range(a)))) #put 0 in the middle
+ if(knRanges[1] != "undefined")
+ ylim = knRanges$speedy
+ par(new=T)
+ if(highlight==FALSE)
+ plot(startX:length(speed$y),speed$y[startX:length(speed$y)],type="l",xlim=c(1,length(a)),ylim=ylim,xlab="",ylab="",col=cols[1],lty=lty[1],lwd=1,axes=F)
+ else
+ plot(startX:length(speed$y),speed$y[startX:length(speed$y)],type="l",xlim=c(1,length(a)),ylim=ylim,xlab="",ylab="",col="darkgreen",lty=2,lwd=3,axes=F)
+ if(axesAndTitle) {
+ axis(4, col=cols[1], lty=lty[1], line=0)
+ abline(h=0,lty=3,col="black")
+ }
+ }
+
+ #show extrema values in speed
+ b=extrema(speed$y)
+ #if(draw & !superpose)
+ # segments(x0=b$maxindex,y0=0,x1=b$maxindex,y1=speed$y[b$maxindex],col=cols[1])
+
+ #declare variables:
+ concentric=0
+ eccentric=0
+ if(eccon=="c") {
+ concentric=1:length(a)
+ } else { #"ec-con", "ec-con-rep"
+ crossSpeedInMiddle = b$cross[,1]
+ crossDownToUp=0
+ count=1
+ for(i in crossSpeedInMiddle) {
+ if(speed$y[i-2]<0) {
+ crossDownToUp[count]=i
+ count=count+1
+ }
+ }
+ eccentric=1:min(crossDownToUp)
+ concentric=max(crossDownToUp):length(a)
+ if(draw) {
+ abline(v=min(crossDownToUp),col=cols[1])
+ abline(v=max(crossDownToUp),col=cols[1])
+ mtext(text=min(crossDownToUp),side=1,at=min(crossDownToUp),cex=.8,col=cols[1])
+ mtext(text=max(crossDownToUp),side=1,at=max(crossDownToUp),cex=.8,col=cols[1])
+ mtext(text="eccentric ",side=3,at=min(crossDownToUp),cex=.8,adj=1,col=cols[1])
+ mtext(text=" concentric ",side=3,at=max(crossDownToUp),cex=.8,adj=0,col=cols[1])
+ }
+ }
+
+ accel <- predict( speed, deriv=1 )
+ accel$y <- accel$y * 1000 #input data is in mm, conversion to m
+#print(c(knRanges$accely, max(accel$y), min(accel$y)))
+ force <- mass*accel$y
+ if(isJump)
+ force <- mass*(accel$y+g) #g:9.81 (used when movement is against gravity)
+ if(draw) {
+ ylim=c(-max(abs(range(force))),max(abs(range(force)))) #put 0 in the middle
+ if(knRanges[1] != "undefined")
+ ylim = knRanges$force
+ par(new=T)
+ if(highlight==FALSE)
+ plot(startX:length(force),force[startX:length(force)],type="l",xlim=c(1,length(a)),ylim=ylim,xlab="",ylab="",col=cols[2],lty=lty[2],lwd=1,axes=F)
+ else
+ plot(startX:length(force),force[startX:length(force)],type="l",xlim=c(1,length(a)),ylim=ylim,xlab="",ylab="",col="darkblue",lty=2,lwd=3,axes=F)
+ if(axesAndTitle)
+ axis(4, col=cols[2], lty=lty[2], line=2.8)
+ }
+
+
+ #mark when it's air and land
+ #if it was a eccon concentric-eccentric, will be useful to calculate flight time
+ #but this eccon will be not done
+ if(draw & (!superpose || (superpose & highlight)) & isJump) {
+ weight=mass*9.81
+ abline(h=weight,lty=1,col=cols[2]) #body force, lower than this, person in the air (in a jump)
+ takeoff = max(which(force>=weight))
+ abline(v=takeoff,lty=1,col=cols[2])
+ mtext(text="land ",side=3,at=takeoff,cex=.8,adj=1,col=cols[2])
+ mtext(text=" air ",side=3,at=takeoff,cex=.8,adj=0,col=cols[2])
+ text(x=length(force),y=weight,labels="Weight (N)",cex=.8,adj=c(.5,0),col=cols[2])
+ if(eccon=="ec-con") {
+ landing = min(which(force>=weight))
+ abline(v=landing,lty=1,col=cols[2])
+ mtext(text="air ",side=3,at=landing,cex=.8,adj=1,col=cols[2])
+ mtext(text=" land ",side=3,at=landing,cex=.8,adj=0,col=cols[2])
+ }
+ }
+ #forceToBodyMass <- force - weight
+ #b=extrema(forceToBodyMass)
+ #abline(v=b$cross[,1],lty=3,col=cols[2]) #body force, lower than this, person in the air (in a jump)
+ #text(x=(mean(b$cross[1,1],b$cross[1,2])+mean(b$cross[2,1],b$cross[2,2]))/2, y=weight,
+ # labels=paste("flight time:", mean(b$cross[2,1],b$cross[2,2])-mean(b$cross[1,1],b$cross[1,2]),"ms"),
+ # col=cols[2], cex=.8, adj=c(0.5,0))
+
+ #power #normalment m=massa barra + peses: F=m*a #com es va contra gravetat: F=m*a+m*g F=m*(a+g) #g sempre es positiva. a es negativa en la baixada de manera que en caiguda lliure F=0 #cal afegir la resistencia del encoder a la forÃa #PotÃncia P=F*V #si es treballa amb el pes corporal, cal afegir-lo
+
+ #F=m*a #bar
+ #F=(m*a)+(m*g) #jump m*(a+g) F=m*0
+
+ power <- force*speed$y
+ if(draw) {
+ ylim=c(-max(abs(range(power))),max(abs(range(power)))) #put 0 in the middle
+ if(knRanges[1] != "undefined")
+ ylim = knRanges$power
+ par(new=T);
+ if(highlight==FALSE)
+ plot(startX:length(power),power[startX:length(power)],type="l",xlim=c(1,length(a)),ylim=ylim,xlab="",ylab="",col=cols[3],lty=lty[3],lwd=1,axes=F)
+ else
+ plot(startX:length(power),power[startX:length(power)],type="l",xlim=c(1,length(a)),ylim=ylim,xlab="",ylab="",col="darkred",lty=2,lwd=3,axes=F)
+ if(axesAndTitle)
+ axis(4, col=cols[3], lty=lty[3], line=5.6, lwd=2)
+ }
+
+ #time to arrive to peak power
+ peakPowerT=which(power == max(power))
+ if(draw & !superpose) {
+ abline(v=peakPowerT, col=cols[3])
+ #points(peakPowerT, max(power),col=cols[3])
+ text(x=peakPowerT,y=max(power),labels=round(max(power),3), adj=c(0.5,0),cex=.8,col=cols[3])
+ mtext(text=peakPowerT,side=1,at=peakPowerT,cex=.8,col=cols[3])
+ }
+ #average power
+
+ meanPowerE = 0
+ if(eccon != "c")
+ meanPowerE = mean(abs(power[eccentric]))
+ meanPowerC = mean(abs(power[concentric]))
+ if(draw & !superpose) {
+ arrows(x0=1,y0=meanPowerE,x1=max(eccentric),y1=meanPowerE,col=cols[3],code=3)
+ text(x=mean(eccentric), y=meanPowerE, labels=paste("mean power:",round(meanPowerE,3)), adj=c(0.5,0),cex=.8,col=cols[3])
+ arrows(x0=min(concentric),y0=meanPowerC,x1=max(concentric),y1=meanPowerC,col=cols[3],code=3)
+ text(x=mean(concentric), y=meanPowerC, labels=paste("mean power:",round(meanPowerC,3)), adj=c(0.5,0),cex=.8,col=cols[3])
+ }
+ if(draw) {
+ if(legend & axesAndTitle) {
+ legendPos = "bottomleft"
+ if(eccon=="c")
+ legendPos = "bottomright"
+ legend(legendPos, xjust=1, legend=c("Distance","Speed","Force","Power"), lty=c(1,lty[1],lty[2],lty[3]),
+ lwd=c(1,1,1,2), col=c("black",cols[1],cols[2],cols[3]), title=paste("Smoothing:",smoothing), cex=1, bg="white")
+ #mtext(text="[ESC: Quit; mouse left: Zoom in; mouse right: Zoom out]",side=3)
+ }
+ }
+}
+
+paintPowerPeakPowerBars <- function(paf) {
+ pafColors=c("tomato1","tomato4",topo.colors(10)[3])
+ bp <- barplot(rbind(paf[,1],paf[,2]),beside=T,col=pafColors[1:2],width=c(1.4,.6),
+ names.arg=1:n,xlim=c(1,n*3+.5),xlab="",ylab="Power (W)")
+ par(new=T)
+ plot(bp[2,],paf[,3],type="o",lwd=2,xlim=c(1,n*3+.5),axes=F,xlab="",ylab="",col=pafColors[3])
+ legend("bottomleft",col=pafColors, lty=c(0,0,1), lwd=c(1,1,2), pch=c(15,15,NA), legend=c("Power","Peak Power", "Time at Peak Power"))
+ axis(4)
+ mtext("time at peak power (s)", side=4, line=3)
+}
+
+find.mfrow <- function(n) {
+ if(n<=3) return(c(1,n))
+ else if(n<=6) return(c(2,ceiling(n/2)))
+ else if(n<=8) return(c(2,ceiling(n/2)))
+ else return(c(3, ceiling(n/3)))
+}
+#concentric, eccentric-concentric, repetitions of eccentric-concentric
+#currently only used "c" and "ec-con". no need of ec-con-rep because c and ec-con are repetitive
+eccons=c("c","ec-con","ec-con-rep")
+
+mass = 79
+g = 9.81
+smoothingAll= 0.1
+#smoothingOne= 0.7 #good smoothing in ec-con is when speed crosses 0 in lowest and highests points encoder line
+minHeight= 300
+#file="data.txt"; isJump=TRUE
+#file="data_falla.txt"; isJump=FALSE #TODO em sembla que falla perque no hi ha cap curve, pq totes son mes petites que minHeight
+
+colSpeed="springgreen3"; colForce="blue2"; colPower="tomato2" #colors
+#colSpeed="black"; colForce="black"; colPower="black" #black & white
+cols=c(colSpeed,colForce,colPower); lty=rep(1,3)
+
+#--- user commands ---
+args <- commandArgs(TRUE)
+print(args)
+if(length(args) < 3) {
+# print("USAGE:\nRscript graph.R c superpose graph.png\neccons:curves, single, side, superpose, powerBars \nsingle and superpose needs a param at end (the jump):\nRscript graph.R c single graph.png 2\n")
+} else {
+ file=args[1]
+ outputGraph=args[2]
+ outputData1=args[3]
+ outputData2=args[4]
+ isJump=as.logical(args[5])
+ eccon=args[6]
+ analysis=args[7]
+ smoothingOne=args[8]
+ jump=args[9]
+ width=as.numeric(args[10])
+ height=as.numeric(args[11])
+
+ png(outputGraph, width=width, height=height)
+
+ rawdata=scan(file=file,sep=",")
+
+ titleType = "execution"
+ if(isJump)
+ titleType="jump"
+
+ curvesPlot = FALSE
+ if(analysis=="curves")
+ curvesPlot = TRUE
+ curves=findCurves(rawdata, eccon, minHeight, curvesPlot)
+ n=length(curves[,1])
+ for(i in 1:n) {
+ if(eccon=="c") {
+ curves[i,1]=reduceCurveBySpeed(curves[i,1],rawdata[curves[i,1]:curves[i,2]], smoothingAll)
+ if(curvesPlot)
+ abline(v=curves[i,1],col="red")
+ }
+ }
+
+ print(curves)
+
+ if(analysis=="single")
+ if(jump>0)
+ paint(rawdata, eccon, curves[jump,1],curves[jump,2],"undefined","undefined",FALSE,FALSE,
+ 1,curves[jump,3],smoothingOne,mass,paste(analysis,eccon,titleType,jump),TRUE,FALSE,TRUE,TRUE)
+ if(analysis=="side") {
+ #comparar 6 salts, falta que xlim i ylim sigui el mateix
+ par(mfrow=find.mfrow(n))
+ a=cumsum(rawdata)
+ yrange=c(min(a),max(a))
+ knRanges=kinematicRanges(rawdata,curves,mass,g)
+ for(i in 1:n) {
+ paint(rawdata, eccon, curves[i,1],curves[i,2],yrange,knRanges,FALSE,FALSE,
+ 1,curves[i,3],smoothingOne,mass,paste(titleType,i),TRUE,FALSE,TRUE,FALSE)
+ }
+ par(mfrow=c(1,1))
+ }
+ if(analysis=="superpose") { #TODO: fix on ec-con startH
+ #falta fer un graf amb les 6 curves sobreposades i les curves de potencia (per exemple) sobrepossades
+ #fer que acabin al mateix punt encara que no iniciin en el mateix
+ #arreglar que els eixos de l'esq han de seguir un ylim,pero els de la dreta un altre, basat en el que es vol observar
+ #fer que es pugui enviar colors que es vol per cada curva, o linetypes
+ wide=max(curves$end-curves$start)
+ a=cumsum(rawdata)
+ yrange=c(min(a),max(a))
+ knRanges=kinematicRanges(rawdata,curves,mass,g)
+ for(i in 1:n) {
+ #in superpose all jumps end at max height
+ #start can change, some are longer than other
+ #xmin and xmax should be the same for all in terms of X concordance
+ #but line maybe don't start on the absolute left
+ #this is controled by startX
+ startX = curves[i,1]-(curves[i,2]-wide)+1;
+ paint(rawdata, eccon, curves[i,2]-wide,curves[i,2],yrange,knRanges,TRUE,(i==jump),
+ startX,curves[i,3],smoothingOne,mass,paste(titleType,jump),TRUE,FALSE,(i==1),TRUE)
+ par(new=T)
+ }
+ par(new=F)
+ print(knRanges)
+ }
+ if(analysis=="powerBars") {
+ paf = data.frame()
+ for(i in 1:n) {
+ paf=rbind(paf,(powerBars(kinematics(rawdata[curves[i,1]:curves[i,2]], mass, g))))
+ }
+ paintPowerPeakPowerBars(paf)
+ }
+ if(analysis=="others") {
+ #revisar amb ec-con
+ i=2; eccon="ec-con"
+ curves=findCurves(rawdata, eccon, minHeight, TRUE)
+ paint(rawdata, eccon, curves[i,1],curves[i,2],"undefined","undefined",FALSE,FALSE,
+ 1,curves[i,3],smoothingOne,mass,paste(titleType,jump),TRUE,TRUE,TRUE,TRUE)
+
+ # png("graph.png", width=1020, height=732)
+ g(file, 1,5000, smoothingOne, mass, "Xavi peÃa performance")
+ # dev.off()
+ }
+ if(analysis=="exportCSV") {
+ export=cumsum(rawdata)
+ file="export.csv" #TODO change this, for not deleting last record
+ #TODO....
+ }
+ dev.off()
+}
+
+#warnings()
+
+
diff --git a/encoder/pyserial_pyper.py b/encoder/pyserial_pyper.py
new file mode 100644
index 0000000..e052134
--- /dev/null
+++ b/encoder/pyserial_pyper.py
@@ -0,0 +1,335 @@
+# encoding=utf-8
+#
+# This problem is for reading data form Chronopic.
+#
+# History:
+# 2011-09-01 Reading data.
+# 2011-12-27 add function: Recording if encoder changes the direction.
+
+
+
+import serial
+import sys
+from datetime import datetime
+from struct import unpack
+from pyper import *
+
+
+#import subprocess
+#import pygame.image
+#import pygame.display
+#import pygame
+#from pygame.locals import * #mouse and key definitions
+
+
+print(sys.argv)
+
+# ============
+# = Variable =
+# ============
+#record_time = 10000 # how long do you want to record (ms).
+outputFile = sys.argv[1]
+record_time = int(sys.argv[2])
+smoothingOne = float(sys.argv[3])
+
+delete_initial_time = 20 #delete first records because there's encoder bug
+#w_baudrate = 9600 # Setting the baudrate of Chronopic(115200)
+w_baudrate = 115200 # Setting the baudrate of Chronopic(115200)
+#w_serial_port = 4 # Setting the serial port (Windows), windows's device number need minus 1
+w_serial_port = "/dev/ttyUSB0" # Setting the serial port (Linux)
+direction_change_period = 25 # how long to recognize as change direction. (I am not sure if this describe correctly.)
+direction_change_count = 0
+direction_pull_to_push = 'pull_to_push' # if people change the motion for pull to push, record this value.
+direction_push_to_pull = 'push_to_pull' # if people change the motion for push to pull, record this value.
+direction_now = 1 # 1 or -1
+direction_last_ms = 1 # 1 or -1
+direction_completed = -1 # 1 or -1
+
+#TODO: do also something about don't accept a phase that has less tha X cm of distance.
+#This will be useful to know the start of movement
+
+frames_pull_top1 = list()
+frames_pull_top2 = list()
+frames_push_bottom1 = list()
+frames_push_bottom2 = list()
+previous_frame_change = 0
+
+#modes:
+#0: don't do calculations
+mode = 0
+
+lag=20
+
+
+#unused now
+def cumulative_sum(n):
+ cum_sum = []
+ y = 0
+ for i in n: # <--- i will contain elements (not indices) from n
+ y += i # <--- so you need to add i, not n[i]
+ cum_sum.append(y)
+ return cum_sum
+
+#https://wiki.archlinux.org/index.php/Color_Bash_Prompt#Prompt_escapes
+FALSE = 0
+TRUE = 1
+
+BLACK = 30
+RED = 31
+GREEN = 32
+BLUE = 34
+REDINV = 41
+GREENINV = 42
+BLUEINV = 44
+
+def colorize(text, color, bold):
+ ESCAPE = '%s[' % chr(27)
+ RESET = '%s0m' % ESCAPE
+ if(bold):
+ FORMAT = '1;%dm'
+ else:
+ FORMAT = '0;%dm'
+ return ESCAPE + (FORMAT % (color, )) + text + RESET
+
+
+def calculate_all_in_r(temp, top_values, bottom_values, direction_now, smoothingOne):
+ if (len(top_values)>0 and len(bottom_values)>0):
+ if direction_now == 1:
+ start=top_values[len(top_values)-1]
+ end=bottom_values[len(bottom_values)-1]
+ else:
+ start=bottom_values[len(bottom_values)-1]
+ end=top_values[len(top_values)-1]
+ myR.assign('smoothingOne',smoothingOne)
+ myR.assign('a',temp[start:end])
+ myR.run('a.cumsum <- cumsum(a)')
+ myR.run('range <- abs(a.cumsum[length(a)]-a.cumsum[1])')
+
+#TODO: this spar should be 0.7,configurable, try it
+#then data here and in graph.R will be the same
+
+ myR.run('speed <- smooth.spline( 1:length(a), a, spar=smoothingOne)')
+ myR.run('accel <- predict( speed, deriv=1 )')
+ myR.run('accel$y <- accel$y * 1000') #input data is in mm, conversion to m
+ myR.run('force <- mass*(accel$y+9.81)')
+ myR.run('power <- force*speed$y')
+ myR.run('meanPower <- mean(abs(power))')
+ myR.run('peakPower <- max(power)')
+ myR.run('peakPowerT=which(power == peakPower)')
+ meanSpeed = myR.get('mean(abs(speed$y))')
+ if direction_now == 1:
+ maxSpeed = myR.get('min(speed$y)')
+ phase = " down,"
+ phaseCol = colorize(phase,BLACK,FALSE)
+ else:
+ maxSpeed = myR.get('max(speed$y)')
+ phase = " up,"
+ phaseCol = colorize(phase,BLUE,TRUE)
+ phaseRange = myR.get('range')
+ meanPower = myR.get('meanPower')
+ peakPower = myR.get('peakPower')
+ peakPowerT = myR.get('peakPowerT')
+
+ meanSpeedCol = "%10.2f," % meanSpeed
+ meanPowerCol = "%10.2f," % meanPower
+ if(meanSpeed > 2): colSpeed = GREENINV
+ else: colSpeed = GREEN
+ if(meanPower > 3500): colPower = REDINV
+ else: colPower = RED
+
+ print phaseCol + "%6i," % phaseRange + colorize(meanSpeedCol,colSpeed,TRUE) + "%9.2f," % maxSpeed + colorize(meanPowerCol,colPower,TRUE) + "%10.2f," % peakPower + "%11i" % peakPowerT
+# print(phase, "%4i" % phaseRange, "%6.2f" % meanSpeed, "%6.2f" % maxSpeed,
+# "%7.2f" % meanPower, "%8.2f" % peakPower, "%4i" % peakPowerT)
+
+
+def calculate_range(temp_cumsum, top_values, bottom_values, direction_now):
+ if len(top_values)>0:
+ rmax=temp_cumsum[top_values[len(top_values)-1]]
+ if len(bottom_values)>0:
+ rmin=temp_cumsum[bottom_values[len(bottom_values)-1]]
+ else:
+ rmin=0
+## if(direction_now == 1): text="rangedown"
+## else: text="rangeup"
+# print(text,rmax-rmin)
+ return(rmax-rmin)
+
+#def update_graph(xmin, xmax):
+# subprocess.Popen([r"Rscript","graph.R",str(xmin),str(xmax)]).wait()
+# picture = pygame.image.load("graph.png")
+# pygame.display.set_mode(picture.get_size())
+# main_surface= pygame.display.get_surface()
+# main_surface.blit(picture, (0,0))
+# pygame.display.update()
+
+
+# ================
+# = Main Problem =
+# ================
+
+#try:
+if __name__ == '__main__':
+ #print "connecting with R"
+ myR = R()
+ #myR.run('library("EMD")') #cal per extrema, pero no per splines
+ mass = 70
+ myR.assign('mass',mass)
+ myR.run('weight=mass*9.81')
+ myR.assign('k',2)
+
+ # Initial serial
+ #print(sys.argv)
+ #if(len(sys.argv) == 2):
+ # file = open(sys.argv[1], 'w')
+ #else:
+ # file = open("data.txt", 'w')
+ file = open(outputFile, 'w')
+
+ ser = serial.Serial(w_serial_port)
+ ser.baudrate = w_baudrate
+ temp = list() #raw values
+ temp_cumsum = list() #cumulative sums of raw values
+ temp_cumsum.append(0)
+ temp_speed = list()
+ w_time = datetime.now().second
+ #print "start read data"
+ # Detecting if serial port is available and Recording the data from Chronopic.
+ for i in xrange(delete_initial_time):
+ #if ser.readable(): #commented because don't work on linux
+ ser.read()
+
+ print("phase, range, meanSpeed, maxSpeed, meanPower, peakPower, peakPowerT")
+ for i in xrange(record_time):
+ #if ser.readable(): #commented because don't work on linux
+ byte_data = ser.read()
+ # conver HEX to INT value
+ signedChar_data = unpack('b' * len(byte_data), byte_data)[0]
+
+ temp.append(signedChar_data)
+ if(i>0):
+ temp_cumsum.append(temp_cumsum[i-1]+signedChar_data)
+ if(i>lag):
+ temp_speed.append(1.0*(temp_cumsum[i]-temp_cumsum[i-lag])/lag)
+ else:
+ temp_speed.append(0)
+
+ # Judging if direction has changed
+ if signedChar_data != 0:
+ direction_now = signedChar_data / abs(signedChar_data) #1 (pull) or -1 (push)
+ if direction_now != direction_last_ms:
+ direction_last_ms = direction_now
+ direction_change_count = 0
+ elif direction_now != direction_completed:
+ #we cannot addd signedChar_data because then is difficult to come back n frames to know the max point
+ #direction_change_count = direction_change_count + signedChar_data
+ direction_change_count = direction_change_count + 1
+ if direction_change_count >= direction_change_period:
+
+ #k=cumulative_sum(temp[previous_frame_change:i-direction_change_period])
+ k=list(temp_cumsum[previous_frame_change:i-direction_change_period])
+
+ phase = 0
+ speed = 0
+
+ if(direction_now == 1):
+ #we are going up, we passed the ditection_change_count
+ #then we can record the bottom moment
+ #and print speed on going down
+ new_frame_change = previous_frame_change+k.index(min(k))
+ frames_push_bottom1.append(new_frame_change)
+ new_frame_change = previous_frame_change+len(k)-1-k[::-1].index(min(k))
+ frames_push_bottom2.append(new_frame_change)
+ phase = " down"
+ speed = min(temp_speed[previous_frame_change:new_frame_change])
+ else:
+ new_frame_change = previous_frame_change+k.index(max(k))
+ frames_pull_top1.append(new_frame_change)
+ new_frame_change = previous_frame_change+len(k)-1-k[::-1].index(max(k))
+ frames_pull_top2.append(new_frame_change)
+ phase = " up"
+ speed = max(temp_speed[previous_frame_change:new_frame_change])
+
+# print phase, "|" + "%(speed)6.2f" %{"speed":speed}, "|", calculate_range(temp_cumsum, frames_pull_top1, frames_push_bottom1, direction_now)
+
+ if len(frames_pull_top1)>0 and len(frames_push_bottom1)>0:
+ calculate_all_in_r(temp, frames_pull_top1, frames_push_bottom1,
+ direction_now, smoothingOne)
+
+ file.write(''+','.join([str(i) for i in temp[
+ previous_frame_change:new_frame_change
+ ]])+'')
+ file.write("\n")
+ file.flush()
+
+ previous_frame_change = new_frame_change
+ direction_change_count = 0
+ direction_completed = direction_now
+
+ w_time = datetime.now().second - w_time
+ ser.close()
+
+
+ #TODO: arreglar aixo per a que el darrer calculate_range mostri el ultim tram (encara que no hagi acabat)
+ if direction_completed == -1:
+ calculate_range(temp_cumsum, frames_pull_top1, temp_cumsum, 1)
+ else:
+ calculate_range(temp_cumsum, frames_push_bottom1, temp_cumsum, -1)
+
+ file.write(''+','.join([str(i) for i in temp[previous_frame_change:len(temp)]])+'')
+ file.flush()
+ file.close()
+ #print "data saved"
+
+ #print ("frames_pull_top1: ",frames_pull_top1)
+ #print ("frames_pull_top2: ",frames_pull_top2)
+ #print ("frames_push_bottom1: ",frames_push_bottom1)
+ #print ("frames_push_bottom2: ",frames_push_bottom2)
+
+# print "creating graph..."
+# update_graph(0,record_time)
+#
+# done = 0
+# mouse_pos=[0,0]
+# while not done:
+# for e in pygame.event.get():
+# if e.type == QUIT or (e.type == KEYUP and e.key == K_ESCAPE):
+# done = 1
+# break
+# elif e.type == MOUSEBUTTONDOWN and e.button == 1:
+# mouse_pos[:] = list(e.pos)
+# print mouse_pos[0]
+# mouse_pos[0] = mouse_pos[0]*record_time/1020 #mouse_pos scaled to signal width
+# print mouse_pos[0]
+# zoom_width=record_time/2
+# xmin=mouse_pos[0]-zoom_width/2
+# xmax=mouse_pos[0]+zoom_width/2
+# #TODO: do all this in R in an interactive way
+# #TODO: other click makes zoom in more
+# #TODO: or better, point with mouse and press 2,4,8 to zoom x times
+# if xmin < 0:
+# xmax += -xmin
+# xmin += -xmin
+# elif xmax > record_time:
+# xmin -= xmax-record_time
+# xmax -= xmax-record_time
+#
+# update_graph(xmin,xmax)
+# elif e.type == MOUSEBUTTONDOWN and (e.button == 2 or e.button == 3):
+# update_graph(0,record_time)
+
+
+ #print "CUMSUM ---------"
+ #print(temp_cumsum)
+ #print "SPEED ----------"
+ #print(temp_speed)
+ #print "HAZ COPIA DE data.txt !!!"
+ print "Done! Please, close this window."
+
+#except:
+# print "aarrgggggh!!"
+# print sys.exc_info()
+# ser.close()
+# file = open("data.txt", 'w')
+# for i in temp:
+# file.write(i)
+# file.close()
diff --git a/glade/chronojump.glade b/glade/chronojump.glade
index dde2a2a..b785ac3 100644
--- a/glade/chronojump.glade
+++ b/glade/chronojump.glade
@@ -14009,6 +14009,8 @@ by you</property>
<widget class="GtkNotebook" id="notebook_sup">
<property name="visible">True</property>
<property name="can_focus">True</property>
+ <property name="tab_hborder">12</property>
+ <property name="tab_vborder">4</property>
<signal name="switch_page" handler="on_notebook_sup_switch_page"/>
<child>
<widget class="GtkViewport" id="viewport_mode_small">
@@ -14318,9 +14320,246 @@ Chronopic</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label71">
+ <widget class="GtkAlignment" id="alignment20">
<property name="visible">True</property>
- <property name="label" translatable="yes">Work in progress</property>
+ <property name="top_padding">4</property>
+ <child>
+ <widget class="GtkFrame" id="frame17">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.69999998807907104</property>
+ <property name="shadow_type">out</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment22">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <widget class="GtkHBox" id="hbox81">
+ <property name="visible">True</property>
+ <property name="spacing">25</property>
+ <child>
+ <widget class="GtkHBox" id="hbox82">
+ <property name="visible">True</property>
+ <property name="spacing">20</property>
+ <child>
+ <widget class="GtkHBox" id="hbox83">
+ <property name="visible">True</property>
+ <property name="spacing">10</property>
+ <child>
+ <widget class="GtkRadioButton" id="radiobutton_encoder_capture_bar">
+ <property name="label" translatable="yes">Weight bar</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_radiobutton_encoder_capture_bar_toggled"/>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox73">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <child>
+ <widget class="GtkSpinButton" id="spin_encoder_bar_limit">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="adjustment">10 1 300 1 10 0</property>
+ <property name="climb_rate">1</property>
+ <property name="snap_to_ticks">True</property>
+ <property name="numeric">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label83">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Kg</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox85">
+ <property name="visible">True</property>
+ <property name="spacing">10</property>
+ <child>
+ <widget class="GtkRadioButton" id="radiobutton_encoder_capture_jump">
+ <property name="label" translatable="yes">Jump</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">radiobutton_encoder_capture_bar</property>
+ <signal name="toggled" handler="on_radiobutton_encoder_capture_jump_toggled"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox76">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <child>
+ <widget class="GtkLabel" id="label_encoder_person_weight">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">0</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label80">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">+</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkSpinButton" id="spin_encoder_jump_limit">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="adjustment">0 0 300 1 10 0</property>
+ <property name="climb_rate">1</property>
+ <property name="snap_to_ticks">True</property>
+ <property name="numeric">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label76">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Kg</property>
+ </widget>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVSeparator" id="vseparator2">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox86">
+ <property name="visible">True</property>
+ <property name="spacing">8</property>
+ <child>
+ <widget class="GtkLabel" id="label85">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Smoothing factor</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkSpinButton" id="spin_encoder_analyze_smooth">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="adjustment">0.69999999999999996 0 1 0.01 0.10000000000000001 0</property>
+ <property name="climb_rate">1</property>
+ <property name="digits">2</property>
+ <property name="snap_to_ticks">True</property>
+ <property name="numeric">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label71">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Main options</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
</widget>
<packing>
<property name="position">1</property>
@@ -22705,31 +22944,724 @@ on current Chronojump version.</property>
<widget class="GtkVBox" id="vbox4">
<property name="visible">True</property>
<child>
- <widget class="GtkLabel" id="label73">
+ <widget class="GtkNotebook" id="notebook2">
<property name="visible">True</property>
- <property name="label" translatable="yes">Work in progress</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">8</property>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label72">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Encoder stuff</property>
+ <property name="can_focus">True</property>
+ <property name="tab_hborder">6</property>
+ <child>
+ <widget class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <child>
+ <widget class="GtkVBox" id="vbox5">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <child>
+ <widget class="GtkFrame" id="frame16">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.69999998807907104</property>
+ <property name="shadow_type">out</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment19">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <widget class="GtkHBox" id="hbox72">
+ <property name="visible">True</property>
+ <property name="spacing">30</property>
+ <child>
+ <widget class="GtkHBox" id="hbox89">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <child>
+ <widget class="GtkRadioButton" id="radiobutton_encoder_concentric">
+ <property name="label" translatable="yes">Concentric</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="radiobutton_encoder_eccentric-concentric">
+ <property name="label" translatable="yes">Eccentric-concentric</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">radiobutton_encoder_concentric</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVSeparator" id="vseparator3">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox87">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <child>
+ <widget class="GtkLabel" id="label82">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Recording time</property>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox74">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <child>
+ <widget class="GtkSpinButton" id="spin_encoder_capture_time">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="adjustment">10 5 99 1 10 0</property>
+ <property name="climb_rate">1</property>
+ <property name="snap_to_ticks">True</property>
+ <property name="numeric">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label84">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">s</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox88">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <child>
+ <widget class="GtkLabel" id="label78">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Minimal height</property>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox75">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <child>
+ <widget class="GtkSpinButton" id="spin_encoder_capture_minimal_height">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="adjustment">30 1 300 1 10 0</property>
+ <property name="climb_rate">1</property>
+ <property name="snap_to_ticks">True</property>
+ <property name="numeric">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label81">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">cm</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="button_encoder_bells">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip" translatable="yes">Bells</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment21">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <widget class="GtkHBox" id="hbox90">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkImage" id="image_encoder_bell">
+ <property name="visible">True</property>
+ <property name="icon-size">2</property>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label86">
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label75">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Options</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox9">
+ <property name="visible">True</property>
+ <property name="layout_style">spread</property>
+ <child>
+ <widget class="GtkButton" id="button_encoder_capture">
+ <property name="label" translatable="yes">Capture from encoder</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="use_underline">True</property>
+ <signal name="clicked" handler="on_button_encoder_capture_clicked"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="button_encoder_recalculate">
+ <property name="label" translatable="yes">Recalculate</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="padding">8</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox8">
+ <property name="visible">True</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="width_request">200</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">etched-in</property>
+ <child>
+ <widget class="GtkTreeView" id="treeview_jumps1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="rules_hint">True</property>
+ <property name="enable_search">False</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox63">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkViewport" id="viewport_image_encoder_capture">
+ <property name="visible">True</property>
+ <property name="resize_mode">queue</property>
+ <child>
+ <widget class="GtkImage" id="image_encoder_capture">
+ <property name="visible">True</property>
+ <property name="stock">gtk-missing-image</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox41">
+ <property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <widget class="GtkButton" id="button_encoder_capture_zoom">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <accelerator key="z" signal="clicked"/>
+ <child>
+ <widget class="GtkImage" id="image_encoder_capture_zoom">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="button_encoder_capture_properties">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip" translatable="yes">Properties</property>
+ <child>
+ <widget class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="stock">gtk-properties</property>
+ <property name="icon-size">2</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label73">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Capture</property>
+ </widget>
+ <packing>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox6">
+ <property name="visible">True</property>
+ <property name="spacing">11</property>
+ <child>
+ <widget class="GtkVBox" id="vbox7">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkFrame" id="frame14">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.69999998807907104</property>
+ <property name="shadow_type">out</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment17">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <widget class="GtkHBox" id="hbox79">
+ <property name="visible">True</property>
+ <property name="spacing">30</property>
+ <child>
+ <widget class="GtkTable" id="table12">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <widget class="GtkRadioButton" id="radiobutton_encoder_analyze_powerbars">
+ <property name="label" translatable="yes">Show power bars</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_radiobutton_encoder_analyze_powerbars_toggled"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="radiobutton_encoder_analyze_single">
+ <property name="label" translatable="yes">Single curve</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">radiobutton_encoder_analyze_powerbars</property>
+ <signal name="toggled" handler="on_radiobutton_encoder_analyze_single_toggled"/>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="radiobutton_encoder_analyze_side">
+ <property name="label" translatable="yes">Side compare</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">radiobutton_encoder_analyze_powerbars</property>
+ <signal name="toggled" handler="on_radiobutton_encoder_analyze_side_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="radiobutton_encoder_analyze_superpose">
+ <property name="label" translatable="yes">Superpose</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">radiobutton_encoder_analyze_powerbars</property>
+ <signal name="toggled" handler="on_radiobutton_encoder_analyze_superpose_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVSeparator" id="vseparator1">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkTable" id="table11">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <widget class="GtkLabel" id="label_encoder_analyze_curve_num">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Curve number</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkSpinButton" id="spin_encoder_analyze_curve_num">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="adjustment">1 1 40 1 10 0</property>
+ <property name="climb_rate">1</property>
+ <property name="snap_to_ticks">True</property>
+ <property name="numeric">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options"></property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox80">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkButton" id="button_encoder_analyze">
+ <property name="label" translatable="yes">Analyze</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <signal name="clicked" handler="on_button_encoder_analyze_clicked"/>
+ </widget>
+ <packing>
+ <property name="padding">12</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label87">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Mode</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="padding">8</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox_image_encoder_analyze">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkViewport" id="viewport_image_encoder_analyze">
+ <property name="visible">True</property>
+ <property name="resize_mode">queue</property>
+ <child>
+ <widget class="GtkImage" id="image_encoder_analyze">
+ <property name="visible">True</property>
+ <property name="stock">gtk-missing-image</property>
+ <property name="icon-size">6</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVButtonBox" id="vbuttonbox2">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <widget class="GtkButton" id="button_encoder_analyze_zoom">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <accelerator key="z" signal="clicked"/>
+ <child>
+ <widget class="GtkImage" id="image_encoder_analyze_zoom">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label74">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Analyze</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox78">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label72">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Encoder stuff</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="position">3</property>
diff --git a/src/Makefile.am b/src/Makefile.am
index 43872a4..e6c1363 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -69,6 +69,7 @@ FILES = \
gui/chronojump.cs\
gui/chronopic.cs\
gui/confirm.cs\
+ gui/encoder.cs\
gui/error.cs\
gui/eventExecute.cs\
gui/eventGraphConfigure.cs\
@@ -167,6 +168,7 @@ FILES = \
../chronojump_server/ChronojumpServer.cs\
AssemblyInfo.cs\
chronojump.cs\
+ encoder.cs\
event.cs\
eventType.cs\
jump.cs\
diff --git a/src/chronojump.cs b/src/chronojump.cs
index 09f537f..939509d 100644
--- a/src/chronojump.cs
+++ b/src/chronojump.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) 2004-2009 Xavier de Blas <xaviblas gmail com>
+ * Copyright (C) 2004-2012 Xavier de Blas <xaviblas gmail com>
*/
@@ -151,6 +151,16 @@ public class ChronoJump
//to store user videos and photos
Util.CreateMultimediaDirsIfNeeded();
+ //to store encoder data and graphs
+ Util.CreateEncoderDirIfNeeded();
+
+//TODO: create encoder session dirs when load or create a session, or when use encoder with button capture_from_encoder
+//TODO: when a session is deleted, encoder data has to be deleted, also multimedia videos, I suppose. Show message to user warning about it
+//TODO: encoder sensitive when person is loaded
+//TODO: encoder weight auto written depending on person loaded, and changes if it changes person or weight
+
+
+
//move database to new location if chronojump version is before 0.7
moveDatabaseToNewLocationIfNeeded();
diff --git a/src/constants.cs b/src/constants.cs
index f105de5..dc2c9bd 100644
--- a/src/constants.cs
+++ b/src/constants.cs
@@ -559,4 +559,17 @@ public class Constants
public static string RunStartInitialSpeedYes = Catalog.GetString("Running start. Started with initial speed.");
public static string RunStartInitialSpeedNo = Catalog.GetString("Standing start. Started without initial speed.");
+
+ /*
+ * encoder storage
+ * chronojump / encoder / sessionID / data
+ * chronojump / encoder / sessionID / graphs
+ */
+
+ public static string EncoderScriptCapture = "/home/xavier/informatica/progs_meus/chronojump/chronojump/encoder/pyserial_pyper.py";
+ public static string EncoderScriptGraphCall = "/home/xavier/informatica/progs_meus/chronojump/chronojump/encoder/call_graph.py";
+ public static string EncoderDataTemp = "chronojump-last-encoder-data.txt";
+ public static string EncoderCurvesTemp = "chronojump-last-encoder-curves.txt";
+ public static string EncoderGraphTemp = "chronojump-last-encoder-graph.png";
+
}
diff --git a/src/encoder.cs b/src/encoder.cs
new file mode 100644
index 0000000..f0692d7
--- /dev/null
+++ b/src/encoder.cs
@@ -0,0 +1,92 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * ChronoJump is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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) 2004-2012 Xavier de Blas <xaviblas gmail com>
+ */
+
+using System;
+using System.Data;
+using System.Text; //StringBuilder
+
+using Mono.Unix;
+
+public class EncoderParams
+{
+ private int time;
+
+ private bool isJump;
+ private string contractionEC;
+ private string analysis;
+ private string smooth; //to pass always as "." to R
+ private int curve;
+ private int width;
+ private int height;
+
+ public EncoderParams(int time, string smooth)
+ {
+ this.time = time;
+ this.smooth = smooth;
+ }
+
+ public string ToString1 ()
+ {
+ return time.ToString() + " " + smooth;
+ }
+
+ public EncoderParams(bool isJump, string contractionEC, string analysis, string smooth, int curve, int width, int height)
+ {
+ this.isJump = isJump;
+ this.contractionEC = contractionEC;
+ this.analysis = analysis;
+ this.smooth = smooth;
+ this.curve = curve;
+ this.width = width;
+ this.height = height;
+ }
+
+ public string ToString2 ()
+ {
+ return isJump + " " + contractionEC + " " + analysis + " " +
+ smooth + " " + curve + " " + width + " " + height;
+ }
+
+ ~EncoderParams() {}
+}
+
+public class EncoderStruct
+{
+ public EncoderStruct() {
+ }
+
+ public string InputData;
+ public string OutputGraph;
+ public string OutputData1;
+ public string OutputData2;
+ public EncoderParams Ep;
+
+ public EncoderStruct(string InputData, string OutputGraph, string OutputData1, string OutputData2,
+ EncoderParams Ep)
+ {
+ this.InputData = InputData;
+ this.OutputGraph = OutputGraph;
+ this.OutputData1 = OutputData1;
+ this.OutputData2 = OutputData2;
+ this.Ep = Ep;
+ }
+
+ ~EncoderStruct() {}
+}
diff --git a/src/gui/chronojump.cs b/src/gui/chronojump.cs
index 8d864a1..adc201f 100644
--- a/src/gui/chronojump.cs
+++ b/src/gui/chronojump.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) 2004-2011 Xavier de Blas <xaviblas gmail com>
+ * Copyright (C) 2004-2012 Xavier de Blas <xaviblas gmail com>
*/
@@ -240,6 +240,10 @@ public partial class ChronoJumpWindow
[Widget] Gtk.Image image_reaction_times_zoom;
[Widget] Gtk.Image image_pulses_zoom;
[Widget] Gtk.Image image_multi_chronopic_zoom;
+
+ //encoder
+ [Widget] Gtk.Image image_encoder_capture_zoom;
+ [Widget] Gtk.Image image_encoder_analyze_zoom;
Random rand;
bool volumeOn;
@@ -271,6 +275,8 @@ public partial class ChronoJumpWindow
//multiChronopic
private TreeStore treeview_multi_chronopic_store;
private TreeViewMultiChronopic myTreeViewMultiChronopic;
+
+
//preferences variables
private static int prefsDigitsNumber;
@@ -683,6 +689,7 @@ public partial class ChronoJumpWindow
pixbuf = new Pixbuf (null, Util.GetImagePath(false) + "stock_bell.png");
image_jump_reactive_bell.Pixbuf = pixbuf;
image_run_interval_bell.Pixbuf = pixbuf;
+ image_encoder_bell.Pixbuf = pixbuf;
pixbuf = new Pixbuf (null, Util.GetImagePath(false) + "preferences-system.png");
image_jump_reactive_repair.Pixbuf = pixbuf;
@@ -715,6 +722,11 @@ public partial class ChronoJumpWindow
image_reaction_times_zoom.Pixbuf = pixbuf;
image_pulses_zoom.Pixbuf = pixbuf;
image_multi_chronopic_zoom.Pixbuf = pixbuf;
+
+ //encoder
+ pixbuf = new Pixbuf (null, Util.GetImagePath(false) + Constants.FileNameZoomInIcon);
+ image_encoder_capture_zoom.Pixbuf = pixbuf;
+ image_encoder_analyze_zoom.Pixbuf = pixbuf;
}
private void loadPreferences ()
@@ -4970,6 +4982,7 @@ Console.WriteLine("X");
extra_window_multichronopic_can_do(false);
} else {
button_execute_test.Sensitive = myTreeViewPersons.IsThereAnyRecord();
+ button_encoder_capture.Sensitive = myTreeViewPersons.IsThereAnyRecord();
}
stats_win_change_test_type(notebook_execute.CurrentPage);
@@ -5106,6 +5119,7 @@ Console.WriteLine("X");
hbox_this_test_buttons.Sensitive = false;
hbox_execute_test.Sensitive = false;
button_execute_test.Sensitive = false;
+ button_encoder_capture.Sensitive = false;
eventExecuteHideAllTables();
}
@@ -5129,6 +5143,7 @@ Console.WriteLine("X");
hbox_jumps.Sensitive = false;
hbox_jumps_rj.Sensitive = false;
button_execute_test.Sensitive = false;
+ button_encoder_capture.Sensitive = false;
notebook_execute.Sensitive = false;
notebook_results.Sensitive = false;
@@ -5143,6 +5158,7 @@ Console.WriteLine("X");
hbox_jumps.Sensitive = true;
hbox_jumps_rj.Sensitive = true;
button_execute_test.Sensitive = true;
+ button_encoder_capture.Sensitive = true;
notebook_execute.Sensitive = true;
notebook_results.Sensitive = true;
@@ -5161,6 +5177,8 @@ Console.WriteLine("X");
combo_pulses.Sensitive = true;
hbox_execute_test.Sensitive = true;
+
+ label_encoder_person_weight.Text = currentPersonSession.Weight.ToString();
}
private void sensitiveGuiYesEvent () {
@@ -5173,6 +5191,7 @@ Console.WriteLine("X");
frame_persons.Sensitive = false;
button_execute_test.Sensitive = false;
+ button_encoder_capture.Sensitive = false;
//hbox
hbox_jumps.Sensitive = false;
hbox_jumps_rj.Sensitive = false;
@@ -5196,6 +5215,7 @@ Console.WriteLine("X");
frame_persons.Sensitive = true;
button_execute_test.Sensitive = true;
+ button_encoder_capture.Sensitive = true;
//hbox
hbox_jumps.Sensitive = true;
hbox_jumps_rj.Sensitive = true;
diff --git a/src/gui/encoder.cs b/src/gui/encoder.cs
new file mode 100644
index 0000000..72b1bce
--- /dev/null
+++ b/src/gui/encoder.cs
@@ -0,0 +1,168 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * ChronoJump is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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) 2004-2012 Xavier de Blas <xaviblas gmail com>
+ */
+
+using System;
+using Gtk;
+using Gdk;
+using Glade;
+
+public partial class ChronoJumpWindow
+{
+ [Widget] Gtk.SpinButton spin_encoder_bar_limit;
+ [Widget] Gtk.SpinButton spin_encoder_jump_limit;
+ [Widget] Gtk.SpinButton spin_encoder_analyze_smooth;
+
+ [Widget] Gtk.Button button_encoder_capture;
+ [Widget] Gtk.Label label_encoder_person_weight;
+ [Widget] Gtk.RadioButton radiobutton_encoder_concentric;
+ [Widget] Gtk.RadioButton radiobutton_encoder_capture_bar;
+ [Widget] Gtk.Viewport viewport_image_encoder_capture;
+ [Widget] Gtk.Image image_encoder_bell;
+ [Widget] Gtk.Image image_encoder_capture;
+
+ [Widget] Gtk.RadioButton radiobutton_encoder_analyze_powerbars;
+ [Widget] Gtk.RadioButton radiobutton_encoder_analyze_single;
+ [Widget] Gtk.RadioButton radiobutton_encoder_analyze_side;
+ [Widget] Gtk.RadioButton radiobutton_encoder_analyze_superpose;
+ [Widget] Gtk.Label label_encoder_analyze_curve_num;
+ [Widget] Gtk.SpinButton spin_encoder_analyze_curve_num;
+ [Widget] Gtk.Viewport viewport_image_encoder_analyze;
+ [Widget] Gtk.Image image_encoder_analyze;
+
+
+ private string encoderEC="c"; //"c" or "ec"
+ private string encoderAnalysis="powerBars";
+
+//TODO: pass selected time
+//TODO:pass minimal height
+//
+//TODO: on capture only show ups if concentric
+
+ //TODO: que el curve no pugui ser mes alt de actual numero de curves, per tant s'ha de retornar algun valor. ha de canviar cada cop que hi ha un capture o recalculate
+
+ //TODO: campanes a l'encoder pq mostri colors i sons en funcio del que passa
+
+ public void on_radiobutton_encoder_capture_bar_toggled (object obj, EventArgs args) {
+ spin_encoder_bar_limit.Sensitive = true;
+ spin_encoder_jump_limit.Sensitive = false;
+ }
+ public void on_radiobutton_encoder_capture_jump_toggled (object obj, EventArgs args) {
+ spin_encoder_bar_limit.Sensitive = false;
+ spin_encoder_jump_limit.Sensitive = true;
+ }
+
+ //TODO: garantir path windows
+ void on_button_encoder_capture_clicked (object o, EventArgs args)
+ {
+ //TODO: que surti barra de progres de calculando... despres de capturar i boto de cerrar automatico
+ //TODO: i mostrar valors des de la gui (potser a zona dreta damunt del zoom)
+
+ //capture data
+ EncoderParams ep = new EncoderParams(
+ 4000, Util.ConvertToPoint((double) spin_encoder_analyze_smooth.Value)); //R decimal: '.'
+
+ EncoderStruct es = new EncoderStruct(
+ "", //no data input
+ "", //no graph ouptut
+ Util.GetEncoderDataTempFileName(), "", ep);
+
+ Util.RunPythonEncoder(Constants.EncoderScriptCapture, es, true);
+
+
+ if(radiobutton_encoder_concentric.Active)
+ encoderEC = "c";
+ else
+ encoderEC = "ec";
+
+ //show curves graph
+ int w = UtilGtk.WidgetWidth(viewport_image_encoder_capture)-2; //image is inside (is smaller than) viewport
+ int h = UtilGtk.WidgetHeight(viewport_image_encoder_capture)-2;
+
+ ep = new EncoderParams(
+ false, //isJump (1st) is not used in "curves"
+ encoderEC, "curves",
+ "0", 0, w, h); //smoothOne, and curve are not used in "curves"
+
+ es = new EncoderStruct(
+ Util.GetEncoderDataTempFileName(),
+ Util.GetEncoderGraphTempFileName(),
+ "NULL", "NULL", ep); //no data ouptut
+
+ Util.RunPythonEncoder(Constants.EncoderScriptGraphCall, es,false);
+
+ Pixbuf pixbuf = new Pixbuf (Util.GetEncoderGraphTempFileName()); //from a file
+ image_encoder_capture.Pixbuf = pixbuf;
+ }
+
+ //show curve_num only on simple and superpose
+ public void on_radiobutton_encoder_analyze_single_toggled (object obj, EventArgs args) {
+ label_encoder_analyze_curve_num.Sensitive=true;
+ spin_encoder_analyze_curve_num.Sensitive=true;
+ encoderAnalysis="single";
+ }
+
+ public void on_radiobutton_encoder_analyze_superpose_toggled (object obj, EventArgs args) {
+ label_encoder_analyze_curve_num.Sensitive=true;
+ spin_encoder_analyze_curve_num.Sensitive=true;
+ encoderAnalysis="superpose";
+ }
+ public void on_radiobutton_encoder_analyze_side_toggled (object obj, EventArgs args) {
+ label_encoder_analyze_curve_num.Sensitive=false;
+ spin_encoder_analyze_curve_num.Sensitive=false;
+ encoderAnalysis="side";
+ }
+ public void on_radiobutton_encoder_analyze_powerbars_toggled (object obj, EventArgs args) {
+ label_encoder_analyze_curve_num.Sensitive=false;
+ spin_encoder_analyze_curve_num.Sensitive=false;
+ encoderAnalysis="powerBars";
+ }
+
+ //TODO: garantir path windows
+ private void on_button_encoder_analyze_clicked (object o, EventArgs args)
+ {
+ if(radiobutton_encoder_concentric.Active)
+ encoderEC = "c";
+ else
+ encoderEC = "ec";
+
+ int w = UtilGtk.WidgetWidth(viewport_image_encoder_analyze)-2; //image is inside (is smaller than) viewport
+ int h = UtilGtk.WidgetHeight(viewport_image_encoder_analyze)-2;
+
+ EncoderParams ep = new EncoderParams(
+ !radiobutton_encoder_capture_bar.Active,
+ encoderEC, encoderAnalysis,
+ Util.ConvertToPoint((double) spin_encoder_analyze_smooth.Value), //R decimal: '.'
+ (int) spin_encoder_analyze_curve_num.Value, w, h);
+
+ EncoderStruct es = new EncoderStruct(
+ Util.GetEncoderDataTempFileName(),
+ Util.GetEncoderGraphTempFileName(),
+ "NULL", "NULL", ep); //no data ouptut
+
+ Util.RunPythonEncoder(Constants.EncoderScriptGraphCall, es, false);
+
+ //TODO pensar en si s'ha de fer 1er amb mida petita i despres amb gran (en el zoom), o si es una sola i fa alguna edicio
+ //TODO per l'anterior estaria be saber la mida de la image_encoder_analyze i passa-ho al call_graph.py
+ Pixbuf pixbuf = new Pixbuf (Util.GetEncoderGraphTempFileName()); //from a file
+ image_encoder_analyze.Pixbuf = pixbuf;
+ }
+
+}
+
diff --git a/src/gui/eventExecute.cs b/src/gui/eventExecute.cs
index 38e4cfa..498c078 100644
--- a/src/gui/eventExecute.cs
+++ b/src/gui/eventExecute.cs
@@ -60,7 +60,7 @@ public partial class ChronoJumpWindow
[Widget] Gtk.Button event_execute_button_cancel;
[Widget] Gtk.Button event_execute_button_finish;
[Widget] Gtk.Button event_execute_button_update;
-
+
[Widget] Gtk.Table event_execute_table_jump_simple;
[Widget] Gtk.Table event_execute_table_jump_reactive;
@@ -1876,7 +1876,7 @@ Log.WriteLine("Preparing reactive A");
void on_event_execute_button_help_clicked (object o, EventArgs args)
{
}
-
+
//projecte cubevirtual de juan gonzalez
diff --git a/src/util.cs b/src/util.cs
index 2d1fc19..da5cf67 100644
--- a/src/util.cs
+++ b/src/util.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) 2004-2009 Xavier de Blas <xaviblas gmail com>
+ * Copyright (C) 2004-2012 Xavier de Blas <xaviblas gmail com>
*/
using System;
@@ -759,8 +759,6 @@ public class Util
Path.GetTempPath(), fileName + GetMultimediaExtension(Constants.MultimediaItems.PHOTO));
}
-
-
public static string GetMultimediaExtension (Constants.MultimediaItems multimediaItem) {
if(multimediaItem == Constants.MultimediaItems.VIDEO)
return Constants.ExtensionVideo;
@@ -785,10 +783,66 @@ public class Util
File.Delete(fileName);
}
+ /********** end of multimedia paths ************/
- /********** end of multimedia paths ************/
+ /********** start of encoder paths ************/
+
+ /*
+ * encoder data and graphs are organized by sessions
+ * chronojump / encoder / sessionID / data
+ * chronojump / encoder / sessionID / graphs
+ */
+
+ public static string GetEncoderDir() {
+ return Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+ "Chronojump" + Path.DirectorySeparatorChar + "encoder");
+ }
+
+ //to store encoder data and graphs
+ public static void CreateEncoderDirIfNeeded () {
+ string [] dirs = { GetEncoderDir() };
+ foreach (string d in dirs) {
+ if( ! Directory.Exists(d)) {
+ Directory.CreateDirectory (d);
+ Log.WriteLine (string.Format("created dir: {0}", d));
+ }
+ }
+ }
+
+ public static string GetEncoderSessionDir (int sessionID) {
+ return GetEncoderDir() + Path.DirectorySeparatorChar + sessionID.ToString();
+ }
+
+ public static string GetEncoderSessionDataDir (int sessionID) {
+ return GetEncoderSessionDir(sessionID) + Path.DirectorySeparatorChar + "data";
+ }
+
+ public static string GetEncoderSessionGraphsDir (int sessionID) {
+ return GetEncoderSessionDir(sessionID) + Path.DirectorySeparatorChar + "graphs";
+ }
+
+ public static void CreateEncoderSessionDirsIfNeeded (int sessionID) {
+ string [] dirs = { GetEncoderSessionDir(sessionID),
+ GetEncoderSessionDataDir(sessionID), GetEncoderSessionGraphsDir(sessionID) };
+ foreach (string d in dirs) {
+ if( ! Directory.Exists(d)) {
+ Directory.CreateDirectory (d);
+ Log.WriteLine (string.Format("created dir: {0}", d));
+ }
+ }
+ }
+
+ public static string GetEncoderDataTempFileName() {
+ return Path.Combine(Path.GetTempPath(), Constants.EncoderDataTemp);
+ }
+ public static string GetEncoderGraphTempFileName() {
+ return Path.Combine(Path.GetTempPath(), Constants.EncoderGraphTemp);
+ }
+
+ /********** end of encoder paths ************/
public static string GetManualDir() {
//we are on:
@@ -843,7 +897,7 @@ public class Util
public static void RunRScript(string rScript){
ProcessStartInfo pinfo;
- Process r;
+ Process r;
string rBin="R";
//If output file is not given, R will try to write in the running folder
//in which we may haven't got permissions
@@ -867,6 +921,53 @@ public class Util
r.WaitForExit();
while (!File.Exists(outputFile));
}
+
+ //python program
+ public static void RunPythonEncoder(string pythonScript, EncoderStruct es, bool useTerminal) {
+ ProcessStartInfo pinfo;
+ Process p;
+ //If output file is not given, R will try to write in the running folder
+ //in which we may haven't got permissions
+
+ string pBin="python";
+ if(useTerminal) {
+ pBin="xterm";
+ }
+
+// if (IsWindows())
+// pBin=System.IO.Path.Combine(GetPrefixDir(), "bin/python.exe");
+
+ pinfo = new ProcessStartInfo();
+ pinfo.FileName=pBin;
+
+ string outputFileCheck = "";
+ if(useTerminal) {
+ pinfo.Arguments = "-hold -geometry 72x34+100+40 -fn *-fixed-*-*-*-20-* -e \"python " +
+ pythonScript + " " + es.OutputData1 + " " + es.Ep.ToString1() + "\"";
+ outputFileCheck = es.OutputData1;
+ } else {
+ pinfo.Arguments = pythonScript + " " + es.InputData + " " +
+ es.OutputGraph + " " + es.OutputData1 + " " + es.OutputData2 + " " + es.Ep.ToString2();
+ outputFileCheck = es.OutputGraph;
+ }
+
+ pinfo.CreateNoWindow = true;
+ pinfo.UseShellExecute = false;
+
+ Console.WriteLine("-------------------");
+ Console.WriteLine(outputFileCheck);
+ if (File.Exists(outputFileCheck))
+ File.Delete(outputFileCheck);
+
+ p = new Process();
+ p.StartInfo = pinfo;
+ p.Start();
+ p.WaitForExit();
+ while (!File.Exists(outputFileCheck));
+ }
+
+
+
/*
* currently not used, we copy the assemblies now
*
diff --git a/src/utilGtk.cs b/src/utilGtk.cs
index 27c2fa5..4197567 100644
--- a/src/utilGtk.cs
+++ b/src/utilGtk.cs
@@ -53,6 +53,13 @@ public class UtilGtk
//libmono-cairo2.0-cil
return Gdk.Display.Default.GetScreen(0).Height;
}
+
+ public static int WidgetWidth(Gtk.Widget w) {
+ return w.Allocation.Width;
+ }
+ public static int WidgetHeight(Gtk.Widget w) {
+ return w.Allocation.Height;
+ }
public static void IconWindow(Gtk.Window myWindow) {
Gdk.Pixbuf chronojumpIcon = new Gdk.Pixbuf (null, Constants.FileNameIcon);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]