From 6d6ffc60ea8ca52316c5569eed8be393bcc9c50e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4berich?= Date: Wed, 25 Sep 2024 17:58:32 +0200 Subject: [PATCH] partial loading of coefficient sets --- .../Calibration/LibreCAL/caldevice.cpp | 210 ++++++++++++------ .../Calibration/LibreCAL/caldevice.h | 24 +- .../Calibration/LibreCAL/librecaldialog.cpp | 93 +++++--- 3 files changed, 221 insertions(+), 106 deletions(-) diff --git a/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/caldevice.cpp b/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/caldevice.cpp index 7bc1ada4..9274a686 100644 --- a/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/caldevice.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/caldevice.cpp @@ -172,14 +172,24 @@ QString CalDevice::getDateTimeUTC() } } -void CalDevice::loadCoefficientSets(QStringList names, bool fast) +void CalDevice::loadCoefficientSets(QStringList names, QList ports, bool fast) { coeffSets.clear(); + + if(ports.isEmpty()) { + for(int i=1;i<=ports.size();i++) { + ports.append(i); + } + } else { + // make sure we are sorted, otherwise the through coefficient naming is wrong + std::sort(ports.begin(), ports.end()); + } + abortLoading = false; if(fast && Util::firmwareEqualOrHigher(firmware, "0.2.1")) { - loadThread = new std::thread(&CalDevice::loadCoefficientSetsThreadFast, this, names); + loadThread = new std::thread(&CalDevice::loadCoefficientSetsThreadFast, this, names, ports); } else { - loadThread = new std::thread(&CalDevice::loadCoefficientSetsThreadSlow, this, names); + loadThread = new std::thread(&CalDevice::loadCoefficientSetsThreadSlow, this, names, ports); } } @@ -202,7 +212,7 @@ void CalDevice::saveCoefficientSets() } } -void CalDevice::loadCoefficientSetsThreadSlow(QStringList names) +void CalDevice::loadCoefficientSetsThreadSlow(QStringList names, QList ports) { QStringList coeffList = getCoefficientSetNames(); if(coeffList.empty()) { @@ -224,14 +234,16 @@ void CalDevice::loadCoefficientSetsThreadSlow(QStringList names) // get total number of coefficient points for accurate percentage calculation unsigned long totalPoints = 0; for(auto name : coeffList) { - for(int i=1;i<=numPorts;i++) { + for(int idx=0;idxQuery(":COEFF:NUM? "+name+" P"+QString::number(i)+"_OPEN").toInt(); totalPoints += usb->Query(":COEFF:NUM? "+name+" P"+QString::number(i)+"_SHORT").toInt(); totalPoints += usb->Query(":COEFF:NUM? "+name+" P"+QString::number(i)+"_LOAD").toInt(); - for(int j=i+1;j<=numPorts;j++) { + for(int jdx=idx+1;jdxQuery(":COEFF:NUM? "+name+" P"+QString::number(i)+QString::number(j)+"_THROUGH").toInt(); } } @@ -244,7 +256,8 @@ void CalDevice::loadCoefficientSetsThreadSlow(QStringList names) set.name = name; set.ports = numPorts; // Read this coefficient set - for(int i=1;i<=numPorts;i++) { + for(int idx=0;idx CoefficientSet::Coefficient* { int points = usb->Query(":COEFF:NUM? "+setName+" "+paramName).toInt(); CoefficientSet::Coefficient *c = new CoefficientSet::Coefficient(); @@ -282,11 +295,12 @@ void CalDevice::loadCoefficientSetsThreadSlow(QStringList names) c->t.setFilename("LibreCAL/"+paramName); return c; }; - set.opens.push_back(createCoefficient(name, "P"+QString::number(i)+"_OPEN")); - set.shorts.push_back(createCoefficient(name, "P"+QString::number(i)+"_SHORT")); - set.loads.push_back(createCoefficient(name, "P"+QString::number(i)+"_LOAD")); - for(int j=i+1;j<=numPorts;j++) { - set.throughs.push_back(createCoefficient(name, "P"+QString::number(i)+QString::number(j)+"_THROUGH")); + set.opens[i] = (createCoefficient(name, "P"+QString::number(i)+"_OPEN")); + set.shorts[i] = (createCoefficient(name, "P"+QString::number(i)+"_SHORT")); + set.loads[i] = (createCoefficient(name, "P"+QString::number(i)+"_LOAD")); + for(int jdx=idx+1;jdx ports) { QStringList coeffList = getCoefficientSetNames(); if(coeffList.empty()) { @@ -317,17 +331,7 @@ void CalDevice::loadCoefficientSetsThreadFast(QStringList names) coeffList = names; } - QStringList coeffNames; - for(int i=1;i<=numPorts;i++) { - coeffNames.append("P"+QString::number(i)+"_OPEN"); - coeffNames.append("P"+QString::number(i)+"_SHORT"); - coeffNames.append("P"+QString::number(i)+"_LOAD"); - for(int j=i+1;j<=numPorts;j++) { - coeffNames.append("P"+QString::number(i)+QString::number(j)+"_THROUGH"); - } - } - - int total_coeffs = coeffNames.size() * names.size(); + int total_coeffs = (ports.size() * 3 + ports.size() * (ports.size() - 1) / 2) * names.size(); int read_coeffs = 0; for(auto name : coeffList) { @@ -389,25 +393,54 @@ void CalDevice::loadCoefficientSetsThreadFast(QStringList names) } }; - for(auto coeff : coeffNames) { - auto c = createCoefficient(name, coeff); + for(int idx=0;idxmodified) { - totalPoints += c->t.points(); + if(c.second->modified) { + totalPoints += c.second->t.points(); } } for(auto c : set.shorts) { - if(c->modified) { - totalPoints += c->t.points(); + if(c.second->modified) { + totalPoints += c.second->t.points(); } } for(auto c : set.loads) { - if(c->modified) { - totalPoints += c->t.points(); + if(c.second->modified) { + totalPoints += c.second->t.points(); } } for(auto c : set.throughs) { - if(c->modified) { - totalPoints += c->t.points(); + if(c.second->modified) { + totalPoints += c.second->t.points(); } } } @@ -488,11 +521,20 @@ void CalDevice::saveCoefficientSetsThread() return true; }; for(int i=1;i<=numPorts;i++) { - success &= createCoefficient(set.name, "P"+QString::number(i)+"_OPEN", set.opens[i-1]->t, set.opens[i-1]->modified); - success &= createCoefficient(set.name, "P"+QString::number(i)+"_SHORT", set.shorts[i-1]->t, set.shorts[i-1]->modified); - success &= createCoefficient(set.name, "P"+QString::number(i)+"_LOAD", set.loads[i-1]->t, set.loads[i-1]->modified); + if(set.opens.count(i)) { + success &= createCoefficient(set.name, "P"+QString::number(i)+"_OPEN", set.opens[i]->t, set.opens[i]->modified); + } + if(set.shorts.count(i)) { + success &= createCoefficient(set.name, "P"+QString::number(i)+"_SHORT", set.shorts[i]->t, set.shorts[i]->modified); + } + if(set.loads.count(i)) { + success &= createCoefficient(set.name, "P"+QString::number(i)+"_LOAD", set.loads[i]->t, set.loads[i]->modified); + } for(int j=i+1;j<=numPorts;j++) { - success &= createCoefficient(set.name, "P"+QString::number(i)+QString::number(j)+"_THROUGH", set.getThrough(i,j)->t, set.getThrough(i,j)->modified); + auto c = set.getThrough(i,j); + if(c) { + success &= createCoefficient(set.name, "P"+QString::number(i)+QString::number(j)+"_THROUGH", c->t, c->modified); + } } } } @@ -509,10 +551,10 @@ void CalDevice::addCoefficientSet(QString name) CoefficientSet set; set.name = name; set.ports = numPorts; - set.loads.resize(numPorts, new CoefficientSet::Coefficient()); - set.shorts.resize(numPorts, new CoefficientSet::Coefficient()); - set.opens.resize(numPorts, new CoefficientSet::Coefficient()); - set.throughs.resize(numPorts*(numPorts-1)/2, new CoefficientSet::Coefficient()); + set.loads.clear(); + set.shorts.clear(); + set.opens.clear(); + set.throughs.clear(); coeffSets.push_back(set); } @@ -529,22 +571,22 @@ bool CalDevice::hasModifiedCoefficients() { for(auto set : coeffSets) { for(auto c : set.opens) { - if(c->modified) { + if(c.second->modified) { return true; } } for(auto c : set.shorts) { - if(c->modified) { + if(c.second->modified) { return true; } } for(auto c : set.loads) { - if(c->modified) { + if(c.second->modified) { return true; } } for(auto c : set.throughs) { - if(c->modified) { + if(c.second->modified) { return true; } } @@ -552,15 +594,59 @@ bool CalDevice::hasModifiedCoefficients() return false; } -CalDevice::CoefficientSet::Coefficient *CalDevice::CoefficientSet::getThrough(int port1, int port2) const +CalDevice::CoefficientSet::Coefficient *CalDevice::CoefficientSet::getOpen(int port) { - if(port1 > ports || port2 > ports || port1 >= port2) { + if(opens.count(port)) { + return opens[port]; + } else { + return nullptr; + } +} + +CalDevice::CoefficientSet::Coefficient *CalDevice::CoefficientSet::getShort(int port) +{ + if(shorts.count(port)) { + return shorts[port]; + } else { + return nullptr; + } +} + +CalDevice::CoefficientSet::Coefficient *CalDevice::CoefficientSet::getLoad(int port) +{ + if(loads.count(port)) { + return loads[port]; + } else { return nullptr; } - int index = port2 - port1 - 1; - while(port1 > 1) { - index += ports - port1 + 1; - port1--; +} + +CalDevice::CoefficientSet::Coefficient *CalDevice::CoefficientSet::getThrough(int port1, int port2) +{ + auto index = portsToThroughIndex(port1, port2); + if(throughs.count(index)) { + return throughs[index]; + } else { + return nullptr; + } +} + +int CalDevice::CoefficientSet::portsToThroughIndex(int port1, int port2) +{ + if(port1 > ports || port2 > ports || port1 >= port2) { + return -1; + } + return port1 * ports + port2; +} + +void CalDevice::CoefficientSet::portsFromThroughIndex(int &port1, int &port2, int index) +{ + port1 = index / ports; + port2 = index - port1 * ports; + if(port1 < 1 || port1 > ports) { + port1 = -1; + } + if(port2 < 1 || port2 > ports) { + port2 = -1; } - return throughs[index]; } diff --git a/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/caldevice.h b/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/caldevice.h index 6fd967fa..7d928f55 100644 --- a/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/caldevice.h +++ b/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/caldevice.h @@ -60,18 +60,24 @@ class CalDevice : public QObject bool modified; }; - std::vector opens; - std::vector shorts; - std::vector loads; - std::vector throughs; - - Coefficient *getThrough(int port1, int port2) const; + Coefficient *getOpen(int port); + Coefficient *getShort(int port); + Coefficient *getLoad(int port); + Coefficient *getThrough(int port1, int port2); + + std::map opens; + std::map shorts; + std::map loads; + std::map throughs; + + int portsToThroughIndex(int port1, int port2); + void portsFromThroughIndex(int &port1, int &port2, int index); }; // Extracts the coefficients from the device. This is done with a dedicated thread. // Do not call any other functions until the update is finished. Process can be // monitored through the updateCoefficientsPercent and updateCoefficientsDone signals - void loadCoefficientSets(QStringList names = QStringList(), bool fast=true); + void loadCoefficientSets(QStringList names = QStringList(), QList ports = {}, bool fast=true); void abortCoefficientLoading(); // Writes coefficient sets to the device. This will only write modified files to save @@ -95,8 +101,8 @@ class CalDevice : public QObject void disconnected(); private: - void loadCoefficientSetsThreadSlow(QStringList names = QStringList()); - void loadCoefficientSetsThreadFast(QStringList names = QStringList()); + void loadCoefficientSetsThreadSlow(QStringList names, QList ports); + void loadCoefficientSetsThreadFast(QStringList names, QList ports); void saveCoefficientSetsThread(); USBDevice *usb; diff --git a/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/librecaldialog.cpp b/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/librecaldialog.cpp index fdd5ea45..eea2a1cd 100644 --- a/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/librecaldialog.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Calibration/LibreCAL/librecaldialog.cpp @@ -153,6 +153,9 @@ bool LibreCALDialog::validateCoefficients() double coeffMaxFreq = numeric_limits::lowest(); auto checkCoefficient = [&](CalDevice::CoefficientSet::Coefficient *c) -> bool { + if(!c) { + return false; + } if(c->t.points() == 0) { return false; } else { @@ -177,17 +180,17 @@ bool LibreCALDialog::validateCoefficients() // check if coefficients for all ports are available for(auto i : usedCalPorts) { // Check if OSL coefficients are there - if(!checkCoefficient(coeffSet.opens[i-1])) { + if(!checkCoefficient(coeffSet.getOpen(i))) { status = "Open coefficient for LibreCAL port "+QString::number(i)+" is missing."; canStart = false; break; } - if(!checkCoefficient(coeffSet.shorts[i-1])) { + if(!checkCoefficient(coeffSet.getShort(i))) { status = "Short coefficient for LibreCAL port "+QString::number(i)+" is missing."; canStart = false; break; } - if(!checkCoefficient(coeffSet.loads[i-1])) { + if(!checkCoefficient(coeffSet.getLoad(i))) { status = "Load coefficient for LibreCAL port "+QString::number(i)+" is missing."; canStart = false; break; @@ -296,18 +299,26 @@ void LibreCALDialog::loadCoefficients() } else { // can continue with loading coefficients // they might already be loaded from a previous calibration run, check first -// if(!validateCoefficients()) { - // TODO only load required coefficients + if(!validateCoefficients()) { + // only load required coefficients ui->progressCal->setValue(0); ui->lCalibrationStatus->setText("Loading coefficients..."); ui->lCalibrationStatus->setStyleSheet("QLabel { color : green; }"); - busy = true; - device->loadCoefficientSets({ui->cbCoefficients->currentText()}); -// } else { -// // can proceed with calibration directly -// startCalibration(); -// } + // determine the used ports of the LibreCAL + QList usedPorts; + for(auto port : portAssignment) { + if(port > 0) { + usedPorts.append(port); + } + } + + busy = true; + device->loadCoefficientSets({ui->cbCoefficients->currentText()}, usedPorts); + } else { + // can proceed with calibration directly + startCalibration(); + } } } @@ -417,33 +428,45 @@ void LibreCALDialog::startCalibration() kit.manufacturer = "LibreCAL ("+coeffSet.name+")"; kit.serialnumber = device->serial(); kit.description = "Automatically created from LibreCAL module"; - std::vector openStandards; - std::vector shortStandards; - std::vector loadStandards; - std::vector throughStandards; - for(unsigned int i=1;i<=device->getNumPorts();i++) { - if(coeffSet.opens[i-1]->t.points() > 0) { + + // determine the used ports of the LibreCAL + QList usedPorts; + for(auto port : portAssignment) { + if(port > 0) { + usedPorts.append(port); + } + } + std::sort(usedPorts.begin(), usedPorts.end()); + + std::map openStandards; + std::map shortStandards; + std::map loadStandards; + std::map throughStandards; + for(unsigned int idx=0;idxt.points() > 0) { auto o = new CalStandard::Open(); o->setName("Port "+QString::number(i)); - o->setMeasurement(coeffSet.opens[i-1]->t); - openStandards.push_back(o); + o->setMeasurement(coeffSet.getOpen(i)->t); + openStandards[i] = o; kit.addStandard(o); } - if(coeffSet.shorts[i-1]->t.points() > 0) { + if(coeffSet.getShort(i)->t.points() > 0) { auto o = new CalStandard::Short(); o->setName("Port "+QString::number(i)); - o->setMeasurement(coeffSet.shorts[i-1]->t); - shortStandards.push_back(o); + o->setMeasurement(coeffSet.getShort(i)->t); + shortStandards[i] = o; kit.addStandard(o); } - if(coeffSet.loads[i-1]->t.points() > 0) { + if(coeffSet.getLoad(i)->t.points() > 0) { auto o = new CalStandard::Load(); o->setName("Port "+QString::number(i)); - o->setMeasurement(coeffSet.loads[i-1]->t); - loadStandards.push_back(o); + o->setMeasurement(coeffSet.getLoad(i)->t); + loadStandards[i] = o; kit.addStandard(o); } - for(unsigned int j=i+1;j<=device->getNumPorts();j++) { + for(unsigned int jdx=idx+1;jdxsetName("Port "+QString::number(i)+" to "+QString::number(j)); o->setMeasurement(c->t); - throughStandards.push_back(o); + throughStandards[coeffSet.portsToThroughIndex(i, j)] = o; kit.addStandard(o); } } @@ -471,19 +494,19 @@ void LibreCALDialog::startCalibration() // Create SOL measurements with correct port of calkit auto open = new CalibrationMeasurement::Open(cal); open->setPort(p+1); - open->setStandard(openStandards[portAssignment[p]-1]); + open->setStandard(openStandards[portAssignment[p]]); openMeasurements.insert(open); cal->measurements.push_back(open); auto _short = new CalibrationMeasurement::Short(cal); _short->setPort(p+1); - _short->setStandard(shortStandards[portAssignment[p]-1]); + _short->setStandard(shortStandards[portAssignment[p]]); shortMeasurements.insert(_short); cal->measurements.push_back(_short); auto load = new CalibrationMeasurement::Load(cal); load->setPort(p+1); - load->setStandard(loadStandards[portAssignment[p]-1]); + load->setStandard(loadStandards[portAssignment[p]]); loadMeasurements.insert(load); cal->measurements.push_back(load); for(unsigned int p2=p+1;p2getName() == forwardName) { - through->setStandard(ts); + if(ts.second->getName() == forwardName) { + through->setStandard(ts.second); through->setReverseStandard(false); - } else if(ts->getName() == reverseName) { - through->setStandard(ts); + } else if(ts.second->getName() == reverseName) { + through->setStandard(ts.second); through->setReverseStandard(true); } } @@ -581,7 +604,7 @@ void LibreCALDialog::startCalibration() }; disconnect(cal, &Calibration::measurementsUpdated, this, nullptr); - connect(cal, &Calibration::measurementsUpdated, this, startNextCalibrationStep); + connect(cal, &Calibration::measurementsUpdated, this, startNextCalibrationStep, Qt::QueuedConnection); connect(cal, &Calibration::measurementsAborted, this, [=](){ enableUI(); });