changeset 45:d23685b9e766

Fixed the alignment error caluculations and added histogram plotting
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Tue, 08 May 2012 21:53:11 +0100
parents 73fbbc92fdfb
children ba36a1721538
files annotationCalculatorSrc/BeatAnnotationReader.cpp annotationCalculatorSrc/BeatAnnotationReader.h annotationCalculatorSrc/Histogram.cpp annotationCalculatorSrc/Histogram.h annotationCalculatorSrc/MatchMultitrackAnnotationReader.cpp annotationCalculatorSrc/MatchMultitrackAnnotationReader.h annotationCalculatorSrc/PlotTools.cpp annotationCalculatorSrc/PlotTools.h annotationCalculatorSrc/testApp.cpp annotationCalculatorSrc/testApp.h dev notes.txt src/AccompanimentSynchroniser.cpp src/AudioEventMatcher.cpp src/AudioEventMatcher.h src/testApp.cpp
diffstat 15 files changed, 494 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/annotationCalculatorSrc/BeatAnnotationReader.cpp	Fri May 04 16:00:33 2012 +0100
+++ b/annotationCalculatorSrc/BeatAnnotationReader.cpp	Tue May 08 21:53:11 2012 +0100
@@ -130,3 +130,91 @@
 	alignmentTimes.push_back(playedAlignTimes);
 }
 
+
+double BeatAnnotationReader::calculateMedianError(const DoubleVector& liveBeatTimes, const DoubleVector& groundTruthAlignment){
+	//use our alignment Times to calculate error rekative to these ground truth times
+	errors.clear();
+	
+	int alignmentLiveIndex = 0;
+	for (int i = 0;i < liveBeatTimes.size() && i < groundTruthAlignment.size();i++){
+		double time = liveBeatTimes[i];
+	
+		//now need alignment at this time
+		//recorded, i.e. MAP estimate alignment, is alignmentTimes[1];
+		//getAlignmentErrorAtTime(time);
+		
+		while (alignmentLiveIndex < alignmentTimes[0].size() && alignmentTimes[0][alignmentLiveIndex] < time) {
+			alignmentLiveIndex++;
+		}
+		
+		while (alignmentLiveIndex > 0 && alignmentTimes[0][alignmentLiveIndex] > time) {
+			alignmentLiveIndex--;
+		}
+		//now is less
+		double result = alignmentTimes[1][alignmentLiveIndex];
+		
+		double fractionOfNext = 0;
+		if (alignmentLiveIndex < alignmentTimes[0].size() + 1 && time > alignmentTimes[0][alignmentLiveIndex]){
+			double numerator = time - alignmentTimes[0][alignmentLiveIndex];
+			double denom = alignmentTimes[0][alignmentLiveIndex+1] - alignmentTimes[0][alignmentLiveIndex];
+			//printf("num %f / demon %f \n", numerator, denom);
+			fractionOfNext = (time - alignmentTimes[0][alignmentLiveIndex])/(alignmentTimes[0][alignmentLiveIndex+1] - alignmentTimes[0][alignmentLiveIndex]);
+			result += fractionOfNext * (alignmentTimes[1][alignmentLiveIndex+1] - alignmentTimes[1][alignmentLiveIndex]);
+		}
+		double error = result - groundTruthAlignment[i];//error relative to ground truth
+		error *= 1000.0;//now in ms
+		printf("live time %.4f align time %f ground truth %.3f error %.1f\n", time, result, groundTruthAlignment[i], error);
+	//	printf("time %.4f align time %f frac %.3f albelow %.4f above %.4f error %.2f\n", time, result, fractionOfNext, alignmentTimes[0][alignmentLiveIndex], alignmentTimes[0][alignmentLiveIndex+1], error);
+		
+	//	printf("aligns to above %.4f below %.4f\n", alignmentTimes[1][alignmentLiveIndex+1], alignmentTimes[1][alignmentLiveIndex]);
+		
+		errors.push_back(error);
+	}
+
+}
+
+
+
+double BeatAnnotationReader::calculateMedianError(const DoubleVector& liveBeatTimes, const DoubleVector& groundTruthAlignment, const DoubleVector& alignmentLiveTimes, const DoubleVector& alignmentRehearsalTimes){
+	//use our alignment Times to calculate error rekative to these ground truth times
+	errors.clear();
+	
+	int alignmentLiveIndex = 0;
+	for (int i = 0;i < liveBeatTimes.size() && i < groundTruthAlignment.size();i++){
+		double time = liveBeatTimes[i];
+		
+		//now need alignment at this time
+		//recorded, i.e. MAP estimate alignment, is alignmentRehearsalTimes;
+		//getAlignmentErrorAtTime(time);
+		
+		while (alignmentLiveIndex < alignmentLiveTimes.size() && alignmentLiveTimes[alignmentLiveIndex] < time) {
+			alignmentLiveIndex++;
+		}
+		
+		while (alignmentLiveIndex > 0 && alignmentLiveTimes[alignmentLiveIndex] > time) {
+			alignmentLiveIndex--;
+		}
+		//now is less
+		double result = alignmentRehearsalTimes[alignmentLiveIndex];
+		
+		double fractionOfNext = 0;
+		if (alignmentLiveIndex < alignmentLiveTimes.size() + 1 && time > alignmentLiveTimes[alignmentLiveIndex]){
+			double numerator = time - alignmentLiveTimes[alignmentLiveIndex];
+			double denom = alignmentLiveTimes[alignmentLiveIndex+1] - alignmentLiveTimes[alignmentLiveIndex];
+			//printf("num %f / demon %f \n", numerator, denom);
+			fractionOfNext = (time - alignmentLiveTimes[alignmentLiveIndex])/(alignmentLiveTimes[alignmentLiveIndex+1] - alignmentLiveTimes[alignmentLiveIndex]);
+			result += fractionOfNext * (alignmentRehearsalTimes[alignmentLiveIndex+1] - alignmentRehearsalTimes[alignmentLiveIndex]);
+		}
+		double error = result - groundTruthAlignment[i];//error relative to ground truth
+		error *= 1000.0;//now in ms
+		printf("live time %.4f align time %f ground truth %.3f error %.1f\n", time, result, groundTruthAlignment[i], error);
+		//	printf("time %.4f align time %f frac %.3f albelow %.4f above %.4f error %.2f\n", time, result, fractionOfNext, alignmentLiveTimes[alignmentLiveIndex], alignmentLiveTimes[alignmentLiveIndex+1], error);
+		
+		//	printf("aligns to above %.4f below %.4f\n", alignmentRehearsalTimes[alignmentLiveIndex+1], alignmentRehearsalTimes[alignmentLiveIndex]);
+		
+		errors.push_back(error);
+	}
+	
+}
+
+
--- a/annotationCalculatorSrc/BeatAnnotationReader.h	Fri May 04 16:00:33 2012 +0100
+++ b/annotationCalculatorSrc/BeatAnnotationReader.h	Tue May 08 21:53:11 2012 +0100
@@ -22,6 +22,7 @@
 public:	
 	typedef std::vector<double> DoubleVector;
 	DoubleVector beatTimes;
+	DoubleVector errors;
 	
 	typedef std::vector<DoubleVector> DoubleMatrix;
 	DoubleMatrix alignmentTimes;
@@ -30,5 +31,12 @@
 	void printBeatTimes();
 	
 	void readInMultiAlignmentFile(std::string pathName);
+	
+
+//	typedef vector<DoubleVector> DoubleMatrix;
+	double calculateMedianError(const DoubleVector& liveBeatTimes, const DoubleVector& groundTruthAlignment);
+	double calculateMedianError(const DoubleVector& liveBeatTimes, const DoubleVector& groundTruthAlignment, const DoubleVector& alignmentLiveTimes, const DoubleVector& alignmentRehearsalTimes);
+
+	//double getAlignmentErrorAtTime(const double& liveTime);
 };
 #endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/annotationCalculatorSrc/Histogram.cpp	Tue May 08 21:53:11 2012 +0100
@@ -0,0 +1,84 @@
+/*
+ *  Histogram.cpp
+ *  annotationResultCalculator
+ *
+ *  Created by Andrew on 08/05/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+#include "Histogram.h"
+
+Histogram::Histogram(){
+screenHeight = ofGetHeight();
+}
+
+void Histogram::createHistogram(const int& binWidthIn, const int& numberofBinsIn, DoubleVector& data){
+	numberofBins = numberofBinsIn;
+	binWidth = binWidthIn;
+	histogram.clear();
+	histogram.assign(numberofBins, 0);
+	maximum = 0;
+	double binPoint;
+	int bin = 0;
+	for (int i = 0;i < data.size();i++){
+		//find which bin it falls into.
+		//5 bins, width is 10
+		//then we start around zero for the 5+1/2 th, i.e. 3rd bin
+		//zero is the 5/2 th pt
+		
+		bin = 0;
+		binPoint = -1.0 * binWidth * ((double)numberofBins/2);
+		
+		if (data[i] >= binPoint){//i.e. falls inside
+			while (data[i] > (binPoint + binWidth) && bin < numberofBins) {
+				//printf("data pt %f bin %i binPt %.1f\n", data[i], bin, binPoint);
+				binPoint += binWidth;
+				bin++;				
+			}
+			
+			printf("data pt %f bin %i binPt %.1f\n", data[i], bin, binPoint);
+			
+			if (data[i] <= binPoint + binWidth){//in case outside range
+				histogram[bin]++;
+			}
+		}
+	}
+	
+	for (int k = 0; k < histogram.size();k++){
+		
+		if (histogram[k] > maximum)
+			maximum = histogram[k];
+		
+		printf("HISTO[%i] = %i\n", k, histogram[k]);
+	}
+	
+	
+}
+
+void Histogram::plotHistogram(){
+	plotHistogram(maximum);
+}
+
+void Histogram::plotHistogram(const double& maxHeight){
+	
+	double width = ofGetWidth();
+	double height = ofGetHeight();
+	screenHeight = ofGetHeight();
+	if (numberofBins > 0 && maxHeight > 0){
+		width /= numberofBins;
+		height /= maxHeight;
+		
+		for (int i = 0;i < numberofBins;i++){
+			ofRect(i * width, getY(histogram[i]*height), width, histogram[i]*height);
+		}
+		
+	}
+	
+}
+
+
+int Histogram::getY(const int& y){
+	return screenHeight - y;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/annotationCalculatorSrc/Histogram.h	Tue May 08 21:53:11 2012 +0100
@@ -0,0 +1,36 @@
+/*
+ *  Histogram.h
+ *  annotationResultCalculator
+ *
+ *  Created by Andrew on 08/05/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+
+
+#ifndef HISTOGRAM
+#define HISTOGRAM
+
+#include "ofMain.h"
+
+class Histogram{
+public:	
+	Histogram();
+	typedef std::vector<double> DoubleVector;
+	typedef std::vector<int> IntVector;
+	IntVector histogram;
+	
+	void createHistogram(const int& binWidth, const int& numberofBins, DoubleVector& data);
+	void plotHistogram();
+	void plotHistogram(const double& maxHeight);
+	
+	int numberofBins;
+	int binWidth;
+
+	double maximum;
+	
+	int getY(const int& y);
+	int screenHeight;
+};
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/annotationCalculatorSrc/MatchMultitrackAnnotationReader.cpp	Tue May 08 21:53:11 2012 +0100
@@ -0,0 +1,69 @@
+/*
+ *  MatchMultitrackAnnotationReader.cpp
+ *  annotationResultCalculator
+ *
+ *  Created by Andrew on 08/05/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+#include "MatchMultitrackAnnotationReader.h"
+
+
+
+void MatchMultitrackAnnotationReader::readInMatchFile(std::string& pathName){
+	
+	// "/Users/andrew/Documents/work/MuseScore/RWC/ANNOTATION/RM-C002_annotation+WavPos.csv"
+	matchData.clear();
+	matchLiveTimes.clear();
+	matchRehearsalTimes.clear();
+	
+	//	printf("MATCH : READ FILE %s\n", pathName.c_str());
+	ifstream file ( pathName.c_str());
+	string value, tmpLine;
+	stringstream iss;
+	int count = 0;
+	MatchNotation n;
+	while ( file.good() )
+	{
+		getline(file, tmpLine);
+		iss << tmpLine;
+		//			printf("tmp line %s\n", tmpLine.c_str());
+		while(getline ( iss, value, '\t' )){ // read a string until next comma: http://www.cplusplus.com/reference/string/getline/
+			//	cout << string( value, 1, value.length()-2 ); // display value removing the first and the last character from it
+			//		printf("line:%s\n", value.c_str());
+			string::size_type start = value.find_first_not_of(" ,\t\v\n");
+			string firstpart = value.substr(start, string::npos);
+			string::size_type end = firstpart.find_first_of(" ,\t\v\n");
+			string part = firstpart.substr(0, end);
+			string secondpart = firstpart.substr(end, string::npos);
+			start = secondpart.find_first_not_of(" ,\t\v\n");
+			secondpart = secondpart.substr(start , string::npos);
+			//		printf("part:%s,%s\n", part.c_str(), secondpart.c_str());
+			MatchNotation n;
+			n.firstTime = atof(part.c_str());
+			n.secondTime = atof(secondpart.c_str());
+			matchLiveTimes.push_back(atof(part.c_str()));
+			matchRehearsalTimes.push_back(atof(secondpart.c_str()));
+			
+			matchData.push_back(n);
+		}//end while reading line
+		iss.clear();
+		
+		
+	}//end while
+	
+	//	printAnnotations();
+	//	printf("There are %i MATCH annotations\n", (int)matchData.size());
+	
+}
+
+void MatchMultitrackAnnotationReader::printAnnotations(){
+	//rwcAnnotations.size()
+	for (int i = 0;i < min(200, (int)matchData.size());i++){
+		printf("MATCH audio times %f, midi played time %f \n", 
+			   matchData[i].firstTime,
+			   matchData[i].secondTime);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/annotationCalculatorSrc/MatchMultitrackAnnotationReader.h	Tue May 08 21:53:11 2012 +0100
@@ -0,0 +1,41 @@
+/*
+ *  MatchMultitrackAnnotationReader.h
+ *  annotationResultCalculator
+ *
+ *  Created by Andrew on 08/05/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+
+
+#ifndef MATCH_MULTITRACK_ANNOTATIONS
+#define MATCH_MULTITRACK_ANNOTATIONS
+
+#include "ofMain.h"
+
+#include <iostream>
+#include <fstream>
+using namespace std;
+
+struct MatchNotation {
+	
+	float firstTime;
+	float secondTime;
+};
+
+class MatchMultitrackAnnotationReader{
+public:
+	//matchAnnotations();
+	
+	void readInMatchFile(std::string& pathName);
+	//~Annotations();
+	void 	printAnnotations();
+	vector<MatchNotation> matchData;
+	
+	typedef vector<double> DoubleVector;
+	DoubleVector matchLiveTimes;
+	DoubleVector matchRehearsalTimes;
+	
+};
+#endif
\ No newline at end of file
--- a/annotationCalculatorSrc/PlotTools.cpp	Fri May 04 16:00:33 2012 +0100
+++ b/annotationCalculatorSrc/PlotTools.cpp	Tue May 08 21:53:11 2012 +0100
@@ -10,7 +10,7 @@
 #include "PlotTools.h"
 
 PlotTools::PlotTools(){
-
+	plotPoints = true;
 }
 
 void PlotTools::plotVector(const DoubleVector& d){
@@ -52,22 +52,26 @@
 void PlotTools::plotTwoVectors(const DoubleVector& d, const DoubleVector& h){
 	//just picks the min and max of each and plots with these as the width and height ranges.
 	plotTwoVectors(d, h, *(std::min_element( d.begin(), d.end() )),*(std::max_element( d.begin(), d.end()) ), 
-				   *(std::min_element( h.begin(), h.end() )),*(std::max_element( h.begin(), h.end()) ) );
+				   *(std::min_element( h.begin(), h.end() )),*(std::max_element( h.begin(), h.end()) ), false);
 	
 }
-void PlotTools::plotTwoVectors(const DoubleVector& d, const DoubleVector& h, const double& xStart, const double& xEnd, const double& yStart, const double& yEnd){
+void PlotTools::plotTwoVectors(const DoubleVector& d, const DoubleVector& h, const double& xStart, const double& xEnd, const double& yStart, const double& yEnd, const bool drawAxes){
 	//	printf("%f %f %f %f\n", xStart, xEnd, yStart, yEnd);
 	int startX, endX, startY, endY;
 	startX = 0;
 	while (d[startX] < xStart)
 		startX++;
 	
+		startX--;
+	
 	startX = max(0, (int) round(xStart));
 	endX = (int)d.size()-1;
 	
 	while (d[endX] > xEnd) {
 		endX--;
 	}
+	if (endX < d.size()-1)
+		endX++;
 	
 	//startX and endX are in terms of indices now...
 
@@ -89,12 +93,19 @@
 			double newYindex = (h[i] - yStart) * heightRatio;
 			double newXindex = (int)(xRatio * (d[i] - xStart));
 			ofLine(xIndex, getY(yIndex), newXindex, getY(newYindex));
+			
+			
+			if (plotPoints)
+				ofCircle(newXindex, getY(newYindex), 1);//then plots points too
+			
 			xIndex = newXindex;
 			yIndex = newYindex;
 		}//end for
 	
 		
 	//do axis
+		if (drawAxes){
+			
 		int wIndex, hIndex;
 		int numberOfPts = 5;
 		for (int x = 1; x < numberOfPts;x++){
@@ -121,6 +132,7 @@
 			ofLine(0, markIndex, 10, markIndex);
 			ofDrawBitmapString(ofToString(h[hIndex], 1), 2, markIndex);
 		}//end for y for axis
+	}//end draw axes
 		
 	}//end if yRange > 0
 	
@@ -130,8 +142,12 @@
 }
 
 
+
+
+
 int PlotTools::getY(const int& y){
 	return screenHeight - y;
 }
 
 
+
--- a/annotationCalculatorSrc/PlotTools.h	Fri May 04 16:00:33 2012 +0100
+++ b/annotationCalculatorSrc/PlotTools.h	Tue May 08 21:53:11 2012 +0100
@@ -24,10 +24,14 @@
 	void plotVector(const DoubleVector& d, const double& xStart, const double& xEnd, const double& yStart, const double& yEnd);
 	
 	void plotTwoVectors(const DoubleVector& d, const DoubleVector& h);
-	void plotTwoVectors(const DoubleVector& d, const DoubleVector& h, const double& xStart, const double& xEnd, const double& yStart, const double& yEnd);
+	void plotTwoVectors(const DoubleVector& d, const DoubleVector& h, const double& xStart, const double& xEnd, const double& yStart, const double& yEnd, const bool drawAxes);
 
 	double screenHeight;
 	double screenWidth;
 	int getY(const int& y);
+	bool plotPoints;
+	
+
+	
 };
 #endif
\ No newline at end of file
--- a/annotationCalculatorSrc/testApp.cpp	Fri May 04 16:00:33 2012 +0100
+++ b/annotationCalculatorSrc/testApp.cpp	Tue May 08 21:53:11 2012 +0100
@@ -4,25 +4,49 @@
 void testApp::setup(){
 	ofBackground(255);
 	
-	std::string path = "../../../data/marbleArch_6_beats.txt";
+	std::string path = "../../../data/marbleArch_4_beats.txt";
+//	path = "../../../data/marbleArchKick_take4.txt";
+	
 	beatReader.readInBeatsFile(path);
 	GroundTruth.push_back(beatReader.beatTimes);//so we have our first file list of beats
 	
 	//now get the second file beat list
-	path = "../../../data/marbleArch_4_beats.txt";//just the same one for the mo...
+	path = "../../../data/marbleArch_6_beats.txt";//just the same one for the mo...
+//	path = "../../../data/marbleArchKick_take6.txt";//annotated kick tracks
 	beatReader.readInBeatsFile(path);
 	GroundTruth.push_back(beatReader.beatTimes);//so we have our first file list of beats
 	
 	//so GroundTruth[0] is the DoubleVector of file 1 beats 
+	//this is the Live file - i.e. played along
 	//i.e. GT[0][0] - first, GT[0][1] second and so on
 	
-	path = "../../../data/marbleArchloaded6_live4.txt";
+//	path = "../../../data/marbleArchloaded6_live4.txt";
+	path = "../../../data/MarbleArch_live4_reh6_output.txt";
+	path = "../../../data/marbleArch_take4_to_take6_new_output.txt";
+	path = "../../../data/MarbleArch_live4_reh6_newOutput.txt";
 	//Then we need to know where our alignment path has gone and projected these positions to be
+	//this is the rehearsal file that was analysed
 	//so we need to load an alignment path
 	//then calculate the error histogram etc
 	beatReader.readInMultiAlignmentFile(path);
 
 	
+	beatReader.calculateMedianError(GroundTruth[0], GroundTruth[1], beatReader.alignmentTimes[0], beatReader.alignmentTimes[1]);
+	
+	histogramWidth = 10;
+	histogramBinNumber = 25;
+	
+	matchPath = "../../../data/MatchAlignments/marbleArchlive4_reh6_match_OB.out";
+	matchNotations.readInMatchFile(matchPath);
+	multiHistogram.createHistogram(histogramWidth, histogramBinNumber, beatReader.errors);
+	
+	printf("\n\nGET ERRORS FOR MATCH\n\n");
+	beatReader.calculateMedianError(GroundTruth[0], GroundTruth[1], matchNotations.matchLiveTimes, matchNotations.matchRehearsalTimes);
+	matchHistogram.createHistogram(histogramWidth, histogramBinNumber, beatReader.errors);
+	
+	screenToDraw = 1;
+
+	
 	xPlotMin = 0;
 	xPlotMax = 40;
 	yPlotMin = 0;
@@ -36,19 +60,42 @@
 
 //--------------------------------------------------------------
 void testApp::draw(){
+	switch (screenToDraw) {
+		case 0:
+			drawAlignmentVectors();
+			break;
+		case 1:
+			ofSetColor(0,0,255);
+			multiHistogram.plotHistogram();
+			break;
+		case 2:
+			ofSetColor(0,255,0);
+			matchHistogram.plotHistogram();
+			break;	
+	}
+}
 
+
+void  testApp::drawAlignmentVectors(){
+	
 	ofSetColor(0,0,0);
-//	plotter.plotVector(beatReader.beatTimes);
+	//	plotter.plotVector(beatReader.beatTimes);
 	int limit = 50;
-		//live is X
-		//rehearsal is Y
-		plotter.plotTwoVectors(GroundTruth[0], GroundTruth[1], xPlotMin, xPlotMax, yPlotMin, yPlotMax);
+	//live is X
+	//rehearsal is Y
+	plotter.plotTwoVectors(GroundTruth[0], GroundTruth[1], xPlotMin, xPlotMax, yPlotMin, yPlotMax, true);
+	
+	//x axis is the live time
 	
 	ofSetColor(0,0,200);
-	plotter.plotTwoVectors(beatReader.alignmentTimes[1], beatReader.alignmentTimes[0], xPlotMin, xPlotMax, yPlotMin, yPlotMax);
-
+	plotter.plotTwoVectors(beatReader.alignmentTimes[0], beatReader.alignmentTimes[1], xPlotMin, xPlotMax, yPlotMin, yPlotMax, false);
+	
 	ofSetColor(200,0,0);
-	plotter.plotTwoVectors(beatReader.alignmentTimes[2], beatReader.alignmentTimes[0], xPlotMin, xPlotMax, yPlotMin, yPlotMax);
+	plotter.plotTwoVectors(beatReader.alignmentTimes[0], beatReader.alignmentTimes[2], xPlotMin, xPlotMax, yPlotMin, yPlotMax, false);
+	
+	ofSetColor(0,200,0);
+	plotter.plotTwoVectors(matchNotations.matchLiveTimes, matchNotations.matchRehearsalTimes, xPlotMin, xPlotMax, yPlotMin, yPlotMax, false);
+	
 	
 }
 
@@ -58,11 +105,13 @@
 	if (key == OF_KEY_RIGHT){
 		xPlotMax += 20;
 		xPlotMin += 20;
+		getYvalues();
 	}
 	
-	if (key == OF_KEY_RIGHT){
+	if (key == OF_KEY_LEFT){
 		xPlotMin -= 20;
 		xPlotMax -= 20;
+		getYvalues();
 	}
 	
 	if (key == OF_KEY_UP){
@@ -74,6 +123,42 @@
 		xPlotMax = -1*xPlotMin + 2*xPlotMax ;
 		yPlotMax = -1*xPlotMin + 2*yPlotMax;
 	}
+		
+	if (key == 's'){
+		screenToDraw++;
+	
+		if (screenToDraw == NUMBER_OF_SCREENS)
+			screenToDraw = 0;
+		
+	}
+
+}
+
+void testApp::getYvalues(){
+//we have xmin and max
+//	need the y equivalent
+	int index = 0;
+	while (index < beatReader.alignmentTimes[0].size() && beatReader.alignmentTimes[0][index] < xPlotMin){
+		index++;
+		//printf("beat[%i]: %f\n", index, beatReader.alignmentTimes[0][index]);
+	}
+	
+	//printf("found index %i, size %i, at val %.3f\n", index, (int)beatReader.alignmentTimes[0].size(), beatReader.alignmentTimes[0][index]);
+	
+	yPlotMin = beatReader.alignmentTimes[1][index];
+	
+	while (index < beatReader.alignmentTimes[0].size() && beatReader.alignmentTimes[0][index] < xPlotMax)
+		index++;
+	
+	yPlotMax = beatReader.alignmentTimes[1][index];
+	
+	
+	printPlotValues();
+}
+
+void testApp::printPlotValues(){
+		printf("xmin %.0f, mxax %.0f\n", xPlotMin, xPlotMax);
+		printf("ymin %.0f, ymax %.0f\n", yPlotMin, yPlotMax);
 }
 
 //--------------------------------------------------------------
--- a/annotationCalculatorSrc/testApp.h	Fri May 04 16:00:33 2012 +0100
+++ b/annotationCalculatorSrc/testApp.h	Tue May 08 21:53:11 2012 +0100
@@ -3,7 +3,10 @@
 #include "ofMain.h"
 #include "BeatAnnotationReader.h"
 #include "PlotTools.h"
+#include "MatchMultitrackAnnotationReader.h"
+#include "Histogram.h"
 
+#define NUMBER_OF_SCREENS 3
 class testApp : public ofBaseApp{
 
 	public:
@@ -27,9 +30,21 @@
 	
 	BeatAnnotationReader beatReader;
 	
+	void drawAlignmentVectors();
+	
 	PlotTools plotter;
 	
 	double xPlotMin, xPlotMax, yPlotMin, yPlotMax;
+	void getYvalues();
+	void printPlotValues();
 	
+	std::string matchPath;
+	MatchMultitrackAnnotationReader matchNotations;
 		
+	Histogram multiHistogram;
+	Histogram matchHistogram;
+	
+	int screenToDraw;
+	int histogramWidth, histogramBinNumber;
+	
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev notes.txt	Tue May 08 21:53:11 2012 +0100
@@ -0,0 +1,3 @@
+TrackType determines which type of chromaOnset
+
+class ChromaOnset - method processFrame useful for the chromatogram creation
--- a/src/AccompanimentSynchroniser.cpp	Fri May 04 16:00:33 2012 +0100
+++ b/src/AccompanimentSynchroniser.cpp	Tue May 08 21:53:11 2012 +0100
@@ -9,6 +9,9 @@
 
 #include "AccompanimentSynchroniser.h"
 
+//recorded position millis is the current alignment position, sent from updateAlignment in event matcher
+//time sent is the live time since start of play
+
 AccompanimentSynchroniser::AccompanimentSynchroniser(){
 	sender.setup(HOST,  SENDER_PORT);
 	counter = 0;
--- a/src/AudioEventMatcher.cpp	Fri May 04 16:00:33 2012 +0100
+++ b/src/AudioEventMatcher.cpp	Tue May 08 21:53:11 2012 +0100
@@ -214,7 +214,7 @@
 	//THIS DEALS WITH WHERE WE ARE NOW! ON THE SCREEN
 	//DIFFERENT TO WHEN EVENTS COME IN AS THEY ARE TIMESTAMPED - SO EG A PITCH EVENT MAY ARRIVE 16 CHROMA FRAMES LATER - BIG DIFFERENCE
 	
-	int newTime = ofGetElapsedTimeMillis() - startTime;
+	int newTime = getTimeNow();
 //	double tmp = bayesianStruct.posterior.getIndexInRealTerms(bayesianStruct.posterior.MAPestimate);;
 //	double timetmp = (newTime - lastAlignmentTime);
 //	double speedtmp = bayesianStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesianStruct.relativeSpeedPosterior.MAPestimate);
@@ -234,6 +234,11 @@
 //	printf("ALIGN pos %f time diff %f (now %f , last %f)speed %f :: ALIGN BEST %f\n", tmp, timetmp, (double)ofGetElapsedTimeMillis(), lastAlignmentTime, speedtmp, currentAlignmentPosition);
 }
 
+int AudioEventMatcher::getTimeNow(){
+	return ofGetElapsedTimeMillis() - startTime;
+}
+
+
 void AudioEventMatcher::draw(){
 
 	//MAIN DRAW FUNCTION FOR ALL
@@ -261,6 +266,8 @@
 	drawRecordedTempo();
 	drawPlayingTempo();
 	
+	drawAlignmentTimes();
+	
 	
 }
 
@@ -392,7 +399,7 @@
 	ofDrawBitmapString(tmpStr, 20,140);
 	tmpStr = "best est "+ofToString(bayesianStruct.bestEstimate);
 	ofDrawBitmapString(tmpStr, 20, 180);
-	ofDrawBitmapString("screenwidth "+ofToString(screenWidthMillis), 20, 800);
+	//ofDrawBitmapString("screenwidth "+ofToString(screenWidthMillis), 20, 800);
 	
 	ofSetColor(255);
 	tmpStr = "pitch "+ofToString(recentPitch, 2);
@@ -411,6 +418,16 @@
 	
 }
 
+
+void AudioEventMatcher::drawAlignmentTimes(){
+	ofSetColor(255);
+	std::string dataString = "Live time "+ofToString(synchroniser.recordedPositionTimeSent);
+	dataString += ", Reh time "+ofToString(synchroniser.recordedPositionMillis);
+	ofDrawBitmapString(dataString, 10, ofGetHeight() - 20);
+
+}
+
+
 void AudioEventMatcher::newPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){
 	if (pitchIn > 0){
 	liveInput.addPitchEvent(pitchIn, timeIn);
@@ -480,7 +497,7 @@
 	//double quantity = 1;//
 	double quantity = 1*onsetLikelihoodToNoise;//BETTER CHANGE THIS BACK TOO..see below//likelihoodToNoiseRatio / numberOfMatches;
 	int numberOfMatchesFound = 0;
-
+	double nearestOnsetDistance = 1000;
 	double startMatchingTime = bayesianStruct.likelihood.offset;
 	double endMatchingTime = bayesianStruct.likelihood.offset + matchWindowWidth;
 	double millisTime = -1*INFINITY;//or 0 is fine
@@ -496,7 +513,8 @@
 				bayesianStruct.likelihood.addGaussianShapeFromRealTime(millisTime, onsetLikelihoodWidth,  quantity);
 				numberOfMatchesFound++;
 		//		printf("Adding Gaussian for onset at time %f offset %f\n", millisTime, bayesianStruct.likelihood.offset);
-				
+				if (fabs(currentAlignmentPosition - millisTime) < nearestOnsetDistance)
+					nearestOnsetDistance = currentAlignmentPosition - millisTime;
 			}//end if within limits (changed so it now is 4 sure)
 		}
 	}
@@ -517,7 +535,9 @@
 	
 	temporal.updateTempo(channel, timeIn);
 	}
+	int timeNow = getTimeNow();
 	
+	printf("Nearest onset is %.1f time is %i and alignemnt %i time now %i\n", nearestOnsetDistance, (int) timeIn, (int)currentAlignmentPosition, timeNow);
 }
 
 
--- a/src/AudioEventMatcher.h	Fri May 04 16:00:33 2012 +0100
+++ b/src/AudioEventMatcher.h	Tue May 08 21:53:11 2012 +0100
@@ -41,9 +41,11 @@
 	void drawPositionWindow();
 	void drawTrackLikelihoods();
 	void drawInfo();
+	void drawAlignmentTimes();
 	
 	void setWindowDimensions();
 	int getScreenWidthIndexOfEventTime(const double& time);
+	int getTimeNow();
 	
 	void newPitchEvent(const int& channel, const double& pitchIn, const double& timeIn);
 	void newKickEvent(const double& timeIn);
--- a/src/testApp.cpp	Fri May 04 16:00:33 2012 +0100
+++ b/src/testApp.cpp	Tue May 08 21:53:11 2012 +0100
@@ -103,8 +103,8 @@
 		if ( m.getAddress() == "/start" ){
 			printf("start!\n");
 			printf("STRART TIME IN %i\n", ofGetElapsedTimeMillis());
+			outputWriter.openFile();
 			eventMatcher.startPlaying();
-			outputWriter.openFile();
 			printf("TIME OUT %i\n", ofGetElapsedTimeMillis());
 		}