Sweep indicator on graphs

This commit is contained in:
Jan Käberich 2022-10-29 21:19:30 +02:00
parent 1fcf25d060
commit 6f0fb5430d
11 changed files with 370 additions and 55 deletions

View File

@ -2,6 +2,7 @@
#include <QIcon>
#include <QDebug>
#include <QDateTime>
using namespace std;
@ -234,6 +235,7 @@ void TraceModel::clearLiveData()
void TraceModel::addVNAData(const VirtualDevice::VNAMeasurement& d, TraceMath::DataType datatype)
{
source = DataSource::VNA;
lastReceivedData = QDateTime::currentDateTimeUtc();
for(auto t : traces) {
if (t->getSource() == Trace::Source::Live && !t->isPaused()) {
int index = -1;
@ -246,13 +248,14 @@ void TraceModel::addVNAData(const VirtualDevice::VNAMeasurement& d, TraceMath::D
td.x = d.dBm;
break;
case TraceMath::DataType::TimeZeroSpan:
td.x = d.us;
td.x = (double) d.us / 1000000.0;
index = d.pointNum;
break;
default:
// invalid type, can not add
return;
}
lastSweepPosition = td.x;
if(d.measurements.count(t->liveParameter())) {
td.y = d.measurements.at(t->liveParameter());
} else {
@ -267,6 +270,7 @@ void TraceModel::addVNAData(const VirtualDevice::VNAMeasurement& d, TraceMath::D
void TraceModel::addSAData(const VirtualDevice::SAMeasurement& d, const VirtualDevice::SASettings &settings)
{
source = DataSource::SA;
lastReceivedData = QDateTime::currentDateTimeUtc();
for(auto t : traces) {
if (t->getSource() == Trace::Source::Live && !t->isPaused()) {
int index = -1;
@ -284,6 +288,7 @@ void TraceModel::addSAData(const VirtualDevice::SAMeasurement& d, const VirtualD
// parameter not included in data, skip
continue;
}
lastSweepPosition = td.x;
t->addData(td, settings, index);
}
}
@ -299,6 +304,17 @@ void TraceModel::setSource(const DataSource &value)
source = value;
}
double TraceModel::getSweepPosition() const
{
auto t = QDateTime::currentDateTimeUtc();
constexpr uint64_t timeout_ms = 1000;
if(lastReceivedData.msecsTo(t) > timeout_ms) {
return std::numeric_limits<double>::quiet_NaN();
} else {
return lastSweepPosition;
}
}
MarkerModel *TraceModel::getMarkerModel() const
{
return markerModel;

View File

@ -1,4 +1,4 @@
#ifndef TRACEMODEL_H
#ifndef TRACEMODEL_H
#define TRACEMODEL_H
#include "Device/device.h"
@ -57,6 +57,8 @@ public:
DataSource getSource() const;
void setSource(const DataSource &value);
double getSweepPosition() const;
signals:
void SpanChanged(double fmin, double fmax);
void traceAdded(Trace *t);
@ -71,6 +73,8 @@ public slots:
private:
DataSource source;
double lastSweepPosition;
QDateTime lastReceivedData;
std::vector<Trace*> traces;
MarkerModel *markerModel;
};

View File

@ -168,6 +168,18 @@ void TracePlot::paintEvent(QPaintEvent *event)
traceRemovalPending = false;
}
xSweep = std::numeric_limits<double>::quiet_NaN();
for(auto t : traces) {
if(!t.second) {
continue;
}
Trace* tr = t.first;
if(tr->getSource() == Trace::Source::Live && tr->isVisible() && !tr->isPaused()) {
xSweep = model.getSweepPosition();
break;
}
}
Q_UNUSED(event)
auto& pref = Preferences::getInstance();
QPainter p(this);

View File

@ -110,6 +110,7 @@ protected:
static constexpr unsigned int marginRight = 0;
double sweep_fmin, sweep_fmax;
double xSweep; // current position in the sweep (NaN if no live traces are active on the plot)
TraceModel &model;
Marker *selectedMarker;
bool movingGraph;

View File

@ -185,6 +185,16 @@ void TracePolarChart::draw(QPainter &p) {
break;
}
if(pref.Graphs.SweepIndicator.hide && !isnan(xSweep) && trace->getSource() == Trace::Source::Live && trace->isVisible() && !trace->isPaused()) {
// check if this part of the trace is visible
double range = maximumVisibleFrequency - minimumVisibleFrequency;
double afterSweep = now.x - xSweep;
if(afterSweep > 0 && afterSweep * 100 / range <= pref.Graphs.SweepIndicator.hidePercent) {
// do not display this part of the trace
continue;
}
}
last = dataAddDx(last);
now = dataAddDx(now);

View File

@ -279,6 +279,16 @@ void TraceSmithChart::draw(QPainter &p) {
break;
}
if(pref.Graphs.SweepIndicator.hide && !isnan(xSweep) && trace->getSource() == Trace::Source::Live && trace->isVisible() && !trace->isPaused()) {
// check if this part of the trace is visible
double range = maximumVisibleFrequency - minimumVisibleFrequency;
double afterSweep = now.x - xSweep;
if(afterSweep > 0 && afterSweep * 100 / range <= pref.Graphs.SweepIndicator.hidePercent) {
// do not display this part of the trace
continue;
}
}
last = dataAddDx(last);
now = dataAddDx(now);

View File

@ -418,6 +418,25 @@ void TraceWaterfall::draw(QPainter &p)
}
p.setClipping(false);
// show sweep indicator if activated
if((xAxis.getType() == XAxis::Type::Frequency || xAxis.getType() == XAxis::Type::TimeZeroSpan || xAxis.getType() == XAxis::Type::Power)
&& !isnan(xSweep)) {
if(xSweep >= xAxis.getRangeMin() && xSweep <= xAxis.getRangeMax()) {
auto xpos = xAxis.transform(xSweep, plotAreaLeft, plotAreaLeft + plotAreaWidth);
pen = QPen(pref.Graphs.Color.axis);
pen.setCosmetic(true);
p.setPen(pen);
if(pref.Graphs.SweepIndicator.line) {
p.drawLine(xpos, plotAreaTop, xpos, plotAreaBottom);
}
if(pref.Graphs.SweepIndicator.triangle) {
for(unsigned int i=0;i<pref.Graphs.SweepIndicator.triangleSize;i++) {
p.drawLine(xpos - i,plotAreaBottom+i+1, xpos + i, plotAreaBottom+i+1);
}
}
}
}
if(dropPending) {
p.setOpacity(0.5);
p.setBrush(Qt::white);

View File

@ -544,6 +544,17 @@ void TraceXYPlot::draw(QPainter &p)
continue;
}
if((xAxis.getType() == XAxis::Type::Frequency || xAxis.getType() == XAxis::Type::TimeZeroSpan || xAxis.getType() == XAxis::Type::Power)
&& pref.Graphs.SweepIndicator.hide && !isnan(xSweep) && t->getSource() == Trace::Source::Live && t->isVisible() && !t->isPaused()) {
// check if this part of the trace is visible
double range = xAxis.getRangeMax() - xAxis.getRangeMin();
double afterSweep = now.x() - xSweep;
if(afterSweep > 0 && afterSweep * 100 / range <= pref.Graphs.SweepIndicator.hidePercent) {
// do not display this part of the trace
continue;
}
}
// scale to plot coordinates
auto p1 = plotValueToPixel(last, i);
auto p2 = plotValueToPixel(now, i);
@ -750,6 +761,26 @@ void TraceXYPlot::draw(QPainter &p)
}
}
// show sweep indicator if activated
if((xAxis.getType() == XAxis::Type::Frequency || xAxis.getType() == XAxis::Type::TimeZeroSpan || xAxis.getType() == XAxis::Type::Power)
&& !isnan(xSweep)) {
if(xSweep >= xAxis.getRangeMin() && xSweep <= xAxis.getRangeMax()) {
auto xpos = plotValueToPixel(QPointF(xSweep, 1.0), 0);
pen = QPen(pref.Graphs.Color.axis);
pen.setCosmetic(true);
p.setPen(pen);
if(pref.Graphs.SweepIndicator.line) {
p.drawLine(xpos.x(), plotAreaTop, xpos.x(), plotAreaBottom);
}
if(pref.Graphs.SweepIndicator.triangle) {
for(unsigned int i=0;i<pref.Graphs.SweepIndicator.triangleSize;i++) {
p.drawLine(xpos.x() - i,plotAreaBottom+i+1, xpos.x() + i, plotAreaBottom+i+1);
}
}
}
}
if(dropPending) {
p.setOpacity(0.5);
p.setBrush(Qt::white);

View File

@ -130,6 +130,8 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
// Graph page
ui->GraphsZoomFactor->setPrecision(3);
ui->GraphsSweepHidePercent->setPrecision(3);
ui->GraphsSweepHidePercent->setUnit("%");
// General page
if(p->TCPoverride) {
@ -327,6 +329,11 @@ void PreferencesDialog::setInitialGUIState()
ui->GraphsFontSizeTraceNames->setValue(p->Graphs.fontSizeTraceNames);
ui->GraphsEnablePanZoom->setChecked(p->Graphs.enablePanAndZoom);
ui->GraphsZoomFactor->setValue(p->Graphs.zoomFactor);
ui->GraphsSweepTriangle->setChecked(p->Graphs.SweepIndicator.triangle);
ui->GraphsSweepTriangleSize->setValue(p->Graphs.SweepIndicator.triangleSize);
ui->GraphsSweepLine->setChecked(p->Graphs.SweepIndicator.line);
ui->GraphsSweepHide->setChecked(p->Graphs.SweepIndicator.hide);
ui->GraphsSweepHidePercent->setValue(p->Graphs.SweepIndicator.hidePercent);
ui->MarkerShowMarkerData->setChecked(p->Marker.defaultBehavior.showDataOnGraphs);
ui->MarkerShowAllMarkerData->setChecked(p->Marker.defaultBehavior.showAllData);
@ -404,6 +411,11 @@ void PreferencesDialog::updateFromGUI()
p->Graphs.fontSizeTraceNames = ui->GraphsFontSizeTraceNames->value();
p->Graphs.enablePanAndZoom = ui->GraphsEnablePanZoom->isChecked();
p->Graphs.zoomFactor = ui->GraphsZoomFactor->value();
p->Graphs.SweepIndicator.triangle = ui->GraphsSweepTriangle->isChecked();
p->Graphs.SweepIndicator.triangleSize = ui->GraphsSweepTriangleSize->value();
p->Graphs.SweepIndicator.line = ui->GraphsSweepLine->isChecked();
p->Graphs.SweepIndicator.hide = ui->GraphsSweepHide->isChecked();
p->Graphs.SweepIndicator.hidePercent = ui->GraphsSweepHidePercent->value();
p->Marker.defaultBehavior.showDataOnGraphs = ui->MarkerShowMarkerData->isChecked();
p->Marker.defaultBehavior.showAllData = ui->MarkerShowAllMarkerData->isChecked();

View File

@ -137,6 +137,14 @@ public:
bool enablePanAndZoom;
double zoomFactor;
struct {
bool triangle;
unsigned int triangleSize;
bool line;
bool hide;
double hidePercent;
} SweepIndicator;
} Graphs;
struct {
struct {
@ -226,6 +234,11 @@ private:
{&Graphs.fontSizeTraceNames, "Graphs.fontSizeTraceNames", 12},
{&Graphs.enablePanAndZoom, "Graphs.enablePanAndZoom", true},
{&Graphs.zoomFactor, "Graphs.zoomFactor", 0.9},
{&Graphs.SweepIndicator.triangle, "Graphs.SweepIndicator.triangle", true},
{&Graphs.SweepIndicator.triangleSize, "Graphs.SweepIndicator.triangleSize", 5},
{&Graphs.SweepIndicator.line, "Graphs.SweepIndicator.line", false},
{&Graphs.SweepIndicator.hide, "Graphs.SweepIndicator.hide", false},
{&Graphs.SweepIndicator.hidePercent, "Graphs.SweepIndicator.hidePercent", 3.0},
{&Marker.defaultBehavior.showDataOnGraphs, "Marker.defaultBehavior.ShowDataOnGraphs", true},
{&Marker.defaultBehavior.showAllData, "Marker.defaultBehavior.ShowAllData", false},
{&Marker.interpolatePoints, "Marker.interpolatePoints", false},

View File

@ -6,14 +6,14 @@
<rect>
<x>0</x>
<y>0</y>
<width>909</width>
<height>657</height>
<width>989</width>
<height>632</height>
</rect>
</property>
<property name="windowTitle">
<string>Preferences</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
<layout class="QVBoxLayout" name="verticalLayout_25">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@ -74,39 +74,39 @@
</widget>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
<widget class="QStackedWidget" name="pageWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>-334</y>
<width>687</width>
<height>938</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="currentIndex">
<number>2</number>
</property>
<widget class="QWidget" name="Startup">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QStackedWidget" name="pageWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="Startup">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>744</width>
<height>920</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
@ -138,9 +138,6 @@
<property name="text">
<string>Last used</string>
</property>
<attribute name="buttonGroup">
<string notr="true">StartupSweepGroup</string>
</attribute>
</widget>
</item>
<item>
@ -148,9 +145,6 @@
<property name="text">
<string>Default values</string>
</property>
<attribute name="buttonGroup">
<string notr="true">StartupSweepGroup</string>
</attribute>
</widget>
</item>
<item>
@ -158,9 +152,6 @@
<property name="text">
<string>Setup file</string>
</property>
<attribute name="buttonGroup">
<string notr="true">StartupSweepGroup</string>
</attribute>
</widget>
</item>
<item>
@ -700,8 +691,27 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="Acquisition">
<layout class="QVBoxLayout" name="verticalLayout_20">
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="Acquisition">
<layout class="QVBoxLayout" name="verticalLayout_20">
<item>
<widget class="QScrollArea" name="scrollArea_2">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>605</width>
<height>866</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_21">
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
@ -1002,8 +1012,27 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="Graphs">
<layout class="QHBoxLayout" name="horizontalLayout_5">
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="Graphs">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QScrollArea" name="scrollArea_3">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_3">
<property name="geometry">
<rect>
<x>0</x>
<y>-216</y>
<width>749</width>
<height>952</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_22">
<item>
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
@ -1178,6 +1207,107 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_20">
<property name="title">
<string>Sweep Indicator</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_26">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_16">
<item>
<widget class="QCheckBox" name="GraphsSweepTriangle">
<property name="text">
<string>Show triangle of size </string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="GraphsSweepTriangleSize"/>
</item>
<item>
<widget class="QLabel" name="label_52">
<property name="text">
<string>below X axis</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QCheckBox" name="GraphsSweepLine">
<property name="text">
<string>Show vertical line in graph</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_17">
<item>
<widget class="QCheckBox" name="GraphsSweepHide">
<property name="text">
<string>Hide </string>
</property>
</widget>
</item>
<item>
<widget class="SIUnitEdit" name="GraphsSweepHidePercent"/>
</item>
<item>
<widget class="QLabel" name="label_53">
<property name="text">
<string>of displayed data after the sweep point</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_18">
<property name="title">
@ -1301,8 +1431,27 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="Marker">
<layout class="QHBoxLayout" name="horizontalLayout_6">
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="Marker">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QScrollArea" name="scrollArea_4">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_4">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>644</width>
<height>544</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_23">
<item>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
@ -1425,8 +1574,27 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="SCPIServer">
<layout class="QHBoxLayout" name="horizontalLayout_10">
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="SCPIServer">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QScrollArea" name="scrollArea_5">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_6">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>644</width>
<height>544</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
@ -1488,7 +1656,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>471</width>
<width>473</width>
<height>20</height>
</size>
</property>
@ -1496,8 +1664,27 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="CompoundDevices">
<layout class="QHBoxLayout" name="horizontalLayout_14">
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="CompoundDevices">
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QScrollArea" name="scrollArea_6">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_7">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>644</width>
<height>544</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_24">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>