Autoscale improvements

This commit is contained in:
Jan Käberich 2020-11-01 22:56:31 +01:00
parent 3976db8f9d
commit 32270dc747
12 changed files with 640 additions and 513 deletions

View File

@ -130,7 +130,9 @@ void TileWidget::on_bSmithchart_clicked()
void TileWidget::on_bXYplot_clicked() void TileWidget::on_bXYplot_clicked()
{ {
setContent(new TraceXYPlot(model)); auto plot = new TraceXYPlot(model);
setContent(plot);
plot->axisSetupDialog();
} }
void TileWidget::traceDeleted(TracePlot *) void TileWidget::traceDeleted(TracePlot *)

View File

@ -18,6 +18,7 @@ MarkerWidget::MarkerWidget(TraceMarkerModel &model, QWidget *parent) :
connect(&model.getModel(), &TraceModel::traceAdded, this, &MarkerWidget::updatePersistentEditors); connect(&model.getModel(), &TraceModel::traceAdded, this, &MarkerWidget::updatePersistentEditors);
connect(&model.getModel(), &TraceModel::traceRemoved, this, &MarkerWidget::updatePersistentEditors); connect(&model.getModel(), &TraceModel::traceRemoved, this, &MarkerWidget::updatePersistentEditors);
connect(&model.getModel(), &TraceModel::traceNameChanged, this, &MarkerWidget::updatePersistentEditors);
} }
MarkerWidget::~MarkerWidget() MarkerWidget::~MarkerWidget()

View File

@ -156,16 +156,22 @@ void Trace::updateTimeDomainData()
// system_clock::now().time_since_epoch() // system_clock::now().time_since_epoch()
// ).count(); // ).count();
auto steps = size(); auto steps = size();
if(minFreq() * size() != maxFreq()) { auto firstStep = minFreq();
if(firstStep == 0) {
// zero as first step would result in infinite number of points, skip and start with second
firstStep = _data[1].frequency;
steps--;
}
if(firstStep * steps != maxFreq()) {
// data is not available with correct frequency spacing, calculate required steps // data is not available with correct frequency spacing, calculate required steps
steps = maxFreq() / minFreq(); steps = maxFreq() / firstStep;
} }
const double PI = 3.141592653589793238463; const double PI = 3.141592653589793238463;
// reserve vector for negative frequenies and DC as well // reserve vector for negative frequenies and DC as well
vector<complex<double>> frequencyDomain(2*steps + 1); vector<complex<double>> frequencyDomain(2*steps + 1);
// copy frequencies, use the flipped conjugate for negative part // copy frequencies, use the flipped conjugate for negative part
for(unsigned int i = 1;i<=steps;i++) { for(unsigned int i = 1;i<=steps;i++) {
auto S = getData(minFreq() * i); auto S = getData(firstStep * i);
constexpr double alpha0 = 0.54; constexpr double alpha0 = 0.54;
auto hamming = alpha0 - (1.0 - alpha0) * -cos(PI * i / steps); auto hamming = alpha0 - (1.0 - alpha0) * -cos(PI * i / steps);
S *= hamming; S *= hamming;
@ -180,13 +186,18 @@ void Trace::updateTimeDomainData()
auto fft_bins = frequencyDomain.size(); auto fft_bins = frequencyDomain.size();
timeDomain.clear(); timeDomain.clear();
timeDomain.resize(fft_bins); timeDomain.resize(fft_bins);
const double fs = 1.0 / (minFreq() * fft_bins); const double fs = 1.0 / (firstStep * fft_bins);
double last_step = 0.0; double last_step = 0.0;
Fft::transform(frequencyDomain, true); Fft::transform(frequencyDomain, true);
constexpr double c = 299792458;
for(unsigned int i = 0;i<fft_bins;i++) { for(unsigned int i = 0;i<fft_bins;i++) {
TimedomainData t; TimedomainData t;
t.time = fs * i; t.time = fs * i;
t.distance = t.time * c * 0.66; // TODO user settable velocity factor
if(isReflection()) {
t.distance /= 2;
}
t.impulseResponse = real(frequencyDomain[i]) / fft_bins; t.impulseResponse = real(frequencyDomain[i]) / fft_bins;
t.stepResponse = last_step; t.stepResponse = last_step;
last_step += t.impulseResponse; last_step += t.impulseResponse;

View File

@ -24,6 +24,7 @@ public:
class TimedomainData { class TimedomainData {
public: public:
double time; double time;
double distance;
double impulseResponse; double impulseResponse;
double stepResponse; double stepResponse;
}; };

View File

@ -20,6 +20,9 @@ TraceModel::~TraceModel()
void TraceModel::addTrace(Trace *t) void TraceModel::addTrace(Trace *t)
{ {
beginInsertRows(QModelIndex(), traces.size(), traces.size()); beginInsertRows(QModelIndex(), traces.size(), traces.size());
connect(t, &Trace::nameChanged, [=]() {
emit traceNameChanged(t);
});
traces.push_back(t); traces.push_back(t);
endInsertRows(); endInsertRows();
emit traceAdded(t); emit traceAdded(t);

View File

@ -32,6 +32,7 @@ signals:
void traceAdded(Trace *t); void traceAdded(Trace *t);
void traceRemoved(Trace *t); void traceRemoved(Trace *t);
void requiredExcitation(bool excitePort1, bool excitePort2); void requiredExcitation(bool excitePort1, bool excitePort2);
void traceNameChanged(Trace *t);
public slots: public slots:
void clearVNAData(); void clearVNAData();

View File

@ -121,8 +121,8 @@ void TracePlot::triggerReplot()
{ {
auto now = QTime::currentTime(); auto now = QTime::currentTime();
if (lastUpdate.msecsTo(now) >= MinUpdateInterval) { if (lastUpdate.msecsTo(now) >= MinUpdateInterval) {
replot();
lastUpdate = now; lastUpdate = now;
replot();
} }
} }

View File

@ -16,7 +16,7 @@ public:
virtual void enableTrace(Trace *t, bool enabled); virtual void enableTrace(Trace *t, bool enabled);
void mouseDoubleClickEvent(QMouseEvent *event) override; void mouseDoubleClickEvent(QMouseEvent *event) override;
virtual void setXAxis(double min, double max){Q_UNUSED(min);Q_UNUSED(max)}; virtual void updateSpan(double min, double max){Q_UNUSED(min);Q_UNUSED(max)};
static std::set<TracePlot *> getPlots(); static std::set<TracePlot *> getPlots();

View File

@ -91,8 +91,11 @@ public:
case TraceXYPlot::YAxisType::Impedance: { case TraceXYPlot::YAxisType::Impedance: {
auto sample = t.getTDR()[i]; auto sample = t.getTDR()[i];
QPointF p; QPointF p;
// TODO set distance if(Xtype == TraceXYPlot::XAxisType::Time) {
p.setX(sample.time); p.setX(sample.time);
} else {
p.setX(sample.distance);
}
p.setY(TimeAxisTransformation(Ytype, &t, i)); p.setY(TimeAxisTransformation(Ytype, &t, i));
return p; return p;
} }
@ -116,23 +119,23 @@ TraceXYPlot::TraceXYPlot(TraceModel &model, QWidget *parent)
selectedMarker(nullptr) selectedMarker(nullptr)
{ {
YAxis[0].log = false; YAxis[0].log = false;
YAxis[0].Ytype = YAxisType::Disabled; YAxis[0].type = YAxisType::Disabled;
YAxis[0].rangeDiv = 1; YAxis[0].rangeDiv = 1;
YAxis[0].rangeMax = 10; YAxis[0].rangeMax = 10;
YAxis[0].rangeMin = 0; YAxis[0].rangeMin = 0;
YAxis[0].autorange = false; YAxis[0].autorange = false;
YAxis[1].log = false; YAxis[1].log = false;
YAxis[1].Ytype = YAxisType::Disabled; YAxis[1].type = YAxisType::Disabled;
YAxis[1].rangeDiv = 1; YAxis[1].rangeDiv = 1;
YAxis[1].rangeMax = 10; YAxis[1].rangeMax = 10;
YAxis[1].rangeMin = 0; YAxis[1].rangeMin = 0;
YAxis[1].autorange = false; YAxis[1].autorange = false;
XAxis.Xtype = XAxisType::Frequency; XAxis.type = XAxisType::Frequency;
XAxis.log = false; XAxis.log = false;
XAxis.rangeDiv = 1; XAxis.rangeDiv = 1;
XAxis.rangeMax = 10; XAxis.rangeMax = 10;
XAxis.rangeMin = 0; XAxis.rangeMin = 0;
XAxis.autorange = true; XAxis.mode = XAxisMode::UseSpan;
plot = new QwtPlot(this); plot = new QwtPlot(this);
@ -168,10 +171,10 @@ TraceXYPlot::TraceXYPlot(TraceModel &model, QWidget *parent)
setYAxis(0, YAxisType::Magnitude, false, false, -120, 20, 10); setYAxis(0, YAxisType::Magnitude, false, false, -120, 20, 10);
setYAxis(1, YAxisType::Phase, false, false, -180, 180, 30); setYAxis(1, YAxisType::Phase, false, false, -180, 180, 30);
// enable autoscaling and set for full span (no information about actual span available yet) // enable autoscaling and set for full span (no information about actual span available yet)
setXAxis(0, 6000000000); updateSpan(0, 6000000000);
setXAxis(XAxisType::Frequency, true, 0, 6000000000, 600000000); setXAxis(XAxisType::Frequency, XAxisMode::UseSpan, 0, 6000000000, 600000000);
// get notified when the span changes // get notified when the span changes
connect(&model, &TraceModel::SpanChanged, this, qOverload<double, double>(&TraceXYPlot::setXAxis)); connect(&model, &TraceModel::SpanChanged, this, qOverload<double, double>(&TraceXYPlot::updateSpan));
allPlots.insert(this); allPlots.insert(this);
} }
@ -187,16 +190,15 @@ TraceXYPlot::~TraceXYPlot()
allPlots.erase(this); allPlots.erase(this);
} }
void TraceXYPlot::setXAxis(double min, double max) void TraceXYPlot::updateSpan(double min, double max)
{ {
sweep_fmin = min; sweep_fmin = min;
sweep_fmax = max; sweep_fmax = max;
updateXAxis();
} }
void TraceXYPlot::setYAxis(int axis, TraceXYPlot::YAxisType type, bool log, bool autorange, double min, double max, double div) void TraceXYPlot::setYAxis(int axis, TraceXYPlot::YAxisType type, bool log, bool autorange, double min, double max, double div)
{ {
if(YAxis[axis].Ytype != type) { if(YAxis[axis].type != type) {
// remove traces that are active but not supported with the new axis type // remove traces that are active but not supported with the new axis type
bool erased = false; bool erased = false;
do { do {
@ -210,12 +212,12 @@ void TraceXYPlot::setYAxis(int axis, TraceXYPlot::YAxisType type, bool log, bool
} }
} while(erased); } while(erased);
if(isTDRtype(YAxis[axis].Ytype)) { if(isTDRtype(YAxis[axis].type)) {
for(auto t : tracesAxis[axis]) { for(auto t : tracesAxis[axis]) {
t->removeTDRinterest(); t->removeTDRinterest();
} }
} }
YAxis[axis].Ytype = type; YAxis[axis].type = type;
for(auto t : tracesAxis[axis]) { for(auto t : tracesAxis[axis]) {
// supported but needs an adjusted QwtSeriesData // supported but needs an adjusted QwtSeriesData
@ -252,20 +254,19 @@ void TraceXYPlot::setYAxis(int axis, TraceXYPlot::YAxisType type, bool log, bool
replot(); replot();
} }
void TraceXYPlot::setXAxis(XAxisType type, bool autorange, double min, double max, double div) void TraceXYPlot::setXAxis(XAxisType type, XAxisMode mode, double min, double max, double div)
{ {
XAxis.Xtype = type; XAxis.type = type;
XAxis.autorange = autorange; XAxis.mode = mode;
XAxis.rangeMin = min; XAxis.rangeMin = min;
XAxis.rangeMax = max; XAxis.rangeMax = max;
XAxis.rangeDiv = div; XAxis.rangeDiv = div;
updateXAxis();
} }
void TraceXYPlot::enableTrace(Trace *t, bool enabled) void TraceXYPlot::enableTrace(Trace *t, bool enabled)
{ {
for(int axis = 0;axis < 2;axis++) { for(int axis = 0;axis < 2;axis++) {
if(supported(t, YAxis[axis].Ytype)) { if(supported(t, YAxis[axis].type)) {
enableTraceAxis(t, axis, enabled); enableTraceAxis(t, axis, enabled);
} }
} }
@ -290,17 +291,20 @@ bool TraceXYPlot::isTDRtype(TraceXYPlot::YAxisType type)
} }
} }
void TraceXYPlot::axisSetupDialog()
{
auto setup = new XYplotAxisDialog(this);
setup->show();
}
void TraceXYPlot::updateContextMenu() void TraceXYPlot::updateContextMenu()
{ {
contextmenu->clear(); contextmenu->clear();
auto setup = new QAction("Axis setup...", contextmenu); auto setup = new QAction("Axis setup...", contextmenu);
connect(setup, &QAction::triggered, [this]() { connect(setup, &QAction::triggered, this, &TraceXYPlot::axisSetupDialog);
auto setup = new XYplotAxisDialog(this);
setup->show();
});
contextmenu->addAction(setup); contextmenu->addAction(setup);
for(int axis = 0;axis < 2;axis++) { for(int axis = 0;axis < 2;axis++) {
if(YAxis[axis].Ytype == YAxisType::Disabled) { if(YAxis[axis].type == YAxisType::Disabled) {
continue; continue;
} }
if(axis == 0) { if(axis == 0) {
@ -310,7 +314,7 @@ void TraceXYPlot::updateContextMenu()
} }
for(auto t : traces) { for(auto t : traces) {
// Skip traces that are not applicable for the selected axis type // Skip traces that are not applicable for the selected axis type
if(!supported(t.first, YAxis[axis].Ytype)) { if(!supported(t.first, YAxis[axis].type)) {
continue; continue;
} }
@ -341,6 +345,7 @@ bool TraceXYPlot::supported(Trace *)
void TraceXYPlot::replot() void TraceXYPlot::replot()
{ {
updateXAxis();
plot->replot(); plot->replot();
} }
@ -381,12 +386,12 @@ void TraceXYPlot::enableTraceAxis(Trace *t, int axis, bool enabled)
markerAdded(m); markerAdded(m);
} }
} }
if(isTDRtype(YAxis[axis].Ytype)) { if(isTDRtype(YAxis[axis].type)) {
t->addTDRinterest(); t->addTDRinterest();
} }
traceColorChanged(t); traceColorChanged(t);
} else { } else {
if(isTDRtype(YAxis[axis].Ytype)) { if(isTDRtype(YAxis[axis].type)) {
t->removeTDRinterest(); t->removeTDRinterest();
} }
tracesAxis[axis].erase(t); tracesAxis[axis].erase(t);
@ -436,22 +441,78 @@ bool TraceXYPlot::supported(Trace *t, TraceXYPlot::YAxisType type)
void TraceXYPlot::updateXAxis() void TraceXYPlot::updateXAxis()
{ {
if(XAxis.autorange && sweep_fmax-sweep_fmin > 0) { if(XAxis.mode == XAxisMode::Manual) {
plot->setAxisScale(QwtPlot::xBottom, XAxis.rangeMin, XAxis.rangeMax, XAxis.rangeDiv);
} else {
// automatic mode, figure out limits
double max = std::numeric_limits<double>::lowest();
double min = std::numeric_limits<double>::max();
if(XAxis.mode == XAxisMode::UseSpan) {
min = sweep_fmin;
max = sweep_fmax;
} else if(XAxis.mode == XAxisMode::FitTraces) {
for(auto t : traces) {
bool enabled = (tracesAxis[0].find(t.first) != tracesAxis[0].end()
|| tracesAxis[1].find(t.first) != tracesAxis[1].end());
auto trace = t.first;
if(enabled && trace->isVisible()) {
// this trace is currently displayed
double trace_min, trace_max;
switch(XAxis.type) {
case XAxisType::Frequency:
trace_min = trace->minFreq();
trace_max = trace->maxFreq();
break;
case XAxisType::Time:
trace_min = trace->getTDR().front().time;
trace_max = trace->getTDR().back().time;
break;
case XAxisType::Distance:
trace_min = trace->getTDR().front().distance;
trace_max = trace->getTDR().back().distance;
break;
}
if(trace_min < min) {
min = trace_min;
}
if(trace_max > max) {
max = trace_max;
}
}
}
}
if(min >= max) {
// still at initial values, no traces are active, leave axis unchanged
return;
}
constexpr int minDivisions = 8;
double max_div_step = (max - min) / minDivisions;
int zeros = floor(log10(max_div_step));
double decimals_shift = pow(10, zeros);
max_div_step /= decimals_shift;
if(max_div_step >= 5) {
max_div_step = 5;
} else if(max_div_step >= 2) {
max_div_step = 2;
} else {
max_div_step = 1;
}
auto div_step = max_div_step * decimals_shift;
// round min up to next multiple of div_step
min = ceil(min / div_step) * div_step;
QList<double> tickList; QList<double> tickList;
for(double tick = sweep_fmin;tick <= sweep_fmax;tick+= (sweep_fmax-sweep_fmin)/10) { for(double tick = min;tick <= max;tick += div_step) {
tickList.append(tick); tickList.append(tick);
} }
QwtScaleDiv scalediv(sweep_fmin, sweep_fmax, QList<double>(), QList<double>(), tickList); QwtScaleDiv scalediv(min, max, QList<double>(), QList<double>(), tickList);
plot->setAxisScaleDiv(QwtPlot::xBottom, scalediv); plot->setAxisScaleDiv(QwtPlot::xBottom, scalediv);
} else {
plot->setAxisScale(QwtPlot::xBottom, XAxis.rangeMin, XAxis.rangeMax, XAxis.rangeDiv);
} }
triggerReplot(); triggerReplot();
} }
QwtSeriesData<QPointF> *TraceXYPlot::createQwtSeriesData(Trace &t, int axis) QwtSeriesData<QPointF> *TraceXYPlot::createQwtSeriesData(Trace &t, int axis)
{ {
return new QwtTraceSeries(t, YAxis[axis].Ytype, XAxis.Xtype); return new QwtTraceSeries(t, YAxis[axis].type, XAxis.type);
} }
void TraceXYPlot::traceColorChanged(Trace *t) void TraceXYPlot::traceColorChanged(Trace *t)
@ -513,7 +574,7 @@ void TraceXYPlot::markerDataChanged(TraceMarker *m)
{ {
auto qwtMarker = markers[m]; auto qwtMarker = markers[m];
qwtMarker->setXValue(m->getFrequency()); qwtMarker->setXValue(m->getFrequency());
qwtMarker->setYValue(FrequencyAxisTransformation(YAxis[0].Ytype, m->getData())); qwtMarker->setYValue(FrequencyAxisTransformation(YAxis[0].type, m->getData()));
triggerReplot(); triggerReplot();
} }

View File

@ -50,17 +50,24 @@ public:
Time, Time,
Distance, Distance,
}; };
enum class XAxisMode {
UseSpan,
FitTraces,
Manual,
};
virtual void setXAxis(double min, double max) override; virtual void updateSpan(double min, double max) override;
void setYAxis(int axis, YAxisType type, bool log, bool autorange, double min, double max, double div); void setYAxis(int axis, YAxisType type, bool log, bool autorange, double min, double max, double div);
void setXAxis(XAxisType type, bool autorange, double min, double max, double div); void setXAxis(XAxisType type, XAxisMode mode, double min, double max, double div);
void enableTrace(Trace *t, bool enabled) override; void enableTrace(Trace *t, bool enabled) override;
// Applies potentially changed colors to all XY-plots // Applies potentially changed colors to all XY-plots
static void updateGraphColors(); static void updateGraphColors();
bool isTDRtype(YAxisType type); bool isTDRtype(YAxisType type);
public slots:
void axisSetupDialog();
protected: protected:
virtual void updateContextMenu() override; virtual void updateContextMenu() override;
virtual bool supported(Trace *t) override; virtual bool supported(Trace *t) override;
@ -85,20 +92,27 @@ private:
std::set<Trace*> tracesAxis[2]; std::set<Trace*> tracesAxis[2];
class Axis { class YAxis {
public: public:
union { YAxisType type;
YAxisType Ytype; bool log; // not used yet
XAxisType Xtype;
};
bool log;
bool autorange; bool autorange;
double rangeMin; double rangeMin;
double rangeMax; double rangeMax;
double rangeDiv; double rangeDiv;
}; };
Axis YAxis[2]; class XAxis {
Axis XAxis; public:
XAxisType type;
XAxisMode mode;
bool log; // not used yet
double rangeMin;
double rangeMax;
double rangeDiv;
};
YAxis YAxis[2];
XAxis XAxis;
double sweep_fmin, sweep_fmax; double sweep_fmin, sweep_fmax;
using CurveData = struct { using CurveData = struct {

View File

@ -59,16 +59,17 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
ui->Xmin->setEnabled(!checked); ui->Xmin->setEnabled(!checked);
ui->Xmax->setEnabled(!checked); ui->Xmax->setEnabled(!checked);
ui->Xdivs->setEnabled(!checked); ui->Xdivs->setEnabled(!checked);
ui->Xautomode->setEnabled(checked);
}); });
ui->XType->setCurrentIndex((int) plot->XAxis.Xtype); ui->XType->setCurrentIndex((int) plot->XAxis.type);
ui->Xmin->setPrefixes("pnum kMG"); ui->Xmin->setPrefixes("pnum kMG");
ui->Xmax->setPrefixes("pnum kMG"); ui->Xmax->setPrefixes("pnum kMG");
ui->Xdivs->setPrefixes("pnum kMG"); ui->Xdivs->setPrefixes("pnum kMG");
// Fill initial values // Fill initial values
// assume same order in YAxisType enum as in ComboBox items // assume same order in YAxisType enum as in ComboBox items
ui->Y1type->setCurrentIndex((int) plot->YAxis[0].Ytype); ui->Y1type->setCurrentIndex((int) plot->YAxis[0].type);
if(plot->YAxis[0].log) { if(plot->YAxis[0].log) {
ui->Y1log->setChecked(true); ui->Y1log->setChecked(true);
} else { } else {
@ -79,7 +80,7 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
ui->Y1max->setValueQuiet(plot->YAxis[0].rangeMax); ui->Y1max->setValueQuiet(plot->YAxis[0].rangeMax);
ui->Y1divs->setValueQuiet(plot->YAxis[0].rangeDiv); ui->Y1divs->setValueQuiet(plot->YAxis[0].rangeDiv);
ui->Y2type->setCurrentIndex((int) plot->YAxis[1].Ytype); ui->Y2type->setCurrentIndex((int) plot->YAxis[1].type);
if(plot->YAxis[1].log) { if(plot->YAxis[1].log) {
ui->Y2log->setChecked(true); ui->Y2log->setChecked(true);
} else { } else {
@ -90,7 +91,12 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
ui->Y2max->setValueQuiet(plot->YAxis[1].rangeMax); ui->Y2max->setValueQuiet(plot->YAxis[1].rangeMax);
ui->Y2divs->setValueQuiet(plot->YAxis[1].rangeDiv); ui->Y2divs->setValueQuiet(plot->YAxis[1].rangeDiv);
ui->Xauto->setChecked(plot->XAxis.autorange); ui->Xauto->setChecked(plot->XAxis.mode != TraceXYPlot::XAxisMode::Manual);
if(plot->XAxis.mode == TraceXYPlot::XAxisMode::UseSpan) {
ui->Xautomode->setCurrentIndex(0);
} else {
ui->Xautomode->setCurrentIndex(1);
}
ui->Xmin->setValueQuiet(plot->XAxis.rangeMin); ui->Xmin->setValueQuiet(plot->XAxis.rangeMin);
ui->Xmax->setValueQuiet(plot->XAxis.rangeMax); ui->Xmax->setValueQuiet(plot->XAxis.rangeMax);
ui->Xdivs->setValueQuiet(plot->XAxis.rangeDiv); ui->Xdivs->setValueQuiet(plot->XAxis.rangeDiv);
@ -106,7 +112,24 @@ void XYplotAxisDialog::on_buttonBox_accepted()
// set plot values to the ones selected in the dialog // set plot values to the ones selected in the dialog
plot->setYAxis(0, (TraceXYPlot::YAxisType) ui->Y1type->currentIndex(), ui->Y1log->isChecked(), ui->Y1auto->isChecked(), ui->Y1min->value(), ui->Y1max->value(), ui->Y1divs->value()); plot->setYAxis(0, (TraceXYPlot::YAxisType) ui->Y1type->currentIndex(), ui->Y1log->isChecked(), ui->Y1auto->isChecked(), ui->Y1min->value(), ui->Y1max->value(), ui->Y1divs->value());
plot->setYAxis(1, (TraceXYPlot::YAxisType) ui->Y2type->currentIndex(), ui->Y2log->isChecked(), ui->Y2auto->isChecked(), ui->Y2min->value(), ui->Y2max->value(), ui->Y2divs->value()); plot->setYAxis(1, (TraceXYPlot::YAxisType) ui->Y2type->currentIndex(), ui->Y2log->isChecked(), ui->Y2auto->isChecked(), ui->Y2min->value(), ui->Y2max->value(), ui->Y2divs->value());
plot->setXAxis((TraceXYPlot::XAxisType) ui->XType->currentIndex(), ui->Xauto->isChecked(), ui->Xmin->value(), ui->Xmax->value(), ui->Xdivs->value()); TraceXYPlot::XAxisMode mode;
if(ui->Xauto->isChecked()) {
if(ui->Xautomode->currentIndex() == 0) {
mode = TraceXYPlot::XAxisMode::UseSpan;
} else {
mode = TraceXYPlot::XAxisMode::FitTraces;
}
} else {
mode = TraceXYPlot::XAxisMode::Manual;
}
plot->setXAxis((TraceXYPlot::XAxisType) ui->XType->currentIndex(), mode, ui->Xmin->value(), ui->Xmax->value(), ui->Xdivs->value());
}
static void enableComboBoxItem(QComboBox *cb, int itemNum, bool enable) {
auto *model = qobject_cast<QStandardItemModel *>(cb->model());
auto item = model->item(itemNum);
item->setFlags(enable ? item->flags() | Qt::ItemIsEnabled
: item->flags() & ~Qt::ItemIsEnabled);
} }
void XYplotAxisDialog::XAxisTypeChanged(int XAxisIndex) void XYplotAxisDialog::XAxisTypeChanged(int XAxisIndex)
@ -116,14 +139,8 @@ void XYplotAxisDialog::XAxisTypeChanged(int XAxisIndex)
for(auto t : TraceXYPlot::YAxisTypes) { for(auto t : TraceXYPlot::YAxisTypes) {
auto enable = supported.count(t) > 0; auto enable = supported.count(t) > 0;
auto index = (int) t; auto index = (int) t;
auto *model = qobject_cast<QStandardItemModel *>(ui->Y1type->model()); enableComboBoxItem(ui->Y1type, index, enable);
auto item = model->item(index); enableComboBoxItem(ui->Y2type, index, enable);
item->setFlags(enable ? item->flags() | Qt::ItemIsEnabled
: item->flags() & ~Qt::ItemIsEnabled);
model = qobject_cast<QStandardItemModel *>(ui->Y2type->model());
item = model->item(index);
item->setFlags(enable ? item->flags() | Qt::ItemIsEnabled
: item->flags() & ~Qt::ItemIsEnabled);
} }
// Disable Yaxis if previously selected type is not supported // Disable Yaxis if previously selected type is not supported
if(!supported.count((TraceXYPlot::YAxisType)ui->Y1type->currentIndex())) { if(!supported.count((TraceXYPlot::YAxisType)ui->Y1type->currentIndex())) {
@ -133,6 +150,16 @@ void XYplotAxisDialog::XAxisTypeChanged(int XAxisIndex)
ui->Y2type->setCurrentIndex(0); ui->Y2type->setCurrentIndex(0);
} }
if(type == TraceXYPlot::XAxisType::Frequency) {
enableComboBoxItem(ui->Xautomode, 0, true);
} else {
// auto mode using span not supported in time mode
if(ui->Xautomode->currentIndex() == 0) {
ui->Xautomode->setCurrentIndex(1);
enableComboBoxItem(ui->Xautomode, 0, false);
}
}
QString unit; QString unit;
switch(type) { switch(type) {
case TraceXYPlot::XAxisType::Frequency: unit = "Hz"; break; case TraceXYPlot::XAxisType::Frequency: unit = "Hz"; break;

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>715</width> <width>689</width>
<height>282</height> <height>282</height>
</rect> </rect>
</property> </property>
@ -16,487 +16,493 @@
<property name="modal"> <property name="modal">
<bool>true</bool> <bool>true</bool>
</property> </property>
<widget class="QDialogButtonBox" name="buttonBox"> <layout class="QVBoxLayout" name="verticalLayout_4">
<property name="geometry"> <item>
<rect> <layout class="QHBoxLayout" name="horizontalLayout_4">
<x>9</x> <item>
<y>248</y> <layout class="QVBoxLayout" name="verticalLayout">
<width>166</width> <item>
<height>25</height> <widget class="QLabel" name="label_2">
</rect> <property name="font">
</property> <font>
<property name="orientation"> <pointsize>15</pointsize>
<enum>Qt::Horizontal</enum> </font>
</property> </property>
<property name="standardButtons"> <property name="text">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> <string>Primary Y axis</string>
</property> </property>
</widget> <property name="alignment">
<widget class="QWidget" name="layoutWidget"> <set>Qt::AlignCenter</set>
<property name="geometry"> </property>
<rect> </widget>
<x>10</x> </item>
<y>10</y> <item>
<width>701</width> <layout class="QFormLayout" name="formLayout">
<height>233</height> <item row="0" column="0">
</rect> <widget class="QLabel" name="label">
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<pointsize>15</pointsize>
</font>
</property>
<property name="text">
<string>Primary Y axis</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="Y1type">
<item>
<property name="text"> <property name="text">
<string>Disabled</string> <string>Type:</string>
</property> </property>
</item> </widget>
<item> </item>
<item row="0" column="1">
<widget class="QComboBox" name="Y1type">
<item>
<property name="text">
<string>Disabled</string>
</property>
</item>
<item>
<property name="text">
<string>Magnitude</string>
</property>
</item>
<item>
<property name="text">
<string>Phase</string>
</property>
</item>
<item>
<property name="text">
<string>VSWR</string>
</property>
</item>
<item>
<property name="text">
<string>Impulse Response</string>
</property>
</item>
<item>
<property name="text">
<string>Step Response</string>
</property>
</item>
<item>
<property name="text">
<string>Impedance</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="Y1linear">
<property name="text"> <property name="text">
<string>Magnitude</string> <string>Linear</string>
</property>
<attribute name="buttonGroup">
<string notr="true">Y1group</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="Y1log">
<property name="enabled">
<bool>false</bool>
</property> </property>
</item>
<item>
<property name="text"> <property name="text">
<string>Phase</string> <string>Log</string>
</property> </property>
</item> <attribute name="buttonGroup">
<item> <string notr="true">Y1group</string>
</attribute>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>VSWR</string> <string>Range:</string>
</property> </property>
</item> </widget>
<item> </item>
<item row="0" column="1">
<widget class="QCheckBox" name="Y1auto">
<property name="text"> <property name="text">
<string>Impulse Response</string> <string>Auto</string>
</property> </property>
</item> </widget>
<item> </item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>Step Response</string> <string>Maximum:</string>
</property> </property>
</item> </widget>
<item> </item>
<item row="1" column="1">
<widget class="SIUnitEdit" name="Y1max"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>Impedance</string> <string>Minimum:</string>
</property> </property>
</item> </widget>
</widget> </item>
</item> <item row="2" column="1">
</layout> <widget class="SIUnitEdit" name="Y1min"/>
</item> </item>
<item> <item row="3" column="0">
<widget class="Line" name="line"> <widget class="QLabel" name="label_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="Y1linear">
<property name="text">
<string>Linear</string>
</property>
<attribute name="buttonGroup">
<string notr="true">Y1group</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="Y1log">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Log</string>
</property>
<attribute name="buttonGroup">
<string notr="true">Y1group</string>
</attribute>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Range:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="Y1auto">
<property name="text">
<string>Auto</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Maximum:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="SIUnitEdit" name="Y1max"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Minimum:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="SIUnitEdit" name="Y1min"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Divisions:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="SIUnitEdit" name="Y1divs"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_7">
<property name="font">
<font>
<pointsize>15</pointsize>
</font>
</property>
<property name="text">
<string>Secondary Y axis</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="Y2type">
<item>
<property name="text"> <property name="text">
<string>Disabled</string> <string>Divisions:</string>
</property> </property>
</item> </widget>
<item> </item>
<item row="3" column="1">
<widget class="SIUnitEdit" name="Y1divs"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_7">
<property name="font">
<font>
<pointsize>15</pointsize>
</font>
</property>
<property name="text">
<string>Secondary Y axis</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_8">
<property name="text"> <property name="text">
<string>Magnitude</string> <string>Type:</string>
</property> </property>
</item> </widget>
<item> </item>
<item row="0" column="1">
<widget class="QComboBox" name="Y2type">
<item>
<property name="text">
<string>Disabled</string>
</property>
</item>
<item>
<property name="text">
<string>Magnitude</string>
</property>
</item>
<item>
<property name="text">
<string>Phase</string>
</property>
</item>
<item>
<property name="text">
<string>VSWR</string>
</property>
</item>
<item>
<property name="text">
<string>Impulse Response</string>
</property>
</item>
<item>
<property name="text">
<string>Step Response</string>
</property>
</item>
<item>
<property name="text">
<string>Impedance</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QRadioButton" name="Y2linear">
<property name="text"> <property name="text">
<string>Phase</string> <string>Linear</string>
</property>
<attribute name="buttonGroup">
<string notr="true">Y2group</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="Y2log">
<property name="enabled">
<bool>false</bool>
</property> </property>
</item>
<item>
<property name="text"> <property name="text">
<string>VSWR</string> <string>Log</string>
</property> </property>
</item> <attribute name="buttonGroup">
<item> <string notr="true">Y2group</string>
</attribute>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="text"> <property name="text">
<string>Impulse Response</string> <string>Range:</string>
</property> </property>
</item> </widget>
<item> </item>
<item row="0" column="1">
<widget class="QCheckBox" name="Y2auto">
<property name="text"> <property name="text">
<string>Step Response</string> <string>Auto</string>
</property> </property>
</item> </widget>
<item> </item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text"> <property name="text">
<string>Impedance</string> <string>Maximum:</string>
</property> </property>
</item> </widget>
</widget> </item>
</item> <item row="1" column="1">
</layout> <widget class="SIUnitEdit" name="Y2max"/>
</item> </item>
<item> <item row="2" column="0">
<widget class="Line" name="line_4"> <widget class="QLabel" name="label_11">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QRadioButton" name="Y2linear">
<property name="text">
<string>Linear</string>
</property>
<attribute name="buttonGroup">
<string notr="true">Y2group</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="Y2log">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Log</string>
</property>
<attribute name="buttonGroup">
<string notr="true">Y2group</string>
</attribute>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Range:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="Y2auto">
<property name="text">
<string>Auto</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Maximum:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="SIUnitEdit" name="Y2max"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Minimum:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="SIUnitEdit" name="Y2min"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Divisions:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="SIUnitEdit" name="Y2divs"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_13">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>15</pointsize>
</font>
</property>
<property name="text">
<string>X axis</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_5">
<item row="0" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="XType">
<item>
<property name="text"> <property name="text">
<string>Frequency</string> <string>Minimum:</string>
</property> </property>
</item> </widget>
<item> </item>
<item row="2" column="1">
<widget class="SIUnitEdit" name="Y2min"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_12">
<property name="text"> <property name="text">
<string>Time</string> <string>Divisions:</string>
</property> </property>
</item> </widget>
<item> </item>
<item row="3" column="1">
<widget class="SIUnitEdit" name="Y2divs"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_13">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>15</pointsize>
</font>
</property>
<property name="text">
<string>X axis</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_5">
<item row="0" column="0">
<widget class="QLabel" name="label_14">
<property name="text"> <property name="text">
<string>Distance</string> <string>Type:</string>
</property> </property>
</item> </widget>
</widget> </item>
</item> <item row="0" column="1">
</layout> <widget class="QComboBox" name="XType">
</item> <item>
<item> <property name="text">
<widget class="Line" name="line_7"> <string>Frequency</string>
<property name="orientation"> </property>
<enum>Qt::Horizontal</enum> </item>
</property> <item>
</widget> <property name="text">
</item> <string>Time</string>
<item> </property>
<spacer name="verticalSpacer"> </item>
<property name="orientation"> <item>
<enum>Qt::Vertical</enum> <property name="text">
</property> <string>Distance</string>
<property name="sizeHint" stdset="0"> </property>
<size> </item>
<width>20</width> </widget>
<height>40</height> </item>
</size> </layout>
</property> </item>
</spacer> <item>
</item> <widget class="Line" name="line_7">
<item> <property name="orientation">
<layout class="QFormLayout" name="formLayout_6"> <enum>Qt::Horizontal</enum>
<item row="0" column="0"> </property>
<widget class="QLabel" name="label_15"> </widget>
<property name="text"> </item>
<string>Range:</string> <item>
</property> <spacer name="verticalSpacer">
</widget> <property name="orientation">
</item> <enum>Qt::Vertical</enum>
<item row="0" column="1"> </property>
<widget class="QCheckBox" name="Xauto"> <property name="sizeHint" stdset="0">
<property name="text"> <size>
<string>Auto</string> <width>20</width>
</property> <height>40</height>
</widget> </size>
</item> </property>
<item row="1" column="0"> </spacer>
<widget class="QLabel" name="label_16"> </item>
<property name="text"> <item>
<string>Maximum:</string> <layout class="QFormLayout" name="formLayout_6">
</property> <item row="0" column="0">
</widget> <widget class="QLabel" name="label_15">
</item> <property name="text">
<item row="1" column="1"> <string>Range:</string>
<widget class="SIUnitEdit" name="Xmax"/> </property>
</item> </widget>
<item row="2" column="0"> </item>
<widget class="QLabel" name="label_17"> <item row="0" column="1">
<property name="text"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<string>Minimum:</string> <item>
</property> <widget class="QCheckBox" name="Xauto">
</widget> <property name="text">
</item> <string>Auto</string>
<item row="2" column="1"> </property>
<widget class="SIUnitEdit" name="Xmin"/> </widget>
</item> </item>
<item row="3" column="0"> <item>
<widget class="QLabel" name="label_18"> <widget class="QComboBox" name="Xautomode">
<property name="text"> <item>
<string>Divisions:</string> <property name="text">
</property> <string>Use Span</string>
</widget> </property>
</item> </item>
<item row="3" column="1"> <item>
<widget class="SIUnitEdit" name="Xdivs"/> <property name="text">
</item> <string>Fit Traces</string>
</layout> </property>
</item> </item>
</layout> </widget>
</item> </item>
</layout> </layout>
</widget> </item>
<item row="1" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Maximum:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="SIUnitEdit" name="Xmax"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Minimum:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="SIUnitEdit" name="Xmin"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_18">
<property name="text">
<string>Divisions:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="SIUnitEdit" name="Xdivs"/>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>