Additional YAxisType: Unwrapped phase

This commit is contained in:
Jan Käberich 2022-01-09 15:41:40 +01:00
parent 4ba02a810f
commit 4d959598b5
7 changed files with 48 additions and 6 deletions

View File

@ -36,6 +36,13 @@ Trace::Trace(QString name, QColor color, LiveParameter live)
dataType = domain; dataType = domain;
emit outputTypeChanged(dataType); emit outputTypeChanged(dataType);
}); });
connect(this, &Trace::outputSamplesChanged, [=](unsigned int begin, unsigned int end){
Q_UNUSED(end);
// some samples changed, delete unwrapped phases from here until the end
if(unwrappedPhase.size() > begin) {
unwrappedPhase.resize(begin);
}
});
} }
Trace::~Trace() Trace::~Trace()
@ -919,6 +926,27 @@ Trace::Data Trace::sample(unsigned int index, bool getStepResponse) const
return data; return data;
} }
double Trace::getUnwrappedPhase(unsigned int index)
{
if(index >= size()) {
return 0.0;
} else if(index >= unwrappedPhase.size()) {
// unwrapped phase not available for this entry, calculate
// copy wrapped phases first
unsigned int start_index = unwrappedPhase.size();
unwrappedPhase.resize(index + 1);
for(unsigned int i=start_index;i<=index;i++) {
unwrappedPhase[i] = arg(lastMath->getSample(i).y);
}
// unwrap the updated part
if(start_index > 0) {
start_index--;
}
Util::unwrapPhase(unwrappedPhase, start_index);
}
return unwrappedPhase[index];
}
Trace::Data Trace::interpolatedSample(double x) Trace::Data Trace::interpolatedSample(double x)
{ {
auto data = lastMath->getInterpolatedSample(x); auto data = lastMath->getInterpolatedSample(x);

View File

@ -81,6 +81,7 @@ public:
}; };
Data sample(unsigned int index, bool getStepResponse = false) const; Data sample(unsigned int index, bool getStepResponse = false) const;
double getUnwrappedPhase(unsigned int index);
// returns a (possibly interpolated sample) at a specified frequency/time/power // returns a (possibly interpolated sample) at a specified frequency/time/power
Data interpolatedSample(double x); Data interpolatedSample(double x);
QString getFilename() const; QString getFilename() const;
@ -186,6 +187,7 @@ private:
std::vector<MathInfo> mathOps; std::vector<MathInfo> mathOps;
TraceMath *lastMath; TraceMath *lastMath;
std::vector<double> unwrappedPhase;
void updateLastMath(std::vector<MathInfo>::reverse_iterator start); void updateLastMath(std::vector<MathInfo>::reverse_iterator start);
}; };

View File

@ -882,6 +882,7 @@ QString TraceXYPlot::AxisTypeToName(TraceXYPlot::YAxisType type)
case YAxisType::Disabled: return "Disabled"; case YAxisType::Disabled: return "Disabled";
case YAxisType::Magnitude: return "Magnitude"; case YAxisType::Magnitude: return "Magnitude";
case YAxisType::Phase: return "Phase"; case YAxisType::Phase: return "Phase";
case YAxisType::UnwrappedPhase: return "Unwrapped Phase";
case YAxisType::VSWR: return "VSWR"; case YAxisType::VSWR: return "VSWR";
case YAxisType::Real: return "Real"; case YAxisType::Real: return "Real";
case YAxisType::Imaginary: return "Imaginary"; case YAxisType::Imaginary: return "Imaginary";
@ -995,6 +996,9 @@ QPointF TraceXYPlot::traceToCoordinate(Trace *t, unsigned int sample, TraceXYPlo
case YAxisType::Phase: case YAxisType::Phase:
ret.setY(Util::SparamToDegree(data.y)); ret.setY(Util::SparamToDegree(data.y));
break; break;
case YAxisType::UnwrappedPhase:
ret.setY(t->getUnwrappedPhase(sample) * 180.0 / M_PI);
break;
case YAxisType::VSWR: case YAxisType::VSWR:
ret.setY(Util::SparamToVSWR(data.y)); ret.setY(Util::SparamToVSWR(data.y));
break; break;
@ -1226,6 +1230,7 @@ QString TraceXYPlot::AxisUnit(TraceXYPlot::YAxisType type)
switch(type) { switch(type) {
case TraceXYPlot::YAxisType::Magnitude: return "dB"; case TraceXYPlot::YAxisType::Magnitude: return "dB";
case TraceXYPlot::YAxisType::Phase: return "°"; case TraceXYPlot::YAxisType::Phase: return "°";
case TraceXYPlot::YAxisType::UnwrappedPhase: return "°";
case TraceXYPlot::YAxisType::VSWR: return ""; case TraceXYPlot::YAxisType::VSWR: return "";
case TraceXYPlot::YAxisType::ImpulseReal: return ""; case TraceXYPlot::YAxisType::ImpulseReal: return "";
case TraceXYPlot::YAxisType::ImpulseMag: return "dB"; case TraceXYPlot::YAxisType::ImpulseMag: return "dB";

View File

@ -17,6 +17,7 @@ public:
// S parameter options // S parameter options
Magnitude, Magnitude,
Phase, Phase,
UnwrappedPhase,
VSWR, VSWR,
Real, Real,
Imaginary, Imaginary,

View File

@ -204,6 +204,7 @@ std::set<TraceXYPlot::YAxisType> XYplotAxisDialog::supportedYAxis(TraceXYPlot::X
case TraceXYPlot::XAxisType::Power: case TraceXYPlot::XAxisType::Power:
ret.insert(TraceXYPlot::YAxisType::Magnitude); ret.insert(TraceXYPlot::YAxisType::Magnitude);
ret.insert(TraceXYPlot::YAxisType::Phase); ret.insert(TraceXYPlot::YAxisType::Phase);
ret.insert(TraceXYPlot::YAxisType::UnwrappedPhase);
ret.insert(TraceXYPlot::YAxisType::VSWR); ret.insert(TraceXYPlot::YAxisType::VSWR);
ret.insert(TraceXYPlot::YAxisType::Real); ret.insert(TraceXYPlot::YAxisType::Real);
ret.insert(TraceXYPlot::YAxisType::Imaginary); ret.insert(TraceXYPlot::YAxisType::Imaginary);

View File

@ -2,12 +2,17 @@
#include <QVector2D> #include <QVector2D>
void Util::unwrapPhase(std::vector<double> &phase) void Util::unwrapPhase(std::vector<double> &phase, unsigned int start_index)
{ {
for (unsigned int i = 1; i < phase.size(); i++) { for (unsigned int i = start_index + 1; i < phase.size(); i++) {
double d = phase[i] - phase[i-1]; int d = trunc(phase[i] - phase[i-1]) / M_PI;
d = d > M_PI ? d - 2 * M_PI : (d < -M_PI ? d + 2 * M_PI : d); if(d > 0) {
phase[i] = phase[i-1] + d; // there is larger than a 180° shift between this and the previous phase
phase[i] -= 2*M_PI*(int)((d+1)/2);
} else if(d < 0) {
// there is larger than a -180° shift between this and the previous phase
phase[i] -= 2*M_PI*(int)((d-1)/2);
}
} }
} }

View File

@ -66,7 +66,7 @@ namespace Util {
return brightness > 0.6 ? Qt::black : Qt::white; return brightness > 0.6 ? Qt::black : Qt::white;
} }
void unwrapPhase(std::vector<double> &phase); void unwrapPhase(std::vector<double> &phase, unsigned int start_index = 0);
// input values are Y coordinates, assumes evenly spaced linear X values from 0 to input.size() - 1 // input values are Y coordinates, assumes evenly spaced linear X values from 0 to input.size() - 1
void linearRegression(const std::vector<double> &input, double &B_0, double &B_1); void linearRegression(const std::vector<double> &input, double &B_0, double &B_1);