This commit is contained in:
2026-02-09 21:28:10 +01:00
parent ee895f95a9
commit 0ac49902af
11 changed files with 29903 additions and 29329 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -124,7 +124,7 @@ class Datumsfestlegung:
return Q_ext, P return Q_ext, P
@staticmethod @staticmethod
def indizes_beobachtungsvektor_nach_beobachtungsgruppe(Jacobimatrix_symbolisch_liste_beobachtungsvektor): def indizes_beobachtungsvektor_nach_beobachtungsgruppe(Jacobimatrix_symbolisch_liste_beobachtungsvektor: list[str]) -> dict[str, tuple[int, int]]:
""" """
Ermittelt Indexbereiche des Beobachtungsvektors getrennt nach Beobachtungsgruppen. Ermittelt Indexbereiche des Beobachtungsvektors getrennt nach Beobachtungsgruppen.
@@ -190,112 +190,3 @@ class Datumsfestlegung:
dict_beobachtungsgruppen_indizes["lA"] = min(liste_anschlusspunkte_indizes), max(liste_anschlusspunkte_indizes) dict_beobachtungsgruppen_indizes["lA"] = min(liste_anschlusspunkte_indizes), max(liste_anschlusspunkte_indizes)
return dict_beobachtungsgruppen_indizes return dict_beobachtungsgruppen_indizes
@staticmethod
def make_index(unbekannten_liste):
names = [str(s).strip() for s in unbekannten_liste]
return names, {n: i for i, n in enumerate(names)}
@staticmethod
def erstelle_G(x0, unbekannten_liste, liste_punktnummern=None, mit_massstab=True):
"""
Baut G (u x d) in den vollen Unbekanntenraum.
Wenn liste_punktnummern=None, werden alle Punkt-IDs aus unbekannten_liste
über X*/Y*/Z* automatisch bestimmt.
"""
x0 = np.asarray(x0, float).reshape(-1)
names, idx = Datumsfestlegung.make_index(unbekannten_liste)
u = len(names)
d = 7 if mit_massstab else 6
G = np.zeros((u, d), dtype=float)
# --- Punktliste automatisch, falls nicht gegeben ---
if liste_punktnummern is None:
pids = set()
for n in names:
if len(n) >= 2 and n[0].upper() in ("X", "Y", "Z"):
pids.add(n[1:]) # alles nach X/Y/Z
liste_punktnummern = sorted(pids)
for pid in liste_punktnummern:
sx, sy, sz = f"X{pid}", f"Y{pid}", f"Z{pid}"
if sx not in idx or sy not in idx or sz not in idx:
continue # Punkt nicht vollständig als XYZ-Unbekannte vorhanden
ix, iy, iz = idx[sx], idx[sy], idx[sz]
xi, yi, zi = x0[ix], x0[iy], x0[iz]
# Translationen
G[ix, 0] = 1.0
G[iy, 1] = 1.0
G[iz, 2] = 1.0
# Rotationen (δr = ω × r)
# Rx: δY=-Z, δZ=+Y
G[iy, 3] = -zi
G[iz, 3] = yi
# Ry: δX=+Z, δZ=-X
G[ix, 4] = zi
G[iz, 4] = -xi
# Rz: δX=-Y, δY=+X
G[ix, 5] = -yi
G[iy, 5] = xi
# Maßstab
if mit_massstab:
G[ix, 6] = xi
G[iy, 6] = yi
G[iz, 6] = zi
return G
def aktive_indices_from_selection(auswahl, unbekannten_liste):
names, idx = Datumsfestlegung.make_index(unbekannten_liste)
aktive = []
for pid, comp in auswahl:
key = f"{comp.upper()}{str(pid)}"
if key not in idx:
raise KeyError(f"{key} nicht im Unbekanntenvektor.")
aktive.append(idx[key])
# unique
out = []
seen = set()
for i in aktive:
if i not in seen:
seen.add(i)
out.append(i)
return out
def auswahlmatrix_E(u, aktive_indices):
E = np.zeros((u, u), dtype=float)
for i in aktive_indices:
E[int(i), int(i)] = 1.0
return E
def berechne_dx(N, n, G):
N = np.asarray(N, float)
n = np.asarray(n, float).reshape(-1, 1)
G = np.asarray(G, float)
u = N.shape[0]
d = G.shape[1]
K = np.block([
[N, G],
[G.T, np.zeros((d, d))]
])
rhs = np.vstack([n, np.zeros((d, 1))])
K_inv = np.linalg.inv(K)
sol = K_inv @ rhs
dx = sol[:u]
k = sol[u:]
Q_xx = K_inv[:u, :u]
return dx, k, Q_xx

View File

@@ -65,11 +65,7 @@ class Export:
@staticmethod @staticmethod
def erzeuge_ergebnis_datenframes( def erzeuge_ergebnis_datenframes(pfad_datenbank: str, pfad_tif_quasigeoidundulation: str, dict_koordinaten_ausgleichungsergebnis: dict) -> tuple[pd.DataFrame, pd.DataFrame]:
pfad_datenbank: str,
pfad_tif_quasigeoidundulation: str,
dict_koordinaten_ausgleichungsergebnis: dict
):
""" """
Erzeugt Ergebnis-DataFrames für ausgeglichene Koordinaten in ECEF (XYZ) und UTM. Erzeugt Ergebnis-DataFrames für ausgeglichene Koordinaten in ECEF (XYZ) und UTM.

View File

@@ -25,7 +25,7 @@ class FunktionalesModell:
Die grundlegende Funktionsweise der Matrixdefinition lautet: Die grundlegende Funktionsweise der Matrixdefinition lautet:
1) Einmaligen Aufbauen der Symbolischen Matrix einmalig 1) Einmaligen Aufbauen der Symbolischen Matrix einmalig
2) In jeder Iteration Substituieren der Symbolischen Matrizen in Numerische np.asarrays 2) In jeder Iteration Substituieren der Symbolischen Matrizen in Numerische np.ndarray
""" """
def __init__(self, pfad_datenbank: str, a: float, b: float, pfad_tif_quasigeoidundulation: str = None) -> None: def __init__(self, pfad_datenbank: str, a: float, b: float, pfad_tif_quasigeoidundulation: str = None) -> None:
@@ -703,8 +703,8 @@ class FunktionalesModell:
def unbekanntenvektor_numerisch(self, liste_unbekanntenvektor_symbolisch: list, def unbekanntenvektor_numerisch(self, liste_unbekanntenvektor_symbolisch: list,
unbekanntenvektor_symbolisch: sp.Matrix, unbekanntenvektor_symbolisch: sp.Matrix,
dX_Vektor: np.asarray = None, dX_Vektor: np.ndarray = None,
unbekanntenvektor_numerisch_vorherige_Iteration: np.asarray = None, unbekanntenvektor_numerisch_vorherige_Iteration: np.ndarray = None,
iterationsnummer: int = 0) -> ndarray[tuple[int, int], Any] | ndarray[tuple[Any, ...], dtype[Any]]: iterationsnummer: int = 0) -> ndarray[tuple[int, int], Any] | ndarray[tuple[Any, ...], dtype[Any]]:
"""Erstellt den numerischen Unbekanntenvektor jeder Iteration. """Erstellt den numerischen Unbekanntenvektor jeder Iteration.
@@ -722,9 +722,9 @@ class FunktionalesModell:
:param unbekanntenvektor_symbolisch: Symbolischer Unbekanntenvektor. :param unbekanntenvektor_symbolisch: Symbolischer Unbekanntenvektor.
:type unbekanntenvektor_symbolisch: sp.Matrix :type unbekanntenvektor_symbolisch: sp.Matrix
:param dX_Vektor: Verbesserungsvektor der aktuellen Iteration (optional). :param dX_Vektor: Verbesserungsvektor der aktuellen Iteration (optional).
:type dX_Vektor: np.asarray | None :type dX_Vektor: np.ndarray | None
:param unbekanntenvektor_numerisch_vorherige_Iteration: Numerischer Unbekanntenvektor der vorherigen Iteration (optional). :param unbekanntenvektor_numerisch_vorherige_Iteration: Numerischer Unbekanntenvektor der vorherigen Iteration (optional).
:type unbekanntenvektor_numerisch_vorherige_Iteration: np.asarray | None :type unbekanntenvektor_numerisch_vorherige_Iteration: np.ndarray | None
:param iterationsnummer: Iterationsnummer für Dateinamen der Zwischenergebnisse. :param iterationsnummer: Iterationsnummer für Dateinamen der Zwischenergebnisse.
:type iterationsnummer: int :type iterationsnummer: int
:return: Numerischer Unbekanntenvektor als Numpy-Array :return: Numerischer Unbekanntenvektor als Numpy-Array
@@ -754,7 +754,7 @@ class FunktionalesModell:
"Unbekanntenvektor") "Unbekanntenvektor")
return unbekanntenvektor_numerisch return unbekanntenvektor_numerisch
def unbekanntenvektor_numerisch_to_dict_unbekanntenvektor(self, liste_unbekanntenvektor_symbolisch: list, unbekanntenvektor_numerisch: np.asarray) -> dict: def unbekanntenvektor_numerisch_to_dict_unbekanntenvektor(self, liste_unbekanntenvektor_symbolisch: list, unbekanntenvektor_numerisch: np.ndarray) -> dict:
"""Wandelt einen numerischen Unbekanntenvektor in ein Koordinatendictionary um. """Wandelt einen numerischen Unbekanntenvektor in ein Koordinatendictionary um.
Aus dem numerischen Unbekanntenvektor werden für alle Punkte die Koordinaten (X, Y, Z) extrahiert Aus dem numerischen Unbekanntenvektor werden für alle Punkte die Koordinaten (X, Y, Z) extrahiert
@@ -763,7 +763,7 @@ class FunktionalesModell:
:param liste_unbekanntenvektor_symbolisch: Liste der Unbekannten (Symbole) in der Reihenfolge des numerischen Vektors. :param liste_unbekanntenvektor_symbolisch: Liste der Unbekannten (Symbole) in der Reihenfolge des numerischen Vektors.
:type liste_unbekanntenvektor_symbolisch: list :type liste_unbekanntenvektor_symbolisch: list
:param unbekanntenvektor_numerisch: Numerischer Unbekanntenvektor. :param unbekanntenvektor_numerisch: Numerischer Unbekanntenvektor.
:type unbekanntenvektor_numerisch: np.asarray :type unbekanntenvektor_numerisch: np.ndarray
:return: Dictionary {punktnummer: sp.Matrix([X, Y, Z])}. :return: Dictionary {punktnummer: sp.Matrix([X, Y, Z])}.
:rtype: dict :rtype: dict
""" """
@@ -796,8 +796,8 @@ class FunktionalesModell:
return dict_koordinaten return dict_koordinaten
def berechnung_dl(self, beobachtungsvektor_numerisch: np.asarray, beobachtungsvektor_naeherung_numerisch: sp.Matrix, def berechnung_dl(self, beobachtungsvektor_numerisch: np.ndarray, beobachtungsvektor_naeherung_numerisch: sp.Matrix,
liste_beobachtungsvektor_symbolisch: list = None, iterationsnummer: int = 0) -> np.asarray: liste_beobachtungsvektor_symbolisch: list = None, iterationsnummer: int = 0) -> np.ndarray:
"""Berechnet den Verbesserungsvektor dl = l f(x0). """Berechnet den Verbesserungsvektor dl = l f(x0).
Der Vektor wird als Differenz aus numerischem Beobachtungsvektor und numerischem Näherungs-Beobachtungsvektor gebildet. Der Vektor wird als Differenz aus numerischem Beobachtungsvektor und numerischem Näherungs-Beobachtungsvektor gebildet.
@@ -806,7 +806,7 @@ class FunktionalesModell:
Der Vektor dl wird als CSV-Datei in den Ordner Zwischenergebnisse exportiert. Der Vektor dl wird als CSV-Datei in den Ordner Zwischenergebnisse exportiert.
:param beobachtungsvektor_numerisch: Numerischer Beobachtungsvektor l. :param beobachtungsvektor_numerisch: Numerischer Beobachtungsvektor l.
:type beobachtungsvektor_numerisch: np.asarray :type beobachtungsvektor_numerisch: np.ndarray
:param beobachtungsvektor_naeherung_numerisch: Numerischer Näherungs-Beobachtungsvektor f(x0). :param beobachtungsvektor_naeherung_numerisch: Numerischer Näherungs-Beobachtungsvektor f(x0).
:type beobachtungsvektor_naeherung_numerisch: sp.Matrix :type beobachtungsvektor_naeherung_numerisch: sp.Matrix
:param liste_beobachtungsvektor_symbolisch: Optional: Liste der Beobachtungskennungen. :param liste_beobachtungsvektor_symbolisch: Optional: Liste der Beobachtungskennungen.
@@ -814,7 +814,7 @@ class FunktionalesModell:
:param iterationsnummer: Iterationsnummer für Dateinamen der Zwischenergebnisse. :param iterationsnummer: Iterationsnummer für Dateinamen der Zwischenergebnisse.
:type iterationsnummer: int :type iterationsnummer: int
:return: Verbesserungsvektor dl. :return: Verbesserungsvektor dl.
:rtype: np.asarray :rtype: np.ndarray
""" """
dl = beobachtungsvektor_numerisch - beobachtungsvektor_naeherung_numerisch dl = beobachtungsvektor_numerisch - beobachtungsvektor_naeherung_numerisch
# Umwandeln in einen Numpy-Array, um Rechenzeit im Vergleich zu einer sympy.MAtrix zu sparen # Umwandeln in einen Numpy-Array, um Rechenzeit im Vergleich zu einer sympy.MAtrix zu sparen
@@ -839,7 +839,7 @@ class FunktionalesModell:
return dl return dl
def dict_substitutionen_uebergeordnetes_system(self, def dict_substitutionen_uebergeordnetes_system(self,
unbekanntenvektor_aus_iteration: np.asarray = None) -> dict[Any, Any]: unbekanntenvektor_aus_iteration: np.ndarray = None) -> dict[Any, Any]:
"""Erstellt das Substitutions-Dictionary für das geozentrisch-kartesische System. """Erstellt das Substitutions-Dictionary für das geozentrisch-kartesische System.
Es werden (abhängig davon, ob ein Unbekanntenvektor aus einer Iteration übergeben wurde) die aktuellen Es werden (abhängig davon, ob ein Unbekanntenvektor aus einer Iteration übergeben wurde) die aktuellen
@@ -852,7 +852,7 @@ class FunktionalesModell:
- Orientierungsunbekannte O. - Orientierungsunbekannte O.
:param unbekanntenvektor_aus_iteration: Optionaler numerischer Unbekanntenvektor einer Iteration zur Aktualisierung der Substitutionen. :param unbekanntenvektor_aus_iteration: Optionaler numerischer Unbekanntenvektor einer Iteration zur Aktualisierung der Substitutionen.
:type unbekanntenvektor_aus_iteration: np.asarray | None :type unbekanntenvektor_aus_iteration: np.ndarray | None
:return: Dictionary mit SymPy-Symbolen als Key und numerischen Werten als Value. :return: Dictionary mit SymPy-Symbolen als Key und numerischen Werten als Value.
:rtype: dict[Any, Any] :rtype: dict[Any, Any]
""" """
@@ -976,7 +976,7 @@ class FunktionalesModell:
return substitutionen return substitutionen
def unbekanntenvektor_numerisch_to_dict_orientierungen(self, liste_unbekanntenvektor_symbolisch: list, def unbekanntenvektor_numerisch_to_dict_orientierungen(self, liste_unbekanntenvektor_symbolisch: list,
unbekanntenvektor_numerisch: np.asarray) -> dict[Any, Any]: unbekanntenvektor_numerisch: np.ndarray) -> dict[Any, Any]:
"""Extrahiert Orientierungsparameter aus einem numerischen Unbekanntenvektor in ein Dictionary. """Extrahiert Orientierungsparameter aus einem numerischen Unbekanntenvektor in ein Dictionary.
Alle Unbekannten, deren Symbolname mit "O" beginnt, werden als als Dictionary in der Form {orientierungs_id: wert} zurückgegeben. Alle Unbekannten, deren Symbolname mit "O" beginnt, werden als als Dictionary in der Form {orientierungs_id: wert} zurückgegeben.
@@ -984,7 +984,7 @@ class FunktionalesModell:
:param liste_unbekanntenvektor_symbolisch: Liste der Unbekannten (Symbole) in der Reihenfolge des numerischen Vektors. :param liste_unbekanntenvektor_symbolisch: Liste der Unbekannten (Symbole) in der Reihenfolge des numerischen Vektors.
:type liste_unbekanntenvektor_symbolisch: list :type liste_unbekanntenvektor_symbolisch: list
:param unbekanntenvektor_numerisch: Numerischer Unbekanntenvektor. :param unbekanntenvektor_numerisch: Numerischer Unbekanntenvektor.
:type unbekanntenvektor_numerisch: np.asarray :type unbekanntenvektor_numerisch: np.ndarray
:return: Dictionary der Orientierungen je Beobachtungsgruppe. :return: Dictionary der Orientierungen je Beobachtungsgruppe.
:rtype: dict[Any, Any] :rtype: dict[Any, Any]
""" """

View File

@@ -401,7 +401,7 @@ class Transformationen:
def ecef_to_utm( def ecef_to_utm(
self, self,
dict_koordinaten: dict, dict_koordinaten: dict,
pfad_gcg_tif: str | Path | None = None): pfad_gcg_tif: str | Path | None = None) -> dict:
"""Rechnet ECEF-Koordinaten (ETRS89 geozentrisch-kartesisch) nach nach UTM (+ DHHN2016 Normalhöhe). """Rechnet ECEF-Koordinaten (ETRS89 geozentrisch-kartesisch) nach nach UTM (+ DHHN2016 Normalhöhe).
Es wird ein PROJ-Transformer von: Es wird ein PROJ-Transformer von:

View File

@@ -13,7 +13,7 @@ class Genauigkeitsmaße:
Die Klasse stellt Methoden zur Verfügung für: Die Klasse stellt Methoden zur Verfügung für:
- Berechnung der a-posteriori Standardabweichung der Gewichtseinheit s - Berechnung der a-posteriori Standardabweichung der Gewichtseinheit σ̂
- Berechnung des Helmertschen Punktfehlers (2D/3D), - Berechnung des Helmertschen Punktfehlers (2D/3D),
- Berechnung der Standardellipse (Helmertschen Fehlerellipse), - Berechnung der Standardellipse (Helmertschen Fehlerellipse),
- Berechnung der Konfidenzellipse auf Basis eines Konfidenzniveaus (alpha) mit Skalierung über die F-Verteilung, - Berechnung der Konfidenzellipse auf Basis eines Konfidenzniveaus (alpha) mit Skalierung über die F-Verteilung,
@@ -25,19 +25,19 @@ class Genauigkeitsmaße:
@staticmethod @staticmethod
def berechne_sigma0apost(v: np.ndarray, P: np.ndarray, r: int, print_ausgabe = True) -> float: def berechne_sigma0apost(v: np.ndarray, P: np.ndarray, r: int, print_ausgabe = True) -> float:
""" """
Berechnet die a-posteriori Standardabweichung der Gewichtseinheit s₀. Berechnet die a-posteriori Standardabweichung der Gewichtseinheit σ̂₀.
Die a-posteriori Standardabweichung dient als Qualitätsmaß für die Die a-posteriori Standardabweichung dient als Qualitätsmaß für die
Ausgleichung nach der Methode der kleinsten Quadrate. Dabei beschreibt Ausgleichung nach der Methode der kleinsten Quadrate. Dabei beschreibt
r die Redundanz (Freiheitsgrade). r die Redundanz (Freiheitsgrade).
:param v: Residuenvektor der Beobachtungen. :param v: Residuenvektor der Beobachtungen.
:type v: numpy.ndarray :type v: np.ndarray
:param P: Gewichtsmatrix der Beobachtungen. :param P: Gewichtsmatrix der Beobachtungen.
:type P: numpy.ndarray :type P: np.ndarray
:param r: Redundanz bzw. Anzahl der Freiheitsgrade der Ausgleichung. :param r: Redundanz bzw. Anzahl der Freiheitsgrade der Ausgleichung.
:type r: int :type r: int
:return: a-posteriori Standardabweichung der Gewichtseinheit s₀. :return: a-posteriori Standardabweichung der Gewichtseinheit σ̂₀.
:rtype: float :rtype: float
""" """
@@ -50,12 +50,12 @@ class Genauigkeitsmaße:
@staticmethod @staticmethod
def helmert_punktfehler(Qxx, s0_apost, unbekannten_liste): def helmert_punktfehler(Qxx: np.ndarray, sigma0_apost: float, unbekannten_liste: list) -> pd.DataFrame:
""" """
Berechnet den Helmertschen Punktfehler (2D/3D) anhand der Standardabweichungen der Koordinaten der Punkte. Berechnet den Helmertschen Punktfehler (2D/3D) anhand der Standardabweichungen der Koordinaten der Punkte.
Aus der Kofaktor-Matrix der Unbekannten Qxx werden die Kofaktoren punktweise ausgelesen. Durch Multiplikation Aus der Kofaktor-Matrix der Unbekannten Qxx werden die Kofaktoren punktweise ausgelesen. Durch Multiplikation
mit der a-posteriori Standardabweichung der Gewichtseinheit s₀ werden die Standardabweichungen je Koordinate mit der a-posteriori Standardabweichung der Gewichtseinheit σ̂₀ werden die Standardabweichungen je Koordinate
(σx, σy, σz) sowie der Helmert'sche Punktfehler σP berechnet: (σx, σy, σz) sowie der Helmert'sche Punktfehler σP berechnet:
Die Punktzuordnung erfolgt über die Symbolnamen der Unbekanntenliste. Die Punktzuordnung erfolgt über die Symbolnamen der Unbekanntenliste.
@@ -63,14 +63,13 @@ class Genauigkeitsmaße:
Ergebnisse als Tabelle ausgegeben und in eine Excel-Datei exportiert. Ergebnisse als Tabelle ausgegeben und in eine Excel-Datei exportiert.
:param Qxx: Kofaktor-Matrix der Unbekannten. :param Qxx: Kofaktor-Matrix der Unbekannten.
:type Qxx: numpy.ndarray :type Qxx: np.ndarray
:param s0_apost: a-posteriori Standardabweichung der Gewichtseinheit s₀. :param sigma0_apost: a-posteriori Standardabweichung der Gewichtseinheit σ̂₀.
:type s0_apost: float :type sigma0_apost: float
:param unbekannten_liste: Liste der Unbekannten. :param unbekannten_liste: Liste der Unbekannten.
:type unbekannten_liste: list :type unbekannten_liste: list
:return: Tabelle mit Standardabweichungen und Helmertschem Punktfehler je Punkt. :return: Tabelle mit Standardabweichungen und Helmertschem Punktfehler je Punkt.
:rtype: pandas.DataFrame :rtype: pandas.DataFrame
:raises ValueError: Wenn eine ungültige Dimension (nicht 2 oder 3) eingegeben wird.
""" """
dim = int(input("Helmertscher Punktfehler (2 = 2D, 3 = 3D): ")) dim = int(input("Helmertscher Punktfehler (2 = 2D, 3 = 3D): "))
diagQ = np.diag(Qxx) diagQ = np.diag(Qxx)
@@ -98,17 +97,17 @@ class Genauigkeitsmaße:
except StopIteration: except StopIteration:
qz = 0.0 qz = 0.0
sx = s0_apost * np.sqrt(qx) sx = sigma0_apost * np.sqrt(qx)
sy = s0_apost * np.sqrt(qy) sy = sigma0_apost * np.sqrt(qy)
sz = s0_apost * np.sqrt(qz) if dim == 3 else 0 sz = sigma0_apost * np.sqrt(qz) if dim == 3 else 0
sP = s0_apost * np.sqrt(qx + qy + qz) sP = sigma0_apost * np.sqrt(qx + qy + qz)
daten.append([pid, float(sx), float(sy), float(sz), float(sP)]) daten.append([pid, float(sx), float(sy), float(sz), float(sP)])
except: except:
continue continue
helmert_punktfehler = pd.DataFrame(daten, columns=["Punkt", "σx", "σy", "σz", f"σP_{dim}D"]) helmert_punktfehler = pd.DataFrame(daten, columns=["Punkt", "σ̂x", "σ̂y", "σ̂z", f"σ̂P_{dim}D"])
mittel_sP = helmert_punktfehler[f"σP_{dim}D"].mean() mittel_sP = helmert_punktfehler[f"σ̂P_{dim}D"].mean()
print(f"Mittlerer Helmert-Punktfehler über alle Punkte: {mittel_sP:.4f} [m]") print(f"Mittlerer Helmert-Punktfehler über alle Punkte: {mittel_sP:.4f} [m]")
display(HTML(helmert_punktfehler.to_html(index=False))) display(HTML(helmert_punktfehler.to_html(index=False)))
helmert_punktfehler.to_excel(r"Netzqualitaet\Standardabweichungen_Helmertscher_Punktfehler.xlsx",index=False) helmert_punktfehler.to_excel(r"Netzqualitaet\Standardabweichungen_Helmertscher_Punktfehler.xlsx",index=False)
@@ -117,9 +116,9 @@ class Genauigkeitsmaße:
@staticmethod @staticmethod
def standardellipsoid(Qxx, s0_apost, unbekannten_liste): def standardellipsoid(Qxx: np.ndarray, sigma0_apost: float, unbekannten_liste: list) -> pd.DataFrame:
""" """
Berechnet Achsenlängen des Fehlerellipsoids (a, b, c) sowie den 2D-Richtungswinkel θ aus Qxx und s₀ a posteriori. Berechnet Achsenlängen des Fehlerellipsoids (a, b, c) sowie den 2D-Richtungswinkel θ aus Qxx und σ̂₀ a posteriori.
Für jeden Punkt wird aus der Kofaktor-Matrix der Unbekannten Qxx die 3×3-Submatrix Für jeden Punkt wird aus der Kofaktor-Matrix der Unbekannten Qxx die 3×3-Submatrix
der Koordinaten (X, Y, Z) gebildet. Daraus werden zunächst die Standardabweichungen der Koordinaten (X, Y, Z) gebildet. Daraus werden zunächst die Standardabweichungen
@@ -137,9 +136,9 @@ class Genauigkeitsmaße:
Die Ergebnisse werden tabellarisch ausgegeben und in eine Excel-Datei exportiert. Die Ergebnisse werden tabellarisch ausgegeben und in eine Excel-Datei exportiert.
:param Qxx: Kofaktor-Matrix der Unbekannten. :param Qxx: Kofaktor-Matrix der Unbekannten.
:type Qxx: numpy.ndarray :type Qxx: np.ndarray
:param s0_apost: A-posteriori Standardabweichung der Gewichtseinheit s₀. :param sigma0_apost: A-posteriori Standardabweichung der Gewichtseinheit σ̂₀.
:type s0_apost: float :type sigma0_apost: float
:param unbekannten_liste: Liste der Unbekannten. :param unbekannten_liste: Liste der Unbekannten.
:type unbekannten_liste: list :type unbekannten_liste: list
:return: Tabelle mit Standardabweichungen (σx, σy, σz), Ellipsoid-Halbachsen (a, b, c) und Richtungswinkel θ je Punkt. :return: Tabelle mit Standardabweichungen (σx, σy, σz), Ellipsoid-Halbachsen (a, b, c) und Richtungswinkel θ je Punkt.
@@ -165,18 +164,18 @@ class Genauigkeitsmaße:
Q_sub = Qxx[np.ix_(indices, indices)] Q_sub = Qxx[np.ix_(indices, indices)]
# Standardabweichungen # Standardabweichungen
sx = s0_apost * np.sqrt(Q_sub[0, 0]) sx = sigma0_apost * np.sqrt(Q_sub[0, 0])
sy = s0_apost * np.sqrt(Q_sub[1, 1]) sy = sigma0_apost * np.sqrt(Q_sub[1, 1])
sz = s0_apost * np.sqrt(Q_sub[2, 2]) sz = sigma0_apost * np.sqrt(Q_sub[2, 2])
# Eigenwertzerlegung # Eigenwertzerlegung
eigenwerte, eigenvektoren = np.linalg.eigh(Q_sub) eigenwerte, eigenvektoren = np.linalg.eigh(Q_sub)
eigenwerte = np.sort(eigenwerte)[::-1] eigenwerte = np.sort(eigenwerte)[::-1]
# Halbachsen # Halbachsen
s_a = s0_apost * np.sqrt(eigenwerte[0]) # Große Halbachse a s_a = sigma0_apost * np.sqrt(eigenwerte[0]) # Große Halbachse a
s_b = s0_apost * np.sqrt(eigenwerte[1]) # Mittlere Halbachse b s_b = sigma0_apost * np.sqrt(eigenwerte[1]) # Mittlere Halbachse b
s_c = s0_apost * np.sqrt(eigenwerte[2]) # Kleine Halbachse c s_c = sigma0_apost * np.sqrt(eigenwerte[2]) # Kleine Halbachse c
# Richtungswinkel theta in gon: # Richtungswinkel theta in gon:
qyx = Q_sub[1, 0] qyx = Q_sub[1, 0]
@@ -192,10 +191,10 @@ class Genauigkeitsmaße:
]) ])
except: except:
continue continue
standardellipsoid = pd.DataFrame(daten, columns=["Punkt", "σx [m]", "σy [m]", "σz [m]", "Halbachse a [m]", "Halbachse b [m]", "Halbachse c [m]", "θ [gon]"]) standardellipsoid = pd.DataFrame(daten, columns=["Punkt", "σ̂x [m]", "σ̂y [m]", "σ̂z [m]", "Halbachse a [m]", "Halbachse b [m]", "Halbachse c [m]", "θ [gon]"])
standardellipsoid["σx [m]"] = standardellipsoid["σx [m]"].astype(float).round(4) standardellipsoid["σ̂x [m]"] = standardellipsoid["σ̂x [m]"].astype(float).round(4)
standardellipsoid["σy [m]"] = standardellipsoid["σy [m]"].astype(float).round(4) standardellipsoid["σ̂y [m]"] = standardellipsoid["σ̂y [m]"].astype(float).round(4)
standardellipsoid["σz [m]"] = standardellipsoid["σz [m]"].astype(float).round(4) standardellipsoid["σ̂z [m]"] = standardellipsoid["σ̂z [m]"].astype(float).round(4)
standardellipsoid["Halbachse a [m]"] = standardellipsoid["Halbachse a [m]"].astype(float).round(4) standardellipsoid["Halbachse a [m]"] = standardellipsoid["Halbachse a [m]"].astype(float).round(4)
standardellipsoid["Halbachse b [m]"] = standardellipsoid["Halbachse b [m]"].astype(float).round(4) standardellipsoid["Halbachse b [m]"] = standardellipsoid["Halbachse b [m]"].astype(float).round(4)
standardellipsoid["Halbachse c [m]"] = standardellipsoid["Halbachse c [m]"].astype(float).round(4) standardellipsoid["Halbachse c [m]"] = standardellipsoid["Halbachse c [m]"].astype(float).round(4)
@@ -207,23 +206,34 @@ class Genauigkeitsmaße:
@staticmethod @staticmethod
def konfidenzellipsoid(Qxx, s0_apost, unbekannten_liste, R, ausgabe_erfolgt): def konfidenzellipsoid(Qxx: np.ndarray, sigma0_apost: float, unbekannten_liste: list, R: int, ausgabe_erfolgt: bool) -> tuple[pd.DataFrame, float]:
""" """
Berechnet die Konfidenzellipse für Punkte aus Qxx und einem Konfidenzniveau. Berechnet die Konfidenzellipsoid für Punkte aus Qxx und einem Konfidenzniveau.
Auf Basis der Kovarianz-Matrix der Unbekannten Qxx und der a-posteriori Auf Basis der Kovarianz-Matrix der Unbekannten Qxx und der a-posteriori
Standardabweichung der Gewichtseinheit s₀ werden für jeden Punkt die Parameter Standardabweichung der Gewichtseinheit σ̂₀ werden für jeden Punkt die Parameter
der Konfidenzellipse berechnet. Das Konfidenzniveau wird mittels einer Eingabe des Konfidenzellipsoids berechnet. Das Konfidenzniveau wird mittels einer Eingabe
über alpha gewählt (Standard: 0.05 für 95%). über alpha festgelegt (Standard: 0.05 für 95%).
Die Punktzuordnung erfolgt über die Symbolnamen der Unbekanntenliste (z.B. X1, Y1). Für jeden Punkt wird die 3×3-Submatrix der Koordinaten (X, Y, Z) aus Qxx gebildet.
Über eine Eigenwertzerlegung dieser Submatrix werden die drei Hauptachsen des
Fehlerellipsoids bestimmt. Die Halbachsen des Konfidenzellipsoids ergeben sich aus:
- Aₖ: große Halbachse des Konfidenzellipsoids,
- Bₖ: mittlere Halbachse des Konfidenzellipsoids,
- Cₖ: kleine Halbachse des Konfidenzellipsoids,
unter Verwendung eines Faktors aus der F-Verteilung in Abhängigkeit vom
Konfidenzniveau und den Freiheitsgraden.
Die Punktzuordnung erfolgt über die Symbolnamen der Unbekanntenliste.
Optional wird die Tabelle ausgegeben und als Excel-Datei exportiert, abhängig von Optional wird die Tabelle ausgegeben und als Excel-Datei exportiert, abhängig von
ausgabe_erfolgt. ausgabe_erfolgt.
:param Qxx: Kofaktor-Matrix der geschätzten Unbekannten. :param Qxx: Kofaktor-Matrix der geschätzten Unbekannten.
:type Qxx: numpy.ndarray :type Qxx: np.ndarray
:param s0_apost: a-posteriori Standardabweichung der Gewichtseinheit s₀. :param sigma0_apost: a-posteriori Standardabweichung der Gewichtseinheit s₀.
:type s0_apost: float :type sigma0_apost: float
:param unbekannten_liste: Liste der Unbekannten. :param unbekannten_liste: Liste der Unbekannten.
:type unbekannten_liste: list :type unbekannten_liste: list
:param R: Redundanz (Freiheitsgrade) für die F-Verteilung. :param R: Redundanz (Freiheitsgrade) für die F-Verteilung.
@@ -232,7 +242,6 @@ class Genauigkeitsmaße:
:type ausgabe_erfolgt: bool :type ausgabe_erfolgt: bool
:return: Tabelle der Konfidenzellipse je Punkt, verwendetes alpha. :return: Tabelle der Konfidenzellipse je Punkt, verwendetes alpha.
:rtype: tuple[pandas.DataFrame, float] :rtype: tuple[pandas.DataFrame, float]
:raises ValueError: Wenn alpha nicht in (0, 1) liegt oder nicht in float umgewandelt werden kann.
""" """
alpha_input = input("Irrtumswahrscheinlichkeit α wählen (z.B. 0.05, 0.01) [Standard=0.05]: ") alpha_input = input("Irrtumswahrscheinlichkeit α wählen (z.B. 0.05, 0.01) [Standard=0.05]: ")
if alpha_input.strip() == "": if alpha_input.strip() == "":
@@ -259,18 +268,18 @@ class Genauigkeitsmaße:
Q_sub = Qxx[np.ix_(indices, indices)] Q_sub = Qxx[np.ix_(indices, indices)]
# Standardabweichungen # Standardabweichungen
sx = s0_apost * np.sqrt(Q_sub[0, 0]) sx = sigma0_apost * np.sqrt(Q_sub[0, 0])
sy = s0_apost * np.sqrt(Q_sub[1, 1]) sy = sigma0_apost * np.sqrt(Q_sub[1, 1])
sz = s0_apost * np.sqrt(Q_sub[2, 2]) sz = sigma0_apost * np.sqrt(Q_sub[2, 2])
# Eigenwertzerlegung # Eigenwertzerlegung
eigenwerte, eigenvektoren = np.linalg.eigh(Q_sub) eigenwerte, eigenvektoren = np.linalg.eigh(Q_sub)
eigenwerte = np.sort(eigenwerte)[::-1] eigenwerte = np.sort(eigenwerte)[::-1]
# Halbachsen des Konfidenzellipoid # Halbachsen des Konfidenzellipoid
A_K = k * s0_apost * np.sqrt(eigenwerte[0]) A_K = k * sigma0_apost * np.sqrt(eigenwerte[0])
B_K = k * s0_apost * np.sqrt(eigenwerte[1]) B_K = k * sigma0_apost * np.sqrt(eigenwerte[1])
C_K = k * s0_apost * np.sqrt(eigenwerte[2]) C_K = k * sigma0_apost * np.sqrt(eigenwerte[2])
# Richtungswinkel theta in gon: # Richtungswinkel theta in gon:
qyx = Q_sub[1, 0] qyx = Q_sub[1, 0]
@@ -288,7 +297,7 @@ class Genauigkeitsmaße:
except: except:
continue continue
konfidenzellipoid = pd.DataFrame(daten, columns=["Punkt", "σx [m]", "σy [m]", "σz [m]", "Halbachse a_k [m]", "Halbachse b_k [m]", "Halbachse c_k [m]", "θ [gon]"]) konfidenzellipoid = pd.DataFrame(daten, columns=["Punkt", "σ̂x [m]", "σ̂y [m]", "σ̂z [m]", "Halbachse a_k [m]", "Halbachse b_k [m]", "Halbachse c_k [m]", "θ [gon]"])
if ausgabe_erfolgt == False: if ausgabe_erfolgt == False:
display(HTML(konfidenzellipoid.to_html(index=False))) display(HTML(konfidenzellipoid.to_html(index=False)))
konfidenzellipoid.to_excel(r"Netzqualitaet\Konfidenzellipoid.xlsx", index=False) konfidenzellipoid.to_excel(r"Netzqualitaet\Konfidenzellipoid.xlsx", index=False)
@@ -296,7 +305,7 @@ class Genauigkeitsmaße:
@staticmethod @staticmethod
def konfidenzellipsen_enu(a, b, ausgabe_parameterschaetzung, liste_unbekannte, ausgleichungsergebnis, s0apost, r_gesamt): def konfidenzellipsen_enu(a: float, b: float, ausgabe_parameterschaetzung: dict, liste_unbekannte: list, ausgleichungsergebnis: dict, sigma0apost: float, r_gesamt: int) -> tuple[pd.DataFrame, np.ndarray]:
""" """
Berechnet Konfidenzellipsen im lokalen ENU-System aus einer ins ENU-System transformierten Qxx-Matrix. Berechnet Konfidenzellipsen im lokalen ENU-System aus einer ins ENU-System transformierten Qxx-Matrix.
@@ -317,13 +326,12 @@ class Genauigkeitsmaße:
:type liste_unbekannte: list :type liste_unbekannte: list
:param ausgleichungsergebnis: Dictionary der geschätzten Punktkoordinaten (XYZ) zur ENU-Referenzbildung. :param ausgleichungsergebnis: Dictionary der geschätzten Punktkoordinaten (XYZ) zur ENU-Referenzbildung.
:type ausgleichungsergebnis: dict :type ausgleichungsergebnis: dict
:param s0apost: a-posteriori Standardabweichung der Gewichtseinheit s₀. :param sigma0apost: a-posteriori Standardabweichung der Gewichtseinheit s₀.
:type s0apost: float :type sigma0apost: float
:param r_gesamt: Redundanz (Freiheitsgrade) für die Konfidenzberechnung. :param r_gesamt: Redundanz (Freiheitsgrade) für die Konfidenzberechnung.
:type r_gesamt: int :type r_gesamt: int
:return: Tabelle der Konfidenzellipse im ENU-System, Rotationsmatrix R0 der ENU-Transformation. :return: Tabelle der Konfidenzellipse im ENU-System, Rotationsmatrix R0 der ENU-Transformation.
:rtype: tuple[pandas.DataFrame, numpy.ndarray] :rtype: tuple[pandas.DataFrame, numpy.ndarray]
:raises KeyError: Wenn ``ausgabe_parameterschaetzung`` keinen Eintrag ``"Q_xx"`` enthält.
""" """
berechnungen = Berechnungen.Berechnungen(a, b) berechnungen = Berechnungen.Berechnungen(a, b)
@@ -342,7 +350,7 @@ class Genauigkeitsmaße:
# 2) Konfidenzellipoid im ENU-System # 2) Konfidenzellipoid im ENU-System
Konfidenzellipse_ENU, alpha = Genauigkeitsmaße.konfidenzellipsoid( Konfidenzellipse_ENU, alpha = Genauigkeitsmaße.konfidenzellipsoid(
Qxx_enu, Qxx_enu,
s0apost, sigma0apost,
liste_unbekannte, liste_unbekannte,
r_gesamt, r_gesamt,
ausgabe_erfolgt = True ausgabe_erfolgt = True
@@ -350,16 +358,16 @@ class Genauigkeitsmaße:
# 3) Spaltennamen anpassen # 3) Spaltennamen anpassen
Konfidenzellipse_ENU = Konfidenzellipse_ENU.rename(columns={ Konfidenzellipse_ENU = Konfidenzellipse_ENU.rename(columns={
"σx [m]": "σE [m]", "σ̂x [m]": "σ̂E [m]",
"σy [m]": "σN [m]", "σ̂y [m]": "σ̂N [m]",
"σz [m]": "σU [m]", "σ̂z [m]": "σ̂U [m]",
"θ [gon]": "θ_EN [gon]" "θ [gon]": "θ_EN [gon]"
}) })
# 4) Runden und Anzeigen # 4) Runden und Anzeigen
Konfidenzellipse_ENU["σE [m]"] = Konfidenzellipse_ENU["σE [m]"].round(6) Konfidenzellipse_ENU["σ̂E [m]"] = Konfidenzellipse_ENU["σ̂E [m]"].round(6)
Konfidenzellipse_ENU["σN [m]"] = Konfidenzellipse_ENU["σN [m]"].round(6) Konfidenzellipse_ENU["σ̂N [m]"] = Konfidenzellipse_ENU["σ̂N [m]"].round(6)
Konfidenzellipse_ENU["σU [m]"] = Konfidenzellipse_ENU["σU [m]"].round(6) Konfidenzellipse_ENU["σ̂U [m]"] = Konfidenzellipse_ENU["σ̂U [m]"].round(6)
Konfidenzellipse_ENU["Halbachse a_k [m]"] = Konfidenzellipse_ENU["Halbachse a_k [m]"].round(4) Konfidenzellipse_ENU["Halbachse a_k [m]"] = Konfidenzellipse_ENU["Halbachse a_k [m]"].round(4)
Konfidenzellipse_ENU["Halbachse b_k [m]"] = Konfidenzellipse_ENU["Halbachse b_k [m]"].round(4) Konfidenzellipse_ENU["Halbachse b_k [m]"] = Konfidenzellipse_ENU["Halbachse b_k [m]"].round(4)
Konfidenzellipse_ENU["Halbachse c_k [m]"] = Konfidenzellipse_ENU["Halbachse c_k [m]"].round(4) Konfidenzellipse_ENU["Halbachse c_k [m]"] = Konfidenzellipse_ENU["Halbachse c_k [m]"].round(4)
@@ -390,15 +398,7 @@ class Plot:
""" """
@staticmethod @staticmethod
def netzplot_ellipsen( def netzplot_ellipsen(Koord_ENU: dict[str, tuple[float, float, float]], unbekannten_labels: list, beobachtungs_labels: list, df_konf_ellipsen_enu: pd.DataFrame, skalierung: float, n_ellipse_pts: int = 60, titel: str = "Netzplot im ENU-System mit Konfidenzellipsen") -> go.Figure:
Koord_ENU,
unbekannten_labels,
beobachtungs_labels,
df_konf_ellipsen_enu,
skalierung,
n_ellipse_pts=60,
titel="Netzplot im ENU-System mit Konfidenzellipsen"
):
""" """
Erstellt einen Netzplot im ENU-System inklusive Konfidenzellipsen, Netzpunkten und Beobachtungslinien. Erstellt einen Netzplot im ENU-System inklusive Konfidenzellipsen, Netzpunkten und Beobachtungslinien.
@@ -430,7 +430,6 @@ class Plot:
:type titel: str :type titel: str
:return: Plotly-Figure-Objekt mit Netz, Beobachtungen und Ellipsen. :return: Plotly-Figure-Objekt mit Netz, Beobachtungen und Ellipsen.
:rtype: plotly.graph_objects.Figure :rtype: plotly.graph_objects.Figure
:raises ValueError: Wenn weder "θ_EN [gon]" noch "θ [gon]" im DataFrame vorhanden ist.
""" """
namen = [str(s).strip() for s in unbekannten_labels] namen = [str(s).strip() for s in unbekannten_labels]
@@ -546,7 +545,7 @@ class Plot:
return plot return plot
def plot_speichere_aktuelle_ansicht(plot, dateiname=r"Netzqualitaet\netzplot_ellipsen_zoom_ansicht.png"): def plot_speichere_aktuelle_ansicht(plot: go.Figure, dateiname: str = r"Netzqualitaet\netzplot_ellipsen_zoom_ansicht.png") -> None:
""" """
Speichert die aktuell dargestellte Plot-Ansicht als Bilddatei. Speichert die aktuell dargestellte Plot-Ansicht als Bilddatei.
@@ -564,7 +563,6 @@ class Plot:
:type dateiname: str :type dateiname: str
:return: None :return: None
:rtype: None :rtype: None
:raises OSError: Wenn die Bilddatei nicht geschrieben werden kann (z.B. fehlender Pfad oder fehlendes Kaleido).
""" """
aktuelles_layout = plot.layout aktuelles_layout = plot.layout

View File

@@ -12,9 +12,20 @@ from itables.widget import ITable
@dataclass @dataclass
class Zuverlaessigkeit: class Zuverlaessigkeit:
"""Berechnung von Zuverlässigkeitsmaße zur Bewertung der erreichten Netzqualität.
Die Klasse stellt Methoden zur Verfügung für:
- Berechnung der Gesamtredundanz
- Aufbau der Redundanzmatrix
- Ableitung und Klassifikation der Redundanzanteile
- Durchführung des Globaltests zur Modellprüfung
- Lokaltest und Maße der inneren Zuverlässigkeit
- Berechnung von Kenngrößen der äußeren Zuverlässigkeit
"""
@staticmethod @staticmethod
def gesamtredundanz(n, u): def gesamtredundanz(n: int, u: int) -> int:
""" """
Berechnet die Gesamtredundanz des Netzes. Berechnet die Gesamtredundanz des Netzes.
@@ -35,7 +46,7 @@ class Zuverlaessigkeit:
@staticmethod @staticmethod
def berechne_R(Q_vv, P): def berechne_R(Q_vv: np.ndarray, P: np.ndarray) -> np.ndarray:
""" """
Berechnet die Redundanzmatrix R aus Qvv und der Gewichtsmatrix P. Berechnet die Redundanzmatrix R aus Qvv und der Gewichtsmatrix P.
@@ -54,7 +65,7 @@ class Zuverlaessigkeit:
@staticmethod @staticmethod
def berechne_ri(R): def berechne_ri(R: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
""" """
Berechnet die Redundanzanteile einzelner Beobachtungen. Berechnet die Redundanzanteile einzelner Beobachtungen.
@@ -74,7 +85,7 @@ class Zuverlaessigkeit:
@staticmethod @staticmethod
def klassifiziere_ri(ri): def klassifiziere_ri(ri: float) -> str:
""" """
Klassifiziert einen Redundanzanteil rᵢ nach seiner Kontrollierbarkeit. Klassifiziert einen Redundanzanteil rᵢ nach seiner Kontrollierbarkeit.
@@ -99,7 +110,7 @@ class Zuverlaessigkeit:
@staticmethod @staticmethod
def redundanzanteile_ri(Qvv, P, liste_beob): def redundanzanteile_ri(Qvv: np.ndarray, P: np.ndarray, liste_beob: list[str]) -> tuple[np.ndarray, np.ndarray, np.ndarray, pd.DataFrame]:
""" """
Berechnet und dokumentiert Redundanzanteile rᵢ und EVᵢ für alle Beobachtungen. Berechnet und dokumentiert Redundanzanteile rᵢ und EVᵢ für alle Beobachtungen.
@@ -129,7 +140,7 @@ class Zuverlaessigkeit:
@staticmethod @staticmethod
def globaltest(r_gesamt, sigma0_apost, sigma0_apriori=1): def globaltest(r_gesamt: int, sigma0_apost: float, sigma0_apriori: float = 1.0) -> dict[str, int | float | bool | str]:
""" """
Führt den Globaltest zur Prüfung des Ausgleichungsmodells durch. Führt den Globaltest zur Prüfung des Ausgleichungsmodells durch.
@@ -148,10 +159,8 @@ class Zuverlaessigkeit:
:param sigma0_apriori: a-priori Standardabweichung der Gewichtseinheit σ₀ (Standard=1). :param sigma0_apriori: a-priori Standardabweichung der Gewichtseinheit σ₀ (Standard=1).
:type sigma0_apriori: float :type sigma0_apriori: float
:return: Dictionary mit Testparametern, Testergebnis (H₀ angenommen/verworfen) und Interpretation. :return: Dictionary mit Testparametern, Testergebnis (H₀ angenommen/verworfen) und Interpretation.
:rtype: dict[str, Any] :rtype: dict[str, int | float | bool | str]
:raises ValueError: Wenn alpha nicht in (0, 1) liegt oder nicht in float umgewandelt werden kann.
""" """
alpha_input = input("Irrtumswahrscheinlichkeit α wählen (z.B. 0.05, 0.01) [Standard=0.001]: ").strip() alpha_input = input("Irrtumswahrscheinlichkeit α wählen (z.B. 0.05, 0.01) [Standard=0.001]: ").strip()
alpha = 0.001 if alpha_input == "" else float(alpha_input) alpha = 0.001 if alpha_input == "" else float(alpha_input)
T_G = (sigma0_apost ** 2) / (sigma0_apriori ** 2) T_G = (sigma0_apost ** 2) / (sigma0_apriori ** 2)
@@ -193,40 +202,38 @@ class Zuverlaessigkeit:
} }
def lokaltest_innere_Zuverlaessigkeit(v, Q_vv, ri, labels, s0_apost, alpha, beta): def lokaltest_innere_Zuverlaessigkeit(v: np.ndarray, Q_vv: np.ndarray, ri: np.ndarray, labels: list, sigma0_apost: float, alpha: float, beta: float) -> pd.DataFrame:
""" """
Führt den Lokaltest zur Grobfehlerdetektion je Beobachtung durch. Führt den Lokaltest zur Grobfehlerdetektion je Beobachtung durch.
Auf Basis der Residuen v, der Kofaktor-Matrix der Residuen Qvv und der Redundanzanteile rᵢ Auf Basis der Residuen v, der Kofaktor-Matrix der Residuen Qvv und der Redundanzanteile rᵢ
werden für jede Beobachtung statistische Kennwerte zur Detektion grober Fehler berechnet. Dazu zählen: werden für jede Beobachtung statistische Kennwerte zur Detektion grober Fehler berechnet. Dazu zählen:
- Grobfehlerabschätzung: GFᵢ = vᵢ / rᵢ - Grobfehlerabschätzung GFᵢ
- Standardabweichung der Residuen: s_vᵢ = s₀ · √q_vᵢ (mit q_vᵢ = diag(Qvv)) - Standardabweichung der Residuen s_vᵢ
- Normierte Verbesserung: NVᵢ = |vᵢ| / s_vᵢ - Normierte Verbesserung NVᵢ
- Nichtzentralitätsparameter: δ₀ = k + k_A - Nichtzentralitätsparameter δ₀ mit k aus dem zweiseitigen Normalquantil (α) und k_A aus der Testmacht (1β)
mit k aus dem zweiseitigen Normalquantil (α) und k_A aus der Testmacht (1β) - Grenzwert der Aufdeckbarkeit (Minimal detektierbarer Grobfehler) GRZWᵢ
- Grenzwert der Aufdeckbarkeit (Minimal detektierbarer Grobfehler): GRZWᵢ = (s_vᵢ / rᵢ) · δ₀
Beobachtungen werden als auffällig markiert, wenn NVᵢ > δ₀. Für rᵢ = 0 wird die Grobfehlerabschätzung Beobachtungen werden als auffällig markiert, wenn NVᵢ > δ₀. Für rᵢ = 0 wird die Grobfehlerabschätzung
und der Grenzwert als NaN gesetzt. und der Grenzwert als NaN gesetzt.
:param v: Residuenvektor der Beobachtungen. :param v: Residuenvektor der Beobachtungen.
:type v: np.asarray :type v: np.ndarray
:param Q_vv: Kofaktor-Matrix der Residuen. :param Q_vv: Kofaktor-Matrix der Residuen.
:type Q_vv: np.asarray :type Q_vv: np.ndarray
:param ri: Redundanzanteile der Beobachtungen. :param ri: Redundanzanteile der Beobachtungen.
:type ri: np.asarray :type ri: np.ndarray
:param labels: Liste der Beobachtungen zur Zuordnung in der Ergebnistabelle. :param labels: Liste der Beobachtungen zur Zuordnung in der Ergebnistabelle.
:type labels: list :type labels: list
:param s0_apost: a-posteriori Standardabweichung der Gewichtseinheit s₀. :param sigma0_apost: a-posteriori Standardabweichung der Gewichtseinheit s₀.
:type s0_apost: float :type sigma0_apost: float
:param alpha: Irrtumswahrscheinlichkeit α (Signifikanzniveau, zweiseitiger Test). :param alpha: Irrtumswahrscheinlichkeit α (Signifikanzniveau, zweiseitiger Test).
:type alpha: float :type alpha: float
:param beta: Wahrscheinlichkeit β für einen Fehler 2. Art (Testmacht = 1β). :param beta: Wahrscheinlichkeit β für einen Fehler 2. Art (Testmacht = 1β).
:type beta: float :type beta: float
:return: DataFrame mit NVᵢ, Auffälligkeit, Grobfehlerabschätzung GFᵢ und Grenzwert GRZWᵢ je Beobachtung. :return: DataFrame mit NVᵢ, Auffälligkeit, Grobfehlerabschätzung GFᵢ und Grenzwert GRZWᵢ je Beobachtung.
:rtype: pandas.DataFrame :rtype: pandas.DataFrame
:raises ValueError: Wenn alpha oder beta nicht im Intervall (0, 1) liegen.
""" """
v = np.asarray(v, float).reshape(-1) v = np.asarray(v, float).reshape(-1)
Q_vv = np.asarray(Q_vv, float) Q_vv = np.asarray(Q_vv, float)
@@ -239,7 +246,7 @@ class Zuverlaessigkeit:
# Standardabweichungen der Residuen # Standardabweichungen der Residuen
qv = np.diag(Q_vv).astype(float) qv = np.diag(Q_vv).astype(float)
s_vi = float(s0_apost) * np.sqrt(qv) s_vi = float(sigma0_apost) * np.sqrt(qv)
# Normierte Verbesserung NV # Normierte Verbesserung NV
NV = np.abs(v) / s_vi NV = np.abs(v) / s_vi
@@ -274,7 +281,7 @@ class Zuverlaessigkeit:
return Lokaltest_innere_Zuv return Lokaltest_innere_Zuv
def aufruf_lokaltest(liste_beob, alpha, ausgabe_parameterschaetzung, ri, s0_aposteriori): def aufruf_lokaltest(liste_beob: list[str], alpha: float, ausgabe_parameterschaetzung: dict, ri: np.ndarray, sigma0_aposteriori: float) -> tuple[dict[str, bool], float]:
"""Startet den Lokaltest und erzeugt die interaktive Tabelle. """Startet den Lokaltest und erzeugt die interaktive Tabelle.
:param liste_beob: Liste der Beobachtungslabels. :param liste_beob: Liste der Beobachtungslabels.
@@ -284,9 +291,9 @@ class Zuverlaessigkeit:
:param ausgabe_parameterschaetzung: Dictionary mit den Ergebnissen der letzten Iteration der Parameterschätzung. :param ausgabe_parameterschaetzung: Dictionary mit den Ergebnissen der letzten Iteration der Parameterschätzung.
:type ausgabe_parameterschaetzung: dict :type ausgabe_parameterschaetzung: dict
:param ri: Redundanz. :param ri: Redundanz.
:type ri: Any :type ri: np.ndarray
:param s0_aposteriori: a-posteriori Standardabweichung. :param sigma0_aposteriori: a-posteriori Standardabweichung.
:type s0_aposteriori: float :type sigma0_aposteriori: float
:return: ausschalten_dict :return: ausschalten_dict
:rtype: dict :rtype: dict
""" """
@@ -305,7 +312,7 @@ class Zuverlaessigkeit:
Q_vv=ausgabe_parameterschaetzung["Q_vv"], Q_vv=ausgabe_parameterschaetzung["Q_vv"],
ri=ri, ri=ri,
labels=labels, labels=labels,
s0_apost=s0_aposteriori, sigma0_apost=sigma0_aposteriori,
alpha=alpha, alpha=alpha,
beta=beta beta=beta
) )
@@ -345,36 +352,23 @@ class Zuverlaessigkeit:
def aeussere_zuverlaessigkeit( def aeussere_zuverlaessigkeit(Lokaltest: pd.DataFrame, bezeichnung: list, Qxx: np.ndarray, A: np.ndarray, P: np.ndarray, sigma0_apost: float, unbekannten_liste: list, x: np.ndarray, ausschliessen: tuple[str, ...] = ("lA_",)) -> pd.DataFrame:
Lokaltest, bezeichnung, Qxx, A, P, s0_apost, unbekannten_liste, x,
ausschliessen=("lA_",),
):
""" """
Berechnet Parameter der äußeren Zuverlässigkeit (EP/EF) je Beobachtung. Berechnet Parameter der äußeren Zuverlässigkeit (EP/EF) je Beobachtung.
Auf Basis der Ergebnisse des Lokaltests werden für jede Beobachtung Maße der äußeren Auf Basis der Ergebnisse des Lokaltests werden für jede Beobachtung Maße der äußeren Zuverlässigkeit bestimmt. Dazu zählen:
Zuverlässigkeit bestimmt. Dazu zählen:
- Einfluss auf die (relative) Punktlage EP: - Einfluss auf die Punktlage EP
- aus geschätzter Modellstörung: EP_GF,i = |(1 - r_i) · GF_i| - aus geschätzter Modellstörung EP_GF,i
- aus Grenzwert der nicht mehr aufdeckbaren Modellstörung: EP_GRZW,i = |(1 - r_i) · GRZW_i| - aus Grenzwert der nicht mehr aufdeckbaren Modellstörung EP_GRZW,i
Für Winkelbeobachtungen (R/ZW) wird EP in eine äquivalente Querabweichung (in m) umgerechnet: q = EP · s - Für Richtungs- und Winkelbeobachtungen erfolgt eine Umrechnung
wobei EP als Winkelstörung im Bogenmaß (rad) und s als räumliche Strecke zwischen Stand- und - Einflussfaktor EF
Zielpunkt verwendet wird. - Es wird eine Einzelstörung Δl_i = GRZW_i angesetzt und in den Unbekanntenraum übertragen
- Einflussfaktor / Netzverzerrung EF (Worst-Case-Einfluss einer nicht detektierten Störung): - Der Einflussfaktor wird lokal berechnet
Es wird eine Einzelstörung Δl_i = GRZW_i angesetzt (alle anderen Δl_j = 0) und in den - Punktstreuungsmaß SP_3D und maximale Verfälschung EF·SP
Unbekanntenraum übertragen: Δx = Q_xx · A^T · P · Δl
Der Einflussfaktor wird lokal (nur für die von der Beobachtung berührten Punktkoordinaten,
i.d.R. Stand- und Zielpunkt) über die gewichtete Norm berechnet: EF_i^2 = (Δx_loc^T · Q_loc^{-1} · Δx_loc) / s0^2
mit s0 = a posteriori Standardabweichung der Gewichtseinheit.
- Punktstreuungsmaß SP_3D und maximale Verfälschung EF·SP:
Für die berührten Punkte wird je Punkt der 3×3-Block aus Q_xx betrachtet: als Maß wird die maximale Spur
verwendet: SP_3D,loc = s0 · sqrt( max( tr(Q_P) ) )
und daraus: (EF·SP)_i = EF_i · SP_3D,loc
Pseudobeobachtungen (z.B. Lagerungs-/Anschlussgleichungen) können über Präfixe in Pseudobeobachtungen (z.B. Lagerungs-/Anschlussgleichungen) können über Präfixe in
"ausschliessen" aus der Auswertung entfernt werden. Es wird geprüft, ob die Anzahl "ausschliessen" aus der Auswertung entfernt werden.
der Bezeichnungen und die Zeilenanzahl des Lokaltests zur Beobachtungsanzahl von A passen.
:param Lokaltest: DataFrame des Lokaltests`. :param Lokaltest: DataFrame des Lokaltests`.
:type Lokaltest: pandas.DataFrame :type Lokaltest: pandas.DataFrame
@@ -386,8 +380,8 @@ class Zuverlaessigkeit:
:type A: numpy.ndarray :type A: numpy.ndarray
:param P: Gewichtsmatrix der Beobachtungen. :param P: Gewichtsmatrix der Beobachtungen.
:type P: numpy.ndarray :type P: numpy.ndarray
:param s0_apost: a-posteriori Standardabweichung der Gewichtseinheit s₀. :param sigma0_apost: a-posteriori Standardabweichung der Gewichtseinheit s₀.
:type s0_apost: float :type sigma0_apost: float
:param unbekannten_liste: Liste der Unbekannten. :param unbekannten_liste: Liste der Unbekannten.
:type unbekannten_liste: list :type unbekannten_liste: list
:param x: Unbekanntenvektor. :param x: Unbekanntenvektor.
@@ -395,7 +389,7 @@ class Zuverlaessigkeit:
:param ausschliessen: Präfixe von Beobachtungsbezeichnungen, die aus der Auswertung entfernt werden sollen :param ausschliessen: Präfixe von Beobachtungsbezeichnungen, die aus der Auswertung entfernt werden sollen
(Standard: ("lA_",) für Lagerungs-/Pseudobeobachtungen). (Standard: ("lA_",) für Lagerungs-/Pseudobeobachtungen).
:type ausschliessen: tuple :type ausschliessen: tuple
:return: DataFrame mit Stand/Zielpunkt, Redundanzanteil rᵢ, EP (aus GF und GRZW), EF sowie SP_3D und EF·SP_3D. :return: DataFrame mit Stand/Zielpunkt, Redundanzanteil rᵢ, EP (aus GF und GRZW), EF, SP_3D und EF·SP_3D.
:rtype: pandas.DataFrame :rtype: pandas.DataFrame
:raises ValueError: Wenn die Anzahl der Bezeichnungen oder die Zeilenanzahl des Lokaltests nicht zu A passt. :raises ValueError: Wenn die Anzahl der Bezeichnungen oder die Zeilenanzahl des Lokaltests nicht zu A passt.
""" """
@@ -434,7 +428,7 @@ class Zuverlaessigkeit:
ri = lokaltest_daten["r_i"].astype(float).to_numpy() ri = lokaltest_daten["r_i"].astype(float).to_numpy()
GF = lokaltest_daten["GF_i"].astype(float).to_numpy() GF = lokaltest_daten["GF_i"].astype(float).to_numpy()
GRZW = lokaltest_daten["GRZW_i"].astype(float).to_numpy() GRZW = lokaltest_daten["GRZW_i"].astype(float).to_numpy()
s0 = float(s0_apost) s0 = float(sigma0_apost)
# Punktkoordinaten # Punktkoordinaten
koordinaten = {} koordinaten = {}
@@ -576,7 +570,7 @@ class LokaltestInnereZuverlaessigkeitGUI:
einer Komponente (bx/by/bz) automatisch das gesamte Trio gewählt bzw. abgewählt wird. einer Komponente (bx/by/bz) automatisch das gesamte Trio gewählt bzw. abgewählt wird.
""" """
def __init__(self, df): def __init__(self, df: pd.DataFrame) -> None:
"""Initialisiert die GUI-Objekte. """Initialisiert die GUI-Objekte.
:param df: DataFrame des Lokaltests (inkl. Spalte "Beobachtung"). :param df: DataFrame des Lokaltests (inkl. Spalte "Beobachtung").
@@ -606,7 +600,7 @@ class LokaltestInnereZuverlaessigkeitGUI:
self.btn_auswahl_zuruecksetzen = widgets.Button(description="Rückgängig", icon="refresh") self.btn_auswahl_zuruecksetzen = widgets.Button(description="Rückgängig", icon="refresh")
@staticmethod @staticmethod
def gnss_komponenten_extrahieren(beobachtung: str): def gnss_komponenten_extrahieren(beobachtung: str) -> tuple[str | None, str | None]:
"""Extrahiert GNSS-Komponente und einen eindeutigen Key für bx/by/bz-Trio. """Extrahiert GNSS-Komponente und einen eindeutigen Key für bx/by/bz-Trio.
:param beobachtung: Text aus Spalte "Beobachtung". :param beobachtung: Text aus Spalte "Beobachtung".

View File

@@ -53,7 +53,8 @@ class Iterationen:
self.fm = Funktionales_Modell.FunktionalesModell(self.pfad_datenbank, self.a, self.b, self.pfad_tif_quasigeoidundulation) self.fm = Funktionales_Modell.FunktionalesModell(self.pfad_datenbank, self.a, self.b, self.pfad_tif_quasigeoidundulation)
def ausgleichung_global(self, A, dl, Q_ext, P):
def ausgleichung_global(self, A: np.ndarray, dl: np.ndarray, Q_ext: np.ndarray, P: np.ndarray) -> tuple[dict[str, np.ndarray], np.ndarray]:
""" """
Führt eine Ausgleichung nach kleinsten Quadraten durch. Führt eine Ausgleichung nach kleinsten Quadraten durch.
@@ -62,24 +63,23 @@ class Iterationen:
Es werden folgende Berechnungsschitte durchgeführt: Es werden folgende Berechnungsschitte durchgeführt:
1) Normalgleichungsmatrix N = Aᵀ · P · A und Absolutglied n = Aᵀ · P · dl - Normalgleichungsmatrix N und Absolutgliedvektor n
2) Lösung dx = N⁻¹ · n - Zuschlagsvektor dx
3) Residuen v = A · dx dl - Residuenvektor v
4) Kofaktormatrix der Unbekannten Q_xx - Kofaktormatrix der Unbekannten Q_xx
5) Kofaktormatrix der ausgeglichenen Beobachtungen Q_ll_dach - Kofaktormatrix der ausgeglichenen Beobachtungen Q_ll_dach
6) Kofaktormatrix der Verbesserungen Q_vv - Kofaktormatrix der Verbesserungen Q_vv
:param A: Jacobi-Matrix (A-Matrix). :param A: Jacobi-Matrix (A-Matrix).
:type A: array_like :type A: np.ndarray
:param dl: Verbesserungsvektor bzw. Beobachtungsabweichungen. :param dl: Verbesserungsvektor bzw. Beobachtungsabweichungen.
:type dl: array_like :type dl: np.ndarray
:param Q_ext: a-priori Kofaktormatrix der Beobachtungen. :param Q_ext: a-priori Kofaktormatrix der Beobachtungen.
:type Q_ext: array_like :type Q_ext: np.ndarray
:param P: Gewichtsmatrix der Beobachtungen. :param P: Gewichtsmatrix der Beobachtungen.
:type P: array_like :type P: np.ndarray
:return: Dictionary mit Ausgleichungsergebnissen, Zuschlagsvektor dx. :return: Dictionary mit Ausgleichungsergebnissen, Zuschlagsvektor dx.
:rtype: tuple[dict[str, Any], numpy.ndarray] :rtype: tuple[dict[str, numpy.ndarray], np.ndarray]
:raises numpy.linalg.LinAlgError: Wenn das Normalgleichungssystem singulär ist und nicht gelöst werden kann.
""" """
A = np.asarray(A, float) A = np.asarray(A, float)
dl = np.asarray(dl, float).reshape(-1, 1) dl = np.asarray(dl, float).reshape(-1, 1)

View File

@@ -1,6 +1,6 @@
import numpy as np import numpy as np
def atpv_probe(A, P, v, tol=1e-7): def atpv_probe(A: np.ndarray, P: np.ndarray, v: np.ndarray, tol: float = 1e-7) -> None:
""" """
Führt die ATPv-Probe zur Kontrolle der Lösung des Normalgleichungssystems durch. Führt die ATPv-Probe zur Kontrolle der Lösung des Normalgleichungssystems durch.
@@ -8,11 +8,11 @@ def atpv_probe(A, P, v, tol=1e-7):
Die Prüfung erfolgt unter Verwendung einer vorgegebenen Toleranz. Die Prüfung erfolgt unter Verwendung einer vorgegebenen Toleranz.
:param A: Jacobi-Matrix (A-Matrix). :param A: Jacobi-Matrix (A-Matrix).
:type A: np.asarray :type A: np.ndarray
:param P: Gewichtsmatrix der Beobachtungen. :param P: Gewichtsmatrix der Beobachtungen.
:type P: np.asarray :type P: np.ndarray
:param v: Residuenvektor der Beobachtungen. :param v: Residuenvektor der Beobachtungen.
:type v: np.asarray :type v: np.ndarray
:param tol: Absolute Toleranz für den Vergleich mit Null. :param tol: Absolute Toleranz für den Vergleich mit Null.
:type tol: float :type tol: float
:return: None :return: None
@@ -30,7 +30,7 @@ def atpv_probe(A, P, v, tol=1e-7):
print("❌ ATPv-Probe nicht erfolgreich. Fehler bei der Lösung des Normalgleichungssystems") print("❌ ATPv-Probe nicht erfolgreich. Fehler bei der Lösung des Normalgleichungssystems")
def hauptprobe(A, x, l, v, tol=1e-7): def hauptprobe(A: np.ndarray, x: np.ndarray, l: np.ndarray, v: np.ndarray, tol: float = 1e-7) -> None:
""" """
Führt die Hauptprobe zur Überprüfung der berechneten Residuen durch. Führt die Hauptprobe zur Überprüfung der berechneten Residuen durch.
@@ -40,13 +40,13 @@ def hauptprobe(A, x, l, v, tol=1e-7):
innerhalb der Toleranz überein, gilt die Ausgleichung als konsistent. innerhalb der Toleranz überein, gilt die Ausgleichung als konsistent.
:param A: Jacobi-Matrix (A-Matrix). :param A: Jacobi-Matrix (A-Matrix).
:type A: np.asarray :type A: np.ndarray
:param x: Lösungsvektor der Unbekannten. :param x: Lösungsvektor der Unbekannten.
:type x: np.asarray :type x: np.ndarray
:param l: Beobachtungsvektor. :param l: Beobachtungsvektor.
:type l: np.asarray :type l: np.ndarray
:param v: Residuenvektor aus der Ausgleichung. :param v: Residuenvektor aus der Ausgleichung.
:type v: np.asarray :type v: np.ndarray
:param tol: Absolute Toleranz für den Vergleich der Residuen. :param tol: Absolute Toleranz für den Vergleich der Residuen.
:type tol: float :type tol: float
:return: None :return: None

View File

@@ -205,7 +205,7 @@ class StochastischesModell:
Export.matrix_to_csv(r"Zwischenergebnisse\Qll_Symbolisch.csv", liste_beobachtungen_symbolisch, liste_beobachtungen_symbolisch, Qll, "Qll") Export.matrix_to_csv(r"Zwischenergebnisse\Qll_Symbolisch.csv", liste_beobachtungen_symbolisch, liste_beobachtungen_symbolisch, Qll, "Qll")
return Qll return Qll
def Qll_numerisch(self, Qll_Matrix_Symbolisch: sp.Matrix, liste_beobachtungen_symbolisch: list) -> np.asarray: def Qll_numerisch(self, Qll_Matrix_Symbolisch: sp.Matrix, liste_beobachtungen_symbolisch: list) -> np.ndarray:
"""Erstellt eine numerische Kofaktormatrix der Beobachtungen aus einer symbolischen Qll-Matrix. """Erstellt eine numerische Kofaktormatrix der Beobachtungen aus einer symbolischen Qll-Matrix.
Es werden die zur Substitution benötigten Werte aus der Datenbank abgefragt und den in Qll vorkommenden Symbolen zugeordnet, Es werden die zur Substitution benötigten Werte aus der Datenbank abgefragt und den in Qll vorkommenden Symbolen zugeordnet,
@@ -228,7 +228,7 @@ class StochastischesModell:
:param liste_beobachtungen_symbolisch: Liste der symbolischen Beobachtungskennungen. :param liste_beobachtungen_symbolisch: Liste der symbolischen Beobachtungskennungen.
:type liste_beobachtungen_symbolisch: list :type liste_beobachtungen_symbolisch: list
:return: Numerische Kofaktormatrix Qll als Numpy-Array. :return: Numerische Kofaktormatrix Qll als Numpy-Array.
:rtype: np.asarray :rtype: np.ndarray
:raises ValueError: Falls Symbole in Qll_Matrix_Symbolisch enthalten sind, für die keine Substitutionen vorhanden sind. :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 = [str(b).strip() for b in liste_beobachtungen_symbolisch]
@@ -381,7 +381,7 @@ class StochastischesModell:
return Qll_numerisch return Qll_numerisch
def QAA_symbolisch(self, liste_beobachtungen_symbolisch: list) -> np.asarray: def QAA_symbolisch(self, liste_beobachtungen_symbolisch: list) -> np.ndarray:
"""Erstellt die symbolische Kofaktormatrix der Anschlusspunkte (weiche Lagerung). """Erstellt die symbolische Kofaktormatrix der Anschlusspunkte (weiche Lagerung).
Es werden ausschließlich Beobachtungen berücksichtigt, deren Kennung mit "lA_" beginnt. Für jede Anschlussbedingung Es werden ausschließlich Beobachtungen berücksichtigt, deren Kennung mit "lA_" beginnt. Für jede Anschlussbedingung
@@ -421,7 +421,7 @@ class StochastischesModell:
Export.matrix_to_csv(r"Zwischenergebnisse\QAA_Symbolisch.csv", liste_beobachtungen_symbolisch, liste_beobachtungen_symbolisch, Qll, "Qll") Export.matrix_to_csv(r"Zwischenergebnisse\QAA_Symbolisch.csv", liste_beobachtungen_symbolisch, liste_beobachtungen_symbolisch, Qll, "Qll")
return Qll return Qll
def QAA_numerisch(self, QAA_Matrix_Symbolisch: sp.Matrix, liste_beobachtungen_symbolisch: list) -> np.asarray: def QAA_numerisch(self, QAA_Matrix_Symbolisch: sp.Matrix, liste_beobachtungen_symbolisch: list) -> np.ndarray:
"""Erstellt eine numerische Matrix aus einer symbolischen QAA-Matrix. """Erstellt eine numerische Matrix aus einer symbolischen QAA-Matrix.
Es werden die numerischen Standardabweichungen der Anschlussbedingungen sowie die Varianzkomponente der Gruppe Es werden die numerischen Standardabweichungen der Anschlussbedingungen sowie die Varianzkomponente der Gruppe
@@ -435,7 +435,7 @@ class StochastischesModell:
:param liste_beobachtungen_symbolisch: Liste der symbolischen Beobachtungskennungen. :param liste_beobachtungen_symbolisch: Liste der symbolischen Beobachtungskennungen.
:type liste_beobachtungen_symbolisch: list :type liste_beobachtungen_symbolisch: list
:return: Numerische VKofaktormatrix QAA als Numpy-Array. :return: Numerische VKofaktormatrix QAA als Numpy-Array.
:rtype: np.asarray :rtype: np.ndarray
""" """
# Symbolische Listen # Symbolische Listen
liste_beobachtungen_symbolisch = [str(b).strip() for b in liste_beobachtungen_symbolisch] liste_beobachtungen_symbolisch = [str(b).strip() for b in liste_beobachtungen_symbolisch]

View File

@@ -42,12 +42,12 @@ class VKS:
self.db_zugriff = Datenbank.Datenbankzugriff(self.pfad_datenbank) self.db_zugriff = Datenbank.Datenbankzugriff(self.pfad_datenbank)
def varianzkomponten_berechnen(self, Jacobimatrix_symbolisch_liste_beobachtungsvektor: list, res: dict, R: np.asarray) -> pd.DataFrame: def varianzkomponten_berechnen(self, Jacobimatrix_symbolisch_liste_beobachtungsvektor: list, res: dict, R: np.ndarray) -> pd.DataFrame:
"""Berechnet a-posteriori Varianzen und a-posteriori Standardabweichungen je Beobachtungsgruppe. """Berechnet a-posteriori Varianzen und a-posteriori Standardabweichungen je Beobachtungsgruppe.
Teilt die Residuen v, die Gewichtsmatrix P sowie die Redundanzmatrix R gemäß der in Teilt die Residuen v, die Gewichtsmatrix P sowie die Redundanzmatrix R gemäß der in
Jacobimatrix_symbolisch_liste_beobachtungsvektor enthaltenen Gruppenindizes auf. Für jede Jacobimatrix_symbolisch_liste_beobachtungsvektor enthaltenen Gruppenindizes auf. Für jede
Beobachtungsgruppe wird die Redundanz ri = Spur(R_i) gebildet und daraus s0_aposteriori Beobachtungsgruppe wird die Redundanz ri = Spur(R_i) gebildet und daraus sigma0_aposteriori
berechnet. berechnet.
Unterstützte Gruppenkennungen: "SD", "R", "ZW", "gnss", "niv", "lA". Unterstützte Gruppenkennungen: "SD", "R", "ZW", "gnss", "niv", "lA".
@@ -57,7 +57,7 @@ class VKS:
:param res: Ergebnis-Dictionary der Ausgleichung, erwartet mindestens res["v"] (Residuen) und res["P"] (Gewichte). :param res: Ergebnis-Dictionary der Ausgleichung, erwartet mindestens res["v"] (Residuen) und res["P"] (Gewichte).
:type res: dict :type res: dict
:param R: Redundanzmatrix (z. B. aus R = Q_vv @ P oder äquivalent), passend zu v/P dimensioniert. :param R: Redundanzmatrix (z. B. aus R = Q_vv @ P oder äquivalent), passend zu v/P dimensioniert.
:type R: np.asarray :type R: np.ndarray
:return: DataFrame mit den Spalten 'Beobachtungsgruppe', 'Standardabweichung', 'Varianz' :return: DataFrame mit den Spalten 'Beobachtungsgruppe', 'Standardabweichung', 'Varianz'
:rtype: pd.DataFrame :rtype: pd.DataFrame
""" """
@@ -80,10 +80,10 @@ class VKS:
aufgeteilt_P_SD = res["P"][z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_P_SD = res["P"][z_start: z_ende + 1, s_start: s_ende + 1]
aufgeteilt_R_SD = R[z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_R_SD = R[z_start: z_ende + 1, s_start: s_ende + 1]
ri_SD = sum(np.diag(aufgeteilt_R_SD)) ri_SD = sum(np.diag(aufgeteilt_R_SD))
s0_aposteriori_SD = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_SD, aufgeteilt_P_SD, ri_SD, False) sigma0_aposteriori_SD = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_SD, aufgeteilt_P_SD, ri_SD, False)
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_SD, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": sigma0_aposteriori_SD,
"Varianz a posteriori": s0_aposteriori_SD ** 2}) "Varianz a posteriori": sigma0_aposteriori_SD ** 2})
# R = Tachymeter Richtungsbeobachtungen # R = Tachymeter Richtungsbeobachtungen
if beobachtungsgruppe == "R": if beobachtungsgruppe == "R":
@@ -92,10 +92,10 @@ class VKS:
aufgeteilt_P_R = res["P"][z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_P_R = res["P"][z_start: z_ende + 1, s_start: s_ende + 1]
aufgeteilt_R_R = R[z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_R_R = R[z_start: z_ende + 1, s_start: s_ende + 1]
ri_R = sum(np.diag(aufgeteilt_R_R)) ri_R = sum(np.diag(aufgeteilt_R_R))
s0_aposteriori_R = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_R, aufgeteilt_P_R, ri_R, False) sigma0_aposteriori_R = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_R, aufgeteilt_P_R, ri_R, False)
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_R, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": sigma0_aposteriori_R,
"Varianz a posteriori": s0_aposteriori_R ** 2}) "Varianz a posteriori": sigma0_aposteriori_R ** 2})
# ZW = Tachymeter Zenitwinkelbeobachtung # ZW = Tachymeter Zenitwinkelbeobachtung
if beobachtungsgruppe == "ZW": if beobachtungsgruppe == "ZW":
@@ -104,10 +104,10 @@ class VKS:
aufgeteilt_P_ZW = res["P"][z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_P_ZW = res["P"][z_start: z_ende + 1, s_start: s_ende + 1]
aufgeteilt_R_ZW = R[z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_R_ZW = R[z_start: z_ende + 1, s_start: s_ende + 1]
ri_ZW = sum(np.diag(aufgeteilt_R_ZW)) ri_ZW = sum(np.diag(aufgeteilt_R_ZW))
s0_aposteriori_ZW = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_ZW, aufgeteilt_P_ZW, ri_ZW, False) sigma0_aposteriori_ZW = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_ZW, aufgeteilt_P_ZW, ri_ZW, False)
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_ZW, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": sigma0_aposteriori_ZW,
"Varianz a posteriori": s0_aposteriori_ZW ** 2}) "Varianz a posteriori": sigma0_aposteriori_ZW ** 2})
# GNSS = GNSS-Basisilinien # GNSS = GNSS-Basisilinien
if beobachtungsgruppe == "gnss": if beobachtungsgruppe == "gnss":
@@ -116,10 +116,10 @@ class VKS:
aufgeteilt_P_gnss = res["P"][z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_P_gnss = res["P"][z_start: z_ende + 1, s_start: s_ende + 1]
aufgeteilt_R_gnss = R[z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_R_gnss = R[z_start: z_ende + 1, s_start: s_ende + 1]
ri_gnss = sum(np.diag(aufgeteilt_R_gnss)) ri_gnss = sum(np.diag(aufgeteilt_R_gnss))
s0_aposteriori_gnss = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_gnss, aufgeteilt_P_gnss, ri_gnss, False) sigma0_aposteriori_gnss = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_gnss, aufgeteilt_P_gnss, ri_gnss, False)
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_gnss, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": sigma0_aposteriori_gnss,
"Varianz a posteriori": s0_aposteriori_gnss ** 2}) "Varianz a posteriori": sigma0_aposteriori_gnss ** 2})
# niv = geometrisches Nivellement # niv = geometrisches Nivellement
if beobachtungsgruppe == "niv": if beobachtungsgruppe == "niv":
@@ -128,10 +128,10 @@ class VKS:
aufgeteilt_P_niv = res["P"][z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_P_niv = res["P"][z_start: z_ende + 1, s_start: s_ende + 1]
aufgeteilt_R_niv = R[z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_R_niv = R[z_start: z_ende + 1, s_start: s_ende + 1]
ri_niv = sum(np.diag(aufgeteilt_R_niv)) ri_niv = sum(np.diag(aufgeteilt_R_niv))
s0_aposteriori_niv = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_niv, aufgeteilt_P_niv, ri_niv, False) sigma0_aposteriori_niv = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_niv, aufgeteilt_P_niv, ri_niv, False)
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_niv, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": sigma0_aposteriori_niv,
"Varianz a posteriori": s0_aposteriori_niv ** 2}) "Varianz a posteriori": sigma0_aposteriori_niv ** 2})
# lA = Anschlusspunkte für die weiche Lagerung # lA = Anschlusspunkte für die weiche Lagerung
if beobachtungsgruppe == "lA": if beobachtungsgruppe == "lA":
@@ -140,11 +140,11 @@ class VKS:
aufgeteilt_P_lA = res["P"][z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_P_lA = res["P"][z_start: z_ende + 1, s_start: s_ende + 1]
aufgeteilt_R_lA = R[z_start: z_ende + 1, s_start: s_ende + 1] aufgeteilt_R_lA = R[z_start: z_ende + 1, s_start: s_ende + 1]
ri_lA = sum(np.diag(aufgeteilt_R_lA)) ri_lA = sum(np.diag(aufgeteilt_R_lA))
s0_aposteriori_lA = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_lA, aufgeteilt_P_lA, ri_lA, False) sigma0_aposteriori_lA = Genauigkeitsmaße.berechne_sigma0apost(aufgeteilt_v_lA, aufgeteilt_P_lA, ri_lA, False)
# Speichern in Instanzvariable # Speichern in Instanzvariable
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_lA, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": sigma0_aposteriori_lA,
"Varianz a posteriori": s0_aposteriori_lA ** 2}) "Varianz a posteriori": sigma0_aposteriori_lA ** 2})
self.liste_ergebnisse = liste_ergebnisse self.liste_ergebnisse = liste_ergebnisse
df_varianzkomponenten = pd.DataFrame(self.liste_ergebnisse) df_varianzkomponenten = pd.DataFrame(self.liste_ergebnisse)