From d31bedd63e5401bebdf1a041047c6d5be21b58f4 Mon Sep 17 00:00:00 2001 From: mrheltic Date: Thu, 21 Nov 2024 16:35:08 +0100 Subject: [PATCH] Added other tests Added tests for: -Average (all cases) -STD (all cases) -Anomaly detection (on a uniform distribution) --- include/dataAcquisition.h | 10 +++- libraries/dataAcquisition.c | 59 +++++++++++++++++++--- test/test_dataAcquisition.c | 97 +++++++++++++++++++++++++++++++++++-- 3 files changed, 155 insertions(+), 11 deletions(-) diff --git a/include/dataAcquisition.h b/include/dataAcquisition.h index 8efb0c4..5443f42 100644 --- a/include/dataAcquisition.h +++ b/include/dataAcquisition.h @@ -6,7 +6,7 @@ #include void initializeReadings(); -void freeReadings(); +bool freeReadings(); int getSensorsNumber(); int getSlidingWindowSize(); @@ -20,6 +20,12 @@ float getOverallAverage(); float getStandardDeviationOnSensor(int sensorIndex); float getStandardDeviationOnAllSensors(); -float getStandardDeviationOnAllSensors(); +float getOverallStandardDeviation(); + +float getLastReading(int sensorIndex); + +bool anomalyDetect(float average, float standardDeviation); + +int getOutlierCount(); #endif // DATA_ACQUISITION_H \ No newline at end of file diff --git a/libraries/dataAcquisition.c b/libraries/dataAcquisition.c index 87e6d1f..4e9c78f 100644 --- a/libraries/dataAcquisition.c +++ b/libraries/dataAcquisition.c @@ -3,6 +3,8 @@ #include #include +int outlierCount; + // Variable definition static float **readings; static int sensorsNumber; @@ -35,11 +37,19 @@ void initializeReadings(int numSensors, int windowSize) { setSlidingWindowSize(windowSize); } -void freeReadings() { +bool freeReadings() { for (int i = 0; i < sensorsNumber; i++) { free(readings[i]); } - free(readings); + + if(readings != NULL){ + free(readings); + return true; + } + else{ + return false; + } + } // Functions @@ -64,6 +74,14 @@ bool isFull(int sensorIndex) { return true; } +float getLastReading(int sensorIndex) { + if (isFull(sensorIndex)) { + return readings[sensorIndex][slidingWindowSize - 1]; + } else { + return readings[sensorIndex][0]; + } +} + // Add a reading to the readings array void addReading(float value, int sensorIndex) { if (isFull(sensorIndex)) { @@ -75,6 +93,8 @@ void addReading(float value, int sensorIndex) { for (int i = 0; i < slidingWindowSize; i++) { if (readings[sensorIndex][i] == 0) { readings[sensorIndex][i] = value; + // Update the position index + break; } @@ -99,7 +119,7 @@ float getAverageOnSensor(int sensorIndex) { float getAverageOnAllSensors() { float sum = 0; for (int i = 0; i < sensorsNumber; i++) { - sum += getAverageOnSensor(i); + sum += getLastReading(i); } return sum / sensorsNumber; } @@ -137,15 +157,33 @@ float getStandardDeviationOnSensor(int sensorIndex) { float getStandardDeviationOnAllSensors() { float sum = 0; + float average = getAverageOnAllSensors(); for (int i = 0; i < sensorsNumber; i++) { - sum += getStandardDeviationOnSensor(i); + float lastReading = getLastReading(i); + sum += pow(lastReading - average, 2); } - return sum / sensorsNumber; + + return sqrt(sum / sensorsNumber); +} + +void anomalyDetect(float average, float standardDeviation) { + float upperThreshold = average + 2.17 * standardDeviation; // 97% confidence interval + float lowerThreshold = average - 2.17 * standardDeviation; // Lower bound for anomaly detection + outlierCount = 0; + for (int i = 0; i < sensorsNumber; i++) { + for (int j = 0; j < slidingWindowSize; j++) { + if (readings[i][j] > upperThreshold || readings[i][j] < lowerThreshold) { + outlierCount++; + } + } + } + } float getOverallStandardDeviation() { float sum = 0; int totalReadings = 0; + float totalAverage = getOverallAverage(); for (int i = 0; i < sensorsNumber; i++) { if (!isFull(i)) { printf("The sliding window for sensor %d is not full\n", i); @@ -156,5 +194,14 @@ float getOverallStandardDeviation() { totalReadings++; } } - return sqrt(sum / totalReadings); + + float totalStandardDeviation = sqrt(sum / totalReadings); + + anomalyDetect(totalAverage, totalStandardDeviation); + + return totalStandardDeviation; +} + +int getOutlierCount() { + return outlierCount; } \ No newline at end of file diff --git a/test/test_dataAcquisition.c b/test/test_dataAcquisition.c index d8227a2..0cd2644 100644 --- a/test/test_dataAcquisition.c +++ b/test/test_dataAcquisition.c @@ -3,14 +3,105 @@ #include #include "../include/dataAcquisition.h" +#define NUMBER_OF_SENSORS 5 +#define SLIDING_WINDOW_SIZE 10 + +#define AVERAGE_UNCERTAINTY 0.01 +#define STD_UNCERTAINTY 0.01 + +// Testing the inizialization and the instanciacion of the sensors' number and sliding window size void test_initializeReadings() { - initializeReadings(5, 100); - assert(getSensorsNumber() == 5); - assert(getSlidingWindowSize() == 100); + initializeReadings(NUMBER_OF_SENSORS, SLIDING_WINDOW_SIZE); + assert(getSensorsNumber() == NUMBER_OF_SENSORS); + assert(getSlidingWindowSize() == SLIDING_WINDOW_SIZE); } +// Testing the logic of add readings to see if the slidinw window is full +void test_addReading() { + for (int sensor = 0; sensor < NUMBER_OF_SENSORS; sensor++) { + for (int value = 1; value <= SLIDING_WINDOW_SIZE; value++) { + addReading(value, sensor); + } + } + assert(isFull(NUMBER_OF_SENSORS-1) == true); // Assuming the last sensor acquired the data +} + +// Testing the logic of average methods +void test_averageOnSensor() { + printf("Average on sensor %d: %f\n", NUMBER_OF_SENSORS-1, getAverageOnSensor(NUMBER_OF_SENSORS-1)); + float average = getAverageOnSensor(NUMBER_OF_SENSORS-1); + float expected_average = (SLIDING_WINDOW_SIZE + 1) / 2.0; + assert(fabs(average - expected_average) < AVERAGE_UNCERTAINTY); +} + +void test_standardDeviationOnSensor() { + printf("Standard deviation on sensor %d: %f\n", NUMBER_OF_SENSORS-1, getStandardDeviationOnSensor(NUMBER_OF_SENSORS-1)); + float standard_deviation = getStandardDeviationOnSensor(NUMBER_OF_SENSORS-1); + float expected_standard_deviation = 2.872281323269; + assert(fabs(standard_deviation - expected_standard_deviation) < STD_UNCERTAINTY); +} + +void test_averageOnAllSensors() { + printf("Average on all sensors: %f\n", getAverageOnAllSensors()); + float average = getAverageOnAllSensors(); + float expected_average = SLIDING_WINDOW_SIZE; + assert(fabs(average - expected_average) < AVERAGE_UNCERTAINTY); +} + +void test_standardDeviationOnAllSensors() { + printf("Standard deviation on all sensors: %f\n", getStandardDeviationOnAllSensors()); + float standard_deviation = getStandardDeviationOnAllSensors(); + float expected_standard_deviation = 0; + assert(fabs(standard_deviation - expected_standard_deviation) < STD_UNCERTAINTY); +} + +void test_overallAverage(){ + printf("Overall average on all sensors: %f\n", getOverallAverage()); + float average = getOverallAverage(); + float expected_overall_average = (SLIDING_WINDOW_SIZE + 1) / 2.0; + assert(fabs(average - expected_overall_average) < AVERAGE_UNCERTAINTY); +} + +void test_overallStandardDeviation(){ + printf("Overall standard deviation: %f\n", getOverallStandardDeviation()); + float standard_deviation = getStandardDeviationOnSensor(NUMBER_OF_SENSORS-1); + float expected_standard_deviation = 2.872281323269; + assert(fabs(standard_deviation - expected_standard_deviation) < STD_UNCERTAINTY); +} + +void test_anomalyDetect(){ + float average = getOverallAverage(); + float standard_deviation = getOverallStandardDeviation(); + anomalyDetect(average, standard_deviation); + printf("Outlier count: %i\n", getOutlierCount()); + assert(fabs(getOutlierCount() - 0) < 0.01); + + // Adding an outlier + addReading(20, NUMBER_OF_SENSORS-1); + average = getOverallAverage(); + standard_deviation = getOverallStandardDeviation(); + anomalyDetect(average, standard_deviation); + printf("Outlier count: %i\n", getOutlierCount()); + assert(fabs(getOutlierCount() - 1) < 0.01); +} + +// TODO: Test all the functions with a normal distribution + +// TODO: Evaluate the normal distribution with the anomaly detection +void test_freeReadings() { + assert(freeReadings() == true); +} int main() { test_initializeReadings(); + test_addReading(); + test_averageOnSensor(); + test_standardDeviationOnSensor(); + test_averageOnAllSensors(); + test_standardDeviationOnAllSensors(); + test_overallAverage(); + test_overallStandardDeviation(); + test_anomalyDetect(); + test_freeReadings(); return 0; } \ No newline at end of file