//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Sun Sep 30 23:06:34 PDT 2007
// Last Modified: Sun Sep 30 23:06:40 PDT 2007
// Last Modified: Sat Apr 12 21:00:21 PDT 2008 (added -a and -A options)
// Filename: ...sig/examples/all/smoother.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/smoother.cpp
// Syntax: C++; museinfo
//
// Description: Smoothes data with exponential smoothing filter.
//
#include "humdrum.h"
#include <stdlib.h>
#ifndef OLDCPP
using namespace std;
#endif
///////////////////////////////////////////////////////////////////////////
// function declarations
void checkOptions(Options& opts, int argc, char* argv[]);
void example(void);
void usage(const char* command);
void processFileBasic(HumdrumFile& infile);
void processFileSmoothAll(HumdrumFile& infile);
void processFileDesmoothAll(HumdrumFile& infile);
void fillDesmooth(Array<double>& sequence,
int spine, HumdrumFile& infile);
void fillSmooth(Array<double>& sequence,
int spine, HumdrumFile& infile);
// global variables
Options options; // database for command-line arguments
double sgain = 0.5; // used with -s option (smoothing amount)
double allsmoothQ = 0; // used with -a option
double allresidueQ = 0; // used with -A option
///////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[]) {
HumdrumFile infile;
// process the command-line options
checkOptions(options, argc, argv);
const char* filename;
infile.clear();
// if no command-line arguments read data file from standard input
int numinputs = options.getArgCount();
if (numinputs < 1) {
infile.read(cin);
} else {
filename = options.getArg(1);
infile.read(options.getArg(1));
}
if (allsmoothQ) {
processFileSmoothAll(infile);
} else if (allresidueQ) {
processFileDesmoothAll(infile);
} else {
processFileBasic(infile);
}
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////
//
// processFileSmoothAll --
//
void processFileSmoothAll(HumdrumFile& infile) {
Array<Array<double> > spines;
spines.setSize(infile.getMaxTracks());
int i;
for (i=0; i<spines.getSize(); i++) {
fillSmooth(spines[i], i, infile);
}
Array<int> pointers;
pointers.setSize(spines.getSize());
pointers.allowGrowth(0);
pointers.setAll(0);
int jsize;
int j;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() == E_humrec_data) {
jsize = infile[i].getFieldCount();
for (j=0; j<jsize; j++) {
if (strcmp(infile[i][j], ".") == 0) {
cout << infile[i][j];
if (j < jsize-1) {
cout << "\t";
}
continue;
}
if (infile[i][j][0] == '=') {
cout << infile[i][j];
if (j < jsize-1) {
cout << "\t";
}
continue;
}
cout << spines[j][pointers[j]++];
if (j < jsize-1) {
cout << "\t";
}
}
cout << "\n";
} else {
cout << infile[i] << "\n";
}
}
}
///////////////////////////////
//
// processFileDesmoothAll --
//
void processFileDesmoothAll(HumdrumFile& infile) {
Array<Array<double> > spines;
spines.setSize(infile.getMaxTracks());
int i;
for (i=0; i<spines.getSize(); i++) {
fillDesmooth(spines[i], i, infile);
}
Array<int> pointers;
pointers.setSize(spines.getSize());
pointers.allowGrowth(0);
pointers.setAll(0);
int jsize;
int j;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() == E_humrec_data) {
jsize = infile[i].getFieldCount();
for (j=0; j<jsize; j++) {
if (strcmp(infile[i][j], ".") == 0) {
cout << infile[i][j];
if (j < jsize-1) {
cout << "\t";
}
continue;
}
if (infile[i][j][0] == '=') {
cout << infile[i][j];
if (j < jsize-1) {
cout << "\t";
}
continue;
}
cout << spines[j][pointers[j]++];
if (j < jsize-1) {
cout << "\t";
}
}
cout << "\n";
} else {
cout << infile[i] << "\n";
}
}
}
//////////////////////////////
//
// fillSmooth --
//
void fillSmooth(Array& sequence, int spine, HumdrumFile& infile) {
sequence.setSize(infile.getNumLines());
sequence.setSize(0);
double value;
int i;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() == E_humrec_data) {
if (strcmp(infile[i][spine], ".") == 0) {
continue;
}
if (infile[i][spine][0] == '=') {
continue;
}
value = atof(infile[i][spine]);
sequence.append(value);
}
}
int thesize = sequence.getSize();
Array<double> smoothed;
smoothed.setSize(thesize);
double filterk = sgain;
double oneminusk = 1.0 - filterk;
// reverse filtering first
smoothed[thesize-1] = sequence[thesize-1];
for (i=thesize-2; i>=0; i--) {
smoothed[i] = filterk*sequence[i] + oneminusk*smoothed[i+1];
}
// then forward filtering
for (i=1; i<thesize; i++) {
smoothed[i] = filterk*smoothed[i] + oneminusk*smoothed[i-1];
}
for (i=0; i<thesize; i++) {
sequence[i] = smoothed[i];
}
}
//////////////////////////////
//
// fillDesmooth --
//
void fillDesmooth(Array& sequence, int spine, HumdrumFile& infile) {
sequence.setSize(infile.getNumLines());
sequence.setSize(0);
double value;
int i;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() == E_humrec_data) {
if (strcmp(infile[i][spine], ".") == 0) {
continue;
}
if (infile[i][spine][0] == '=') {
continue;
}
value = atof(infile[i][spine]);
sequence.append(value);
}
}
int thesize = sequence.getSize();
Array<double> smoothed;
smoothed.setSize(thesize);
double filterk = sgain;
double oneminusk = 1.0 - filterk;
// reverse filtering first
smoothed[thesize-1] = sequence[thesize-1];
for (i=thesize-2; i>=0; i--) {
smoothed[i] = filterk*sequence[i] + oneminusk*smoothed[i+1];
}
// then forward filtering
for (i=1; i<thesize; i++) {
smoothed[i] = filterk*smoothed[i] + oneminusk*smoothed[i-1];
}
for (i=0; i<thesize; i++) {
sequence[i] = sequence[i] - smoothed[i];
}
}
//////////////////////////////
//
// processFileBasic -- only read the first row for processing for now...
//
void processFileBasic(HumdrumFile& infile) {
Array<double> sequence;
sequence.setSize(infile.getNumLines());
sequence.setSize(0);
double value;
int i;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() == E_humrec_data) {
value = atof(infile[i][0]);
sequence.append(value);
}
}
int thesize = sequence.getSize();
Array<double> smoothed;
smoothed.setSize(thesize);
double filterk = sgain;
double oneminusk = 1.0 - filterk;
// reverse filtering first
smoothed[thesize-1] = sequence[thesize-1];
for (i=thesize-2; i>=0; i--) {
smoothed[i] = filterk*sequence[i] + oneminusk*smoothed[i+1];
}
// then forward filtering
for (i=1; i<thesize; i++) {
smoothed[i] = filterk*smoothed[i] + oneminusk*smoothed[i-1];
}
// print original, smoothed, and unsmoothed data in columns:
for (i=0; i<thesize; i++) {
cout << sequence[i] << "\t" << smoothed[i] << "\t";
cout << sequence[i] - smoothed[i];
cout << "\n";
}
}
//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//
void checkOptions(Options& opts, int argc, char* argv[]) {
opts.define("s|smooth=d:0.5"); // smoothing factor
opts.define("a|all|allsmooth=b"); // smoothing factor
opts.define("A|All|allresidue=b"); // smoothing factor
opts.define("debug=b"); // determine bad input line num
opts.define("author=b"); // author of program
opts.define("version=b"); // compilation info
opts.define("example=b"); // example usages
opts.define("h|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, Oct 2007" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: 1 Oct 2007" << endl;
cout << "compiled: " << __DATE__ << endl;
cout << MUSEINFO_VERSION << endl;
exit(0);
} else if (opts.getBoolean("help")) {
usage(opts.getCommand());
exit(0);
} else if (opts.getBoolean("example")) {
example();
exit(0);
}
sgain = opts.getDouble("smooth");
allsmoothQ = opts.getBoolean("allsmooth");
allresidueQ = opts.getBoolean("allresidue");
}
//////////////////////////////
//
// example -- example usage of the program
//
void example(void) {
cout <<
" \n"
<< endl;
}
//////////////////////////////
//
// usage -- gives the usage statement for the program
//
void usage(const char* command) {
cout <<
" \n"
<< endl;
}
// md5sum: f2227993f2a04e711de7aaebe248ec06 smoother.cpp [20080518]