add: fix for frequency & svg picture
This commit is contained in:
209
main.cpp
209
main.cpp
@@ -8,18 +8,25 @@
|
||||
#include "fstream"
|
||||
#include "sstream"
|
||||
#include "matplot/matplot.h"
|
||||
#include <filesystem>
|
||||
|
||||
using namespace std;
|
||||
namespace plt = matplot;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
int MIN_ZERO_SEPARATION = 10;
|
||||
int POWERED_MIN = 5;
|
||||
int POWERED_MAX = 5;
|
||||
int MIN_ZERO_SEPARATION = 100;
|
||||
int POWERED_MIN = 3;
|
||||
int POWERED_MAX = 3;
|
||||
|
||||
vector<double> findZeroCrossings(const vector<double>& data) {
|
||||
vector<double> zeroCrossings;
|
||||
long double average(vector<long double> a)
|
||||
{
|
||||
return reduce(a.begin(), a.end(), 0.0) / a.size();
|
||||
}
|
||||
|
||||
vector<long double> findZeroCrossings(const vector<long double>& data, long double absZero) {
|
||||
vector<long double> zeroCrossings;
|
||||
for (int i = 1; i < data.size(); ++i) {
|
||||
if (data[i - 1] * data[i] < 0 || data[i - 1] * data[i] == 0) {
|
||||
if ((data[i - 1] - absZero) * (data[i] - absZero) < 0 || (data[i - 1] - absZero) * (data[i] - absZero) == 0) {
|
||||
|
||||
// Cleaning the duplicate zero which are +-MIN_ZERO_SEPARATION
|
||||
if(zeroCrossings.size() >= 1) {
|
||||
@@ -35,17 +42,17 @@ vector<double> findZeroCrossings(const vector<double>& data) {
|
||||
return zeroCrossings;
|
||||
}
|
||||
|
||||
pair<double, bool> poweredMax(const vector<double>& data, int n) {
|
||||
pair<long double, bool> poweredMax(const vector<long 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) {
|
||||
unordered_map<long double, int> freqMap;
|
||||
for (long double value : data) {
|
||||
freqMap[value]++;
|
||||
}
|
||||
|
||||
double maxVal = data[0]; // Initialize maxVal with the first element
|
||||
long double maxVal = data[0]; // Initialize maxVal with the first element
|
||||
int maxFreq = freqMap[maxVal];
|
||||
|
||||
for (const auto& entry : freqMap) {
|
||||
@@ -60,17 +67,17 @@ pair<double, bool> poweredMax(const vector<double>& data, int n) {
|
||||
return {maxVal, found};
|
||||
}
|
||||
|
||||
std::pair<double, bool> poweredMin(const std::vector<double>& data, int n) {
|
||||
std::pair<long double, bool> poweredMin(const std::vector<long 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) {
|
||||
std::unordered_map<long double, int> freqMap;
|
||||
for (long double value : data) {
|
||||
freqMap[value]++;
|
||||
}
|
||||
|
||||
double minVal = std::numeric_limits<double>::max(); // Initialize minVal with maximum double value
|
||||
long double minVal = std::numeric_limits<long double>::max(); // Initialize minVal with maximum double value
|
||||
int minFreq = freqMap[minVal];
|
||||
|
||||
for (const auto& entry : freqMap) {
|
||||
@@ -85,7 +92,7 @@ std::pair<double, bool> poweredMin(const std::vector<double>& data, int n) {
|
||||
return {minVal, found};
|
||||
}
|
||||
|
||||
std::vector<double> slice(const std::vector<double>& data, int start, int end) {
|
||||
std::vector<long double> slice(const std::vector<long 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 {};
|
||||
@@ -103,18 +110,26 @@ ifstream openFile(string path) {
|
||||
return file;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int analyseOne(int i, ofstream &out) {
|
||||
cout << setprecision(13);
|
||||
out << setprecision(13);
|
||||
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"));
|
||||
if(i < 10) {
|
||||
channels.push_back(openFile("/Users/eliebaier/Workspace/Physique/TP8/DATA/ALL000" + to_string(i) + "/F000" + to_string(i) + "CH1.CSV"));
|
||||
channels.push_back(openFile("/Users/eliebaier/Workspace/Physique/TP8/DATA/ALL000" + to_string(i) + "/F000" + to_string(i) + "CH2.CSV"));
|
||||
} else {
|
||||
channels.push_back(openFile("/Users/eliebaier/Workspace/Physique/TP8/DATA/ALL00" + to_string(i) + "/F00" + to_string(i) + "CH1.CSV"));
|
||||
channels.push_back(openFile("/Users/eliebaier/Workspace/Physique/TP8/DATA/ALL00" + to_string(i) + "/F00" + to_string(i) + "CH2.CSV"));
|
||||
}
|
||||
|
||||
vector<vector<double>> channelsXData, channelsYData, channelsZeros;
|
||||
vector<double> channelsP2P;
|
||||
double channelOneT = 0;
|
||||
vector<vector<long double>> channelsXData, channelsYData, channelsZeros;
|
||||
vector<long double> channelsP2P, channelsAbsoluteZero, channelsTimings, channelsFrequency;
|
||||
long double channelOneT = 0;
|
||||
|
||||
for(int channel = 0; channel < channels.size(); channel++) {
|
||||
string line;
|
||||
|
||||
cout << "========== CHANNEL " << channel << " ==========" << endl;
|
||||
cout << "[INFO] Starting data fetching for channel " << channel << endl;
|
||||
|
||||
// Skipping the TEKTRONICS DEFINITION lines
|
||||
@@ -124,7 +139,7 @@ int main() {
|
||||
}
|
||||
|
||||
cout << "[INFO] Reading channel data" << endl;
|
||||
vector<double> xs, ys;
|
||||
vector<long double> xs, ys;
|
||||
while(getline(channels[channel], line)) {
|
||||
// Cleaning the lines
|
||||
line.erase(0, 3);
|
||||
@@ -137,7 +152,7 @@ int main() {
|
||||
}
|
||||
}
|
||||
|
||||
double x, y;
|
||||
long double x, y;
|
||||
istringstream iss(line);
|
||||
char comma;
|
||||
if (!(iss >> x >> comma >> y)) {
|
||||
@@ -147,49 +162,60 @@ int main() {
|
||||
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();
|
||||
|
||||
// Finding the zeros and finding the average minimum and the average maximum (also finding the reference zero)
|
||||
// Finding the absolute max (powered)
|
||||
cout << "[INFO] Finding the absolute max and min" << endl;
|
||||
double absoluteMax = poweredMax(channelsYData[channel], POWERED_MAX).first;
|
||||
cout << "[INFO] Absolute max is " << absoluteMax << endl;
|
||||
double absoluteMin = poweredMin(channelsYData[channel], POWERED_MAX).first;
|
||||
cout << "[INFO] Absolute min is " << absoluteMin << endl;
|
||||
|
||||
// Find the reference zero and the offset to the measured one
|
||||
channelsAbsoluteZero.push_back((absoluteMax + absoluteMin)/2);
|
||||
cout << "[INFO] Reference zero is " << channelsAbsoluteZero[channel] << endl;
|
||||
|
||||
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;
|
||||
if(channel == 0) {
|
||||
channelOneT = avgFrequency;
|
||||
cout << "Set chan 1 freq: " << channelOneT << endl;
|
||||
}
|
||||
|
||||
vector<double> mins, maxs;
|
||||
channelsZeros.push_back(findZeroCrossings(channelsYData[channel], channelsAbsoluteZero[channel]));
|
||||
vector<long 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
|
||||
// Add subtraction with channelsAbsoluteZero[channel]
|
||||
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);
|
||||
long double newlyMax = poweredMax(slice(channelsYData[channel], channelsZeros[channel][i - 1], channelsZeros[channel][i]), POWERED_MAX).first;
|
||||
cout << "Max found " << newlyMax << endl;
|
||||
maxs.push_back(newlyMax);
|
||||
} else {
|
||||
mins.push_back(poweredMin(slice(channelsYData[channel], channelsZeros[channel][i - 1], channelsZeros[channel][i]), POWERED_MIN).first);
|
||||
}
|
||||
}
|
||||
|
||||
double avgMax = 0, avgMin = 0;
|
||||
vector<long double> frequency;
|
||||
for(int j = 0; j + 2 < channelsZeros[channel].size(); j=j+2) {
|
||||
// cout << "[INFO] Processing zeros " << j << " and " << j+1 << endl;
|
||||
frequency.push_back(((channelsXData[channel][channelsZeros[channel][j + 2]]) - channelsXData[channel][channelsZeros[channel][j]]));
|
||||
cout << "[INFO] Distance between zero " << j << " (" << channelsZeros[channel][j] << ") and " << j+2 << " (" << channelsZeros[channel][j + 2] << ") is " << ((channelsXData[channel][channelsZeros[channel][j + 2]]) - channelsXData[channel][channelsZeros[channel][j]]) << " (" << channelsZeros[channel][j+2] - channelsZeros[channel][j] << ")" << endl;
|
||||
}
|
||||
|
||||
long double avgFrequency = average(frequency);
|
||||
// avgFrequency *= 2;
|
||||
cout << "[INFO] Average peak time for channel " << channel << " is " << avgFrequency << "s" << endl;
|
||||
channelsTimings.push_back(avgFrequency);
|
||||
cout << "[INFO] Average frequency for channel " << channel << " is " << 1/avgFrequency << "Hz" << endl;
|
||||
channelsFrequency.push_back(1/avgFrequency);
|
||||
if(channel == 0) {
|
||||
channelOneT = avgFrequency;
|
||||
// cout << "Set chan 1 freq: " << channelOneT << endl;
|
||||
}
|
||||
|
||||
long double avgMax = 0, avgMin = 0;
|
||||
for(auto max : maxs) {
|
||||
avgMax += max;
|
||||
}
|
||||
@@ -198,25 +224,58 @@ int main() {
|
||||
}
|
||||
avgMax /= maxs.size();
|
||||
avgMin /= mins.size();
|
||||
cout << "[INFO] Average Peak for channel " << channel << " max is " << avgMax << endl;
|
||||
cout << "[INFO] Average Peak for channel " << channel << " min is " << avgMin << endl;
|
||||
cout << "[INFO] Average Peak-to-Peak for channel " << channel << " is " << abs(avgMin) + abs(avgMax) << endl;
|
||||
// Change this to subtraction for cases which are all negative
|
||||
channelsP2P.push_back(abs(avgMin) + abs(avgMax));
|
||||
}
|
||||
|
||||
cout << "[INFO] Starting the calculate the phase shift" << endl;
|
||||
double deltas;
|
||||
long double deltas = 0;
|
||||
int ndeltas = 0;
|
||||
for(int i = 0; i < channelsZeros[0].size(); i++) {
|
||||
if(channelsZeros[1].size() <= i) continue;
|
||||
// cout << "[INFO] Phase shift for zero " << i << " is " << ((channelsXData[0][channelsZeros[0][i]] - channelsXData[1][channelsZeros[1][i]]) / channelOneT) * 360 << endl;
|
||||
deltas += channelsXData[1][channelsZeros[1][i]] - channelsXData[0][channelsZeros[0][i]];
|
||||
long double d = channelsXData[1][channelsZeros[1][i]] - channelsXData[0][channelsZeros[0][i]];
|
||||
cout << "[INFO] Phase shift for zero " << i << " is " << ((d) / channelOneT) * (-360) << endl;
|
||||
deltas += (d / channelOneT) * (-360);
|
||||
ndeltas++;
|
||||
}
|
||||
cout << "[INFO] Average phase shift (CHA0 to CHA1) " << ((deltas/ndeltas) / channelOneT) * 360 << endl;
|
||||
deltas /= ndeltas;
|
||||
// cout << ndeltas << deltas << channelOneT << endl;
|
||||
cout << "[INFO] Average phase shift (CHA0 to CHA1) " << deltas << endl;
|
||||
|
||||
plt::plot(channelsXData[0], channelsYData[0], channelsXData[1], channelsYData[1]);
|
||||
plt::xlabel("X Label");
|
||||
plt::ylabel("Y Label");
|
||||
plt::title("Line Plot");
|
||||
cout << "[INFO] Writing to CSV" << endl;
|
||||
out << i << "," << deltas << "," << channelsP2P[0] << "," << channelsP2P[1] << "," << channelsTimings[0] << "," << channelsTimings[1] << "," << channelsFrequency[0] << "," << channelsFrequency[1] << "\n";
|
||||
|
||||
plt::tiledlayout(1, 1);
|
||||
|
||||
auto ax1 = plt::nexttile();
|
||||
|
||||
plt::plot(channelsXData[0], channelsYData[0]);
|
||||
plt::xlabel("Temps [s]");
|
||||
plt::ylabel("Tension [V]");
|
||||
plt::title("Tension en fonction du temps (Mesure 00" + to_string(i) + ")");
|
||||
|
||||
plt::hold(matplot::on);
|
||||
|
||||
plt::plot(channelsXData[1], channelsYData[1])->use_y2(true);
|
||||
|
||||
plt::grid(matplot::on);
|
||||
plt::gca()->minor_grid(true);
|
||||
|
||||
auto lgd = ::matplot::legend(ax1, {"Générateur", "Bornes de la résistance"});
|
||||
lgd->location(matplot::legend::general_alignment::bottomleft);
|
||||
lgd->box(false);
|
||||
|
||||
/* auto ax2 = plt::nexttile();
|
||||
plt::plot(ax2, channelsXData[1], channelsYData[1]);
|
||||
plt::xlabel(ax2, "Temps [s]");
|
||||
plt::ylabel(ax2, "Tension [V]");
|
||||
plt::title(ax2, "Tension aux bornes de la résistance en fonction du temps (Mesure 00" + to_string(i) + ")");
|
||||
|
||||
plt::grid(matplot::on);
|
||||
plt::gca()->minor_grid(true); */
|
||||
|
||||
/* vector<double> zeroCrossings = findZeroCrossings(yData);
|
||||
|
||||
@@ -227,8 +286,42 @@ int main() {
|
||||
} */
|
||||
|
||||
// Show the plot
|
||||
plt::show();
|
||||
// plt::show();
|
||||
|
||||
/* cout << "[INFO] Saving svg to " << "/Users/eliebaier/Workspace/Physique/TP8/build/" + to_string(i) + "/ch1.svg" << endl;
|
||||
fs::create_directories("./build/" + to_string(i));
|
||||
plt::save("/Users/eliebaier/Workspace/Physique/TP8/build/" + to_string(i) + "/ch1.svg"); */
|
||||
|
||||
/* plt::tiledlayout(2, 1);
|
||||
|
||||
auto ax2 = plt::nexttile();
|
||||
|
||||
plt::plot(ax2, channelsXData[1], channelsYData[1]);
|
||||
plt::xlabel(ax2, "Temps [s]");
|
||||
plt::ylabel(ax2, "Tension [V]");
|
||||
plt::title(ax2, "Tension aux bornes de la résistance en fonction du temps (Mesure 00" + to_string(i) + ")"); */
|
||||
|
||||
/* for(auto zero : channelsZeros[1]) {
|
||||
cout << "Zero: " << zero << endl;
|
||||
plt::line(channelsXData[1][zero], -2, channelsXData[1][zero], 2);
|
||||
} */
|
||||
|
||||
// plt::show();
|
||||
|
||||
cout << "[INFO] Saving svg to " << "/Users/eliebaier/Workspace/Physique/TP8/build/" + to_string(i) + "/both-with-label.svg" << endl;
|
||||
fs::create_directories("./build/" + to_string(i));
|
||||
plt::save("/Users/eliebaier/Workspace/Physique/TP8/build/" + to_string(i) + "/both-with-label.svg");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::ofstream out;
|
||||
out.open("/Users/eliebaier/Workspace/Physique/TP8/build/out.csv");
|
||||
out << "Mesure, Average Phase Shift, Ch1 Peak-to-Peak, Ch2 Peak-to-Peak, Ch1 Time, Ch2 Time, Ch1 Frequency, Ch2 Frequency" << endl;
|
||||
for(int i = 0; i < 53; i++) {
|
||||
analyseOne(i, out);
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
Reference in New Issue
Block a user