Merge pull request #21 from zarath/feature/refactor_calibration

Refactored Calibration Code
pull/190/head
Holger Müller 2020-06-24 22:14:27 +02:00 zatwierdzone przez GitHub
commit aa9f1accc9
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
2 zmienionych plików z 245 dodań i 275 usunięć

Wyświetl plik

@ -1,4 +1,5 @@
# NanoVNASaver - a python program to view and export Touchstone data from a NanoVNA
# NanoVNASaver
# A python program to view and export Touchstone data from a NanoVNA
# Copyright (C) 2019. Rune B. Broberg
#
# This program is free software: you can redistribute it and/or modify
@ -13,94 +14,138 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging
import math
import os
import re
from typing import List
import numpy as np
from .RFTools import Datapoint
RXP_CAL_LINE = re.compile(r"""^\s*
(?P<freq>\d+) \s+
(?P<shortr>[-0-9Ee.]+) \s+ (?P<shorti>[-0-9Ee.]+) \s+
(?P<openr>[-0-9Ee.]+) \s+ (?P<openi>[-0-9Ee.]+) \s+
(?P<loadr>[-0-9Ee.]+) \s+ (?P<loadi>[-0-9Ee.]+)(?: \s
(?P<throughr>[-0-9Ee.]+) \s+ (?P<throughi>[-0-9Ee.]+) \s+
(?P<isolationr>[-0-9Ee.]+) \s+ (?P<isolationi>[-0-9Ee.]+)
)?
""", re.VERBOSE)
logger = logging.getLogger(__name__)
# TODO: make a real class of calibration
class Calibration:
notes = []
s11short: List[Datapoint] = []
s11open: List[Datapoint] = []
s11load: List[Datapoint] = []
s21through: List[Datapoint] = []
s21isolation: List[Datapoint] = []
_CAL_NAMES = ("short", "open", "load", "through", "isolation",)
frequencies = []
def __init__(self):
# 1-port
e00 = [] # Directivity
e11 = [] # Port match
deltaE = [] # Tracking
self.notes = []
self.cals = {}
self._reset_cals()
self.frequencies = []
# 1-port
self.e00 = [] # Directivity
self.e11 = [] # Port match
self.deltaE = [] # Tracking
# 2-port
e30 = [] # Port match
e10e32 = [] # Transmission
# 2-port
self.e30 = [] # Port match
self.e10e32 = [] # Transmission
shortIdeal = np.complex(-1, 0)
useIdealShort = True
shortL0 = 5.7 * 10E-12
shortL1 = -8960 * 10E-24
shortL2 = -1100 * 10E-33
shortL3 = -41200 * 10E-42
shortLength = -34.2 # Picoseconds
# These numbers look very large, considering what Keysight suggests their numbers are.
self.shortIdeal = np.complex(-1, 0)
self.useIdealShort = True
self.shortL0 = 5.7 * 10E-12
self.shortL1 = -8960 * 10E-24
self.shortL2 = -1100 * 10E-33
self.shortL3 = -41200 * 10E-42
self.shortLength = -34.2 # Picoseconds
# These numbers look very large, considering what Keysight suggests their numbers are.
useIdealOpen = True
openIdeal = np.complex(1, 0)
openC0 = 2.1 * 10E-14 # Subtract 50fF for the nanoVNA calibration if nanoVNA is calibrated?
openC1 = 5.67 * 10E-23
openC2 = -2.39 * 10E-31
openC3 = 2.0 * 10E-40
openLength = 0
self.useIdealOpen = True
self.openIdeal = np.complex(1, 0)
self.openC0 = 2.1 * 10E-14 # Subtract 50fF for the nanoVNA calibration if nanoVNA is calibrated?
self.openC1 = 5.67 * 10E-23
self.openC2 = -2.39 * 10E-31
self.openC3 = 2.0 * 10E-40
self.openLength = 0
useIdealLoad = True
loadR = 25
loadL = 0
loadC = 0
loadLength = 0
loadIdeal = np.complex(0, 0)
self.useIdealLoad = True
self.loadR = 25
self.loadL = 0
self.loadC = 0
self.loadLength = 0
self.loadIdeal = np.complex(0, 0)
useIdealThrough = True
throughLength = 0
self.useIdealThrough = True
self.throughLength = 0
isCalculated = False
self.isCalculated = False
source = "Manual"
self.source = "Manual"
def isValid2Port(self):
valid = len(self.s21through) > 0 and len(self.s21isolation) > 0 and self.isValid1Port()
valid &= len(self.s21through) == len(self.s21isolation) == len(self.s11short)
return valid
def _reset_cals(self):
for name in Calibration._CAL_NAMES:
self.cals[name] = []
@property
def s11short(self) -> List[Datapoint]:
return self.cals["short"]
@s11short.setter
def s11short(self, values: List[Datapoint]):
self.cals["short"] = values
@property
def s11open(self) -> List[Datapoint]:
return self.cals["open"]
@s11open.setter
def s11open(self, values: List[Datapoint]):
self.cals["open"] = values
@property
def s11load(self) -> List[Datapoint]:
return self.cals["load"]
@s11load.setter
def s11load(self, values: List[Datapoint]):
self.cals["load"] = values
@property
def s21through(self) -> List[Datapoint]:
return self.cals["through"]
@s21through.setter
def s21through(self, values: List[Datapoint]):
self.cals["through"] = values
@property
def s21isolation(self) -> List[Datapoint]:
return self.cals["isolation"]
@s21isolation.setter
def s21isolation(self, values: List[Datapoint]):
self.cals["isolation"] = values
def isValid1Port(self):
valid = len(self.s11short) > 0 and len(self.s11open) > 0 and len(self.s11load) > 0
valid &= len(self.s11short) == len(self.s11open) == len(self.s11load)
return valid
lengths = [len(self.cals[x])
for x in Calibration._CAL_NAMES[:3]]
return min(lengths) > 0 and min(lengths) == max(lengths)
def calculateCorrections(self) -> (bool, str):
def isValid2Port(self):
lengths = [len(self.cals[x]) for x in Calibration._CAL_NAMES]
return min(lengths) > 0 and min(lengths) == max(lengths)
def calc_corrections(self):
if not self.isValid1Port():
logger.warning("Tried to calibrate from insufficient data.")
if len(self.s11short) == 0 or len(self.s11open) == 0 or len(self.s11load) == 0:
return (False,
"All of short, open and load calibration steps"
"must be completed for calibration to be applied.")
return False, "All calibration data sets must be the same size."
self.frequencies = [int] * len(self.s11short)
self.e00 = [np.complex] * len(self.s11short)
self.e11 = [np.complex] * len(self.s11short)
self.deltaE = [np.complex] * len(self.s11short)
self.e30 = [np.complex] * len(self.s11short)
self.e10e32 = [np.complex] * len(self.s11short)
logger.debug("Calculating calibration for %d points.", len(self.s11short))
logger.warning(
"Tried to calibrate from insufficient data.")
raise ValueError(
"All of short, open and load calibration steps"
"must be completed for calibration to be applied.")
nr_points = len(self.cals["short"])
logger.debug("Calculating calibration for %d points.", nr_points)
self.frequencies = []
self.e00 = [np.complex] * nr_points
self.e11 = [np.complex] * nr_points
self.deltaE = [np.complex] * nr_points
self.e30 = [np.complex] * nr_points
self.e10e32 = [np.complex] * nr_points
if self.useIdealShort:
logger.debug("Using ideal values.")
else:
@ -109,9 +154,11 @@ class Calibration:
logger.debug("Calculating 2-port calibration.")
else:
logger.debug("Calculating 1-port calibration.")
for i in range(len(self.s11short)):
self.frequencies[i] = self.s11short[i].freq
f = self.s11short[i].freq
for i, cur_short in enumerate(self.cals["short"]):
cur_open = self.cals["open"][i]
cur_load = self.cals["load"][i]
f = cur_short.freq
self.frequencies.append(f)
pi = math.pi
if self.useIdealShort:
@ -151,9 +198,9 @@ class Calibration:
g3 = g3 * np.exp(
np.complex(0, 1) * 2 * 2 * math.pi * f * self.loadLength * -1)
gm1 = np.complex(self.s11short[i].re, self.s11short[i].im)
gm2 = np.complex(self.s11open[i].re, self.s11open[i].im)
gm3 = np.complex(self.s11load[i].re, self.s11load[i].im)
gm1 = np.complex(cur_short.re, cur_short.im)
gm2 = np.complex(cur_open.re, cur_open.im)
gm3 = np.complex(cur_load.re, cur_load.im)
try:
denominator = (
@ -181,52 +228,55 @@ class Calibration:
" for two of short, open and load?")
logger.debug(
"Division error at index %d"
" Short == Load: %s"
" Short == Open: %s"
" Open == Load: %s",
i,
self.s11short[i] == self.s11load[i],
self.s11short[i] == self.s11open[i],
self.s11open[i] == self.s11load[i])
return (self.isCalculated,
f"Two of short, open and load returned the same"
f" values at frequency {self.s11open[i].freq}Hz.")
" Short == Load: %s Short == Open: %s"
" Open == Load: %s", i,
cur_short == cur_load, cur_short == cur_open,
cur_open == cur_load)
raise ValueError(
f"Two of short, open and load returned the same"
f" values at frequency {f}Hz.")
if self.isValid2Port():
cur_through = self.cals["through"][i]
cur_isolation = self.cals["isolation"][i]
self.e30[i] = np.complex(
self.s21isolation[i].re, self.s21isolation[i].im)
s21m = np.complex(self.s21through[i].re, self.s21through[i].im)
cur_isolation.re, cur_isolation.im)
s21m = np.complex(cur_through.re, cur_through.im)
if not self.useIdealThrough:
gammaThrough = np.exp(
np.complex(0, 1) * 2 * math.pi * self.throughLength * f * -1)
np.complex(0, 1) * 2 * math.pi *
self.throughLength * f * -1)
s21m = s21m / gammaThrough
self.e10e32[i] = (s21m - self.e30[i]) * (1 - (self.e11[i]*self.e11[i]))
self.e10e32[i] = (s21m - self.e30[i]) * (
1 - (self.e11[i] * self.e11[i]))
self.isCalculated = True
logger.debug("Calibration correctly calculated.")
return self.isCalculated, "Calibration successful."
def correct11(self, re, im, freq):
s11m = np.complex(re, im)
distance = 10**10
index = 0
for i in range(len(self.s11short)):
if abs(self.s11short[i].freq - freq) < distance:
for i, cur_short in enumerate(self.cals["short"]):
if abs(cur_short.freq - freq) < distance:
index = i
distance = abs(self.s11short[i].freq - freq)
# TODO: Interpolate with the adjacent data point to get better corrections?
distance = abs(cur_short.freq - freq)
# TODO: Interpolate with the adjacent data point
# to get better corrections?
s11 = (s11m - self.e00[index]) / ((s11m * self.e11[index]) - self.deltaE[index])
s11 = (s11m - self.e00[index]) / (
(s11m * self.e11[index]) - self.deltaE[index])
return s11.real, s11.imag
def correct21(self, re, im, freq):
s21m = np.complex(re, im)
distance = 10**10
index = 0
for i in range(len(self.s21through)):
if abs(self.s21through[i].freq - freq) < distance:
for i, cur_through in enumerate(self.cals["through"]):
if abs(cur_through.freq - freq) < distance:
index = i
distance = abs(self.s21through[i].freq - freq)
distance = abs(cur_through.freq - freq)
s21 = (s21m - self.e30[index]) / self.e10e32[index]
return s21.real, s21.imag
@ -242,104 +292,74 @@ class Calibration:
output = input_val * np.exp(np.complex(0, 1) * 2 * math.pi * d.freq * delay * -1)
return Datapoint(d.freq, output.real, output.imag)
def saveCalibration(self, filename):
# TODO: implement tests
def save(self, filename: str):
# Save the calibration data to file
if filename == "" or not self.isValid1Port():
return False
try:
file = open(filename, "w+")
file.write("# Calibration data for NanoVNA-Saver\n")
if not self.isValid1Port():
raise ValueError("Not a valid 1-Port calibration")
with open(filename, "w+") as calfile:
calfile.write("# Calibration data for NanoVNA-Saver\n")
for note in self.notes:
file.write(f"! {note}\n")
file.write(
calfile.write(f"! {note}\n")
calfile.write(
"# Hz ShortR ShortI OpenR OpenI LoadR LoadI"
" ThroughR ThroughI IsolationR IsolationI\n")
for i in range(len(self.s11short)):
freq = str(self.s11short[i].freq)
shortr = str(self.s11short[i].re)
shorti = str(self.s11short[i].im)
openr = str(self.s11open[i].re)
openi = str(self.s11open[i].im)
loadr = str(self.s11load[i].re)
loadi = str(self.s11load[i].im)
file.write(" ".join((freq, shortr, shorti, openr, openi, loadr, loadi)))
for i, cur_short in enumerate(self.cals["short"]):
data = [
cur_short.freq,
cur_short.re, cur_short.im,
self.s11open[i].re, self.s11open[i].im,
self.s11load[i].re, self.s11load[i].im,
]
if self.isValid2Port():
throughr = str(self.s21through[i].re)
throughi = str(self.s21through[i].im)
isolationr = str(self.s21isolation[i].re)
isolationi = str(self.s21isolation[i].im)
file.write(" ".join((throughr, throughi, isolationr, isolationi)))
file.write("\n")
file.close()
return True
except Exception as e:
logger.exception("Error saving calibration data: %s", e)
return False
def loadCalibration(self, filename):
# Load calibration data from file
if filename == "":
return
data.extend([
self.s21through[i].re, self.s21through[i].im,
self.s21isolation[i].re, self.s21isolation[i].im
])
calfile.write(" ".join([str(val) for val in data]))
calfile.write("\n")
# TODO: implement tests
# TODO: Exception should be catched by caller
def load(self, filename):
self.source = os.path.basename(filename)
self.s11short = []
self.s11open = []
self.s11load = []
self.s21through = []
self.s21isolation = []
self._reset_cals()
self.notes = []
try:
file = open(filename, "r")
lines = file.readlines()
parsed_header = False
for line in lines:
parsed_header = False
with open(filename) as calfile:
for i, line in enumerate(calfile):
line = line.strip()
if line.startswith("!"):
note = line[2:]
self.notes.append(note)
continue
if line.startswith("#") and not parsed_header:
# Check that this is a valid header
if line == ("# Hz ShortR ShortI OpenR OpenI LoadR LoadI"
if line.startswith("#"):
if not parsed_header:
# Check that this is a valid header
if line == (
"# Hz ShortR ShortI OpenR OpenI LoadR LoadI"
" ThroughR ThroughI IsolationR IsolationI"):
parsed_header = True
parsed_header = True
continue
if not parsed_header:
logger.warning(
"Warning: Read line without having read header: %s", line)
"Warning: Read line without having read header: %s",
line)
continue
try:
if line.count(" ") == 6:
freq, shortr, shorti, openr, openi, loadr, loadi = line.split(
" ")
self.s11short.append(
Datapoint(int(freq), float(shortr), float(shorti)))
self.s11open.append(
Datapoint(int(freq), float(openr), float(openi)))
self.s11load.append(
Datapoint(int(freq), float(loadr), float(loadi)))
else:
(freq, shortr, shorti, openr, openi, loadr, loadi,
throughr, throughi, isolationr, isolationi) = line.split(" ")
self.s11short.append(
Datapoint(int(freq), float(shortr), float(shorti)))
self.s11open.append(
Datapoint(int(freq), float(openr), float(openi)))
self.s11load.append(
Datapoint(int(freq), float(loadr), float(loadi)))
self.s21through.append(
Datapoint(int(freq), float(throughr), float(throughi)))
self.s21isolation.append(
Datapoint(int(freq), float(isolationr), float(isolationi)))
m = RXP_CAL_LINE.search(line)
if not m:
logger.warning("Illegal data in cal file. Line %i", i)
cal = m.groupdict()
except ValueError as e:
logger.exception(
"Error parsing calibration data \"%s\": %s", line, e)
file.close()
except Exception as e:
logger.exception("Failed loading calibration data: %s", e)
if cal["throughr"]:
nr_cals = 5
else:
nr_cals = 3
for name in Calibration._CAL_NAMES[:nr_cals]:
self.cals[name].append(
Datapoint(int(cal["freq"]),
float(cal[f"{name}r"]),
float(cal[f"{name}i"])))

Wyświetl plik

@ -24,6 +24,10 @@ from NanoVNASaver.Calibration import Calibration
logger = logging.getLogger(__name__)
def _format_cal_label(data: list, prefix: str = "Set") -> str:
return f"{prefix} ({len(data)} points)"
class CalibrationWindow(QtWidgets.QWidget):
nextStep = -1
@ -57,27 +61,15 @@ class CalibrationWindow(QtWidgets.QWidget):
calibration_control_group = QtWidgets.QGroupBox("Calibrate")
calibration_control_layout = QtWidgets.QFormLayout(calibration_control_group)
btn_cal_short = QtWidgets.QPushButton("Short")
btn_cal_short.clicked.connect(self.manualSaveShort)
self.cal_short_label = QtWidgets.QLabel("Uncalibrated")
btn_cal_open = QtWidgets.QPushButton("Open")
btn_cal_open.clicked.connect(self.manualSaveOpen)
self.cal_open_label = QtWidgets.QLabel("Uncalibrated")
btn_cal_load = QtWidgets.QPushButton("Load")
btn_cal_load.clicked.connect(self.manualSaveLoad)
self.cal_load_label = QtWidgets.QLabel("Uncalibrated")
btn_cal_through = QtWidgets.QPushButton("Through")
btn_cal_through.clicked.connect(self.manualSaveThrough)
# btn_cal_through.setDisabled(True)
self.cal_through_label = QtWidgets.QLabel("Uncalibrated")
btn_cal_isolation = QtWidgets.QPushButton("Isolation")
btn_cal_isolation.clicked.connect(self.manualSaveIsolation)
# btn_cal_isolation.setDisabled(True)
self.cal_isolation_label = QtWidgets.QLabel("Uncalibrated")
cal_btn = {}
self.cal_label = {}
for label_name in Calibration._CAL_NAMES:
self.cal_label[label_name] = QtWidgets.QLabel("Uncalibrated")
cal_btn[label_name] = QtWidgets.QPushButton(
label_name.capitalize())
cal_btn[label_name].clicked.connect(lambda: self.manual_save(label_name))
calibration_control_layout.addRow(
cal_btn[label_name], self.cal_label[label_name])
self.input_offset_delay = QtWidgets.QDoubleSpinBox()
self.input_offset_delay.setValue(0)
@ -86,12 +78,6 @@ class CalibrationWindow(QtWidgets.QWidget):
self.input_offset_delay.valueChanged.connect(self.setOffsetDelay)
self.input_offset_delay.setRange(-10e6, 10e6)
calibration_control_layout.addRow(btn_cal_short, self.cal_short_label)
calibration_control_layout.addRow(btn_cal_open, self.cal_open_label)
calibration_control_layout.addRow(btn_cal_load, self.cal_load_label)
calibration_control_layout.addRow(btn_cal_isolation, self.cal_isolation_label)
calibration_control_layout.addRow(btn_cal_through, self.cal_through_label)
calibration_control_layout.addRow(QtWidgets.QLabel(""))
calibration_control_layout.addRow("Offset delay", self.input_offset_delay)
@ -239,50 +225,14 @@ class CalibrationWindow(QtWidgets.QWidget):
return False
return True
def manualSaveShort(self):
def cal_save(self, name):
self.app.calibration.cals[name] = self.app.data
self.cal_label[name].setText(
_format_cal_label(self.app.data))
def manual_save(self, name):
if self.checkExpertUser():
self.saveShort()
def saveShort(self):
self.app.calibration.s11short = self.app.data
self.cal_short_label.setText(
f"Data set ({self.app.calibration.s11short} points)")
def manualSaveOpen(self):
if self.checkExpertUser():
self.saveOpen()
def saveOpen(self):
self.app.calibration.s11open = self.app.data
self.cal_open_label.setText(
f"Data set ({self.app.calibration.s11open} points)")
def manualSaveLoad(self):
if self.checkExpertUser():
self.saveLoad()
def saveLoad(self):
self.app.calibration.s11load = self.app.data
self.cal_load_label.setText(
f"Data set ({self.app.calibration.s11load} points)")
def manualSaveIsolation(self):
if self.checkExpertUser():
self.saveIsolation()
def saveIsolation(self):
self.app.calibration.s21isolation = self.app.data21
self.cal_isolation_label.setText(
f"Data set ({self.app.calibration.s21isolation} points)")
def manualSaveThrough(self):
if self.checkExpertUser():
self.saveThrough()
def saveThrough(self):
self.app.calibration.s21through = self.app.data21
self.cal_through_label.setText(
f"Data set ({self.app.calibration.s21through} points)")
self.cal_save(name)
def listCalibrationStandards(self):
self.cal_standard_save_selector.clear()
@ -469,11 +419,8 @@ class CalibrationWindow(QtWidgets.QWidget):
def reset(self):
self.app.calibration = Calibration()
self.cal_short_label.setText("Uncalibrated")
self.cal_open_label.setText("Uncalibrated")
self.cal_load_label.setText("Uncalibrated")
self.cal_through_label.setText("Uncalibrated")
self.cal_isolation_label.setText("Uncalibrated")
for label in self.cal_label.values():
label.setText("Uncalibrated")
self.calibration_status_label.setText("Device calibration")
self.calibration_source_label.setText("Device")
self.notes_textedit.clear()
@ -572,8 +519,8 @@ class CalibrationWindow(QtWidgets.QWidget):
'Invalid data for "through" calibration standard. Using ideal values.')
logger.debug("Attempting calibration calculation.")
valid, error = self.app.calibration.calculateCorrections()
if valid:
try:
self.app.calibration.calc_corrections()
self.calibration_status_label.setText(
f"Application calibration ({len(self.app.calibration.s11short)} points)")
if self.use_ideal_values.isChecked():
@ -591,9 +538,9 @@ class CalibrationWindow(QtWidgets.QWidget):
self.app.saveData(self.app.worker.data11,
self.app.worker.data21, self.app.sweepSource)
self.app.worker.signals.updated.emit()
else:
except ValueError as e:
# showError here hides the calibration window, so we need to pop up our own
QtWidgets.QMessageBox.warning(self, "Error applying calibration", error)
QtWidgets.QMessageBox.warning(self, "Error applying calibration", str(e))
self.calibration_status_label.setText("Applying calibration failed.")
self.calibration_source_label.setText(self.app.calibration.source)
@ -608,24 +555,26 @@ class CalibrationWindow(QtWidgets.QWidget):
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
filter="Calibration Files (*.cal);;All files (*.*)")
if filename:
self.app.calibration.loadCalibration(filename)
if self.app.calibration.isValid1Port():
self.cal_short_label.setText(
f"Loaded ({len(self.app.calibration.s11short)})")
self.cal_open_label.setText(
f"Loaded ({len(self.app.calibration.s11open)})")
self.cal_load_label.setText(
f"Loaded ({len(self.app.calibration.s11load)})")
if self.app.calibration.isValid2Port():
self.cal_through_label.setText(
f"Loaded ({len(self.app.calibration.s21through)})")
self.cal_isolation_label.setText(
f"Loaded ({len(self.app.calibration.s21isolation)})")
self.calculate()
self.notes_textedit.clear()
for note in self.app.calibration.notes:
self.notes_textedit.appendPlainText(note)
self.app.settings.setValue("CalibrationFile", filename)
self.app.calibration.load(filename)
if not self.app.calibration.isValid1Port():
return
cals = (
("short", self.app.calibration.s11short),
("open", self.app.calibration.s11open),
("load", self.app.calibration.s11load),
("through", self.app.calibration.s21through),
("isolation", self.app.calibration.s21isolation),
)
for i, cal in enumerate(cals):
self.cal_label[cal[0]].setText(
_format_cal_label(cal[1], "Loaded"))
if i == 2 and not self.app.calibration.isValid2Port():
break
self.calculate()
self.notes_textedit.clear()
for note in self.app.calibration.notes:
self.notes_textedit.appendPlainText(note)
self.app.settings.setValue("CalibrationFile", filename)
def saveCalibration(self):
if not self.app.calibration.isCalculated:
@ -645,9 +594,10 @@ class CalibrationWindow(QtWidgets.QWidget):
logger.debug("No file name selected.")
return
self.app.calibration.notes = self.notes_textedit.toPlainText().splitlines()
if filename and self.app.calibration.saveCalibration(filename):
try:
self.app.calibration.save(filename)
self.app.settings.setValue("CalibrationFile", filename)
else:
except IOError:
logger.error("Calibration save failed!")
self.app.showError("Calibration save failed.")
@ -724,7 +674,7 @@ class CalibrationWindow(QtWidgets.QWidget):
if self.nextStep == 0:
# Short
self.saveShort()
self.save("short")
self.nextStep = 1
open_step = QtWidgets.QMessageBox(
@ -748,7 +698,7 @@ class CalibrationWindow(QtWidgets.QWidget):
if self.nextStep == 1:
# Open
self.saveOpen()
self.save("open")
self.nextStep = 2
load_step = QtWidgets.QMessageBox(
QtWidgets.QMessageBox.Information,
@ -769,7 +719,7 @@ class CalibrationWindow(QtWidgets.QWidget):
if self.nextStep == 2:
# Load
self.saveLoad()
self.save("load")
self.nextStep = 3
continue_step = QtWidgets.QMessageBox(
QtWidgets.QMessageBox.Information,
@ -813,7 +763,7 @@ class CalibrationWindow(QtWidgets.QWidget):
if self.nextStep == 3:
# Isolation
self.saveIsolation()
self.save("isolation")
self.nextStep = 4
through_step = QtWidgets.QMessageBox(
QtWidgets.QMessageBox.Information,
@ -835,7 +785,7 @@ class CalibrationWindow(QtWidgets.QWidget):
if self.nextStep == 4:
# Done
self.saveThrough()
self.save("through")
apply_step = QtWidgets.QMessageBox(
QtWidgets.QMessageBox.Information,
"Calibrate complete",