Conditions, Schaltmatrix und Pfadkorrekturen¶
Pfadkorrekturen verbinden die in einem DOT-Graph beschriebenen Übertragungswege mit den tatsächlich gemessenen Größen. Bei frequenzabhängigen Messaufbauten müssen drei Schritte zusammenpassen:
aktive Graphzweige auswählen;
reale Geräte und Schaltmatrix auf die Frequenz einstellen;
die Korrektur des aktiven Pfades lesen und anwenden.
Knoten, Kanten, Conditions und dev/what-Attribute sind in der
DOT-Referenz vollständig beschrieben.
Die Korrekturwerte selbst werden typischerweise durch einen INI-Kanal und eine DAT-Datei bereitgestellt. Syntax, Einheiten, komplexe Werte und Unsicherheiten stehen in der INI- und DAT-Referenz.
Conditions auswerten¶
EvaluateConditions aktiviert Knoten und Kanten anhand des expliziten
Kontexts:
mg.EvaluateConditions(context={"frequency": frequency})
Mit doAction=False wird nur der Graphzustand berechnet. Das ist für
Preflight, Scanplanung und Pfadprüfung wichtig, weil dabei keine Hardware
geschaltet werden darf.
Ein aktives Element kann zusätzlich ein action-Attribut besitzen.
Ausgeführt wird ausschließlich ein direkter Methodenaufruf auf einem Objekt
aus dem Kontext mit literalen Argumenten. Beliebiger Python-Code ist nicht
zulässig. Actions eignen sich für kleine, ausdrücklich konfigurierte
Zustandswechsel; gerätespezifische Schaltlogik gehört bevorzugt in den
Treiber.
Eine kleine Matrix kann alternativ direkt über Actions geschaltet werden:
SwitchLF [condition="FREQUENCY <= 1e9"
action="switch.switch_to(0)"]
SwitchHF [condition="FREQUENCY > 1e9"
action="switch.switch_to(1)"]
mg.EvaluateConditions(context={
"frequency": frequency,
"switch": switch_instance,
})
Diese Variante und ein frequenzabhängiges SetFreq im Switch-Treiber sind
Alternativen. Derselbe Relaiszustand soll nicht über beide Wege gleichzeitig
gesetzt werden.
Switch-Matrix über SetFreq¶
Eine Switch-Matrix ist ein reguläres Gerät im MGraph. Ihr Treiber
implementiert SetFreq(frequency) und wählt anhand seiner INI-Konfiguration
den erforderlichen Relaiszustand. SetFreq_Devices ruft diese Methode
zusammen mit den anderen frequenzabhängigen Geräten auf:
mg.EvaluateConditions(context={"frequency": frequency})
mg.SetFreq_Devices(frequency)
Die Conditions und die Schaltschwelle des Treibers müssen dieselben
Bereichsgrenzen verwenden. Der Graph wählt beispielsweise den LF-Zweig bis
einschließlich 1 GHz, während der Switch-Treiber bei f <= 1e9 dieselbe
Relaisstellung wählt.
Vor dem Umschalten wird ein Signalgenerator auf einen sicheren Startpegel gesetzt oder RF abgeschaltet. Das ist besonders wichtig, wenn der Frequenzwechsel einen anderen Verstärker mit abweichender Eingangsgrenze aktiviert.
Komplexeres TEM-Beispiel¶
digraph {
Switch [ini="sw_gtem.ini"]
Sg [ini="sg.ini"]
AmpLF [ini="amp-lf.ini"
condition="FREQUENCY <= 1e9"]
AmpHF [ini="amp-hf.ini"
condition="FREQUENCY > 1e9"]
PathSgLF [ini="sg-lf.ini"]
PathSgHF [ini="sg-hf.ini"]
PathLFCell [ini="lf-cell.ini"]
PathHFCell [ini="hf-cell.ini"]
Sg -> SgLF [condition="FREQUENCY <= 1e9"]
Sg -> SgHF [condition="FREQUENCY > 1e9"]
SgLF -> AmpInLF [dev=PathSgLF what="S21"]
SgHF -> AmpInHF [dev=PathSgHF what="S21"]
AmpInLF -> AmpOutLF [dev=AmpLF what="S21"]
AmpInHF -> AmpOutHF [dev=AmpHF what="S21"]
AmpOutLF -> GTEM [dev=PathLFCell what="S21"]
AmpOutHF -> GTEM [dev=PathHFCell what="S21"]
}
Der Condition-Kontext wählt den roten oder blauen Korrekturpfad. Parallel
dazu stellt SetFreq_Devices die Switch-Matrix und alle aktiven Geräte
auf dieselbe Frequenz ein.¶
Dieses vereinfachte Beispiel zeigt nur den Vorwärtspfad. Eine reale TEM-Verifikation ergänzt Abzweige zu Vorwärts- und Rückwärtsleistungsmessern sowie deren eigene Koppler- und Kabelkorrekturen.
Gesamtkorrektur lesen¶
get_path_correction liefert die Gesamtkorrektur zwischen zwei
Messpositionen:
from mpylab.tools.aunits import POWERRATIO
correction = mg.get_path_correction(
names["sg"],
names["port"],
POWERRATIO,
)
Ohne unit wird AMPLITUDERATIO verwendet. Bei der Umwandlung eines
komplexen Amplitudenverhältnisses in ein Leistungsverhältnis wird
abs(S21) ** 2 gebildet. Einheit und Unsicherheit bleiben erhalten.
get_path_corrections gibt zusätzlich die einzelnen
Korrekturelemente zurück. Der Schlüssel "total" enthält das
Gesamtergebnis:
details = mg.get_path_corrections("Sg", "GTEM")
total = details["total"]
Diese detaillierte Form eignet sich für Diagnose und Reports. Anwendungslogik
sollte für die übliche Gesamtkorrektur get_path_correction verwenden.
Kohärente Reihen- und Parallelpfade¶
Alle aktiven Pfade werden unabhängig von der angeforderten Ausgabeeinheit als komplexe Amplitudenverhältnisse verknüpft:
POWERRATIO entsteht erst nach dieser Summe und einer eventuellen Division
durch einen Referenzpfad. Zwei Beiträge mit Amplitudenbetrag eins ergeben bei
0, 90 und 180 Grad Phasendifferenz somit Leistungsverhältnisse von 4, 2 und 0.
In Reihe werden komplexe Amplituden multipliziert; ihre Phasen addieren sich.
Gemeinsame Segmente behalten dieselben unsicheren Eingangsgrößen.
Ein S-Parameter-Betrag d in dB entspricht der Amplitude 10**(d/20).
Polare DAT-Werte behalten ihre Phase. Die historische DAT-Darstellung
POWERRATIO codiert |S21|**2 * exp(1j*phase) und wird vor der
Verknüpfung in Amplitude umgerechnet. Sie ist keine physikalische komplexe
Leistung. Skalare Betragsdaten setzen implizit Phase null voraus und können
die Interferenz eines tatsächlichen Parallelaufbaus nicht bestimmen.
Das Modell setzt kohärente Beiträge einer Quelle, konsistente Wellennormierung und vernachlässigbare oder bereits enthaltene Reflexionseffekte voraus. Teilungs- und Kombinationskoeffizienten müssen in den konfigurierten Übertragungswegen enthalten sein. Der Faktor vier oben bezieht sich auf einen einzelnen Einheitsbeitrag am Summationspunkt; er bedeutet keinen passiven Leistungsgewinn beim Aufteilen einer Quelle. Vollständige S-Matrix-Netzwerke, Fehlanpassung und inkohärente Leistungsaddition liegen außerhalb dieses Modells. Zu den Wellenkonventionen siehe F. Caspers, RF engineering basic concepts: S-parameters.
get_path_correction(end, start) liefert die inverse Korrektur, nicht S12.
Ein Nenner null führt zu ZeroDivisionError, eine fehlende Verbindung zu
ValueError. get_path_corrections behält null für einen fehlenden
Vorwärtspfad und eins für den leeren Pfad eines Knotens zu sich selbst bei.
Die Geräteeinträge bleiben die ursprünglichen Größen; nur "total" folgt
der angeforderten Einheit. Jeder Gerätekanal wird je Abfrage einmal gelesen,
auch bei Quotienten über einen gemeinsamen Vorgänger. Die nächste Abfrage
liest erneut, damit Frequenzwechsel keine veralteten Werte verwenden.
Unsicherheit bei Auslöschung¶
Das Ergebnis behält die Abhängigkeiten der SCUQ-Ausdrücke, statt jeden Pfad
durch einen unabhängigen Unsicherheitseingang zu ersetzen. Auch gemischte
reelle und komplexe Ausdrücke behalten gemeinsame skalare Eingänge.
Die Leistung wird über das kartesische Betragsquadrat mit der Jacobi-Matrix
(2*Re(H), 2*Im(H)) berechnet. Dadurch entfällt die problematische
Ableitung von abs(H) bei null.
SCUQ propagiert Unsicherheiten weiterhin in erster Ordnung. Bei nomineller Auslöschung ist diese Jacobi-Matrix null, obwohl unabhängige Amplitudenfehler in Realisierungen eine Leistung ungleich null ergeben. Eine verschwindende linearisierte Leistungsunsicherheit belegt daher keine exakte Auslöschung. Für solche Fälle sind die Amplitudenkovarianz und eine geeignete Auswertung höherer Ordnung oder Monte-Carlo-Rechnung erforderlich. Die Regressionstests enthalten analytische Interferenzfälle, Auslöschung gemeinsamer Eingänge und reproduzierbare Monte-Carlo-Vergleiche zur Verdeutlichung dieser Grenze.
Kompatibilität¶
INI/DAT-Format und Schlüssel der Diagnose-Dictionaries bleiben unverändert.
Zuvor addierte eine POWERRATIO-Abfrage Pfadleistungen oder behielt eine
codierte Übertragungsphase. Bei parallelen oder phasenbehafteten Pfaden können
die korrigierten Ergebnisse deshalb abweichen. Gespeicherte Messwerte werden
nicht automatisch umgeschrieben. Eine Neuauswertung verwendet die korrigierte
Rechnung. Zurückgegebene Korrekturen behalten SCUQ-Ausdrücke; neue Pickles mit
diesen Ausdrücken benötigen eine mpylab-Version mit den Hilfsklassen für
Übertragungsausdrücke.
Korrektur anwenden¶
Die Richtung muss fachlich ausdrücklich gewählt werden:
corrected = mg.apply_path_correction(
measured,
correction,
operation="divide",
magnitude=True,
output_unit=VOLT,
)
operation ist "multiply" oder "divide". magnitude=False
erhält die Phase; magnitude=True erzeugt eine reelle Betragsgröße mit
Unsicherheit.
Schnelle wiederholte Anwendung¶
Wenn viele Messwerte mit derselben Korrektur verarbeitet werden, kann sie einmal vorbereitet werden:
prepared = mg.prepare_path_correction(
correction,
operation="divide",
magnitude=True,
output_unit=VOLT,
)
corrected = [
mg.apply_path_correction(value, prepared)
for value in measured_values
]
Eine exakt bekannte, konstante Korrektur kann dadurch einen schnellen Skalierungspfad verwenden. Unsichere oder nicht unterstützte Fälle fallen automatisch auf die vollständige SCUQ-Rechnung zurück.
Das vorbereitete Objekt darf nur wiederverwendet werden, solange Frequenz,
aktiver Graphpfad und zugrunde liegende Kalibrierdaten unverändert sind. Nach
jedem EvaluateConditions oder Frequenzwechsel wird die Pfadkorrektur neu
gelesen und gegebenenfalls neu vorbereitet.
Prüfregeln¶
Conditions vor dem Lesen einer Korrektur auswerten.
Schaltmatrix und Graph mit identischen Bereichsgrenzen konfigurieren.
Grenzfrequenzen auf fehlende oder doppelte Pfade testen.
Korrekturen als SCUQ-Quantities führen.
Multiplikation oder Division und das Verwerfen der Phase ausdrücklich angeben.
Vorbereitete Korrekturen nicht über einen Graphzustandswechsel hinweg wiederverwenden.