zusammenfügen 02.2.

This commit is contained in:
2026-02-02 20:01:37 +01:00
parent 774acc3854
commit 4e7c55500b
11 changed files with 62593 additions and 2121 deletions

View File

@@ -1,91 +1,85 @@
import sympy as sp
import numpy as np
from dataclasses import dataclass, field
from typing import Dict, Tuple, Iterable, Any
from Export import Export
import numpy as np
import sympy as sp
from typing import Dict, Iterable
from Datenbank import Datenbankzugriff
from Export import Export
@dataclass
class StochastischesModell:
"""Stochastisches Modell zur Aufstellung und Auswertung von Varianz-Kovarianz-Matrizen.
Die Klasse stellt Methoden zur Verfügung für:
- symbolischen Aufbau der Varianz-Kovarianz-Matrix der Beobachtungen Qll,
- numerische Substitution von Qll aus der Datenbank,
- symbolischen und numerischen Aufbau der Zusatz-Varianz-Kovarianz-Matrix QAA für Anschlusspunkte (weiche Lagerung, lA_*),
- Ableitung zentraler Matrizen der Ausgleichung (P, Qxx, Qll_dach, Qvv) als Hilfsfunktionen.
Die Grundidee ist, die stochastischen Zusammenhänge zunächst symbolisch abzubilden (SymPy) und anschließend
mit Datenbankwerten zu substituieren.
"""
n_beob: int
sigma_beob: Iterable[float] =None #σ a priori der einzelnen Beobachtung
gruppe_beob: Iterable[int] =None #Gruppenzugehörigkeit jeder Beobachtung (Distanz, Richtung, GNSS, Nivellement,...,)
sigma0_gruppe: Dict[int, float] = field(default_factory=dict) #σ0² für jede Gruppe
sigma_beob: Iterable[float] =None #σ a priori der einzelnen Beobachtung
gruppe_beob: Iterable[int] =None #Gruppenzugehörigkeit jeder Beobachtung (Distanz, Richtung, GNSS, Nivellement,...,)
sigma0_gruppe: Dict[int, float] = field(default_factory=dict) #σ0² für jede Gruppe
def __post_init__(self):
# Defaults setzen
if self.sigma_beob is None:
self.sigma_beob = [1.0] * int(self.n_beob)
def __init__(self, pfad_datenbank: str) -> None:
"""Initialisiert das stochastische Modell.
if self.gruppe_beob is None:
self.gruppe_beob = [1] * int(self.n_beob)
# In SymPy-Spaltenvektoren umwandeln
#self.sigma_beob = sp.Matrix(list(self.sigma_beob))
#self.gruppe_beob = sp.Matrix(list(self.gruppe_beob))
# Dimension prüfen
#if self.sigma_beob.rows != self.gruppe_beob.rows:
# raise ValueError("sigma_beob und gruppe_beob müssen gleich viele Einträge haben.")
#if self.sigma_beob.rows != int(self.n_beob):
# raise ValueError("n_beob passt nicht zur Länge von sigma_beob / gruppe_beob.")
# Fehlende Gruppen mit sigma0_sq = 1.0 ergänzen
#unique_groups = sorted({int(g) for g in self.gruppe_beob})
#for g in unique_groups:
# if g not in self.sigma0_gruppe:
# self.sigma0_gruppe[g] = 1.0
# In NumPy-Spaltenvektoren umwandeln
self.sigma_beob = np.asarray(list(self.sigma_beob), dtype=float).reshape(-1, 1)
self.gruppe_beob = np.asarray(list(self.gruppe_beob), dtype=int).reshape(-1, 1)
# Dimension prüfen
if self.sigma_beob.shape[0] != self.gruppe_beob.shape[0]:
raise ValueError("sigma_beob und gruppe_beob müssen gleich viele Einträge haben.")
if self.sigma_beob.shape[0] != int(self.n_beob):
raise ValueError("n_beob passt nicht zur Länge von sigma_beob / gruppe_beob.")
# Fehlende Gruppen mit sigma0_sq = 1.0 ergänzen
unique_groups = sorted({int(g) for g in self.gruppe_beob.flatten()})
for g in unique_groups:
if g not in self.sigma0_gruppe:
self.sigma0_gruppe[g] = 1.0
Speichert den Pfad zur SQLite-Datenbank, initialisiert den Datenbankzugriff und legt Cache-Variablen an,
die in den numerischen Auswertungen zur Rechenzeitersparnis wiederverwendet werden.
:param pfad_datenbank: Pfad zur SQLite-Datenbank.
:type pfad_datenbank: str
:return: None
:rtype: None
"""
self.pfad_datenbank = pfad_datenbank
self.func_Qll_numerisch = None
self.liste_symbole_lambdify = None
self.db_zugriff = Datenbankzugriff(self.pfad_datenbank)
def Qll_symbolisch(self, liste_beobachtungen_symbolisch: list) -> sp.Matrix:
"""Erstellt die symbolische Varianz-Kovarianz-Matrix Qll der Beobachtungen.
#def berechne_Qll(self) -> Tuple[sp.Matrix, sp.Matrix]:
# n = self.n_beob
# Q_ll = sp.zeros(n, n)
# P = sp.zeros(n, n)
# for i in range(self.n_beob):
# sigma_i = self.sigma_beob[i, 0] #σ-Wert der i-ten Beobachtung holen
# g = int(self.gruppe_beob[i, 0]) #Gruppenzugehörigkeit der Beobachtung bestimmen
# sigma0_sq = self.sigma0_gruppe[g] #Den Varianzfaktor der Gruppe holen
# q_ii = sigma_i**2 #σ² berechnen
# Q_ll[i, i] = q_ii #Diagonale
# return Q_ll
Aus den symbolischen Beobachtungskennungen wird die Beobachtungsart abgeleitet (Tachymeter: SD/R/ZW,
GNSS: gnssbx/gnssby/gnssbz, Geometrisches Nivellement: niv). Für jede Beobachtung wird eine symbolische Varianzgleichung
aufgestellt und in Qll eingetragen.
def Qll_symbolisch(self, pfad_datenbank: str, liste_beobachtungen_symbolisch: list) -> sp.Matrix:
Berücksichtigte Gleichungen:
- Tachymeter SD: σ = sqrt(σ_konstant² + (σ_streckenprop * SD / 1 000 000)²), Varianz = varkomp * σ²
- Tachymeter R/ZW: σ = sqrt(σ_konstant² + (σ_konstant_SD / SD)²), Varianz = varkomp * σ²
- GNSS: Diagonale und Korrelationen je Basislinie aus cxx/cyy/czz und cxy/cxz/cyz, jeweils skaliert mit s0²
- Nivellement: σ = sqrt(n_wechselpunkte * σ_konstant² + σ_streckenprop² * distanz / 1000), Varianz = varkomp * σ²
Die symbolische Matrix wird als CSV-Datei in Zwischenergebnisse\\Qll_Symbolisch.csv exportiert.
:param liste_beobachtungen_symbolisch: Liste der symbolischen Beobachtungskennungen.
:type liste_beobachtungen_symbolisch: list
:return: Symbolische Varianz-Kovarianz-Matrix Qll.
:rtype: sp.Matrix
"""
liste_standardabweichungen_symbole = []
# Vorbereitung und Abfrage der notwendigen Listen und Dictionaries
liste_beobachtungen_symbolisch = [str(b) for b in liste_beobachtungen_symbolisch]
liste_beobachtungen_symbolisch = [b for b in liste_beobachtungen_symbolisch if not b.startswith("lA_")]
Qll = sp.zeros(len(liste_beobachtungen_symbolisch), len(liste_beobachtungen_symbolisch))
dict_beobachtungenID_instrumenteID = self.db_zugriff.get_instrumenteID_beobachtungenID_dict()
db_zugriff = Datenbankzugriff(pfad_datenbank)
dict_beobachtungenID_instrumenteID = db_zugriff.get_instrumenteID_beobachtungenID_dict()
# Aufstellen der Symbolischen Gleichungen für die Einträge in der Qll-Matrix jeder Beobachtungsgruppe
for i, beobachtung_symbolisch_i in enumerate(liste_beobachtungen_symbolisch):
aufgeteilt_i = beobachtung_symbolisch_i.split("_")
beobachtungenID_i = int(aufgeteilt_i[0])
instrumenteID_i = dict_beobachtungenID_instrumenteID[beobachtungenID_i]
# SD = Schrägdistanzen | R = Richtung | ZW = Zenitwinkel
# varkomp = Varianzkomponentenschätzung (Ist noch keine Erfolgt, ist dieser Faktor = 1
if aufgeteilt_i[1] == "SD" or aufgeteilt_i[1] == "R" or aufgeteilt_i[1] == "ZW":
beobachtungsart_i = str(aufgeteilt_i[1])
@@ -120,6 +114,7 @@ class StochastischesModell:
Qll[i, i] = (varianzkompontenschaetzung) * sigma ** 2
# Setzen der 0-Einträge in der Qll-Matrix
for j in range(i + 1, len(liste_beobachtungen_symbolisch)):
beobachtung_symbolisch_j = liste_beobachtungen_symbolisch[j]
aufgeteilt_j = beobachtung_symbolisch_j.split("_")
@@ -128,8 +123,10 @@ class StochastischesModell:
if beobachtungsart_i == "SD" and beobachtungsart_j == "SD":
Qll[i, j] = 0
Qll[j, i] = 0
# GNSS
# s0, sowie die kovarianzen cxx, ... entstammen direkt LeicaGeooffice
if aufgeteilt_i [1] == "gnssbx" or aufgeteilt_i[1] == "gnssby" or aufgeteilt_i[1] == "gnssbz":
#beobachtungenID_i = int(aufgeteilt_i[0])
beobachtungsart_i = str(aufgeteilt_i[1])
varianzkompontenschaetzung = sp.Symbol(
f"varkomp_{instrumenteID_i}_GNSS-Rover_Basislinienbeobachtungen")
@@ -185,9 +182,8 @@ class StochastischesModell:
liste_standardabweichungen_symbole.append(czz)
Qll[i, i] = (varianzkompontenschaetzung) * (czz * (s0 ** 2))
# Geometrisches Nivellement
if aufgeteilt_i[1] == "niv":
#beobachtungenID_i = int(aufgeteilt_i[0])
#instrumenteID_i = dict_beobachtungenID_instrumenteID[beobachtungenID_i]
beobachtungsart_i = str(aufgeteilt_i[1])
varianzkompontenschaetzung = sp.Symbol(
@@ -198,6 +194,7 @@ class StochastischesModell:
nivellement_distanz = sp.Symbol(f"niv_distanz_{beobachtungenID_i}")
nivellement_anz_wechselpunkte = sp.Symbol(f"niv_anz_wechselpunkte_{beobachtungenID_i}")
# Berechnen der Standardabweichung unter Einbeziehung der Anzahl Wechselpunkte
sigma = sp.sqrt(nivellement_anz_wechselpunkte * stabw_apriori_konstant ** 2 + stabw_apriori_streckenprop ** 2 * nivellement_distanz / 1000)
liste_standardabweichungen_symbole.append(sigma)
@@ -206,24 +203,49 @@ class StochastischesModell:
Export.matrix_to_csv(r"Zwischenergebnisse\Qll_Symbolisch.csv", liste_beobachtungen_symbolisch, liste_beobachtungen_symbolisch, Qll, "Qll")
return Qll
def Qll_numerisch(self, pfad_datenbank: str, Qll_Matrix_Symbolisch: sp.Matrix, liste_beobachtungen_symbolisch: list) -> np.Matrix:
def Qll_numerisch(self, Qll_Matrix_Symbolisch: sp.Matrix, liste_beobachtungen_symbolisch: list) -> np.Matrix:
"""Erstellt eine numerische Varianz-Kovarianz-Matrix aus einer symbolischen Qll-Matrix.
Es werden die zur Substitution benötigten Werte aus der Datenbank abgefragt und den in Qll vorkommenden Symbolen zugeordnet,
u. a.:
- Genauigkeiten (stabw_apriori_konstant / stabw_apriori_streckenprop) je Instrument und Beobachtungsart,
- Varianzkomponenten (varkomp_*) je Instrument und Beobachtungsgruppe,
- gemessene Tachymeter-Distanzen SD_* zur Bildung der Winkel-/Zenitwinkel-Ansätze,
- GNSS-Kovarianzen cxx, cxy, cxz, cyy, cyz, czz sowie s0 je Basislinie,
- Geomtrisches Nivellement-Strecken und Anzahl Wechsel-/Standpunkte.
Die Methode prüft, ob alle freien Symbole der Qll-Matrix substituierbar sind.
Zur Rechenzeitersparnis wird ein Lambdify-Cache geführt. Die Matrix wird anschließend gezielt
über Nicht-Null-Einträge befüllt, um unnötige Auswertung von Nullzellen zu vermeiden.
Die numerische Matrix wird als CSV-Datei in Zwischenergebnisse\\Qll_Numerisch.csv exportiert.
:param Qll_Matrix_Symbolisch: Symbolische Varianz-Kovarianz-Matrix Qll.
:type Qll_Matrix_Symbolisch: sp.Matrix
:param liste_beobachtungen_symbolisch: Liste der symbolischen Beobachtungskennungen.
:type liste_beobachtungen_symbolisch: list
:return: Numerische Varianz-Kovarianz-Matrix Qll als Numpy-Array.
:rtype: np.Matrix
:raises ValueError: Falls Symbole in Qll_Matrix_Symbolisch enthalten sind, für die keine Substitutionen vorhanden sind.
"""
liste_beobachtungen_symbolisch = [str(b).strip() for b in liste_beobachtungen_symbolisch]
liste_beobachtungen_symbolisch = [b for b in liste_beobachtungen_symbolisch if not b.startswith("lA_")]
db_zugriff = Datenbankzugriff(pfad_datenbank)
dict_genauigkeiten = db_zugriff.get_genauigkeiten_dict()
dict_beobachtungenID_instrumenteID = db_zugriff.get_instrumenteID_beobachtungenID_dict()
# Abfragen der Zahlen zu den Symbolen aus der Datenbank
dict_genauigkeiten = self.db_zugriff.get_genauigkeiten_dict()
liste_beobachtungen_tachymeter = db_zugriff.get_beobachtungen_from_beobachtungenid()
liste_beobachtungen_gnss = db_zugriff.get_beobachtungen_gnssbasislinien()
liste_beobachtungen_nivellement = db_zugriff.get_beobachtungen_nivellement()
liste_varianzkomponenten = db_zugriff.get_varianzkomponentenschaetzung()
liste_beobachtungen_tachymeter = self.db_zugriff.get_beobachtungen_from_beobachtungenid()
liste_beobachtungen_gnss = self.db_zugriff.get_beobachtungen_gnssbasislinien()
liste_beobachtungen_nivellement = self.db_zugriff.get_beobachtungen_nivellement()
liste_varianzkomponenten = self.db_zugriff.get_varianzkomponentenschaetzung()
# Erstellen eines Dicts mit der zuordnung beobachtungenID : Distanz
dict_beobachtungenID_distanz = {}
for standpunkt, zielpunkt, beobachtungenID, beobachtungsgruppeID, tachymeter_richtung, tachymeter_zenitwinkel, tachymeter_distanz in liste_beobachtungen_tachymeter:
dict_beobachtungenID_distanz[int(beobachtungenID)] = tachymeter_distanz
# Erstellen eines Dicts mit den Genauigkeiten aus der Tabelle Genauigkeiten
dict_genauigkeiten_neu = {}
for genauigkeitenID, eintrag in dict_genauigkeiten.items():
instrumenteID = int(eintrag[0])
@@ -235,6 +257,7 @@ class StochastischesModell:
substitutionen = {}
# Erstellen eines Dicts mit den konstanten Anteilen der Standardabweichungen aus der Datenbank
dict_konstante_sd = {}
for (instrumenteID, beobachtungsart), (stabw_apriori_konstant,
stabw_apriori_streckenprop) in dict_genauigkeiten_neu.items():
@@ -242,9 +265,11 @@ class StochastischesModell:
if stabw_apriori_konstant is not None:
dict_konstante_sd[instrumenteID] = float(stabw_apriori_konstant)
# Zuordnen des numerischen Varianzfaktors zum entsprechenden Symbol für die Substitution
for (varianzkomponenteID, instrumenteID, beobachtungsgruppe, varianz_varianzkomponentenschaetzung) in liste_varianzkomponenten:
substitutionen[sp.Symbol(f"varkomp_{instrumenteID}_{beobachtungsgruppe.strip()}")] = float(varianz_varianzkomponentenschaetzung)
# Zuordnen der numerischen Genauigkeitsangaben aus der Datenbank zum entsprechenden Symbol für die Substitution
for (instrumenteID, beobachtungsart), (stabw_apriori_konstant,
stabw_apriori_streckenprop) in dict_genauigkeiten_neu.items():
@@ -257,7 +282,6 @@ class StochastischesModell:
elif beobachtungsart == "Geometrisches_Nivellement":
beobachtungsart_kurz = "niv"
if stabw_apriori_konstant is not None:
substitutionen[sp.Symbol(f"stabw_apriori_konstant_{beobachtungsart_kurz}_{instrumenteID}")] = float(stabw_apriori_konstant)
if stabw_apriori_streckenprop is not None:
@@ -266,17 +290,12 @@ class StochastischesModell:
wert = wert / 1000.0
substitutionen[sp.Symbol(f"stabw_apriori_streckenprop_{beobachtungsart_kurz}_{instrumenteID}")] = wert
# --- DEBUG NIV Genauigkeiten (einmalig) ---
for k, v in substitutionen.items():
ks = str(k)
if "stabw_apriori_streckenprop_niv_" in ks or "stabw_apriori_konstant_niv_" in ks:
print("DEBUG", ks, "=", v)
for instrumenteID, wert in dict_konstante_sd.items():
substitutionen[sp.Symbol(f"stabw_apriori_konstant_SD_{instrumenteID}")] = float(wert)
liste_beobachtungen_symbolisch = [str(b) for b in liste_beobachtungen_symbolisch]
# Zuordnen der numerischen gemessenen Distanz aus der Datenbank zum entsprechenden Symbol für die Substitution
for beobachtung_symbolisch in liste_beobachtungen_symbolisch:
aufgeteilt = beobachtung_symbolisch.split("_")
beobachtungenID = int(aufgeteilt[0])
@@ -285,7 +304,7 @@ class StochastischesModell:
if distanz is not None:
substitutionen[sp.Symbol(f"SD_{beobachtungenID}")] = float(distanz)
#GNSS Basislinien
# Zuordnen der numerischen GNSS-Bestandteile aus der Tabelle Beobachtungen zum entsprechenden Symbol für die Substitution
for gnss_beobachtungen in liste_beobachtungen_gnss:
beobachtungenID = gnss_beobachtungen[0]
gnss_s0 = gnss_beobachtungen[6]
@@ -313,7 +332,7 @@ class StochastischesModell:
substitutionen[sp.Symbol(f"niv_anz_wechselpunkte_{beobachtungenID}")] = float(niv_anz_standpkte)
substitutionen[sp.Symbol(f"niv_distanz_{beobachtungenID}")] = float(niv_strecke)
#Qll_numerisch = Qll_Matrix_Symbolisch.xreplace(substitutionen)
# Substituieren mit der Methode lambdify
if (self.func_Qll_numerisch is None) or (set(self.liste_symbole_lambdify) != set(substitutionen.keys())):
self.liste_symbole_lambdify = sorted(substitutionen.keys(), key=lambda s: str(s))
self.func_Qll_numerisch = sp.lambdify(
@@ -323,14 +342,13 @@ class StochastischesModell:
cse=True
)
# Ausgeben der fehlenden Substitutionen
fehlend = sorted(list(Qll_Matrix_Symbolisch.free_symbols - set(substitutionen.keys())), key=lambda s: str(s))
if fehlend:
raise ValueError(
f"Qll_numerisch: Fehlende Substitutionen ({len(fehlend)}): {[str(s) for s in fehlend[:80]]}")
#liste_werte = [substitutionen[s] for s in self.liste_symbole_lambdify]
#Qll_numerisch = np.asarray(self.func_Qll_numerisch(*liste_werte), dtype=float)
# Eingrenzen der Substitution auf nicht 0 Zellen
rows = int(Qll_Matrix_Symbolisch.rows)
cols = int(Qll_Matrix_Symbolisch.cols)
@@ -349,12 +367,6 @@ class StochastischesModell:
eintrag_num = eintrag.xreplace(substitutionen)
if hasattr(eintrag_num, "free_symbols") and len(eintrag_num.free_symbols) > 0:
rest = sorted(list(eintrag_num.free_symbols), key=lambda s: str(s))
raise ValueError(
f"Qll_numerisch: Eintrag [{i},{j}] bleibt symbolisch. Rest-Symbole: {[str(s) for s in rest[:20]]}"
)
Qll_numerisch[i, j] = float(eintrag_num)
Export.matrix_to_csv(
@@ -367,15 +379,28 @@ class StochastischesModell:
return Qll_numerisch
def QAA_symbolisch(self, liste_beobachtungen_symbolisch: list, pfad_datenbank: str) -> np.Matrix:
def QAA_symbolisch(self, liste_beobachtungen_symbolisch: list) -> np.Matrix:
"""Erstellt die symbolische Varianz-Kovarianz-Matrix QAA der Anschlusspunkte (weiche Lagerung).
Es werden ausschließlich Beobachtungen berücksichtigt, deren Kennung mit "lA_" beginnt. Für jede Anschlussbedingung
wird eine (symbolische) Standardabweichung StabwAA_* angesetzt und mit der Varianzkomponente der Beobachtungsgruppe
"Anschlusspunkte" multipliziert.
Die symbolische Matrix wird als CSV-Datei in Zwischenergebnisse\\QAA_Symbolisch.csv exportiert.
:param liste_beobachtungen_symbolisch: Liste der symbolischen Beobachtungskennungen.
:type liste_beobachtungen_symbolisch: list
:return: Symbolische Varianz-Kovarianz-Matrix QAA.
:rtype: sp.Matrix
"""
liste_standardabweichungen_symbole = []
liste_beobachtungen_symbolisch = [str(b) for b in liste_beobachtungen_symbolisch]
liste_beobachtungen_symbolisch = [b for b in liste_beobachtungen_symbolisch if b.startswith("lA_")]
Qll = sp.zeros(len(liste_beobachtungen_symbolisch), len(liste_beobachtungen_symbolisch))
db_zugriff = Datenbankzugriff(pfad_datenbank)
instrumente_id_anschlusspunkte = db_zugriff.get_instrument_liste("Anschlusspunkte")[0][0]
instrumente_id_anschlusspunkte = self.db_zugriff.get_instrument_liste("Anschlusspunkte")[0][0]
# Erstellen der Symbolischen Gleichungen für die QAA-Matrix
for i, beobachtung_symbolisch_i in enumerate(liste_beobachtungen_symbolisch):
aufgeteilt_i = beobachtung_symbolisch_i.split("_")
datumskoordinate = str(aufgeteilt_i[1])
@@ -394,17 +419,32 @@ class StochastischesModell:
Export.matrix_to_csv(r"Zwischenergebnisse\QAA_Symbolisch.csv", liste_beobachtungen_symbolisch, liste_beobachtungen_symbolisch, Qll, "Qll")
return Qll
def QAA_numerisch(self, pfad_datenbank: str, QAA_Matrix_Symbolisch: sp.Matrix, liste_beobachtungen_symbolisch: list) -> np.Matrix:
def QAA_numerisch(self, QAA_Matrix_Symbolisch: sp.Matrix, liste_beobachtungen_symbolisch: list) -> np.Matrix:
"""Erstellt eine numerische Matrix aus einer symbolischen QAA-Matrix.
Es werden die numerischen Standardabweichungen der Anschlussbedingungen sowie die Varianzkomponente der Gruppe
"Anschlusspunkte" aus der Datenbank abgefragt und substituiert. Zur Rechenzeitersparnis wird ein Lambdify-Cache geführt,
der bei Änderung der Symbolmenge neu aufgebaut.
Die numerische Matrix wird als CSV-Datei in Zwischenergebnisse\\QAA_Numerisch.csv exportiert.
:param QAA_Matrix_Symbolisch: Symbolische Varianz-Kovarianz-Matrix QAA.
:type QAA_Matrix_Symbolisch: sp.Matrix
:param liste_beobachtungen_symbolisch: Liste der symbolischen Beobachtungskennungen.
:type liste_beobachtungen_symbolisch: list
:return: Numerische Varianz-Kovarianz-Matrix QAA als Numpy-Array.
:rtype: np.Matrix
"""
# Symbolische Listen
liste_beobachtungen_symbolisch = [str(b).strip() for b in liste_beobachtungen_symbolisch]
liste_beobachtungen_symbolisch = [b for b in liste_beobachtungen_symbolisch if b.startswith("lA_")]
db_zugriff = Datenbankzugriff(pfad_datenbank)
dict_stabwAA_vorinfo = db_zugriff.get_stabw_AA_Netzpunkte()
liste_varianzkomponenten = db_zugriff.get_varianzkomponentenschaetzung()
# Abfrage der numerischen Werte aus der Datenbank
dict_stabwAA_vorinfo = self.db_zugriff.get_stabw_AA_Netzpunkte()
liste_varianzkomponenten = self.db_zugriff.get_varianzkomponentenschaetzung()
# Zuordnen des Symbols zum numerischen Wert
substitutionen = {}
for koordinate, stabwAA in dict_stabwAA_vorinfo.items():
substitutionen[sp.Symbol(str(koordinate).strip())] = float(stabwAA)
@@ -412,11 +452,13 @@ class StochastischesModell:
varianz_varianzkomponentenschaetzung) in liste_varianzkomponenten:
substitutionen[sp.Symbol(f"varkomp_{instrumenteID}_Anschlusspunkte")] = float(varianz_varianzkomponentenschaetzung)
# Speichern der MAtrix in einer Instanzvariablen
if not hasattr(self, "func_QAA_numerisch"):
self.func_QAA_numerisch = None
if not hasattr(self, "liste_symbole_lambdify_QAA"):
self.liste_symbole_lambdify_QAA = []
# Substituieren
if (self.func_QAA_numerisch is None) or (set(self.liste_symbole_lambdify_QAA) != set(substitutionen.keys())):
self.liste_symbole_lambdify_QAA = sorted(substitutionen.keys(), key=lambda s: str(s))
self.func_QAA_numerisch = sp.lambdify(
@@ -440,21 +482,66 @@ class StochastischesModell:
return QAA_numerisch
@staticmethod
def berechne_P(Q_ll):
def berechne_P(Q_ll: np.ndarray) -> np.ndarray:
"""Berechnet die Gewichtsmatrix P aus einer Varianz-Kovarianz-Matrix Qll.
Die Gewichtsmatrix wird als Inverse von Qll gebildet: P = inv(Qll).
:param Q_ll: Varianz-Kovarianz-Matrix der Beobachtungen.
:type Q_ll: np.ndarray
:return: Gewichtsmatrix P.
:rtype: np.ndarray
"""
P = np.linalg.inv(Q_ll)
return P
@staticmethod
def berechne_Q_xx(N):
def berechne_Q_xx(N: np.ndarray) -> np.ndarray:
"""Berechnet die Kofaktormatrix der Unbekannten Qxx aus der Normalgleichungsmatrix N.
Die Kofaktormatrix wird als Inverse der Normalgleichungsmatrix gebildet: Qxx = inv(N).
Vor der Inversion wird geprüft, ob N quadratisch ist.
:param N: Normalgleichungsmatrix.
:type N: np.ndarray
:return: Kofaktormatrix der Unbekannten Qxx.
:rtype: np.ndarray
:raises ValueError: Falls N nicht quadratisch ist.
"""
if N.shape[0] != N.shape[1]:
raise ValueError("N muss eine quadratische Matrix sein")
Qxx = np.linalg.inv(N)
return Qxx
def berechne_Q_ll_dach(A, Q_xx):
@staticmethod
def berechne_Q_ll_dach(A: np.ndarray, Q_xx: np.ndarray) -> np.ndarray:
"""Berechnet die (geschätzte) Varianz-Kovarianz-Matrix der Beobachtungen Qll_dach.
Die Matrix wird gemäß Qll_dach = A @ Qxx @ A.T gebildet.
:param A: Jacobi-Matrix.
:type A: np.ndarray
:param Q_xx: Kofaktormatrix der Unbekannten.
:type Q_xx: np.ndarray
:return: Geschätzte Varianz-Kovarianz-Matrix der Beobachtungen Qll_dach.
:rtype: np.ndarray
"""
Q_ll_dach = A @ Q_xx @ A.T
return Q_ll_dach
def berechne_Qvv(Q_ll, Q_ll_dach):
@staticmethod
def berechne_Qvv(Q_ll: np.ndarray, Q_ll_dach: np.ndarray) -> np.ndarray:
"""Berechnet die Varianz-Kovarianz-Matrix der Residuen Qvv.
Die Residuenkovarianz wird als Differenz aus Beobachtungs-Kovarianz und dem durch das Modell erklärten Anteil gebildet:
Qvv = Qll - Qll_dach.
:param Q_ll: Varianz-Kovarianz-Matrix der Beobachtungen.
:type Q_ll: np.ndarray
:param Q_ll_dach: Geschätzte Varianz-Kovarianz-Matrix der Beobachtungen.
:type Q_ll_dach: np.ndarray
:return: Varianz-Kovarianz-Matrix der Residuen Qvv.
:rtype: np.ndarray
"""
Q_vv = Q_ll - Q_ll_dach
return Q_vv