NLMSvariants/src/ansi_c_implementation/NLMSvariants.c

844 lines
28 KiB
C
Raw Normal View History

2018-05-19 19:08:02 +02:00
/*
===========================================================================
Created by Stefan Friese on 26.04.2018
===========================================================================
*/
//
2018-05-16 12:47:49 +02:00
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include "nlms_types.h" // added types
2018-05-16 12:47:49 +02:00
#define RGB_COLOR 255
#if defined(_MSC_VER)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
2018-05-24 18:28:28 +02:00
double *xSamples; // Input color values from PPM
mldata_t *mlData = NULL; // Machine learning realted data
point_t *points = NULL; // Graphing
2018-05-24 18:28:28 +02:00
/* *Graph building* */
static imagePixel_t * rdPPM(char *fileName); // Read PPM file format
void mkPpmFile(char *fileName, imagePixel_t *image); // Writes PPM file
int ppmColorChannel(FILE* fp, imagePixel_t *image, // Writes colorChannel from PPM file to log file
char *colorChannel, mldata_t *mlData);
void colorSamples(FILE* fp, mldata_t *mlData); // Stores color channel values in xSamples
2018-05-16 12:47:49 +02:00
2018-05-24 18:28:28 +02:00
/* *File handling* */
char * mkFileName ( char* buffer, // Date+suffix as filename
size_t max_len, int suffixId );
2018-05-24 18:28:28 +02:00
char *fileSuffix ( int id ); // Filename ending of logs
char *fileHeader ( int id ); // Header inside the logfiles
void bufferLogger(char *buffer, point_t points[]); // Writes points to graph template
void mkSvgGraph ( point_t points[], char *templatePath); // Parses graph template and calls bufferLogger()
void weightsLogger ( double *weights, int suffix ); // Writes updated weights to a file
2018-05-16 12:47:49 +02:00
/* *rand seed* */
double r2 ( void ); // Random val between 0 and 1
double rndm ( void );
2018-05-16 12:47:49 +02:00
2018-05-16 23:54:38 +02:00
/* *args parser* */
void usage ( char **argv ); // Help text called by args parser
2018-05-16 23:54:38 +02:00
2018-05-16 12:47:49 +02:00
/* *math* */
mldata_t * init_mldata_t(unsigned windowSize, unsigned samplesCount, double learnrate);
2018-05-16 12:47:49 +02:00
double sum_array(double x[], int length);
void localMean ( mldata_t *mlData,point_t points[] ); // First,
void directPredecessor ( mldata_t *mlData, point_t points[] ); // Second,
void differentialPredecessor ( mldata_t *mlData, point_t points[] ); // Third filter implementation
double windowXMean(int _arraylength, int xCount); // Returns mean value of given window
2018-05-16 23:54:38 +02:00
int main( int argc, char **argv ) {
char *colorChannel = (char *) malloc(sizeof(char)* 32);
2018-05-16 23:54:38 +02:00
char *inputfile = (char *)malloc(sizeof(char) * 32);
2018-05-22 17:03:42 +02:00
unsigned *seed = NULL;
2018-05-24 11:02:00 +02:00
unsigned k, include = 0;
2018-05-22 17:03:42 +02:00
unsigned windowSize = 5;
unsigned samplesCount = 512;
char *stdcolor = "green", xBuffer[512];
2018-05-16 23:54:38 +02:00
colorChannel = stdcolor;
2018-05-22 17:03:42 +02:00
unsigned int uint_buffer[1], windowBuffer[1];
2018-05-19 20:52:39 +02:00
double learnrate = 0.4;
2018-05-24 11:02:00 +02:00
char *istrue = "true";
char *templatePath = NULL;
2018-05-16 23:54:38 +02:00
while( (argc > 1) && (argv[1][0] == '-') ) { // Parses parameters from stdin
switch( argv[1][1] ) {
case 'i':
inputfile = &argv[1][3];
++argv;
--argc;
break;
case 'w':
2018-05-22 17:03:42 +02:00
sscanf(&argv[1][3], "%u", windowBuffer);
windowSize = windowBuffer[0];
2018-05-16 23:54:38 +02:00
++argv;
--argc;
break;
case 'c':
colorChannel = &argv[1][3];
++argv;
--argc;
break;
case 's':
sscanf(&argv[1][3], "%u", uint_buffer);
seed = &uint_buffer[0];
++argv;
--argc;
break;
case 'n':
sscanf(&argv[1][3], "%u", &samplesCount);
++argv;
--argc;
break;
case'h':
2018-05-16 23:54:38 +02:00
printf("Program name: %s\n", argv[0]);
usage(argv);
2018-05-16 23:54:38 +02:00
break;
case 'l':
sscanf(&argv[1][3], "%lf", &learnrate);
++argv;
--argc;
break;
2018-05-24 11:02:00 +02:00
case 'g':
2018-05-22 17:03:42 +02:00
sscanf(&argv[1][3], "%s", xBuffer);
2018-05-24 11:02:00 +02:00
if ( strstr(xBuffer, istrue) ) {
include = 1;
} else if ( xBuffer && !strstr(xBuffer, istrue) ) {
templatePath = xBuffer;
include = 1;
} else {
2018-05-24 11:02:00 +02:00
printf( "Wrong Argruments: %s\n", argv[1]);
usage(argv);
}
++argv;
--argc;
break;
2018-05-16 23:54:38 +02:00
default:
printf("Wrong Arguments: %s\n", argv[1]);
usage(argv);
2018-05-16 23:54:38 +02:00
}
++argv;
--argc;
}
2018-05-22 17:03:42 +02:00
2018-05-19 20:52:39 +02:00
init_mldata_t ( windowSize, samplesCount, learnrate );
xSamples = (double *) malloc ( sizeof(double) * mlData->samplesCount ); // Resize input values
points = (point_t *) malloc ( sizeof(point_t) * mlData->samplesCount); // Resize points
imagePixel_t *image;
2018-05-22 17:03:42 +02:00
image = rdPPM(inputfile); // Set Pointer on input values
printf("window Size: %d\n", mlData->windowSize);
2018-05-19 20:52:39 +02:00
char fileName[50]; // Logfiles and their names
2018-05-16 12:47:49 +02:00
mkFileName(fileName, sizeof(fileName), TEST_VALUES);
FILE* fp5 = fopen(fileName, "w");
2018-05-24 18:28:28 +02:00
ppmColorChannel(fp5, image, colorChannel, mlData);
2018-05-16 12:47:49 +02:00
FILE* fp6 = fopen(fileName, "r");
colorSamples(fp6, mlData);
2018-05-16 12:47:49 +02:00
if ( (seed != NULL) ){
2018-05-19 20:52:39 +02:00
srand( *seed ); // Seed for random number generating
printf("srand is reproducable\n");
2018-05-16 23:54:38 +02:00
} else {
srand( (unsigned int)time(NULL) );
2018-05-19 20:52:39 +02:00
printf("srand depends on time\n"); // Default seed is time(NULL)
2018-05-16 23:54:38 +02:00
}
2018-05-19 20:52:39 +02:00
printf("generated weights:\n");
2018-05-22 17:03:42 +02:00
for (k = 0; k < mlData->windowSize; k++) {
2018-05-19 20:52:39 +02:00
mlData->weights[k] = rndm(); // Init random weights
2018-05-22 17:03:42 +02:00
printf("[%d] %lf\n", k, mlData->weights[k]);
}
2018-05-19 20:52:39 +02:00
mkFileName(fileName, sizeof(fileName), PURE_WEIGHTS); // Logfile weights
2018-05-16 12:47:49 +02:00
FILE *fp0 = fopen(fileName, "w");
2018-05-22 17:03:42 +02:00
for (k = 0; k < mlData->windowSize; k++) {
2018-05-24 18:28:28 +02:00
fprintf(fp0, "[%d]%lf\n", k, mlData->weights[k]);
2018-05-22 17:03:42 +02:00
}
2018-05-16 12:47:49 +02:00
fclose(fp0);
2018-05-16 23:54:38 +02:00
2018-05-24 18:28:28 +02:00
localMean ( mlData, points ); // math magic functions
directPredecessor ( mlData, points );
differentialPredecessor( mlData, points );
2018-05-24 11:02:00 +02:00
if ( include == 1 ) {
mkSvgGraph(points, templatePath); // Graph building
2018-05-22 17:03:42 +02:00
}
free(image);
free(xSamples);
free(points);
2018-05-19 20:52:39 +02:00
free(mlData);
2018-05-16 12:47:49 +02:00
printf("\nDONE!\n");
}
/*
======================================================================================================
localMean
Variant (1/3), substract local mean.
======================================================================================================
*/
void localMean ( mldata_t *mlData, point_t points[] ) {
2018-05-19 20:52:39 +02:00
double *localWeights = (double *) malloc ( sizeof(double) * mlData->windowSize + 1);
2018-05-23 11:17:31 +02:00
localWeights = mlData->weights;
2018-05-16 12:47:49 +02:00
char fileName[50];
const unsigned xErrorLength = mlData->samplesCount;
double xError[xErrorLength];
unsigned i, xCount = 0; // Runtime vars
2018-05-22 17:03:42 +02:00
2018-05-19 20:52:39 +02:00
mkFileName(fileName, sizeof(fileName), LOCAL_MEAN); // Create Logfile and its filename
FILE* fp4 = fopen(fileName, "w");
2018-05-22 17:03:42 +02:00
fprintf( fp4, fileHeader(LOCAL_MEAN_HEADER) );
mkFileName ( fileName, sizeof(fileName), USED_WEIGHTS_LOCAL_MEAN);
FILE *fp9 = fopen(fileName, "w");
2018-05-16 12:47:49 +02:00
double xMean = xSamples[0];
double xSquared = 0.0;
double xPredicted = 0.0;
double xActual = 0.0;
2018-05-24 18:28:28 +02:00
for ( xCount = 1; xCount < mlData->samplesCount-1; xCount++ ) { // First value will not get predicted
2018-05-19 20:52:39 +02:00
unsigned _arrayLength = ( xCount > mlData->windowSize ) ? mlData->windowSize + 1 : xCount; // Ensures corect length at start
xMean = (xCount > 0) ? windowXMean(_arrayLength, xCount) : 0;
2018-05-16 12:47:49 +02:00
xPredicted = 0.0;
xActual = xSamples[xCount];
2018-05-16 12:47:49 +02:00
2018-05-19 20:52:39 +02:00
for ( i = 1; i < _arrayLength; i++ ) { // Get predicted value
xPredicted += ( localWeights[i - 1] * (xSamples[xCount - i] - xMean) );
2018-05-16 12:47:49 +02:00
}
2018-05-19 20:52:39 +02:00
xPredicted += xMean;
xError[xCount] = xActual - xPredicted; // Get error value
2018-05-16 12:47:49 +02:00
xSquared = 0.0;
2018-05-19 20:52:39 +02:00
for (i = 1; i < _arrayLength; i++) { // Get xSquared
2018-05-16 12:47:49 +02:00
xSquared += pow(xSamples[xCount - i] - xMean, 2);
}
2018-05-19 20:52:39 +02:00
if ( xSquared == 0.0 ) { // Otherwise returns Pred: -1.#IND00 in some occassions
2018-05-16 12:47:49 +02:00
xSquared = 1.0;
}
2018-05-19 20:52:39 +02:00
for ( i = 1; i < _arrayLength; i++ ) { // Update weights
2018-05-22 17:03:42 +02:00
localWeights[i] = localWeights[i - 1] + mlData->learnrate * xError[xCount] // Substract localMean
2018-05-19 20:52:39 +02:00
* ( (xSamples[xCount - i] - xMean) / xSquared );
2018-05-22 17:03:42 +02:00
fprintf( fp9, "%lf\n", localWeights[i] );
2018-05-16 12:47:49 +02:00
}
2018-05-19 20:52:39 +02:00
fprintf(fp4, "%d\t%f\t%f\t%f\n", xCount, xPredicted, xActual, xError[xCount]); // Write to logfile
2018-05-19 20:52:39 +02:00
points[xCount].xVal[1] = xCount; // Save points so graph can be build later on
points[xCount].yVal[1] = xPredicted;
points[xCount].xVal[4] = xCount;
points[xCount].yVal[4] = xError[xCount];
2018-05-16 12:47:49 +02:00
}
2018-05-22 17:03:42 +02:00
fclose(fp9);
2018-05-24 18:28:28 +02:00
double mean = sum_array(xError, xErrorLength) / xErrorLength; // Mean
2018-05-16 12:47:49 +02:00
double deviation = 0.0;
2018-05-19 20:52:39 +02:00
for (i = 1; i < xErrorLength; i++) { // Mean square
2018-05-16 12:47:49 +02:00
deviation += pow(xError[i] - mean, 2);
}
2018-05-19 20:52:39 +02:00
deviation /= xErrorLength; // Deviation
2018-05-25 19:28:31 +02:00
printf("mean square err: %lf, variance: %lf\t\tlocal Mean\n", mean, deviation);
2018-05-19 20:52:39 +02:00
fprintf(fp4, "\nQuadratische Varianz(x_error): %f\nMittelwert:(x_error): %f\n\n", deviation, mean); // Write to logfile
2018-05-16 12:47:49 +02:00
fclose(fp4);
}
/*
======================================================================================================
directPredecessor
Variant (2/3),
substract direct predecessor
======================================================================================================
*/
void directPredecessor( mldata_t *mlData, point_t points[]) {
double *localWeights = ( double * ) malloc ( sizeof(double) * mlData->windowSize + 1 );
2018-05-23 11:17:31 +02:00
localWeights = mlData->weights;
2018-05-16 12:47:49 +02:00
char fileName[512];
const unsigned xErrorLength = mlData->samplesCount;
double xError[xErrorLength];
unsigned xCount = 0, i;
2018-05-16 12:47:49 +02:00
double xActual = 0.0;
double xPredicted = 0.0;
2018-05-24 18:28:28 +02:00
mkFileName(fileName, sizeof(fileName), DIRECT_PREDECESSOR); // Logfile and name handling
2018-05-16 12:47:49 +02:00
FILE *fp3 = fopen(fileName, "w");
fprintf( fp3, fileHeader(DIRECT_PREDECESSOR_HEADER) );
2018-05-22 17:03:42 +02:00
mkFileName ( fileName, sizeof(fileName), USED_WEIGHTS_DIR_PRED);
FILE *fp9 = fopen(fileName, "w");
2018-05-16 12:47:49 +02:00
2018-05-24 18:28:28 +02:00
for (xCount = 1; xCount < mlData->samplesCount-1; xCount++) { // first value will not get predicted
unsigned _arrayLength = ( xCount > mlData->windowSize ) ? mlData->windowSize + 1 : xCount;
2018-05-16 12:47:49 +02:00
xPredicted = 0.0;
xActual = xSamples[xCount];
2018-05-16 12:47:49 +02:00
for (i = 1; i < _arrayLength; i++) {
xPredicted += ( localWeights[i - 1] * (xSamples[xCount - 1] - xSamples[xCount - i - 1]));
2018-05-16 12:47:49 +02:00
}
2018-05-16 12:47:49 +02:00
xPredicted += xSamples[xCount - 1];
xError[xCount] = xActual - xPredicted;
double xSquared = 0.0;
for (i = 1; i < _arrayLength; i++) {
2018-05-19 20:52:39 +02:00
xSquared += pow(xSamples[xCount - 1] - xSamples[xCount - i - 1], 2); // substract direct predecessor
2018-05-16 12:47:49 +02:00
}
2018-05-19 20:52:39 +02:00
if ( xSquared == 0.0 ) { // Otherwise returns Pred: -1.#IND00 in some occassions
xSquared = 1.0;
}
for ( i = 1; i < _arrayLength; i++ ) { // Update weights
2018-05-22 17:03:42 +02:00
localWeights[i] = localWeights[i-1] + mlData->learnrate * xError[xCount]
2018-05-19 20:52:39 +02:00
* ( (xSamples[xCount - 1] - xSamples[xCount - i - 1]) / xSquared);
fprintf( fp9, "%lf\n", localWeights[i] );
2018-05-16 12:47:49 +02:00
}
2018-05-19 20:52:39 +02:00
fprintf(fp3, "%d\t%f\t%f\t%f\n", xCount, xPredicted, xActual, xError[xCount]); // Write to logfile
points[xCount].xVal[2] = xCount; // Fill point_t array for graph building
points[xCount].yVal[2] = xPredicted;
points[xCount].xVal[5] = xCount;
points[xCount].yVal[5] = xError[xCount];
}
fclose(fp9);
2018-05-16 12:47:49 +02:00
double mean = sum_array(xError, xErrorLength) / xErrorLength; // Mean
2018-05-19 20:52:39 +02:00
double deviation = 0.0;
2018-05-16 12:47:49 +02:00
for (i = 1; i < xErrorLength; i++) {
2018-05-19 20:52:39 +02:00
deviation += pow(xError[i] - mean, 2); // Mean square
2018-05-16 12:47:49 +02:00
}
2018-05-19 20:52:39 +02:00
deviation /= xErrorLength; // Deviation
printf("mean square err: %lf, variance: %lf\t\t\tdirect Predecessor\n", mean, deviation);
2018-05-16 12:47:49 +02:00
fprintf(fp3, "\nQuadratische Varianz(x_error): %f\nMittelwert:(x_error): %f\n\n", deviation, mean);
fclose(fp3);
}
/*
======================================================================================================
differentialPredecessor
variant (3/3),
differential predecessor.
======================================================================================================
*/
void differentialPredecessor ( mldata_t *mlData, point_t points[] ) {
double *localWeights = (double *) malloc ( sizeof(double) * mlData->windowSize + 1 );
2018-05-23 11:17:31 +02:00
localWeights = mlData->weights;
const unsigned xErrorLength = mlData->samplesCount;
2018-05-16 12:47:49 +02:00
char fileName[512];
double xError[xErrorLength];
2018-05-23 11:17:31 +02:00
unsigned xCount = 0, i;
2018-05-16 12:47:49 +02:00
double xPredicted = 0.0;
double xActual = 0.0;
2018-05-19 20:52:39 +02:00
mkFileName(fileName, sizeof(fileName), DIFFERENTIAL_PREDECESSOR); // File handling
2018-05-16 12:47:49 +02:00
FILE *fp6 = fopen(fileName, "w");
fprintf(fp6, fileHeader(DIFFERENTIAL_PREDECESSOR_HEADER) );
2018-05-16 12:47:49 +02:00
2018-05-22 17:03:42 +02:00
mkFileName ( fileName, sizeof(fileName), USED_WEIGHTS_DIFF_PRED);
FILE *fp9 = fopen(fileName, "w");
2018-05-23 11:17:31 +02:00
for (xCount = 1; xCount < mlData->samplesCount-1; xCount++) { // First value will not get predicted
2018-05-16 12:47:49 +02:00
unsigned _arrayLength = (xCount > mlData->windowSize) ? mlData->windowSize + 1 : xCount;
2018-05-16 12:47:49 +02:00
xPredicted = 0.0;
xActual = xSamples[xCount];
2018-05-16 12:47:49 +02:00
for (i = 1; i < _arrayLength; i++) {
xPredicted += ( localWeights[i - 1] * (xSamples[xCount - i] - xSamples[xCount - i - 1]));
2018-05-16 12:47:49 +02:00
}
xPredicted += xSamples[xCount - 1];
xError[xCount] = xActual - xPredicted;
double xSquared = 0.0;
for (i = 1; i < _arrayLength; i++) {
2018-05-19 20:52:39 +02:00
xSquared += pow(xSamples[xCount - i] - xSamples[xCount - i - 1], 2); // Substract direct predecessor
2018-05-16 12:47:49 +02:00
}
2018-05-19 20:52:39 +02:00
if ( xSquared == 0.0 ) { // Otherwise returns Pred: -1.#IND00 in some occassions
xSquared = 1.0;
}
2018-05-16 12:47:49 +02:00
for (i = 1; i < _arrayLength; i++) {
2018-05-22 17:03:42 +02:00
localWeights[i] = localWeights[i-1] + mlData->learnrate * xError[xCount]
* ((xSamples[xCount - i] - xSamples[xCount - i - 1]) / xSquared);
fprintf( fp9, "%lf\n", localWeights[i] );
2018-05-16 12:47:49 +02:00
}
2018-05-24 18:28:28 +02:00
fprintf(fp6, "%d\t%f\t%f\t%f\n", xCount, xPredicted, xActual, xError[xCount]); // Write to logfile
points[xCount].xVal[3] = xCount;
points[xCount].yVal[3] = xPredicted;
points[xCount].xVal[6] = xCount;
points[xCount].yVal[6] = xError[xCount];
2018-05-16 12:47:49 +02:00
}
2018-05-22 17:03:42 +02:00
fclose(fp9);
2018-05-16 12:47:49 +02:00
double mean = sum_array(xError, xErrorLength) / xErrorLength;
2018-05-16 12:47:49 +02:00
double deviation = 0.0;
2018-05-19 20:52:39 +02:00
for (i = 1; i < xErrorLength; i++) { // Mean square
2018-05-16 12:47:49 +02:00
deviation += pow(xError[i] - mean, 2);
}
deviation /= xErrorLength;
2018-05-25 19:28:31 +02:00
printf("mean square err: %lf, variance: %lf\t\t\tdifferential Predecessor\n", mean, deviation);
2018-05-16 12:47:49 +02:00
fprintf(fp6, "\nQuadratische Varianz(x_error): %f\nMittelwert:(x_error): %f\n\n", deviation, mean);
fclose(fp6);
}
/*
======================================================================================================
mkFileName
2018-05-19 20:52:39 +02:00
Writes the current date plus suffix with index suffixId
2018-05-16 12:47:49 +02:00
into the given buffer. If the total length is longer than max_len,
only max_len characters will be written.
======================================================================================================
*/
char *mkFileName(char* buffer, size_t max_len, int suffixId) {
2018-05-19 20:52:39 +02:00
const char * format_str = "%Y-%m-%d_%H_%M_%S"; // Date formatting
2018-05-16 12:47:49 +02:00
size_t date_len;
const char * suffix = fileSuffix(suffixId);
2018-05-19 20:52:39 +02:00
time_t now = time(NULL);
2018-05-16 12:47:49 +02:00
2018-05-19 20:52:39 +02:00
strftime(buffer, max_len, format_str, localtime(&now)); // Get Date
2018-05-16 12:47:49 +02:00
date_len = strlen(buffer);
2018-05-19 20:52:39 +02:00
strncat(buffer, suffix, max_len - date_len); // Concat filename
2018-05-16 12:47:49 +02:00
return buffer;
}
/*
======================================================================================================
fileSuffix
Contains and returns every suffix for all existing filenames
======================================================================================================
*/
char * fileSuffix ( int id ) {
char * suffix[] = { "_weights_pure.txt",
2018-05-22 17:03:42 +02:00
"_weights_used_dir_pred_.txt",
"_direct_predecessor.txt",
"_ergebnisse.txt",
"_localMean.txt",
"_testvalues.txt",
2018-05-22 17:03:42 +02:00
"_differential_predecessor.txt",
2018-05-24 11:02:00 +02:00
"_weights_used_local_mean.txt",
"_weights_used_diff_pred.txt",
};
2018-05-16 12:47:49 +02:00
return suffix[id];
}
/*
======================================================================================================
fileHeader
2018-05-19 20:52:39 +02:00
Contains and returns header from logfiles
======================================================================================================
*/
char * fileHeader ( int id ) {
char * header[] = { "\n=========================== Local Mean ===========================\nNo.\txPredicted\txAcutal\t\txError\n",
"\n=========================== Direct Predecessor ===========================\nNo.\txPredicted\txAcutal\t\txError\n",
"\n=========================== Differential Predecessor ===========================\nNo.\txPredicted\txAcutal\t\txError\n"
};
return header[id];
}
/*
======================================================================================================
2018-05-19 20:52:39 +02:00
weightsLogger
2018-05-16 12:47:49 +02:00
2018-05-24 18:28:28 +02:00
Logs used weights to logfile - not used right now
2018-05-16 12:47:49 +02:00
======================================================================================================
*/
2018-05-24 18:28:28 +02:00
void weightsLogger (double *weights, int val ) {
2018-05-16 12:47:49 +02:00
char fileName[512];
unsigned i;
2018-05-16 12:47:49 +02:00
mkFileName(fileName, sizeof(fileName), val);
FILE* fp = fopen(fileName, "wa");
for (i = 0; i < mlData->windowSize - 1; i++) {
2018-05-22 17:03:42 +02:00
fprintf(fp, "[%d]%lf\n", i, weights[i]);
2018-05-16 12:47:49 +02:00
}
fclose(fp);
}
/*
======================================================================================================
bufferLogger
formats output of mkSvgGraph -- Please open graphResults.html to see the output--
[0] = xActual,
[1] = xPredicted from localMean,
[2] = xPredicted from directPredecessor,
[3] = xPredicted from differentialpredecessor,
[4] = xError from localMean,
[5] = xError from directPredecessor,
[6] = xError from differentialPredecessor
2018-05-16 12:47:49 +02:00
======================================================================================================
*/
void bufferLogger(char *buffer, point_t points[]) {
unsigned i;
2018-05-24 18:28:28 +02:00
char _buffer[512] = "";
2018-05-23 11:17:31 +02:00
for (i = 1; i < mlData->samplesCount - 1; i++) { // xActual
2018-05-16 12:47:49 +02:00
sprintf(_buffer, "L %f %f\n", points[i].xVal[0], points[i].yVal[0]);
strcat(buffer, _buffer);
}
strcat(buffer, "\" fill=\"none\" id=\"svg_1\" stroke=\"black\" stroke-width=\"0.4px\"/>\n<path d=\"M0 0\n");
2018-05-23 11:17:31 +02:00
for (i = 1; i < mlData->samplesCount - 1; i++) { // xPredicted from localMean
2018-05-16 12:47:49 +02:00
sprintf(_buffer, "L %f %f\n", points[i].xVal[1], points[i].yVal[1]);
strcat(buffer, _buffer);
}
strcat(buffer, "\" fill=\"none\" id=\"svg_2\" stroke=\"green\" stroke-width=\"0.4px\"/>\n<path d=\"M0 0\n");
2018-05-24 18:28:28 +02:00
for (i = 1; i <= mlData->samplesCount - 2; i++) { //xPredicted from directPredecessor
2018-05-16 12:47:49 +02:00
sprintf(_buffer, "L %f %f\n", points[i].xVal[2], points[i].yVal[2]);
strcat(buffer, _buffer);
}
strcat(buffer, "\" fill=\"none\" id=\"svg_3\" stroke=\"blue\" stroke-width=\"0.4px\"/>\n<path d=\"M0 0\n");
2018-05-23 11:17:31 +02:00
for (i = 1; i < mlData->samplesCount - 1; i++) { //xPredicted from diff Pred
2018-05-16 12:47:49 +02:00
sprintf(_buffer, "L %f %f\n", points[i].xVal[3], points[i].yVal[3]);
strcat(buffer, _buffer);
}
strcat(buffer, "\" fill=\"none\" id=\"svg_4\" stroke=\"red\" stroke-width=\"0.4px\"/>\n");
}
/*
======================================================================================================
sum_array
Sum of all elements in x within a defined length
======================================================================================================
*/
double sum_array(double x[], int xlength) {
int i = 0;
double sum = 0.0;
if (xlength != 0) {
for (i = 0; i < xlength; i++) {
sum += x[i];
}
}
return sum;
}
/*
======================================================================================================
r2
returns a random double value between 0 and 1
======================================================================================================
*/
double r2(void) {
return((rand() % 10000) / 10000.0);
}
/*
======================================================================================================
rndm
fills a double variable with random value and returns it
======================================================================================================
*/
double rndm(void) {
double rndmval = r2();
return rndmval;
}
/*
======================================================================================================
mkSvgGraph
parses template.svg and writes results in said template
======================================================================================================
*/
void mkSvgGraph(point_t points[], char *templatePath) {
FILE* input = NULL;
FILE *target = fopen("graphResults.html", "w");
if (templatePath){
printf("\ngraph template src at: %s\n", templatePath);
input = fopen(templatePath, "r");
} else {
input = fopen("graphResults_template.html", "r");
}
2018-05-16 12:47:49 +02:00
char line[512];
2018-05-19 20:52:39 +02:00
char firstGraph[15] = { "<path d=\"M0 0" }; // Position where points will be written after
2018-05-16 12:47:49 +02:00
if (input == NULL) {
printf("\nNo inputfile at mkSvgGraph()\n");
2018-05-16 12:47:49 +02:00
exit(EXIT_FAILURE);
2018-05-24 17:21:20 +02:00
}
2018-05-24 18:28:28 +02:00
char buffer[131072] = ""; // Really really dirty
2018-05-16 12:47:49 +02:00
memset(buffer, '\0', sizeof(buffer));
2018-05-19 20:52:39 +02:00
while (!feof(input)) { // parses file until "firstGraph" has been found
fgets(line, 512, input);
2018-05-16 12:47:49 +02:00
strncat(buffer, line, strlen(line));
2018-05-19 20:52:39 +02:00
if (strstr(line, firstGraph) != NULL) { // Compares line <-> "firstGraph"
bufferLogger(buffer, points); // write points
2018-05-16 12:47:49 +02:00
}
}
fprintf(target, buffer);
}
/*
======================================================================================================
rdPPM
reads data from file of type PPM, stores colorchannels in a struct in the
size of given picture
======================================================================================================
*/
static imagePixel_t *rdPPM(char *fileName) {
char buffer[16];
imagePixel_t *image;
int c, rgbColor;
double *tmp;
2018-05-16 12:47:49 +02:00
FILE *fp = fopen(fileName, "rb");
if (!fp) {
exit(EXIT_FAILURE);
}
if (!fgets(buffer, sizeof(buffer), fp)) {
perror(fileName);
exit(EXIT_FAILURE);
}
2018-05-24 18:28:28 +02:00
if (buffer[0] != 'P' || buffer[1] != '6') { // PPM files start with P6
2018-05-16 12:47:49 +02:00
fprintf(stderr, "No PPM file format\n");
exit(EXIT_FAILURE);
}
image = (imagePixel_t *)malloc(sizeof(imagePixel_t));
if (!image) {
fprintf(stderr, "malloc() failed");
}
c = getc(fp);
2018-05-24 18:28:28 +02:00
while (c == '#') { // PPM Comments start with #
2018-05-16 12:47:49 +02:00
while (getc(fp) != '\n');
c = getc(fp);
}
ungetc(c, fp);
2018-05-19 20:52:39 +02:00
if ( fscanf(fp, "%d %d", &image->x, &image->y) != 2 ) {
2018-05-16 12:47:49 +02:00
fprintf(stderr, "Invalid image size in %s\n", fileName);
exit(EXIT_FAILURE);
}
2018-05-19 20:52:39 +02:00
if ( fscanf(fp, "%d", &rgbColor) != 1 ) {
2018-05-16 12:47:49 +02:00
fprintf(stderr, "Invalid rgb component in %s\n", fileName);
}
2018-05-19 20:52:39 +02:00
if ( rgbColor != RGB_COLOR ) {
2018-05-16 12:47:49 +02:00
fprintf(stderr, "Invalid image color range in %s\n", fileName);
exit(EXIT_FAILURE);
}
2018-05-19 20:52:39 +02:00
while ( fgetc(fp) != '\n' );
2018-05-16 12:47:49 +02:00
image->data = (colorChannel_t *)malloc(image->x * image->y * sizeof(imagePixel_t));
if (!image) {
fprintf(stderr, "malloc() on image->data failed");
2018-05-16 12:47:49 +02:00
exit(EXIT_FAILURE);
}
if ( (image->x * image->y) < mlData->samplesCount) {
printf("Changing \"-n\" to %d, image max data size\n", ( image->x * image->y ) );
tmp = (double *) realloc ( xSamples, sizeof(double) * (image->x * image->y) );
xSamples = tmp;
2018-05-24 18:28:28 +02:00
mlData->samplesCount = (image->x * image->y );
}
if ( fread( image->data, 3 * image->x, image->y, fp) != image->y) {
2018-05-16 12:47:49 +02:00
fprintf(stderr, "Loading image failed");
exit(EXIT_FAILURE);
}
fclose(fp);
return image;
}
/*
======================================================================================================
mkPpmFile
2018-05-19 20:52:39 +02:00
gets output from result of rdPPM and writes a new PPM file. Best Case is a
carbon copy of the source image. Build for debugging.
2018-05-16 12:47:49 +02:00
======================================================================================================
*/
void mkPpmFile(char *fileName, imagePixel_t *image) {
FILE* fp = fopen(fileName, "wb");
if (!fp) {
fprintf(stderr, "Opening file failed.");
exit(EXIT_FAILURE);
}
fprintf(fp, "P6\n");
fprintf(fp, "%d %d\n", image->x, image->y);
fprintf(fp, "%d\n", RGB_COLOR);
fwrite(image->data, 3 * image->x, image->y, fp);
fclose(fp);
}
/*
======================================================================================================
ppmColorChannel
gets one of the rgb color channels and writes them to a file
======================================================================================================
*/
int ppmColorChannel(FILE* fp, imagePixel_t *image, char *colorChannel, mldata_t *mlData) {
unsigned i = 0;
2018-05-16 12:47:49 +02:00
2018-05-19 20:52:39 +02:00
printf("colorChannel : %s\n", colorChannel);
if ( image ) { // RGB channel can be set through args from cli
if ( strcmp(colorChannel, "green") == 0 ){
for ( i = 0; i < mlData->samplesCount - 1; i++ ) {
fprintf ( fp, "%d\n", image->data[i].green );
2018-05-16 23:54:38 +02:00
}
2018-05-19 20:52:39 +02:00
} else if ( strcmp(colorChannel, "red") == 0 ){
for ( i = 0; i < mlData->samplesCount - 1; i++ ) {
fprintf ( fp, "%d\n", image->data[i].red );
2018-05-16 23:54:38 +02:00
}
} else if ( strcmp(colorChannel, "blue") == 0 ) {
2018-05-19 20:52:39 +02:00
for ( i = 0; i < mlData->samplesCount - 1; i++ ) {
fprintf ( fp, "%d\n", image->data[i].blue );
2018-05-16 23:54:38 +02:00
}
} else {
printf("Colorchannels are red, green and blue. Pick one of them!");
2018-05-19 20:52:39 +02:00
exit( EXIT_FAILURE );
2018-05-16 12:47:49 +02:00
}
}
fclose(fp);
2018-05-19 20:52:39 +02:00
return mlData->samplesCount; // returned for debugging, TODO: void PPmcolorChannel
2018-05-16 12:47:49 +02:00
}
/*
======================================================================================================
colorSamples
2018-05-16 23:54:38 +02:00
reads colorChannel values from file and stores them in xSamples as well as in points datatype for
2018-05-16 12:47:49 +02:00
creating the SVG graph
======================================================================================================
*/
void colorSamples ( FILE* fp, mldata_t *mlData ) {
2018-05-16 12:47:49 +02:00
int i = 0;
char *buffer = (char *) malloc(sizeof(char) * mlData->samplesCount + 1);
2018-05-19 20:52:39 +02:00
2018-05-16 12:47:49 +02:00
while (!feof(fp)) {
2018-05-19 20:52:39 +02:00
if (fgets(buffer, mlData->samplesCount, fp) != NULL) {
2018-05-24 18:28:28 +02:00
sscanf(buffer, "%lf", &xSamples[i]);
2018-05-19 20:52:39 +02:00
points[i].yVal[0] = xSamples[i]; // Fills points so actual input values can be seen as a graph
2018-05-16 12:47:49 +02:00
points[i].xVal[0] = i;
++i;
}
}
fclose(fp);
}
/*
======================================================================================================
windowXMean
2018-05-19 20:52:39 +02:00
returns mean value of given input
2018-05-16 12:47:49 +02:00
======================================================================================================
*/
double windowXMean(int _arraylength, int xCount) {
double sum = 0.0;
double *ptr;
2018-05-24 18:28:28 +02:00
for (ptr = &xSamples[xCount - _arraylength]; ptr != &xSamples[xCount]; ptr++) { // Set ptr to beginning of window and iterate through array
2018-05-16 12:47:49 +02:00
sum += *ptr;
}
return sum / (double)_arraylength;
}
2018-05-16 23:54:38 +02:00
/*
======================================================================================================
usage
used in conjunction with the args parser. Returns help section of "-h"
======================================================================================================
*/
void usage ( char **argv ) {
printf("Usage: %s [POSIX style options] -i file ...\n", &argv[0][0]);
2018-05-16 23:54:38 +02:00
printf("POSIX options:\n");
printf("\t-h\t\t\tDisplay this information.\n");
printf("\t-i <filename>\t\tName of inputfile. Must be PPM image.\n");
printf("\t-n <digit>\t\tAmount of input data used.\n");
2018-05-16 23:54:38 +02:00
printf("\t-c <color>\t\tUse this color channel from inputfile.\n");
printf("\t-w <digit>\t\tCount of used weights (windowSize).\n");
printf("\t-l <digit>\t\tLearnrate, 0 < learnrate < 1.\n");
printf("\t-g true\t\t\tGraph building.\n\t\t\t\tChoose for n < 1200.\n");
printf("\t-s <digit>\t\tDigit for random seed generator.\n\t\t\t\tSame Digits produce same random values. Default is srand by time.\n");
2018-05-16 23:54:38 +02:00
printf("\n\n");
2018-05-24 15:15:22 +02:00
printf("%s compares prediction methods of least mean square filters.\nBy default it reads ppm file format and return logfiles as well\nas an svg graphs as an output of said least mean square methods.\n\nExample:\n\t%s -i myimage.ppm -w 3 -c green -s 5 -g true\n", &argv[0][0], &argv[0][0]);
2018-05-16 23:54:38 +02:00
exit(8);
}
/*
======================================================================================================
init_mldata_t
2018-05-24 18:28:28 +02:00
Init meachine learning data
======================================================================================================
*/
mldata_t * init_mldata_t(unsigned windowSize, unsigned samplesCount, double learnrate) {
mlData = (mldata_t *) malloc( sizeof(mldata_t) );
mlData->windowSize = windowSize;
mlData->samplesCount = samplesCount;
mlData->learnrate = learnrate;
2018-05-22 17:03:42 +02:00
mlData->weights = (double *) malloc ( sizeof(double) * windowSize + 1 );
return mlData;
}