mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-06 06:53:37 +00:00
Improve graph divisions and markers
- Added group delay option to markers - Additional configuration for calculation of group delay in the preferences - Specify divisions as amount of divisions instead of spacing - Add option for auto divisions on graph with manual min/max limits
This commit is contained in:
parent
fe08937bb7
commit
b2d07d532d
24 changed files with 462 additions and 243 deletions
|
|
@ -1249,8 +1249,8 @@ void SpectrumAnalyzer::createDefaultTracesAndGraphs(int ports)
|
|||
{
|
||||
tiles->clear();
|
||||
auto traceXY = new TraceXYPlot(traceModel);
|
||||
traceXY->setYAxis(0, YAxis::Type::Magnitude, false, false, -120,0,10);
|
||||
traceXY->setYAxis(1, YAxis::Type::Disabled, false, true, 0,0,1);
|
||||
traceXY->setYAxis(0, YAxis::Type::Magnitude, false, false, -120,0,12,false);
|
||||
traceXY->setYAxis(1, YAxis::Type::Disabled, false, true, 0, 0, 10, false);
|
||||
traceXY->updateSpan(settings.freqStart, settings.freqStop);
|
||||
|
||||
tiles->setPlot(traceXY);
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ QString Marker::formatToString(Marker::Format f)
|
|||
case Format::Capacitance: return "Capacitance";
|
||||
case Format::Inductance: return "Inductance";
|
||||
case Format::QualityFactor: return "Quality Factor";
|
||||
case Format::GroupDelay: return "Group Delay";
|
||||
case Format::TOI: return "Third order intercept";
|
||||
case Format::AvgTone: return "Average Tone Level";
|
||||
case Format::AvgModulationProduct: return "Average Modulation Product Level";
|
||||
|
|
@ -234,6 +235,7 @@ std::vector<Marker::Format> Marker::applicableFormats()
|
|||
ret.push_back(Format::dB);
|
||||
ret.push_back(Format::dBAngle);
|
||||
ret.push_back(Format::RealImag);
|
||||
ret.push_back(Format::GroupDelay);
|
||||
}
|
||||
if(parentTrace) {
|
||||
if(parentTrace->isReflection()) {
|
||||
|
|
@ -346,6 +348,9 @@ std::vector<Marker::Format> Marker::defaultActiveFormats()
|
|||
if(pref.Marker.defaultBehavior.showQualityFactor) {
|
||||
ret.push_back(Format::QualityFactor);
|
||||
}
|
||||
if(pref.Marker.defaultBehavior.showGroupDelay) {
|
||||
ret.push_back(Format::GroupDelay);
|
||||
}
|
||||
if(pref.Marker.defaultBehavior.showNoise) {
|
||||
ret.push_back(Format::Noise);
|
||||
}
|
||||
|
|
@ -477,6 +482,7 @@ QString Marker::readableData(Format f)
|
|||
case Format::Capacitance: return "Δ:"+Unit::ToString(Util::SparamToCapacitance(data, position, trace()->getReferenceImpedance()) - Util::SparamToCapacitance(delta->data, delta->position, trace()->getReferenceImpedance()), "F", "pnum ", 4);
|
||||
case Format::Inductance: return "Δ:"+Unit::ToString(Util::SparamToInductance(data, position, trace()->getReferenceImpedance()) - Util::SparamToInductance(delta->data, delta->position, trace()->getReferenceImpedance()), "H", "pnum ", 4);
|
||||
case Format::QualityFactor: return "ΔQ:" + Unit::ToString(Util::SparamToQualityFactor(data) - Util::SparamToQualityFactor(delta->data), "", " ", 3);
|
||||
case Format::GroupDelay: return "Δτg:"+Unit::ToString(trace()->getGroupDelay(position) - delta->trace()->getGroupDelay(delta->position), "s", "pnum ", 4);
|
||||
case Format::Noise: return "Δ:"+Unit::ToString(parentTrace->getNoise(position) - delta->parentTrace->getNoise(delta->position), "dbm/Hz", " ", 3);
|
||||
default: return "Invalid";
|
||||
}
|
||||
|
|
@ -501,6 +507,7 @@ QString Marker::readableData(Format f)
|
|||
case Format::Capacitance: return Unit::ToString(Util::SparamToCapacitance(data, position, trace()->getReferenceImpedance()), "F", "pnum ", 4);
|
||||
case Format::Inductance: return Unit::ToString(Util::SparamToInductance(data, position, trace()->getReferenceImpedance()), "H", "pnum ", 4);
|
||||
case Format::QualityFactor: return "Q:" + Unit::ToString(Util::SparamToQualityFactor(data), "", " ", 3);
|
||||
case Format::GroupDelay: return "τg:"+Unit::ToString(trace()->getGroupDelay(position), "s", "pnum ", 4);
|
||||
case Format::Noise: return Unit::ToString(parentTrace->getNoise(position), "dbm/Hz", " ", 3);
|
||||
case Format::TOI: {
|
||||
auto avgFundamental = (helperMarkers[0]->toDecibel() + helperMarkers[1]->toDecibel()) / 2;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public:
|
|||
Capacitance,
|
||||
Inductance,
|
||||
QualityFactor,
|
||||
GroupDelay,
|
||||
// Noise marker parameters
|
||||
Noise,
|
||||
PhaseNoise,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
<property name="title">
|
||||
<string>X Axis</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
|
|
@ -75,7 +75,18 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="SIUnitEdit" name="Xdivs"/>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="Xdivs"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="XautoDivs">
|
||||
<property name="text">
|
||||
<string>Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
@ -85,7 +96,7 @@
|
|||
<property name="title">
|
||||
<string>Y Axis</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_5">
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
|
|
@ -128,7 +139,18 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="SIUnitEdit" name="Ydivs"/>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="Ydivs"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="YautoDivs">
|
||||
<property name="text">
|
||||
<string>Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ EyeDiagramPlot::EyeDiagramPlot(TraceModel &model, QWidget *parent)
|
|||
calcData = &data[0];
|
||||
displayData = &data[1];
|
||||
|
||||
xAxis.set(XAxis::Type::Time, false, true, 0, 0.000001, 1);
|
||||
yAxis.set(YAxis::Type::Real, false, true, -1, 1, 1);
|
||||
xAxis.set(XAxis::Type::Time, false, true, 0, 0.000001, 10, true);
|
||||
yAxis.set(YAxis::Type::Real, false, true, -1, 1, 10, true);
|
||||
initializeTraceInfo();
|
||||
|
||||
destructing = false;
|
||||
|
|
@ -101,10 +101,10 @@ void EyeDiagramPlot::enableTrace(Trace *t, bool enabled)
|
|||
void EyeDiagramPlot::replot()
|
||||
{
|
||||
if(xAxis.getAutorange()) {
|
||||
xAxis.set(xAxis.getType(), false, true, 0, calculatedTime(), 8);
|
||||
xAxis.set(xAxis.getType(), false, true, 0, calculatedTime(), 10, false);
|
||||
}
|
||||
if(yAxis.getAutorange()) {
|
||||
yAxis.set(yAxis.getType(), false, true, minDisplayVoltage(), maxDisplayVoltage(), 8);
|
||||
yAxis.set(yAxis.getType(), false, true, minDisplayVoltage(), maxDisplayVoltage(), 10, false);
|
||||
}
|
||||
TracePlot::replot();
|
||||
}
|
||||
|
|
@ -115,13 +115,13 @@ void EyeDiagramPlot::move(const QPoint &vect)
|
|||
// can only move axis in linear mode
|
||||
// calculate amount of movement
|
||||
double distance = xAxis.inverseTransform(vect.x(), 0, plotAreaWidth) - xAxis.getRangeMin();
|
||||
xAxis.set(xAxis.getType(), false, false, xAxis.getRangeMin() - distance, xAxis.getRangeMax() - distance, xAxis.getRangeDiv());
|
||||
xAxis.set(xAxis.getType(), false, false, xAxis.getRangeMin() - distance, xAxis.getRangeMax() - distance, xAxis.getDivs(), xAxis.getAutoDivs());
|
||||
}
|
||||
if(!yAxis.getLog()) {
|
||||
// can only move axis in linear mode
|
||||
// calculate amount of movement
|
||||
double distance = yAxis.inverseTransform(vect.y(), 0, plotAreaTop - plotAreaBottom) - yAxis.getRangeMin();
|
||||
yAxis.set(yAxis.getType(), false, false, yAxis.getRangeMin() - distance, yAxis.getRangeMax() - distance, yAxis.getRangeDiv());
|
||||
yAxis.set(yAxis.getType(), false, false, yAxis.getRangeMin() - distance, yAxis.getRangeMax() - distance, yAxis.getDivs(), yAxis.getAutoDivs());
|
||||
}
|
||||
replot();
|
||||
}
|
||||
|
|
@ -134,7 +134,7 @@ void EyeDiagramPlot::zoom(const QPoint ¢er, double factor, bool horizontally
|
|||
double cp = xAxis.inverseTransform(center.x(), plotAreaLeft, plotAreaLeft + plotAreaWidth);
|
||||
double min = ((xAxis.getRangeMin() - cp) * factor) + cp;
|
||||
double max = ((xAxis.getRangeMax() - cp) * factor) + cp;
|
||||
xAxis.set(xAxis.getType(), false, false, min, max, xAxis.getRangeDiv() * factor);
|
||||
xAxis.set(xAxis.getType(), false, false, min, max, xAxis.getDivs(), xAxis.getAutoDivs());
|
||||
}
|
||||
if(vertically) {
|
||||
// can only move axis in linear mode
|
||||
|
|
@ -142,7 +142,7 @@ void EyeDiagramPlot::zoom(const QPoint ¢er, double factor, bool horizontally
|
|||
double cp = yAxis.inverseTransform(center.y(), plotAreaBottom, plotAreaTop);
|
||||
double min = ((yAxis.getRangeMin() - cp) * factor) + cp;
|
||||
double max = ((yAxis.getRangeMax() - cp) * factor) + cp;
|
||||
yAxis.set(yAxis.getType(), false, false, min, max, yAxis.getRangeDiv() * factor);
|
||||
yAxis.set(yAxis.getType(), false, false, min, max, yAxis.getDivs(), yAxis.getAutoDivs());
|
||||
}
|
||||
replot();
|
||||
}
|
||||
|
|
@ -150,10 +150,10 @@ void EyeDiagramPlot::zoom(const QPoint ¢er, double factor, bool horizontally
|
|||
void EyeDiagramPlot::setAuto(bool horizontally, bool vertically)
|
||||
{
|
||||
if(horizontally) {
|
||||
xAxis.set(xAxis.getType(), xAxis.getLog(), true, xAxis.getRangeMin(), xAxis.getRangeMax(), xAxis.getRangeDiv());
|
||||
xAxis.set(xAxis.getType(), xAxis.getLog(), true, xAxis.getRangeMin(), xAxis.getRangeMax(), xAxis.getDivs(), xAxis.getAutoDivs());
|
||||
}
|
||||
if(vertically) {
|
||||
yAxis.set(yAxis.getType(), yAxis.getLog(), true, yAxis.getRangeMin(), yAxis.getRangeMax(), yAxis.getRangeDiv());
|
||||
yAxis.set(yAxis.getType(), yAxis.getLog(), true, yAxis.getRangeMin(), yAxis.getRangeMax(), yAxis.getDivs(), yAxis.getAutoDivs());
|
||||
}
|
||||
replot();
|
||||
}
|
||||
|
|
@ -164,15 +164,25 @@ void EyeDiagramPlot::fromJSON(nlohmann::json j)
|
|||
bool xAuto = jX.value("autorange", xAxis.getAutorange());
|
||||
double xMin = jX.value("min", xAxis.getRangeMin());
|
||||
double xMax = jX.value("max", xAxis.getRangeMax());
|
||||
double xDivs = jX.value("div", xAxis.getRangeDiv());
|
||||
xAxis.set(xAxis.getType(), false, xAuto, xMin, xMax, xDivs);
|
||||
double xDivs = jX.value("divs", xAxis.getDivs());
|
||||
// older formats specified the spacing instead of the number of divisions
|
||||
if(jX.contains("div")) {
|
||||
xDivs = (xMax - xMin) / jX.value("div", (xMax - xMin) / xDivs);
|
||||
}
|
||||
auto xautodivs = jX.value("autoDivs", false);
|
||||
xAxis.set(xAxis.getType(), false, xAuto, xMin, xMax, xDivs, xautodivs);
|
||||
|
||||
auto jY = j["YAxis"];
|
||||
bool yAuto = jY.value("autorange", yAxis.getAutorange());
|
||||
double yMin = jY.value("min", yAxis.getRangeMin());
|
||||
double yMax = jY.value("max", yAxis.getRangeMax());
|
||||
double yDivs = jY.value("div", yAxis.getRangeDiv());
|
||||
yAxis.set(yAxis.getType(), false, yAuto, yMin, yMax, yDivs);
|
||||
double yDivs = jY.value("divs", yAxis.getDivs());
|
||||
// older formats specified the spacing instead of the number of divisions
|
||||
if(jY.contains("div")) {
|
||||
yDivs = (yMax - yMin) / jY.value("div", (yMax - yMin) / yDivs);
|
||||
}
|
||||
auto yautodivs = jY.value("autoDivs", false);
|
||||
yAxis.set(yAxis.getType(), false, yAuto, yMin, yMax, yDivs, yautodivs);
|
||||
|
||||
datarate = j.value("datarate", datarate);
|
||||
risetime = j.value("risetime", risetime);
|
||||
|
|
@ -211,13 +221,15 @@ nlohmann::json EyeDiagramPlot::toJSON()
|
|||
jX["autorange"] = yAxis.getAutorange();
|
||||
jX["min"] = xAxis.getRangeMin();
|
||||
jX["max"] = xAxis.getRangeMax();
|
||||
jX["div"] = xAxis.getRangeDiv();
|
||||
jX["divs"] = xAxis.getDivs();
|
||||
jX["autoDivs"] = xAxis.getAutoDivs();
|
||||
j["XAxis"] = jX;
|
||||
nlohmann::json jY;
|
||||
jY["autorange"] = yAxis.getAutorange();
|
||||
jY["min"] = yAxis.getRangeMin();
|
||||
jY["max"] = yAxis.getRangeMax();
|
||||
jY["div"] = yAxis.getRangeDiv();
|
||||
jY["divs"] = yAxis.getDivs();
|
||||
jY["autoDivs"] = yAxis.getAutoDivs();
|
||||
j["YAxis"] = jY;
|
||||
nlohmann::json jtraces;
|
||||
for(auto t : traces) {
|
||||
|
|
@ -286,10 +298,6 @@ void EyeDiagramPlot::axisSetupDialog()
|
|||
ui->Xmax->setPrefixes("pnum ");
|
||||
ui->Xmax->setPrecision(5);
|
||||
|
||||
ui->Xdivs->setUnit("s");
|
||||
ui->Xdivs->setPrefixes("pnum ");
|
||||
ui->Xdivs->setPrecision(3);
|
||||
|
||||
ui->Ymin->setUnit("V");
|
||||
ui->Ymin->setPrefixes("um ");
|
||||
ui->Ymin->setPrecision(4);
|
||||
|
|
@ -298,10 +306,6 @@ void EyeDiagramPlot::axisSetupDialog()
|
|||
ui->Ymax->setPrefixes("um ");
|
||||
ui->Ymax->setPrecision(4);
|
||||
|
||||
ui->Ydivs->setUnit("V");
|
||||
ui->Ydivs->setPrefixes("um ");
|
||||
ui->Ydivs->setPrecision(3);
|
||||
|
||||
// set initial values
|
||||
ui->datarate->setValue(datarate);
|
||||
ui->risetime->setValue(risetime);
|
||||
|
|
@ -322,22 +326,30 @@ void EyeDiagramPlot::axisSetupDialog()
|
|||
connect(ui->Xauto, &QCheckBox::toggled, [=](bool checked) {
|
||||
ui->Xmin->setEnabled(!checked);
|
||||
ui->Xmax->setEnabled(!checked);
|
||||
ui->Xdivs->setEnabled(!checked && !ui->XautoDivs->isChecked());
|
||||
ui->XautoDivs->setEnabled(!checked);
|
||||
});
|
||||
connect(ui->XautoDivs, &QCheckBox::toggled, [=](bool checked) {
|
||||
ui->Xdivs->setEnabled(!checked);
|
||||
});
|
||||
ui->Xauto->setChecked(xAxis.getAutorange());
|
||||
ui->Xmin->setValue(xAxis.getRangeMin());
|
||||
ui->Xmax->setValue(xAxis.getRangeMax());
|
||||
ui->Xdivs->setValue(xAxis.getRangeDiv());
|
||||
ui->Xdivs->setValue(xAxis.getDivs());
|
||||
|
||||
connect(ui->Yauto, &QCheckBox::toggled, [=](bool checked) {
|
||||
ui->Ymin->setEnabled(!checked);
|
||||
ui->Ymax->setEnabled(!checked);
|
||||
ui->Ydivs->setEnabled(!checked && !ui->YautoDivs->isChecked());
|
||||
ui->YautoDivs->setEnabled(!checked);
|
||||
});
|
||||
connect(ui->YautoDivs, &QCheckBox::toggled, [=](bool checked) {
|
||||
ui->Ydivs->setEnabled(!checked);
|
||||
});
|
||||
ui->Yauto->setChecked(yAxis.getAutorange());
|
||||
ui->Ymin->setValue(yAxis.getRangeMin());
|
||||
ui->Ymax->setValue(yAxis.getRangeMax());
|
||||
ui->Ydivs->setValue(yAxis.getRangeDiv());
|
||||
ui->Ydivs->setValue(yAxis.getDivs());
|
||||
|
||||
auto updateValues = [=](){
|
||||
std::lock_guard<std::mutex> guard(calcMutex);
|
||||
|
|
@ -357,8 +369,8 @@ void EyeDiagramPlot::axisSetupDialog()
|
|||
xSamples = ui->pointsPerCycle->value();
|
||||
traceBlurring = ui->traceBlurring->value();
|
||||
|
||||
xAxis.set(xAxis.getType(), false, ui->Xauto->isChecked(), ui->Xmin->value(), ui->Xmax->value(), ui->Xdivs->value());
|
||||
yAxis.set(yAxis.getType(), false, ui->Yauto->isChecked(), ui->Ymin->value(), ui->Ymax->value(), ui->Ydivs->value());
|
||||
xAxis.set(xAxis.getType(), false, ui->Xauto->isChecked(), ui->Xmin->value(), ui->Xmax->value(), ui->Xdivs->value(), ui->XautoDivs->isChecked());
|
||||
yAxis.set(yAxis.getType(), false, ui->Yauto->isChecked(), ui->Ymin->value(), ui->Ymax->value(), ui->Ydivs->value(), ui->YautoDivs->isChecked());
|
||||
};
|
||||
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, [=](){
|
||||
|
|
|
|||
|
|
@ -1572,6 +1572,48 @@ double Trace::getNoise(double frequency)
|
|||
return dbm;
|
||||
}
|
||||
|
||||
double Trace::getGroupDelay(double frequency)
|
||||
{
|
||||
if(!isVNAParameter(liveParam) || lastMath->getDataType() != DataType::Frequency) {
|
||||
// data not suitable for group delay calculation
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
|
||||
// get index that matches frequency best
|
||||
unsigned int sample = index(frequency);
|
||||
|
||||
auto &p = Preferences::getInstance();
|
||||
const unsigned int requiredSamples = p.Acquisition.groupDelaySamples;
|
||||
if(size() < requiredSamples) {
|
||||
// unable to calculate
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
}
|
||||
// needs at least some samples before/after current sample for calculating the derivative.
|
||||
// For samples too far at either end of the trace, return group delay of "inner" trace sample instead
|
||||
if(sample < requiredSamples / 2) {
|
||||
sample = requiredSamples / 2;
|
||||
} else if(sample >= size() - requiredSamples / 2) {
|
||||
sample = size() - requiredSamples / 2 - 1;
|
||||
}
|
||||
|
||||
// got enough samples at either end to calculate derivative.
|
||||
// acquire phases of the required samples
|
||||
std::vector<double> phases;
|
||||
phases.reserve(requiredSamples);
|
||||
for(unsigned int index = sample - requiredSamples / 2;index <= sample + requiredSamples / 2;index++) {
|
||||
phases.push_back(arg(this->sample(index).y));
|
||||
}
|
||||
// make sure there are no phase jumps
|
||||
Util::unwrapPhase(phases);
|
||||
// calculate linearRegression to get derivative
|
||||
double B_0, B_1;
|
||||
Util::linearRegression(phases, B_0, B_1);
|
||||
// B_1 now contains the derived phase vs. the sample. Scale by frequency to get group delay
|
||||
double freq_step = this->sample(sample).x - this->sample(sample - 1).x;
|
||||
return -B_1 / (2.0*M_PI * freq_step);
|
||||
}
|
||||
|
||||
int Trace::index(double x)
|
||||
{
|
||||
auto lower = lower_bound(lastMath->rData().begin(), lastMath->rData().end(), x, [](const Data &lhs, const double x) -> bool {
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ public:
|
|||
unsigned int getFileParameter() const;
|
||||
/* Returns the noise in dbm/Hz for spectrum analyzer measurements. May return NaN if calculation not possible */
|
||||
double getNoise(double frequency);
|
||||
double getGroupDelay(double frequency);
|
||||
int index(double x);
|
||||
std::set<Marker *> getMarkers() const;
|
||||
void setCalibration();
|
||||
|
|
|
|||
|
|
@ -1,23 +1,24 @@
|
|||
#include "traceaxis.h"
|
||||
#include "Util/util.h"
|
||||
#include "preferences.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static void createEvenlySpacedTicks(vector<double>& ticks, double start, double stop, double step) {
|
||||
static void createEvenlySpacedTicks(vector<double>& ticks, double start, double stop, unsigned int divisions) {
|
||||
ticks.clear();
|
||||
if(start > stop) {
|
||||
swap(start, stop);
|
||||
}
|
||||
step = abs(step);
|
||||
auto step = (stop - start) / divisions;
|
||||
constexpr unsigned int maxTicks = 100;
|
||||
for(double tick = start; tick - stop < numeric_limits<double>::epsilon() && ticks.size() <= maxTicks;tick+= step) {
|
||||
ticks.push_back(tick);
|
||||
}
|
||||
}
|
||||
|
||||
static double createAutomaticTicks(vector<double>& ticks, double start, double stop, int minDivisions) {
|
||||
static unsigned int createAutomaticTicks(vector<double>& ticks, double start, double stop, int minDivisions) {
|
||||
Q_ASSERT(stop > start);
|
||||
ticks.clear();
|
||||
double max_div_step = (stop - start) / minDivisions;
|
||||
|
|
@ -37,7 +38,7 @@ static double createAutomaticTicks(vector<double>& ticks, double start, double s
|
|||
for(double tick = start_div;tick <= stop;tick += div_step) {
|
||||
ticks.push_back(tick);
|
||||
}
|
||||
return div_step;
|
||||
return (stop - start) / div_step;
|
||||
}
|
||||
|
||||
static void createLogarithmicTicks(vector<double>& ticks, double start, double stop, int minDivisions) {
|
||||
|
|
@ -132,37 +133,11 @@ double YAxis::sampleToCoordinate(Trace::Data data, Trace *t, unsigned int sample
|
|||
return Util::SparamToInductance(data.y, data.x);
|
||||
case YAxis::Type::QualityFactor:
|
||||
return Util::SparamToQualityFactor(data.y);
|
||||
case YAxis::Type::GroupDelay: {
|
||||
constexpr int requiredSamples = 5;
|
||||
if(!t || t->size() < requiredSamples) {
|
||||
// unable to calculate
|
||||
case YAxis::Type::GroupDelay:
|
||||
if(!t) {
|
||||
return 0.0;
|
||||
|
||||
}
|
||||
// needs at least some samples before/after current sample for calculating the derivative.
|
||||
// For samples too far at either end of the trace, return group delay of "inner" trace sample instead
|
||||
if(sample < requiredSamples / 2) {
|
||||
return sampleToCoordinate(data, t, requiredSamples / 2);
|
||||
} else if(sample >= t->size() - requiredSamples / 2) {
|
||||
return sampleToCoordinate(data, t, t->size() - requiredSamples / 2 - 1);
|
||||
} else {
|
||||
// got enough samples at either end to calculate derivative.
|
||||
// acquire phases of the required samples
|
||||
std::vector<double> phases;
|
||||
phases.reserve(requiredSamples);
|
||||
for(unsigned int index = sample - requiredSamples / 2;index <= sample + requiredSamples / 2;index++) {
|
||||
phases.push_back(arg(t->sample(index).y));
|
||||
}
|
||||
// make sure there are no phase jumps
|
||||
Util::unwrapPhase(phases);
|
||||
// calculate linearRegression to get derivative
|
||||
double B_0, B_1;
|
||||
Util::linearRegression(phases, B_0, B_1);
|
||||
// B_1 now contains the derived phase vs. the sample. Scale by frequency to get group delay
|
||||
double freq_step = t->sample(sample).x - t->sample(sample - 1).x;
|
||||
return -B_1 / (2.0*M_PI * freq_step);
|
||||
}
|
||||
}
|
||||
return t->getGroupDelay(data.x);
|
||||
case YAxis::Type::ImpulseReal:
|
||||
return real(data.y);
|
||||
case YAxis::Type::ImpulseMag:
|
||||
|
|
@ -190,14 +165,15 @@ double YAxis::sampleToCoordinate(Trace::Data data, Trace *t, unsigned int sample
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
void YAxis::set(Type type, bool log, bool autorange, double min, double max, double div)
|
||||
void YAxis::set(Type type, bool log, bool autorange, double min, double max, unsigned int divs, bool autoDivs)
|
||||
{
|
||||
this->type = type;
|
||||
this->log = log;
|
||||
this->autorange = autorange;
|
||||
this->rangeMin = min;
|
||||
this->rangeMax = max;
|
||||
this->rangeDiv = div;
|
||||
this->divs = divs;
|
||||
this->autoDivs = autoDivs;
|
||||
if(type != Type::Disabled) {
|
||||
updateTicks();
|
||||
}
|
||||
|
|
@ -440,9 +416,13 @@ void Axis::updateTicks()
|
|||
rangeMin -= 1.0;
|
||||
rangeMax += 1.0;
|
||||
}
|
||||
rangeDiv = createAutomaticTicks(ticks, rangeMin, rangeMax, 8);
|
||||
divs = createAutomaticTicks(ticks, rangeMin, rangeMax, 8);
|
||||
} else {
|
||||
createEvenlySpacedTicks(ticks, rangeMin, rangeMax, rangeDiv);
|
||||
if(autoDivs) {
|
||||
divs = createAutomaticTicks(ticks, rangeMin, rangeMax, 8);
|
||||
} else {
|
||||
createEvenlySpacedTicks(ticks, rangeMin, rangeMax, divs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -451,9 +431,14 @@ const std::vector<double> &Axis::getTicks() const
|
|||
return ticks;
|
||||
}
|
||||
|
||||
double Axis::getRangeDiv() const
|
||||
unsigned int Axis::getDivs() const
|
||||
{
|
||||
return rangeDiv;
|
||||
return divs;
|
||||
}
|
||||
|
||||
bool Axis::getAutoDivs() const
|
||||
{
|
||||
return autoDivs;
|
||||
}
|
||||
|
||||
double Axis::getRangeMax() const
|
||||
|
|
@ -495,7 +480,7 @@ double XAxis::sampleToCoordinate(Trace::Data data, Trace *t, unsigned int sample
|
|||
}
|
||||
}
|
||||
|
||||
void XAxis::set(Type type, bool log, bool autorange, double min, double max, double div)
|
||||
void XAxis::set(Type type, bool log, bool autorange, double min, double max, unsigned int divs, bool autoDivs)
|
||||
{
|
||||
if(max <= min) {
|
||||
auto info = DeviceDriver::getInfo(DeviceDriver::getActiveDriver());
|
||||
|
|
@ -529,7 +514,8 @@ void XAxis::set(Type type, bool log, bool autorange, double min, double max, dou
|
|||
this->autorange = autorange;
|
||||
this->rangeMin = min;
|
||||
this->rangeMax = max;
|
||||
this->rangeDiv = div;
|
||||
this->divs = divs;
|
||||
this->autoDivs = autoDivs;
|
||||
updateTicks();
|
||||
}
|
||||
|
||||
|
|
@ -589,7 +575,8 @@ Axis::Axis()
|
|||
autorange = true;
|
||||
rangeMin = -1.0;
|
||||
rangeMax = 1.0;
|
||||
rangeDiv = 1.0;
|
||||
divs = 10;
|
||||
autoDivs = false;
|
||||
ticks.clear();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ public:
|
|||
bool getAutorange() const;
|
||||
double getRangeMin() const;
|
||||
double getRangeMax() const;
|
||||
double getRangeDiv() const;
|
||||
unsigned int getDivs() const;
|
||||
bool getAutoDivs() const;
|
||||
const std::vector<double> &getTicks() const;
|
||||
|
||||
protected:
|
||||
|
|
@ -26,7 +27,8 @@ protected:
|
|||
bool autorange;
|
||||
double rangeMin;
|
||||
double rangeMax;
|
||||
double rangeDiv;
|
||||
unsigned int divs;
|
||||
bool autoDivs;
|
||||
std::vector<double> ticks;
|
||||
};
|
||||
|
||||
|
|
@ -42,7 +44,7 @@ public:
|
|||
};
|
||||
XAxis();
|
||||
double sampleToCoordinate(Trace::Data data, Trace *t = nullptr, unsigned int sample = 0) override;
|
||||
void set(Type type, bool log, bool autorange, double min, double max, double div);
|
||||
void set(Type type, bool log, bool autorange, double min, double max, unsigned int divs, bool autoDivs);
|
||||
static QString TypeToName(Type type);
|
||||
static Type TypeFromName(QString name);
|
||||
static QString Unit(Type type);
|
||||
|
|
@ -88,7 +90,7 @@ public:
|
|||
YAxis();
|
||||
double sampleToCoordinate(Trace::Data data, Trace *t = nullptr, unsigned int sample = 0) override;
|
||||
|
||||
void set(Type type, bool log, bool autorange, double min, double max, double div);
|
||||
void set(Type type, bool log, bool autorange, double min, double max, unsigned int divs, bool autoDivs);
|
||||
static QString TypeToName(Type type);
|
||||
static Type TypeFromName(QString name);
|
||||
static QString Unit(Type type, TraceModel::DataSource source = TraceModel::DataSource::VNA);
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ void TraceCSVExport::on_buttonBox_accepted()
|
|||
for(auto trace : traces) {
|
||||
for(auto ytype : getSelectedYAxisTypes()) {
|
||||
auto axis = YAxis();
|
||||
axis.set(ytype, false, false, 0, 1, 1);
|
||||
axis.set(ytype, false, false, 0, 1, 10, false);
|
||||
auto samples = trace->numSamples();
|
||||
vector<double> values;
|
||||
for(unsigned int i=0;i<samples;i++) {
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ TraceWaterfall::TraceWaterfall(TraceModel &model, QWidget *parent)
|
|||
plotAreaWidth = 0;
|
||||
plotAreaBottom = 0;
|
||||
|
||||
xAxis.set(XAxis::Type::Frequency, false, true, 0, 6000000000, 500000000);
|
||||
yAxis.set(YAxis::Type::Magnitude, false, true, -1, 1, 1);
|
||||
xAxis.set(XAxis::Type::Frequency, false, true, 0, 6000000000, 10, false);
|
||||
yAxis.set(YAxis::Type::Magnitude, false, true, -1, 1, 10, false);
|
||||
initializeTraceInfo();
|
||||
}
|
||||
|
||||
|
|
@ -163,11 +163,11 @@ bool TraceWaterfall::configureForTrace(Trace *t)
|
|||
|
||||
switch(t->outputType()) {
|
||||
case Trace::DataType::Frequency:
|
||||
xAxis.set(XAxis::Type::Frequency, false, true, 0, 1, 0.1);
|
||||
xAxis.set(XAxis::Type::Frequency, false, true, 0, 1, 10, false);
|
||||
yDefault = YAxis::Type::Magnitude;
|
||||
break;
|
||||
case Trace::DataType::Power:
|
||||
xAxis.set(XAxis::Type::Power, false, true, 0, 1, 0.1);
|
||||
xAxis.set(XAxis::Type::Power, false, true, 0, 1, 10, false);
|
||||
yDefault = YAxis::Type::Magnitude;
|
||||
break;
|
||||
case Trace::DataType::Time:
|
||||
|
|
@ -177,7 +177,7 @@ bool TraceWaterfall::configureForTrace(Trace *t)
|
|||
return false;
|
||||
}
|
||||
if(!yAxis.isSupported(xAxis.getType(), getModel().getSource())) {
|
||||
yAxis.set(yDefault, false, true, 0, 1, 1.0);
|
||||
yAxis.set(yDefault, false, true, 0, 1, 10, false);
|
||||
}
|
||||
traceRemovalPending = true;
|
||||
return true;
|
||||
|
|
@ -556,7 +556,7 @@ void TraceWaterfall::traceDataChanged(unsigned int begin, unsigned int end)
|
|||
if(min_x != xAxis.getRangeMin() || max_x != xAxis.getRangeMax()) {
|
||||
resetWaterfall();
|
||||
// adjust axis
|
||||
xAxis.set(xAxis.getType(), xAxis.getLog(), true, min_x, max_x, 0);
|
||||
xAxis.set(xAxis.getType(), xAxis.getLog(), true, min_x, max_x, xAxis.getDivs(), xAxis.getAutoDivs());
|
||||
}
|
||||
}
|
||||
bool YAxisUpdateRequired = false;
|
||||
|
|
@ -593,7 +593,7 @@ void TraceWaterfall::traceDataChanged(unsigned int begin, unsigned int end)
|
|||
}
|
||||
if(yAxis.getAutorange() && !YAxisUpdateRequired && (min != yAxis.getRangeMin() || max != yAxis.getRangeMax())) {
|
||||
// axis scaling needs update due to new trace data
|
||||
yAxis.set(yAxis.getType(), yAxis.getLog(), true, min, max, 0);
|
||||
yAxis.set(yAxis.getType(), yAxis.getLog(), true, min, max, yAxis.getDivs(), yAxis.getAutoDivs());
|
||||
} else if(YAxisUpdateRequired) {
|
||||
updateYAxis();
|
||||
}
|
||||
|
|
@ -619,7 +619,7 @@ void TraceWaterfall::updateYAxis()
|
|||
}
|
||||
}
|
||||
if(max > min) {
|
||||
yAxis.set(yAxis.getType(), yAxis.getLog(), true, min, max, 0);
|
||||
yAxis.set(yAxis.getType(), yAxis.getLog(), true, min, max, yAxis.getDivs(), yAxis.getAutoDivs());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@ TraceXYPlot::TraceXYPlot(TraceModel &model, QWidget *parent)
|
|||
xAxisMode = XAxisMode::UseSpan;
|
||||
|
||||
// Setup default axis
|
||||
setYAxis(0, YAxis::Type::Magnitude, false, false, -120, 20, 10);
|
||||
setYAxis(1, YAxis::Type::Phase, false, false, -180, 180, 30);
|
||||
setYAxis(0, YAxis::Type::Magnitude, false, false, -120, 20, 14, true);
|
||||
setYAxis(1, YAxis::Type::Phase, false, false, -180, 180, 12, true);
|
||||
// enable autoscaling and set for full span (no information about actual span available yet)
|
||||
updateSpan(0, 6000000000);
|
||||
setXAxis(XAxis::Type::Frequency, XAxisMode::UseSpan, false, 0, 6000000000, 600000000);
|
||||
setXAxis(XAxis::Type::Frequency, XAxisMode::UseSpan, false, 0, 6000000000, 10, true);
|
||||
initializeTraceInfo();
|
||||
}
|
||||
TraceXYPlot::~TraceXYPlot()
|
||||
|
|
@ -39,7 +39,7 @@ TraceXYPlot::~TraceXYPlot()
|
|||
}
|
||||
}
|
||||
|
||||
void TraceXYPlot::setYAxis(int axis, YAxis::Type type, bool log, bool autorange, double min, double max, double div)
|
||||
void TraceXYPlot::setYAxis(int axis, YAxis::Type type, bool log, bool autorange, double min, double max, unsigned int divs, bool autoDivs)
|
||||
{
|
||||
if(yAxis[axis].getType() != type) {
|
||||
// remove traces that are active but not supported with the new axis type
|
||||
|
|
@ -55,19 +55,19 @@ void TraceXYPlot::setYAxis(int axis, YAxis::Type type, bool log, bool autorange,
|
|||
}
|
||||
} while(erased);
|
||||
}
|
||||
yAxis[axis].set(type, log, autorange, min, max, div);
|
||||
yAxis[axis].set(type, log, autorange, min, max, divs, autoDivs);
|
||||
traceRemovalPending = true;
|
||||
updateContextMenu();
|
||||
replot();
|
||||
}
|
||||
|
||||
void TraceXYPlot::setXAxis(XAxis::Type type, XAxisMode mode, bool log, double min, double max, double div)
|
||||
void TraceXYPlot::setXAxis(XAxis::Type type, XAxisMode mode, bool log, double min, double max, unsigned int divs, bool autoDivs)
|
||||
{
|
||||
bool autorange = false;
|
||||
if(mode == XAxisMode::FitTraces || mode == XAxisMode::UseSpan) {
|
||||
autorange = true;
|
||||
}
|
||||
xAxis.set(type, log, autorange, min, max, div);
|
||||
xAxis.set(type, log, autorange, min, max, divs, autoDivs);
|
||||
xAxisMode = mode;
|
||||
traceRemovalPending = true;
|
||||
updateContextMenu();
|
||||
|
|
@ -101,7 +101,7 @@ void TraceXYPlot::move(const QPoint &vect)
|
|||
// can only move axis in linear mode
|
||||
// calculate amount of movement
|
||||
double distance = xAxis.inverseTransform(vect.x(), 0, plotAreaWidth) - xAxis.getRangeMin();
|
||||
xAxis.set(xAxis.getType(), false, false, xAxis.getRangeMin() - distance, xAxis.getRangeMax() - distance, xAxis.getRangeDiv());
|
||||
xAxis.set(xAxis.getType(), false, false, xAxis.getRangeMin() - distance, xAxis.getRangeMax() - distance, xAxis.getDivs(), xAxis.getAutoDivs());
|
||||
xAxisMode = XAxisMode::Manual;
|
||||
}
|
||||
for(int i=0;i<2;i++) {
|
||||
|
|
@ -109,7 +109,7 @@ void TraceXYPlot::move(const QPoint &vect)
|
|||
// can only move axis in linear mode
|
||||
// calculate amount of movement
|
||||
double distance = yAxis[i].inverseTransform(vect.y(), 0, plotAreaTop - plotAreaBottom) - yAxis[i].getRangeMin();
|
||||
yAxis[i].set(yAxis[i].getType(), false, false, yAxis[i].getRangeMin() - distance, yAxis[i].getRangeMax() - distance, yAxis[i].getRangeDiv());
|
||||
yAxis[i].set(yAxis[i].getType(), false, false, yAxis[i].getRangeMin() - distance, yAxis[i].getRangeMax() - distance, yAxis[i].getDivs(), yAxis[i].getAutoDivs());
|
||||
}
|
||||
}
|
||||
replot();
|
||||
|
|
@ -123,7 +123,7 @@ void TraceXYPlot::zoom(const QPoint ¢er, double factor, bool horizontally, b
|
|||
double cp = xAxis.inverseTransform(center.x(), plotAreaLeft, plotAreaLeft + plotAreaWidth);
|
||||
double min = ((xAxis.getRangeMin() - cp) * factor) + cp;
|
||||
double max = ((xAxis.getRangeMax() - cp) * factor) + cp;
|
||||
xAxis.set(xAxis.getType(), false, false, min, max, xAxis.getRangeDiv() * factor);
|
||||
xAxis.set(xAxis.getType(), false, false, min, max, xAxis.getDivs(), xAxis.getAutoDivs());
|
||||
xAxisMode = XAxisMode::Manual;
|
||||
}
|
||||
for(int i=0;i<2;i++) {
|
||||
|
|
@ -133,7 +133,7 @@ void TraceXYPlot::zoom(const QPoint ¢er, double factor, bool horizontally, b
|
|||
double cp = yAxis[i].inverseTransform(center.y(), plotAreaBottom, plotAreaTop);
|
||||
double min = ((yAxis[i].getRangeMin() - cp) * factor) + cp;
|
||||
double max = ((yAxis[i].getRangeMax() - cp) * factor) + cp;
|
||||
yAxis[i].set(yAxis[i].getType(), false, false, min, max, yAxis[i].getRangeDiv() * factor);
|
||||
yAxis[i].set(yAxis[i].getType(), false, false, min, max, yAxis[i].getDivs(), yAxis[i].getAutoDivs());
|
||||
}
|
||||
}
|
||||
replot();
|
||||
|
|
@ -143,11 +143,11 @@ void TraceXYPlot::setAuto(bool horizontally, bool vertically)
|
|||
{
|
||||
if(horizontally) {
|
||||
xAxisMode = XAxisMode::FitTraces;
|
||||
xAxis.set(xAxis.getType(), xAxis.getLog(), true, xAxis.getRangeMin(), xAxis.getRangeMax(), xAxis.getRangeDiv());
|
||||
xAxis.set(xAxis.getType(), xAxis.getLog(), true, xAxis.getRangeMin(), xAxis.getRangeMax(), xAxis.getDivs(), xAxis.getAutoDivs());
|
||||
}
|
||||
for(int i=0;i<2;i++) {
|
||||
if(vertically && yAxis[i].getType() != YAxis::Type::Disabled) {
|
||||
yAxis[i].set(yAxis[i].getType(), yAxis[i].getLog(), true, yAxis[i].getRangeMin(), yAxis[i].getRangeMax(), yAxis[i].getRangeDiv());
|
||||
yAxis[i].set(yAxis[i].getType(), yAxis[i].getLog(), true, yAxis[i].getRangeMin(), yAxis[i].getRangeMax(), yAxis[i].getDivs(), yAxis[i].getAutoDivs());
|
||||
}
|
||||
}
|
||||
replot();
|
||||
|
|
@ -162,7 +162,8 @@ nlohmann::json TraceXYPlot::toJSON()
|
|||
jX["log"] = xAxis.getLog();
|
||||
jX["min"] = xAxis.getRangeMin();
|
||||
jX["max"] = xAxis.getRangeMax();
|
||||
jX["div"] = xAxis.getRangeDiv();
|
||||
jX["divs"] = xAxis.getDivs();
|
||||
jX["autoDivs"] = xAxis.getAutoDivs();
|
||||
j["XAxis"] = jX;
|
||||
for(unsigned int i=0;i<2;i++) {
|
||||
nlohmann::json jY;
|
||||
|
|
@ -171,7 +172,8 @@ nlohmann::json TraceXYPlot::toJSON()
|
|||
jY["autorange"] = yAxis[i].getAutorange();
|
||||
jY["min"] = yAxis[i].getRangeMin();
|
||||
jY["max"] = yAxis[i].getRangeMax();
|
||||
jY["div"] = yAxis[i].getRangeDiv();
|
||||
jY["divs"] = yAxis[i].getDivs();
|
||||
jY["autoDivs"] = yAxis[i].getAutoDivs();
|
||||
nlohmann::json jtraces;
|
||||
for(auto t : tracesAxis[i]) {
|
||||
jtraces.push_back(t->toHash());
|
||||
|
|
@ -212,9 +214,14 @@ void TraceXYPlot::fromJSON(nlohmann::json j)
|
|||
// auto xlog = jX.value("log", false);
|
||||
auto xmin = jX.value("min", 0.0);
|
||||
auto xmax = jX.value("max", 6000000000.0);
|
||||
auto xdiv = jX.value("div", 600000000.0);
|
||||
auto xdivs = jX.value("divs", 10);
|
||||
// older formats specified the spacing instead of the number of divisions
|
||||
if(jX.contains("div")) {
|
||||
xdivs = (xmax - xmin) / jX.value("div", 600000000.0);
|
||||
}
|
||||
auto xautodivs = jX.value("autoDivs", false);
|
||||
auto xlog = jX.value("log", false);
|
||||
setXAxis(xtype, xmode, xlog, xmin, xmax, xdiv);
|
||||
setXAxis(xtype, xmode, xlog, xmin, xmax, xdivs, xautodivs);
|
||||
nlohmann::json jY[2] = {j["YPrimary"], j["YSecondary"]};
|
||||
for(unsigned int i=0;i<2;i++) {
|
||||
YAxis::Type ytype;
|
||||
|
|
@ -227,8 +234,13 @@ void TraceXYPlot::fromJSON(nlohmann::json j)
|
|||
auto ylog = jY[i].value("log", false);
|
||||
auto ymin = jY[i].value("min", -120.0);
|
||||
auto ymax = jY[i].value("max", 20.0);
|
||||
auto ydiv = jY[i].value("div", 10.0);
|
||||
setYAxis(i, ytype, ylog, yauto, ymin, ymax, ydiv);
|
||||
auto ydivs = jY[i].value("divs", 10);
|
||||
// older formats specified the spacing instead of the number of divisions
|
||||
if(jY[i].contains("div")) {
|
||||
ydivs = (ymax - ymin) / jY[i].value("div", 10);
|
||||
}
|
||||
auto yautodivs = jY[i].value("autoDivs", false);
|
||||
setYAxis(i, ytype, ylog, yauto, ymin, ymax, ydivs, yautodivs);
|
||||
for(unsigned int hash : jY[i]["traces"]) {
|
||||
// attempt to find the traces with this hash
|
||||
bool found = false;
|
||||
|
|
@ -292,21 +304,21 @@ bool TraceXYPlot::configureForTrace(Trace *t)
|
|||
|
||||
switch(t->outputType()) {
|
||||
case Trace::DataType::Frequency:
|
||||
setXAxis(XAxis::Type::Frequency, XAxisMode::FitTraces, false, 0, 1, 0.1);
|
||||
setXAxis(XAxis::Type::Frequency, XAxisMode::FitTraces, false, 0, 1, 10, false);
|
||||
yLeftDefault = YAxis::Type::Magnitude;
|
||||
yRightDefault = YAxis::Type::Phase;
|
||||
break;
|
||||
case Trace::DataType::Time:
|
||||
setXAxis(XAxis::Type::Time, XAxisMode::FitTraces, false, 0, 1, 0.1);
|
||||
setXAxis(XAxis::Type::Time, XAxisMode::FitTraces, false, 0, 1, 10, false);
|
||||
yLeftDefault = YAxis::Type::ImpulseMag;
|
||||
break;
|
||||
case Trace::DataType::Power:
|
||||
setXAxis(XAxis::Type::Power, XAxisMode::FitTraces, false, 0, 1, 0.1);
|
||||
setXAxis(XAxis::Type::Power, XAxisMode::FitTraces, false, 0, 1, 10, false);
|
||||
yLeftDefault = YAxis::Type::Magnitude;
|
||||
yRightDefault = YAxis::Type::Phase;
|
||||
break;
|
||||
case Trace::DataType::TimeZeroSpan:
|
||||
setXAxis(XAxis::Type::TimeZeroSpan, XAxisMode::FitTraces, false, 0, 1, 0.1);
|
||||
setXAxis(XAxis::Type::TimeZeroSpan, XAxisMode::FitTraces, false, 0, 1, 10, false);
|
||||
yLeftDefault = YAxis::Type::Magnitude;
|
||||
yRightDefault = YAxis::Type::Phase;
|
||||
break;
|
||||
|
|
@ -315,10 +327,10 @@ bool TraceXYPlot::configureForTrace(Trace *t)
|
|||
return false;
|
||||
}
|
||||
if(!yAxis[0].isSupported(xAxis.getType(), getModel().getSource())) {
|
||||
setYAxis(0, yLeftDefault, false, true, 0, 1, 1.0);
|
||||
setYAxis(0, yLeftDefault, false, true, 0, 1, 10, false);
|
||||
}
|
||||
if(!yAxis[1].isSupported(xAxis.getType(), getModel().getSource())) {
|
||||
setYAxis(1, yRightDefault, false, true, 0, 1, 1.0);
|
||||
setYAxis(1, yRightDefault, false, true, 0, 1, 10, false);
|
||||
}
|
||||
traceRemovalPending = true;
|
||||
return true;
|
||||
|
|
@ -899,7 +911,7 @@ void TraceXYPlot::updateAxisTicks()
|
|||
}
|
||||
}
|
||||
}
|
||||
xAxis.set(xAxis.getType(), xAxis.getLog(), true, min, max, 0);
|
||||
xAxis.set(xAxis.getType(), xAxis.getLog(), true, min, max, 0, xAxis.getAutoDivs());
|
||||
}
|
||||
|
||||
for(int i=0;i<2;i++) {
|
||||
|
|
@ -981,7 +993,7 @@ void TraceXYPlot::updateAxisTicks()
|
|||
min = 0.1;
|
||||
}
|
||||
}
|
||||
yAxis[i].set(yAxis[i].getType(), yAxis[i].getLog(), true, min, max, 0);
|
||||
yAxis[i].set(yAxis[i].getType(), yAxis[i].getLog(), true, min, max, 0, xAxis.getAutoDivs());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ public:
|
|||
Last,
|
||||
};
|
||||
|
||||
void setYAxis(int axis, YAxis::Type type, bool log, bool autorange, double min, double max, double div);
|
||||
void setXAxis(XAxis::Type type, XAxisMode mode, bool log, double min, double max, double div);
|
||||
void setYAxis(int axis, YAxis::Type type, bool log, bool autorange, double min, double max, unsigned int divs, bool autoDivs);
|
||||
void setXAxis(XAxis::Type type, XAxisMode mode, bool log, double min, double max, unsigned int divs, bool autoDivs);
|
||||
void enableTrace(Trace *t, bool enabled) override;
|
||||
void updateSpan(double min, double max) override;
|
||||
void replot() override;
|
||||
|
|
|
|||
|
|
@ -115,8 +115,8 @@ WaterfallAxisDialog::~WaterfallAxisDialog()
|
|||
void WaterfallAxisDialog::on_buttonBox_accepted()
|
||||
{
|
||||
// set plot values to the ones selected in the dialog
|
||||
plot->xAxis.set(plot->xAxis.getType(), ui->Xlog->isChecked(), true, plot->xAxis.getRangeMin(), plot->xAxis.getRangeMax(), 0);
|
||||
plot->yAxis.set((YAxis::Type) ui->Wtype->currentIndex(), ui->Wlog->isChecked(), ui->Wauto->isChecked(), ui->Wmin->value(), ui->Wmax->value(), 2);
|
||||
plot->xAxis.set(plot->xAxis.getType(), ui->Xlog->isChecked(), true, plot->xAxis.getRangeMin(), plot->xAxis.getRangeMax(), 10, false);
|
||||
plot->yAxis.set((YAxis::Type) ui->Wtype->currentIndex(), ui->Wlog->isChecked(), ui->Wauto->isChecked(), ui->Wmin->value(), ui->Wmax->value(), 2, false);
|
||||
if(ui->Wdir->currentIndex() == 0) {
|
||||
plot->dir = TraceWaterfall::Direction::TopToBottom;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -49,85 +49,114 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
}
|
||||
|
||||
// Setup GUI connections
|
||||
connect(ui->Y1type, qOverload<int>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||
ui->Y1log->setEnabled(index != 0);
|
||||
ui->Y1linear->setEnabled(index != 0);
|
||||
ui->Y1auto->setEnabled(index != 0);
|
||||
bool autoRange = ui->Y1auto->isChecked();
|
||||
ui->Y1min->setEnabled(index != 0 && !autoRange);
|
||||
ui->Y1max->setEnabled(index != 0 && !autoRange);
|
||||
ui->Y1divs->setEnabled(index != 0 && !autoRange);
|
||||
auto type = (YAxis::Type) index;
|
||||
QString unit = YAxis::Unit(type);
|
||||
QString prefixes = YAxis::Prefixes(type);
|
||||
ui->Y1min->setUnit(unit);
|
||||
ui->Y1min->setPrefixes(prefixes);
|
||||
ui->Y1max->setUnit(unit);
|
||||
ui->Y1max->setPrefixes(prefixes);
|
||||
ui->Y1divs->setUnit(unit);
|
||||
ui->Y1divs->setPrefixes(prefixes);
|
||||
auto updateYenableState = [](QComboBox *type, QRadioButton *linear, QRadioButton *log, QCheckBox *CBauto, SIUnitEdit *min, SIUnitEdit *max, QSpinBox *divs, QCheckBox *autoDivs) {
|
||||
if(type->currentIndex() == 0) {
|
||||
// axis disabled
|
||||
log->setEnabled(false);
|
||||
linear->setEnabled(false);
|
||||
CBauto->setEnabled(false);
|
||||
} else {
|
||||
// axis enabled
|
||||
log->setEnabled(true);
|
||||
linear->setEnabled(true);
|
||||
CBauto->setEnabled(true);
|
||||
if(CBauto->isChecked()) {
|
||||
// autorange active, other settings disabled
|
||||
min->setEnabled(false);
|
||||
max->setEnabled(false);
|
||||
divs->setEnabled(false);
|
||||
autoDivs->setEnabled(false);
|
||||
} else {
|
||||
min->setEnabled(true);
|
||||
max->setEnabled(true);
|
||||
if(log->isChecked()) {
|
||||
divs->setEnabled(false);
|
||||
autoDivs->setEnabled(false);
|
||||
} else {
|
||||
autoDivs->setEnabled(true);
|
||||
divs->setEnabled(!autoDivs->isChecked());
|
||||
}
|
||||
}
|
||||
}
|
||||
auto t = (YAxis::Type) type->currentIndex();
|
||||
QString unit = YAxis::Unit(t);
|
||||
QString prefixes = YAxis::Prefixes(t);
|
||||
min->setUnit(unit);
|
||||
min->setPrefixes(prefixes);
|
||||
max->setUnit(unit);
|
||||
max->setPrefixes(prefixes);
|
||||
};
|
||||
|
||||
connect(ui->Y1type, qOverload<int>(&QComboBox::currentIndexChanged), [this, updateYenableState](int) {
|
||||
updateYenableState(ui->Y1type, ui->Y1linear, ui->Y1log, ui->Y1auto, ui->Y1min, ui->Y1max, ui->Y1Divs, ui->Y1autoDivs);
|
||||
});
|
||||
connect(ui->Y1auto, &QCheckBox::toggled, [this](bool checked) {
|
||||
ui->Y1min->setEnabled(!checked);
|
||||
ui->Y1max->setEnabled(!checked);
|
||||
ui->Y1divs->setEnabled(!checked && !ui->Y1log->isChecked());
|
||||
connect(ui->Y1auto, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y1type, ui->Y1linear, ui->Y1log, ui->Y1auto, ui->Y1min, ui->Y1max, ui->Y1Divs, ui->Y1autoDivs);
|
||||
});
|
||||
connect(ui->Y1log, &QCheckBox::toggled, [this](bool checked) {
|
||||
ui->Y1divs->setEnabled(!checked && !ui->Y1auto->isChecked());
|
||||
connect(ui->Y1log, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y1type, ui->Y1linear, ui->Y1log, ui->Y1auto, ui->Y1min, ui->Y1max, ui->Y1Divs, ui->Y1autoDivs);
|
||||
});
|
||||
connect(ui->Y1autoDivs, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y1type, ui->Y1linear, ui->Y1log, ui->Y1auto, ui->Y1min, ui->Y1max, ui->Y1Divs, ui->Y1autoDivs);
|
||||
});
|
||||
|
||||
connect(ui->Y2type, qOverload<int>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||
ui->Y2log->setEnabled(index != 0);
|
||||
ui->Y2linear->setEnabled(index != 0);
|
||||
ui->Y2auto->setEnabled(index != 0);
|
||||
bool autoRange = ui->Y2auto->isChecked();
|
||||
ui->Y2min->setEnabled(index != 0 && !autoRange);
|
||||
ui->Y2max->setEnabled(index != 0 && !autoRange);
|
||||
ui->Y2divs->setEnabled(index != 0 && !autoRange);
|
||||
auto type = (YAxis::Type) index;
|
||||
QString unit = YAxis::Unit(type);
|
||||
QString prefixes = YAxis::Prefixes(type);
|
||||
ui->Y2min->setUnit(unit);
|
||||
ui->Y2min->setPrefixes(prefixes);
|
||||
ui->Y2max->setUnit(unit);
|
||||
ui->Y2max->setPrefixes(prefixes);
|
||||
ui->Y2divs->setUnit(unit);
|
||||
ui->Y2divs->setPrefixes(prefixes);
|
||||
connect(ui->Y2type, qOverload<int>(&QComboBox::currentIndexChanged), [this, updateYenableState](int) {
|
||||
updateYenableState(ui->Y2type, ui->Y2linear, ui->Y2log, ui->Y2auto, ui->Y2min, ui->Y2max, ui->Y2Divs, ui->Y2autoDivs);
|
||||
});
|
||||
connect(ui->Y2auto, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y2type, ui->Y2linear, ui->Y2log, ui->Y2auto, ui->Y2min, ui->Y2max, ui->Y2Divs, ui->Y2autoDivs);
|
||||
});
|
||||
connect(ui->Y2log, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y2type, ui->Y2linear, ui->Y2log, ui->Y2auto, ui->Y2min, ui->Y2max, ui->Y2Divs, ui->Y2autoDivs);
|
||||
});
|
||||
connect(ui->Y2autoDivs, &QCheckBox::toggled, [this, updateYenableState](bool) {
|
||||
updateYenableState(ui->Y2type, ui->Y2linear, ui->Y2log, ui->Y2auto, ui->Y2min, ui->Y2max, ui->Y2Divs, ui->Y2autoDivs);
|
||||
});
|
||||
|
||||
connect(ui->Y2auto, &QCheckBox::toggled, [this](bool checked) {
|
||||
ui->Y2min->setEnabled(!checked);
|
||||
ui->Y2max->setEnabled(!checked);
|
||||
ui->Y2divs->setEnabled(!checked && !ui->Y1log->isChecked());
|
||||
});
|
||||
connect(ui->Y2log, &QCheckBox::toggled, [this](bool checked) {
|
||||
ui->Y2divs->setEnabled(!checked && !ui->Y2auto->isChecked());
|
||||
});
|
||||
auto updateXenableState = [](QRadioButton *linear, QRadioButton *log, QCheckBox *CBauto, SIUnitEdit *min, SIUnitEdit *max, QSpinBox *divs, QCheckBox *autoDivs) {
|
||||
log->setEnabled(true);
|
||||
linear->setEnabled(true);
|
||||
CBauto->setEnabled(true);
|
||||
if(CBauto->isChecked()) {
|
||||
// autorange active, other settings disabled
|
||||
min->setEnabled(false);
|
||||
max->setEnabled(false);
|
||||
divs->setEnabled(false);
|
||||
autoDivs->setEnabled(false);
|
||||
} else {
|
||||
min->setEnabled(true);
|
||||
max->setEnabled(true);
|
||||
if(log->isChecked()) {
|
||||
divs->setEnabled(false);
|
||||
autoDivs->setEnabled(false);
|
||||
} else {
|
||||
autoDivs->setEnabled(true);
|
||||
divs->setEnabled(!autoDivs->isChecked());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
connect(ui->Xauto, &QCheckBox::toggled, [this](bool checked) {
|
||||
ui->Xmin->setEnabled(!checked);
|
||||
ui->Xmax->setEnabled(!checked);
|
||||
ui->Xdivs->setEnabled(!checked && ui->Xlinear->isChecked());
|
||||
ui->Xautomode->setEnabled(checked);
|
||||
connect(ui->Xauto, &QCheckBox::toggled, [this, updateXenableState](bool checked) {
|
||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
||||
});
|
||||
connect(ui->XautoDivs, &QCheckBox::toggled, [this, updateXenableState](bool checked) {
|
||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
||||
});
|
||||
|
||||
ui->XType->setCurrentIndex((int) plot->xAxis.getType());
|
||||
ui->Xmin->setPrefixes("pnum kMG");
|
||||
ui->Xmax->setPrefixes("pnum kMG");
|
||||
ui->Xdivs->setPrefixes("pnum kMG");
|
||||
|
||||
ui->Y1min->setPrefixes("pnum kMG");
|
||||
ui->Y1max->setPrefixes("pnum kMG");
|
||||
ui->Y1divs->setPrefixes("pnum kMG");
|
||||
|
||||
ui->Y2min->setPrefixes("pnum kMG");
|
||||
ui->Y2max->setPrefixes("pnum kMG");
|
||||
ui->Y2divs->setPrefixes("pnum kMG");
|
||||
|
||||
XAxisTypeChanged((int) plot->xAxis.getType());
|
||||
connect(ui->XType, qOverload<int>(&QComboBox::currentIndexChanged), this, &XYplotAxisDialog::XAxisTypeChanged);
|
||||
connect(ui->Xlog, &QCheckBox::toggled, [=](bool checked){
|
||||
ui->Xdivs->setEnabled(!checked && !ui->Xauto->isChecked());
|
||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
||||
});
|
||||
|
||||
// Fill initial values
|
||||
|
|
@ -140,7 +169,8 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
ui->Y1auto->setChecked(plot->yAxis[0].getAutorange());
|
||||
ui->Y1min->setValueQuiet(plot->yAxis[0].getRangeMin());
|
||||
ui->Y1max->setValueQuiet(plot->yAxis[0].getRangeMax());
|
||||
ui->Y1divs->setValueQuiet(plot->yAxis[0].getRangeDiv());
|
||||
ui->Y1Divs->setValue(plot->yAxis[0].getDivs());
|
||||
ui->Y1autoDivs->setChecked(plot->yAxis[0].getAutoDivs());
|
||||
|
||||
ui->Y2type->setCurrentIndex((int) plot->yAxis[1].getType());
|
||||
if(plot->yAxis[1].getLog()) {
|
||||
|
|
@ -151,7 +181,8 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
ui->Y2auto->setChecked(plot->yAxis[1].getAutorange());
|
||||
ui->Y2min->setValueQuiet(plot->yAxis[1].getRangeMin());
|
||||
ui->Y2max->setValueQuiet(plot->yAxis[1].getRangeMax());
|
||||
ui->Y2divs->setValueQuiet(plot->yAxis[1].getRangeDiv());
|
||||
ui->Y2Divs->setValue(plot->yAxis[1].getDivs());
|
||||
ui->Y2autoDivs->setChecked(plot->yAxis[1].getAutoDivs());
|
||||
|
||||
if(plot->xAxis.getLog()) {
|
||||
ui->Xlog->setChecked(true);
|
||||
|
|
@ -166,7 +197,8 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
}
|
||||
ui->Xmin->setValueQuiet(plot->xAxis.getRangeMin());
|
||||
ui->Xmax->setValueQuiet(plot->xAxis.getRangeMax());
|
||||
ui->Xdivs->setValueQuiet(plot->xAxis.getRangeDiv());
|
||||
ui->XDivs->setValue(plot->xAxis.getDivs());
|
||||
ui->XautoDivs->setChecked(plot->xAxis.getAutoDivs());
|
||||
|
||||
// Constant line list handling
|
||||
auto editLine = [&](XYPlotConstantLine *line) {
|
||||
|
|
@ -277,8 +309,8 @@ XYplotAxisDialog::~XYplotAxisDialog()
|
|||
void XYplotAxisDialog::on_buttonBox_accepted()
|
||||
{
|
||||
// set plot values to the ones selected in the dialog
|
||||
plot->setYAxis(0, (YAxis::Type) ui->Y1type->currentIndex(), ui->Y1log->isChecked(), ui->Y1auto->isChecked(), ui->Y1min->value(), ui->Y1max->value(), ui->Y1divs->value());
|
||||
plot->setYAxis(1, (YAxis::Type) ui->Y2type->currentIndex(), ui->Y2log->isChecked(), ui->Y2auto->isChecked(), ui->Y2min->value(), ui->Y2max->value(), ui->Y2divs->value());
|
||||
plot->setYAxis(0, (YAxis::Type) ui->Y1type->currentIndex(), ui->Y1log->isChecked(), ui->Y1auto->isChecked(), ui->Y1min->value(), ui->Y1max->value(), ui->Y1Divs->value(), ui->Y1autoDivs->isChecked());
|
||||
plot->setYAxis(1, (YAxis::Type) ui->Y2type->currentIndex(), ui->Y2log->isChecked(), ui->Y2auto->isChecked(), ui->Y2min->value(), ui->Y2max->value(), ui->Y2Divs->value(), ui->Y2autoDivs->isChecked());
|
||||
TraceXYPlot::XAxisMode mode;
|
||||
if(ui->Xauto->isChecked()) {
|
||||
if(ui->Xautomode->currentIndex() == 0) {
|
||||
|
|
@ -289,7 +321,7 @@ void XYplotAxisDialog::on_buttonBox_accepted()
|
|||
} else {
|
||||
mode = TraceXYPlot::XAxisMode::Manual;
|
||||
}
|
||||
plot->setXAxis((XAxis::Type) ui->XType->currentIndex(), mode, ui->Xlog->isChecked(), ui->Xmin->value(), ui->Xmax->value(), ui->Xdivs->value());
|
||||
plot->setXAxis((XAxis::Type) ui->XType->currentIndex(), mode, ui->Xlog->isChecked(), ui->Xmin->value(), ui->Xmax->value(), ui->XDivs->value(), ui->XautoDivs->isChecked());
|
||||
}
|
||||
|
||||
void XYplotAxisDialog::XAxisTypeChanged(int XAxisIndex)
|
||||
|
|
@ -330,7 +362,6 @@ void XYplotAxisDialog::XAxisTypeChanged(int XAxisIndex)
|
|||
QString unit = XAxis::Unit(type);
|
||||
ui->Xmin->setUnit(unit);
|
||||
ui->Xmax->setUnit(unit);
|
||||
ui->Xdivs->setUnit(unit);
|
||||
}
|
||||
|
||||
std::set<YAxis::Type> XYplotAxisDialog::supportedYAxis(XAxis::Type type)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>814</width>
|
||||
<height>458</height>
|
||||
<width>810</width>
|
||||
<height>461</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -21,9 +21,9 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
|
|
@ -133,12 +133,27 @@
|
|||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Divisions:</string>
|
||||
<string># Divisions:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="SIUnitEdit" name="Y1divs"/>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="Y1Divs">
|
||||
<property name="minimum">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="Y1autoDivs">
|
||||
<property name="text">
|
||||
<string>Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
|
@ -262,12 +277,27 @@
|
|||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Divisions:</string>
|
||||
<string># Divisions:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="SIUnitEdit" name="Y2divs"/>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="Y2Divs">
|
||||
<property name="minimum">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="Y2autoDivs">
|
||||
<property name="text">
|
||||
<string>Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
|
@ -281,7 +311,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -418,12 +448,27 @@
|
|||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Divisions:</string>
|
||||
<string># Divisions:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="SIUnitEdit" name="Xdivs"/>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="XDivs">
|
||||
<property name="minimum">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="XautoDivs">
|
||||
<property name="text">
|
||||
<string>Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
|
@ -592,8 +637,8 @@
|
|||
</connection>
|
||||
</connections>
|
||||
<buttongroups>
|
||||
<buttongroup name="Y1group"/>
|
||||
<buttongroup name="Xgroup"/>
|
||||
<buttongroup name="Y2group"/>
|
||||
<buttongroup name="Y1group"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
|
|
|||
|
|
@ -262,6 +262,7 @@ void PreferencesDialog::setInitialGUIState()
|
|||
ui->AcquisitionFullSpanCalibrated->setChecked(p->Acquisition.fullSpanCalibratedRange);
|
||||
ui->AcquisitionLimitTDRCheckbox->setChecked(p->Acquisition.limitDFT);
|
||||
ui->AcquisitionDFTLimitValue->setValue(p->Acquisition.maxDFTrate);
|
||||
ui->AcquisitionGroupDelaySamples->setValue(p->Acquisition.groupDelaySamples);
|
||||
|
||||
ui->GraphsDefaultTransmission->setCurrentText(p->Graphs.defaultGraphs.transmission);
|
||||
ui->GraphsDefaultReflection->setCurrentText(p->Graphs.defaultGraphs.reflection);
|
||||
|
|
@ -299,6 +300,7 @@ void PreferencesDialog::setInitialGUIState()
|
|||
ui->MarkerShowCapacitance->setChecked(p->Marker.defaultBehavior.showCapacitance);
|
||||
ui->MarkerShowInductance->setChecked(p->Marker.defaultBehavior.showInductance);
|
||||
ui->MarkerShowQualityFactor->setChecked(p->Marker.defaultBehavior.showQualityFactor);
|
||||
ui->MarkerShowGroupDelay->setChecked(p->Marker.defaultBehavior.showGroupDelay);
|
||||
ui->MarkerShowNoise->setChecked(p->Marker.defaultBehavior.showNoise);
|
||||
ui->MarkerShowPhasenoise->setChecked(p->Marker.defaultBehavior.showPhasenoise);
|
||||
ui->MarkerShowCenterBandwidth->setChecked(p->Marker.defaultBehavior.showCenterBandwidth);
|
||||
|
|
@ -361,6 +363,7 @@ void PreferencesDialog::updateFromGUI()
|
|||
p->Acquisition.fullSpanCalibratedRange = ui->AcquisitionFullSpanCalibrated->isChecked();
|
||||
p->Acquisition.limitDFT = ui->AcquisitionLimitTDRCheckbox->isChecked();
|
||||
p->Acquisition.maxDFTrate = ui->AcquisitionDFTLimitValue->value();
|
||||
p->Acquisition.groupDelaySamples = ui->AcquisitionGroupDelaySamples->value();
|
||||
|
||||
p->Graphs.defaultGraphs.transmission = ui->GraphsDefaultTransmission->currentText();
|
||||
p->Graphs.defaultGraphs.reflection = ui->GraphsDefaultReflection->currentText();
|
||||
|
|
@ -397,6 +400,7 @@ void PreferencesDialog::updateFromGUI()
|
|||
p->Marker.defaultBehavior.showCapacitance = ui->MarkerShowCapacitance->isChecked();
|
||||
p->Marker.defaultBehavior.showInductance = ui->MarkerShowInductance->isChecked();
|
||||
p->Marker.defaultBehavior.showQualityFactor = ui->MarkerShowQualityFactor->isChecked();
|
||||
p->Marker.defaultBehavior.showGroupDelay = ui->MarkerShowGroupDelay->isChecked();
|
||||
p->Marker.defaultBehavior.showNoise = ui->MarkerShowNoise->isChecked();
|
||||
p->Marker.defaultBehavior.showPhasenoise = ui->MarkerShowPhasenoise->isChecked();
|
||||
p->Marker.defaultBehavior.showCenterBandwidth = ui->MarkerShowCenterBandwidth->isChecked();
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ public:
|
|||
// Math settings
|
||||
bool limitDFT;
|
||||
double maxDFTrate;
|
||||
int groupDelaySamples;
|
||||
} Acquisition;
|
||||
struct {
|
||||
bool showUnits;
|
||||
|
|
@ -150,7 +151,7 @@ public:
|
|||
struct {
|
||||
struct {
|
||||
bool showDataOnGraphs;
|
||||
bool showdB, showdBm, showdBuV, showdBAngle, showRealImag, showImpedance, showVSWR, showResistance, showCapacitance, showInductance, showQualityFactor;
|
||||
bool showdB, showdBm, showdBuV, showdBAngle, showRealImag, showImpedance, showVSWR, showResistance, showCapacitance, showInductance, showQualityFactor, showGroupDelay;
|
||||
bool showNoise, showPhasenoise, showCenterBandwidth, showCutoff, showInsertionLoss, showTOI, showAvgTone, showAvgModulation, showP1dB, showFlatness, showMaxDeltaNeg, showMaxDeltaPos;
|
||||
} defaultBehavior;
|
||||
bool interpolatePoints;
|
||||
|
|
@ -214,6 +215,7 @@ private:
|
|||
{&Acquisition.fullSpanCalibratedRange, "Acquisition.fullSpanCalibratedRange", false},
|
||||
{&Acquisition.limitDFT, "Acquisition.limitDFT", true},
|
||||
{&Acquisition.maxDFTrate, "Acquisition.maxDFTrate", 1.0},
|
||||
{&Acquisition.groupDelaySamples, "Acquisition.groupDelaySamples", 5},
|
||||
{&Graphs.showUnits, "Graphs.showUnits", true},
|
||||
{&Graphs.Color.background, "Graphs.Color.background", QColor(Qt::black)},
|
||||
{&Graphs.Color.axis, "Graphs.Color.axis", QColor(Qt::white)},
|
||||
|
|
@ -248,6 +250,7 @@ private:
|
|||
{&Marker.defaultBehavior.showCapacitance, "Marker.defaultBehavior.showCapacitance", true},
|
||||
{&Marker.defaultBehavior.showInductance, "Marker.defaultBehavior.showInductance", true},
|
||||
{&Marker.defaultBehavior.showQualityFactor, "Marker.defaultBehavior.showQualityFactor", true},
|
||||
{&Marker.defaultBehavior.showGroupDelay, "Marker.defaultBehavior.showGroupDelay", true},
|
||||
{&Marker.defaultBehavior.showNoise, "Marker.defaultBehavior.showNoise", true},
|
||||
{&Marker.defaultBehavior.showPhasenoise, "Marker.defaultBehavior.showPhasenoise", true},
|
||||
{&Marker.defaultBehavior.showCenterBandwidth, "Marker.defaultBehavior.showCenterBandwidth", true},
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="Startup">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
|
|
@ -107,8 +107,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>683</width>
|
||||
<height>897</height>
|
||||
<width>522</width>
|
||||
<height>914</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
|
|
@ -829,46 +829,81 @@
|
|||
<property name="title">
|
||||
<string>Math operations</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="AcquisitionLimitTDRCheckbox">
|
||||
<property name="text">
|
||||
<string>Limit TDR/DFT to </string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="AcquisitionLimitTDRCheckbox">
|
||||
<property name="text">
|
||||
<string>Limit TDR/DFT to </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="AcquisitionDFTLimitValue">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_30">
|
||||
<property name="text">
|
||||
<string>updates per second</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<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>
|
||||
<widget class="QDoubleSpinBox" name="AcquisitionDFTLimitValue">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_30">
|
||||
<property name="text">
|
||||
<string>updates per second</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_31">
|
||||
<property name="text">
|
||||
<string>Number of samples used for group delay calculation: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="AcquisitionGroupDelaySamples">
|
||||
<property name="minimum">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<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>
|
||||
|
|
@ -1503,6 +1538,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="MarkerShowGroupDelay">
|
||||
<property name="text">
|
||||
<string>Group Delay</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -1737,8 +1779,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>697</width>
|
||||
<height>563</height>
|
||||
<width>168</width>
|
||||
<height>127</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
|
|
@ -1827,8 +1869,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>697</width>
|
||||
<height>563</height>
|
||||
<width>215</width>
|
||||
<height>168</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_19">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue