Contant lines/limits on XY-Plot
This commit is contained in:
parent
cacea26e3f
commit
27490e1a33
Binary file not shown.
@ -379,6 +379,9 @@ Example (assuming <averaging sweep> = 3):
|
||||
\subsubsection{VNA:ACQuisition:FINished}
|
||||
\query{Queries whether the average filter has reached a steady state (that is <acquired sweeps> = <averaging sweeps>)}{VNA:ACQuisition:FINished?}{None}{TRUE or FALSE}
|
||||
|
||||
\subsubsection{VNA:ACQuisition:LIMit}
|
||||
\query{Queries the status of limits that maybe set up on any graph}{VNA:ACQuisition:LIMit?}{None}{PASS or FAIL}
|
||||
|
||||
\subsubsection{VNA:STIMulus:LVL}
|
||||
\event{Sets the output power of the stimulus signal when sweep type is frequency}{VNA:STIMulus:LVL}{<power>, in dBm}
|
||||
\query{Queries the currently selected output power}{VNA:STIMulus:LVL?}{None}{power in dBm}
|
||||
@ -602,6 +605,9 @@ Example (assuming <averaging sweep> = 3):
|
||||
\subsubsection{SA:ACQuisition:FINished}
|
||||
\query{Queries whether the average filter has reached a steady state (that is <acquired sweeps> = <averaging sweeps>)}{SA:ACQuisition:FINished?}{None}{TRUE or FALSE}
|
||||
|
||||
\subsubsection{SA:ACQuisition:LIMit}
|
||||
\query{Queries the status of limits that maybe set up on any graph}{SA:ACQuisition:LIMit?}{None}{PASS or FAIL}
|
||||
|
||||
\subsubsection{SA:ACQuisition:SIGid}
|
||||
\event{Enables/disables signal identification}{SA:ACQuisition:SIGid}{<enabled>, option are TRUE, FALSE, 1 or 0}
|
||||
\query{Queries whether signal identification is enabled}{SA:ACQuisition:SIGid?}{None}{TRUE or FALSE}
|
||||
|
@ -110,6 +110,18 @@ void TileWidget::fromJSON(nlohmann::json j)
|
||||
}
|
||||
}
|
||||
|
||||
bool TileWidget::allLimitsPassing()
|
||||
{
|
||||
if(isSplit) {
|
||||
return child1->allLimitsPassing() && child2->allLimitsPassing();
|
||||
} else if(hasContent) {
|
||||
return content->getLimitPassing();
|
||||
} else {
|
||||
// empty tile always passes
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void TileWidget::splitVertically()
|
||||
{
|
||||
if(isSplit) {
|
||||
|
@ -28,6 +28,9 @@ public:
|
||||
|
||||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
// check potential trace limits on graphs, only returns true if all traces in all graphs are within limits
|
||||
bool allLimitsPassing();
|
||||
public slots:
|
||||
void splitVertically();
|
||||
void splitHorizontally();
|
||||
|
@ -905,6 +905,9 @@ void SpectrumAnalyzer::SetupSCPI()
|
||||
scpi_acq->add(new SCPICommand("FINished", nullptr, [=](QStringList) -> QString {
|
||||
return average.getLevel() == averages ? "TRUE" : "FALSE";
|
||||
}));
|
||||
scpi_acq->add(new SCPICommand("LIMit", nullptr, [=](QStringList) -> QString {
|
||||
return central->allLimitsPassing() ? "PASS" : "FAIL";
|
||||
}));
|
||||
scpi_acq->add(new SCPICommand("SIGid", [=](QStringList params) -> QString {
|
||||
if (params.size() != 1) {
|
||||
return "ERROR";
|
||||
|
@ -97,10 +97,16 @@
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tableWidget">
|
||||
<widget class="QTableWidget" name="pointTable">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -186,21 +192,5 @@
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>XYPlotConstantLineEditDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
@ -22,7 +22,8 @@ TracePlot::TracePlot(TraceModel &model, QWidget *parent)
|
||||
traceRemovalPending(false),
|
||||
dropPending(false),
|
||||
dropTrace(nullptr),
|
||||
marginTop(20)
|
||||
marginTop(20),
|
||||
limitPassing(true)
|
||||
{
|
||||
contextmenu = new QMenu();
|
||||
markedForDeletion = false;
|
||||
@ -492,6 +493,11 @@ void TracePlot::markerRemoved(Marker *m)
|
||||
triggerReplot();
|
||||
}
|
||||
|
||||
bool TracePlot::getLimitPassing() const
|
||||
{
|
||||
return limitPassing;
|
||||
}
|
||||
|
||||
TraceModel &TracePlot::getModel() const
|
||||
{
|
||||
return model;
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
|
||||
TraceModel &getModel() const;
|
||||
|
||||
bool getLimitPassing() const;
|
||||
|
||||
public slots:
|
||||
void updateGraphColors();
|
||||
|
||||
@ -106,6 +108,8 @@ protected:
|
||||
QLabel *cursorLabel;
|
||||
|
||||
unsigned int marginTop;
|
||||
|
||||
bool limitPassing;
|
||||
};
|
||||
|
||||
#endif // TRACEPLOT_H
|
||||
|
@ -350,7 +350,7 @@ void TraceXYPlot::draw(QPainter &p)
|
||||
{
|
||||
auto pref = Preferences::getInstance();
|
||||
|
||||
bool limitPassing = true;
|
||||
limitPassing = true;
|
||||
|
||||
auto w = p.window();
|
||||
auto pen = QPen(pref.Graphs.Color.axis, 0);
|
||||
@ -647,7 +647,42 @@ void TraceXYPlot::draw(QPainter &p)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO check limitPassing
|
||||
// only show limit indication if there are limit lines configured
|
||||
if(constantLines.size() > 0) {
|
||||
switch(pref.Graphs.limitIndication) {
|
||||
case GraphLimitIndication::PassFailText: {
|
||||
QString text;
|
||||
if(limitPassing) {
|
||||
p.setPen(Qt::green);
|
||||
text = "PASS";
|
||||
} else {
|
||||
p.setPen(Qt::red);
|
||||
text = "FAIL";
|
||||
}
|
||||
auto font = p.font();
|
||||
font.setPixelSize(20);
|
||||
p.setFont(font);
|
||||
p.drawText(plotRect.x() + 2, plotRect.y() + 22, text);
|
||||
}
|
||||
break;
|
||||
case GraphLimitIndication::Overlay:
|
||||
if(!limitPassing) {
|
||||
p.setOpacity(0.5);
|
||||
p.setBrush(Qt::red);
|
||||
p.setPen(Qt::red);
|
||||
p.drawRect(plotRect);
|
||||
auto font = p.font();
|
||||
font.setPixelSize(20);
|
||||
p.setFont(font);
|
||||
p.setOpacity(1.0);
|
||||
p.setPen(Qt::red);
|
||||
p.drawText(plotRect, Qt::AlignCenter, "LIMIT FAIL");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(dropPending) {
|
||||
p.setOpacity(0.5);
|
||||
@ -1200,18 +1235,72 @@ void XYPlotConstantLine::editDialog(QString xUnit, QString yUnitPrimary, QString
|
||||
connect(ui->color, &ColorPickerButton::colorChanged, [=](){
|
||||
color = ui->color->getColor();
|
||||
});
|
||||
auto updatePointTable = [=](){
|
||||
sort(points.begin(), points.end(), [](QPointF &a, QPointF &b) -> bool{
|
||||
return a.x() < b.x();
|
||||
});
|
||||
ui->pointTable->blockSignals(true);
|
||||
ui->pointTable->clear();
|
||||
ui->pointTable->setHorizontalHeaderLabels({"#", "X", "Y"});
|
||||
ui->pointTable->setColumnCount(3);
|
||||
ui->pointTable->setRowCount(points.size());
|
||||
QString yUnit = axis == Axis::Primary ? yUnitPrimary : yUnitSecondary;
|
||||
for(unsigned int i=0;i<points.size();i++) {
|
||||
auto numItem = new QTableWidgetItem(QString::number(i+1));
|
||||
numItem->setFlags(numItem->flags() &= ~(Qt::ItemIsEditable | Qt::ItemIsSelectable));
|
||||
auto xItem = new QTableWidgetItem(Unit::ToString(points[i].x(), xUnit, "pnum kMG", 6));
|
||||
auto yItem = new QTableWidgetItem(Unit::ToString(points[i].y(), yUnit, "pnum kMG", 6));
|
||||
ui->pointTable->setItem(i, 0, numItem);
|
||||
ui->pointTable->setItem(i, 1, xItem);
|
||||
ui->pointTable->setItem(i, 2, yItem);
|
||||
}
|
||||
ui->pointTable->blockSignals(false);
|
||||
};
|
||||
connect(ui->axis, qOverload<int>(&QComboBox::currentIndexChanged), [=](){
|
||||
axis = (Axis) ui->axis->currentIndex();
|
||||
// TODO apply unit change
|
||||
updatePointTable();
|
||||
});
|
||||
connect(ui->passFail, qOverload<int>(&QComboBox::currentIndexChanged), [=](){
|
||||
passFail = (PassFail) ui->passFail->currentIndex();
|
||||
});
|
||||
|
||||
// TODO handle adding/removing of points
|
||||
// handle adding/removing of points
|
||||
connect(ui->pointTable, &QTableWidget::itemChanged, [=](QTableWidgetItem *item){
|
||||
auto row = ui->pointTable->row(item);
|
||||
auto column = ui->pointTable->column(item);
|
||||
auto& point = points[row];
|
||||
if(column == 1) {
|
||||
// changed X coordinate
|
||||
point.setX(Unit::FromString(item->text(), xUnit, "pnum kMG"));
|
||||
// potentially reordered the points, update whole table
|
||||
updatePointTable();
|
||||
} else {
|
||||
// change Y coordinate
|
||||
QString yUnit = axis == Axis::Primary ? yUnitPrimary : yUnitSecondary;
|
||||
point.setY(Unit::FromString(item->text(), yUnit, "pnum kMG"));
|
||||
// point order only depends on X coordinate, no table update necessary, only update text of the changed item
|
||||
ui->pointTable->blockSignals(true);
|
||||
item->setText(Unit::ToString(point.y(), yUnit, "pnum kMG", 6));
|
||||
ui->pointTable->blockSignals(false);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->addPoint, &QPushButton::clicked, [=](){
|
||||
points.push_back(QPointF());
|
||||
updatePointTable();
|
||||
});
|
||||
connect(ui->removePoint, &QPushButton::clicked, [=](){
|
||||
auto row = ui->pointTable->currentRow();
|
||||
if(row >= 0 && row < (int) points.size()) {
|
||||
points.erase(points.begin() + row);
|
||||
updatePointTable();
|
||||
}
|
||||
});
|
||||
|
||||
connect(d, &QDialog::finished, this, &XYPlotConstantLine::editingFinished);
|
||||
|
||||
updatePointTable();
|
||||
|
||||
if(AppWindow::showGUI()) {
|
||||
d->show();
|
||||
}
|
||||
@ -1221,7 +1310,8 @@ QString XYPlotConstantLine::getDescription()
|
||||
{
|
||||
QString ret;
|
||||
ret += name;
|
||||
ret += ", " + QString::number(points.size()) + " points, limit: "+PassFailToString(passFail);
|
||||
ret += ", " + AxisToString(axis) + " axis, ";
|
||||
ret += QString::number(points.size()) + " points, limit: "+PassFailToString(passFail);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,11 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
||||
};
|
||||
|
||||
for(auto l : plot->constantLines) {
|
||||
ui->lineList->addItem(l->getDescription());
|
||||
auto item = new QListWidgetItem(l->getDescription());
|
||||
ui->lineList->addItem(item);
|
||||
connect(l, &XYPlotConstantLine::editingFinished, [=](){
|
||||
item->setText(l->getDescription());
|
||||
});
|
||||
}
|
||||
if(plot->constantLines.size() > 0) {
|
||||
ui->removeLine->setEnabled(true);
|
||||
|
@ -1374,6 +1374,9 @@ void VNA::SetupSCPI()
|
||||
scpi_acq->add(new SCPICommand("FINished", nullptr, [=](QStringList) -> QString {
|
||||
return average.getLevel() == averages ? "TRUE" : "FALSE";
|
||||
}));
|
||||
scpi_acq->add(new SCPICommand("LIMit", nullptr, [=](QStringList) -> QString {
|
||||
return central->allLimitsPassing() ? "PASS" : "FAIL";
|
||||
}));
|
||||
auto scpi_stim = new SCPINode("STIMulus");
|
||||
SCPINode::add(scpi_stim);
|
||||
scpi_stim->add(new SCPICommand("LVL", [=](QStringList params) -> QString {
|
||||
|
@ -248,6 +248,7 @@ void PreferencesDialog::setInitialGUIState()
|
||||
ui->GraphsColorTicksBackgroundEnabled->setChecked(p->Graphs.Color.Ticks.Background.enabled);
|
||||
ui->GraphsColorTicksBackground->setColor(p->Graphs.Color.Ticks.Background.background);
|
||||
ui->GraphsDomainChangeBehavior->setCurrentIndex((int) p->Graphs.domainChangeBehavior);
|
||||
ui->GraphsLimitIndication->setCurrentIndex((int) p->Graphs.limitIndication);
|
||||
ui->GraphsLineWidth->setValue(p->Graphs.lineWidth);
|
||||
ui->GraphsFontSizeAxis->setValue(p->Graphs.fontSizeAxis);
|
||||
ui->GraphsFontSizeCursorOverlay->setValue(p->Graphs.fontSizeCursorOverlay);
|
||||
@ -312,6 +313,7 @@ void PreferencesDialog::updateFromGUI()
|
||||
p->Graphs.Color.Ticks.Background.background = ui->GraphsColorTicksBackground->getColor();
|
||||
p->Graphs.Color.Ticks.divisions = ui->GraphsColorTicksDivisions->getColor();
|
||||
p->Graphs.domainChangeBehavior = (GraphDomainChangeBehavior) ui->GraphsDomainChangeBehavior->currentIndex();
|
||||
p->Graphs.limitIndication = (GraphLimitIndication) ui->GraphsLimitIndication->currentIndex();
|
||||
p->Graphs.lineWidth = ui->GraphsLineWidth->value();
|
||||
p->Graphs.fontSizeAxis = ui->GraphsFontSizeAxis->value();
|
||||
p->Graphs.fontSizeCursorOverlay = ui->GraphsFontSizeCursorOverlay->value();
|
||||
|
@ -16,6 +16,14 @@ enum GraphDomainChangeBehavior {
|
||||
|
||||
Q_DECLARE_METATYPE(GraphDomainChangeBehavior);
|
||||
|
||||
enum GraphLimitIndication {
|
||||
DontShowAnything = 0,
|
||||
PassFailText = 1,
|
||||
Overlay = 2,
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(GraphLimitIndication);
|
||||
|
||||
|
||||
class Preferences : public Savable {
|
||||
public:
|
||||
@ -93,6 +101,7 @@ public:
|
||||
} Ticks;
|
||||
} Color;
|
||||
GraphDomainChangeBehavior domainChangeBehavior;
|
||||
GraphLimitIndication limitIndication;
|
||||
|
||||
double lineWidth;
|
||||
int fontSizeAxis;
|
||||
@ -166,6 +175,7 @@ private:
|
||||
{&Graphs.Color.Ticks.Background.background, "Graphs.Color.Ticks.Background.background", QColor(20, 20, 20)},
|
||||
{&Graphs.Color.Ticks.divisions, "Graphs.Color.Ticks.divisions", QColor(Qt::gray)},
|
||||
{&Graphs.domainChangeBehavior, "Graphs.domainChangeBehavior", GraphDomainChangeBehavior::AdjustGraphs},
|
||||
{&Graphs.limitIndication, "Graphs.limitIndication", GraphLimitIndication::PassFailText},
|
||||
{&Graphs.lineWidth, "Graphs.lineWidth", 1.0},
|
||||
{&Graphs.fontSizeAxis, "Graphs.fontSizeAxis", 10},
|
||||
{&Graphs.fontSizeCursorOverlay, "Graphs.fontSizeCursorOverlay", 12},
|
||||
|
@ -77,9 +77,9 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>654</width>
|
||||
<height>884</height>
|
||||
<y>-319</y>
|
||||
<width>651</width>
|
||||
<height>854</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
@ -98,7 +98,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>3</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="Startup">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
@ -1150,6 +1150,41 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_17">
|
||||
<property name="title">
|
||||
<string>Limit checking</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_12">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_43">
|
||||
<property name="text">
|
||||
<string>Behavior:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="GraphsLimitIndication">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Don't show any indication</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PASS/FAIL text in graph corner</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Overlay over whole graph on FAIL</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
@ -1360,16 +1395,16 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SIUnitEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>CustomWidgets/siunitedit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ColorPickerButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>CustomWidgets/colorpickerbutton.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SIUnitEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>CustomWidgets/siunitedit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
Loading…
Reference in New Issue
Block a user