geoidundolation und export

This commit is contained in:
2026-02-06 21:01:48 +01:00
parent 4340205f45
commit 75d41bd21b
5 changed files with 343 additions and 365 deletions

File diff suppressed because it is too large Load Diff

116
Export.py
View File

@@ -1,5 +1,6 @@
import csv
from datetime import datetime
from Koordinatentransformationen import Transformationen
import numpy as np
import os
import pandas as pd
@@ -61,6 +62,83 @@ class Export:
zeile_als_text.append(eintrag_text)
writer.writerow(zeile_als_text)
@staticmethod
def erzeuge_ergebnis_datenframes(
pfad_datenbank,
pfad_tif_quasigeoidundulation,
dict_koordinaten_ausgleichungsergebnis
):
"""
Erzeugt Ergebnis-DataFrames für ausgeglichene Koordinaten in ECEF (XYZ) und UTM.
Die Funktion nimmt ein Dictionary mit ausgeglichenen geozentrisch-kartesischen Koordinaten
(ECEF/XYZ) entgegen, transformiert diese über die Transformationen-Klasse nach ETRS89/UTM
(inkl. Höhenangabe; optional unter Nutzung einer Quasigeoidundulations-Datei) und erstellt
zwei tabellarische Ergebnisdarstellungen:
- df_x_final: Geozentrische Koordinaten X/Y/Z [m],
- df_utm_final: UTM-Koordinaten (Rechtswert/Hochwert/Höhe) [m].
:param pfad_datenbank: Pfad zur SQLite-Datenbank (für Koordinaten-/Transformationszugriffe).
:type pfad_datenbank: str
:param pfad_tif_quasigeoidundulation: Pfad zu Quasigeoidundulationsdaten als GeoTIFF (optional, für Höhen/PROJ).
:type pfad_tif_quasigeoidundulution: str | None
:param dict_koordinaten_ausgleichungsergebnis: Dictionary der ausgeglichenen ECEF-Koordinaten je Punkt.
:type dict_koordinaten_ausgleichungsergebnis: dict
:return: Tuple aus DataFrame der ECEF-Koordinaten (XYZ) und DataFrame der UTM-Koordinaten.
:rtype: tuple[pandas.DataFrame, pandas.DataFrame]
"""
# Transformation initialisieren
trafos = Transformationen(pfad_datenbank)
dict_koordinaten_utm = trafos.ecef_to_utm(
dict_koordinaten_ausgleichungsergebnis,
pfad_tif_quasigeoidundulation
)
namen = list(dict_koordinaten_ausgleichungsergebnis.keys())
# SymPy-Matrizen zu Liste
koordinaten_liste = []
for k in namen:
matrix_werte = dict_koordinaten_ausgleichungsergebnis[k]
koordinaten_liste.append([
float(matrix_werte[0]),
float(matrix_werte[1]),
float(matrix_werte[2])
])
# DataFrame geozentrisch
df_x_final = pd.DataFrame(
koordinaten_liste,
columns=['X [m]', 'Y [m]', 'Z [m]'],
index=namen
)
df_x_final.index.name = 'Punktnummer'
# DataFrame UTM
utm_flach = {
k: np.array(v).flatten().tolist()
for k, v in dict_koordinaten_utm.items()
}
df_utm_final = pd.DataFrame.from_dict(
utm_flach,
orient='index',
columns=['Rechtswert [m]', 'Hochwert [m]', 'Höhe [m]']
)
df_utm_final.index.name = 'Punktnummer'
# Zahlenformatierung
df_x_final = df_x_final.map(lambda val: f"{val:.4f}")
df_utm_final = df_utm_final.map(lambda val: f"{val:.4f}")
return df_x_final, df_utm_final
def speichere_html_protokoll(metadaten: dict, ergebnisse: dict) -> None:
"""Erzeugt ein HTML-Protokoll der Ausgleichungsergebnisse und speichert es als Datei.
@@ -79,7 +157,6 @@ class Export:
:return: None
:rtype: None
"""
for key in ergebnisse:
wert = ergebnisse[key]
@@ -92,7 +169,7 @@ class Export:
elif isinstance(wert, dict):
ergebnisse[key] = pd.DataFrame([wert])
# Pfad für den Ordner erstellen
# Pfad für den Ordner
ordner = "Protokolle"
if not os.path.exists(ordner):
os.makedirs(ordner)
@@ -100,7 +177,7 @@ class Export:
dateiname = f"{ordner}/Protokoll_{metadaten['projekt']}.html"
abs_path = os.path.abspath(dateiname)
# HTML Inhalt zusammenbauen
# HTML Inhalt
html_content = f"""
<!DOCTYPE html>
<html lang="de">
@@ -211,39 +288,6 @@ class Export:
<h3 id="koordinaten_utm">13. Koordinaten UTM</h3>
{ergebnisse['df_koordinaten_utm'].to_html(index=True)}
<h3>1. Globaltest</h3>
{ergebnisse['df_globaltest'].to_html(index=False)}
<h3>2. Redundanzanteile</h3>
{ergebnisse['df_redundanz'].to_html(index=False)}
<h3>2. Lokaltest (data snooping)</h3>
{ergebnisse['df_lokaltest'].to_html(index=False)}
<h3>2. Varianzkomponentenschätzung</h3>
{ergebnisse['df_vks'].to_html(index=False)}
<h3>2. Äussere Zuverlässigkeit</h3>
{ergebnisse['df_aeussere_zuver'].to_html(index=False)}
<h3>2. Standardabweichungen und Helmert'scher Punktfehler</h3>
{ergebnisse['df_punktfehler'].to_html(index=False)}
<h3>3. Standardellipsen</h3>
{ergebnisse['df_ellipsen'].to_html(index=False)}
<h3>3. Konfidenzellipsen</h3>
{ergebnisse['df_konfidenzellipsen'].to_html(index=False)}
<h3>3. Konfidenzellipsen im ENU-System</h3>
{ergebnisse['df_konfidenzellipsen_enu'].to_html(index=False)}
<h3>3. Koordinaten Geozentrisch Kartesisch</h3>
{ergebnisse['df_koordinaten_geozentrisch_kartesisch'].to_html(index=True)}
<h3>3. Koordinaten UTM</h3>
{ergebnisse['df_koordinaten_utm'].to_html(index=True)}
<div class="footer">
Erstellt automatisch am {datetime.now().strftime('%d.%m.%Y um %H:%M:%S')}
</div>

View File

@@ -28,7 +28,7 @@ class FunktionalesModell:
2) In jeder Iteration Substituieren der Symbolischen Matrizen in Numerische np.asarrays
"""
def __init__(self, pfad_datenbank: str, a: float, b: float, pfad_tif_quasigeoidundolation: str = None) -> None:
def __init__(self, pfad_datenbank: str, a: float, b: float, pfad_tif_quasigeoidundulation: str = None) -> None:
"""Initialisiert das funktionale Modell.
Legt die Ellipsoidparameter a und b fest, initialisiert Hilfsklassen (Berechnungen, Datenbankzugriff, Transformationen)
@@ -40,8 +40,8 @@ class FunktionalesModell:
:type a: float
:param b: Kleine Halbachse b des Referenzellipsoids in Meter.
:type b: float
:param pfad_tif_quasigeoidundolation: Pfad zu Quasigeoidundulationsdaten als GeoTIFF vom BKG für Transformationen (optional).
:type pfad_tif_quasigeoidundolation: str | None
:param pfad_tif_quasigeoidundulation: Pfad zu Quasigeoidundulationsdaten als GeoTIFF vom BKG für Transformationen (optional).
:type pfad_tif_quasigeoidundulation: str | None
:return: None
:rtype: None
"""
@@ -51,7 +51,7 @@ class FunktionalesModell:
self.berechnungen = Berechnungen(self.a, self.b)
self.db_zugriff = Datenbankzugriff(self.pfad_datenbank)
self.trafos = Transformationen(pfad_datenbank)
self.pfad_tif_quasigeoidundolation = pfad_tif_quasigeoidundolation
self.pfad_tif_quasigeoidundulation = pfad_tif_quasigeoidundulation
self.substitutionen_dict = self.dict_substitutionen_uebergeordnetes_system()
self.dict_punkt_symbole = {}
self.liste_symbole_lambdify = sorted(self.substitutionen_dict.keys(), key=lambda s: str(s))
@@ -889,7 +889,7 @@ class FunktionalesModell:
dict_koordinaten_utm = self.trafos.ecef_to_utm(
dict_koordinaten_niv,
self.pfad_tif_quasigeoidundolation)
self.pfad_tif_quasigeoidundulation)
# Zuweisen der Symbole zu dem jeweiligen numerischen Wert. Gespeichert wird dies in einem Dictionary.
substitutionen = {}

View File

@@ -350,7 +350,7 @@ class Transformationen:
])
return dict_transformiert
def utm_to_XYZ(self, pfad_tif_quasigeoidundolation: str, liste_utm: list) -> dict[Any, Any]:
def utm_to_XYZ(self, pfad_tif_quasigeoidundulation: str, liste_utm: list) -> dict[Any, Any]:
"""Rechnet UTM-Koordinaten (ETRS89 / UTM + DHHN2016) in ECEF-Koordinaten (ETRS89 geozentrisch-kartesisch) um.
Es wird ein PROJ-Transformer von:
@@ -361,15 +361,15 @@ class Transformationen:
initialisiert. Zusätzlich wird ein BKG-GeoTIFF (Quasigeoidunndulation) in den PROJ-Datenpfad eingebunden,
indem eine Kopie mit dem erwarteten Dateinamen "de_bkg_gcg2016.tif" im selben Ordner erzeugt wird.
:param pfad_tif_quasigeoidundolation: Pfad zur BKG-GeoTIFF-Datei (Quasigeoidundulation).
:type pfad_tif_quasigeoidundolation: str
:param pfad_tif_quasigeoidundulation: Pfad zur BKG-GeoTIFF-Datei (Quasigeoidundulation).
:type pfad_tif_quasigeoidundulation: str
:param liste_utm: Liste von UTM-Koordinaten in der Form [(punktnummer, E, N, Normalhoehe), ...].
:type liste_utm: list
:return: Dictionary {punktnummer: sp.Matrix([X, Y, Z])} mit ECEF-Koordinaten (Meter).
:rtype: dict[Any, Any]
"""
# tif vom BKG zur Quasigeoidundolation übergeben
pfad_gcg_tif = Path(pfad_tif_quasigeoidundolation)
# tif vom BKG zur Quasigeoidundulation übergeben
pfad_gcg_tif = Path(pfad_tif_quasigeoidundulation)
pfad_gcg_tif_proj = pfad_gcg_tif.with_name("de_bkg_gcg2016.tif")
# Kopie des TIF anlegen (Dies ist voraussetzung für die Transformer-Bibliothek
@@ -423,7 +423,7 @@ class Transformationen:
:rtype: dict
"""
# Kopie des TIF vom BKG mit der Quasigeoidundolation erstellen
# Kopie des TIF vom BKG mit der Quasigeoidundulation erstellen
pfad_gcg_tif = Path(pfad_gcg_tif).resolve()
pfad_proj_grid = pfad_gcg_tif.with_name("de_bkg_gcg2016.tif")
if (

View File

@@ -26,7 +26,7 @@ class Iterationen:
Die Iteration verwendet bei weicher Lagerung eine erweiterte Kovarianzmatrix (Q_ext) inklusive Anschlusspunkten (lA_*),
aus der die Gewichtsmatrix P abgeleitet wird.
"""
def __init__(self, pfad_datenbank: str, pfad_tif_quasigeoidundolation: str, a: float, b: float) -> None:
def __init__(self, pfad_datenbank: str, pfad_tif_quasigeoidundulation: str, a: float, b: float) -> None:
"""Initialisiert die Iterationssteuerung.
Speichert Datenbankpfade und Ellipsoidparameter, initialisiert das funktionale Modell sowie das stochastische Modell
@@ -34,8 +34,8 @@ class Iterationen:
:param pfad_datenbank: Pfad zur SQLite-Datenbank.
:type pfad_datenbank: str
:param pfad_tif_quasigeoidundolation: Pfad zum GeoTIFF der Quasigeoidundulation (BKG), benötigt für UTM/Normalhöhen in Transformationen.
:type pfad_tif_quasigeoidundolation: str
:param pfad_tif_quasigeoidundulation: Pfad zum GeoTIFF der Quasigeoidundulation (BKG), benötigt für UTM/Normalhöhen in Transformationen.
:type pfad_tif_quasigeoidundulation: str
:param a: Große Halbachse a des Referenzellipsoids in Meter.
:type a: float
:param b: Kleine Halbachse b des Referenzellipsoids in Meter.
@@ -44,13 +44,13 @@ class Iterationen:
:rtype: None
"""
self.pfad_datenbank = pfad_datenbank
self.pfad_tif_quasigeoidundolation = pfad_tif_quasigeoidundolation
self.pfad_tif_quasigeoidundulation = pfad_tif_quasigeoidundulation
self.a = a
self.b = b
self.stoch_modell = Stochastisches_Modell.StochastischesModell(pfad_datenbank)
self.db_zugriff = Datenbank.Datenbankzugriff(pfad_datenbank)
self.fm = Funktionales_Modell.FunktionalesModell(self.pfad_datenbank, self.a, self.b, self.pfad_tif_quasigeoidundolation)
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):