Markers adjusted for time domain math + distance mode fixed

This commit is contained in:
Jan Käberich 2020-12-02 22:15:34 +01:00
parent b8ccca5ebc
commit b91f431473
11 changed files with 375 additions and 229 deletions

View File

@ -2,6 +2,7 @@
#include "medianfilter.h" #include "medianfilter.h"
#include "tdr.h" #include "tdr.h"
#include "Traces/trace.h"
TraceMath::TraceMath() TraceMath::TraceMath()
{ {
@ -165,6 +166,15 @@ QString TraceMath::getStatusDescription() const
return statusString; return statusString;
} }
Trace *TraceMath::root()
{
auto root = this;
while(root->input) {
root = root->input;
}
return static_cast<Trace*>(root);
}
TraceMath::Status TraceMath::getStatus() const TraceMath::Status TraceMath::getStatus() const
{ {
return status; return status;

View File

@ -41,6 +41,8 @@
* 6. Extend the function getInfo(Type type) to set a name and create the explanation widget for your operation * 6. Extend the function getInfo(Type type) to set a name and create the explanation widget for your operation
*/ */
class Trace;
class TraceMath : public QObject { class TraceMath : public QObject {
Q_OBJECT Q_OBJECT
public: public:
@ -97,6 +99,9 @@ public:
Status getStatus() const; Status getStatus() const;
QString getStatusDescription() const; QString getStatusDescription() const;
// returns the trace this math operation is attached to
Trace* root();
public slots: public slots:
// some values of the input data have changed, begin/end determine which sample(s) has changed // some values of the input data have changed, begin/end determine which sample(s) has changed
virtual void inputSamplesChanged(unsigned int begin, unsigned int end){Q_UNUSED(begin) Q_UNUSED(end)}; virtual void inputSamplesChanged(unsigned int begin, unsigned int end){Q_UNUSED(begin) Q_UNUSED(end)};

View File

@ -15,7 +15,7 @@ QString WindowFunction::typeToName(WindowFunction::Type type)
case Type::Hann: return "Hann"; break; case Type::Hann: return "Hann"; break;
case Type::Blackman: return "Blackman"; break; case Type::Blackman: return "Blackman"; break;
case Type::Gaussian: return "Gaussian"; break; case Type::Gaussian: return "Gaussian"; break;
case Type::Chebyshev: return "Chebyshev"; break; // case Type::Chebyshev: return "Chebyshev"; break;
default: return "Invalid"; break; default: return "Invalid"; break;
} }
} }
@ -66,14 +66,14 @@ QWidget *WindowFunction::createEditor()
gaussian_sigma = newval; gaussian_sigma = newval;
}); });
break; break;
case Type::Chebyshev: // case Type::Chebyshev:
paramLabel = new QLabel("Parameter α:"); // paramLabel = new QLabel("Parameter α:");
paramEdit = new SIUnitEdit("", " ", 3); // paramEdit = new SIUnitEdit("", " ", 3);
paramEdit->setValue(chebyshev_alpha); // paramEdit->setValue(chebyshev_alpha);
QObject::connect(paramEdit, &SIUnitEdit::valueChanged, [=](double newval) { // QObject::connect(paramEdit, &SIUnitEdit::valueChanged, [=](double newval) {
chebyshev_alpha = newval; // chebyshev_alpha = newval;
}); // });
break; // break;
// case Type::Kaiser: // case Type::Kaiser:
// // TODO // // TODO
// break; // break;
@ -102,8 +102,8 @@ QString WindowFunction::getDescription()
QString ret = typeToName(type); QString ret = typeToName(type);
if(type == Type::Gaussian) { if(type == Type::Gaussian) {
ret += ", σ=" + QString::number(gaussian_sigma); ret += ", σ=" + QString::number(gaussian_sigma);
} else if(type == Type::Chebyshev) { // } else if(type == Type::Chebyshev) {
ret += ", α=" + QString::number(chebyshev_alpha); // ret += ", α=" + QString::number(chebyshev_alpha);
} }
return ret; return ret;
} }
@ -126,19 +126,19 @@ double WindowFunction::getFactor(unsigned int n, unsigned int N)
return 0.42 - 0.5 * cos(2*M_PI*n / N) + 0.08 * cos(4*M_PI*n / N); return 0.42 - 0.5 * cos(2*M_PI*n / N) + 0.08 * cos(4*M_PI*n / N);
case Type::Gaussian: case Type::Gaussian:
return exp(-0.5 * pow((n - (double) N/2) / (gaussian_sigma * N / 2), 2)); return exp(-0.5 * pow((n - (double) N/2) / (gaussian_sigma * N / 2), 2));
case Type::Chebyshev: { // case Type::Chebyshev: {
double beta = cosh(1.0 / N * acosh(pow(10, chebyshev_alpha))); // double beta = cosh(1.0 / N * acosh(pow(10, chebyshev_alpha)));
double T_N_arg = beta * cos(M_PI*n/(N+1)); // double T_N_arg = beta * cos(M_PI*n/(N+1));
double T_N; // double T_N;
if(T_N_arg >= 1.0) { // if(T_N_arg >= 1.0) {
T_N = cosh(N * acosh(T_N_arg)); // T_N = cosh(N * acosh(T_N_arg));
} else if(T_N_arg <= -1.0) { // } else if(T_N_arg <= -1.0) {
T_N = pow(-1.0, N) * cosh(N * acosh(T_N_arg)); // T_N = pow(-1.0, N) * cosh(N * acosh(T_N_arg));
} else { // } else {
T_N = cos(N * acos(T_N_arg)); // T_N = cos(N * acos(T_N_arg));
} // }
return T_N / pow(10.0, chebyshev_alpha); // return T_N / pow(10.0, chebyshev_alpha);
} // }
default: default:
return 1.0; return 1.0;
} }

View File

@ -13,7 +13,7 @@ public:
Rectangular, Rectangular,
// Kaiser, // Kaiser,
Gaussian, Gaussian,
Chebyshev, // Chebyshev,
Hann, Hann,
Hamming, Hamming,
Blackman, Blackman,

View File

@ -19,7 +19,6 @@ 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); connect(&model.getModel(), &TraceModel::traceNameChanged, this, &MarkerWidget::updatePersistentEditors);
connect(&model.getModel(), &TraceModel::traceTDRstateChanged, this, &MarkerWidget::updatePersistentEditors);
} }
MarkerWidget::~MarkerWidget() MarkerWidget::~MarkerWidget()
@ -56,7 +55,7 @@ void MarkerWidget::on_bAdd_clicked()
{ {
auto marker = model.createDefaultMarker(); auto marker = model.createDefaultMarker();
connect(marker, &TraceMarker::typeChanged, this, &MarkerWidget::updatePersistentEditors); connect(marker, &TraceMarker::typeChanged, this, &MarkerWidget::updatePersistentEditors);
connect(marker, &TraceMarker::timeDomainChanged, this, &MarkerWidget::updatePersistentEditors); connect(marker, &TraceMarker::traceChanged, this, &MarkerWidget::updatePersistentEditors);
model.addMarker(marker); model.addMarker(marker);
updatePersistentEditors(); updatePersistentEditors();
} }

View File

@ -167,6 +167,32 @@ const std::vector<Trace::MathInfo>& Trace::getMathOperations() const
return mathOps; return mathOps;
} }
double Trace::velocityFactor()
{
// TODO make changeable
return 0.66;
}
double Trace::timeToDistance(double time)
{
double c = 299792458;
auto distance = time * c * velocityFactor();
if(isReflection()) {
distance /= 2.0;
}
return distance;
}
double Trace::distanceToTime(double distance)
{
double c = 299792458;
auto time = distance / (c * velocityFactor());
if(isReflection()) {
time *= 2.0;
}
return time;
}
void Trace::updateLastMath(vector<MathInfo>::reverse_iterator start) void Trace::updateLastMath(vector<MathInfo>::reverse_iterator start)
{ {
TraceMath *newLast = nullptr; TraceMath *newLast = nullptr;

View File

@ -104,6 +104,10 @@ public:
}; };
const std::vector<MathInfo>& getMathOperations() const; const std::vector<MathInfo>& getMathOperations() const;
double velocityFactor();
double timeToDistance(double time);
double distanceToTime(double distance);
public slots: public slots:
void setTouchstoneParameter(int value); void setTouchstoneParameter(int value);
void setTouchstoneFilename(const QString &value); void setTouchstoneFilename(const QString &value);

View File

@ -21,7 +21,9 @@ TraceMarker::TraceMarker(TraceMarkerModel *model, int number, TraceMarker *paren
description(descr), description(descr),
delta(nullptr), delta(nullptr),
parent(parent), parent(parent),
cutoffAmplitude(-3.0) cutoffAmplitude(-3.0),
peakThreshold(-40.0),
offset(10000)
{ {
} }
@ -40,9 +42,7 @@ void TraceMarker::assignTrace(Trace *t)
if(parentTrace) { if(parentTrace) {
// remove connection from previous parent trace // remove connection from previous parent trace
parentTrace->removeMarker(this); parentTrace->removeMarker(this);
disconnect(parentTrace, &Trace::deleted, this, &TraceMarker::parentTraceDeleted); disconnect(parentTrace, &Trace::deleted, this, nullptr);
disconnect(parentTrace, &Trace::dataChanged, this, &TraceMarker::traceDataChanged);
disconnect(parentTrace, &Trace::colorChanged, this, &TraceMarker::updateSymbol);
} }
parentTrace = t; parentTrace = t;
if(!getSupportedTypes().count(type)) { if(!getSupportedTypes().count(type)) {
@ -53,6 +53,10 @@ void TraceMarker::assignTrace(Trace *t)
connect(parentTrace, &Trace::deleted, this, &TraceMarker::parentTraceDeleted); connect(parentTrace, &Trace::deleted, this, &TraceMarker::parentTraceDeleted);
connect(parentTrace, &Trace::dataChanged, this, &TraceMarker::traceDataChanged); connect(parentTrace, &Trace::dataChanged, this, &TraceMarker::traceDataChanged);
connect(parentTrace, &Trace::colorChanged, this, &TraceMarker::updateSymbol); connect(parentTrace, &Trace::colorChanged, this, &TraceMarker::updateSymbol);
connect(parentTrace, &Trace::typeChanged, [=](){
emit domainChanged();
checkDeltaMarker();
});
constrainPosition(); constrainPosition();
updateSymbol(); updateSymbol();
parentTrace->addMarker(this); parentTrace->addMarker(this);
@ -70,49 +74,68 @@ Trace *TraceMarker::trace()
QString TraceMarker::readableData() QString TraceMarker::readableData()
{ {
if(isTimeDomain()) {
switch(type) {
case Type::Manual: {
QString ret;
auto impulse = data.real();
auto step = parentTrace->sample(parentTrace->index(position), Trace::SampleType::TimeStep).y.real();
ret += "Impulse:"+Unit::ToString(impulse, "", "m ", 3);
if(!isnan(step)) {
ret += " Step:"+Unit::ToString(step, "", "m ", 3);
if(abs(step) < 1.0) {
auto impedance = 50.0 * (1.0 + step) / (1.0 - step);
ret += " Impedance:"+Unit::ToString(impedance, "Ω", "m kM", 3);
}
}
return ret;
}
case Type::Delta: {
if(!delta || !delta->isTimeDomain()) {
return "Invalid delta marker";
}
// calculate difference between markers
auto impulse = data.real() - delta->data.real();
QString ret;
auto timeDiff = position - delta->position;
auto distanceDiff = parentTrace->timeToDistance(position) - delta->parentTrace->timeToDistance(delta->position);
ret += "Δ:"+Unit::ToString(timeDiff, "s", "fpnum ", 4) + "/" + Unit::ToString(distanceDiff, "m", "m k", 4);
ret += " ΔImpulse:"+Unit::ToString(impulse, "", "m ", 3);
auto step = parentTrace->sample(parentTrace->index(position), Trace::SampleType::TimeStep).y.real();
auto stepDelta = delta->parentTrace->sample(delta->parentTrace->index(delta->position), Trace::SampleType::TimeStep).y.real();
if(!isnan(step) && !isnan(stepDelta)) {
auto stepDiff = step - stepDelta;
ret += " ΔStep:"+Unit::ToString(stepDiff, "", "m ", 3);
if(abs(step) < 1.0 && abs(stepDelta) < 1.0) {
auto impedance = 50.0 * (1.0 + step) / (1.0 - step);
auto impedanceDelta = 50.0 * (1.0 + stepDelta) / (1.0 - stepDelta);
auto impedanceDiff = impedance - impedanceDelta;
ret += " ΔImpedance:"+Unit::ToString(impedanceDiff, "Ω", "m kM", 3);
}
}
return ret;
}
default:
return "Invalid type";
}
} else {
switch(type) { switch(type) {
case Type::Manual: case Type::Manual:
case Type::Maximum: case Type::Maximum:
case Type::Minimum: case Type::Minimum: {
// if(isTimeDomain()) {
// QString ret;
// ret += "Impulse:"+Unit::ToString(timeData.impulseResponse, "", "m ", 3)+" Step:"+Unit::ToString(timeData.stepResponse, "", "m ", 3)+" Impedance:";
// if(isnan(timeData.impedance)) {
// ret += "Invalid";
// } else {
// ret += Unit::ToString(timeData.impedance, "Ω", "m k", 3);
// }
// return ret;
// } else
{
auto phase = arg(data); auto phase = arg(data);
return QString::number(toDecibel(), 'g', 4) + "db@" + QString::number(phase*180/M_PI, 'g', 4); return QString::number(toDecibel(), 'g', 4) + "db@" + QString::number(phase*180/M_PI, 'g', 4);
} }
case Type::Delta: case Type::Delta:
if(!delta /*|| delta->isTimeDomain() != isTimeDomain()*/) { if(!delta && delta->isTimeDomain()) {
return "Invalid delta marker"; return "Invalid delta marker";
} else { } else {
// if(isTimeDomain()) {
// // calculate difference between markers
// auto impulse = timeData.impulseResponse - delta->timeData.impulseResponse;
// auto step = timeData.stepResponse - delta->timeData.stepResponse;
// auto impedance = timeData.impedance - delta->timeData.impedance;
// QString ret;
// ret += "ΔImpulse:"+Unit::ToString(impulse, "", "m ", 3)+" ΔStep:"+Unit::ToString(step, "", "m ", 3)+" ΔImpedance:";
// if(isnan(timeData.impedance)) {
// ret += "Invalid";
// } else {
// ret += Unit::ToString(impedance, "Ω", "m k", 3);
// }
// return ret;
// } else {
// calculate difference between markers // calculate difference between markers
auto freqDiff = position - delta->position; auto freqDiff = position - delta->position;
auto valueDiff = data / delta->data; auto valueDiff = data / delta->data;
auto phase = arg(valueDiff); auto phase = arg(valueDiff);
auto db = 20*log10(abs(valueDiff)); auto db = 20*log10(abs(valueDiff));
return Unit::ToString(freqDiff, "Hz", " kMG") + " / " + QString::number(db, 'g', 4) + "db@" + QString::number(phase*180/M_PI, 'g', 4); return Unit::ToString(freqDiff, "Hz", " kMG") + " / " + QString::number(db, 'g', 4) + "db@" + QString::number(phase*180/M_PI, 'g', 4);
// }
} }
break; break;
case Type::Noise: case Type::Noise:
@ -173,25 +196,19 @@ QString TraceMarker::readableData()
return "Unknown marker type"; return "Unknown marker type";
} }
} }
}
QString TraceMarker::readableSettings() QString TraceMarker::readableSettings()
{ {
// if(timeDomain) { if(isTimeDomain()) {
// switch(type) { switch(type) {
// case Type::Manual: case Type::Manual:
// case Type::Delta: { case Type::Delta:
// QString unit; return Unit::ToString(position, "s", "fpnum ", 4) + "/" + Unit::ToString(parentTrace->timeToDistance(position), "m", "um k", 4);
// if(position <= parentTrace->getTDR().back().time) { default:
// unit = "s"; return "Unhandled case";
// } else { }
// unit = "m"; } else {
// }
// return Unit::ToString(position, unit, "fpnum k", 4);
// }
// default:
// return "Unhandled case";
// }
// } else {
switch(type) { switch(type) {
case Type::Manual: case Type::Manual:
case Type::Maximum: case Type::Maximum:
@ -212,7 +229,39 @@ QString TraceMarker::readableSettings()
default: default:
return "Unhandled case"; return "Unhandled case";
} }
// } }
}
QString TraceMarker::tooltipSettings()
{
if(isTimeDomain()) {
switch(type) {
case Type::Manual:
case Type::Delta:
return "Time/Distance";
default:
return QString();
}
} else {
switch(type) {
case Type::Manual:
case Type::Maximum:
case Type::Minimum:
case Type::Delta:
case Type::Noise:
return "Marker frequency";
case Type::Lowpass:
case Type::Highpass:
case Type::Bandpass:
return "Cutoff amplitude (relativ to peak)";
case Type::PeakTable:
return "Peak threshold";
case Type::PhaseNoise:
return "Frequency offset";
default:
return QString();
}
}
} }
QString TraceMarker::readableType() QString TraceMarker::readableType()
@ -241,12 +290,8 @@ void TraceMarker::traceDataChanged()
{ {
// some data of the parent trace changed, check if marker data also changed // some data of the parent trace changed, check if marker data also changed
complex<double> newdata; complex<double> newdata;
// if (timeDomain) { auto sampleType = isTimeDomain() ? Trace::SampleType::TimeImpulse : Trace::SampleType::Frequency;
// timeData = parentTrace->getTDR(position); newdata = parentTrace->sample(parentTrace->index(position), sampleType).y;
// newdata = complex<double>(timeData.stepResponse, timeData.impulseResponse);
// } else {
newdata = parentTrace->sample(parentTrace->index(position)).y;
// }
if (newdata != data) { if (newdata != data) {
data = newdata; data = newdata;
update(); update();
@ -276,15 +321,28 @@ void TraceMarker::updateSymbol()
emit symbolChanged(this); emit symbolChanged(this);
} }
void TraceMarker::checkDeltaMarker()
{
if(type != Type::Delta) {
// not a delta marker, nothing to do
return;
}
// Check if type of delta marker is still okay
if(delta->isTimeDomain() != isTimeDomain()) {
// not the same domain anymore, adjust delta
assignDeltaMarker(bestDeltaCandidate());
}
}
std::set<TraceMarker::Type> TraceMarker::getSupportedTypes() std::set<TraceMarker::Type> TraceMarker::getSupportedTypes()
{ {
set<TraceMarker::Type> supported; set<TraceMarker::Type> supported;
if(parentTrace) { if(parentTrace) {
// if(timeDomain) { if(isTimeDomain()) {
// // only basic markers in time domain // only basic markers in time domain
// supported.insert(Type::Manual); supported.insert(Type::Manual);
// supported.insert(Type::Delta); supported.insert(Type::Delta);
// } else { } else {
// all traces support some basic markers // all traces support some basic markers
supported.insert(Type::Manual); supported.insert(Type::Manual);
supported.insert(Type::Maximum); supported.insert(Type::Maximum);
@ -311,7 +369,7 @@ std::set<TraceMarker::Type> TraceMarker::getSupportedTypes()
break; break;
} }
} }
// } }
} }
return supported; return supported;
} }
@ -319,13 +377,6 @@ std::set<TraceMarker::Type> TraceMarker::getSupportedTypes()
void TraceMarker::constrainPosition() void TraceMarker::constrainPosition()
{ {
if(parentTrace) { if(parentTrace) {
// if(timeDomain) {
// if(position < 0) {
// position = 0;
// } else if(position > parentTrace->getTDR().back().distance) {
// position = parentTrace->getTDR().back().distance;
// }
// } else {
if(parentTrace->size() > 0) { if(parentTrace->size() > 0) {
if(position > parentTrace->maxX()) { if(position > parentTrace->maxX()) {
position = parentTrace->maxX(); position = parentTrace->maxX();
@ -333,11 +384,38 @@ void TraceMarker::constrainPosition()
position = parentTrace->minX(); position = parentTrace->minX();
} }
} }
// }
traceDataChanged(); traceDataChanged();
} }
} }
TraceMarker *TraceMarker::bestDeltaCandidate()
{
TraceMarker *match = nullptr;
// invalid delta marker assigned, attempt to find a matching marker
for(int pass = 0;pass < 3;pass++) {
for(auto m : model->getMarkers()) {
if(m->isTimeDomain() != isTimeDomain()) {
// markers are not on the same domain
continue;
}
if(pass == 0 && m->parentTrace != parentTrace) {
// ignore markers on different traces in first pass
continue;
}
if(pass <= 1 && m == this) {
// ignore itself on second pass
continue;
}
match = m;
break;
}
if(match) {
break;
}
}
return match;
}
void TraceMarker::assignDeltaMarker(TraceMarker *m) void TraceMarker::assignDeltaMarker(TraceMarker *m)
{ {
if(delta) { if(delta) {
@ -347,8 +425,9 @@ void TraceMarker::assignDeltaMarker(TraceMarker *m)
if(delta && delta != this) { if(delta && delta != this) {
// this marker has to be updated when the delta marker changes // this marker has to be updated when the delta marker changes
connect(delta, &TraceMarker::rawDataChanged, this, &TraceMarker::update); connect(delta, &TraceMarker::rawDataChanged, this, &TraceMarker::update);
connect(delta, &TraceMarker::domainChanged, this, &TraceMarker::checkDeltaMarker);
connect(delta, &TraceMarker::deleted, [=](){ connect(delta, &TraceMarker::deleted, [=](){
delta = nullptr; assignDeltaMarker(bestDeltaCandidate());
update(); update();
}); });
} }
@ -377,29 +456,7 @@ void TraceMarker::setType(TraceMarker::Type t)
vector<helper_descr> required_helpers; vector<helper_descr> required_helpers;
switch(type) { switch(type) {
case Type::Delta: case Type::Delta:
delta = nullptr; assignDeltaMarker(bestDeltaCandidate());
// invalid delta marker assigned, attempt to find a matching marker
for(int pass = 0;pass < 3;pass++) {
for(auto m : model->getMarkers()) {
// if(m->isTimeDomain() != isTimeDomain()) {
// // markers are not on the same domain
// continue;
// }
if(pass == 0 && m->parentTrace != parentTrace) {
// ignore markers on different traces in first pass
continue;
}
if(pass <= 1 && m == this) {
// ignore itself on second pass
continue;
}
assignDeltaMarker(m);
break;
}
if(delta) {
break;
}
}
break; break;
case Type::Lowpass: case Type::Lowpass:
case Type::Highpass: case Type::Highpass:
@ -560,15 +617,15 @@ void TraceMarker::updateTypeFromEditor(QWidget *w)
SIUnitEdit *TraceMarker::getSettingsEditor() SIUnitEdit *TraceMarker::getSettingsEditor()
{ {
// if(timeDomain) { if(isTimeDomain()) {
// switch(type) { switch(type) {
// case Type::Manual: case Type::Manual:
// case Type::Delta: case Type::Delta:
// return new SIUnitEdit("", "fpnum k", 6); return new SIUnitEdit("", "fpnum k", 6);
// default: default:
// return nullptr; return nullptr;
// } }
// } else { } else {
switch(type) { switch(type) {
case Type::Manual: case Type::Manual:
case Type::Maximum: case Type::Maximum:
@ -585,20 +642,36 @@ SIUnitEdit *TraceMarker::getSettingsEditor()
case Type::TOI: case Type::TOI:
return nullptr; return nullptr;
} }
// } }
} }
void TraceMarker::adjustSettings(double value) void TraceMarker::adjustSettings(double value)
{ {
if(isTimeDomain()) {
switch(type) {
case Type::Manual:
case Type::Delta: {
// check if entered position is time or distance
if(value > parentTrace->sample(parentTrace->size() - 1).x) {
// entered a distance, convert to time
setPosition(parentTrace->distanceToTime(value));
} else {
// entered a time, can set directly
setPosition(value);
}
}
default:
break;
}
} else {
switch(type) { switch(type) {
case Type::Manual: case Type::Manual:
case Type::Maximum: case Type::Maximum:
case Type::Minimum: case Type::Minimum:
case Type::Delta: case Type::Delta:
case Type::Noise: case Type::Noise:
default:
setPosition(value); setPosition(value);
/* no break */ break;
case Type::Lowpass: case Type::Lowpass:
case Type::Highpass: case Type::Highpass:
case Type::Bandpass: case Type::Bandpass:
@ -613,6 +686,9 @@ void TraceMarker::adjustSettings(double value)
case Type::PhaseNoise: case Type::PhaseNoise:
offset = value; offset = value;
break; break;
default:
break;
}
} }
update(); update();
} }
@ -790,3 +866,13 @@ double TraceMarker::getPosition() const
return position; return position;
} }
bool TraceMarker::isTimeDomain()
{
if(parentTrace) {
if(parentTrace->outputType() == Trace::DataType::Time) {
return true;
}
}
return false;
}

View File

@ -19,11 +19,13 @@ public:
Trace* trace(); Trace* trace();
QString readableData(); QString readableData();
QString readableSettings(); QString readableSettings();
QString tooltipSettings();
QString readableType(); QString readableType();
double getPosition() const; double getPosition() const;
std::complex<double> getData() const; std::complex<double> getData() const;
bool isMovable(); bool isMovable();
bool isTimeDomain();
QPixmap& getSymbol(); QPixmap& getSymbol();
@ -56,14 +58,15 @@ signals:
void traceChanged(TraceMarker *m); void traceChanged(TraceMarker *m);
void beginRemoveHelperMarkers(TraceMarker *m); void beginRemoveHelperMarkers(TraceMarker *m);
void endRemoveHelperMarkers(TraceMarker *m); void endRemoveHelperMarkers(TraceMarker *m);
void timeDomainChanged();
private slots: private slots:
void parentTraceDeleted(Trace *t); void parentTraceDeleted(Trace *t);
void traceDataChanged(); void traceDataChanged();
void updateSymbol(); void updateSymbol();
void checkDeltaMarker();
signals: signals:
void rawDataChanged(); void rawDataChanged();
void domainChanged();
private: private:
enum class Type { enum class Type {
@ -97,6 +100,7 @@ private:
} }
} }
void constrainPosition(); void constrainPosition();
TraceMarker *bestDeltaCandidate();
void assignDeltaMarker(TraceMarker *m); void assignDeltaMarker(TraceMarker *m);
void deleteHelperMarkers(); void deleteHelperMarkers();
void setType(Type t); void setType(Type t);
@ -108,7 +112,7 @@ private:
double position; double position;
int number; int number;
// Frequency domain: S parameter // Frequency domain: S parameter
// Time domain: imag part is impulse response, real part is step response // Time domain: impulse response
std::complex<double> data; std::complex<double> data;
QPixmap symbol; QPixmap symbol;
Type type; Type type;
@ -118,11 +122,10 @@ private:
TraceMarker *delta; TraceMarker *delta;
std::vector<TraceMarker*> helperMarkers; std::vector<TraceMarker*> helperMarkers;
TraceMarker *parent; TraceMarker *parent;
union { // settings for the different marker types
double cutoffAmplitude; double cutoffAmplitude;
double peakThreshold; double peakThreshold;
double offset; double offset;
}; };
};
#endif // TRACEMARKER_H #endif // TRACEMARKER_H

View File

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

View File

@ -513,6 +513,10 @@ void TraceXYPlot::updateAxisTicks()
// this trace is currently displayed // this trace is currently displayed
double trace_min = trace->minX(); double trace_min = trace->minX();
double trace_max = trace->maxX(); double trace_max = trace->maxX();
if(XAxis.type == XAxisType::Distance) {
trace_min = trace->timeToDistance(trace_min);
trace_max = trace->timeToDistance(trace_max);
}
if(trace_min < min) { if(trace_min < min) {
min = trace_min; min = trace_min;
} }
@ -666,7 +670,14 @@ QPointF TraceXYPlot::traceToCoordinate(Trace *t, unsigned int sample, TraceXYPlo
{ {
QPointF ret = QPointF(numeric_limits<double>::quiet_NaN(), numeric_limits<double>::quiet_NaN()); QPointF ret = QPointF(numeric_limits<double>::quiet_NaN(), numeric_limits<double>::quiet_NaN());
auto data = t->sample(sample); auto data = t->sample(sample);
switch(XAxis.type) {
case XAxisType::Distance:
ret.setX(t->timeToDistance(data.x));
break;
default:
ret.setX(data.x); ret.setX(data.x);
break;
}
switch(type) { switch(type) {
case YAxisType::Magnitude: case YAxisType::Magnitude:
ret.setY(20*log10(abs(data.y))); ret.setY(20*log10(abs(data.y)));
@ -762,6 +773,9 @@ double TraceXYPlot::nearestTracePoint(Trace *t, QPoint pixel)
closestXpos = point.x(); closestXpos = point.x();
} }
} }
if(XAxis.type == XAxisType::Distance) {
closestXpos = t->distanceToTime(closestXpos);
}
return closestXpos; return closestXpos;
} }