//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Sat Oct 4 05:50:39 PDT 2008 (extended version of scaperank)
// Last Modified: Sun Oct 5 16:40:18 PDT 2008
// Filename: ...sig/examples/all/ismir2008.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/ismir2008/ismir2008.cpp
// Syntax: C++; museinfo
//
// Description: Generate a comparison between multiple sets of
// number sequences from S0 through S4.
//
#include "Array.h"
#include "Options.h"
#include <math.h>
#ifndef OLDCPP
using namespace std;
#include <fstream>
#else
#include <fstream.h>
#endif
#include <stdlib.h> /* for qsort and bsearch functions */
#include <time.h> /* for random number seeding */
#include "museinfo.h" /* for humdrum file class */
///////////////////////////////////////////////////////////////////////////
class Performance {
public:
Performance(void);
~Performance();
int spine; // original spine from input
int process; // process = 0 means do not process in analysis
int random; // random = 1 => random testing sequence
int average; // average = 1 => average performance data
const char* pid; // performance id string, if given in input
const char* name; // performance name
Array<double> data; // array of performance data
};
Performance::Performance(void) {
spine = process = random = average = -1;
pid = "";
name = "";
data.setSize(1000);
data.setSize(0);
data.setGrowth(1000);
}
Performance::~Performance() {
data.setSize(0);
pid = "";
name = "";
spine = process = random = average = -1;
}
class Scape {
public:
Scape (void);
~Scape (void);
void setScapeSize (int aSize);
Array<Array<float> > data;
};
Scape::Scape(void) {
data.setSize(0);
}
Scape::~Scape() {
// do nothing;
}
void Scape::setScapeSize(int aSize) {
//cout << "SCAPE SIZE: " << aSize << endl;
data.setSize(aSize-1);
data.allowGrowth(0);
int i;
for (i=0; i<data.getSize(); i++) {
data[i].setSize(i+1);
data[i].allowGrowth(0);
data[i].setAll(-1000.0);
}
}
///////////////////////////////////////////////////////////////////////////
// function declarations:
void checkOptions(Options& opts, int argc, char** argv);
void example(void);
void usage(const char* command);
void readData(Array<Performance>& performances,
HumdrumFile& infile);
void createScore0Files(Array<Performance>& performances,
HumdrumFile& infile);
void printNumberDecimal(ofstream& outfile, double number,
int decimals);
void printScore(const char* filename, HumdrumFile& infile,
Array<Performance>& performances,
Array<Array<double> >& score0data,
int decimals);
void sortRanks(Array<int>& ranks, Array<double>& values);
double pearsonCorrelation(int size, double* a, double* b);
void calculateScore0Array(Array<Array<double> >& dataarray,
Array<Performance>& performances);
void calculateRankArray(Array<Array<int> >& rankarray,
Array<Array<double> >& scorearray);
double getMean(int size, double* a);
int numbersort(const void* A, const void* B);
void getRange(double& minn, double& maxx,
Array<double> data);
int performerNameQ(const char* string);
void printRank(const char* filename, HumdrumFile& infile,
Array<Performance>& performances,
Array<Array<int> >& rank0data);
void calculateAllCorrelations(Array<Array<Scape> >& correlations,
Array<Performance>& performances);
void calculateCorrelationLayer(Scape& scape, Performance& a,
Performance& b);
void calculateType1Scores(Array<Array<double> >& score1data,
Array<Array<Scape> >& correlations,
Array<Performance>& perfs);
void calculateType1ScoreSingle(Array<double>& performancedata,
Array<Array<Scape> >& correlations,
int reference,
Array<int>& masklayer);
int getMaxCorrIndex(Array<Array<Scape> >& correlations,
int reference, int scaperow, int scapecol,
Array<int>& masklayer);
void calculateScore0Test(Array<Array<double> >& score0data,
Array<Array<Scape> >& correlations);
double getCorrelation(int row, int col, int scaperow, int scapecol,
Array<Array<Scape> >& correlations);
void findBestMatch(Array<Array<Scape> >& correlations,
Array<int>& masklayer, int& bestmatch,
double& bestscore, int reference);
void calculateType2ScoresAndRanks(Array<Array<double> >& score2data,
Array<Array<int> >& rank2data,
Array<Array<double> >& score1data,
Array<Array<int> >& rank1data,
Array<Array<Scape> >& correlations,
Array<Performance>& perfs);
void calculateType2ScoresAndRanksSingle(Array<double>& score2data,
Array<int>& rank2data,
Array<int>& masklayer,
Array<Array<Scape> >& correlations,
int reference);
void calculateType3Scores(Array<Array<double> >& score3data,
Array<Array<int> >& rank2data,
Array<Array<Scape> >& correlations,
Array<Performance>& perfs);
void calculateType4Scores(Array<Array<double> >& score4data,
Array<Array<double> >& score3data);
void removeBetterHalfFromMaskLayer(Array<int>& masklayer,
Array<int>& rank2data);
void calculateType3ScoreSingle(Array<double>& score3data,
Array<int>& masklayer,
Array<Array<Scape> >& correlations,
int reference);
// User interface variables:
Options options;
int score0q = 0; // used with --s0 (correlation score)
int rank0q = 0; // used with --r0 (correlation score)
int score1q = 0; // used with --s1 (correlation score)
int rank1q = 0; // used with --r1 (correlation score)
int score2q = 0; // used with --s2 (correlation score)
int rank2q = 0; // used with --r2 (correlation score)
int score3q = 0; // used with --s3 (correlation score)
int rank3q = 0; // used with --r3 (correlation score)
int score4q = 0; // used with --s4 (correlation score)
int rank4q = 0; // used with --r4 (correlation score)
const char* filebase = "data"; // used with -b: output file basename
int level = 0;
///////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv) {
// process the command-line options
checkOptions(options, argc, argv);
HumdrumFile infile;
Array<Performance> performances;
int i;
const char* hum_filename = "";
if (options.getArgCount() <= 0) {
hum_filename = "<STDIN>";
} else {
hum_filename = options.getArg(1);
}
infile.read(hum_filename);
readData(performances, infile);
if (level < 0) { // finished calculating everything requested
std::cout << "Warning: no calculations done" << std::endl;
exit(0);
}
// calculate score 0 data: /////////////////////////////////////////
Array<Array<double> > score0data;
Array<Array<int> > rank0data;
char filename[1024] = {0};
calculateScore0Array(score0data, performances);
calculateRankArray(rank0data, score0data);
if (score0q) {
strcpy(filename, filebase);
strcat(filename, "-s0.txt");
cout << "Storing score-0 data in " << filename << endl;
printScore(filename, infile, performances, score0data, 3);
}
if (rank0q) {
strcpy(filename, filebase);
strcat(filename, "-r0.txt");
cout << "Storing score-0 ranks in " << filename << endl;
printRank(filename, infile, performances, rank0data);
}
if (level == 0) { // finished calculating everything requested
exit(0);
}
// prepare correlation data: ///////////////////////////////////////
cout << "Calculating correlation data" << endl;
Array<Array<Scape> > correlations;
calculateAllCorrelations(correlations, performances);
// calculate score 1 data: /////////////////////////////////////////
cout << "Calculating Score 1 data:" << endl;
Array<Array<double> > score1data;
Array<Array<int> > rank1data;
score1data.setSize(performances.getSize());
score1data.allowGrowth(0);
for (i=0; i<score1data.getSize(); i++) {
score1data[i].setSize(score1data.getSize());
score1data[i].allowGrowth(0);
}
calculateType1Scores(score1data, correlations, performances);
calculateRankArray(rank1data, score1data);
if (score1q) {
strcpy(filename, filebase);
strcat(filename, "-s1.txt");
cout << "Storing score-1 data in " << filename << endl;
printScore(filename, infile, performances, score1data, 3);
}
if (rank1q) {
strcpy(filename, filebase);
strcat(filename, "-r1.txt");
cout << "Storing score-1 ranks in " << filename << endl;
printRank(filename, infile, performances, rank1data);
}
if (level == 1) { // finished calculating everything requested
exit(0);
}
// calculate score 2 data: /////////////////////////////////////////
cout << "Calculating Score 2 data:" << endl;
Array<Array<double> > score2data;
Array<Array<int> > rank2data;
score2data.setSize(performances.getSize());
score2data.allowGrowth(0);
rank2data.setSize(performances.getSize());
rank2data.allowGrowth(0);
for (i=0; i<score2data.getSize(); i++) {
score2data[i].setSize(score2data.getSize());
score2data[i].allowGrowth(0);
score2data[i].setAll(-100);
rank2data[i].setSize(score2data.getSize());
rank2data[i].allowGrowth(0);
rank2data[i].setAll(-100);
}
calculateType2ScoresAndRanks(score2data, rank2data,
score1data, rank1data, correlations, performances);
if (score2q) {
strcpy(filename, filebase);
strcat(filename, "-s2.txt");
cout << "Storing score-2 data in " << filename << endl;
printScore(filename, infile, performances, score2data, 3);
}
if (rank2q) {
strcpy(filename, filebase);
strcat(filename, "-r2.txt");
cout << "Storing score-2 ranks in " << filename << endl;
printRank(filename, infile, performances, rank2data);
}
if (level == 2) { // finished calculating everything requested
exit(0);
}
// calculate score 3 data: /////////////////////////////////////////
cout << "Calculating Score 3 data:" << endl;
Array<Array<double> > score3data;
Array<Array<int> > rank3data;
score3data.setSize(performances.getSize());
score3data.allowGrowth(0);
rank3data.setSize(performances.getSize());
rank3data.allowGrowth(0);
for (i=0; i<score3data.getSize(); i++) {
score3data[i].setSize(score3data.getSize());
score3data[i].allowGrowth(0);
score3data[i].setAll(-100);
rank3data[i].setSize(score3data.getSize());
rank2data[i].allowGrowth(0);
rank3data[i].setAll(-100);
}
calculateType3Scores(score3data, rank2data, correlations, performances);
calculateRankArray(rank3data, score3data);
if (score3q) {
strcpy(filename, filebase);
strcat(filename, "-s3.txt");
cout << "Storing score-3 data in " << filename << endl;
printScore(filename, infile, performances, score3data, 3);
}
if (rank3q) {
strcpy(filename, filebase);
strcat(filename, "-r3.txt");
cout << "Storing score-3 ranks in " << filename << endl;
printRank(filename, infile, performances, rank3data);
}
if (level == 3) { // finished calculating everything requested
exit(0);
}
// calculate score 4 data: /////////////////////////////////////////
cout << "Calculating Score 4 data:" << endl;
Array<Array<double> > score4data;
Array<Array<int> > rank4data;
calculateType4Scores(score4data, score3data);
calculateRankArray(rank4data, score4data);
if (score4q) {
strcpy(filename, filebase);
strcat(filename, "-s4.txt");
cout << "Storing score-4 data in " << filename << endl;
printScore(filename, infile, performances, score4data, 3);
}
if (rank4q) {
strcpy(filename, filebase);
strcat(filename, "-r4.txt");
cout << "Storing score-4 ranks in " << filename << endl;
printRank(filename, infile, performances, rank4data);
}
return 0;
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// calculateType4Scores --
//
void calculateType4Scores(Array<Array<double> >& score4data,
Array<Array<double> >& score3data) {
score4data.setSize(score3data.getSize());
score4data.allowGrowth(0);
int i, j;
for (i=0; i<score4data.getSize(); i++) {
score4data[i].setSize(score4data.getSize());
score4data[i].allowGrowth(0);
score4data[i].setAll(-1969);
}
for (i=0; i<score4data.getSize(); i++) {
for (j=0; j<i; j++) {
score4data[i][j] = sqrt(score3data[i][j] * score3data[j][i]);
score4data[j][i] = score4data[i][j];
}
}
for (i=0; i<score4data.getSize(); i++) {
score4data[i][i] = 1.0;
}
}
//////////////////////////////
//
// calculateType3Scores --
//
void calculateType3Scores(Array<Array<double> >& score3data,
Array<Array<int> >& rank2data, Array<Array<Scape> >& correlations,
Array<Performance>& perfs) {
int i;
Array<Array<int> > masklayer;
masklayer.setSize(score3data.getSize());
masklayer.allowGrowth(0);
for (i=0; i<masklayer.getSize(); i++) {
masklayer[i].setSize(masklayer.getSize());
masklayer[i].allowGrowth(0);
masklayer[i].setAll(1);
removeBetterHalfFromMaskLayer(masklayer[i], rank2data[i]);
}
for (i=0; i<score3data.getSize(); i++) {
cout << "\t";
if (strcmp(perfs[i].name, "") == 0) {
cout << i;
} else {
cout << perfs[i].name;
}
cout << endl;
calculateType3ScoreSingle(score3data[i], masklayer[i], correlations, i);
}
}
//////////////////////////////
//
// removeBetterHalfFromMaskLayer -- remove better matches from
// analysis (added back later one-by-one).
//
void removeBetterHalfFromMaskLayer(Array<int>& masklayer,
Array<int>& rank2data) {
int i;
int cutoff = rank2data.getSize()/2;
for (i=0; i<masklayer.getSize(); i++) {
if (rank2data[i] < cutoff) {
masklayer[i] = 0;
}
}
}
//////////////////////////////
//
// calculateType2ScoresAndRanks --
//
void calculateType2ScoresAndRanks(Array<Array<double> >& score2data,
Array<Array<int> >& rank2data, Array<Array<double> >& score1data,
Array<Array<int> >& rank1data, Array<Array<Scape> >& correlations,
Array<Performance>& perfs) {
int i, j;
Array<Array<int> > masklayer;
masklayer.setSize(score2data.getSize());
masklayer.allowGrowth(0);
for (i=0; i<masklayer.getSize(); i++) {
masklayer[i].setSize(masklayer.getSize());
masklayer[i].allowGrowth(0);
masklayer[i].setAll(1);
masklayer[i][i] = 0;
}
// store best matches from score1data
for (i=0; i<rank1data.getSize(); i++) {
for (j=0; j<rank1data[0].getSize(); j++) {
if (rank1data[i][j] == 1) {
score2data[i][j] = score1data[i][j];
rank2data[i][j] = rank1data[i][j];
masklayer[i][j] = 0;
}
}
}
for (i=0; i<score2data.getSize(); i++) {
cout << "\t";
if (strcmp(perfs[i].name, "") == 0) {
cout << i;
} else {
cout << perfs[i].name;
}
cout << endl;
calculateType2ScoresAndRanksSingle(score2data[i], rank2data[i],
masklayer[i], correlations, i);
}
}
//////////////////////////////
//
// calculateType2ScoresAndRanksSingle -- top match is already stored
// (and self-matching is disabled).
//
void calculateType2ScoresAndRanksSingle(Array<double>& score2data,
Array<int>& rank2data, Array<int>& masklayer,
Array<Array<Scape> >& correlations, int reference) {
int i;
int iterations = score2data.getSize() - 3;
// minus one for self,
// minus one for previously found score1data
// minus one for very last case
int rankcounter = 2; // #0 = self; #1 = best match from before
int bestmatch;
double bestscore;
for (i=0; i<iterations; i++) {
findBestMatch(correlations, masklayer, bestmatch, bestscore, reference);
if (masklayer[bestmatch] != 1) {
cout << "ERROR CASE 1" << endl;
cout << "Reference = " << reference << endl;
cout << "Bestmatch = " << bestmatch << endl;
cout << "Bestscore = " << bestscore << endl;
cout << "masklayer[bestmatch] = " << masklayer[bestmatch] << endl;
exit(1);
}
masklayer[bestmatch] = 0;
if (rank2data[bestmatch] >= 0) {
cout << "ERROR CASE 2" << endl;
exit(2);
}
rank2data[bestmatch] = rankcounter++;
score2data[bestmatch] = bestscore;
}
// add last match, which must have a score of 1.0 (so don't calculate)
Array<int> templastcount;
templastcount = masklayer;
int lastcount = 0;
for (i=0; i<masklayer.getSize(); i++) {
if (masklayer[i]) {
masklayer[i] = 0;
score2data[i] = 1.0;
rank2data[i] = rankcounter;
lastcount++;
}
}
if (lastcount != 1) {
cout << "ERROR CASE 3" << endl;
cout << "Lastcount is " << lastcount << " but expected 1" << endl;
cout << "Masklayer info: " << endl;
for (i=0; i<templastcount.getSize(); i++) {
cout << " " << i << ":" << templastcount[i] << endl;
}
cout << endl;
exit(3);
}
// scale rank2values by their best match value to minimize tail of scores
double dcount = score2data.getSize();
for (i=0; i<dcount; i++) {
score2data[i] = score2data[i] * (dcount-rank2data[i])/dcount;
}
// no need to sort rank2data since best matches were found sequentially
// make self-match score 1.0 and its ranking be 0:
score2data[reference] = 1.0;
rank2data[reference] = 0;
}
//////////////////////////////
//
// calculateType3ScoreSingle --
//
void calculateType3ScoreSingle(Array<double>& score3data, Array<int>& masklayer,
Array<Array<Scape> >& correlations, int reference) {
Array<double> score1data;
score1data.setSize(masklayer.getSize());
score1data.allowGrowth(0);
score1data.setAll(-1000);
int arraysize = masklayer.getSize();
int i;
for (i=0; i<arraysize; i++) {
if (i == reference) {
continue;
}
if (masklayer[i] == 1) {
continue;
}
masklayer[i] = 1;
calculateType1ScoreSingle(score1data, correlations, reference, masklayer);
score3data[i] = score1data[i];
masklayer[i] = 0;
}
// calculate the scores of the background noise:
calculateType1ScoreSingle(score1data, correlations, reference, masklayer);
for (i=0; i<arraysize; i++) {
if (masklayer[i] == 1) {
score3data[i] = score1data[i];
}
}
// set the score for self-matching to 1.0:
score3data[reference] = 1.0;
}
//////////////////////////////
//
// findBestMatch --
//
void findBestMatch(Array<Array<Scape> >& correlations, Array<int>& masklayer,
int& bestmatch, double& bestscore, int reference) {
Array<double> score1data;
score1data.setSize(masklayer.getSize());
score1data.allowGrowth(0);
score1data.setAll(-1000);
calculateType1ScoreSingle(score1data, correlations, reference, masklayer);
bestmatch = -1000;
bestscore = -1000.0;
int i;
for (i=1; i<score1data.getSize(); i++) {
if (masklayer[i] == 0) {
continue;
}
if (bestscore < score1data[i]) {
bestscore = score1data[i];
bestmatch = i;
}
}
}
//////////////////////////////
//
// calculateScore0Test --
//
void calculateScore0Test(Array<Array<double> >& score0data,
Array<Array<Scape> >& correlations) {
int i, j;
for (i=0; i<score0data.getSize(); i++) {
for (j=0; j<score0data.getSize(); j++) {
score0data[i][j] = getCorrelation(i, j, 0, 0, correlations);
}
}
}
//////////////////////////////
//
// getCorrelation --
//
double getCorrelation(int row, int col, int scaperow, int scapecol,
Array<Array<Scape> >& correlations) {
int a;
int b;
if (row < col) {
a = col;
b = row;
} else if (row > col) {
a = row;
b = col;
} else {
return 1.0;
}
//cout << "correlation[" << row << "][" << col << "][" << scaperow
// << "][" << scapecol << "] = "
// << correlations[a-1][b].data[scaperow][scapecol]
// << endl;
return correlations[a-1][b].data[scaperow][scapecol];
}
//////////////////////////////
//
// calculateType1Scores -- calculate the index of the best correlations
// for each subsequence.
//
void calculateType1Scores(Array<Array<double> >& score1data,
Array<Array<Scape> >& correlations, Array<Performance>& perfs) {
Array<Array<int> > masklayer;
int arraysize = score1data.getSize();
int i;
masklayer.setSize(arraysize);
masklayer.allowGrowth(0);
for (i=0; i<arraysize; i++) {
masklayer[i].setSize(arraysize);
masklayer[i].allowGrowth(0);
masklayer[i].setAll(1);
masklayer[i][i] = 0; // exclude self-matching from analysis
}
for (i=0; i<score1data.getSize(); i++) {
cout << "\t";
if (strcmp(perfs[i].name, "") == 0) {
cout << i;
} else {
cout << perfs[i].name;
}
cout << endl;
calculateType1ScoreSingle(score1data[i], correlations, i,
masklayer[i]);
}
}
//////////////////////////////
//
// calculateType1ScoreSingle --
//
void calculateType1ScoreSingle(Array<double>& performancedata,
Array<Array<Scape> >& correlations, int reference,
Array<int>& masklayer) {
Array<int> sums;
sums.setSize(performancedata.getSize());
sums.allowGrowth(0);
sums.setAll(0);
int i, j;
int maxindex;
int tsum = 0;
int scaperows = correlations[0][0].data.getSize();
int scapecols;
for (i=0; i<scaperows; i++) {
scapecols = i + 1;
for (j=0; j<scapecols; j++) {
maxindex = getMaxCorrIndex(correlations, reference, i, j,
masklayer);
sums[maxindex]++;
tsum++;
}
}
for (i=0; i<sums.getSize(); i++) {
if (reference == i) {
performancedata[i] = 1.0;
} else {
performancedata[i] = (double)sums[i] / (double)tsum;
}
}
}
//////////////////////////////
//
// getMaxCorrIndex -- find the best match at a given scape location.
//
int getMaxCorrIndex(Array<Array<Scape> >& correlations, int reference,
int scaperow, int scapecol, Array<int>& masklayer) {
int maxindex = -2;
double maxval = -2.0;
double testval;
int i;
int rowsize = correlations.getSize()+1;
for (i=0; i<rowsize; i++) {
//if (i == reference) {
if (!masklayer[i]) {
continue;
}
testval = getCorrelation(reference, i, scaperow, scapecol, correlations);
if (maxval < testval) {
maxval = testval;
maxindex = i;
}
}
return maxindex;
}
//////////////////////////////
//
// calculateAllCorrelations -- calculate a lot of correlations
//
void calculateAllCorrelations(Array<Array<Scape> >& correlations,
Array<Performance>& performances) {
int i, j;
// subtract one for top row since diagonal always one
correlations.setSize(performances.getSize()-1);
for (i=1; i<correlations.getSize() + 1; i++) {
correlations[i-1].setSize(i);
for (j=0; j<i; j++) {
correlations[i-1][j].setScapeSize(performances[0].data.getSize());
calculateCorrelationLayer(correlations[i-1][j], performances[i],
performances[j]);
}
}
}
//////////////////////////////
//
// calculateCorrelationLayer --
//
void calculateCorrelationLayer(Scape& scape, Performance& a, Performance& b) {
int i, j;
double *aa;
double *bb;
int rowsize;
int corelsize;
for (i=0; i<scape.data.getSize(); i++) {
rowsize = scape.data[i].getSize();
corelsize = a.data.getSize() - i;
for (j=0; j<rowsize; j++) {
aa = a.data.getBase() + j;
bb = b.data.getBase() + j;
scape.data[i][j] = pearsonCorrelation(corelsize, aa, bb);
}
}
}
//////////////////////////////
//
// readData -- read the input data array from humdrum.
// All spines must be data. Spines cannot split/join/exchange
// or terminate at other times than the rest of the data.
//
void readData(Array& performances, HumdrumFile& infile) {
int dataspines = infile.getMaxTracks();
performances.setSize(dataspines);
performances.allowGrowth(0);
// pre-allocate storage space for data
int i, j;
for (i=0; i<performances.getSize(); i++) {
performances[i].data.setSize(infile.getNumLines());
performances[i].data.setSize(0);
performances[i].spine = i;
performances[i].process = 1;
performances[i].average = 0;
performances[i].random = 0;
}
int flag;
double value;
// i = line of input
// j = spine of input; performance number
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() == E_humrec_data) {
for (j=0; j<infile[i].getFieldCount(); j++) {
flag = sscanf(infile[i][j], "%lf", &value);
if (flag <= 0) {
std::cout << "Error: line " << i+1
<< " spine " << j+1 << " is invalid:\n";
std::cout << infile[i] << std::endl;
exit(1);
}
performances[j].data.append(value);
}
} else if (infile[i].getType() == E_humrec_local_comment) {
if (strncmp(infile[i][0], "!pid", 4) == 0) {
for (j=0; j<infile[i].getFieldCount(); j++) {
performances[j].pid = &(infile[i][j][1]);
}
} else if (performerNameQ(infile[i][0])) {
for (j=0; j<infile[i].getFieldCount(); j++) {
performances[j].name = &(infile[i][j][1]);
}
}
}
}
// identify random and average spines
double minn;
double maxx;
for (i=0; i<performances.getSize(); i++) {
if (strncmp(performances[i].name, "Average", 7) == 0) {
performances[i].average = 1;
}
getRange(minn, maxx, performances[i].data);
if ((minn <= 1.0) && (minn >= 0.0) && (maxx >= 0.0) && (maxx <= 1.0)) {
performances[i].random = 1;
}
}
}
//////////////////////////////
//
// performerNameQ --
//
int performerNameQ(const char* string) {
int digitcount = 0;
int spacecount = 0;
int len = strlen(string);
int i;
for (i=0; i<len; i++) {
if (string[i] == ' ') {
spacecount++;
}
if (isdigit(string[i])) {
digitcount++;
}
}
if (spacecount != 1) {
return 0;
}
if (digitcount != 4) {
return 0;
}
return 1;
}
//////////////////////////////
//
// getRange --
//
void getRange(double& minn, double& maxx, Array data) {
int i;
minn = data[0];
maxx = data[0];
for (i=1; i<data.getSize(); i++) {
if (minn > data[i]) {
minn = data[i];
}
if (maxx < data[i]) {
maxx = data[i];
}
}
}
//////////////////////////////
//
// calculateScore0Array --
//
void calculateScore0Array(Array<Array<double> >& dataarray,
Array<Performance>& performances) {
dataarray.setSize(performances.getSize());
int i, j;
for (i=0; i<dataarray.getSize(); i++) {
dataarray[i].setSize(performances.getSize());
dataarray[i][i] = 1.0;
}
int plen = performances[0].data.getSize();
for (i=0; i<dataarray.getSize(); i++) {
for (j=0; j<i; j++) {
dataarray[i][j] = pearsonCorrelation(plen,
performances[i].data.getBase(),
performances[j].data.getBase());
dataarray[j][i] = dataarray[i][j];
}
}
}
//////////////////////////////
//
// calculateRankArray --
//
void calculateRankArray(Array<Array<int> >& rankarray,
Array<Array<double> >& scorearray) {
rankarray.setSize(scorearray.getSize());
int i;
for (i=0; i<scorearray.getSize(); i++) {
rankarray[i].setSize(scorearray.getSize());
sortRanks(rankarray[i], scorearray[i]);
}
}
////////////////////
//
// sortRanks --
//
void sortRanks(Array& ranks, Array& values) {
int i;
Array<double*> presort;
Array<double> sortdata;
presort.setSize(values.getSize());
sortdata.setSize(values.getSize());
for (i=0; i<values.getSize(); i++) {
sortdata[i] = values[i];
presort[i] = &(sortdata[i]);
}
qsort(presort.getBase(), presort.getSize(), sizeof(double*), numbersort);
for (i=0; i<values.getSize(); i++) {
*presort[i] = i;
}
for (i=0; i<values.getSize(); i++) {
ranks[i] = (int)sortdata[i];
}
}
//////////////////////////////
//
// printRank --
//
void printRank(const char* filename, HumdrumFile& infile,
Array<Performance>& performances, Array<Array<int> >& rank0data) {
int i, j;
ofstream outfile;
#ifndef OLDCPP
outfile.open(filename);
#else
outfile.open(filename, ios::noreplace);
#endif
if (!outfile.is_open()) {
std::cout << "Error: could not open " << filename
<< " for writing" << std::endl;
exit(1);
}
// print bibliographic information:
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() == E_humrec_bibliography) {
outfile << infile[i] << "\n";
}
}
// print start of data markers
outfile << "**text";
for (i=0; i<performances.getSize(); i++) {
outfile << "\t**data";
}
outfile << "\n";
// print pid information
outfile << "!";
for (i=0; i<performances.getSize(); i++) {
outfile << "\t!" << performances[i].pid;
}
outfile << "\n";
// print performer information
outfile << "!";
for (i=0; i<performances.getSize(); i++) {
outfile << "\t!" << performances[i].name;
}
outfile << "\n";
// print data
if (performances.getSize() != rank0data.getSize()) {
std::cout << "Error: matrix is not square" << std::endl;
exit(1);
}
if (rank0data[0].getSize() != rank0data.getSize()) {
std::cout << "Error: matrix is not square" << std::endl;
exit(1);
}
for (i=0; i<performances.getSize(); i++) {
if (strcmp(performances[i].name, "") == 0) {
outfile << ".";
} else {
outfile << performances[i].name;
}
for (j=0; j<rank0data.getSize(); j++) {
// indices have to be reversed here since performance
// data is printed in the column not the row:
outfile << "\t" << rank0data[j][i];
}
outfile << "\n";
}
// print end of data markers
outfile << "*-";
for (i=0; i<rank0data.getSize(); i++) {
outfile << "\t*-";
}
outfile << "\n";
}
//////////////////////////////
//
// printScore --
//
void printScore(const char* filename, HumdrumFile& infile,
Array<Performance>& performances, Array<Array<double> >& score0data,
int decimals) {
int i, j;
ofstream outfile;
#ifndef OLDCPP
outfile.open(filename);
#else
outfile.open(filename, ios::noreplace);
#endif
if (!outfile.is_open()) {
std::cout << "Error: could not open " << filename
<< " for writing" << std::endl;
exit(1);
}
// print bibliographic information:
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() == E_humrec_bibliography) {
outfile << infile[i] << "\n";
}
}
// print start of data markers
outfile << "**text";
for (i=0; i<performances.getSize(); i++) {
outfile << "\t**data";
}
outfile << "\n";
// print pid information
outfile << "!";
for (i=0; i<performances.getSize(); i++) {
outfile << "\t!" << performances[i].pid;
}
outfile << "\n";
// print performer information
outfile << "!";
for (i=0; i<performances.getSize(); i++) {
outfile << "\t!" << performances[i].name;
}
outfile << "\n";
if (performances.getSize() != score0data.getSize()) {
std::cout << "Error: matrix is not square" << std::endl;
exit(1);
}
if (score0data[0].getSize() != score0data.getSize()) {
std::cout << "Error: matrix is not square" << std::endl;
exit(1);
}
// print data
for (i=0; i<performances.getSize(); i++) {
if (strcmp(performances[i].name, "") == 0) {
outfile << ".";
} else {
outfile << performances[i].name;
}
for (j=0; j<performances.getSize(); j++) {
outfile << "\t";
// indices have to be reversed here since performance
// data is printed in the column not the row:
printNumberDecimal(outfile, score0data[j][i], decimals);
}
outfile << "\n";
}
// print end of data markers
outfile << "*-";
for (i=0; i<performances.getSize(); i++) {
outfile << "\t*-";
}
outfile << "\n";
}
//////////////////////////////
//
// printNumberDecimal --
//
void printNumberDecimal(ofstream& outfile, double number, int decimals) {
number = int(number * pow(10.0, (double)decimals) + 0.5);
number = number / pow(10.0, (double)decimals);
char string[32];
char format[32];
strcpy(format, "%.");
sprintf(string, "%d", decimals);
strcat(format, string);
strcat(format, "lf");
sprintf(string, format, number);
int len = strlen(string);
int i;
int deccount = 0;
int decarea = 0;
for (i=0; i<len; i++) {
if (string[i] == '.') {
decarea = 1;
continue;
}
if (decarea) {
deccount++;
}
}
if (deccount > decimals) {
std::cout << "Error printing number " << number << std::endl;
std::cout << "deccount = " << deccount << std::endl;
std::cout << "decimals = " << decimals << std::endl;
std::cout << "string = >>" << string << "<<" << std::endl;
exit(1);
}
outfile << string;
if (decarea == 0) {
outfile << '.';
}
for (i=0; i<decimals-deccount; i++) {
outfile << '0';
}
}
//////////////////////////////
//
// pearsonCorrelation --
//
double pearsonCorrelation(int size, double* a, double* b) {
double meana = getMean(size, a);
double meanb = getMean(size, b);
double topsum = 0.0;
double bottomasum = 0.0;
double bottombsum = 0.0;
int i;
for (i=0; i<size; i++) {
topsum += (a[i] - meana) * (b[i] - meanb);
bottomasum += (a[i] - meana) * (a[i] - meana);
bottombsum += (b[i] - meanb) * (b[i] - meanb);
}
if (bottomasum == 0.0 || bottombsum == 0.0) {
return 0.0;
}
return topsum / sqrt(bottomasum * bottombsum);
}
//////////////////////////////
//
// getMean --
//
double getMean(int size, double* a) {
if (size <= 0) {
return 0.0;
}
int i;
double sum = 0.0;
for (i=0; i<size; i++) {
sum += a[i];
}
return sum / size;
}
//////////////////////////////
//
// numbersort -- sort items largest first
//
int numbersort(const void* A, const void* B) {
double valuea = **((double**)A);
double valueb = **((double**)B);
if (valuea > valueb) {
return -1;
} else if (valuea < valueb) {
return +1;
} else {
return 0;
}
}
//////////////////////////////
//
// checkOptions --
//
void checkOptions(Options& opts, int argc, char* argv[]) {
opts.define("s0=b", "create score-0 data file");
opts.define("r0=b", "create rank-0 data file");
opts.define("s1=b", "create score-1 data file");
opts.define("r1=b", "create rank-1 data file");
opts.define("s2=b", "create score-2 data file");
opts.define("r2=b", "create rank-2 data file");
opts.define("s3=b", "create score-3 data file");
opts.define("r3=b", "create rank-3 data file");
opts.define("s4=b", "create score-4 data file");
opts.define("r4=b", "create rank-4 data file");
opts.define("0=b", "create rank-0 and score-0 data file");
opts.define("1=b", "create rank-1 and score-1 data file");
opts.define("2=b", "create rank-2 and score-2 data file");
opts.define("3=b", "create rank-3 and score-2 data file");
opts.define("4=b", "create rank-4 and score-2 data file");
opts.define("a|all=b", "create all score and rank files");
opts.define("b|base|filebase=s:data", "basename for generating filenames");
opts.define("author=b", "author of program");
opts.define("version=b", "compilation info");
opts.define("example=b", "example usages");
opts.define("help=b", "short description");
opts.process(argc, argv);
// handle basic options:
if (opts.getBoolean("author")) {
cout << "Written by Craig Stuart Sapp, "
<< "craig@ccrma.stanford.edu, October 2008" << std::endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: October 2008" << std::endl;
cout << "compiled: " << __DATE__ << std::endl;
exit(0);
} else if (opts.getBoolean("help")) {
usage(opts.getCommand());
exit(0);
} else if (opts.getBoolean("example")) {
example();
exit(0);
}
if (opts.getBoolean("s0")) {
score0q = 1;
}
if (opts.getBoolean("r0")) {
rank0q = 1;
}
if (opts.getBoolean("0")) {
score0q = rank0q = 1;
}
if (opts.getBoolean("s1")) {
score1q = 1;
level = 1;
}
if (opts.getBoolean("r1")) {
rank1q = 1;
level = 1;
}
if (opts.getBoolean("1")) {
score1q = rank1q = 1;
level = 1;
}
if (opts.getBoolean("s2")) {
score2q = 1;
level = 2;
}
if (opts.getBoolean("r2")) {
rank2q = 1;
level = 2;
}
if (opts.getBoolean("2")) {
score2q = rank2q = 1;
level = 2;
}
if (opts.getBoolean("s3")) {
score3q = 1;
level = 3;
}
if (opts.getBoolean("r3")) {
rank3q = 1;
level = 3;
}
if (opts.getBoolean("3")) {
score3q = rank3q = 1;
level = 3;
}
if (opts.getBoolean("s4")) {
score4q = 1;
level = 4;
}
if (opts.getBoolean("r4")) {
rank4q = 1;
level = 4;
}
if (opts.getBoolean("4")) {
score4q = rank4q = 1;
level = 4;
}
if (opts.getBoolean("all")) {
score0q = rank0q = 1;
score1q = rank1q = 1;
score2q = rank2q = 1;
score3q = rank3q = 1;
score4q = rank4q = 1;
level = 4;
}
filebase = opts.getString("filebase");
}
//////////////////////////////
//
// example --
//
void example(void) {
}
//////////////////////////////
//
// usage --
//
void usage(const char* command) {
}
// md5sum: 11cea91ba3db575bd4b3b701e7c379ab ismir2008.cpp [20081011]