Push 06.02.2026

This commit is contained in:
2026-02-06 22:56:50 +01:00
parent 75d41bd21b
commit 4e89330cab
3 changed files with 176 additions and 39339 deletions

File diff suppressed because one or more lines are too long

View File

@@ -26,7 +26,7 @@ class Export:
zusätzliche Beschriftung sowie Spaltenbeschriftungen. zusätzliche Beschriftung sowie Spaltenbeschriftungen.
Zudem werden Zeilenbeschriftungen durchgeführt. Zudem werden Zeilenbeschriftungen durchgeführt.
:param dateiname: Pfad zu schreibenden CSV-Datei. :param dateiname: Pfad der zu erstellenden CSV-Datei.
:type dateiname: str :type dateiname: str
:param liste_spaltenbeschriftung: Liste der Spaltenbeschriftungen. :param liste_spaltenbeschriftung: Liste der Spaltenbeschriftungen.
:type liste_spaltenbeschriftung: list :type liste_spaltenbeschriftung: list
@@ -66,25 +66,24 @@ class Export:
@staticmethod @staticmethod
def erzeuge_ergebnis_datenframes( def erzeuge_ergebnis_datenframes(
pfad_datenbank, pfad_datenbank: str,
pfad_tif_quasigeoidundulation, pfad_tif_quasigeoidundulation: str,
dict_koordinaten_ausgleichungsergebnis 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.
Die Funktion nimmt ein Dictionary mit ausgeglichenen geozentrisch-kartesischen Koordinaten Die Funktion nimmt ein Dictionary mit ausgeglichenen geozentrisch-kartesischen Koordinaten
(ECEF/XYZ) entgegen, transformiert diese über die Transformationen-Klasse nach ETRS89/UTM entgegen, transformiert diese über die Transformationen-Klasse in UTM mit Normalhöhen
(inkl. Höhenangabe; optional unter Nutzung einer Quasigeoidundulations-Datei) und erstellt unter Nutzung des GCG2016
zwei tabellarische Ergebnisdarstellungen:
- df_x_final: Geozentrische Koordinaten X/Y/Z [m], - df_x_final: Geozentrische Koordinaten X/Y/Z [m],
- df_utm_final: UTM-Koordinaten (Rechtswert/Hochwert/Höhe) [m]. - df_utm_final: UTM-Koordinaten (Rechtswert/Hochwert/Höhe) [m].
:param pfad_datenbank: Pfad zur SQLite-Datenbank (für Koordinaten-/Transformationszugriffe). :param pfad_datenbank: Pfad zur SQLite-Datenbank (für Koordinaten-/Transformationszugriffe).
:type pfad_datenbank: str :type pfad_datenbank: str
:param pfad_tif_quasigeoidundulation: Pfad zu Quasigeoidundulationsdaten als GeoTIFF (optional, für Höhen/PROJ). :param pfad_tif_quasigeoidundulation: Pfad zum GCG 2016 als GeoTIFF.
:type pfad_tif_quasigeoidundulution: str | None :type pfad_tif_quasigeoidundulution: str
:param dict_koordinaten_ausgleichungsergebnis: Dictionary der ausgeglichenen ECEF-Koordinaten je Punkt. :param dict_koordinaten_ausgleichungsergebnis: Dictionary der ausgeglichenen ECEF-Koordinaten je Punkt.
:type dict_koordinaten_ausgleichungsergebnis: dict :type dict_koordinaten_ausgleichungsergebnis: dict
:return: Tuple aus DataFrame der ECEF-Koordinaten (XYZ) und DataFrame der UTM-Koordinaten. :return: Tuple aus DataFrame der ECEF-Koordinaten (XYZ) und DataFrame der UTM-Koordinaten.
@@ -145,8 +144,8 @@ class Export:
Es wird der Unterordner Protokolle angelegt, falls dieser noch nicht existiert. Es wird der Unterordner Protokolle angelegt, falls dieser noch nicht existiert.
Das Protokoll wird als HTML-Datei gespeichert und anschließend im Browser geöffnet. Das Protokoll wird als HTML-Datei gespeichert und anschließend im Browser geöffnet.
Erwartete Schlüssel in metadaten sind u. a. "projekt", "bearbeiter" und "datum". Erwartete Eingaben in metadaten sind u. a. "projekt", "bearbeiter" und "datum".
Erwartete Schlüssel in ergebnisse sind u. a. "df_globaltest", "df_redundanz", Erwartete Eingaben in ergebnisse sind u. a. "df_globaltest", "df_redundanz",
"df_ellipsen", "df_konfidenzellipsen", "df_koordinaten_geozentrisch_kartesisch" "df_ellipsen", "df_konfidenzellipsen", "df_koordinaten_geozentrisch_kartesisch"
und "df_koordinaten_utm". Die zugehörigen Werte müssen die Methode to_html bereitstellen. und "df_koordinaten_utm". Die zugehörigen Werte müssen die Methode to_html bereitstellen.

View File

@@ -38,10 +38,11 @@ class VKS:
self.btn_save = None self.btn_save = None
self.log_output = None self.log_output = None
self.columns = ['ID', 'InstrumentenID', 'Beobachtungsgruppe', 'Varianzfaktor_aktuelle_iteration'] self.columns = ['ID', 'InstrumentenID', 'Beobachtungsgruppe', 'Varianzfaktor_aktuelle_iteration']
self.liste_ergebnisse = []
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.ndarray) -> pd.DataFrame: def varianzkomponten_berechnen(self, Jacobimatrix_symbolisch_liste_beobachtungsvektor: list, res: dict, R: np.asarray) -> 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
@@ -56,11 +57,11 @@ 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.ndarray :type R: np.asarray
:return: DataFrame mit den Spalten 'Beobachtungsgruppe', 'Standardabweichung', 'Varianz' :return: DataFrame mit den Spalten 'Beobachtungsgruppe', 'Standardabweichung', 'Varianz'
:rtype: pd.DataFrame :rtype: pd.DataFrame
""" """
self.liste_ergebnisse = []
liste_ergebnisse = [] liste_ergebnisse = []
# Zeilen- und Spaltennummern der jeweiligen Beobachtungsgruppe, z.B. SD für Schrägdistanz ermitteln # Zeilen- und Spaltennummern der jeweiligen Beobachtungsgruppe, z.B. SD für Schrägdistanz ermitteln
@@ -74,71 +75,79 @@ class VKS:
# SD = Tachymeter Schrägstrecke # SD = Tachymeter Schrägstrecke
if beobachtungsgruppe == "SD": if beobachtungsgruppe == "SD":
beobachtungsgruppe_lang = "Tachymeter_Streckenbeobachtungen"
aufgeteilt_v_SD = res["v"][z_start: z_ende + 1, :] aufgeteilt_v_SD = res["v"][z_start: z_ende + 1, :]
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_s0apost(aufgeteilt_v_SD, aufgeteilt_P_SD, ri_SD, False) s0_aposteriori_SD = Genauigkeitsmaße.berechne_s0apost(aufgeteilt_v_SD, aufgeteilt_P_SD, ri_SD, False)
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe, "Standardabweichung a posteriori": s0_aposteriori_SD, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_SD,
"Varianz a posteriori": s0_aposteriori_SD ** 2}) "Varianz a posteriori": s0_aposteriori_SD ** 2})
# R = Tachymeter Richtungsbeobachtungen # R = Tachymeter Richtungsbeobachtungen
if beobachtungsgruppe == "R": if beobachtungsgruppe == "R":
beobachtungsgruppe_lang = "Tachymeter_Richtungsbeobachtungen"
aufgeteilt_v_R = res["v"][z_start: z_ende + 1, :] aufgeteilt_v_R = res["v"][z_start: z_ende + 1, :]
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_s0apost(aufgeteilt_v_R, aufgeteilt_P_R, ri_R, False) s0_aposteriori_R = Genauigkeitsmaße.berechne_s0apost(aufgeteilt_v_R, aufgeteilt_P_R, ri_R, False)
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe, "Standardabweichung a posteriori": s0_aposteriori_R, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_R,
"Varianz a posteriori": s0_aposteriori_R ** 2}) "Varianz a posteriori": s0_aposteriori_R ** 2})
# ZW = Tachymeter Zenitwinkelbeobachtung # ZW = Tachymeter Zenitwinkelbeobachtung
if beobachtungsgruppe == "ZW": if beobachtungsgruppe == "ZW":
beobachtungsgruppe_lang = "Tachymeter_Zenitwinkelbeobachtungen"
aufgeteilt_v_ZW = res["v"][z_start: z_ende + 1, :] aufgeteilt_v_ZW = res["v"][z_start: z_ende + 1, :]
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_s0apost(aufgeteilt_v_ZW, aufgeteilt_P_ZW, ri_ZW, False) s0_aposteriori_ZW = Genauigkeitsmaße.berechne_s0apost(aufgeteilt_v_ZW, aufgeteilt_P_ZW, ri_ZW, False)
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe, "Standardabweichung a posteriori": s0_aposteriori_ZW, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_ZW,
"Varianz a posteriori": s0_aposteriori_ZW ** 2}) "Varianz a posteriori": s0_aposteriori_ZW ** 2})
# GNSS = GNSS-Basisilinien # GNSS = GNSS-Basisilinien
if beobachtungsgruppe == "gnss": if beobachtungsgruppe == "gnss":
beobachtungsgruppe_lang = "GNSS-Rover_Basislinienbeobachtungen"
aufgeteilt_v_gnss = res["v"][z_start: z_ende + 1, :] aufgeteilt_v_gnss = res["v"][z_start: z_ende + 1, :]
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_s0apost(aufgeteilt_v_gnss, aufgeteilt_P_gnss, ri_gnss, False) s0_aposteriori_gnss = Genauigkeitsmaße.berechne_s0apost(aufgeteilt_v_gnss, aufgeteilt_P_gnss, ri_gnss, False)
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe, "Standardabweichung a posteriori": s0_aposteriori_gnss, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_gnss,
"Varianz a posteriori": s0_aposteriori_gnss ** 2}) "Varianz a posteriori": s0_aposteriori_gnss ** 2})
# niv = geometrisches Nivellement # niv = geometrisches Nivellement
if beobachtungsgruppe == "niv": if beobachtungsgruppe == "niv":
beobachtungsgruppe_lang = "Nivellier_Hoehendifferenzbeobachtungen"
aufgeteilt_v_niv = res["v"][z_start: z_ende + 1, :] aufgeteilt_v_niv = res["v"][z_start: z_ende + 1, :]
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_s0apost(aufgeteilt_v_niv, aufgeteilt_P_niv, ri_niv, False) s0_aposteriori_niv = Genauigkeitsmaße.berechne_s0apost(aufgeteilt_v_niv, aufgeteilt_P_niv, ri_niv, False)
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe, "Standardabweichung a posteriori": s0_aposteriori_niv, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_niv,
"Varianz a posteriori": s0_aposteriori_niv ** 2}) "Varianz a posteriori": s0_aposteriori_niv ** 2})
# lA = Anschlusspunkte für die weiche Lagerung # lA = Anschlusspunkte für die weiche Lagerung
if beobachtungsgruppe == "lA": if beobachtungsgruppe == "lA":
beobachtungsgruppe_lang = "Anschlusspunkte"
aufgeteilt_v_lA = res["v"][z_start: z_ende + 1, :] aufgeteilt_v_lA = res["v"][z_start: z_ende + 1, :]
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_s0apost(aufgeteilt_v_lA, aufgeteilt_P_lA, ri_lA, False) s0_aposteriori_lA = Genauigkeitsmaße.berechne_s0apost(aufgeteilt_v_lA, aufgeteilt_P_lA, ri_lA, False)
# Speichern in Instanzvariable
liste_ergebnisse.append( liste_ergebnisse.append(
{"Beobachtungsgruppe": beobachtungsgruppe, "Standardabweichung a posteriori": s0_aposteriori_lA, {"Beobachtungsgruppe": beobachtungsgruppe_lang, "Standardabweichung a posteriori": s0_aposteriori_lA,
"Varianz a posteriori": s0_aposteriori_lA ** 2}) "Varianz a posteriori": s0_aposteriori_lA ** 2})
df_varianzkomponenten = pd.DataFrame(liste_ergebnisse) self.liste_ergebnisse = liste_ergebnisse
df_varianzkomponenten = pd.DataFrame(self.liste_ergebnisse)
return df_varianzkomponenten return df_varianzkomponenten
def vks_ausfuehren(self) -> None: def vks_ausfuehren(self) -> None:
@@ -154,7 +163,15 @@ class VKS:
# In der aktuellen Iteration verwendete Varianzkomponenten aus der Datenbank abfragen und zur Tabelle hinzufügen # In der aktuellen Iteration verwendete Varianzkomponenten aus der Datenbank abfragen und zur Tabelle hinzufügen
rohdaten = self.db_zugriff.get_varianzkomponentenschaetzung() rohdaten = self.db_zugriff.get_varianzkomponentenschaetzung()
self.df = pd.DataFrame(rohdaten, columns=self.columns) df_temporaer = pd.DataFrame(rohdaten, columns=self.columns)
if self.liste_ergebnisse:
sortierreihenfolge = [item['Beobachtungsgruppe'] for item in self.liste_ergebnisse]
self.df = (df_temporaer.set_index('Beobachtungsgruppe')
.reindex(sortierreihenfolge)
.reset_index())
self.df = self.df[self.columns].dropna(subset=['ID'])
else:
self.df = df_temporaer
# Festlegen der Tupel für die Eintragung des Multiplikationsfaktors auf die Varianzkomponente der aktuellen Iteration # Festlegen der Tupel für die Eintragung des Multiplikationsfaktors auf die Varianzkomponente der aktuellen Iteration
self.neue_werte_widgets = [ self.neue_werte_widgets = [
@@ -216,19 +233,21 @@ class VKS:
:return: None :return: None
:rtype: None :rtype: None
""" """
# ID nicht mehr anzeigen
columns_anzeige = [c for c in self.columns if c != "ID"]
# Header erstellen # Header erstellen
header = widgets.HBox([ header = widgets.HBox([
widgets.Label(col, layout=widgets.Layout(width='250px', font_weight='bold', align='center')) widgets.Label(col, layout=widgets.Layout(width='250px', font_weight='bold', align='center'))
for col in self.columns for col in columns_anzeige
] + [widgets.Label('Varianzmultiplikator', ] + [widgets.Label('Varianzmultiplikator',
layout=widgets.Layout(width='150px', font_weight='bold', align='center'))]) layout=widgets.Layout(width='150px', font_weight='bold', align='center'))])
zeilen = [] zeilen = []
# Iterieren über df und widgets gleichzeitig # Iterieren über df und widgets gleichzeitig
for i, row in enumerate(self.df.itertuples(index=False)): for i, row in enumerate(self.df[columns_anzeige].itertuples(index=False)):
zellen = [widgets.Label(str(val), layout=widgets.Layout(width='250px', align='center')) for val in row] zellen = [widgets.Label(str(val), layout=widgets.Layout(width='250px', align='center')) for val in row]
zellen.append(self.neue_werte_widgets[i]) zellen.append(self.neue_werte_widgets[i])
zeilen.append(widgets.HBox(zellen)) zeilen.append(widgets.HBox(zellen))
# Darstellen der Tabelle display(widgets.VBox([header] + zeilen + [widgets.HTML("<br>"), self.btn_save, self.log_output]))
display(widgets.VBox([header] + zeilen + [widgets.HTML("<br>"), self.btn_save, self.log_output]))