LibreVNA/Software/PC_Application/LibreVNA-GUI/averaging.cpp

167 lines
4.0 KiB
C++
Raw Normal View History

2022-10-01 23:10:44 +08:00
#include "averaging.h"
using namespace std;
Averaging::Averaging()
{
averages = 1;
mode = Mode::Mean;
}
void Averaging::reset(unsigned int points)
{
avg.clear();
for(unsigned int i = 0;i<points;i++) {
avg.push_back(deque<vector<complex<double>>>());
}
}
void Averaging::setAverages(unsigned int a)
{
averages = a;
reset(avg.size());
}
VirtualDevice::VNAMeasurement Averaging::process(VirtualDevice::VNAMeasurement d)
{
if(d.measurements.size() != numMeasurements) {
numMeasurements = d.measurements.size();
reset(avg.size());
}
vector<complex<double>> data;
for(auto m : d.measurements) {
data.push_back(m.second);
}
process(d.pointNum, data);
int i=0;
for(auto &m : d.measurements) {
m.second = data[i++];
}
return d;
}
VirtualDevice::SAMeasurement Averaging::process(VirtualDevice::SAMeasurement d)
{
if(d.measurements.size() != numMeasurements) {
numMeasurements = d.measurements.size();
reset(avg.size());
}
vector<complex<double>> data;
for(auto m : d.measurements) {
data.push_back(m.second);
}
process(d.pointNum, data);
int i=0;
for(auto &m : d.measurements) {
m.second = data[i++].real();
}
return d;
}
unsigned int Averaging::getLevel()
{
if(avg.size() > 0) {
return avg.back().size();
} else {
return 0;
}
}
unsigned int Averaging::currentSweep()
{
if(avg.size() > 0) {
return avg.front().size();
} else {
return 0;
}
}
Averaging::Mode Averaging::getMode() const
{
return mode;
}
void Averaging::setMode(const Mode &value)
{
mode = value;
}
void Averaging::process(unsigned int pointNum, std::vector<std::complex<double>> &data)
{
if(data.size() != numMeasurements) {
numMeasurements = data.size();
reset(avg.size());
}
if (pointNum == avg.size()) {
// add moving average entry
deque<vector<complex<double>>> deque;
avg.push_back(deque);
}
if (pointNum < avg.size()) {
// can compute average
// get correct queue
auto deque = &avg[pointNum];
// add newest sample to queue
deque->push_back(data);
// remove oldest sample if required number of averages reached
if(deque->size() > averages) {
deque->pop_front();
}
std::deque<complex<double>> averagedResults = {};
switch(mode) {
case Mode::Mean: {
// calculate average
complex<double> sum[numMeasurements];
for(auto s : *deque) {
for(unsigned int i=0;i<numMeasurements;i++) {
sum[i] += s[i];
}
}
for(auto s : sum) {
averagedResults.push_back(s / (double) (deque->size()));
}
}
break;
case Mode::Median: {
auto size = deque->size();
// create sorted vectors
vector<vector<complex<double>>> vectors(numMeasurements);
auto comp = [=](const complex<double>&a, const complex<double>&b){
return abs(a) < abs(b);
};
for(auto d : *deque) {
int i=0;
for(auto &v : vectors) {
v.insert(upper_bound(v.begin(), v.end(), d[i], comp), d[i]);
i++;
}
}
if(size & 0x01) {
// odd number of samples
for(auto v : vectors) {
averagedResults.push_back(v[size / 2]);
}
} else {
// even number, use average of middle samples
for(auto v : vectors) {
averagedResults.push_back((v[size / 2 - 1] + v[size / 2]) / 2.0);
}
}
}
break;
}
for(auto &m : data) {
m = averagedResults.front();
averagedResults.pop_front();
}
}
}