Main
unknown
c_cpp
10 months ago
6.9 kB
6
Indexable
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <filesystem>
#include <map>
#include <set>
#include <functional>
#include <unordered_set>
using namespace std;
namespace fs = filesystem;
struct Parameters {
int vt, width, pulse_delta, below_drop_ratio;
double drop_ratio;
};
bool parseIniFile(const string& filename, Parameters& params) {
ifstream file(filename);
if (!file) {
cerr << "Invalid INI file: " << filename << " could not be opened.\n";
return false;
}
map<string, string> paramMap;
set<string> allowedKeys = { "vt", "width", "pulse_delta", "drop_ratio", "below_drop_ratio" };
string line;
while (getline(file, line)) {
if (line.empty() || line[0] == '#') continue;
istringstream iss(line);
string key, value;
if (getline(iss, key, '=') && getline(iss, value)) {
// Checking for any unexpected keys
if (allowedKeys.find(key) == allowedKeys.end()) {
cerr << "Invalid or duplicate INI key: " << key << "\n";
return false;
}
// Checking for duplicates
if (paramMap.find(key) != paramMap.end()) {
cerr << "Invalid or duplicate INI key: " << key << "\n";
return false;
}
paramMap[key] = value;
}
}
// Check for missing keys
for (const string& requiredKey : allowedKeys) {
if (paramMap.find(requiredKey) == paramMap.end()) {
cerr << "Invalid INI file: missing one or more keys\n";
return false;
}
}
try {
params.vt = stoi(paramMap.at("vt"));
params.width = stoi(paramMap.at("width"));
params.pulse_delta = stoi(paramMap.at("pulse_delta"));
params.drop_ratio = stod(paramMap.at("drop_ratio"));
params.below_drop_ratio = stoi(paramMap.at("below_drop_ratio"));
}
catch (const invalid_argument& e) {
cerr << "Invalid value for vt in " << filename << "\n";
return false;
}
return true;
}
vector<int> readAndNegateFile(const string& filename) {
ifstream file(filename);
vector<int> data((istream_iterator<int>(file)), istream_iterator<int>());
transform(data.begin(), data.end(), data.begin(), negate<int>());
return data;
}
vector<int> smoothData(const vector<int>& data) {
if (data.size() < 7) return data;
vector<int> smoothed;
copy(data.begin(), data.begin() + 3, std::back_inserter(smoothed));
for (size_t i = 3; i < data.size() - 3; ++i) {
int avg = ((data[i - 3]) + (2 * data[i - 2]) + (3 * data[i - 1]) + (3 * data[i]) + (3 * data[i + 1]) + (2 * data[i + 2]) + (data[i + 3])) / 15;
smoothed.push_back(avg);
}
copy(data.end() - 3, data.end(), std::back_inserter(smoothed));
return smoothed;
}
vector<int> detectPulses(const vector<int>& smoothed, int vt) {
vector<int> pulses;
for (size_t i = 0; i < smoothed.size() - 2; ++i) {
if (smoothed[i + 2] - smoothed[i] > vt) {
pulses.push_back(i);
while (i + 2 < smoothed.size() && smoothed[i + 2] >= smoothed[i]) {
i++;
}
}
}
return pulses;
}
void processFiles(const Parameters& params) {
for (const auto& entry : fs::directory_iterator(".")) {
if (entry.path().extension() == ".dat") {
vector<int> data = readAndNegateFile(entry.path().string());
if (data.empty()) continue;
vector<int> smoothed = smoothData(data);
vector<int> pulses = detectPulses(smoothed, params.vt);
if (pulses.empty()) continue;
cout << entry.path().filename() << ":\n";
unordered_set<int> ignored_pulses;
for (auto it = pulses.begin(); it != pulses.end(); ++it) {
auto nextIt = std::adjacent_find(it, pulses.end(), [params](int a, int b) { return b - a <= params.pulse_delta; });
if (nextIt != pulses.end()) {
int firstPulse = *it;
int nextPulse = *nextIt;
int peak = smoothed[firstPulse];
for (int j = firstPulse + 1; j <= nextPulse; ++j) {
peak = max(peak, smoothed[j]);
}
if (peak > 0) {
int drop_count = 0;
for (int j = firstPulse + 1; j < nextPulse; ++j) {
if (smoothed[j] > params.drop_ratio * peak) {
drop_count++;
}
}
if (drop_count < params.below_drop_ratio) {
// Ensure the first pulse is not already ignored
if (ignored_pulses.count(firstPulse) == 0) {
ignored_pulses.insert(firstPulse);
cout << "Found piggyback at " << firstPulse << "\n";
}
}
}
it = nextIt;
}
}
for (size_t i = 0; i < pulses.size(); ++i) {
if (ignored_pulses.count(pulses[i])) continue;
int pulseStart = pulses[i];
int pulseEnd = std::min(pulseStart + params.width, static_cast<int>(data.size()));
for (size_t j = i + 1; j < pulses.size(); ++j) {
if (pulses[j] < pulseEnd) {
pulseEnd = pulses[j];
break;
}
}
int area = 0;
for (int k = pulseStart; k < pulseEnd && k < data.size(); ++k) {
area += data[k];
}
cout << pulseStart << " (" << area << ")\n";
}
}
}
}
void printParameters(const Parameters& params) {
cout << "# Pulse parameters\n";
cout << "vt = " << params.vt << "\n";
cout << "width = " << params.width << "\n";
cout << "pulse_delta = " << params.pulse_delta << "\n";
cout << "drop_ratio = " << params.drop_ratio << "\n";
cout << "below_drop_ratio = " << params.below_drop_ratio << "\n";
cout << "\n";
}
int main(int argc, char* argv[]) {
if (argc != 2) {
cerr << "Usage: " << argv[0] << " <ini_file>\n";
return 1;
}
Parameters params;
if (!parseIniFile(argv[1], params)) {
return 1;
}
printParameters(params);
processFiles(params);
return 0;
}Editor is loading...
Leave a Comment