median option for averaging
This commit is contained in:
parent
82891ac766
commit
dced1732d6
@ -265,6 +265,13 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window)
|
||||
|
||||
// Set initial sweep settings
|
||||
auto pref = Preferences::getInstance();
|
||||
|
||||
if(pref.Acquisition.useMedianAveraging) {
|
||||
average.setMode(Averaging::Mode::Median);
|
||||
} else {
|
||||
average.setMode(Averaging::Mode::Mean);
|
||||
}
|
||||
|
||||
if(pref.Startup.RememberSweepSettings) {
|
||||
LoadSweepSettings();
|
||||
} else {
|
||||
@ -1075,6 +1082,11 @@ void SpectrumAnalyzer::updateGraphColors()
|
||||
emit graphColorsChanged();
|
||||
}
|
||||
|
||||
void SpectrumAnalyzer::setAveragingMode(Averaging::Mode mode)
|
||||
{
|
||||
average.setMode(mode);
|
||||
}
|
||||
|
||||
QString SpectrumAnalyzer::WindowToString(SpectrumAnalyzer::Window w)
|
||||
{
|
||||
switch(w) {
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
void updateGraphColors();
|
||||
void setAveragingMode(Averaging::Mode mode);
|
||||
|
||||
|
||||
private:
|
||||
|
@ -530,6 +530,12 @@ VNA::VNA(AppWindow *window)
|
||||
// Set initial sweep settings
|
||||
auto pref = Preferences::getInstance();
|
||||
|
||||
if(pref.Acquisition.useMedianAveraging) {
|
||||
average.setMode(Averaging::Mode::Median);
|
||||
} else {
|
||||
average.setMode(Averaging::Mode::Mean);
|
||||
}
|
||||
|
||||
if(pref.Startup.RememberSweepSettings) {
|
||||
LoadSweepSettings();
|
||||
} else {
|
||||
@ -1466,6 +1472,11 @@ void VNA::updateGraphColors()
|
||||
emit graphColorsChanged();
|
||||
}
|
||||
|
||||
void VNA::setAveragingMode(Averaging::Mode mode)
|
||||
{
|
||||
average.setMode(mode);
|
||||
}
|
||||
|
||||
QString VNA::SweepTypeToString(VNA::SweepType sw)
|
||||
{
|
||||
switch(sw) {
|
||||
|
@ -29,6 +29,7 @@ public:
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
void updateGraphColors();
|
||||
void setAveragingMode(Averaging::Mode mode);
|
||||
|
||||
enum class SweepType {
|
||||
Frequency = 0,
|
||||
|
@ -204,6 +204,14 @@ AppWindow::AppWindow(QWidget *parent)
|
||||
vna->updateGraphColors();
|
||||
}
|
||||
|
||||
// averaging mode may have changed, update for all relevant modes
|
||||
if(p.Acquisition.useMedianAveraging) {
|
||||
spectrumAnalyzer->setAveragingMode(Averaging::Mode::Median);
|
||||
vna->setAveragingMode(Averaging::Mode::Median);
|
||||
} else {
|
||||
spectrumAnalyzer->setAveragingMode(Averaging::Mode::Mean);
|
||||
vna->setAveragingMode(Averaging::Mode::Mean);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->actionAbout, &QAction::triggered, [=](){
|
||||
|
@ -5,6 +5,7 @@ using namespace std;
|
||||
Averaging::Averaging()
|
||||
{
|
||||
averages = 1;
|
||||
mode = Mode::Mean;
|
||||
}
|
||||
|
||||
void Averaging::reset(unsigned int points)
|
||||
@ -45,6 +46,8 @@ Protocol::Datapoint Averaging::process(Protocol::Datapoint d)
|
||||
deque->pop_front();
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case Mode::Mean: {
|
||||
// calculate average
|
||||
complex<double> sum[4];
|
||||
for(auto s : *deque) {
|
||||
@ -58,6 +61,43 @@ Protocol::Datapoint Averaging::process(Protocol::Datapoint d)
|
||||
S21 = sum[2] / (double) (deque->size());
|
||||
S22 = sum[3] / (double) (deque->size());
|
||||
}
|
||||
break;
|
||||
case Mode::Median: {
|
||||
auto size = deque->size();
|
||||
// create sorted arrays
|
||||
std::vector<complex<double>> S11sorted, S12sorted, S21sorted, S22sorted;
|
||||
S11sorted.reserve(size);
|
||||
S12sorted.reserve(size);
|
||||
S21sorted.reserve(size);
|
||||
S22sorted.reserve(size);
|
||||
|
||||
auto comp = [=](const complex<double>&a, const complex<double>&b){
|
||||
return abs(a) < abs(b);
|
||||
};
|
||||
|
||||
for(auto d : *deque) {
|
||||
S11sorted.insert(upper_bound(S11sorted.begin(), S11sorted.end(), d[0], comp), d[0]);
|
||||
S12sorted.insert(upper_bound(S12sorted.begin(), S12sorted.end(), d[1], comp), d[1]);
|
||||
S21sorted.insert(upper_bound(S21sorted.begin(), S21sorted.end(), d[2], comp), d[2]);
|
||||
S22sorted.insert(upper_bound(S22sorted.begin(), S22sorted.end(), d[3], comp), d[3]);
|
||||
}
|
||||
if(size & 0x01) {
|
||||
// odd number of samples
|
||||
S11 = S11sorted[size / 2];
|
||||
S12 = S12sorted[size / 2];
|
||||
S21 = S21sorted[size / 2];
|
||||
S22 = S22sorted[size / 2];
|
||||
} else {
|
||||
// even number, use average of middle samples
|
||||
S11 = (S11sorted[size / 2 - 1] + S11sorted[size / 2]) / 2.0;
|
||||
S12 = (S12sorted[size / 2 - 1] + S12sorted[size / 2]) / 2.0;
|
||||
S21 = (S21sorted[size / 2 - 1] + S21sorted[size / 2]) / 2.0;
|
||||
S22 = (S22sorted[size / 2 - 1] + S22sorted[size / 2]) / 2.0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
d.real_S11 = S11.real();
|
||||
d.imag_S11 = S11.imag();
|
||||
@ -90,17 +130,41 @@ Protocol::SpectrumAnalyzerResult Averaging::process(Protocol::SpectrumAnalyzerRe
|
||||
deque->pop_front();
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case Mode::Mean: {
|
||||
// calculate average
|
||||
complex<double> sum[4];
|
||||
complex<double> sum[2];
|
||||
for(auto s : *deque) {
|
||||
sum[0] += s[0];
|
||||
sum[1] += s[1];
|
||||
sum[2] += s[2];
|
||||
sum[3] += s[3];
|
||||
}
|
||||
d.port1 = abs(sum[0] / (double) (deque->size()));
|
||||
d.port2 = abs(sum[1] / (double) (deque->size()));
|
||||
}
|
||||
break;
|
||||
case Mode::Median: {
|
||||
auto size = deque->size();
|
||||
// create sorted arrays
|
||||
std::vector<double> port1, port2;
|
||||
port1.reserve(size);
|
||||
port2.reserve(size);
|
||||
for(auto d : *deque) {
|
||||
port1.insert(upper_bound(port1.begin(), port1.end(), abs(d[0])), abs(d[0]));
|
||||
port2.insert(upper_bound(port2.begin(), port2.end(), abs(d[0])), abs(d[0]));
|
||||
}
|
||||
if(size & 0x01) {
|
||||
// odd number of samples
|
||||
d.port1 = port1[size / 2];
|
||||
d.port2 = port1[size / 2];
|
||||
} else {
|
||||
// even number, use average of middle samples
|
||||
d.port1 = (port1[size / 2 - 1] + port1[size / 2]) / 2;
|
||||
d.port2 = (port2[size / 2 - 1] + port2[size / 2]) / 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
@ -122,3 +186,13 @@ unsigned int Averaging::currentSweep()
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Averaging::Mode Averaging::getMode() const
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
void Averaging::setMode(const Mode &value)
|
||||
{
|
||||
mode = value;
|
||||
}
|
||||
|
@ -10,6 +10,11 @@
|
||||
class Averaging
|
||||
{
|
||||
public:
|
||||
enum class Mode {
|
||||
Mean,
|
||||
Median
|
||||
};
|
||||
|
||||
Averaging();
|
||||
void reset(unsigned int points);
|
||||
void setAverages(unsigned int a);
|
||||
@ -21,10 +26,14 @@ public:
|
||||
// Returns the number of the currently active sweep. Value is incremented whenever the the first point of the sweep is added
|
||||
// Returned values are in range 0 (when no data has been added yet) to averages
|
||||
unsigned int currentSweep();
|
||||
Mode getMode() const;
|
||||
void setMode(const Mode &value);
|
||||
|
||||
private:
|
||||
std::vector<std::deque<std::array<std::complex<double>, 4>>> avg;
|
||||
int maxPoints;
|
||||
unsigned int averages;
|
||||
Mode mode;
|
||||
};
|
||||
|
||||
#endif // AVERAGING_H
|
||||
|
@ -134,6 +134,7 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
||||
p->Acquisition.harmonicMixing = ui->AcquisitionUseHarmonic->isChecked();
|
||||
p->Acquisition.useDFTinSAmode = ui->AcquisitionUseDFT->isChecked();
|
||||
p->Acquisition.RBWLimitForDFT = ui->AcquisitionDFTlimitRBW->value();
|
||||
p->Acquisition.useMedianAveraging = ui->AcquisitionAveragingMode->currentIndex() == 1;
|
||||
p->Graphs.Color.background = ui->GraphsColorBackground->getColor();
|
||||
p->Graphs.Color.axis = ui->GraphsColorAxis->getColor();
|
||||
p->Graphs.Color.Ticks.Background.enabled = ui->GraphsColorTicksBackgroundEnabled->isChecked();
|
||||
@ -199,6 +200,7 @@ void PreferencesDialog::setInitialGUIState()
|
||||
ui->AcquisitionUseHarmonic->setChecked(p->Acquisition.harmonicMixing);
|
||||
ui->AcquisitionUseDFT->setChecked(p->Acquisition.useDFTinSAmode);
|
||||
ui->AcquisitionDFTlimitRBW->setValue(p->Acquisition.RBWLimitForDFT);
|
||||
ui->AcquisitionAveragingMode->setCurrentIndex(p->Acquisition.useMedianAveraging ? 1 : 0);
|
||||
|
||||
ui->GraphsColorBackground->setColor(p->Graphs.Color.background);
|
||||
ui->GraphsColorAxis->setColor(p->Graphs.Color.axis);
|
||||
|
@ -66,6 +66,7 @@ public:
|
||||
bool harmonicMixing;
|
||||
bool useDFTinSAmode;
|
||||
double RBWLimitForDFT;
|
||||
bool useMedianAveraging;
|
||||
} Acquisition;
|
||||
struct {
|
||||
struct {
|
||||
@ -100,7 +101,7 @@ private:
|
||||
QString name;
|
||||
QVariant def;
|
||||
};
|
||||
const std::array<SettingDescription, 37> descr = {{
|
||||
const std::array<SettingDescription, 38> descr = {{
|
||||
{&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true},
|
||||
{&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false},
|
||||
{&Startup.DefaultSweep.type, "Startup.DefaultSweep.type", "Frequency"},
|
||||
@ -128,6 +129,7 @@ private:
|
||||
{&Acquisition.harmonicMixing, "Acquisition.harmonicMixing", false},
|
||||
{&Acquisition.useDFTinSAmode, "Acquisition.useDFTinSAmode", true},
|
||||
{&Acquisition.RBWLimitForDFT, "Acquisition.RBWLimitForDFT", 3000.0},
|
||||
{&Acquisition.useMedianAveraging, "Acquisition.useMedianAveraging", false},
|
||||
{&Graphs.Color.background, "Graphs.Color.background", QColor(Qt::black)},
|
||||
{&Graphs.Color.axis, "Graphs.Color.axis", QColor(Qt::white)},
|
||||
{&Graphs.Color.Ticks.Background.enabled, "Graphs.Color.Ticks.Background.enabled", true},
|
||||
|
@ -78,7 +78,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="Startup">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
@ -637,6 +637,36 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_14">
|
||||
<property name="title">
|
||||
<string>Common</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>Averaging mode:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="AcquisitionAveragingMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mean</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Median</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
|
Loading…
Reference in New Issue
Block a user