WIP: flexible calibration measurements

This commit is contained in:
Jan Käberich 2022-08-27 15:28:45 +02:00
parent b442736cb5
commit 6e38aaddb8
16 changed files with 933 additions and 17 deletions

View File

@ -0,0 +1,84 @@
#include "calibration2.h"
#include "ui_calibrationdialogui.h"
#include <QDialog>
#include <QMenu>
using namespace std;
Calibration2::Calibration2()
{
}
void Calibration2::edit()
{
auto d = new QDialog();
auto ui = new Ui::CalibrationDialog;
ui->setupUi(d);
QObject::connect(ui->bDelete, &QPushButton::clicked, [=](){
auto row = ui->table->currentRow();
if(row >= 0) {
delete measurements[row];
measurements.erase(measurements.begin() + row);
// updateMeasurementTable();
}
});
QObject::connect(ui->bMoveUp, &QPushButton::clicked, [=](){
auto row = ui->table->currentRow();
if(row >= 1) {
swap(measurements[row], measurements[row-1]);
ui->table->selectRow(row-1);
// updateMeasurementTable();
}
});
QObject::connect(ui->bMoveDown, &QPushButton::clicked, [=](){
auto row = ui->table->currentRow();
if(row >= 1) {
swap(measurements[row], measurements[row-1]);
ui->table->selectRow(row+1);
// updateMeasurementTable();
}
});
// connect(ui->table, &QTableWidget::currentRowChanged, this, &CalibrationDialog::updateTableEditButtons);
auto addMenu = new QMenu();
for(auto t : CalibrationMeasurement::Base::availableTypes()) {
auto action = new QAction(CalibrationMeasurement::Base::TypeToString(t));
QObject::connect(action, &QAction::triggered, [=](){
auto newMeas = newMeasurement(t);
if(newMeas) {
measurements.push_back(newMeas);
// updateMeasurementTable();
}
});
addMenu->addAction(action);
}
ui->bAdd->setMenu(addMenu);
// updateMeasurementTable();
d->show();
}
CalibrationMeasurement::Base *Calibration2::newMeasurement(CalibrationMeasurement::Base::Type type)
{
CalibrationMeasurement::Base *m = nullptr;
switch(type) {
case CalibrationMeasurement::Base::Type::Open: m = new CalibrationMeasurement::Open(this); break;
case CalibrationMeasurement::Base::Type::Short: m = new CalibrationMeasurement::Short(this); break;
case CalibrationMeasurement::Base::Type::Load: m = new CalibrationMeasurement::Load(this); break;
case CalibrationMeasurement::Base::Type::Through: m = new CalibrationMeasurement::Through(this); break;
}
return m;
}
Calkit &Calibration2::getKit()
{
return kit;
}

View File

@ -0,0 +1,25 @@
#ifndef CALIBRATION2_H
#define CALIBRATION2_H
#include "savable.h"
#include "calibrationmeasurement.h"
#include "calkit.h"
class Calibration2 : public Savable
{
public:
Calibration2();
void edit();
Calkit& getKit();
private:
CalibrationMeasurement::Base *newMeasurement(CalibrationMeasurement::Base::Type type);
std::vector<CalibrationMeasurement::Base*> measurements;
Calkit kit;
};
#endif // CALIBRATION2_H

View File

@ -0,0 +1,247 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CalibrationDialog</class>
<widget class="QDialog" name="CalibrationDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>912</width>
<height>438</height>
</rect>
</property>
<property name="windowTitle">
<string>Calibration Measurements</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Measurements</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Create default measurements for:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox">
<item>
<property name="text">
<string/>
</property>
</item>
<item>
<property name="text">
<string>1 Port SOL calibration</string>
</property>
</item>
<item>
<property name="text">
<string>2 Port SOLT calibration</string>
</property>
</item>
<item>
<property name="text">
<string>3 Port SOLT calibration</string>
</property>
</item>
<item>
<property name="text">
<string>4 Port SOLT calibration</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QTableWidget" name="table"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="bAdd">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Add</string>
</property>
<property name="text">
<string>Add</string>
</property>
<property name="icon">
<iconset theme="list-add" resource="../icons.qrc">
<normaloff>:/icons/add.png</normaloff>:/icons/add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="bDelete">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Delete</string>
</property>
<property name="text">
<string>Delete</string>
</property>
<property name="icon">
<iconset theme="list-remove" resource="../icons.qrc">
<normaloff>:/icons/remove.png</normaloff>:/icons/remove.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="bMoveUp">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move up</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset theme="go-up" resource="../icons.qrc">
<normaloff>:/icons/up.png</normaloff>:/icons/up.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="bMoveDown">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move down</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset theme="go-down" resource="../icons.qrc">
<normaloff>:/icons/down.png</normaloff>:/icons/down.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="measure">
<property name="text">
<string>Measure</string>
</property>
<property name="icon">
<iconset theme="media-playback-start" resource="../icons.qrc">
<normaloff>:/icons/play.png</normaloff>:/icons/play.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clearMeasurement">
<property name="text">
<string>Clear</string>
</property>
<property name="icon">
<iconset theme="edit-delete" resource="../icons.qrc">
<normaloff>:/icons/trash.png</normaloff>:/icons/trash.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>18</width>
<height>186</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../icons.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>CalibrationDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CalibrationDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,331 @@
#include "calibrationmeasurement.h"
#include "unit.h"
#include "calibration2.h"
#include <QDateTime>
using namespace std;
CalibrationMeasurement::Base::Base(Calibration2 *cal)
: cal(cal)
{
standard = nullptr;
timestamp = QDateTime();
}
bool CalibrationMeasurement::Base::setFirstSupportedStandard()
{
// assign first valid standard
for(auto s : cal->getKit().getStandards()) {
if(supportedStandards().count(s->getType())) {
setStandard(s);
break;
}
}
}
bool CalibrationMeasurement::Base::setStandard(CalStandard::Virtual *standard)
{
if(standard) {
if(supportedStandards().count(standard->getType())) {
// can use this standard
this->standard = standard;
return true;
} else {
// can't use this standard, leave unchanged
return false;
}
} else {
// nullptr passed, remove currently used standard
this->standard = nullptr;
return true;
}
}
QString CalibrationMeasurement::Base::getStatistics()
{
if(numPoints() > 0) {
QString data = QString::number(numPoints());
data.append(" points from ");
data.append(Unit::ToString(minFreq(), "Hz", " kMG"));
data.append(" to ");
data.append(Unit::ToString(maxFreq(), "Hz", " kMG"));
return data;
} else {
return "Not available";
}
}
std::vector<CalibrationMeasurement::Base::Type> CalibrationMeasurement::Base::availableTypes()
{
std::vector<Type> ret;
for(int i=0;i<(int) Type::Last;i++) {
ret.push_back((Type) i);
}
return ret;
}
QString CalibrationMeasurement::Base::TypeToString(CalibrationMeasurement::Base::Type type)
{
switch(type) {
case Type::Open: return "Open";
case Type::Short: return "Short";
case Type::Load: return "Load";
case Type::Through: return "Through";
case Type::Last: return "Invalid";
}
}
CalibrationMeasurement::Base::Type CalibrationMeasurement::Base::TypeFromString(QString s)
{
for(int i=0;i<(int) Type::Last;i++) {
if(TypeToString((Type) i) == s) {
return (Type) i;
}
}
return Type::Last;
}
nlohmann::json CalibrationMeasurement::Base::toJSON()
{
nlohmann::json j;
if(standard) {
j["standard"] = standard->getID();
}
j["timestamp"] = timestamp.toSecsSinceEpoch();
return j;
}
void CalibrationMeasurement::Base::fromJSON(nlohmann::json j)
{
if(j.contains("standard")) {
// TODO find standard from ID
}
timestamp = QDateTime::fromSecsSinceEpoch(j.value("timestamp", 0));
}
bool CalibrationMeasurement::Base::canMeasureSimultaneously(std::vector<CalibrationMeasurement::Base *> measurements)
{
std::set<int> usedPorts;
for(auto m : measurements) {
std::vector<int> ports;
switch(m->getType()) {
case Type::Open:
case Type::Short:
case Type::Load:
// Uses one port
ports.push_back(static_cast<OnePort*>(m)->getPort());
break;
case Type::Through:
// Uses two ports
ports.push_back(static_cast<TwoPort*>(m)->getPort1());
ports.push_back(static_cast<TwoPort*>(m)->getPort2());
break;
}
for(auto p : ports) {
if(usedPorts.count(p)) {
// port already used for another measurement
return false;
} else {
usedPorts.insert(p);
}
}
}
// if we get here, no port collisions occurred
return true;
}
double CalibrationMeasurement::OnePort::minFreq()
{
if(points.size() > 0) {
return points.front().frequency;
} else {
return numeric_limits<double>::max();
}
}
double CalibrationMeasurement::OnePort::maxFreq()
{
if(points.size() > 0) {
return points.back().frequency;
} else {
return 0;
}
}
void CalibrationMeasurement::OnePort::clearPoints()
{
points.clear();
timestamp = QDateTime();
}
void CalibrationMeasurement::OnePort::addPoint(const VirtualDevice::VNAMeasurement &m)
{
QString measurementName = "S"+QString::number(port)+QString::number(port);
if(m.measurements.count(measurementName) > 0) {
Point p;
p.frequency = m.frequency;
p.S = m.measurements.at(measurementName);
points.push_back(p);
timestamp = QDateTime::currentDateTimeUtc();
}
}
nlohmann::json CalibrationMeasurement::OnePort::toJSON()
{
auto j = Base::toJSON();
j["port"] = port;
nlohmann::json jpoints;
for(auto &p : points) {
nlohmann::json jpoint;
jpoint["frequency"] = p.frequency;
jpoint["real"] = p.S.real();
jpoint["imag"] = p.S.imag();
jpoints.push_back(jpoint);
}
j["points"] = jpoints;
return j;
}
void CalibrationMeasurement::OnePort::fromJSON(nlohmann::json j)
{
clearPoints();
Base::fromJSON(j);
port = j.value("port", 0);
if(j.contains("points")) {
for(auto jpoint : j["points"]) {
Point p;
p.frequency = jpoint.value("frequency", 0.0);
p.S = complex<double>(jpoint.value("real", 0.0), jpoint.value("imag", 0.0));
points.push_back(p);
}
}
}
std::complex<double> CalibrationMeasurement::OnePort::getMeasured(double frequency)
{
if(points.size() == 0 || frequency < points.front().frequency || frequency > points.back().frequency) {
return numeric_limits<complex<double>>::quiet_NaN();
}
// frequency within points, interpolate
auto lower = lower_bound(points.begin(), points.end(), frequency, [](const Point &lhs, double rhs) -> bool {
return lhs.frequency < rhs;
});
auto lowPoint = *lower;
advance(lower, 1);
auto highPoint = *lower;
double alpha = (frequency - lowPoint.frequency) / (highPoint.frequency - lowPoint.frequency);
complex<double> ret;
return lowPoint.S * (1.0 - alpha) + highPoint.S * alpha;
}
std::complex<double> CalibrationMeasurement::OnePort::getActual(double frequency)
{
return static_cast<CalStandard::OnePort*>(standard)->toS11(frequency);
}
int CalibrationMeasurement::OnePort::getPort() const
{
return port;
}
double CalibrationMeasurement::TwoPort::minFreq()
{
if(points.size() > 0) {
return points.front().frequency;
} else {
return numeric_limits<double>::max();
}
}
double CalibrationMeasurement::TwoPort::maxFreq()
{
if(points.size() > 0) {
return points.back().frequency;
} else {
return 0;
}
}
void CalibrationMeasurement::TwoPort::clearPoints()
{
points.clear();
timestamp = QDateTime();
}
void CalibrationMeasurement::TwoPort::addPoint(const VirtualDevice::VNAMeasurement &m)
{
Point p;
p.frequency = m.frequency;
p.S = m.toSparam(port1, port2);
points.push_back(p);
timestamp = QDateTime::currentDateTimeUtc();
}
nlohmann::json CalibrationMeasurement::TwoPort::toJSON()
{
auto j = Base::toJSON();
j["port1"] = port1;
j["port2"] = port2;
nlohmann::json jpoints;
for(auto &p : points) {
nlohmann::json jpoint;
jpoint["frequency"] = p.frequency;
jpoint["Sparam"] = p.S.toJSON();
jpoints.push_back(jpoint);
}
j["points"] = jpoints;
return j;
}
void CalibrationMeasurement::TwoPort::fromJSON(nlohmann::json j)
{
clearPoints();
Base::fromJSON(j);
port1 = j.value("port1", 0);
port2 = j.value("port2", 0);
if(j.contains("points")) {
for(auto jpoint : j["points"]) {
Point p;
p.frequency = jpoint.value("frequency", 0.0);
p.S.fromJSON(j["Sparam"]);
points.push_back(p);
}
}
}
Sparam CalibrationMeasurement::TwoPort::getMeasured(double frequency)
{
if(points.size() == 0 || frequency < points.front().frequency || frequency > points.back().frequency) {
return Sparam();
}
// frequency within points, interpolate
auto lower = lower_bound(points.begin(), points.end(), frequency, [](const Point &lhs, double rhs) -> bool {
return lhs.frequency < rhs;
});
auto lowPoint = *lower;
advance(lower, 1);
auto highPoint = *lower;
double alpha = (frequency - lowPoint.frequency) / (highPoint.frequency - lowPoint.frequency);
Sparam ret;
ret.m11 = lowPoint.S.m11 * (1.0 - alpha) + highPoint.S.m11 * alpha;
ret.m12 = lowPoint.S.m12 * (1.0 - alpha) + highPoint.S.m12 * alpha;
ret.m21 = lowPoint.S.m21 * (1.0 - alpha) + highPoint.S.m21 * alpha;
ret.m22 = lowPoint.S.m22 * (1.0 - alpha) + highPoint.S.m22 * alpha;
return ret;
}
Sparam CalibrationMeasurement::TwoPort::getActual(double frequency)
{
return static_cast<CalStandard::TwoPort*>(standard)->toSparam(frequency);
}
int CalibrationMeasurement::TwoPort::getPort2() const
{
return port2;
}
int CalibrationMeasurement::TwoPort::getPort1() const
{
return port1;
}

View File

@ -0,0 +1,157 @@
#ifndef CALIBRATIONMEASUREMENT_H
#define CALIBRATIONMEASUREMENT_H
#include "calstandard.h"
#include "Device/virtualdevice.h"
#include <QDateTime>
class Calibration2;
namespace CalibrationMeasurement {
class Base : public Savable
{
public:
Base(Calibration2 *cal);
enum class Type {
Open,
Short,
Load,
Through,
Last,
};
bool setFirstSupportedStandard();
bool setStandard(CalStandard::Virtual *standard);
QString getStatistics();
virtual double minFreq() = 0;
virtual double maxFreq() = 0;
virtual unsigned int numPoints() = 0;
static std::vector<Type> availableTypes();
static QString TypeToString(Type type);
static Type TypeFromString(QString s);
virtual std::set<CalStandard::Virtual::Type> supportedStandards() = 0;
virtual Type getType() = 0;
virtual void clearPoints() = 0;
virtual void addPoint(const VirtualDevice::VNAMeasurement &m) = 0;
virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override;
static bool canMeasureSimultaneously(std::vector<Base*> measurements);
protected:
CalStandard::Virtual *standard;
QDateTime timestamp;
Calibration2 *cal;
};
class OnePort : public Base
{
public:
OnePort(Calibration2 *cal) :
Base(cal),
port(0) {}
virtual double minFreq() override;
virtual double maxFreq() override;
virtual unsigned int numPoints() override {return points.size();}
virtual void clearPoints();
virtual void addPoint(const VirtualDevice::VNAMeasurement &m);
virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override;
std::complex<double> getMeasured(double frequency);
std::complex<double> getActual(double frequency);
int getPort() const;
protected:
int port;
class Point {
public:
double frequency;
std::complex<double> S;
};
std::vector<Point> points;
};
class Open : public OnePort
{
public:
Open(Calibration2 *cal) :
OnePort(cal){setFirstSupportedStandard();}
virtual std::set<CalStandard::Virtual::Type> supportedStandards() override {return {CalStandard::Virtual::Type::Open};}
virtual Type getType() override {return Type::Open;}
};
class Short : public OnePort
{
public:
Short(Calibration2 *cal) :
OnePort(cal){setFirstSupportedStandard();}
virtual std::set<CalStandard::Virtual::Type> supportedStandards() override {return {CalStandard::Virtual::Type::Short};}
virtual Type getType() override {return Type::Short;}
};
class Load : public OnePort
{
public:
Load(Calibration2 *cal) :
OnePort(cal){setFirstSupportedStandard();}
virtual std::set<CalStandard::Virtual::Type> supportedStandards() override {return {CalStandard::Virtual::Type::Load};}
virtual Type getType() override {return Type::Load;}
};
class TwoPort : public Base
{
public:
TwoPort(Calibration2 *cal) :
Base(cal),
port1(0),
port2(0){}
virtual double minFreq() override;
virtual double maxFreq() override;
virtual unsigned int numPoints() override {return points.size();}
virtual void clearPoints();
virtual void addPoint(const VirtualDevice::VNAMeasurement &m);
virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override;
Sparam getMeasured(double frequency);
Sparam getActual(double frequency);
int getPort1() const;
int getPort2() const;
protected:
int port1, port2;
class Point {
public:
double frequency;
Sparam S;
};
std::vector<Point> points;
};
class Through : public TwoPort
{
public:
Through(Calibration2 *cal) :
TwoPort(cal){setFirstSupportedStandard();}
virtual std::set<CalStandard::Virtual::Type> supportedStandards() override {return {CalStandard::Virtual::Type::Through};}
virtual Type getType() override {return Type::Through;}
};
}
#endif // CALIBRATIONMEASUREMENT_H

View File

@ -417,3 +417,8 @@ void Calkit::clearStandards()
}
standards.clear();
}
std::vector<CalStandard::Virtual *> Calkit::getStandards() const
{
return standards;
}

View File

@ -51,6 +51,8 @@ public:
bool checkIfValid(double min_freq, double max_freq, bool isTRL, bool include_male, bool include_female);
bool isTRLReflectionShort() const;
std::vector<CalStandard::Virtual *> getStandards() const;
private:
void clearStandards();
QString manufacturer, serialnumber, description;

View File

@ -4,20 +4,31 @@
#include "ui_CalStandardLoadEditDialog.h"
#include "ui_CalStandardThroughEditDialog.h"
#include "unit.h"
#include "Util/util.h"
using namespace std;
using namespace CalStandard;
Virtual::Virtual(QString name) :
name(name),
minFreq(std::numeric_limits<double>::lowest()),
maxFreq(std::numeric_limits<double>::max())
{
id = Util::random(numeric_limits<unsigned long long>::max());
}
Virtual *Virtual::create(Virtual::Type type)
{
Virtual *ret = nullptr;
switch(type) {
case Type::Open: ret = new Open; break;
case Type::Short: ret = new Short; break;
case Type::Load: ret = new Load; break;
case Type::Through: ret = new Through; break;
case Type::Open: return new Open;
case Type::Short: return new Short;
case Type::Load: return new Load;
case Type::Through: return new Through;
case Type::Line: // TODO
case Type::Last:
break;
}
return ret;
return nullptr;
}
std::vector<Virtual::Type> Virtual::availableTypes()
@ -60,12 +71,19 @@ nlohmann::json Virtual::toJSON()
{
nlohmann::json j;
j["name"] = name.toStdString();
j["id"] = id;
return j;
}
void Virtual::fromJSON(nlohmann::json j)
{
name = QString::fromStdString(j.value("name", ""));
id = j.value("id", id);
}
unsigned long long Virtual::getID()
{
return id;
}
void OnePort::setMeasurement(const Touchstone &ts, int port)

View File

@ -14,10 +14,7 @@ namespace CalStandard
class Virtual : public Savable
{
public:
Virtual(QString name = "") :
name(name),
minFreq(std::numeric_limits<double>::lowest()),
maxFreq(std::numeric_limits<double>::max()){}
Virtual(QString name = "");
enum class Type {
Open,
@ -44,10 +41,13 @@ public:
virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override;
unsigned long long getID();
protected:
QString name;
double minFreq;
double maxFreq;
unsigned long long id;
};
class OnePort : public Virtual

View File

@ -752,13 +752,13 @@ void VirtualDevice::checkIfAllTransmissionsComplete(std::function<void (bool)> c
}
}
Sparam VirtualDevice::VNAMeasurement::toSparam(int port1, int port2)
Sparam VirtualDevice::VNAMeasurement::toSparam(int port1, int port2) const
{
Sparam S;
S.m11 = measurements["S"+QString::number(port1)+QString::number(port1)];
S.m12 = measurements["S"+QString::number(port1)+QString::number(port2)];
S.m21 = measurements["S"+QString::number(port2)+QString::number(port1)];
S.m22 = measurements["S"+QString::number(port2)+QString::number(port2)];
S.m11 = measurements.at("S"+QString::number(port1)+QString::number(port1));
S.m12 = measurements.at("S"+QString::number(port1)+QString::number(port2));
S.m21 = measurements.at("S"+QString::number(port2)+QString::number(port1));
S.m22 = measurements.at("S"+QString::number(port2)+QString::number(port2));
return S;
}

View File

@ -96,7 +96,7 @@ public:
};
std::map<QString, std::complex<double>> measurements;
Sparam toSparam(int port1, int port2);
Sparam toSparam(int port1, int port2) const;
void fromSparam(Sparam S, int port1, int port2);
VNAMeasurement interpolateTo(const VNAMeasurement &to, double a);
};

View File

@ -2,6 +2,8 @@ HEADERS += \
../VNA_embedded/Application/Communication/Protocol.hpp \
Calibration/amplitudecaldialog.h \
Calibration/calibration.h \
Calibration/calibration2.h \
Calibration/calibrationmeasurement.h \
Calibration/calibrationtracedialog.h \
Calibration/calkit.h \
Calibration/calkitdialog.h \
@ -142,6 +144,8 @@ SOURCES += \
../VNA_embedded/Application/Communication/Protocol.cpp \
Calibration/amplitudecaldialog.cpp \
Calibration/calibration.cpp \
Calibration/calibration2.cpp \
Calibration/calibrationmeasurement.cpp \
Calibration/calibrationtracedialog.cpp \
Calibration/calkit.cpp \
Calibration/calkitdialog.cpp \
@ -281,6 +285,7 @@ FORMS += \
Calibration/addamplitudepointsdialog.ui \
Calibration/amplitudecaldialog.ui \
Calibration/automaticamplitudedialog.ui \
Calibration/calibrationdialogui.ui \
Calibration/calibrationtracedialog.ui \
Calibration/calkitdialog.ui \
Calibration/frequencycaldialog.ui \

View File

@ -1,5 +1,7 @@
#include "parameters.h"
using namespace std;
Sparam::Sparam(const Tparam &t) {
m11 = t.m12 / t.m22;
m21 = Type(1) / t.m22;
@ -41,3 +43,25 @@ ABCDparam::ABCDparam(const Sparam &s, Type Z0)
: ABCDparam(s, Z0, Z0)
{
}
nlohmann::json Parameters::toJSON()
{
nlohmann::json j;
j["m11_real"] = m11.real();
j["m11_imag"] = m11.imag();
j["m12_real"] = m12.real();
j["m12_imag"] = m12.imag();
j["m21_real"] = m21.real();
j["m21_imag"] = m21.imag();
j["m22_real"] = m22.real();
j["m22_imag"] = m22.imag();
return j;
}
void Parameters::fromJSON(nlohmann::json j)
{
m11 = complex<double>(j.value("m11_real", 0.0), j.value("m11_imag", 0.0));
m12 = complex<double>(j.value("m12_real", 0.0), j.value("m12_imag", 0.0));
m21 = complex<double>(j.value("m21_real", 0.0), j.value("m21_imag", 0.0));
m22 = complex<double>(j.value("m22_real", 0.0), j.value("m22_imag", 0.0));
}

View File

@ -1,17 +1,22 @@
#ifndef TPARAM_H
#define TPARAM_H
#include "savable.h"
#include <complex>
using Type = std::complex<double>;
class Parameters {
class Parameters : public Savable {
public:
Parameters(Type m11, Type m12, Type m21, Type m22)
: m11(m11), m12(m12), m21(m21), m22(m22){}
Parameters(){}
Type m11, m12, m21, m22;
nlohmann::json toJSON() override;
void fromJSON(nlohmann::json j) override;
};
// forward declaration of parameter classes

View File

@ -2,6 +2,7 @@
#include "preferences.h"
#include <random>
#include <QVector2D>
void Util::unwrapPhase(std::vector<double> &phase, unsigned int start_index)
@ -79,3 +80,13 @@ double Util::dBuVTodBm(double dBuV)
double dBdiff = 10*log10(uVpower*1000);
return dBuV + dBdiff;
}
unsigned long long Util::random(unsigned long long max)
{
static std::random_device os_seed;
static const unsigned long long seed = os_seed();
static std::mt19937_64 generator(seed);
std::uniform_int_distribution<unsigned long long> distribute(0, max);
return distribute(generator);
}

View File

@ -75,6 +75,8 @@ namespace Util {
void linearRegression(const std::vector<double> &input, double &B_0, double &B_1);
double distanceToLine(QPointF point, QPointF l1, QPointF l2, QPointF *closestLinePoint = nullptr, double *pointRatio = nullptr);
unsigned long long random(unsigned long long max);
}
#endif // UTILH_H