WIP: make de-embedding and calibration work with arbitrary number of ports

This commit is contained in:
Jan Käberich 2022-09-13 21:42:47 +02:00
parent 8301448343
commit 9cf76c9681
30 changed files with 478 additions and 193 deletions

View File

@ -45,6 +45,7 @@ QString Calibration::TypeToString(Calibration::Type type)
switch(type) { switch(type) {
case Type::None: return "None"; case Type::None: return "None";
case Type::SOLT: return "SOLT"; case Type::SOLT: return "SOLT";
case Type::ThroughNormalization: return "ThroughNormalization";
case Type::Last: return "Invalid"; case Type::Last: return "Invalid";
} }
} }
@ -134,6 +135,18 @@ void Calibration::correctMeasurement(VirtualDevice::VNAMeasurement &d)
} }
} }
void Calibration::correctTraces(std::map<QString, Trace *> traceSet)
{
auto points = Trace::assembleDatapoints(traceSet);
if(points.size()) {
// succeeded in assembling datapoints
for(auto &p : points) {
correctMeasurement(p);
}
Trace::fillFromDatapoints(traceSet, points);
}
}
void Calibration::edit() void Calibration::edit()
{ {
auto d = new QDialog(); auto d = new QDialog();
@ -390,8 +403,7 @@ CalibrationMeasurement::Base *Calibration::newMeasurement(CalibrationMeasurement
return m; return m;
} }
Calibration::Point Calibration::computeSOLT(double f) Calibration::Point Calibration::createInitializedPoint(double f) {
{
Point point; Point point;
point.frequency = f; point.frequency = f;
// resize vectors // resize vectors
@ -405,6 +417,12 @@ Calibration::Point Calibration::computeSOLT(double f)
fill(point.L.begin(), point.L.end(), vector<complex<double>>(caltype.usedPorts.size())); fill(point.L.begin(), point.L.end(), vector<complex<double>>(caltype.usedPorts.size()));
fill(point.T.begin(), point.T.end(), vector<complex<double>>(caltype.usedPorts.size())); fill(point.T.begin(), point.T.end(), vector<complex<double>>(caltype.usedPorts.size()));
fill(point.I.begin(), point.I.end(), vector<complex<double>>(caltype.usedPorts.size())); fill(point.I.begin(), point.I.end(), vector<complex<double>>(caltype.usedPorts.size()));
return point;
}
Calibration::Point Calibration::computeSOLT(double f)
{
Point point = createInitializedPoint(f);
// Calculate SOL coefficients // Calculate SOL coefficients
for(unsigned int i=0;i<caltype.usedPorts.size();i++) { for(unsigned int i=0;i<caltype.usedPorts.size();i++) {
@ -464,6 +482,47 @@ Calibration::Point Calibration::computeSOLT(double f)
return point; return point;
} }
Calibration::Point Calibration::computeThroughNormalization(double f)
{
Point point = createInitializedPoint(f);
// Calculate SOL coefficients
for(unsigned int i=0;i<caltype.usedPorts.size();i++) {
// use ideal coefficients
point.D[i] = 0.0;
point.S[i] = 0.0;
point.R[i] = 1.0;
}
// calculate forward match and transmission
for(unsigned int i=0;i<caltype.usedPorts.size();i++) {
for(unsigned int j=0;j<caltype.usedPorts.size();j++) {
if(i == j) {
// this is the exciting port, SOL error box used here
continue;
}
auto p1 = caltype.usedPorts[i];
auto p2 = caltype.usedPorts[j];
// grab measurement and calkit through definitions
auto throughForward = static_cast<CalibrationMeasurement::Through*>(findMeasurement(CalibrationMeasurement::Base::Type::Through, p1, p2));
auto throughReverse = static_cast<CalibrationMeasurement::Through*>(findMeasurement(CalibrationMeasurement::Base::Type::Through, p2, p1));
complex<double> S11, S21;
Sparam Sideal;
if(throughForward) {
S21 = throughForward->getMeasured(f).m21;
Sideal = throughForward->getActual(f);
} else if(throughReverse) {
S21 = throughReverse->getMeasured(f).m12;
Sideal = throughReverse->getActual(f);
swap(Sideal.m12, Sideal.m21);
}
point.L[i][j] = 0.0;
point.T[i][j] = S21 / Sideal.m21;
point.I[i][j] = 0.0;
}
}
return point;
}
Calibration::CalType Calibration::getCaltype() const Calibration::CalType Calibration::getCaltype() const
{ {
return caltype; return caltype;
@ -504,12 +563,151 @@ Calibration::InterpolationType Calibration::getInterpolation(double f_start, dou
std::vector<Trace *> Calibration::getErrorTermTraces() std::vector<Trace *> Calibration::getErrorTermTraces()
{ {
return vector<Trace*>(); // TODO vector<Trace*> ret;
if(points.size() == 0) {
return ret;
}
for(unsigned int i=0;i<caltype.usedPorts.size();i++) {
auto p = caltype.usedPorts[i];
auto tDir = new Trace("Directivity_Port"+QString::number(p));
tDir->setReflection(true);
tDir->setCalibration();
auto tSM = new Trace("SourceMatch_Port"+QString::number(p));
tSM->setReflection(true);
tSM->setCalibration();
auto tRT = new Trace("ReflectionTracking_Port"+QString::number(p));
tRT->setReflection(false);
tRT->setCalibration();
for(auto p : points) {
Trace::Data td;
td.x = p.frequency;
td.y = p.D[i];
tDir->addData(td, Trace::DataType::Frequency);
td.y = p.S[i];
tSM->addData(td, Trace::DataType::Frequency);
td.y = p.R[i];
tRT->addData(td, Trace::DataType::Frequency);
}
ret.push_back(tDir);
ret.push_back(tSM);
ret.push_back(tRT);
for(unsigned int j=0;j<caltype.usedPorts.size();j++) {
if(i==j) {
continue;
}
auto p2 = caltype.usedPorts[j];
auto tRM = new Trace("ReceiverMatch_"+QString::number(p)+QString::number(p2));
tRM->setReflection(true);
tRM->setCalibration();
auto tTT = new Trace("TransmissionTracking_"+QString::number(p)+QString::number(p2));
tTT->setReflection(false);
tTT->setCalibration();
auto tTI = new Trace("TransmissionIsolation_"+QString::number(p)+QString::number(p2));
tTI->setReflection(false);
tTI->setCalibration();
for(auto p : points) {
Trace::Data td;
td.x = p.frequency;
td.y = p.L[i][j];
tRM->addData(td, Trace::DataType::Frequency);
td.y = p.T[i][j];
tTT->addData(td, Trace::DataType::Frequency);
td.y = p.I[i][j];
tTI->addData(td, Trace::DataType::Frequency);
}
ret.push_back(tRM);
ret.push_back(tTT);
ret.push_back(tTI);
}
}
return ret;
} }
std::vector<Trace *> Calibration::getMeasurementTraces() std::vector<Trace *> Calibration::getMeasurementTraces()
{ {
return vector<Trace*>(); // TODO vector<Trace*> ret;
for(auto m : measurements) {
switch(m->getType()) {
case CalibrationMeasurement::Base::Type::Open:
case CalibrationMeasurement::Base::Type::Short:
case CalibrationMeasurement::Base::Type::Load: {
auto onePort = static_cast<CalibrationMeasurement::OnePort*>(m);
auto t = new Trace(CalibrationMeasurement::Base::TypeToString(onePort->getType())+"_Port"+QString::number(onePort->getPort()));
t->setCalibration();
t->setReflection(true);
for(auto d : onePort->getPoints()) {
Trace::Data td;
td.x = d.frequency;
td.y = d.S;
t->addData(td, Trace::DataType::Frequency);
}
ret.push_back(t);
}
break;
case CalibrationMeasurement::Base::Type::Through: {
auto twoPort = static_cast<CalibrationMeasurement::TwoPort*>(m);
auto ts11 = new Trace(CalibrationMeasurement::Base::TypeToString(twoPort->getType())+"_Port"+QString::number(twoPort->getPort1())+QString::number(twoPort->getPort2())+"_S11");
auto ts12 = new Trace(CalibrationMeasurement::Base::TypeToString(twoPort->getType())+"_Port"+QString::number(twoPort->getPort1())+QString::number(twoPort->getPort2())+"_S12");
auto ts21 = new Trace(CalibrationMeasurement::Base::TypeToString(twoPort->getType())+"_Port"+QString::number(twoPort->getPort1())+QString::number(twoPort->getPort2())+"_S21");
auto ts22 = new Trace(CalibrationMeasurement::Base::TypeToString(twoPort->getType())+"_Port"+QString::number(twoPort->getPort1())+QString::number(twoPort->getPort2())+"_S22");
ts11->setCalibration();
ts11->setReflection(true);
ts12->setCalibration();
ts12->setReflection(false);
ts21->setCalibration();
ts21->setReflection(false);
ts22->setCalibration();
ts22->setReflection(true);
for(auto d : twoPort->getPoints()) {
Trace::Data td;
td.x = d.frequency;
td.y = d.S.m11;
ts11->addData(td, Trace::DataType::Frequency);
td.y = d.S.m12;
ts12->addData(td, Trace::DataType::Frequency);
td.y = d.S.m21;
ts21->addData(td, Trace::DataType::Frequency);
td.y = d.S.m22;
ts22->addData(td, Trace::DataType::Frequency);
}
ret.push_back(ts11);
ret.push_back(ts12);
ret.push_back(ts21);
ret.push_back(ts22);
}
break;
case CalibrationMeasurement::Base::Type::Isolation: {
auto iso = static_cast<CalibrationMeasurement::Isolation*>(m);
int ports = iso->getPoints()[0].S.size();
// Create the traces
vector<vector<Trace*>> traces;
traces.resize(ports);
for(int i=0;i<ports;i++) {
for(int j=0;j<ports;j++) {
auto t = new Trace(CalibrationMeasurement::Base::TypeToString(iso->getType())+"_S"+QString::number(i+1)+QString::number(j+1));
t->setCalibration();
t->setReflection(i==j);
traces[i].push_back(t);
// also add to main return vector
ret.push_back(t);
}
}
// Fill the traces
for(auto p : iso->getPoints()) {
Trace::Data td;
td.x = p.frequency;
for(int i=0;i<p.S.size();i++) {
for(int j=0;j<p.S[i].size();j++) {
td.y = p.S[i][j];
traces[i][j]->addData(td, Trace::DataType::Frequency);
}
}
}
}
break;
}
}
return ret;
} }
QString Calibration::getCurrentCalibrationFile() QString Calibration::getCurrentCalibrationFile()
@ -735,15 +933,15 @@ std::vector<Calibration::Type> Calibration::getTypes()
bool Calibration::canCompute(Calibration::CalType type, double *startFreq, double *stopFreq, int *points) bool Calibration::canCompute(Calibration::CalType type, double *startFreq, double *stopFreq, int *points)
{ {
using RequiredMeasurements = struct {
CalibrationMeasurement::Base::Type type;
int port1, port2;
};
vector<RequiredMeasurements> required;
switch(type.type) { switch(type.type) {
case Type::None: case Type::None:
return true; // Always possible to reset the calibration return true; // Always possible to reset the calibration
case Type::SOLT: { case Type::SOLT:
using RequiredMeasurements = struct {
CalibrationMeasurement::Base::Type type;
int port1, port2;
};
vector<RequiredMeasurements> required;
// SOL measurements for every port // SOL measurements for every port
for(auto p : type.usedPorts) { for(auto p : type.usedPorts) {
required.push_back({.type = CalibrationMeasurement::Base::Type::Short, .port1 = p}); required.push_back({.type = CalibrationMeasurement::Base::Type::Short, .port1 = p});
@ -756,6 +954,17 @@ bool Calibration::canCompute(Calibration::CalType type, double *startFreq, doubl
required.push_back({.type = CalibrationMeasurement::Base::Type::Through, .port1 = i, .port2 = j}); required.push_back({.type = CalibrationMeasurement::Base::Type::Through, .port1 = i, .port2 = j});
} }
} }
break;
case Type::ThroughNormalization:
// through measurements between all ports
for(int i=1;i<=type.usedPorts.size();i++) {
for(int j=i+1;j<=type.usedPorts.size();j++) {
required.push_back({.type = CalibrationMeasurement::Base::Type::Through, .port1 = i, .port2 = j});
}
}
break;
}
if(required.size() > 0) {
vector<CalibrationMeasurement::Base*> foundMeasurements; vector<CalibrationMeasurement::Base*> foundMeasurements;
for(auto m : required) { for(auto m : required) {
auto meas = findMeasurement(m.type, m.port1, m.port2); auto meas = findMeasurement(m.type, m.port1, m.port2);
@ -767,8 +976,6 @@ bool Calibration::canCompute(Calibration::CalType type, double *startFreq, doubl
} }
} }
return hasFrequencyOverlap(foundMeasurements, startFreq, stopFreq, points); return hasFrequencyOverlap(foundMeasurements, startFreq, stopFreq, points);
}
break;
} }
return false; return false;
} }
@ -816,6 +1023,7 @@ int Calibration::minimumPorts(Calibration::Type type)
{ {
switch(type) { switch(type) {
case Type::SOLT: return 1; case Type::SOLT: return 1;
case Type::ThroughNormalization: return 2;
} }
return -1; return -1;
} }

View File

@ -17,6 +17,7 @@ public:
enum class Type { enum class Type {
None, None,
SOLT, SOLT,
ThroughNormalization,
Last, Last,
}; };
class CalType { class CalType {
@ -36,6 +37,7 @@ public:
// Applies calculated calibration coefficients to measurement data // Applies calculated calibration coefficients to measurement data
void correctMeasurement(VirtualDevice::VNAMeasurement &d); void correctMeasurement(VirtualDevice::VNAMeasurement &d);
void correctTraces(std::map<QString, Trace*> traceSet);
// Starts the calibration edit dialog, allowing the user to make/delete measurements // Starts the calibration edit dialog, allowing the user to make/delete measurements
void edit(); void edit();
@ -123,8 +125,8 @@ private:
public: public:
double frequency; double frequency;
std::vector<std::complex<double>> D; // Directivity std::vector<std::complex<double>> D; // Directivity
std::vector<std::complex<double>> R; // Source Match std::vector<std::complex<double>> R; // Reflection tracking
std::vector<std::complex<double>> S; // Reflection tracking std::vector<std::complex<double>> S; // Source Match
std::vector<std::vector<std::complex<double>>> L; // Receiver Match std::vector<std::vector<std::complex<double>>> L; // Receiver Match
std::vector<std::vector<std::complex<double>>> T; // Transmission tracking std::vector<std::vector<std::complex<double>>> T; // Transmission tracking
std::vector<std::vector<std::complex<double>>> I; // Transmission isolation std::vector<std::vector<std::complex<double>>> I; // Transmission isolation
@ -132,7 +134,9 @@ private:
}; };
std::vector<Point> points; std::vector<Point> points;
Point createInitializedPoint(double f);
Point computeSOLT(double f); Point computeSOLT(double f);
Point computeThroughNormalization(double f);
std::vector<CalibrationMeasurement::Base*> measurements; std::vector<CalibrationMeasurement::Base*> measurements;

View File

@ -328,6 +328,11 @@ void CalibrationMeasurement::OnePort::setPort(int p)
} }
} }
std::vector<CalibrationMeasurement::OnePort::Point> CalibrationMeasurement::OnePort::getPoints() const
{
return points;
}
double CalibrationMeasurement::TwoPort::minFreq() double CalibrationMeasurement::TwoPort::minFreq()
{ {
if(points.size() > 0) { if(points.size() > 0) {
@ -529,6 +534,11 @@ void CalibrationMeasurement::TwoPort::setReverseStandard(bool reverse)
} }
} }
std::vector<CalibrationMeasurement::TwoPort::Point> CalibrationMeasurement::TwoPort::getPoints() const
{
return points;
}
int CalibrationMeasurement::TwoPort::getPort1() const int CalibrationMeasurement::TwoPort::getPort1() const
{ {
return port1; return port1;
@ -658,3 +668,8 @@ std::complex<double> CalibrationMeasurement::Isolation::getMeasured(double frequ
return p.S[portRcv][portSrc]; return p.S[portRcv][portSrc];
} }
} }
std::vector<CalibrationMeasurement::Isolation::Point> CalibrationMeasurement::Isolation::getPoints() const
{
return points;
}

View File

@ -1,4 +1,4 @@
#ifndef CALIBRATIONMEASUREMENT_H #ifndef CALIBRATIONMEASUREMENT_H
#define CALIBRATIONMEASUREMENT_H #define CALIBRATIONMEASUREMENT_H
#include "calstandard.h" #include "calstandard.h"
@ -83,6 +83,13 @@ public:
virtual nlohmann::json toJSON() override; virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override; virtual void fromJSON(nlohmann::json j) override;
class Point {
public:
double frequency;
std::complex<double> S;
};
std::vector<Point> getPoints() const;
std::complex<double> getMeasured(double frequency); std::complex<double> getMeasured(double frequency);
std::complex<double> getActual(double frequency); std::complex<double> getActual(double frequency);
@ -95,11 +102,6 @@ signals:
void portChanged(int p); void portChanged(int p);
protected: protected:
int port; int port;
class Point {
public:
double frequency;
std::complex<double> S;
};
std::vector<Point> points; std::vector<Point> points;
}; };
@ -156,12 +158,20 @@ public:
virtual nlohmann::json toJSON() override; virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override; virtual void fromJSON(nlohmann::json j) override;
class Point {
public:
double frequency;
Sparam S;
};
std::vector<Point> getPoints() const;
Sparam getMeasured(double frequency); Sparam getMeasured(double frequency);
Sparam getActual(double frequency); Sparam getActual(double frequency);
int getPort1() const; int getPort1() const;
int getPort2() const; int getPort2() const;
public slots: public slots:
void setPort1(int p); void setPort1(int p);
void setPort2(int p); void setPort2(int p);
@ -174,11 +184,6 @@ signals:
protected: protected:
int port1, port2; int port1, port2;
bool reverseStandard; // Set to true if standard is defined with ports swapped bool reverseStandard; // Set to true if standard is defined with ports swapped
class Point {
public:
double frequency;
Sparam S;
};
std::vector<Point> points; std::vector<Point> points;
}; };
@ -211,17 +216,19 @@ public:
virtual nlohmann::json toJSON() override; virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override; virtual void fromJSON(nlohmann::json j) override;
class Point {
public:
double frequency;
std::vector<std::vector<std::complex<double>>> S;
};
std::vector<Point> getPoints() const;
std::complex<double> getMeasured(double frequency, unsigned int portRcv, unsigned int portSrc); std::complex<double> getMeasured(double frequency, unsigned int portRcv, unsigned int portSrc);
virtual std::set<CalStandard::Virtual::Type> supportedStandardTypes() override {return {};} virtual std::set<CalStandard::Virtual::Type> supportedStandardTypes() override {return {};}
virtual Type getType() override {return Type::Isolation;} virtual Type getType() override {return Type::Isolation;}
protected: protected:
class Point {
public:
double frequency;
std::vector<std::vector<std::complex<double>>> S;
};
std::vector<Point> points; std::vector<Point> points;
}; };

View File

@ -7,13 +7,12 @@ ManualCalibrationDialog::ManualCalibrationDialog(const TraceModel &model, Calibr
ui(new Ui::ManualCalibrationDialog) ui(new Ui::ManualCalibrationDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
auto traceSelector = new SparamTraceSelector(model, 2); auto traceSelector = new SparamTraceSelector(model, cal->getCaltype().usedPorts);
ui->verticalLayout->insertWidget(1, traceSelector, 1.0); ui->verticalLayout->insertWidget(1, traceSelector, 1.0);
ui->buttonBox->setEnabled(false); ui->buttonBox->setEnabled(false);
connect(traceSelector, &SparamTraceSelector::selectionValid, ui->buttonBox, &QDialogButtonBox::setEnabled); connect(traceSelector, &SparamTraceSelector::selectionValid, ui->buttonBox, &QDialogButtonBox::setEnabled);
connect(ui->buttonBox, &QDialogButtonBox::accepted, [=]() { connect(ui->buttonBox, &QDialogButtonBox::accepted, [=]() {
auto t = traceSelector->getTraces(); cal->correctTraces(traceSelector->getTraces());
// cal->correctTraces(*t[0], *t[1], *t[2], *t[3]); // TODO
accept(); accept();
}); });
} }

View File

@ -5,42 +5,39 @@
using namespace std; using namespace std;
SparamTraceSelector::SparamTraceSelector(const TraceModel &model, unsigned int num_ports, bool empty_allowed, std::set<unsigned int> skip) SparamTraceSelector::SparamTraceSelector(const TraceModel &model, std::vector<int> used_ports, bool empty_allowed)
: model(model), : model(model),
num_ports(num_ports), used_ports(used_ports),
empty_allowed(empty_allowed) empty_allowed(empty_allowed)
{ {
// Create comboboxes createGUI();
auto layout = new QFormLayout;
setLayout(layout);
for(unsigned int i=0;i<num_ports;i++) {
for(unsigned int j=0;j<num_ports;j++) {
auto label = new QLabel("S"+QString::number(i+1)+QString::number(j+1)+":");
auto box = new QComboBox();
connect(box, qOverload<int>(&QComboBox::currentIndexChanged), [=](int) {
traceSelectionChanged(box);
});
boxes.push_back(box);
layout->addRow(label, box);
if(skip.count(i*num_ports + j)) {
label->setVisible(false);
box->setVisible(false);
}
}
}
setInitialChoices(); setInitialChoices();
} }
std::vector<Trace*> SparamTraceSelector::getTraces() SparamTraceSelector::SparamTraceSelector(const TraceModel &model, std::set<int> used_ports, bool empty_allowed)
: model(model),
empty_allowed(empty_allowed)
{ {
vector<Trace*> ret; // create vector from set
for(auto b : boxes) { std::copy(used_ports.begin(), used_ports.end(), std::back_inserter(this->used_ports));
if(b->currentIndex() == 0) { createGUI();
ret.push_back(nullptr); setInitialChoices();
} else { }
auto trace = qvariant_cast<Trace*>(b->itemData(b->currentIndex()));
ret.push_back(trace); std::map<QString, Trace*> SparamTraceSelector::getTraces()
{
std::map<QString, Trace*> ret;
for(unsigned int i=0;i<used_ports.size();i++) {
for(unsigned int j=0;j<used_ports.size();j++) {
auto b = boxes[i*used_ports.size()+j];
Trace *t;
if(b->currentIndex() == 0) {
t = nullptr;
} else {
t = qvariant_cast<Trace*>(b->itemData(b->currentIndex()));
}
QString name = "S"+QString::number(used_ports[i])+QString::number(used_ports[j]);
ret[name] = t;
} }
} }
return ret; return ret;
@ -48,7 +45,7 @@ std::vector<Trace*> SparamTraceSelector::getTraces()
void SparamTraceSelector::setInitialChoices() void SparamTraceSelector::setInitialChoices()
{ {
for(unsigned int i=0;i<num_ports*num_ports;i++) { for(unsigned int i=0;i<used_ports.size()*used_ports.size();i++) {
boxes[i]->blockSignals(true); boxes[i]->blockSignals(true);
boxes[i]->clear(); boxes[i]->clear();
boxes[i]->addItem("None"); boxes[i]->addItem("None");
@ -61,7 +58,7 @@ void SparamTraceSelector::setInitialChoices()
// can't select empty traces // can't select empty traces
continue; continue;
} }
bool reflectionRequired = i%(num_ports+1) == 0 ? true : false; bool reflectionRequired = i%(used_ports.size()+1) == 0 ? true : false;
if(reflectionRequired != t->isReflection()) { if(reflectionRequired != t->isReflection()) {
// invalid S parameter // invalid S parameter
continue; continue;
@ -106,7 +103,7 @@ void SparamTraceSelector::traceSelectionChanged(QComboBox *cb)
text.chop(2); text.chop(2);
if(text.endsWith("S")) { if(text.endsWith("S")) {
// tracename ended in Sxx, probably other traces with matching prefix available // tracename ended in Sxx, probably other traces with matching prefix available
for(unsigned int i=0;i<num_ports*num_ports;i++) { for(unsigned int i=0;i<used_ports.size()*used_ports.size();i++) {
auto b = boxes[i]; auto b = boxes[i];
if(b == cb) { if(b == cb) {
// skip this box // skip this box
@ -115,7 +112,7 @@ void SparamTraceSelector::traceSelectionChanged(QComboBox *cb)
for(int j=0;j<b->count();j++) { for(int j=0;j<b->count();j++) {
auto candidate = b->itemText(j); auto candidate = b->itemText(j);
// check if correct parameter // check if correct parameter
QString expectedSparam = QString::number(i/num_ports+1)+QString::number(i%num_ports+1); QString expectedSparam = QString::number(i/used_ports.size()+1)+QString::number(i%used_ports.size()+1);
if(!candidate.endsWith(expectedSparam)) { if(!candidate.endsWith(expectedSparam)) {
// wrong S parameter, skip // wrong S parameter, skip
continue; continue;
@ -170,3 +167,21 @@ void SparamTraceSelector::traceSelectionChanged(QComboBox *cb)
emit selectionValid(valid); emit selectionValid(valid);
} }
} }
void SparamTraceSelector::createGUI()
{
// Create comboboxes
auto layout = new QFormLayout;
setLayout(layout);
for(unsigned int i=0;i<used_ports.size();i++) {
for(unsigned int j=0;j<used_ports.size();j++) {
auto label = new QLabel("S"+QString::number(used_ports[i])+QString::number(used_ports[j])+":");
auto box = new QComboBox();
connect(box, qOverload<int>(&QComboBox::currentIndexChanged), [=](int) {
traceSelectionChanged(box);
});
boxes.push_back(box);
layout->addRow(label, box);
}
}
}

View File

@ -3,6 +3,8 @@
#include "tracemodel.h" #include "tracemodel.h"
#include <vector>
#include <map>
#include <QWidget> #include <QWidget>
#include <QComboBox> #include <QComboBox>
@ -11,12 +13,13 @@ class SparamTraceSelector : public QWidget
Q_OBJECT Q_OBJECT
public: public:
SparamTraceSelector(const TraceModel &model, unsigned int num_ports, bool empty_allowed = false, std::set<unsigned int> skip = {}); SparamTraceSelector(const TraceModel &model, std::vector<int> used_ports, bool empty_allowed = false);
SparamTraceSelector(const TraceModel &model, std::set<int> used_ports, bool empty_allowed = false);
bool isValid(); bool isValid();
std::vector<Trace*> getTraces(); std::map<QString, Trace*> getTraces();
unsigned int getPoints() { return points;}; unsigned int getPoints() { return points;}
signals: signals:
void selectionValid(bool valid); void selectionValid(bool valid);
@ -24,12 +27,13 @@ signals:
private: private:
void setInitialChoices(); void setInitialChoices();
void traceSelectionChanged(QComboBox *cb); void traceSelectionChanged(QComboBox *cb);
void createGUI();
const TraceModel &model; const TraceModel &model;
std::vector<QComboBox*> boxes; std::vector<QComboBox*> boxes;
unsigned int num_ports;
bool empty_allowed; bool empty_allowed;
std::vector<int> used_ports;
unsigned int points; unsigned int points;
double minFreq, maxFreq; double minFreq, maxFreq;
bool valid; bool valid;

View File

@ -260,24 +260,24 @@ QString Trace::fillFromCSV(CSV &csv, unsigned int parameter)
return lastTraceName; return lastTraceName;
} }
void Trace::fillFromDatapoints(Trace &S11, Trace &S12, Trace &S21, Trace &S22, const std::vector<VirtualDevice::VNAMeasurement> &data) void Trace::fillFromDatapoints(std::map<QString, Trace *> traceSet, const std::vector<VirtualDevice::VNAMeasurement> &data)
{ {
S11.clear(); // remove all previous points
S12.clear(); for(auto m : traceSet) {
S21.clear(); m.second->clear();
S22.clear(); }
// add new points to traces
for(auto d : data) { for(auto d : data) {
Trace::Data td; Trace::Data td;
auto S = d.toSparam(1, 2); auto S = d.toSparam(1, 2);
td.x = d.frequency; td.x = d.frequency;
td.y = S.m11; for(auto m : d.measurements) {
S11.addData(td, DataType::Frequency); td.y = m.second;
td.y = S.m12; QString measurement = m.first;
S12.addData(td, DataType::Frequency); if(traceSet.count(measurement)) {
td.y = S.m21; traceSet[measurement]->addData(td, DataType::Frequency);
S21.addData(td, DataType::Frequency); }
td.y = S.m22; }
S22.addData(td, DataType::Frequency);
} }
} }
@ -894,20 +894,16 @@ std::vector<Trace *> Trace::createFromCSV(CSV &csv)
return traces; return traces;
} }
std::vector<VirtualDevice::VNAMeasurement> Trace::assembleDatapoints(const Trace &S11, const Trace &S12, const Trace &S21, const Trace &S22) std::vector<VirtualDevice::VNAMeasurement> Trace::assembleDatapoints(std::map<QString, Trace *> traceSet)
{ {
vector<VirtualDevice::VNAMeasurement> ret; vector<VirtualDevice::VNAMeasurement> ret;
// Sanity check traces // Sanity check traces
unsigned int samples = S11.size(); unsigned int samples = traceSet.begin()->second->size();
auto impedance = S11.getReferenceImpedance(); auto impedance = traceSet.begin()->second->getReferenceImpedance();
vector<const Trace*> traces;
traces.push_back(&S11);
traces.push_back(&S12);
traces.push_back(&S21);
traces.push_back(&S22);
vector<double> freqs; vector<double> freqs;
for(const auto t : traces) { for(auto m : traceSet) {
const Trace *t = m.second;
if(t->size() != samples) { if(t->size() != samples) {
qWarning() << "Selected traces do not have the same size"; qWarning() << "Selected traces do not have the same size";
return ret; return ret;
@ -939,10 +935,11 @@ std::vector<VirtualDevice::VNAMeasurement> Trace::assembleDatapoints(const Trace
// Checks passed, assemble datapoints // Checks passed, assemble datapoints
for(unsigned int i=0;i<samples;i++) { for(unsigned int i=0;i<samples;i++) {
VirtualDevice::VNAMeasurement d; VirtualDevice::VNAMeasurement d;
d.measurements["S11"] = S11.sample(i).y; for(auto m : traceSet) {
d.measurements["S12"] = S12.sample(i).y; QString measurement = m.first;
d.measurements["S21"] = S21.sample(i).y; const Trace *t = m.second;
d.measurements["S22"] = S22.sample(i).y; d.measurements[measurement] = t->sample(i).y;
}
d.pointNum = i; d.pointNum = i;
d.frequency = freqs[i]; d.frequency = freqs[i];
ret.push_back(d); ret.push_back(d);

View File

@ -49,7 +49,7 @@ public:
void setVelocityFactor(double v); void setVelocityFactor(double v);
void fillFromTouchstone(Touchstone &t, unsigned int parameter); void fillFromTouchstone(Touchstone &t, unsigned int parameter);
QString fillFromCSV(CSV &csv, unsigned int parameter); // returns the suggested trace name (not yet set in member data) QString fillFromCSV(CSV &csv, unsigned int parameter); // returns the suggested trace name (not yet set in member data)
static void fillFromDatapoints(Trace &S11, Trace &S12, Trace &S21, Trace &S22, const std::vector<VirtualDevice::VNAMeasurement> &data); static void fillFromDatapoints(std::map<QString, Trace*> traceSet, const std::vector<VirtualDevice::VNAMeasurement> &data);
void fromLivedata(LivedataType type, QString param); void fromLivedata(LivedataType type, QString param);
void fromMath(); void fromMath();
QString name() { return _name; } QString name() { return _name; }
@ -137,7 +137,7 @@ public:
// Assembles datapoints as received from the VNA from four S parameter traces. Requires that all traces are in the frequency domain, // Assembles datapoints as received from the VNA from four S parameter traces. Requires that all traces are in the frequency domain,
// have the same number of samples and their samples must be at the same frequencies across all traces // have the same number of samples and their samples must be at the same frequencies across all traces
static std::vector<VirtualDevice::VNAMeasurement> assembleDatapoints(const Trace &S11, const Trace &S12, const Trace &S21, const Trace &S22); static std::vector<VirtualDevice::VNAMeasurement> assembleDatapoints(std::map<QString, Trace *> traceSet);
static LivedataType TypeFromString(QString s); static LivedataType TypeFromString(QString s);
static QString TypeToString(LivedataType t); static QString TypeToString(LivedataType t);

View File

@ -232,7 +232,7 @@ void TracePolarChart::draw(QPainter &p) {
} }
if(dropPending) { if(dropPending) {
// TODO adjust coords due to shifted restore // adjust coords due to shifted restore
p.setOpacity(0.5); p.setOpacity(0.5);
p.setBrush(Qt::white); p.setBrush(Qt::white);
p.setPen(Qt::white); p.setPen(Qt::white);

View File

@ -328,7 +328,7 @@ void TraceSmithChart::draw(QPainter &p) {
} }
} }
if(dropPending) { if(dropPending) {
// TODO adjust coords due to shifted restore // adjust coords due to shifted restore
p.setOpacity(0.5); p.setOpacity(0.5);
p.setBrush(Qt::white); p.setBrush(Qt::white);
p.setPen(Qt::white); p.setPen(Qt::white);

View File

@ -30,7 +30,7 @@ void Deembedding::measurementCompleted()
measurementUI = nullptr; measurementUI = nullptr;
} }
void Deembedding::startMeasurementDialog(bool S11, bool S12, bool S21, bool S22) void Deembedding::startMeasurementDialog(DeembeddingOption *option)
{ {
measurements.clear(); measurements.clear();
measurementDialog = new QDialog; measurementDialog = new QDialog;
@ -42,20 +42,7 @@ void Deembedding::startMeasurementDialog(bool S11, bool S12, bool S21, bool S22)
}); });
// add the trace selector // add the trace selector
set<unsigned int> skip; auto traceChooser = new SparamTraceSelector(tm, option->getAffectedPorts());
if(!S11) {
skip.insert(0);
}
if(!S12) {
skip.insert(1);
}
if(!S21) {
skip.insert(2);
}
if(!S22) {
skip.insert(3);
}
auto traceChooser = new SparamTraceSelector(tm, 2, false, skip);
ui->horizontalLayout_2->insertWidget(0, traceChooser, 1); ui->horizontalLayout_2->insertWidget(0, traceChooser, 1);
connect(traceChooser, &SparamTraceSelector::selectionValid, ui->buttonBox, &QDialogButtonBox::setEnabled); connect(traceChooser, &SparamTraceSelector::selectionValid, ui->buttonBox, &QDialogButtonBox::setEnabled);
@ -70,33 +57,8 @@ void Deembedding::startMeasurementDialog(bool S11, bool S12, bool S21, bool S22)
connect(ui->buttonBox, &QDialogButtonBox::accepted, [=](){ connect(ui->buttonBox, &QDialogButtonBox::accepted, [=](){
// create datapoints from individual traces // create datapoints from individual traces
measurements.clear(); measurements.clear();
auto t = traceChooser->getTraces(); auto points = Trace::assembleDatapoints(traceChooser->getTraces());
auto S11 = t[0]; for(auto p : points) {
auto S12 = t[1];
auto S21 = t[2];
auto S22 = t[3];
for(unsigned int i=0;i<traceChooser->getPoints();i++) {
VirtualDevice::VNAMeasurement p;
p.pointNum = i;
p.Z0 = 0;
p.dBm = 0;
Sparam S;
if(S11) {
S.m11 = S11->sample(i).y;
p.frequency = S11->sample(i).x;
}
if(S12) {
S.m12 = S12->sample(i).y;
p.frequency = S11->sample(i).x;
}
if(S21) {
S.m21 = S21->sample(i).y;
p.frequency = S11->sample(i).x;
}
if(S22) {
S.m22 = S22->sample(i).y;
p.frequency = S11->sample(i).x;
}
measurements.push_back(p); measurements.push_back(p);
} }
measurementCompleted(); measurementCompleted();
@ -151,15 +113,15 @@ void Deembedding::Deembed(VirtualDevice::VNAMeasurement &d)
} }
} }
void Deembedding::Deembed(Trace &S11, Trace &S12, Trace &S21, Trace &S22) void Deembedding::Deembed(std::map<QString, Trace *> traceSet)
{ {
auto points = Trace::assembleDatapoints(S11, S12, S21, S22); auto points = Trace::assembleDatapoints(traceSet);
if(points.size()) { if(points.size()) {
// succeeded in assembling datapoints // succeeded in assembling datapoints
for(auto &p : points) { for(auto &p : points) {
Deembed(p); Deembed(p);
} }
Trace::fillFromDatapoints(S11, S12, S21, S22, points); Trace::fillFromDatapoints(traceSet, points);
} }
} }
@ -184,9 +146,9 @@ void Deembedding::addOption(DeembeddingOption *option)
options.erase(pos); options.erase(pos);
} }
}); });
connect(option, &DeembeddingOption::triggerMeasurement, [=](bool S11, bool S12, bool S21, bool S22) { connect(option, &DeembeddingOption::triggerMeasurement, [=]() {
measuringOption = option; measuringOption = option;
startMeasurementDialog(S11, S12, S21, S22); startMeasurementDialog(option);
}); });
emit optionAdded(); emit optionAdded();
} }
@ -199,6 +161,16 @@ void Deembedding::swapOptions(unsigned int index)
std::swap(options[index], options[index+1]); std::swap(options[index], options[index+1]);
} }
std::set<int> Deembedding::getAffectedPorts()
{
set<int> ret;
for(auto o : options) {
auto affected = o->getAffectedPorts();
ret.insert(affected.begin(), affected.end());
}
return ret;
}
nlohmann::json Deembedding::toJSON() nlohmann::json Deembedding::toJSON()
{ {
nlohmann::json list; nlohmann::json list;

View File

@ -6,6 +6,8 @@
#include "Traces/tracemodel.h" #include "Traces/tracemodel.h"
#include <vector> #include <vector>
#include <map>
#include <QObject> #include <QObject>
#include <QDialog> #include <QDialog>
#include <QComboBox> #include <QComboBox>
@ -20,11 +22,14 @@ public:
~Deembedding(){} ~Deembedding(){}
void Deembed(VirtualDevice::VNAMeasurement &d); void Deembed(VirtualDevice::VNAMeasurement &d);
void Deembed(Trace &S11, Trace &S12, Trace &S21, Trace &S22); void Deembed(std::map<QString, Trace*> traceSet);
void removeOption(unsigned int index); void removeOption(unsigned int index);
void addOption(DeembeddingOption* option); void addOption(DeembeddingOption* option);
void swapOptions(unsigned int index); void swapOptions(unsigned int index);
std::set<int> getAffectedPorts();
std::vector<DeembeddingOption*>& getOptions() {return options;} std::vector<DeembeddingOption*>& getOptions() {return options;}
nlohmann::json toJSON() override; nlohmann::json toJSON() override;
void fromJSON(nlohmann::json j) override; void fromJSON(nlohmann::json j) override;
@ -36,7 +41,7 @@ signals:
void allOptionsCleared(); void allOptionsCleared();
private: private:
void measurementCompleted(); void measurementCompleted();
void startMeasurementDialog(bool S11, bool S12, bool S21, bool S22); void startMeasurementDialog(DeembeddingOption *option);
std::vector<DeembeddingOption*> options; std::vector<DeembeddingOption*> options;
DeembeddingOption *measuringOption; DeembeddingOption *measuringOption;
TraceModel &tm; TraceModel &tm;

View File

@ -23,6 +23,7 @@ public:
static DeembeddingOption *create(Type type); static DeembeddingOption *create(Type type);
static QString getName(Type type); static QString getName(Type type);
virtual std::set<int> getAffectedPorts() = 0;
virtual void transformDatapoint(VirtualDevice::VNAMeasurement &p) = 0; virtual void transformDatapoint(VirtualDevice::VNAMeasurement &p) = 0;
virtual void edit(){} virtual void edit(){}
virtual Type getType() = 0; virtual Type getType() = 0;
@ -33,7 +34,7 @@ signals:
// Deembedding option may selfdestruct if not applicable with current settings. It should emit this signal before deleting itself // Deembedding option may selfdestruct if not applicable with current settings. It should emit this signal before deleting itself
void deleted(DeembeddingOption *option); void deleted(DeembeddingOption *option);
void triggerMeasurement(bool S11 = true, bool S12 = true, bool S21 = true, bool S22 = true); void triggerMeasurement();
}; };
#endif // DEEMBEDDING_H #endif // DEEMBEDDING_H

View File

@ -15,6 +15,15 @@ ImpedanceRenormalization::ImpedanceRenormalization()
} }
std::set<int> ImpedanceRenormalization::getAffectedPorts()
{
set<int> ret;
for(int i=1;i<=VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;i++) {
ret.insert(i);
}
return ret;
}
void ImpedanceRenormalization::transformDatapoint(VirtualDevice::VNAMeasurement &p) void ImpedanceRenormalization::transformDatapoint(VirtualDevice::VNAMeasurement &p)
{ {
std::map<QString, std::complex<double>> transformed; std::map<QString, std::complex<double>> transformed;

View File

@ -13,6 +13,7 @@ class ImpedanceRenormalization : public DeembeddingOption
public: public:
ImpedanceRenormalization(); ImpedanceRenormalization();
std::set<int> getAffectedPorts() override;
void transformDatapoint(VirtualDevice::VNAMeasurement &p) override; void transformDatapoint(VirtualDevice::VNAMeasurement &p) override;
Type getType() override { return Type::ImpedanceRenormalization;} Type getType() override { return Type::ImpedanceRenormalization;}
nlohmann::json toJSON() override; nlohmann::json toJSON() override;

View File

@ -7,13 +7,12 @@ ManualDeembeddingDialog::ManualDeembeddingDialog(const TraceModel &model, Deembe
ui(new Ui::ManualDeembeddingDialog) ui(new Ui::ManualDeembeddingDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
auto traceSelector = new SparamTraceSelector(model, 2); auto traceSelector = new SparamTraceSelector(model, deemb->getAffectedPorts());
ui->verticalLayout->insertWidget(1, traceSelector, 1.0); ui->verticalLayout->insertWidget(1, traceSelector, 1.0);
ui->buttonBox->setEnabled(false); ui->buttonBox->setEnabled(false);
connect(traceSelector, &SparamTraceSelector::selectionValid, ui->buttonBox, &QDialogButtonBox::setEnabled); connect(traceSelector, &SparamTraceSelector::selectionValid, ui->buttonBox, &QDialogButtonBox::setEnabled);
connect(ui->buttonBox, &QDialogButtonBox::accepted, [=]() { connect(ui->buttonBox, &QDialogButtonBox::accepted, [=]() {
auto t = traceSelector->getTraces(); deemb->Deembed(traceSelector->getTraces());
deemb->Deembed(*t[0], *t[1], *t[2], *t[3]);
accept(); accept();
}); });
} }

View File

@ -27,6 +27,11 @@ MatchingNetwork::MatchingNetwork()
port = 1; port = 1;
} }
std::set<int> MatchingNetwork::getAffectedPorts()
{
return {port};
}
void MatchingNetwork::transformDatapoint(VirtualDevice::VNAMeasurement &p) void MatchingNetwork::transformDatapoint(VirtualDevice::VNAMeasurement &p)
{ {
auto S = p.toSparam(1, 2); auto S = p.toSparam(1, 2);
@ -106,12 +111,12 @@ void MatchingNetwork::edit()
p1->setMinimumSize(portWidth, 151); p1->setMinimumSize(portWidth, 151);
p1->setMaximumSize(portWidth, 151); p1->setMaximumSize(portWidth, 151);
p1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); p1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
p1->setStyleSheet("image: url(:/icons/port1.png);"); p1->setStyleSheet("image: url(:/icons/port.png);");
auto DUT = new QWidget(); auto DUT = new QWidget();
DUT->setMinimumSize(DUTWidth, 151); DUT->setMinimumSize(DUTWidth, 151);
DUT->setMaximumSize(DUTWidth, 151); DUT->setMaximumSize(DUTWidth, 151);
DUT->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); DUT->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
DUT->setStyleSheet("image: url(:/icons/DUT.png);"); DUT->setStyleSheet("image: url(:/icons/DUT_onePort.png);");
layout->addWidget(p1); layout->addWidget(p1);
for(auto w : network) { for(auto w : network) {

View File

@ -64,6 +64,7 @@ public:
// DeembeddingOption interface // DeembeddingOption interface
public: public:
std::set<int> getAffectedPorts() override;
void transformDatapoint(VirtualDevice::VNAMeasurement &p) override; void transformDatapoint(VirtualDevice::VNAMeasurement &p) override;
void edit() override; void edit() override;
Type getType() override {return Type::MatchingNetwork;} Type getType() override {return Type::MatchingNetwork;}

View File

@ -24,6 +24,11 @@ PortExtension::PortExtension()
kit = nullptr; kit = nullptr;
} }
std::set<int> PortExtension::getAffectedPorts()
{
return {port};
}
void PortExtension::transformDatapoint(VirtualDevice::VNAMeasurement &d) void PortExtension::transformDatapoint(VirtualDevice::VNAMeasurement &d)
{ {
auto phase = -2 * M_PI * ext.delay * d.frequency; auto phase = -2 * M_PI * ext.delay * d.frequency;
@ -72,6 +77,8 @@ void PortExtension::edit()
ui->DCloss->setValue(ext.DCloss); ui->DCloss->setValue(ext.DCloss);
ui->Loss->setValue(ext.loss); ui->Loss->setValue(ext.loss);
ui->Frequency->setValue(ext.frequency); ui->Frequency->setValue(ext.frequency);
ui->port->setValue(port);
ui->port->setMaximum(VirtualDevice::getInfo(VirtualDevice::getConnected()).ports);
if(!kit) { if(!kit) {
ui->calkit->setEnabled(false); ui->calkit->setEnabled(false);
} }
@ -97,6 +104,9 @@ void PortExtension::edit()
ui->Time->setValueQuiet(ui->Distance->value() / (newval * c)); ui->Time->setValueQuiet(ui->Distance->value() / (newval * c));
updateValuesFromUI(); updateValuesFromUI();
}); });
connect(ui->port, qOverload<int>(&QSpinBox::valueChanged), [=](){
port = ui->port->value();
});
connect(ui->DCloss, &SIUnitEdit::valueChanged, updateValuesFromUI); connect(ui->DCloss, &SIUnitEdit::valueChanged, updateValuesFromUI);
connect(ui->Loss, &SIUnitEdit::valueChanged, updateValuesFromUI); connect(ui->Loss, &SIUnitEdit::valueChanged, updateValuesFromUI);
connect(ui->Frequency, &SIUnitEdit::valueChanged, updateValuesFromUI); connect(ui->Frequency, &SIUnitEdit::valueChanged, updateValuesFromUI);

View File

@ -18,6 +18,7 @@ class PortExtension : public DeembeddingOption
Q_OBJECT Q_OBJECT
public: public:
PortExtension(); PortExtension();
std::set<int> getAffectedPorts() override;
void transformDatapoint(VirtualDevice::VNAMeasurement& d) override; void transformDatapoint(VirtualDevice::VNAMeasurement& d) override;
void setCalkit(Calkit *kit); void setCalkit(Calkit *kit);
Type getType() override {return Type::PortExtension;} Type getType() override {return Type::PortExtension;}

View File

@ -17,6 +17,11 @@ TwoThru::TwoThru()
port2 = 2; port2 = 2;
} }
std::set<int> TwoThru::getAffectedPorts()
{
return {port1, port2};
}
void TwoThru::transformDatapoint(VirtualDevice::VNAMeasurement &p) void TwoThru::transformDatapoint(VirtualDevice::VNAMeasurement &p)
{ {
// correct measurement // correct measurement

View File

@ -16,6 +16,7 @@ class TwoThru : public DeembeddingOption
public: public:
TwoThru(); TwoThru();
std::set<int> getAffectedPorts() override;
virtual void transformDatapoint(VirtualDevice::VNAMeasurement& p) override; virtual void transformDatapoint(VirtualDevice::VNAMeasurement& p) override;
virtual void edit() override; virtual void edit() override;
virtual Type getType() override {return DeembeddingOption::Type::TwoThru;} virtual Type getType() override {return DeembeddingOption::Type::TwoThru;}

View File

@ -20,7 +20,7 @@
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>You imported a two-port touchstone file, do you want to apply the currently active calibration or de-embed the data?</string> <string>You imported a touchstone file, do you want to apply the currently active calibration or de-embed the data?</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>

View File

@ -55,6 +55,7 @@ void TraceWidgetVNA::importDialog()
if (!filename.isEmpty()) { if (!filename.isEmpty()) {
try { try {
std::vector<Trace*> traces; std::vector<Trace*> traces;
int touchstonePorts = 0;
QString prefix = QString(); QString prefix = QString();
if(filename.endsWith(".csv")) { if(filename.endsWith(".csv")) {
auto csv = CSV::fromFile(filename); auto csv = CSV::fromFile(filename);
@ -63,6 +64,7 @@ void TraceWidgetVNA::importDialog()
// must be a touchstone file // must be a touchstone file
auto t = Touchstone::fromFile(filename.toStdString()); auto t = Touchstone::fromFile(filename.toStdString());
traces = Trace::createFromTouchstone(t); traces = Trace::createFromTouchstone(t);
touchstonePorts = t.ports();
} }
// contruct prefix from filename // contruct prefix from filename
prefix = filename; prefix = filename;
@ -78,44 +80,51 @@ void TraceWidgetVNA::importDialog()
if(AppWindow::showGUI()) { if(AppWindow::showGUI()) {
i->show(); i->show();
} }
if(filename.endsWith(".s2p")) { // potential candidate to process via calibration/de-embedding
// potential candidate to process via calibration/de-embedding connect(i, &TraceImportDialog::importFinsished, [=](const std::vector<Trace*> &traces) {
connect(i, &TraceImportDialog::importFinsished, [=](const std::vector<Trace*> &traces) { if(traces.size() == touchstonePorts*touchstonePorts) {
if(traces.size() == 4) { // all traces imported, can calculate calibration/de-embedding
// all traces imported, can calculate calibration/de-embedding bool calAvailable = cal.getNumPoints() > 0;
bool calAvailable = cal.getNumPoints() > 0; bool deembedAvailable = deembed.getOptions().size() > 0;
bool deembedAvailable = deembed.getOptions().size() > 0; if(calAvailable || deembedAvailable) {
if(calAvailable || deembedAvailable) { // check if user wants to apply either one to the imported traces
// check if user wants to apply either one to the imported traces auto dialog = new QDialog();
auto dialog = new QDialog(); auto ui = new Ui::s2pImportOptions;
auto ui = new Ui::s2pImportOptions; ui->setupUi(dialog);
ui->setupUi(dialog); connect(dialog, &QDialog::finished, [=](){
connect(dialog, &QDialog::finished, [=](){ delete ui;
delete ui; });
}); ui->applyCal->setEnabled(calAvailable);
ui->applyCal->setEnabled(calAvailable); ui->deembed->setEnabled(deembedAvailable);
ui->deembed->setEnabled(deembedAvailable); bool applyCal = false;
bool applyCal = false; bool applyDeembed = false;
bool applyDeembed = false; connect(ui->applyCal, &QCheckBox::toggled, [&](bool checked) {
connect(ui->applyCal, &QCheckBox::toggled, [&](bool checked) { applyCal = checked;
applyCal = checked; });
}); connect(ui->deembed, &QCheckBox::toggled, [&](bool checked) {
connect(ui->deembed, &QCheckBox::toggled, [&](bool checked) { applyDeembed = checked;
applyDeembed = checked; });
}); if(AppWindow::showGUI()) {
if(AppWindow::showGUI()) { dialog->exec();
dialog->exec(); }
} // assemble trace set
if(applyCal) { std::map<QString, Trace*> set;
// cal.correctTraces(*traces[0], *traces[1], *traces[2], *traces[3]); // TODO for(int i=1;i<=touchstonePorts;i++) {
} for(int j=1;j<=touchstonePorts;j++) {
if(applyDeembed) { QString name = "S"+QString::number(i)+QString::number(j);
deembed.Deembed(*traces[0], *traces[1], *traces[2], *traces[3]); int index = (i-1)*touchstonePorts+(j-1);
set[name] = traces[index];
} }
} }
if(applyCal) {
cal.correctTraces(set);
}
if(applyDeembed) {
deembed.Deembed(set);
}
} }
}); }
} });
} catch(const std::exception& e) { } catch(const std::exception& e) {
InformationBox::ShowError("Failed to import file", QString("Attempt to import file ended with error: \"") + e.what()+"\""); InformationBox::ShowError("Failed to import file", QString("Attempt to import file ended with error: \"") + e.what()+"\"");
} }

View File

@ -573,8 +573,23 @@ void AppWindow::SetupSCPI()
if(!vdevice) { if(!vdevice) {
return QString("0/0/0"); return QString("0/0/0");
} else if(vdevice->isCompoundDevice()) { } else if(vdevice->isCompoundDevice()) {
// TODO // show highest temperature of all devices
return QString(); int maxTempSource = 0;
int maxTempLO = 0;
int maxTempMCU = 0;
for(auto dev : vdevice->getDevices()) {
auto status = dev->StatusV1();
if(status.temp_source > maxTempSource) {
maxTempSource = status.temp_source;
}
if(status.temp_LO1 > maxTempLO) {
maxTempLO = status.temp_LO1;
}
if(status.temp_MCU > maxTempMCU) {
maxTempMCU = status.temp_MCU;
}
}
return QString::number(maxTempSource)+"/"+QString::number(maxTempLO)+"/"+QString::number(maxTempMCU);
} else { } else {
auto dev = vdevice->getDevice(); auto dev = vdevice->getDevice();
return QString::number(dev->StatusV1().temp_source)+"/"+QString::number(dev->StatusV1().temp_LO1)+"/"+QString::number(dev->StatusV1().temp_MCU); return QString::number(dev->StatusV1().temp_source)+"/"+QString::number(dev->StatusV1().temp_LO1)+"/"+QString::number(dev->StatusV1().temp_MCU);

View File

@ -67,5 +67,7 @@
<file>icons/compound_V1_Ref_Middle.png</file> <file>icons/compound_V1_Ref_Middle.png</file>
<file>icons/compound_V1_Ref_Right.png</file> <file>icons/compound_V1_Ref_Right.png</file>
<file>icons/compound_V1_USB.png</file> <file>icons/compound_V1_USB.png</file>
<file>icons/DUT_onePort.png</file>
<file>icons/port.png</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 909 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB