Option: restrict marker position

This commit is contained in:
Jan Käberich 2022-10-05 22:17:53 +02:00
parent ce84370a03
commit 26ba329a0c
24 changed files with 214 additions and 58 deletions

View File

@ -110,7 +110,7 @@ VirtualDevice::VirtualDevice(QString serial)
zerospan = false; zerospan = false;
// Check if this is a compound device // Check if this is a compound device
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
for(auto cd : pref.compoundDevices) { for(auto cd : pref.compoundDevices) {
if(cd->name == serial) { if(cd->name == serial) {
// connect request to this compound device // connect request to this compound device
@ -257,8 +257,8 @@ bool VirtualDevice::setVNA(const VirtualDevice::VNASettings &s, std::function<vo
portStageMapping[s.excitedPorts[i]] = i; portStageMapping[s.excitedPorts[i]] = i;
} }
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
Protocol::SweepSettings sd; Protocol::SweepSettings sd = {};
sd.f_start = s.freqStart; sd.f_start = s.freqStart;
sd.f_stop = s.freqStop; sd.f_stop = s.freqStop;
sd.points = s.points; sd.points = s.points;
@ -335,8 +335,8 @@ bool VirtualDevice::setSA(const VirtualDevice::SASettings &s, std::function<void
return false; return false;
} }
zerospan = s.freqStart == s.freqStop; zerospan = s.freqStart == s.freqStop;
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
Protocol::SpectrumAnalyzerSettings sd; Protocol::SpectrumAnalyzerSettings sd = {};
sd.f_start = s.freqStart; sd.f_start = s.freqStart;
sd.f_stop = s.freqStop; sd.f_stop = s.freqStop;
sd.pointNum = s.points; sd.pointNum = s.points;
@ -410,8 +410,8 @@ bool VirtualDevice::setSG(const SGSettings &s)
if(!info.supportsSGmode) { if(!info.supportsSGmode) {
return false; return false;
} }
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
Protocol::PacketInfo packet; Protocol::PacketInfo packet = {};
packet.type = Protocol::PacketType::Generator; packet.type = Protocol::PacketType::Generator;
Protocol::GeneratorSettings &sd = packet.generator; Protocol::GeneratorSettings &sd = packet.generator;
sd.frequency = s.freq; sd.frequency = s.freq;
@ -485,7 +485,7 @@ bool VirtualDevice::setExtRef(QString option_in, QString option_out)
refOut = Reference::OutFreq::Off; refOut = Reference::OutFreq::Off;
} }
Protocol::PacketInfo p; Protocol::PacketInfo p = {};
p.type = Protocol::PacketType::Reference; p.type = Protocol::PacketType::Reference;
switch(refIn) { switch(refIn) {
case Reference::TypeIn::Internal: case Reference::TypeIn::Internal:
@ -518,7 +518,7 @@ bool VirtualDevice::setExtRef(QString option_in, QString option_out)
std::set<QString> VirtualDevice::GetAvailableVirtualDevices() std::set<QString> VirtualDevice::GetAvailableVirtualDevices()
{ {
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
auto ret = Device::GetDevices(); auto ret = Device::GetDevices();
// Add compound devices as well // Add compound devices as well
for(auto vdev : pref.compoundDevices) { for(auto vdev : pref.compoundDevices) {

View File

@ -7,7 +7,7 @@ Generator::Generator(AppWindow *window, QString name)
{ {
central = new SignalgeneratorWidget(window, window); central = new SignalgeneratorWidget(window, window);
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
// set initial values // set initial values
if(pref.Startup.RememberSweepSettings) { if(pref.Startup.RememberSweepSettings) {

View File

@ -264,7 +264,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
SetTGEnabled(false); SetTGEnabled(false);
// Set initial sweep settings // Set initial sweep settings
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
if(pref.Acquisition.useMedianAveraging) { if(pref.Acquisition.useMedianAveraging) {
average.setMode(Averaging::Mode::Median); average.setMode(Averaging::Mode::Median);
@ -1130,7 +1130,7 @@ void SpectrumAnalyzer::ConstrainAndUpdateFrequencies()
void SpectrumAnalyzer::LoadSweepSettings() void SpectrumAnalyzer::LoadSweepSettings()
{ {
QSettings s; QSettings s;
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
settings.freqStart = s.value("SAStart", pref.Startup.SA.start).toULongLong(); settings.freqStart = s.value("SAStart", pref.Startup.SA.start).toULongLong();
settings.freqStop = s.value("SAStop", pref.Startup.SA.stop).toULongLong(); settings.freqStop = s.value("SAStop", pref.Startup.SA.stop).toULongLong();
ConstrainAndUpdateFrequencies(); ConstrainAndUpdateFrequencies();

View File

@ -16,6 +16,7 @@
#include <QActionGroup> #include <QActionGroup>
#include <QApplication> #include <QApplication>
#include <QDateTime> #include <QDateTime>
#include <QCheckBox>
using namespace std; using namespace std;
@ -24,6 +25,9 @@ Marker::Marker(MarkerModel *model, int number, Marker *parent, QString descr)
model(model), model(model),
parentTrace(nullptr), parentTrace(nullptr),
position(1000000000), position(1000000000),
minPosition(0),
maxPosition(0),
restrictPosition(false),
number(number), number(number),
visible(true), visible(true),
data(0), data(0),
@ -87,7 +91,7 @@ void Marker::assignTrace(Trace *t)
if(firstAssignment) { if(firstAssignment) {
// Marker was just created and this is the first assignment to a trace. // Marker was just created and this is the first assignment to a trace.
// Use display format on graph from preferences // Use display format on graph from preferences
auto p = Preferences::getInstance(); auto& p = Preferences::getInstance();
if(p.Marker.defaultBehavior.showDataOnGraphs) { if(p.Marker.defaultBehavior.showDataOnGraphs) {
if(p.Marker.defaultBehavior.showAllData) { if(p.Marker.defaultBehavior.showAllData) {
for(auto f : applicableFormats()) { for(auto f : applicableFormats()) {
@ -644,6 +648,22 @@ QString Marker::readableType()
} }
} }
QString Marker::domainToUnit()
{
return domainToUnit(getDomain());
}
QString Marker::domainToUnit(Trace::DataType domain)
{
switch(domain) {
case Trace::DataType::Frequency: return "Hz";
case Trace::DataType::Power: return "dBm";
case Trace::DataType::Time: return "s";
case Trace::DataType::TimeZeroSpan: return "s";
}
return "";
}
void Marker::setPosition(double pos) void Marker::setPosition(double pos)
{ {
position = pos; position = pos;
@ -938,6 +958,14 @@ void Marker::constrainPosition()
{ {
if(parentTrace) { if(parentTrace) {
if(parentTrace->size() > 0) { if(parentTrace->size() > 0) {
if(restrictPosition) {
if(position > maxPosition) {
position = maxPosition;
}
if(position < minPosition) {
position = minPosition;
}
}
if(position > parentTrace->maxX()) { if(position > parentTrace->maxX()) {
position = parentTrace->maxX(); position = parentTrace->maxX();
} else if(position < parentTrace->minX()) { } else if(position < parentTrace->minX()) {
@ -1166,6 +1194,9 @@ nlohmann::json Marker::toJSON()
j["type"] = typeToString(type).toStdString(); j["type"] = typeToString(type).toStdString();
j["number"] = number; j["number"] = number;
j["position"] = position; j["position"] = position;
j["minPosition"] = minPosition;
j["maxPosition"] = maxPosition;
j["restrictPosition"] = restrictPosition;
if(group) { if(group) {
j["group"] = group->getNumber(); j["group"] = group->getNumber();
} }
@ -1205,6 +1236,9 @@ void Marker::fromJSON(nlohmann::json j)
creationTimestamp = j.value("creationTimestamp", QDateTime::currentSecsSinceEpoch()); creationTimestamp = j.value("creationTimestamp", QDateTime::currentSecsSinceEpoch());
number = j.value("number", 1); number = j.value("number", 1);
position = j.value("position", 0.0); position = j.value("position", 0.0);
minPosition = j.value("minPosition", 0.0);
maxPosition = j.value("maxPosition", 0.0);
restrictPosition = j.value("restrictPosition", false);
visible = j.value("visible", true); visible = j.value("visible", true);
unsigned int hash = j["trace"]; unsigned int hash = j["trace"];
@ -1458,6 +1492,59 @@ SIUnitEdit *Marker::getSettingsEditor()
return ret; return ret;
} }
QWidget *Marker::getRestrictEditor()
{
auto w = new QWidget;
auto layout = new QHBoxLayout;
layout->setContentsMargins(0,0,0,0);
auto cb = new QCheckBox;
cb->setChecked(restrictPosition);
layout->addWidget(cb);
auto min = new SIUnitEdit;
min->setPrefixes("pnum kMG");
min->setUnit(domainToUnit());
min->setPrecision(5);
min->setValue(minPosition);
min->setEnabled(restrictPosition);
layout->addWidget(new QLabel("from"));
layout->addWidget(min);
auto max = new SIUnitEdit;
max->setPrefixes("pnum kMG");
max->setUnit(domainToUnit());
max->setPrecision(5);
max->setValue(maxPosition);
max->setEnabled(restrictPosition);
layout->addWidget(new QLabel("to"));
layout->addWidget(max);
connect(cb, &QCheckBox::toggled, this, [=](){
restrictPosition = cb->isChecked();
min->setEnabled(restrictPosition);
max->setEnabled(restrictPosition);
constrainPosition();
update();
});
connect(min, &SIUnitEdit::valueChanged, this, [=](){
minPosition = min->value();
if(maxPosition < minPosition) {
maxPosition = minPosition;
max->setValueQuiet(maxPosition);
}
constrainPosition();
});
connect(max, &SIUnitEdit::valueChanged, this, [=](){
maxPosition = max->value();
if(maxPosition < minPosition) {
minPosition = maxPosition;
min->setValueQuiet(minPosition);
}
constrainPosition();
});
w->setLayout(layout);
return w;
}
void Marker::adjustSettings(double value) void Marker::adjustSettings(double value)
{ {
switch(getDomain()) { switch(getDomain()) {
@ -1565,20 +1652,22 @@ void Marker::update()
// empty trace, nothing to do // empty trace, nothing to do
return; return;
} }
auto xmin = restrictPosition ? minPosition : numeric_limits<double>::lowest();
auto xmax = restrictPosition ? maxPosition : numeric_limits<double>::max();
switch(type) { switch(type) {
case Type::Manual: case Type::Manual:
case Type::Delta: case Type::Delta:
// nothing to do // nothing to do
break; break;
case Type::Maximum: case Type::Maximum:
setPosition(parentTrace->findExtremum(true)); setPosition(parentTrace->findExtremum(true, xmin, xmax));
break; break;
case Type::Minimum: case Type::Minimum:
setPosition(parentTrace->findExtremum(false)); setPosition(parentTrace->findExtremum(false, xmin, xmax));
break; break;
case Type::PeakTable: { case Type::PeakTable: {
deleteHelperMarkers(); deleteHelperMarkers();
auto peaks = parentTrace->findPeakFrequencies(100, peakThreshold); auto peaks = parentTrace->findPeakFrequencies(100, peakThreshold, 3.0, xmin, xmax);
char suffix = 'a'; char suffix = 'a';
for(auto p : peaks) { for(auto p : peaks) {
auto helper = new Marker(model, number, this); auto helper = new Marker(model, number, this);
@ -1600,7 +1689,7 @@ void Marker::update()
break; break;
} else { } else {
// find the maximum // find the maximum
auto peakFreq = parentTrace->findExtremum(true); auto peakFreq = parentTrace->findExtremum(true, xmin, xmax);
// this marker shows the insertion loss // this marker shows the insertion loss
setPosition(peakFreq); setPosition(peakFreq);
// find the cutoff frequency // find the cutoff frequency
@ -1609,7 +1698,11 @@ void Marker::update()
auto cutoff = peakAmplitude + cutoffAmplitude; auto cutoff = peakAmplitude + cutoffAmplitude;
int inc = type == Type::Lowpass ? 1 : -1; int inc = type == Type::Lowpass ? 1 : -1;
while(index >= 0 && index < (int) parentTrace->size()) { while(index >= 0 && index < (int) parentTrace->size()) {
auto amplitude = Util::SparamTodB(parentTrace->sample(index).y); auto sample = parentTrace->sample(index);
if(sample.x > xmax) {
break;
}
auto amplitude = Util::SparamTodB(sample.y);
if(amplitude <= cutoff) { if(amplitude <= cutoff) {
break; break;
} }
@ -1640,7 +1733,11 @@ void Marker::update()
auto low_index = index; auto low_index = index;
while(low_index >= 0) { while(low_index >= 0) {
auto amplitude = Util::SparamTodB(parentTrace->sample(low_index).y); auto sample = parentTrace->sample(low_index);
if(sample.x < xmin) {
break;
}
auto amplitude = Util::SparamTodB(sample.y);
if(amplitude <= cutoff) { if(amplitude <= cutoff) {
break; break;
} }
@ -1654,7 +1751,11 @@ void Marker::update()
auto high_index = index; auto high_index = index;
while(high_index < (int) parentTrace->size()) { while(high_index < (int) parentTrace->size()) {
auto amplitude = Util::SparamTodB(parentTrace->sample(high_index).y); auto sample = parentTrace->sample(high_index);
if(sample.x > xmax) {
break;
}
auto amplitude = Util::SparamTodB(sample.y);
if(amplitude <= cutoff) { if(amplitude <= cutoff) {
break; break;
} }
@ -1670,7 +1771,7 @@ void Marker::update()
} }
break; break;
case Type::TOI: { case Type::TOI: {
auto peaks = parentTrace->findPeakFrequencies(2); auto peaks = parentTrace->findPeakFrequencies(2, -100, 3.0, xmin, xmax);
if(peaks.size() != 2) { if(peaks.size() != 2) {
// error finding peaks, do nothing // error finding peaks, do nothing
break; break;
@ -1691,13 +1792,16 @@ void Marker::update()
break; break;
case Type::P1dB: { case Type::P1dB: {
// find maximum // find maximum
auto maxpos = parentTrace->findExtremum(true); auto maxpos = parentTrace->findExtremum(true, xmin, xmax);
// starting at the maximum point, traverse trace data towards higher power levels until amplitude dropped by 1dB // starting at the maximum point, traverse trace data towards higher power levels until amplitude dropped by 1dB
auto maxindex = parentTrace->index(maxpos); auto maxindex = parentTrace->index(maxpos);
auto maxpower = abs(parentTrace->sample(maxindex).y); auto maxpower = abs(parentTrace->sample(maxindex).y);
double p1db = parentTrace->maxX(); double p1db = parentTrace->maxX() > xmax ? xmax : parentTrace->maxX();
for(unsigned int i = maxindex; i < parentTrace->size(); i++) { for(unsigned int i = maxindex; i < parentTrace->size(); i++) {
auto sample = parentTrace->sample(i); auto sample = parentTrace->sample(i);
if(sample.x > xmax) {
break;
}
if(Util::SparamTodB(maxpower) - Util::SparamTodB(sample.y) >= 1.0) { if(Util::SparamTodB(maxpower) - Util::SparamTodB(sample.y) >= 1.0) {
p1db = sample.x; p1db = sample.x;
break; break;

View File

@ -15,7 +15,7 @@ class MarkerGroup;
class Marker : public QObject, public Savable class Marker : public QObject, public Savable
{ {
Q_OBJECT; Q_OBJECT
public: public:
Marker(MarkerModel *model, int number = 1, Marker *parent = nullptr, QString descr = QString()); Marker(MarkerModel *model, int number = 1, Marker *parent = nullptr, QString descr = QString());
~Marker(); ~Marker();
@ -61,6 +61,8 @@ public:
QString readableSettings(); QString readableSettings();
QString tooltipSettings(); QString tooltipSettings();
QString readableType(); QString readableType();
QString domainToUnit();
static QString domainToUnit(Trace::DataType domain);
double getPosition() const; double getPosition() const;
std::complex<double> getData() const; std::complex<double> getData() const;
@ -96,6 +98,7 @@ public:
QWidget *getTypeEditor(QAbstractItemDelegate *delegate = nullptr); QWidget *getTypeEditor(QAbstractItemDelegate *delegate = nullptr);
void updateTypeFromEditor(QWidget *c); void updateTypeFromEditor(QWidget *c);
SIUnitEdit* getSettingsEditor(); SIUnitEdit* getSettingsEditor();
QWidget *getRestrictEditor();
void adjustSettings(double value); void adjustSettings(double value);
bool isVisible(); bool isVisible();
void setVisible(bool visible); void setVisible(bool visible);
@ -184,6 +187,9 @@ private:
Trace *parentTrace; Trace *parentTrace;
unsigned long creationTimestamp; unsigned long creationTimestamp;
double position; double position;
double minPosition;
double maxPosition;
bool restrictPosition;
int number; int number;
bool visible; bool visible;
// Frequency domain: S parameter // Frequency domain: S parameter

View File

@ -279,6 +279,7 @@ QVariant MarkerModel::headerData(int section, Qt::Orientation orientation, int r
case ColIndexTrace: return "Trace"; case ColIndexTrace: return "Trace";
case ColIndexType: return "Type"; case ColIndexType: return "Type";
case ColIndexSettings: return "Settings"; case ColIndexSettings: return "Settings";
case ColIndexRestrict: return "Restrict";
case ColIndexData: return "Data"; case ColIndexData: return "Data";
} }
break; break;
@ -291,6 +292,7 @@ QVariant MarkerModel::headerData(int section, Qt::Orientation orientation, int r
case ColIndexTrace: return "The trace from which the marker gets its data"; case ColIndexTrace: return "The trace from which the marker gets its data";
case ColIndexType: return "Depending on marker type, it can be positioned by the user or will be set automatically"; case ColIndexType: return "Depending on marker type, it can be positioned by the user or will be set automatically";
case ColIndexSettings: return "Configurable marker parameter, depends on the marker type"; case ColIndexSettings: return "Configurable marker parameter, depends on the marker type";
case ColIndexRestrict: return "Restrict the range available for this marker";
case ColIndexData: return "Tracedata at the marker position"; case ColIndexData: return "Tracedata at the marker position";
} }
break; break;
@ -334,6 +336,7 @@ Qt::ItemFlags MarkerModel::flags(const QModelIndex &index) const
case ColIndexTrace: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break; case ColIndexTrace: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
case ColIndexType: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break; case ColIndexType: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
case ColIndexSettings: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break; case ColIndexSettings: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
case ColIndexRestrict: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
case ColIndexData: flags |= Qt::ItemIsEnabled; break; case ColIndexData: flags |= Qt::ItemIsEnabled; break;
} }
auto marker = markerFromIndex(index); auto marker = markerFromIndex(index);
@ -524,3 +527,22 @@ void MarkerTypeDelegate::setModelData(QWidget *editor, QAbstractItemModel *, con
auto marker = static_cast<const MarkerModel*>(index.model())->markerFromIndex(index); auto marker = static_cast<const MarkerModel*>(index.model())->markerFromIndex(index);
marker->updateTypeFromEditor(editor); marker->updateTypeFromEditor(editor);
} }
QSize MarkerRestrictDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return QSize(0, rowHeight);
}
QWidget *MarkerRestrictDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
auto marker = static_cast<const MarkerModel*>(index.model())->markerFromIndex(index);
auto editor = marker->getRestrictEditor();
editor->setMaximumHeight(rowHeight);
editor->setParent(parent);
return editor;
}
void MarkerRestrictDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
// nothing to do
}

View File

@ -11,7 +11,7 @@
class MarkerTraceDelegate : public QStyledItemDelegate class MarkerTraceDelegate : public QStyledItemDelegate
{ {
Q_OBJECT; Q_OBJECT
QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const override; QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const override;
QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override; QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
void setEditorData(QWidget * editor, const QModelIndex & index) const override; void setEditorData(QWidget * editor, const QModelIndex & index) const override;
@ -31,7 +31,7 @@ Q_DECLARE_METATYPE(MarkerWidgetTraceInfo)
class MarkerTypeDelegate : public QStyledItemDelegate class MarkerTypeDelegate : public QStyledItemDelegate
{ {
Q_OBJECT; Q_OBJECT
QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const override; QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const override;
QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override; QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override; void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override;
@ -39,7 +39,15 @@ class MarkerTypeDelegate : public QStyledItemDelegate
class MarkerSettingsDelegate : public QStyledItemDelegate class MarkerSettingsDelegate : public QStyledItemDelegate
{ {
Q_OBJECT; Q_OBJECT
QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const override;
QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override;
};
class MarkerRestrictDelegate : public QStyledItemDelegate
{
Q_OBJECT
QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const override; QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const override;
QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override; QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override; void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override;
@ -59,6 +67,7 @@ public:
ColIndexTrace, ColIndexTrace,
ColIndexType, ColIndexType,
ColIndexSettings, ColIndexSettings,
ColIndexRestrict,
ColIndexData, ColIndexData,
ColIndexLast, ColIndexLast,
}; };

View File

@ -27,6 +27,7 @@ MarkerWidget::MarkerWidget(MarkerModel &model, QWidget *parent) :
ui->treeView->setItemDelegateForColumn(MarkerModel::ColIndexTrace, new MarkerTraceDelegate); ui->treeView->setItemDelegateForColumn(MarkerModel::ColIndexTrace, new MarkerTraceDelegate);
ui->treeView->setItemDelegateForColumn(MarkerModel::ColIndexType, new MarkerTypeDelegate); ui->treeView->setItemDelegateForColumn(MarkerModel::ColIndexType, new MarkerTypeDelegate);
ui->treeView->setItemDelegateForColumn(MarkerModel::ColIndexSettings, new MarkerSettingsDelegate); ui->treeView->setItemDelegateForColumn(MarkerModel::ColIndexSettings, new MarkerSettingsDelegate);
ui->treeView->setItemDelegateForColumn(MarkerModel::ColIndexRestrict, new MarkerRestrictDelegate);
ui->treeView->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection); ui->treeView->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
ui->treeView->installEventFilter(this); ui->treeView->installEventFilter(this);
@ -36,6 +37,7 @@ MarkerWidget::MarkerWidget(MarkerModel &model, QWidget *parent) :
ui->treeView->setColumnWidth(MarkerModel::ColIndexVisible, 20); ui->treeView->setColumnWidth(MarkerModel::ColIndexVisible, 20);
ui->treeView->setColumnWidth(MarkerModel::ColIndexTrace, 60); ui->treeView->setColumnWidth(MarkerModel::ColIndexTrace, 60);
ui->treeView->setColumnWidth(MarkerModel::ColIndexType, 120); ui->treeView->setColumnWidth(MarkerModel::ColIndexType, 120);
ui->treeView->setColumnWidth(MarkerModel::ColIndexRestrict, 200);
ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu); ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->treeView, &QTreeView::customContextMenuRequested, [&](const QPoint &p){ connect(ui->treeView, &QTreeView::customContextMenuRequested, [&](const QPoint &p){
@ -175,7 +177,7 @@ bool MarkerWidget::eventFilter(QObject *, QEvent *event)
void MarkerWidget::updatePersistentEditors() void MarkerWidget::updatePersistentEditors()
{ {
for(int i=0;i<model.rowCount();i++) { for(int i=0;i<model.rowCount();i++) {
auto columns = {MarkerModel::ColIndexTrace, MarkerModel::ColIndexType}; auto columns = {MarkerModel::ColIndexTrace, MarkerModel::ColIndexType, MarkerModel::ColIndexRestrict};
for(auto c : columns) { for(auto c : columns) {
auto index = model.index(i, c); auto index = model.index(i, c);
ui->treeView->closePersistentEditor(index); ui->treeView->closePersistentEditor(index);

View File

@ -334,7 +334,7 @@ void Math::TimeGateGraph::paintEvent(QPaintEvent *event)
auto input = gate->getInput()->rData(); auto input = gate->getInput()->rData();
Q_UNUSED(event) Q_UNUSED(event)
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
QPainter p(this); QPainter p(this);
// fill background // fill background
p.setBackground(QBrush(pref.Graphs.Color.background)); p.setBackground(QBrush(pref.Graphs.Color.background));

View File

@ -1206,11 +1206,14 @@ double Trace::maxX()
} }
} }
double Trace::findExtremum(bool max) double Trace::findExtremum(bool max, double xmin, double xmax)
{ {
double compare = max ? numeric_limits<double>::min() : numeric_limits<double>::max(); double compare = max ? numeric_limits<double>::min() : numeric_limits<double>::max();
double freq = 0.0; double freq = 0.0;
for(auto sample : lastMath->rData()) { for(auto sample : lastMath->rData()) {
if(sample.x < xmin || sample.x > xmax) {
continue;
}
double amplitude = abs(sample.y); double amplitude = abs(sample.y);
if((max && (amplitude > compare)) || (!max && (amplitude < compare))) { if((max && (amplitude > compare)) || (!max && (amplitude < compare))) {
// higher/lower extremum found // higher/lower extremum found
@ -1221,7 +1224,7 @@ double Trace::findExtremum(bool max)
return freq; return freq;
} }
std::vector<double> Trace::findPeakFrequencies(unsigned int maxPeaks, double minLevel, double minValley) std::vector<double> Trace::findPeakFrequencies(unsigned int maxPeaks, double minLevel, double minValley, double xmin, double xmax)
{ {
if(lastMath->getDataType() != DataType::Frequency) { if(lastMath->getDataType() != DataType::Frequency) {
// not in frequency domain // not in frequency domain
@ -1236,6 +1239,9 @@ std::vector<double> Trace::findPeakFrequencies(unsigned int maxPeaks, double min
double max_dbm = -200.0; double max_dbm = -200.0;
double min_dbm = 200.0; double min_dbm = 200.0;
for(auto d : lastMath->rData()) { for(auto d : lastMath->rData()) {
if(d.x < xmin || d.x > xmax) {
continue;
}
double dbm = Util::SparamTodB(d.y); double dbm = Util::SparamTodB(d.y);
if((dbm >= max_dbm) && (min_dbm <= dbm - minValley)) { if((dbm >= max_dbm) && (min_dbm <= dbm - minValley)) {
// potential peak frequency // potential peak frequency

View File

@ -67,13 +67,14 @@ public:
unsigned int size() const; unsigned int size() const;
double minX(); double minX();
double maxX(); double maxX();
double findExtremum(bool max); double findExtremum(bool max, double xmin = std::numeric_limits<double>::lowest(), double xmax = std::numeric_limits<double>::max());
/* Searches for peaks in the trace data and returns the peak frequencies in ascending order. /* Searches for peaks in the trace data and returns the peak frequencies in ascending order.
* Up to maxPeaks will be returned, with higher level peaks taking priority over lower level peaks. * Up to maxPeaks will be returned, with higher level peaks taking priority over lower level peaks.
* Only peaks with at least minLevel will be considered. * Only peaks with at least minLevel will be considered.
* To detect the next peak, the signal first has to drop at least minValley below the peak level. * To detect the next peak, the signal first has to drop at least minValley below the peak level.
*/ */
std::vector<double> findPeakFrequencies(unsigned int maxPeaks = 100, double minLevel = -100.0, double minValley = 3.0); std::vector<double> findPeakFrequencies(unsigned int maxPeaks = 100, double minLevel = -100.0, double minValley = 3.0,
double xmin = std::numeric_limits<double>::lowest(), double xmax = std::numeric_limits<double>::max());
enum class SampleType { enum class SampleType {
Frequency, Frequency,
TimeImpulse, TimeImpulse,

View File

@ -168,7 +168,7 @@ void TracePlot::paintEvent(QPaintEvent *event)
} }
Q_UNUSED(event) Q_UNUSED(event)
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
QPainter p(this); QPainter p(this);
// p.setRenderHint(QPainter::Antialiasing); // p.setRenderHint(QPainter::Antialiasing);
// fill background // fill background

View File

@ -80,7 +80,7 @@ void TracePolarChart::axisSetupDialog()
} }
void TracePolarChart::draw(QPainter &p) { void TracePolarChart::draw(QPainter &p) {
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
p.setRenderHint(QPainter::Antialiasing); p.setRenderHint(QPainter::Antialiasing);
auto w = p.window(); auto w = p.window();

View File

@ -189,7 +189,7 @@ bool TraceSmithChart::configureForTrace(Trace *t)
} }
void TraceSmithChart::draw(QPainter &p) { void TraceSmithChart::draw(QPainter &p) {
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
// translate coordinate system so that the smith chart sits in the origin and has a size of 1 // translate coordinate system so that the smith chart sits in the origin and has a size of 1
auto w = p.window(); auto w = p.window();

View File

@ -210,7 +210,7 @@ void TraceWaterfall::updateContextMenu()
void TraceWaterfall::draw(QPainter &p) void TraceWaterfall::draw(QPainter &p)
{ {
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
int xAxisSpace = pref.Graphs.fontSizeAxis * 3; int xAxisSpace = pref.Graphs.fontSizeAxis * 3;
constexpr int topMargin = 10; constexpr int topMargin = 10;

View File

@ -348,7 +348,7 @@ bool TraceXYPlot::supported(Trace *t)
void TraceXYPlot::draw(QPainter &p) void TraceXYPlot::draw(QPainter &p)
{ {
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
limitPassing = true; limitPassing = true;

View File

@ -61,8 +61,8 @@ void MatchingNetwork::transformDatapoint(VirtualDevice::VNAMeasurement &p)
p.measurements[name] = corrected.m11; p.measurements[name] = corrected.m11;
} }
// handle the rest of the measurements // handle the rest of the measurements
for(int i=0;i<VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;i++) { for(int i=1;i<=VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;i++) {
for(int j=i+1;j<VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;j++) { for(int j=i+1;j<=VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;j++) {
if(i == port) { if(i == port) {
auto S = uncorrected.toSparam(i, j); auto S = uncorrected.toSparam(i, j);
auto corrected = Sparam(m.p * ABCDparam(S, p.Z0), p.Z0); auto corrected = Sparam(m.p * ABCDparam(S, p.Z0), p.Z0);

View File

@ -80,7 +80,6 @@ VNA::VNA(AppWindow *window, QString name)
auto calLoad = calMenu->addAction("Load"); auto calLoad = calMenu->addAction("Load");
saveCal = calMenu->addAction("Save"); saveCal = calMenu->addAction("Save");
calMenu->addSeparator(); calMenu->addSeparator();
// saveCal->setEnabled(false);
connect(calLoad, &QAction::triggered, [=](){ connect(calLoad, &QAction::triggered, [=](){
LoadCalibration(""); LoadCalibration("");
@ -97,17 +96,15 @@ VNA::VNA(AppWindow *window, QString name)
auto calData = calMenu->addAction("Calibration Measurements"); auto calData = calMenu->addAction("Calibration Measurements");
connect(calData, &QAction::triggered, [=](){ connect(calData, &QAction::triggered, [=](){
cal.edit(); cal.edit();
// StartCalibrationDialog();
}); });
auto calEditKit = calMenu->addAction("Edit Calibration Kit"); auto calEditKit = calMenu->addAction("Edit Calibration Kit");
connect(calEditKit, &QAction::triggered, [=](){ connect(calEditKit, &QAction::triggered, [=](){
cal.getKit().edit(); cal.getKit().edit([=](){
// cal.getCalibrationKit().edit([=](){ if(cal.getCaltype().type != Calibration::Type::None) {
// if(calValid) { cal.compute(cal.getCaltype());
// ApplyCalibration(cal.getType()); }
// } });
// });
}); });
auto calElectronic = calMenu->addAction("Electronic Calibration"); auto calElectronic = calMenu->addAction("Electronic Calibration");
@ -518,7 +515,7 @@ VNA::VNA(AppWindow *window, QString name)
SetupSCPI(); SetupSCPI();
// Set initial sweep settings // Set initial sweep settings
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
if(pref.Acquisition.useMedianAveraging) { if(pref.Acquisition.useMedianAveraging) {
average.setMode(Averaging::Mode::Median); average.setMode(Averaging::Mode::Median);
@ -1408,7 +1405,7 @@ void VNA::SetupSCPI()
void VNA::ConstrainAndUpdateFrequencies() void VNA::ConstrainAndUpdateFrequencies()
{ {
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
double maxFreq; double maxFreq;
if(pref.Acquisition.harmonicMixing) { if(pref.Acquisition.harmonicMixing) {
maxFreq = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreqHarmonic; maxFreq = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreqHarmonic;
@ -1435,7 +1432,7 @@ void VNA::ConstrainAndUpdateFrequencies()
void VNA::LoadSweepSettings() void VNA::LoadSweepSettings()
{ {
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
QSettings s; QSettings s;
// frequency sweep settings // frequency sweep settings
settings.Freq.start = s.value("SweepFreqStart", pref.Startup.DefaultSweep.f_start).toULongLong(); settings.Freq.start = s.value("SweepFreqStart", pref.Startup.DefaultSweep.f_start).toULongLong();

View File

@ -171,7 +171,7 @@ AppWindow::AppWindow(QWidget *parent)
SetupSCPI(); SetupSCPI();
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
if(pref.Startup.UseSetupFile) { if(pref.Startup.UseSetupFile) {
LoadSetup(pref.Startup.SetupFile); LoadSetup(pref.Startup.SetupFile);
} }
@ -297,7 +297,7 @@ void AppWindow::SetupMenu()
void AppWindow::closeEvent(QCloseEvent *event) void AppWindow::closeEvent(QCloseEvent *event)
{ {
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
if(pref.Startup.UseSetupFile && pref.Startup.AutosaveSetupFile) { if(pref.Startup.UseSetupFile && pref.Startup.AutosaveSetupFile) {
SaveSetup(pref.Startup.SetupFile); SaveSetup(pref.Startup.SetupFile);
} }
@ -983,7 +983,7 @@ void AppWindow::UpdateAcquisitionFrequencies()
} }
Protocol::PacketInfo p; Protocol::PacketInfo p;
p.type = Protocol::PacketType::AcquisitionFrequencySettings; p.type = Protocol::PacketType::AcquisitionFrequencySettings;
auto pref = Preferences::getInstance(); auto& pref = Preferences::getInstance();
p.acquisitionFrequencySettings.IF1 = pref.Acquisition.IF1; p.acquisitionFrequencySettings.IF1 = pref.Acquisition.IF1;
p.acquisitionFrequencySettings.ADCprescaler = pref.Acquisition.ADCprescaler; p.acquisitionFrequencySettings.ADCprescaler = pref.Acquisition.ADCprescaler;
p.acquisitionFrequencySettings.DFTphaseInc = pref.Acquisition.DFTPhaseInc; p.acquisitionFrequencySettings.DFTphaseInc = pref.Acquisition.DFTPhaseInc;

View File

@ -5,6 +5,7 @@ using namespace std;
Averaging::Averaging() Averaging::Averaging()
{ {
averages = 1; averages = 1;
numMeasurements = 0;
mode = Mode::Mean; mode = Mode::Mean;
} }

View File

@ -33,7 +33,6 @@ private:
void process(unsigned int pointNum, std::vector<std::complex<double> > &data); void process(unsigned int pointNum, std::vector<std::complex<double> > &data);
std::vector<std::deque<std::vector<std::complex<double>>>> avg; std::vector<std::deque<std::vector<std::complex<double>>>> avg;
int maxPoints;
unsigned int numMeasurements; unsigned int numMeasurements;
unsigned int averages; unsigned int averages;
Mode mode; Mode mode;

View File

@ -20,6 +20,9 @@ int main(int argc, char *argv[]) {
qSetMessagePattern("%{time process}: [%{type}] %{message}"); qSetMessagePattern("%{time process}: [%{type}] %{message}");
Device::RegisterTypes();
VirtualDevice::RegisterTypes();
app = new QApplication(argc, argv); app = new QApplication(argc, argv);
QCoreApplication::setOrganizationName("LibreVNA"); QCoreApplication::setOrganizationName("LibreVNA");
QCoreApplication::setApplicationName("LibreVNA-GUI"); QCoreApplication::setApplicationName("LibreVNA-GUI");
@ -27,9 +30,6 @@ int main(int argc, char *argv[]) {
QCoreApplication::setApplicationVersion(window->getAppVersion() + "-" + QCoreApplication::setApplicationVersion(window->getAppVersion() + "-" +
window->getAppGitHash().left(9)); window->getAppGitHash().left(9));
Device::RegisterTypes();
VirtualDevice::RegisterTypes();
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
signal(SIGINT, tryExitGracefully); signal(SIGINT, tryExitGracefully);
#endif #endif

View File

@ -389,6 +389,13 @@ void PreferencesDialog::updateFromGUI()
p->nonTrivialWriting(); p->nonTrivialWriting();
} }
Preferences::~Preferences()
{
for(auto cd : compoundDevices) {
delete cd;
}
}
void Preferences::load() void Preferences::load()
{ {
QSettings settings; QSettings settings;

View File

@ -48,6 +48,8 @@ public:
static Preferences& getInstance() { static Preferences& getInstance() {
return instance; return instance;
} }
Preferences(const Preferences&) = delete;
~Preferences();
void load(); void load();
void store(); void store();
void edit(); void edit();