218 lines
7.0 KiB
C++
218 lines
7.0 KiB
C++
//
|
|
// Created by Elie Baier on 23.02.24.
|
|
//
|
|
|
|
#include <cmath>
|
|
#include "iostream"
|
|
#include "string"
|
|
#include "fstream"
|
|
#include "sstream"
|
|
#include "matplot/matplot.h"
|
|
|
|
using namespace std;
|
|
namespace plt = matplot;
|
|
|
|
int MIN_ZERO_SEPARATION = 10;
|
|
int POWERED_MIN = 5;
|
|
int POWERED_MAX = 5;
|
|
|
|
vector<double> findZeroCrossings(const vector<double>& data) {
|
|
vector<double> zeroCrossings;
|
|
for (int i = 1; i < data.size(); ++i) {
|
|
if (data[i - 1] * data[i] < 0 || data[i - 1] * data[i] == 0) {
|
|
|
|
// Cleaning the duplicate zero which are +-MIN_ZERO_SEPARATION
|
|
if(zeroCrossings.size() >= 1) {
|
|
if(zeroCrossings[zeroCrossings.size() - 1] - MIN_ZERO_SEPARATION < i && zeroCrossings[zeroCrossings.size() - 1] + MIN_ZERO_SEPARATION > i) {
|
|
// cout << "Found duplicate zero: " << i << endl;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
zeroCrossings.push_back(i);
|
|
}
|
|
}
|
|
return zeroCrossings;
|
|
}
|
|
|
|
pair<double, bool> poweredMax(const vector<double>& data, int n) {
|
|
if (data.empty()) {
|
|
return {0.0, false}; // If vector is empty, return false
|
|
}
|
|
|
|
unordered_map<double, int> freqMap;
|
|
for (double value : data) {
|
|
freqMap[value]++;
|
|
}
|
|
|
|
double maxVal = data[0]; // Initialize maxVal with the first element
|
|
int maxFreq = freqMap[maxVal];
|
|
|
|
for (const auto& entry : freqMap) {
|
|
if (entry.second >= n && entry.first > maxVal) {
|
|
maxVal = entry.first;
|
|
maxFreq = entry.second;
|
|
}
|
|
}
|
|
|
|
bool found = maxFreq >= n;
|
|
|
|
return {maxVal, found};
|
|
}
|
|
|
|
std::pair<double, bool> poweredMin(const std::vector<double>& data, int n) {
|
|
if (data.empty()) {
|
|
return {0.0, false}; // If vector is empty, return false
|
|
}
|
|
|
|
std::unordered_map<double, int> freqMap;
|
|
for (double value : data) {
|
|
freqMap[value]++;
|
|
}
|
|
|
|
double minVal = std::numeric_limits<double>::max(); // Initialize minVal with maximum double value
|
|
int minFreq = freqMap[minVal];
|
|
|
|
for (const auto& entry : freqMap) {
|
|
if (entry.second >= n && entry.first < minVal) {
|
|
minVal = entry.first;
|
|
minFreq = entry.second;
|
|
}
|
|
}
|
|
|
|
bool found = minFreq >= n;
|
|
|
|
return {minVal, found};
|
|
}
|
|
|
|
std::vector<double> slice(const std::vector<double>& data, int start, int end) {
|
|
if (start < 0 || end >= static_cast<int>(data.size()) || start > end) {
|
|
std::cerr << "Invalid slice indices." << std::endl;
|
|
return {};
|
|
}
|
|
|
|
return {data.begin() + start, data.begin() + end + 1};
|
|
}
|
|
|
|
ifstream openFile(string path) {
|
|
ifstream file;
|
|
file.open(path);
|
|
if(!file.is_open()) {
|
|
std::cerr << "Error opening file." << std::endl;
|
|
}
|
|
return file;
|
|
}
|
|
|
|
int main() {
|
|
vector<ifstream> channels;
|
|
channels.push_back(openFile("/Users/eliebaier/Workspace/Physique/TP8/DATA/ALL0012/F0012CH1.CSV"));
|
|
channels.push_back(openFile("/Users/eliebaier/Workspace/Physique/TP8/DATA/ALL0012/F0012CH2.CSV"));
|
|
|
|
vector<vector<double>> channelsXData, channelsYData, channelsZeros;
|
|
vector<double> channelsP2P;
|
|
|
|
for(int channel = 0; channel < channels.size(); channel++) {
|
|
string line;
|
|
|
|
cout << "[INFO] Starting data fetching for channel " << channel << endl;
|
|
|
|
// Skipping the TEKTRONICS DEFINITION lines
|
|
cout << "[INFO] Skipping lines used by TEKTRONICS to store device data" << endl;
|
|
for(auto i = 0; i < 18; i++) {
|
|
getline(channels[channel], line);
|
|
}
|
|
|
|
cout << "[INFO] Reading channel data" << endl;
|
|
vector<double> xs, ys;
|
|
while(getline(channels[channel], line)) {
|
|
// Cleaning the lines
|
|
line.erase(0, 3);
|
|
line.erase(line.size() - 1, line.size());
|
|
|
|
std::string cleanedLine;
|
|
for (char c : line) {
|
|
if (std::isdigit(c) || c == '.' || c == ',') {
|
|
cleanedLine += c;
|
|
}
|
|
}
|
|
|
|
double x, y;
|
|
istringstream iss(line);
|
|
char comma;
|
|
if (!(iss >> x >> comma >> y)) {
|
|
std::cerr << "Error parsing line: " << line << std::endl;
|
|
continue;
|
|
}
|
|
xs.push_back(x);
|
|
ys.push_back(y);
|
|
}
|
|
|
|
channelsXData.push_back(xs);
|
|
channelsYData.push_back(ys);
|
|
|
|
cout << "[INFO] Closing channel " << channel << " file" << endl;
|
|
channels[channel].close();
|
|
|
|
cout << "[INFO] Finding zeros" << endl;
|
|
channelsZeros.push_back(findZeroCrossings(channelsYData[channel]));
|
|
|
|
vector<double> frequency;
|
|
for(int j = 0; j + 1 < channelsZeros[channel].size(); j=j+2) {
|
|
// cout << "[INFO] Processing zeros " << j << " and " << j+1 << endl;
|
|
frequency.push_back((channelsXData[channel][channelsZeros[channel][j + 1]] - channelsXData[channel][channelsZeros[channel][j]]));
|
|
}
|
|
|
|
double avgFrequency = 0;
|
|
for(auto freq : frequency) {
|
|
avgFrequency += freq;
|
|
}
|
|
avgFrequency /= (frequency.size());
|
|
avgFrequency *= 2;
|
|
cout << "[INFO] Average peak time is " << avgFrequency << "s" << endl;
|
|
cout << "[INFO] Average frequency is " << 1/avgFrequency << "Hz" << endl;
|
|
|
|
vector<double> mins, maxs;
|
|
for(int i = 1; i < channelsZeros[channel].size(); i++) {
|
|
// Checking if it's a min or a max by taking the middle and looking at the sign
|
|
if(channelsYData[channel][int (channelsZeros[channel][i - 1] + channelsZeros[channel][i])/2] >= 0) {
|
|
// This is a max
|
|
// cout << "Found max between " << xData[zeroCrossings[i - 1]] << " and " << xData[zeroCrossings[i]] << " ";
|
|
// cout << "max is: " << poweredMax(slice(yData, zeroCrossings[i - 1], zeroCrossings[i]), 5).first << endl;
|
|
maxs.push_back(poweredMax(slice(channelsYData[channel], channelsZeros[channel][i - 1], channelsZeros[channel][i]), POWERED_MAX).first);
|
|
} else {
|
|
mins.push_back(poweredMin(slice(channelsYData[channel], channelsZeros[channel][i - 1], channelsZeros[channel][i]), POWERED_MIN).first);
|
|
}
|
|
}
|
|
|
|
double avgMax = 0, avgMin = 0;
|
|
for(auto max : maxs) {
|
|
avgMax += max;
|
|
}
|
|
for(auto min : mins) {
|
|
avgMin += min;
|
|
}
|
|
avgMax /= maxs.size();
|
|
avgMin /= mins.size();
|
|
cout << "[INFO] Average Peak-to-Peak for channel " << channel << " is " << abs(avgMin) + abs(avgMax) << endl;
|
|
channelsP2P.push_back(abs(avgMin) + abs(avgMax));
|
|
}
|
|
|
|
plt::plot(channelsXData[0], channelsYData[0], channelsXData[1], channelsYData[1]);
|
|
plt::xlabel("X Label");
|
|
plt::ylabel("Y Label");
|
|
plt::title("Line Plot");
|
|
|
|
/* vector<double> zeroCrossings = findZeroCrossings(yData);
|
|
|
|
// Drawing lines on the found zeros
|
|
for(auto zero : zeroCrossings) {
|
|
cout << "Zero: " << zero << endl;
|
|
plt::line(xData[zero], -2, xData[zero], 2);
|
|
} */
|
|
|
|
// Show the plot
|
|
plt::show();
|
|
|
|
return 0;
|
|
|
|
} |