add support for logarithmically spaced calibration points

This commit is contained in:
Jan Käberich 2025-07-18 19:18:28 +02:00
parent c1705290ff
commit 8e917faed4
3 changed files with 54 additions and 7 deletions

View file

@ -1606,7 +1606,7 @@ std::vector<Calibration::Type> Calibration::getTypes()
return types;
}
bool Calibration::canCompute(Calibration::CalType type, double *startFreq, double *stopFreq, int *points)
bool Calibration::canCompute(Calibration::CalType type, double *startFreq, double *stopFreq, int *points, bool *isLog)
{
using RequiredMeasurements = struct {
CalibrationMeasurement::Base::Type type;
@ -1676,7 +1676,7 @@ bool Calibration::canCompute(Calibration::CalType type, double *startFreq, doubl
foundMeasurements.push_back(meas);
}
}
return hasFrequencyOverlap(foundMeasurements, startFreq, stopFreq, points);
return hasFrequencyOverlap(foundMeasurements, startFreq, stopFreq, points, isLog);
}
return false;
}
@ -1690,14 +1690,20 @@ bool Calibration::compute(Calibration::CalType type)
}
double start, stop;
int numPoints;
if(!canCompute(type, &start, &stop, &numPoints)) {
bool isLog;
if(!canCompute(type, &start, &stop, &numPoints, &isLog)) {
return false;
}
caltype = type;
try {
points.clear();
for(int i=0;i<numPoints;i++) {
double f = start + (stop - start) * i / (numPoints - 1);
double f;
if(!isLog) {
f = start + (stop - start) * i / (numPoints - 1);
} else {
f = start * pow(10.0, i * log10(stop / start) / (numPoints - 1));
}
Point p;
switch(type.type) {
case Type::SOLT: p = computeSOLT(f); break;
@ -1852,11 +1858,13 @@ void Calibration::deleteMeasurements()
measurements.clear();
}
bool Calibration::hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base *> m, double *startFreq, double *stopFreq, int *points)
bool Calibration::hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base *> m, double *startFreq, double *stopFreq, int *points, bool *isLog)
{
double minResolution = std::numeric_limits<double>::max();
double minFreq = 0;
double maxFreq = std::numeric_limits<double>::max();
unsigned int logCount = 0;
unsigned int linCount = 0;
for(auto meas : m) {
if(meas->numPoints() < 2) {
return false;
@ -1871,6 +1879,38 @@ bool Calibration::hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base *
if(resolution < minResolution) {
minResolution = resolution;
}
// check whether the frequency points are more linear or more logarithmic
double minDiff = std::numeric_limits<double>::max();
double maxDiff = 0;
double minRatio = std::numeric_limits<double>::max();
double maxRatio = 0;
for(unsigned int i=1;i<meas->numPoints();i++) {
double f_prev = meas->getPointFreq(i-1);
double f_next = meas->getPointFreq(i);
double diff = f_next - f_prev;
double ratio = f_next / f_prev;
if(diff < minDiff) {
minDiff = diff;
}
if(diff > maxDiff) {
maxDiff = diff;
}
if(ratio < minRatio) {
minRatio = ratio;
}
if(ratio > maxRatio) {
maxRatio = ratio;
}
}
double diffVariationNormalized = (maxDiff - minDiff) / maxDiff;
double ratioVariationNormalized = (maxRatio - minRatio) / maxRatio;
if(abs(diffVariationNormalized) < abs(ratioVariationNormalized)) {
// more linear
linCount++;
} else {
// more logarithmic
logCount++;
}
}
if(startFreq) {
*startFreq = minFreq;
@ -1881,6 +1921,9 @@ bool Calibration::hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base *
if(points) {
*points = (maxFreq - minFreq) / minResolution + 1;
}
if(isLog) {
*isLog = logCount > linCount;
}
if(maxFreq > minFreq) {
return true;
} else {

View file

@ -62,7 +62,7 @@ public:
static std::vector<Type> getTypes();
// Checks whether all measurements for a specific calibration are available.
// If pointer to the frequency/points variables are given, the start/stop frequency and number of points the calibration will have after the calculation is stored there
bool canCompute(CalType type, double *startFreq = nullptr, double *stopFreq = nullptr, int *points = nullptr);
bool canCompute(CalType type, double *startFreq = nullptr, double *stopFreq = nullptr, int *points = nullptr, bool *isLog = nullptr);
// Resets the calibration (deletes all measurements and calculated coefficients)
void reset();
// Returns the minimum number of ports for a given calibration type.
@ -130,7 +130,7 @@ private:
void createDefaultMeasurements(DefaultMeasurements dm);
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, bool *isLog = 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

View file

@ -41,6 +41,7 @@ public:
virtual double maxUsableFreq() = 0;
virtual double minFreq() = 0;
virtual double maxFreq() = 0;
virtual double getPointFreq(unsigned int p) = 0;
virtual unsigned int numPoints() = 0;
virtual bool readyForMeasurement() {return false;}
virtual bool readyForCalculation() {return false;}
@ -88,6 +89,7 @@ public:
virtual double maxUsableFreq() override;
virtual double minFreq() override {return points.size() > 0 ? points.front().frequency : std::numeric_limits<double>::max();}
virtual double maxFreq() override {return points.size() > 0 ? points.back().frequency : 0;}
virtual double getPointFreq(unsigned int p) override { return p < points.size() ? points[p].frequency : 0;}
virtual unsigned int numPoints() override {return points.size();}
virtual bool readyForMeasurement() override {return standard != nullptr;}
virtual bool readyForCalculation() override {return standard && points.size() > 0;}
@ -207,6 +209,7 @@ public:
virtual double maxUsableFreq() override;
virtual double minFreq() override {return points.size() > 0 ? points.front().frequency : std::numeric_limits<double>::max();}
virtual double maxFreq() override {return points.size() > 0 ? points.back().frequency : 0;}
virtual double getPointFreq(unsigned int p) override { return p < points.size() ? points[p].frequency : 0;}
virtual unsigned int numPoints() override {return points.size();}
virtual bool readyForMeasurement() override {return standard != nullptr;}
virtual bool readyForCalculation() override {return standard && points.size() > 0;}
@ -281,6 +284,7 @@ public:
virtual double maxUsableFreq() override {return maxFreq();}
virtual double minFreq() override {return points.size() > 0 ? points.front().frequency : std::numeric_limits<double>::max();}
virtual double maxFreq() override {return points.size() > 0 ? points.back().frequency : 0;}
virtual double getPointFreq(unsigned int p) override { return p < points.size() ? points[p].frequency : 0;}
virtual unsigned int numPoints() override;
virtual bool readyForMeasurement() override {return true;}
virtual bool readyForCalculation() override {return points.size() > 0;}