Sliding load support + TRL standard and measurements
This commit is contained in:
parent
858e945373
commit
fc1d006edd
147
Software/PC_Application/Calibration/CalStandardLineEditDialog.ui
Normal file
147
Software/PC_Application/Calibration/CalStandardLineEditDialog.ui
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>CalStandardLineEditDialog</class>
|
||||||
|
<widget class="QDialog" name="CalStandardLineEditDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>383</width>
|
||||||
|
<height>202</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Edit Line Standard</string>
|
||||||
|
</property>
|
||||||
|
<property name="modal">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Name:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="name"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_35">
|
||||||
|
<property name="text">
|
||||||
|
<string>Z0:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="Z0">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_21">
|
||||||
|
<property name="text">
|
||||||
|
<string>Delay:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="delay"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Minimum usable frequency:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="minFreq">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Maximum usable frequency:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="maxFreq">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</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>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>SIUnitEdit</class>
|
||||||
|
<extends>QLineEdit</extends>
|
||||||
|
<header>CustomWidgets/siunitedit.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>CalStandardLineEditDialog</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>CalStandardLineEditDialog</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>
|
||||||
|
<buttongroups>
|
||||||
|
<buttongroup name="buttonGroup"/>
|
||||||
|
</buttongroups>
|
||||||
|
</ui>
|
@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>CalStandardReflectEditDialog</class>
|
||||||
|
<widget class="QDialog" name="CalStandardReflectEditDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>291</width>
|
||||||
|
<height>109</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Edit Reflect Standard</string>
|
||||||
|
</property>
|
||||||
|
<property name="modal">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Name:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="name"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Reflection type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="type">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Open</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Short</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</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/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>CalStandardReflectEditDialog</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>CalStandardReflectEditDialog</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>
|
@ -3,6 +3,7 @@
|
|||||||
#include "CustomWidgets/informationbox.h"
|
#include "CustomWidgets/informationbox.h"
|
||||||
#include "Util/app_common.h"
|
#include "Util/app_common.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
|
#include "Util/util.h"
|
||||||
#include "LibreCAL/librecaldialog.h"
|
#include "LibreCAL/librecaldialog.h"
|
||||||
|
|
||||||
#include "Eigen/Dense"
|
#include "Eigen/Dense"
|
||||||
@ -296,6 +297,7 @@ QString Calibration::TypeToString(Calibration::Type 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::ThroughNormalization: return "ThroughNormalization";
|
||||||
|
case Type::TRL: return "TRL";
|
||||||
case Type::Last: return "Invalid";
|
case Type::Last: return "Invalid";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -560,6 +562,12 @@ void Calibration::edit()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// update calibration (may have changed due to deleted measurement)
|
||||||
|
if(canCompute(caltype)) {
|
||||||
|
compute(caltype);
|
||||||
|
} else {
|
||||||
|
deactivate();
|
||||||
|
}
|
||||||
updateMeasurementTable();
|
updateMeasurementTable();
|
||||||
updateCalibrationList();
|
updateCalibrationList();
|
||||||
});
|
});
|
||||||
@ -605,6 +613,12 @@ void Calibration::edit()
|
|||||||
for(auto s : selected) {
|
for(auto s : selected) {
|
||||||
measurements[s.row()]->clearPoints();
|
measurements[s.row()]->clearPoints();
|
||||||
}
|
}
|
||||||
|
// update calibration (may have changed due to deleted measurement)
|
||||||
|
if(canCompute(caltype)) {
|
||||||
|
compute(caltype);
|
||||||
|
} else {
|
||||||
|
deactivate();
|
||||||
|
}
|
||||||
updateMeasurementTable();
|
updateMeasurementTable();
|
||||||
updateCalibrationList();
|
updateCalibrationList();
|
||||||
});
|
});
|
||||||
@ -647,8 +661,11 @@ CalibrationMeasurement::Base *Calibration::newMeasurement(CalibrationMeasurement
|
|||||||
case CalibrationMeasurement::Base::Type::Open: m = new CalibrationMeasurement::Open(this); break;
|
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::Short: m = new CalibrationMeasurement::Short(this); break;
|
||||||
case CalibrationMeasurement::Base::Type::Load: m = new CalibrationMeasurement::Load(this); break;
|
case CalibrationMeasurement::Base::Type::Load: m = new CalibrationMeasurement::Load(this); break;
|
||||||
|
case CalibrationMeasurement::Base::Type::SlidingLoad: m = new CalibrationMeasurement::SlidingLoad(this); break;
|
||||||
|
case CalibrationMeasurement::Base::Type::Reflect: m = new CalibrationMeasurement::Reflect(this); break;
|
||||||
case CalibrationMeasurement::Base::Type::Through: m = new CalibrationMeasurement::Through(this); break;
|
case CalibrationMeasurement::Base::Type::Through: m = new CalibrationMeasurement::Through(this); break;
|
||||||
case CalibrationMeasurement::Base::Type::Isolation: m = new CalibrationMeasurement::Isolation(this); break;
|
case CalibrationMeasurement::Base::Type::Isolation: m = new CalibrationMeasurement::Isolation(this); break;
|
||||||
|
case CalibrationMeasurement::Base::Type::Line: m = new CalibrationMeasurement::Line(this); break;
|
||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
@ -679,13 +696,33 @@ Calibration::Point Calibration::computeSOLT(double f)
|
|||||||
auto p = caltype.usedPorts[i];
|
auto p = caltype.usedPorts[i];
|
||||||
auto _short = static_cast<CalibrationMeasurement::Short*>(findMeasurement(CalibrationMeasurement::Base::Type::Short, p));
|
auto _short = static_cast<CalibrationMeasurement::Short*>(findMeasurement(CalibrationMeasurement::Base::Type::Short, p));
|
||||||
auto open = static_cast<CalibrationMeasurement::Open*>(findMeasurement(CalibrationMeasurement::Base::Type::Open, p));
|
auto open = static_cast<CalibrationMeasurement::Open*>(findMeasurement(CalibrationMeasurement::Base::Type::Open, p));
|
||||||
auto load = static_cast<CalibrationMeasurement::Load*>(findMeasurement(CalibrationMeasurement::Base::Type::Load, p));
|
|
||||||
auto s_m = _short->getMeasured(f);
|
auto s_m = _short->getMeasured(f);
|
||||||
auto o_m = open->getMeasured(f);
|
auto o_m = open->getMeasured(f);
|
||||||
auto l_m = load->getMeasured(f);
|
|
||||||
auto s_c = _short->getActual(f);
|
auto s_c = _short->getActual(f);
|
||||||
auto o_c = open->getActual(f);
|
auto o_c = open->getActual(f);
|
||||||
auto l_c = load->getActual(f);
|
complex<double> l_c, l_m;
|
||||||
|
auto slidingMeasurements = findMeasurements(CalibrationMeasurement::Base::Type::SlidingLoad, p);
|
||||||
|
if(slidingMeasurements.size() >= 3) {
|
||||||
|
// use sliding load
|
||||||
|
vector<complex<double>> slidingMeasured;
|
||||||
|
for(auto m : slidingMeasurements) {
|
||||||
|
auto slidingLoad = static_cast<CalibrationMeasurement::SlidingLoad*>(m);
|
||||||
|
auto value = slidingLoad->getMeasured(f);
|
||||||
|
if(isnan(abs(value))) {
|
||||||
|
throw runtime_error("missing sliding load measurement");
|
||||||
|
}
|
||||||
|
slidingMeasured.push_back(value);
|
||||||
|
}
|
||||||
|
// use center of measurement for ideal load measurement
|
||||||
|
l_m = Util::findCenterOfCircle(slidingMeasured);
|
||||||
|
// assume perfect sliding load
|
||||||
|
l_c = 0.0;
|
||||||
|
} else {
|
||||||
|
// use normal load standard
|
||||||
|
auto load = static_cast<CalibrationMeasurement::Load*>(findMeasurement(CalibrationMeasurement::Base::Type::Load, p));
|
||||||
|
l_c = load->getActual(f);
|
||||||
|
l_m = load->getMeasured(f);
|
||||||
|
}
|
||||||
auto denom = l_c * o_c * (o_m - l_m) + l_c * s_c * (l_m - s_m) + o_c * s_c * (s_m - o_m);
|
auto denom = l_c * o_c * (o_m - l_m) + l_c * s_c * (l_m - s_m) + o_c * s_c * (s_m - o_m);
|
||||||
point.D[i] = (l_c * o_m * (s_m * (o_c - s_c) + l_m * s_c) - l_c * o_c * l_m * s_m + o_c * l_m * s_c * (s_m - o_m)) / denom;
|
point.D[i] = (l_c * o_m * (s_m * (o_c - s_c) + l_m * s_c) - l_c * o_c * l_m * s_m + o_c * l_m * s_c * (s_m - o_m)) / denom;
|
||||||
point.S[i] = (l_c * (o_m - s_m) + o_c * (s_m - l_m) + s_c * (l_m - o_m)) / denom;
|
point.S[i] = (l_c * (o_m - s_m) + o_c * (s_m - l_m) + s_c * (l_m - o_m)) / denom;
|
||||||
@ -1203,7 +1240,13 @@ bool Calibration::canCompute(Calibration::CalType type, double *startFreq, doubl
|
|||||||
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});
|
||||||
required.push_back({.type = CalibrationMeasurement::Base::Type::Open, .port1 = p});
|
required.push_back({.type = CalibrationMeasurement::Base::Type::Open, .port1 = p});
|
||||||
required.push_back({.type = CalibrationMeasurement::Base::Type::Load, .port1 = p});
|
if(findMeasurements(CalibrationMeasurement::Base::Type::SlidingLoad, p).size() >= 3) {
|
||||||
|
// got enough sliding load measurements, use these
|
||||||
|
required.push_back({.type = CalibrationMeasurement::Base::Type::SlidingLoad, .port1 = p});
|
||||||
|
} else {
|
||||||
|
// not enough sliding load measurement, use normal load
|
||||||
|
required.push_back({.type = CalibrationMeasurement::Base::Type::Load, .port1 = p});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// through measurements between all ports
|
// through measurements between all ports
|
||||||
for(int i=1;i<=type.usedPorts.size();i++) {
|
for(int i=1;i<=type.usedPorts.size();i++) {
|
||||||
@ -1220,6 +1263,19 @@ bool Calibration::canCompute(Calibration::CalType type, double *startFreq, doubl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Type::TRL:
|
||||||
|
// Reflect measurement for every port
|
||||||
|
for(auto p : type.usedPorts) {
|
||||||
|
required.push_back({.type = CalibrationMeasurement::Base::Type::Reflect, .port1 = p});
|
||||||
|
}
|
||||||
|
// through and line 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});
|
||||||
|
required.push_back({.type = CalibrationMeasurement::Base::Type::Line, .port1 = i, .port2 = j});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if(required.size() > 0) {
|
if(required.size() > 0) {
|
||||||
vector<CalibrationMeasurement::Base*> foundMeasurements;
|
vector<CalibrationMeasurement::Base*> foundMeasurements;
|
||||||
@ -1278,6 +1334,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;
|
case Type::ThroughNormalization: return 2;
|
||||||
|
case Type::TRL: return 2;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1415,8 +1472,9 @@ bool Calibration::hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CalibrationMeasurement::Base *Calibration::findMeasurement(CalibrationMeasurement::Base::Type type, int port1, int port2)
|
std::vector<CalibrationMeasurement::Base *> Calibration::findMeasurements(CalibrationMeasurement::Base::Type type, int port1, int port2)
|
||||||
{
|
{
|
||||||
|
vector<CalibrationMeasurement::Base*> ret;
|
||||||
for(auto m : measurements) {
|
for(auto m : measurements) {
|
||||||
if(m->getType() != type) {
|
if(m->getType() != type) {
|
||||||
continue;
|
continue;
|
||||||
@ -1434,9 +1492,19 @@ CalibrationMeasurement::Base *Calibration::findMeasurement(CalibrationMeasuremen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if we get here, we have a match
|
// if we get here, we have a match
|
||||||
return m;
|
ret.push_back(m);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
CalibrationMeasurement::Base *Calibration::findMeasurement(CalibrationMeasurement::Base::Type type, int port1, int port2)
|
||||||
|
{
|
||||||
|
auto meas = findMeasurements(type, port1, port2);
|
||||||
|
if(meas.size() > 0) {
|
||||||
|
return meas[0];
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Calibration::CalType::getReadableDescription()
|
QString Calibration::CalType::getReadableDescription()
|
||||||
|
@ -19,6 +19,7 @@ public:
|
|||||||
None,
|
None,
|
||||||
SOLT,
|
SOLT,
|
||||||
ThroughNormalization,
|
ThroughNormalization,
|
||||||
|
TRL,
|
||||||
Last,
|
Last,
|
||||||
};
|
};
|
||||||
class CalType {
|
class CalType {
|
||||||
@ -121,8 +122,10 @@ private:
|
|||||||
void deleteMeasurements();
|
void deleteMeasurements();
|
||||||
|
|
||||||
bool hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base*> m, double *startFreq = nullptr, double *stopFreq = nullptr, int *points = nullptr);
|
bool hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base*> m, double *startFreq = nullptr, double *stopFreq = nullptr, int *points = nullptr);
|
||||||
|
// returns all measurements that match the paramaters
|
||||||
|
std::vector<CalibrationMeasurement::Base*> findMeasurements(CalibrationMeasurement::Base::Type type, int port1 = 0, int port2 = 0);
|
||||||
|
// returns the first measurement in the list that matches the parameters
|
||||||
CalibrationMeasurement::Base* findMeasurement(CalibrationMeasurement::Base::Type type, int port1 = 0, int port2 = 0);
|
CalibrationMeasurement::Base* findMeasurement(CalibrationMeasurement::Base::Type type, int port1 = 0, int port2 = 0);
|
||||||
|
|
||||||
CalibrationMeasurement::Base *newMeasurement(CalibrationMeasurement::Base::Type type);
|
CalibrationMeasurement::Base *newMeasurement(CalibrationMeasurement::Base::Type type);
|
||||||
|
|
||||||
class Point {
|
class Point {
|
||||||
|
@ -86,8 +86,11 @@ QString CalibrationMeasurement::Base::TypeToString(CalibrationMeasurement::Base:
|
|||||||
case Type::Open: return "Open";
|
case Type::Open: return "Open";
|
||||||
case Type::Short: return "Short";
|
case Type::Short: return "Short";
|
||||||
case Type::Load: return "Load";
|
case Type::Load: return "Load";
|
||||||
|
case Type::SlidingLoad: return "SlidingLoad";
|
||||||
|
case Type::Reflect: return "Reflect";
|
||||||
case Type::Through: return "Through";
|
case Type::Through: return "Through";
|
||||||
case Type::Isolation: return "Isolation";
|
case Type::Isolation: return "Isolation";
|
||||||
|
case Type::Line: return "Line";
|
||||||
case Type::Last: return "Invalid";
|
case Type::Last: return "Invalid";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -678,3 +681,8 @@ std::vector<CalibrationMeasurement::Isolation::Point> CalibrationMeasurement::Is
|
|||||||
{
|
{
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWidget *CalibrationMeasurement::SlidingLoad::createStandardWidget()
|
||||||
|
{
|
||||||
|
return new QLabel("Connect sliding load");
|
||||||
|
}
|
||||||
|
@ -21,8 +21,11 @@ public:
|
|||||||
Open,
|
Open,
|
||||||
Short,
|
Short,
|
||||||
Load,
|
Load,
|
||||||
|
SlidingLoad,
|
||||||
|
Reflect,
|
||||||
Through,
|
Through,
|
||||||
Isolation,
|
Isolation,
|
||||||
|
Line,
|
||||||
Last,
|
Last,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -138,6 +141,31 @@ public:
|
|||||||
virtual Type getType() override {return Type::Load;}
|
virtual Type getType() override {return Type::Load;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SlidingLoad : public OnePort
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
SlidingLoad(Calibration *cal) :
|
||||||
|
OnePort(cal){setFirstSupportedStandard();}
|
||||||
|
|
||||||
|
virtual QWidget* createStandardWidget() override;
|
||||||
|
|
||||||
|
virtual std::set<CalStandard::Virtual::Type> supportedStandardTypes() override {return {};}
|
||||||
|
virtual Type getType() override {return Type::SlidingLoad;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Reflect : public OnePort
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Reflect(Calibration *cal) :
|
||||||
|
OnePort(cal){setFirstSupportedStandard();}
|
||||||
|
|
||||||
|
virtual std::set<CalStandard::Virtual::Type> supportedStandardTypes() override {return {CalStandard::Virtual::Type::Open,
|
||||||
|
CalStandard::Virtual::Type::Short, CalStandard::Virtual::Type::Reflect};}
|
||||||
|
virtual Type getType() override {return Type::Reflect;}
|
||||||
|
};
|
||||||
|
|
||||||
class TwoPort : public Base
|
class TwoPort : public Base
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -234,5 +262,15 @@ protected:
|
|||||||
std::vector<Point> points;
|
std::vector<Point> points;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Line : public TwoPort
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Line(Calibration *cal) :
|
||||||
|
TwoPort(cal){setFirstSupportedStandard();}
|
||||||
|
virtual std::set<CalStandard::Virtual::Type> supportedStandardTypes() override {return {CalStandard::Virtual::Type::Line};}
|
||||||
|
virtual Type getType() override {return Type::Line;}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif // CALIBRATIONMEASUREMENT_H
|
#endif // CALIBRATIONMEASUREMENT_H
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
#include "ui_CalStandardOpenEditDialog.h"
|
#include "ui_CalStandardOpenEditDialog.h"
|
||||||
#include "ui_CalStandardShortEditDialog.h"
|
#include "ui_CalStandardShortEditDialog.h"
|
||||||
#include "ui_CalStandardLoadEditDialog.h"
|
#include "ui_CalStandardLoadEditDialog.h"
|
||||||
|
#include "ui_CalStandardReflectEditDialog.h"
|
||||||
#include "ui_CalStandardThroughEditDialog.h"
|
#include "ui_CalStandardThroughEditDialog.h"
|
||||||
|
#include "ui_CalStandardLineEditDialog.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include "Util/util.h"
|
#include "Util/util.h"
|
||||||
|
|
||||||
@ -23,8 +25,9 @@ Virtual *Virtual::create(Virtual::Type type)
|
|||||||
case Type::Open: return new Open;
|
case Type::Open: return new Open;
|
||||||
case Type::Short: return new Short;
|
case Type::Short: return new Short;
|
||||||
case Type::Load: return new Load;
|
case Type::Load: return new Load;
|
||||||
|
case Type::Reflect: return new Reflect;
|
||||||
case Type::Through: return new Through;
|
case Type::Through: return new Through;
|
||||||
case Type::Line: // TODO
|
case Type::Line: return new Line;
|
||||||
case Type::Last:
|
case Type::Last:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -46,6 +49,7 @@ QString Virtual::TypeToString(Virtual::Type type)
|
|||||||
case Type::Open: return "Open";
|
case Type::Open: return "Open";
|
||||||
case Type::Short: return "Short";
|
case Type::Short: return "Short";
|
||||||
case Type::Load: return "Load";
|
case Type::Load: return "Load";
|
||||||
|
case Type::Reflect: return "Reflect";
|
||||||
case Type::Through: return "Through";
|
case Type::Through: return "Through";
|
||||||
case Type::Line: return "Line";
|
case Type::Line: return "Line";
|
||||||
case Type::Last: return "Invalid";
|
case Type::Last: return "Invalid";
|
||||||
@ -677,3 +681,123 @@ void Through::fromJSON(nlohmann::json j)
|
|||||||
delay = j.value("delay", 0.0);
|
delay = j.value("delay", 0.0);
|
||||||
loss = j.value("loss", 0.0);
|
loss = j.value("loss", 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reflect::Reflect()
|
||||||
|
{
|
||||||
|
isShort = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::complex<double> Reflect::toS11(double freq)
|
||||||
|
{
|
||||||
|
Q_UNUSED(freq)
|
||||||
|
return std::numeric_limits<complex<double>>::quiet_NaN();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reflect::edit(std::function<void ()> finishedCallback)
|
||||||
|
{
|
||||||
|
auto d = new QDialog;
|
||||||
|
auto ui = new Ui::CalStandardReflectEditDialog;
|
||||||
|
ui->setupUi(d);
|
||||||
|
|
||||||
|
ui->name->setText(name);
|
||||||
|
ui->type->setCurrentIndex(isShort ? 1 : 0);
|
||||||
|
|
||||||
|
QObject::connect(d, &QDialog::accepted, [=](){
|
||||||
|
name = ui->name->text();
|
||||||
|
isShort = ui->type->currentIndex() == 1;
|
||||||
|
if(finishedCallback) {
|
||||||
|
finishedCallback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
d->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json Reflect::toJSON()
|
||||||
|
{
|
||||||
|
auto j = OnePort::toJSON();
|
||||||
|
j["isShort"] = isShort;
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reflect::fromJSON(nlohmann::json j)
|
||||||
|
{
|
||||||
|
OnePort::fromJSON(j);
|
||||||
|
isShort = j.value("isShort", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Line::Line()
|
||||||
|
{
|
||||||
|
Z0 = 50.0;
|
||||||
|
setDelay(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sparam Line::toSparam(double freq)
|
||||||
|
{
|
||||||
|
Sparam ret;
|
||||||
|
ret.m11 = numeric_limits<complex<double>>::quiet_NaN();
|
||||||
|
ret.m12 = numeric_limits<complex<double>>::quiet_NaN();
|
||||||
|
ret.m21 = numeric_limits<complex<double>>::quiet_NaN();
|
||||||
|
ret.m22 = numeric_limits<complex<double>>::quiet_NaN();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Line::edit(std::function<void ()> finishedCallback)
|
||||||
|
{
|
||||||
|
auto d = new QDialog;
|
||||||
|
auto ui = new Ui::CalStandardLineEditDialog;
|
||||||
|
ui->setupUi(d);
|
||||||
|
|
||||||
|
ui->name->setText(name);
|
||||||
|
ui->Z0->setUnit("Ω");
|
||||||
|
ui->Z0->setPrecision(2);
|
||||||
|
ui->Z0->setValue(Z0);
|
||||||
|
ui->delay->setValue(delay);
|
||||||
|
ui->delay->setUnit("s");
|
||||||
|
ui->delay->setPrefixes("pnum ");
|
||||||
|
ui->delay->setPrecision(4);
|
||||||
|
ui->minFreq->setUnit("Hz");
|
||||||
|
ui->minFreq->setPrecision(3);
|
||||||
|
ui->minFreq->setPrefixes(" kMG");
|
||||||
|
ui->minFreq->setValue(minFreq);
|
||||||
|
ui->maxFreq->setUnit("Hz");
|
||||||
|
ui->maxFreq->setPrecision(3);
|
||||||
|
ui->maxFreq->setPrefixes(" kMG");
|
||||||
|
ui->maxFreq->setValue(maxFreq);
|
||||||
|
|
||||||
|
QObject::connect(ui->delay, &SIUnitEdit::valueChanged, [=](double val){
|
||||||
|
ui->minFreq->setValue(1.0 / val * 20 / 360);
|
||||||
|
ui->maxFreq->setValue(1.0 / val * 160 / 360);
|
||||||
|
});
|
||||||
|
|
||||||
|
QObject::connect(d, &QDialog::accepted, [=](){
|
||||||
|
name = ui->name->text();
|
||||||
|
Z0 = ui->Z0->value();
|
||||||
|
setDelay(ui->delay->value());
|
||||||
|
if(finishedCallback) {
|
||||||
|
finishedCallback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
d->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json Line::toJSON()
|
||||||
|
{
|
||||||
|
auto j = TwoPort::toJSON();
|
||||||
|
j["delay"] = delay;
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Line::fromJSON(nlohmann::json j)
|
||||||
|
{
|
||||||
|
TwoPort::fromJSON(j);
|
||||||
|
setDelay(j.value("delay", 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Line::setDelay(double delay)
|
||||||
|
{
|
||||||
|
this->delay = delay;
|
||||||
|
minFreq = 1.0 / delay * 20 / 360;
|
||||||
|
maxFreq = 1.0 / delay * 160 / 360;
|
||||||
|
}
|
||||||
|
@ -20,6 +20,7 @@ public:
|
|||||||
Open,
|
Open,
|
||||||
Short,
|
Short,
|
||||||
Load,
|
Load,
|
||||||
|
Reflect,
|
||||||
Through,
|
Through,
|
||||||
Line,
|
Line,
|
||||||
Last
|
Last
|
||||||
@ -126,6 +127,23 @@ private:
|
|||||||
bool Cfirst;
|
bool Cfirst;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Reflect : public OnePort
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Reflect();
|
||||||
|
Reflect(QString name, bool isShort)
|
||||||
|
: OnePort(name), isShort(isShort){}
|
||||||
|
|
||||||
|
virtual std::complex<double> toS11(double freq) override;
|
||||||
|
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||||
|
virtual Type getType() override {return Type::Reflect;}
|
||||||
|
virtual nlohmann::json toJSON() override;
|
||||||
|
virtual void fromJSON(nlohmann::json j) override;
|
||||||
|
private:
|
||||||
|
bool isShort;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class TwoPort : public Virtual
|
class TwoPort : public Virtual
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -161,6 +179,23 @@ private:
|
|||||||
double Z0, delay, loss;
|
double Z0, delay, loss;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Line : public TwoPort
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Line();
|
||||||
|
Line(QString name, double Z0, double delay)
|
||||||
|
: TwoPort(name), Z0(Z0), delay(delay){}
|
||||||
|
|
||||||
|
virtual Sparam toSparam(double freq) override;
|
||||||
|
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||||
|
virtual Type getType() override {return Type::Line;}
|
||||||
|
virtual nlohmann::json toJSON() override;
|
||||||
|
virtual void fromJSON(nlohmann::json j) override;
|
||||||
|
private:
|
||||||
|
void setDelay(double delay);
|
||||||
|
double Z0, delay;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CALSTANDARD_H
|
#endif // CALSTANDARD_H
|
||||||
|
@ -278,8 +278,10 @@ osx:LIBS += $(shell pkg-config --libs libusb-1.0)
|
|||||||
QT += widgets network
|
QT += widgets network
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
Calibration/CalStandardLineEditDialog.ui \
|
||||||
Calibration/CalStandardLoadEditDialog.ui \
|
Calibration/CalStandardLoadEditDialog.ui \
|
||||||
Calibration/CalStandardOpenEditDialog.ui \
|
Calibration/CalStandardOpenEditDialog.ui \
|
||||||
|
Calibration/CalStandardReflectEditDialog.ui \
|
||||||
Calibration/CalStandardShortEditDialog.ui \
|
Calibration/CalStandardShortEditDialog.ui \
|
||||||
Calibration/CalStandardThroughEditDialog.ui \
|
Calibration/CalStandardThroughEditDialog.ui \
|
||||||
Calibration/LibreCAL/librecaldialog.ui \
|
Calibration/LibreCAL/librecaldialog.ui \
|
||||||
|
@ -90,3 +90,82 @@ unsigned long long Util::random(unsigned long long max)
|
|||||||
std::uniform_int_distribution<unsigned long long> distribute(0, max);
|
std::uniform_int_distribution<unsigned long long> distribute(0, max);
|
||||||
return distribute(generator);
|
return distribute(generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::complex<double> Util::findCenterOfCircle(const std::vector<std::complex<double> > &points)
|
||||||
|
{
|
||||||
|
int i,iter,IterMAX=99;
|
||||||
|
|
||||||
|
double Xi,Yi,Zi;
|
||||||
|
double Mz,Mxy,Mxx,Myy,Mxz,Myz,Mzz,Cov_xy,Var_z;
|
||||||
|
double A0,A1,A2,A22;
|
||||||
|
double Dy,xnew,x,ynew,y;
|
||||||
|
double DET,Xcenter,Ycenter;
|
||||||
|
|
||||||
|
// find means
|
||||||
|
double meanX = 0.0, meanY = 0.0;
|
||||||
|
for(auto p : points) {
|
||||||
|
meanX += p.real();
|
||||||
|
meanY += p.imag();
|
||||||
|
}
|
||||||
|
meanX /= points.size();
|
||||||
|
meanY /= points.size();
|
||||||
|
|
||||||
|
// computing moments
|
||||||
|
|
||||||
|
Mxx=Myy=Mxy=Mxz=Myz=Mzz=0.;
|
||||||
|
|
||||||
|
for (i=0; i<(int) points.size(); i++)
|
||||||
|
{
|
||||||
|
Xi = points[i].real() - meanX; // centered x-coordinates
|
||||||
|
Yi = points[i].imag() - meanY; // centered y-coordinates
|
||||||
|
Zi = Xi*Xi + Yi*Yi;
|
||||||
|
|
||||||
|
Mxy += Xi*Yi;
|
||||||
|
Mxx += Xi*Xi;
|
||||||
|
Myy += Yi*Yi;
|
||||||
|
Mxz += Xi*Zi;
|
||||||
|
Myz += Yi*Zi;
|
||||||
|
Mzz += Zi*Zi;
|
||||||
|
}
|
||||||
|
Mxx /= points.size();
|
||||||
|
Myy /= points.size();
|
||||||
|
Mxy /= points.size();
|
||||||
|
Mxz /= points.size();
|
||||||
|
Myz /= points.size();
|
||||||
|
Mzz /= points.size();
|
||||||
|
|
||||||
|
// computing the coefficients of the characteristic polynomial
|
||||||
|
|
||||||
|
Mz = Mxx + Myy;
|
||||||
|
Cov_xy = Mxx*Myy - Mxy*Mxy;
|
||||||
|
Var_z = Mzz - Mz*Mz;
|
||||||
|
|
||||||
|
A2 = 4.0*Cov_xy - 3.0*Mz*Mz - Mzz;
|
||||||
|
A1 = Var_z*Mz + 4.0*Cov_xy*Mz - Mxz*Mxz - Myz*Myz;
|
||||||
|
A0 = Mxz*(Mxz*Myy - Myz*Mxy) + Myz*(Myz*Mxx - Mxz*Mxy) - Var_z*Cov_xy;
|
||||||
|
A22 = A2 + A2;
|
||||||
|
|
||||||
|
// finding the root of the characteristic polynomial
|
||||||
|
// using Newton's method starting at x=0
|
||||||
|
// (it is guaranteed to converge to the right root)
|
||||||
|
|
||||||
|
for (x=0.,y=A0,iter=0; iter<IterMAX; iter++) // usually, 4-6 iterations are enough
|
||||||
|
{
|
||||||
|
Dy = A1 + x*(A22 + 16.*x*x);
|
||||||
|
xnew = x - y/Dy;
|
||||||
|
if ((xnew == x)||(!isfinite(xnew))) break;
|
||||||
|
ynew = A0 + xnew*(A1 + xnew*(A2 + 4.0*xnew*xnew));
|
||||||
|
if (abs(ynew)>=abs(y)) break;
|
||||||
|
x = xnew; y = ynew;
|
||||||
|
}
|
||||||
|
|
||||||
|
// computing paramters of the fitting circle
|
||||||
|
|
||||||
|
DET = x*x - x*Mz + Cov_xy;
|
||||||
|
Xcenter = (Mxz*(Myy - x) - Myz*Mxy)/DET/2.0;
|
||||||
|
Ycenter = (Myz*(Mxx - x) - Mxz*Mxy)/DET/2.0;
|
||||||
|
|
||||||
|
// assembling the output
|
||||||
|
|
||||||
|
return std::complex<double>(Xcenter + meanX, Ycenter + meanY);
|
||||||
|
}
|
||||||
|
@ -77,6 +77,8 @@ namespace Util {
|
|||||||
double distanceToLine(QPointF point, QPointF l1, QPointF l2, QPointF *closestLinePoint = nullptr, double *pointRatio = nullptr);
|
double distanceToLine(QPointF point, QPointF l1, QPointF l2, QPointF *closestLinePoint = nullptr, double *pointRatio = nullptr);
|
||||||
|
|
||||||
unsigned long long random(unsigned long long max);
|
unsigned long long random(unsigned long long max);
|
||||||
|
|
||||||
|
std::complex<double> findCenterOfCircle(const std::vector<std::complex<double>> &points);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // UTILH_H
|
#endif // UTILH_H
|
||||||
|
Loading…
Reference in New Issue
Block a user