from decimal import Decimal import os import pandas as pd import sqlite3 import sympy as sp from sympy import MutableDenseMatrix from typing import Any from Einheitenumrechnung import Einheitenumrechnung class Datenbank_anlegen: """Legt die SQLite-Datenbank für die Ausgleichungsrechnung an. Die Klasse erstellt die Datenbankdatei nur dann, wenn am angegebenen Pfad noch keine Datenbank existiert. In diesem Fall werden die Tabellen und Constraints per SQL-Skript angelegt. Angelegte Tabellen: - Netzpunkte, - Beobachtungen, - Instrumente, - Genauigkeiten, - Varianzkomponentenschaetzung. :ivar pfad_datenbank: Pfad zur SQLite-Datenbankdatei. :vartype pfad_datenbank: str """ def __init__(self, pfad_datenbank: str) -> None: """Initialisiert den Datenbankpfad und legt die Datenbank bei Bedarf an. Beim Erstellen der Instanz wird db_anlegen() aufgerufen. Existiert die Datenbankdatei unter dem übergebenen Pfad bereits, erfolgt keine Änderung. :param pfad_datenbank: Pfad zur SQLite-Datenbankdatei. :type pfad_datenbank: str :return: None :rtype: None """ self.pfad_datenbank = pfad_datenbank self.db_anlegen() def db_anlegen(self) -> None: """Legt die SQLite-Datenbank an, sofern die Datei nicht existiert. Prüft, ob die Datenbankdatei am Pfad vorhanden ist. Falls nicht, wird eine neue SQLite-Datenbank erstellt. Anschließend werden die Änderungen committet und die Verbindung geschlossen. :return: None :rtype: None """ if not os.path.exists(self.pfad_datenbank): con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() cursor.executescript("""CREATE TABLE Netzpunkte ( punktnummer TEXT(10), naeherungx_lh NUMERIC(9,3), naeherungy_lh NUMERIC(7,3), naeherungz_lh NUMERIC(8,3), naeherungz_lh_niv NUMERIC(8,3), naeherungx_us NUMERIC(9,3), naeherungy_us NUMERIC(7,3), naeherungz_us NUMERIC(8,3), normalhoehe_hfp NUMERIC(5,3), datumskoordinate_x INTEGER DEFAULT 0, datumskoordinate_y INTEGER DEFAULT 0, datumskoordinate_z INTEGER DEFAULT 0, stabw_vorinfo_x NUMERIC(3, 8), stabw_vorinfo_y NUMERIC(3, 8), stabw_vorinfo_z NUMERIC(3, 8), CONSTRAINT pk_Netzpunkte PRIMARY KEY (punktnummer) ); """); cursor.executescript("""CREATE TABLE Beobachtungen( beobachtungenID INTEGER, beobachtungsgruppeID INTEGER, punktnummer_sp TEXT(10), punktnummer_zp TEXT(10), instrumenteID INTEGER, tachymeter_richtung NUMERIC(8, 6), tachymeter_richtung_ausschalten INTEGER DEFAULT 0, tachymeter_zenitwinkel_roh NUMERIC(8, 6), tachymeter_zenitwinkel NUMERIC(8, 6), tachymeter_zenitwinkel_ausschalten INTEGER DEFAULT 0, tachymeter_distanz_roh NUMERIC(8, 4), tachymeter_distanz NUMERIC(8, 4), tachymeter_distanz_auschalten INTEGER DEFAULT 0, tachymeter_instrumentenhoehe NUMERIC(3, 8), tachymeter_prismenhoehe NUMERIC(3, 8), gnss_bx NUMERIC(7, 4), gnss_bx_ausschalten INTEGER DEFAULT 0, gnss_by NUMERIC(7, 4), gnss_by_ausschalten INTEGER DEFAULT 0, gnss_bz NUMERIC(7, 4), gnss_bz_ausschalten INTEGER DEFAULT 0, gnss_s0 NUMERIC(1, 8), gnss_cxx NUMERIC(1, 8), gnss_cxy NUMERIC(1, 8), gnss_cxz NUMERIC(1, 8), gnss_cyy NUMERIC(1, 8), gnss_cyz NUMERIC(1, 8), gnss_czz NUMERIC(1, 8), niv_dh NUMERIC(8, 6), niv_strecke NUMERIC(8, 6), niv_anz_standpkte INTEGER, niv_ausschalten INTEGER DEFAULT 0, dateiname TEXT(200), CONSTRAINT pk_Beobachtungen PRIMARY KEY (beobachtungenID), CONSTRAINT fk_Beobachtungen_Netzpunktesp FOREIGN KEY (punktnummer_sp) REFERENCES Netzpunkte(punktnummer), CONSTRAINT fk_Beobachtungen_Netzpunktezp FOREIGN KEY (punktnummer_zp) REFERENCES Netzpunkte(punktnummer), CONSTRAINT fk_Beobachtungen_Instrumente FOREIGN KEY (instrumenteID) REFERENCES Instrumente(instrumenteID) ); """); cursor.executescript("""CREATE TABLE Instrumente( instrumenteID INTEGER, typ TEXT(200), name TEXT(200), CONSTRAINT pk_Instrumente PRIMARY KEY (instrumenteID) ); """); cursor.executescript("""CREATE TABLE Genauigkeiten( genauigkeitenID INTEGER, instrumenteID INTEGER, beobachtungsart TEXT(25), stabw_apriori_konstant NUMERIC(3, 8), stabw_apriori_streckenprop NUMERIC(3, 8), CONSTRAINT pk_Genauigkeiten PRIMARY KEY (genauigkeitenID), CONSTRAINT fk_Genauigkeiten_Instrumente FOREIGN KEY (instrumenteID) REFERENCES Instrumente(instrumenteID) ); """); cursor.executescript("""CREATE TABLE Varianzkomponentenschaetzung( varianzkomponenteID INTEGER, instrumenteID INTEGER, beobachtungsgruppe TEXT(50), varianz_varianzkomponentenschaetzung NUMERIC(3, 16) DEFAULT 1, CONSTRAINT pk_Varianzkomponentenschaetzung PRIMARY KEY (varianzkomponenteID), CONSTRAINT fk_Varianzkomponentenschaetzung_Instrumente FOREIGN KEY (instrumenteID) REFERENCES Instrumente(instrumenteID) ); """) con.commit() cursor.close() con.close() class Datenbankzugriff: """Zugriff auf die SQLite-Datenbank des Ausgleichungsprogramms. Die Klasse stellt Methoden zur Verfügung für: - Schreiben in die Datenbank durch alle set_* Methoden - Lesen aus der Datenbank durch alle get_* Methoden - Darstellen der aus der Datenbenak gelesenen Daten in tabellarischer Form durch alle tabelle_* Methoden :ivar pfad_datenbank: Pfad zur SQLite-Datenbankdatei. :vartype pfad_datenbank: str """ def __init__(self, pfad_datenbank: str) -> None: """Initialisiert den Datenbankzugriff. :param pfad_datenbank: Pfad zur SQLite-Datenbankdatei. :type pfad_datenbank: str """ self.pfad_datenbank = pfad_datenbank def set_koordinaten(self, dict_koordinaten: dict, koordinatenart: str) -> None: """Schreibt Koordinaten in die Tabelle Netzpunkte. Die Koordinaten werden aus `dict_koordinaten` gelesen und abhängig von der koordinatenart in die entsprechenden Felder geschrieben. Es werden nur Einträge aktualisiert, deren Zielspalten aktuell ``NULL`` sind. :param dict_koordinaten: Dictionary mit Punktnummer → (X, Y, Z). :type dict_koordinaten: dict :param koordinatenart: Art der Koordinaten ("naeherung_lh" für die Koordinaten im lokalen Horizontsystem aus der Tachymetermessung oder "naeherung_us" für die Näherungskoordinaten der Netzpunkte im geozentrisch-kartesischen-system). :type koordinatenart: str :return: None :rtype: None """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() daten = [] for punktnummer, wert in dict_koordinaten.items(): daten.append(( float(wert[0]), float(wert[1]), float(wert[2]), str(punktnummer) )) # Der Import für die Koordinatenart "naeherung_lh" ist im Zuge möglicher Erweiterungen zu implementieren. if koordinatenart == "naeherung_lh": pass elif koordinatenart == "naeherung_us": cursor.executemany(f"""UPDATE Netzpunkte SET naeherungx_us = ?, naeherungy_us = ?, naeherungz_us = ? WHERE punktnummer = ? AND naeherungx_us IS NULL AND naeherungy_us IS NULL AND naeherungz_us IS NULL""", daten) con.commit() cursor.close() con.close() def set_instrument(self, typ: str, name: str, liste_beobachtungsarten: list) -> None: """Fügt ein Instrument hinzu und initialisiert Varianzkomponenten. Ist das Instrument (typ, name) noch nicht in der Datenbank vorhanden, wird es in die Tabelle Instrumente eingefügt. Zusätzlich werden Einträge in Varianzkomponentenschaetzung für die angegebenen Beobachtungsarten erzeugt. Falls die Varianzkomponentenschätzung noch leer ist, wird ein zusätzlicher Eintrag für die Beobachtungsgruppe "Anschlusspunkte" angelegt. :param typ: Instrumenttyp. :type typ: str :param name: Instrumentname. :type name: str :param liste_beobachtungsarten: Liste der Beobachtungsgruppen zur Initialisierung. :type liste_beobachtungsarten: list :return: None :rtype: None """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_instrumente = cursor.execute("SELECT * FROM Instrumente WHERE typ = ? AND name =?", (typ, name)).fetchall() if liste_instrumente == []: cursor.execute( "INSERT INTO Instrumente (typ, name) VALUES (?, ?)", (typ, name) ) id_instrument = cursor.lastrowid print(f"Das Instrument {name} wurde erfolgreich hinzugefügt.") if self.get_varianzkomponentenschaetzung() == []: cursor.execute( "INSERT INTO Instrumente (typ, name) VALUES (?, ?)", ("Anschlusspunkte", "lA") ) id_instrument_anschlusspunkte = cursor.lastrowid cursor.execute( "INSERT INTO Varianzkomponentenschaetzung (instrumenteID, beobachtungsgruppe) VALUES (?, ?)", (id_instrument_anschlusspunkte, "Anschlusspunkte") ) for beobachtungsart in liste_beobachtungsarten: cursor.execute( "INSERT INTO Varianzkomponentenschaetzung (instrumenteID, beobachtungsgruppe) VALUES (?, ?)", (id_instrument, beobachtungsart) ) else: id_instrument = cursor.execute( "SELECT instrumenteID FROM Instrumente WHERE typ = ? AND name =?", (typ, name)) print(f"Das Instrument {name} ist bereits in der Datenbank vorhanden.") con.commit() cursor.close() con.close() def set_genauigkeiten(self, instrumenteID: int, beobachtungsart: str, stabw_apriori_konstant: float = None, stabw_apriori_streckenprop: float = None) -> None: """Speichert a-priori Genauigkeiten für die Beobachtungsgruppen pro Instrument. Prüft, ob instrumenteID existiert und ob mindestens eine Genauigkeitsangabe übergeben wurde. Je nach Beobachtungsart werden Einheitenumrechnungen durchgeführt (z. B. mgon → rad bzw. mm → m). Der Eintrag wird neu hinzugefügt, wenn in Genauigkeiten kein identischer Datensatz vorhanden ist. Ansonsten wird der bestehende Datensatz in der Datenbank aktualisiert. :param instrumenteID: ID des Instruments in der Tabelle Instrumente. :type instrumenteID: int :param beobachtungsart: Bezeichnung der Beobachtungsart. :type beobachtungsart: str :param stabw_apriori_konstant: Konstanter Anteil der Standardabweichung (optional). :type stabw_apriori_konstant: float | None :param stabw_apriori_streckenprop: Streckenproportionaler Anteil der Standardabweichung (optional). :type stabw_apriori_streckenprop: float | None :return: None :rtype: None """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() # Überprüfung auf vorhandensein der Instrumentes in der Tabelle Instrumente instrumentenname = cursor.execute("SELECT name FROM Instrumente WHERE instrumenteID = ?", (instrumenteID, )).fetchone() if instrumentenname is None: print( f"Die InstumentenID {instrumenteID} ist in der Datenbank nicht vorhanden. Bitte zuerst das Instrument hinzufügen.") cursor.close() con.close() return instrumentenname = instrumentenname[0] # Überprüfung, ob Genauigkeitsinformationen vom Benutzer übergeben wurden. if stabw_apriori_konstant is None and stabw_apriori_streckenprop is None: print( "Es wurden keine Genauigkeiten importiert. Bitte stabw_apriori_konstant und / oder stabw_apriori_streckenprop angeben.") cursor.close() con.close() return # Umrechnen der Einheiten in Radiant und Meter if beobachtungsart == "Tachymeter_Richtung" or beobachtungsart == "Tachymeter_Zenitwinkel" : stabw_apriori_konstant = Einheitenumrechnung.mgon_to_rad_Decimal(stabw_apriori_konstant) if beobachtungsart == "Tachymeter_Strecke" or beobachtungsart == "Geometrisches_Nivellement": stabw_apriori_konstant = Einheitenumrechnung.mm_to_m(stabw_apriori_konstant) if isinstance(stabw_apriori_konstant, Decimal): stabw_apriori_konstant = float(stabw_apriori_konstant) if isinstance(stabw_apriori_streckenprop, Decimal): stabw_apriori_streckenprop = float(stabw_apriori_streckenprop) # Prüfen, ob für dieses Instrument und diese Art bereits ein Eintrag existiert vorhanden = cursor.execute("SELECT 1 FROM Genauigkeiten WHERE instrumenteID = ? AND beobachtungsart = ?", (instrumenteID, beobachtungsart)).fetchone() if vorhanden: # Bestehenden Datensatz aktualisieren cursor.execute( "UPDATE Genauigkeiten SET stabw_apriori_konstant = ?, stabw_apriori_streckenprop = ? WHERE instrumenteID = ? AND beobachtungsart = ?", (stabw_apriori_konstant, stabw_apriori_streckenprop, instrumenteID, beobachtungsart) ) print(f"Die Genauigkeitsangabe für {beobachtungsart} (Instrument: {instrumentenname}) wurde aktualisiert.") else: # Neuen Datensatz anlegen if stabw_apriori_konstant is not None and stabw_apriori_streckenprop is not None: cursor.execute( "INSERT INTO Genauigkeiten (instrumenteID, beobachtungsart, stabw_apriori_konstant, stabw_apriori_streckenprop) VALUES (?, ?, ?, ?)", (instrumenteID, beobachtungsart, stabw_apriori_konstant, stabw_apriori_streckenprop) ) elif stabw_apriori_konstant is None: cursor.execute( "INSERT INTO Genauigkeiten (instrumenteID, beobachtungsart, stabw_apriori_streckenprop) VALUES (?, ?, ?)", (instrumenteID, beobachtungsart, stabw_apriori_streckenprop) ) else: cursor.execute( "INSERT INTO Genauigkeiten (instrumenteID, beobachtungsart, stabw_apriori_konstant) VALUES (?, ?, ?)", (instrumenteID, beobachtungsart, stabw_apriori_konstant) ) print( f"Die Genauigkeitsangabe für {beobachtungsart} (Instrument: {instrumentenname}) wurde erfolgreich hinzugefügt.") con.commit() cursor.close() con.close() def set_datumskoordinaten(self, liste_datumskoordinaten_x: list, liste_datumskoordinaten_y: list, liste_datumskoordinaten_z: list, liste_datumskoordinaten_x_y_z: list) -> None: """Setzt Datumskoordinaten für Netzpunkte unter Berücksichtigung von Vorinformationen. Für die übergebenen Punktlisten werden die Felder datumskoordinate_x, datumskoordinate_y und / oder datumskoordinate_z auf 1 gesetzt. Ein Setzen erfolgt nur, wenn zu der jeweiligen Koordinate eine Vorinformation zur Standardabweichung (stabw_vorinfo_*) vorhanden ist. Eine 1 bedeutet, dass dieser Punkt für die Datumdefinition verwendet wird. :param liste_datumskoordinaten_x: Liste der Punktnummern mit Datumsdefinition in X. :type liste_datumskoordinaten_x: list :param liste_datumskoordinaten_y: Liste der Punktnummern mit Datumsdefinition in Y. :type liste_datumskoordinaten_y: list :param liste_datumskoordinaten_z: Liste der Punktnummern mit Datumsdefinition in Z. :type liste_datumskoordinaten_z: list :param liste_datumskoordinaten_x_y_z: Liste der Punktnummern mit Datumsdefinition in X, Y und Z. :type liste_datumskoordinaten_x_y_z: list :return: None :rtype: None """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() # Überprüfen, ob Genauigkeitsinformationen zu den Punkten in der Datenbank gespeichert sind. Ist dies der Fall, wird eine 1 in das entsprechende Tupel geschrieben. liste_stabw_vorinfo_x = [str(row[0]).strip() for row in cursor.execute( "SELECT punktnummer FROM Netzpunkte WHERE stabw_vorinfo_x IS NOT NULL").fetchall()] liste_stabw_vorinfo_y = [str(row[0]).strip() for row in cursor.execute( "SELECT punktnummer FROM Netzpunkte WHERE stabw_vorinfo_y IS NOT NULL").fetchall()] liste_stabw_vorinfo_z = [str(row[0]).strip() for row in cursor.execute( "SELECT punktnummer FROM Netzpunkte WHERE stabw_vorinfo_z IS NOT NULL").fetchall()] liste_stabw_vorinfo_x_y_z = [str(row[0]).strip() for row in cursor.execute( "SELECT punktnummer FROM Netzpunkte WHERE stabw_vorinfo_x IS NOT NULL AND stabw_vorinfo_y IS NOT NULL AND stabw_vorinfo_z IS NOT NULL").fetchall()] if liste_datumskoordinaten_x != []: for punktnummer in liste_datumskoordinaten_x: punktnummer = str(punktnummer).strip() if punktnummer in liste_stabw_vorinfo_x: cursor.execute(f"UPDATE Netzpunkte SET datumskoordinate_x = 1 WHERE punktnummer = ? AND stabw_vorinfo_x IS NOT NULL", (str(punktnummer),)) else: print(f"Die X-Koordinate des Punktes {punktnummer} wurde nicht in eine Datumskoordinate geändert, weil keine Vorinformationen zur Standardabweichung der X-Koordinate des Punktes vorliegen. Diese bitte zuerst erfassen und Datumsdefinition wiederholen.") if liste_datumskoordinaten_y != []: for punktnummer in liste_datumskoordinaten_y: punktnummer = str(punktnummer).strip() if punktnummer in liste_stabw_vorinfo_y: cursor.execute(f"UPDATE Netzpunkte SET datumskoordinate_y = 1 WHERE punktnummer = ? AND stabw_vorinfo_y IS NOT NULL", (str(punktnummer),)) else: print(f"Die Y-Koordinate des Punktes {punktnummer} wurde nicht in eine Datumskoordinate geändert, weil keine Vorinformationen zur Standardabweichung der Y-Koordinate des Punktes vorliegen. Diese bitte zuerst erfassen und Datumsdefinition wiederholen.") if liste_datumskoordinaten_z != []: for punktnummer in liste_datumskoordinaten_z: punktnummer = str(punktnummer).strip() if punktnummer in liste_stabw_vorinfo_z: cursor.execute(f"UPDATE Netzpunkte SET datumskoordinate_z = 1 WHERE punktnummer = ? AND stabw_vorinfo_z IS NOT NULL", (str(punktnummer),)) else: print(f"Die Z-Koordinate des Punktes {punktnummer} wurde nicht in eine Datumskoordinate geändert, weil keine Vorinformationen zur Standardabweichung der Z-Koordinate des Punktes vorliegen. Diese bitte zuerst erfassen und Datumsdefinition wiederholen.") if liste_datumskoordinaten_x_y_z != []: for punktnummer in liste_datumskoordinaten_x_y_z: punktnummer = str(punktnummer).strip() if punktnummer in liste_stabw_vorinfo_x_y_z: cursor.execute(f"UPDATE Netzpunkte SET datumskoordinate_x = 1, datumskoordinate_y = 1, datumskoordinate_z = 1 WHERE punktnummer = ? AND stabw_vorinfo_x IS NOT NULL AND stabw_vorinfo_y IS NOT NULL AND stabw_vorinfo_z IS NOT NULL", (str(punktnummer),)) else: print(f"Der Punkt {punktnummer} wurde nicht in einen Datumspunkt geändert, weil nicht alle Vorinformationen zur Standardabweichung der Koordinaten des Punktes vorliegen. Diese bitte zuerst erfassen und Datumsdefinition wiederholen.") con.commit() cursor.close() con.close() def set_datumskoordinaten_to_neupunkte(self, liste_datumskoordinaten_x: list, liste_datumskoordinaten_y: list, liste_datumskoordinaten_z: list, liste_datumskoordinaten_x_y_z: list) -> None: """Setzt Datumskoordinaten für angegebene Punkte wieder zurück. Für die übergebenen Punktlisten werden die Felder datumskoordinate_x, datumskoordinate_y und / oder datumskoordinate_z auf 0 gesetzt. Dadurch werden diese in der Ausgleichung wieder als Neupunkte behandelt und werden nicht für die Datumsdefinition verwendet. :param liste_datumskoordinaten_x: Liste der Punktnummern, deren X-Datumsfestlegung zurückgesetzt wird. :type liste_datumskoordinaten_x: list :param liste_datumskoordinaten_y: Liste der Punktnummern, deren Y-Datumsfestlegung zurückgesetzt wird. :type liste_datumskoordinaten_y: list :param liste_datumskoordinaten_z: Liste der Punktnummern, deren Z-Datumsfestlegung zurückgesetzt wird. :type liste_datumskoordinaten_z: list :param liste_datumskoordinaten_x_y_z: Liste der Punktnummern, deren X-, Y- und Z-Datumsfestlegung zurückgesetzt werden. :type liste_datumskoordinaten_x_y_z: list :return: None :rtype: None """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() # Überprüfung, ob eine Benutzereingabe in der entsprechenden Liste vorgenommen wurde. Wenn ja, wird ein UPDATE in der Datenbank durchgeführt. if liste_datumskoordinaten_x != []: for punktnummer in liste_datumskoordinaten_x: punktnummer = str(punktnummer).strip() cursor.execute( f"UPDATE Netzpunkte SET datumskoordinate_x = 0 WHERE punktnummer = ?", (str(punktnummer),)) if liste_datumskoordinaten_y != []: for punktnummer in liste_datumskoordinaten_y: punktnummer = str(punktnummer).strip() cursor.execute( f"UPDATE Netzpunkte SET datumskoordinate_y = 0 WHERE punktnummer = ?", (str(punktnummer),)) if liste_datumskoordinaten_z != []: for punktnummer in liste_datumskoordinaten_z: punktnummer = str(punktnummer).strip() cursor.execute( f"UPDATE Netzpunkte SET datumskoordinate_z = 0 WHERE punktnummer = ?", (str(punktnummer),)) if liste_datumskoordinaten_x_y_z != []: for punktnummer in liste_datumskoordinaten_x_y_z: punktnummer = str(punktnummer).strip() cursor.execute( f"UPDATE Netzpunkte SET datumskoordinate_x = 0, datumskoordinate_y = 0, datumskoordinate_z = 0 WHERE punktnummer = ?", (str(punktnummer),)) con.commit() cursor.close() con.close() def set_normalhoehe_hfp(self, liste_normalhoehe_hfp: list) -> LiteralString | str: """Speichert Normalhöhen von amtlichen Höhenfestpunkten (HFP) in Netzpunkte. Existiert die Punktnummer bereits in der Tabelle Netzpunkte, wird das Attribut normalhoehe_hfp aktualisiert. Andernfalls wird ein neuer Datensatz mit Punktnummer und Normalhöhe eingefügt. :param liste_normalhoehe_hfp: Liste mit HFP-Informationen (u. a. Punktnummer und Normalhöhe). :type liste_normalhoehe_hfp: list :return: Zusammenfassung der durchgeführten Aktualisierungen bzw. Hinweis, falls keine Daten übergeben wurden. :rtype: str """ liste_hfp_in_db = self.get_normalhoehe_hfp() if liste_normalhoehe_hfp != []: con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_punktnummern_in_db = [str(r[0]) for r in cursor.execute( "SELECT punktnummer FROM Netzpunkte" ).fetchall()] ausgaben = [] for hfp in liste_normalhoehe_hfp: if str(hfp[0]) in liste_punktnummern_in_db: cursor.execute("UPDATE Netzpunkte SET normalhoehe_hfp = ? WHERE punktnummer = ?", (hfp[3], hfp[0]) ) ausgaben.append(f"Der HFP {hfp[0]} wurde aktualisiert.") else: cursor.execute( "INSERT INTO Netzpunkte (punktnummer, normalhoehe_hfp) VALUES (?, ?)", (hfp[0], hfp[1]) ) ausgaben.append(f"Der HFP {hfp[0]} wurde neu hinzugefügt.") con.commit() cursor.close() con.close() return "\n".join(ausgaben) else: return f"Es wurden keine neuen Normalhöhen übergeben. Folgende Normalhöhen sind in der Datenbank enthalten: {liste_hfp_in_db}" def set_beobachtung_ausschalten(self, dict_beobachtung_ausschalten: dict) -> None: """Schaltet ausgewählte Beobachtungen für die Ausgleichung aus. Die zu deaktivierenden Beobachtungen werden über dict_beobachtung_ausschalten übergeben. Der Schlüssel wird ausgewertet und das zugehörige *_ausschalten-Tupel in der Datenbank auf 1 gesetzt (z. B. Richtungen, Zenitwinkel, Strecken, GNSS-Komponenten, Geometrisches Nivellement). Dadurch wird die jeweilige Beobachtung in allen folgenden Iterationen nicht mehr berücksichtigt. :param dict_beobachtung_ausschalten: Dictionary zur Steuerung, welche Beobachtungen deaktiviert werden, in der Form: {Beobachtung: "beobachtung_ausschalten"} zum ausschalten und {Beobachtung: ""} fürs beibehalten. :type dict_beobachtung_ausschalten: dict :return: None :rtype: None """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() for beobachtung, ausschalten in dict_beobachtung_ausschalten.items(): # Nur in die Schleife gehen, wenn im Value des Dicts "beobachtung_ausschalten" enthalten ist. if ausschalten == "beobachtung_ausschalten": beobachtung_gesplittet = beobachtung.split("_") # Distanz if beobachtung_gesplittet[1] == "SD": try: cursor.execute(f"""UPDATE Beobachtungen SET tachymeter_distanz_auschalten = 1 WHERE beobachtungenID = ? AND beobachtungsgruppeID = ? AND punktnummer_sp = ? AND punktnummer_zp = ?""", (beobachtung_gesplittet[0], beobachtung_gesplittet[2], beobachtung_gesplittet[3], beobachtung_gesplittet[4])) except: print(f"Die Beobachtung {beobachtung} konnte aufgrund eines Fehlers nicht ausgeschaltet werden.") # Richtungen if beobachtung_gesplittet[1] == "R": try: cursor.execute(f"""UPDATE Beobachtungen SET tachymeter_richtung_ausschalten = 1 WHERE beobachtungenID = ? AND beobachtungsgruppeID = ? AND punktnummer_sp = ? AND punktnummer_zp = ?""", (beobachtung_gesplittet[0], beobachtung_gesplittet[2], beobachtung_gesplittet[3], beobachtung_gesplittet[4])) except: print(f"Die Beobachtung {beobachtung} konnte aufgrund eines Fehlers nicht ausgeschaltet werden.") # Zenitwinkel if beobachtung_gesplittet[1] == "ZW": try: cursor.execute(f"""UPDATE Beobachtungen SET tachymeter_zenitwinkel_ausschalten = 1 WHERE beobachtungenID = ? AND beobachtungsgruppeID = ? AND punktnummer_sp = ? AND punktnummer_zp = ?""", (beobachtung_gesplittet[0], beobachtung_gesplittet[2], beobachtung_gesplittet[3], beobachtung_gesplittet[4])) except: print(f"Die Beobachtung {beobachtung} konnte aufgrund eines Fehlers nicht ausgeschaltet werden.") if beobachtung_gesplittet[1] == "gnssbx": try: cursor.execute(f"""UPDATE Beobachtungen SET gnss_bx_ausschalten = 1 WHERE beobachtungenID = ? AND punktnummer_sp = ? AND punktnummer_zp = ?""", (beobachtung_gesplittet[0], beobachtung_gesplittet[2], beobachtung_gesplittet[3])) except: print(f"Die Beobachtung {beobachtung} konnte aufgrund eines Fehlers nicht ausgeschaltet werden.") #GNSS-Basislinien if beobachtung_gesplittet[1] == "gnssby": try: cursor.execute(f"""UPDATE Beobachtungen SET gnss_by_ausschalten = 1 WHERE beobachtungenID = ? AND punktnummer_sp = ? AND punktnummer_zp = ?""", (beobachtung_gesplittet[0], beobachtung_gesplittet[2], beobachtung_gesplittet[3])) except: print(f"Die Beobachtung {beobachtung} konnte aufgrund eines Fehlers nicht ausgeschaltet werden.") if beobachtung_gesplittet[1] == "gnssbz": try: cursor.execute(f"""UPDATE Beobachtungen SET gnss_bz_ausschalten = 1 WHERE beobachtungenID = ? AND punktnummer_sp = ? AND punktnummer_zp = ?""", (beobachtung_gesplittet[0], beobachtung_gesplittet[2], beobachtung_gesplittet[3])) except: print(f"Die Beobachtung {beobachtung} konnte aufgrund eines Fehlers nicht ausgeschaltet werden.") # Geometrisches Nivellement if beobachtung_gesplittet[1] == "niv": try: cursor.execute(f"""UPDATE Beobachtungen SET niv_ausschalten = 1 WHERE beobachtungenID = ? AND punktnummer_sp = ? AND punktnummer_zp = ?""", (beobachtung_gesplittet[0], beobachtung_gesplittet[2], beobachtung_gesplittet[3])) except: print(f"Die Beobachtung {beobachtung} konnte aufgrund eines Fehlers nicht ausgeschaltet werden.") print("Die ausgewählten Beobachtungen werden für die folgenden Iterationen ausgeschaltet.") con.commit() cursor.close() con.close() def set_varianzkomponente(self, liste_varianzkomponten_anpassen: list) -> None: """Passt Varianzkomponenten für die nächste Iteration an. Für jede angegebene Varianzkomponente wird der aktuelle Datenbankwert mit einem vom Benutzer übergebenen Faktor multipliziert und zurückgeschrieben. :param liste_varianzkomponten_anpassen: Liste mit Einträgen (instrumenteID, beobachtungsgruppe, faktor). :type liste_varianzkomponten_anpassen: list :return: None :rtype: None """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() if liste_varianzkomponten_anpassen != []: for varianzkomponente in liste_varianzkomponten_anpassen: # Faktor für die Varianzkomponentenschätzung der aktuellen Iteration aus der Datenbank abfragen varianz_db = cursor.execute(f"SELECT varianz_varianzkomponentenschaetzung FROM Varianzkomponentenschaetzung WHERE instrumenteID = ? AND beobachtungsgruppe = ?", (varianzkomponente[0], varianzkomponente[1])).fetchone()[0] # Faktor für die Varianzkompontenschätzung aus der Datenbank mit der Benutzereingabe multiplizieren und das Produkt in der Datenbank für die nächste Iteration speichern. cursor.execute( f"UPDATE Varianzkomponentenschaetzung SET varianz_varianzkomponentenschaetzung = ? WHERE instrumenteID = ? AND beobachtungsgruppe = ?", (varianz_db * varianzkomponente[2], varianzkomponente[0], varianzkomponente[1])) print(f"Folgende Varianzkomponente wurde für die nächste Iteration gespeichert: {liste_varianzkomponten_anpassen}.") con.commit() cursor.close() con.close() def get_koordinaten(self, koordinatenart: str, ausgabeart: str = "Dict") -> dict[Any, MutableDenseMatrix] | None: """Liest Koordinaten aus der Tabelle Netzpunkte. Abhängig von der koordinatenart werden die entsprechenden Koordinatenspalten gelesen. Es werden nur Datensätze berücksichtigt, bei denen X, Y und Z nicht NULL sind. Bei ausgabeart="Dict" wird ein Dictionary in der Form {Punktnummer : sympy.Matrix([X, Y, Z])} zurückgegeben. :param koordinatenart: Art der Koordinaten ("naeherung_lh" für Koordinaten im lokalen Horizontsystem aus dem Tachymeterimport oder "naeherung_us" für Näherungskoordinaten im geozentrisch-kartesischen System). :type koordinatenart: str :param ausgabeart: Ausgabeformat (Standard: "Dict"). :type ausgabeart: str :return: Dictionary mit Punktnummer → Koordinatenmatrix oder None (abhängig von ausgabeart). :rtype: dict | None """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() # Festlegen der Attribute, welche je nach Koordinatenart aus der Datenbank abgefragt werden sollen if koordinatenart == "naeherung_lh": values = "punktnummer, naeherungx_lh, naeherungy_lh, naeherungz_lh" elif koordinatenart == "naeherung_us": values = "punktnummer, naeherungx_us, naeherungy_us, naeherungz_us" # SQL-Abfrage liste_koordinaten = cursor.execute(f""" SELECT {values} FROM Netzpunkte; """).fetchall() cursor.close() con.close() # Nur ausgeben, wenn für einen Punkt X, Y und Z Koordinaten vorhanden sind liste_koordinaten = [ koordinate for koordinate in liste_koordinaten if koordinate[1] is not None and koordinate[2] is not None and koordinate[3] is not None ] # Aktuell ist nur die Ausgabeart "Dict" implementiert. Weitere Ausgabearten sind im Zuge möglicher erweiterungen zu implementieren. if ausgabeart == "Dict": return { koordinate[0]: sp.Matrix([ sp.Float(str(koordinate[1])), sp.Float(str(koordinate[2])), sp.Float(str(koordinate[3])) ]) for koordinate in liste_koordinaten } def get_normalhoehe_hfp(self) -> list[Any]: """Liest alle Normalhöhen von amtlichen Höhenfestpunkten (HFP) aus der Tabelle Netzpunkte. :return: Liste mit Tupeln (punktnummer, normalhoehe_hfp) für alle Punkte mit gesetzter Normalhöhe. :rtype: list """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_hfp = cursor.execute("SELECT punktnummer, normalhoehe_hfp FROM Netzpunkte WHERE normalhoehe_hfp IS NOT NULL").fetchall() cursor.close() con.close() return liste_hfp def get_instrument_liste(self, typ: str) -> list: """Liest Instrumente eines gegebenen Typs aus der Tabelle Instrumente. Gibt eine Liste der gefundenen Instrumente zurück. Falls keine Instrumente vorhanden sind, wird eine Textausgabe mit verfügbaren Typen zurückgegeben. :param typ: Instrumenttyp. :type typ: str :return: Liste der Instrumente oder Hinweistext, falls keine Instrumente gefunden wurden. :rtype: list | str """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_instrumente = cursor.execute("SELECT * FROM Instrumente WHERE typ = ?", (typ,)).fetchall() liste_typen = cursor.execute("SELECT DISTINCT typ FROM Instrumente").fetchall() cursor.close() con.close() if liste_instrumente == []: liste_instrumente = f"Kein Instrument vom Typ {typ} gefunden. Folgende Typen stehen aktuell zur Auswahl: {liste_typen}" return liste_instrumente def get_alle_instrumente_liste(self: str) -> list: """Liest alle Instrumente aus der Tabelle Instrumente auf. Gibt eine Liste der gefundenen Instrumente zurück. Falls keine Instrumente vorhanden sind, wird eine Textausgabe mit verfügbaren Typen zurückgegeben. :return: Liste der Instrumente oder Hinweistext, falls keine Instrumente gefunden wurden. :rtype: list | str """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_instrumente = cursor.execute("SELECT * FROM Instrumente").fetchall() liste_typen = cursor.execute("SELECT DISTINCT typ FROM Instrumente").fetchall() cursor.close() con.close() if liste_instrumente == []: liste_instrumente = f"Kein Instrumente gefunden. Bitte in der Folgenden Zelle anlegen." return liste_instrumente def get_genauigkeiten_dict(self) -> dict[Any, Any]: """Liest alle Genauigkeiten aus der Tabelle Genauigkeiten und gibt diese als Dictionary zurück. :return: Dictionary {genauigkeitenID : restliche Tabellenwerte}. :rtype: dict """ dict = {} con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_genauigkeiten = cursor.execute("SELECT * FROM Genauigkeiten").fetchall() for genauigkeit in liste_genauigkeiten: dict[genauigkeit[0]] = genauigkeit[1:] cursor.close() con.close() return dict def get_instrumenteID_beobachtungenID_dict(self) -> dict[Any, Any]: """Liest die Zuordnung BeobachtungenID → InstrumenteID aus der Tabelle Beobachtungen. :return: Dictionary {beobachtungenID : instrumenteID}. :rtype: dict """ dict = {} con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_beobachtungen_instrumente = cursor.execute("SELECT beobachtungenID, instrumenteID FROM Beobachtungen").fetchall() for i in liste_beobachtungen_instrumente: dict[i[0]] = i[1] cursor.close() con.close() return dict def get_puntknummern_beobachtungen_tachymeter(self, beobachtungsart: str) -> list[Any]: """Liest Beobachtungen (ID, Gruppe, Standpunkt, Zielpunkt) für Tachymeterbeobachtungen. Es werden nur Beobachtungen berücksichtigt, bei denen die angegebene Beobachtungsart nicht NULL ist. Zudem werden zusätzlich werden nur Beobachtungen übergeben, die nicht ausgeschaltet werden. :param beobachtungsart: Name der Beobachtungsspalte. :type beobachtungsart: str :return: Liste von Tupeln (beobachtungenID, beobachtungsgruppeID, punktnummer_sp, punktnummer_zp). :rtype: list """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() sql_ausdruck = f"SELECT beobachtungenID, beobachtungsgruppeID, punktnummer_sp, punktnummer_zp FROM Beobachtungen WHERE {beobachtungsart} IS NOT NULL" if beobachtungsart == "tachymeter_distanz": sql_ausdruck += " AND tachymeter_distanz_auschalten = 0" elif beobachtungsart == "tachymeter_richtung": sql_ausdruck += " AND tachymeter_richtung_ausschalten = 0" elif beobachtungsart == "tachymeter_zenitwinkel": sql_ausdruck += " AND tachymeter_zenitwinkel_ausschalten = 0" liste_beobachtungen = cursor.execute(sql_ausdruck).fetchall() cursor.close() con.close() return liste_beobachtungen def get_beobachtungen_from_beobachtungenid(self) -> list[Any]: """Liest Tachymeterbeobachtungen aus der Tabelle ``Beobachtungen``. Es werden nur Datensätze mit gesetzter Tachymeter-Richtung berücksichtigt. :return: Liste von Tupeln (punktnummer_sp, punktnummer_zp, beobachtungenID, beobachtungsgruppeID, tachymeter_richtung, tachymeter_zenitwinkel, tachymeter_distanz). :rtype: list """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_beobachtungen = cursor.execute(f"SELECT punktnummer_sp, punktnummer_zp, beobachtungenID, beobachtungsgruppeID, tachymeter_richtung, tachymeter_zenitwinkel, tachymeter_distanz FROM Beobachtungen WHERE tachymeter_richtung IS NOT NULL").fetchall() cursor.close() con.close() return liste_beobachtungen def get_beobachtungen_gnssbasislinien(self) -> list[Any]: """Liest GNSS-Basislinienbeobachtungen inklusive Kovarianzangaben. Es werden nur Datensätze zurückgegeben, bei denen alle benötigten GNSS-Felder (bx, by, bz, s0 und Kovarianzelemente) nicht NULL sind. :return: Liste von Tupeln mit GNSS-Basisliniendaten und Kovarianzelementen. :rtype: list """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_beobachtungen = cursor.execute(f"SELECT beobachtungenID, punktnummer_sp, punktnummer_zp, gnss_bx, gnss_by, gnss_bz, gnss_s0, gnss_cxx, gnss_cxy, gnss_cxz, gnss_cyy, gnss_cyz, gnss_czz FROM Beobachtungen WHERE gnss_bx IS NOT NULL AND gnss_by IS NOT NULL AND gnss_bz IS NOT NULL AND gnss_s0 IS NOT NULL AND gnss_cxx IS NOT NULL AND gnss_cxy IS NOT NULL AND gnss_cxz IS NOT NULL AND gnss_cyy IS NOT NULL AND gnss_cyz IS NOT NULL AND gnss_czz IS NOT NULL").fetchall() cursor.close() con.close() return liste_beobachtungen def get_beobachtungen_nivellement(self) -> list[Any]: """Liest Nivellementbeobachtungen aus der Tabelle Beobachtungen. Es werden nur Datensätze zurückgegeben, bei denen alle Nivellementfelder Daten enthalten und niv_ausschalten = 0 ist, also diese Beobachtung in der Ausgleichung verwendet wird. :return: Liste von Tupeln (beobachtungenID, punktnummer_sp, punktnummer_zp, niv_dh, niv_strecke, niv_anz_standpkte). :rtype: list """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_beobachtungen = cursor.execute(f"SELECT beobachtungenID, punktnummer_sp, punktnummer_zp, niv_dh, niv_strecke, niv_anz_standpkte FROM Beobachtungen WHERE niv_dh IS NOT NULL AND niv_strecke IS NOT NULL AND niv_anz_standpkte IS NOT NULL AND niv_ausschalten = 0").fetchall() cursor.close() con.close() return liste_beobachtungen def get_datumskoordinate(self) -> list[Any]: """Liest die aktuell gesetzten Datumskoordinaten aus der Tabelle Netzpunkte. Die Rückgabe erfolgt als Liste von Symbolnamen der Form "X", "Y" und "Z". :return: Liste der Datumskoordinatenbezeichner. :rtype: list """ # Abragen der Koordinaten mit einer 1 im Attribut datumskoordinate_*, da diese für die Lagerung verwendet werden sollen. con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_datumskoordinate_x = cursor.execute( f"SELECT punktnummer FROM Netzpunkte WHERE datumskoordinate_x = 1").fetchall() liste_datumskoordinate_y = cursor.execute( f"SELECT punktnummer FROM Netzpunkte WHERE datumskoordinate_y = 1").fetchall() liste_datumskoordinate_z = cursor.execute( f"SELECT punktnummer FROM Netzpunkte WHERE datumskoordinate_z = 1").fetchall() cursor.close() con.close() # Hinzufügen der jeweiligen Punktnummer als Symbol mit X, Y oder Z-Präfix zur Rückgabeliste liste_datumskoordinaten = [] if liste_datumskoordinate_x != []: for datumskoordinate in liste_datumskoordinate_x: datumskoordinate = str(datumskoordinate[0]).strip() liste_datumskoordinaten.append(f"X{datumskoordinate}") if liste_datumskoordinate_y != []: for datumskoordinate in liste_datumskoordinate_y: datumskoordinate = str(datumskoordinate[0]).strip() liste_datumskoordinaten.append(f"Y{datumskoordinate}") if liste_datumskoordinate_z != []: for datumskoordinate in liste_datumskoordinate_z: datumskoordinate = str(datumskoordinate[0]).strip() liste_datumskoordinaten.append(f"Z{datumskoordinate}") return liste_datumskoordinaten def get_stabw_AA_Netzpunkte(self) -> dict[Any, Any]: """Liest Vorinformationen zur Standardabweichung der Netzpunkte aus der Tabelle Netzpunkte. Die Rückgabe erfolgt als Dictionary mit Schlüsseln der Form "StabwAA_X", "StabwAA_Y" und "StabwAA_Z". :return: Dictionary der Vorinformationen zur Standardabweichung je Koordinate. :rtype: dict """ # Abfragen aller Punktnummern und s0 apriori Vorinformationen aus der Datenbank, wenn die Vorinformationen vorliegen. con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_stabwAA_x = cursor.execute(f"SELECT punktnummer, stabw_vorinfo_x FROM Netzpunkte WHERE stabw_vorinfo_x IS NOT NULL").fetchall() liste_stabwAA_y = cursor.execute( f"SELECT punktnummer, stabw_vorinfo_y FROM Netzpunkte WHERE stabw_vorinfo_y IS NOT NULL").fetchall() liste_stabwAA_z = cursor.execute( f"SELECT punktnummer, stabw_vorinfo_z FROM Netzpunkte WHERE stabw_vorinfo_z IS NOT NULL").fetchall() cursor.close() con.close() # Erstellen des Rückgabedictionaries. dict_stabwAA = {} for stabwAA_x in liste_stabwAA_x: punktnummer = str(stabwAA_x[0]).strip() wert = stabwAA_x[1] dict_stabwAA[f"StabwAA_X{punktnummer}"]= wert for stabwAA_y in liste_stabwAA_y: punktnummer = str(stabwAA_y[0]).strip() wert = stabwAA_y[1] dict_stabwAA[f"StabwAA_Y{punktnummer}"]= wert for stabwAA_z in liste_stabwAA_z: punktnummer = str(stabwAA_z[0]).strip() wert = stabwAA_z[1] dict_stabwAA[f"StabwAA_Z{punktnummer}"]= wert return dict_stabwAA def get_gnss_beobachtungen_punktnummern(self, gnss_komponente: str) -> list[Any]: """Liest GNSS-Beobachtungen (ID, Standpunkt, Zielpunkt) für eine GNSS-Komponente. Es werden nur Datensätze berücksichtigt, bei denen die geforderte Komponente sowie alle zugehörigen GNSS-Genauigkeitsangaben (s0 und Kovarianzelemente) vorhanden sind. Zusätzlich wird das jeweilige Ausschalt-Attribut berücksichtigt. :param gnss_komponente: Name der GNSS-Basislinienkomponente (z. B. "gnss_bx", "gnss_by", "gnss_bz"). :type gnss_komponente: str :return: Liste von Tupeln (beobachtungenID, punktnummer_sp, punktnummer_zp). :rtype: list """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() sql = f"""SELECT beobachtungenID, punktnummer_sp, punktnummer_zp FROM Beobachtungen WHERE {gnss_komponente} IS NOT NULL AND gnss_s0 IS NOT NULL AND gnss_cxx IS NOT NULL AND gnss_cxy IS NOT NULL AND gnss_cxz IS NOT NULL AND gnss_cyy IS NOT NULL AND gnss_cyz IS NOT NULL AND gnss_czz IS NOT NULL""" if gnss_komponente == "gnss_bx": sql += " AND gnss_bx_ausschalten = 0" elif gnss_komponente == "gnss_by": sql += " AND gnss_by_ausschalten = 0" elif gnss_komponente == "gnss_bz": sql += " AND gnss_bz_ausschalten = 0" liste_gnss_beobachtungen = cursor.execute(sql).fetchall() cursor.close() con.close() return liste_gnss_beobachtungen def get_nivellement_beobachtungen_punktnummern(self) -> list[Any]: """Liest Beobachtungen vom geometrischen Nivellement (ID, Standpunkt, Zielpunkt) aus der Tabelle Beobachtungen. Es werden nur Datensätze berücksichtigt, bei denen alle Attribute gesetzt sind und niv_ausschalten = 0 ist. :return: Liste von Tupeln (beobachtungenID, punktnummer_sp, punktnummer_zp). :rtype: list """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_nivellement_beobachtungen = cursor.execute(f"SELECT beobachtungenID, punktnummer_sp, punktnummer_zp FROM Beobachtungen WHERE niv_dh IS NOT NULL AND niv_strecke IS NOT NULL AND niv_anz_standpkte IS NOT NULL AND niv_ausschalten = 0").fetchall() cursor.close() con.close() return liste_nivellement_beobachtungen def get_varianzkomponentenschaetzung(self) -> list[Any]: """Liest alle Einträge der Varianzkomponentenschätzung aus der Datenbank. :return: Liste von Tupeln (varianzkomponenteID, instrumenteID, beobachtungsgruppe, varianz_varianzkomponentenschaetzung). :rtype: list """ con = sqlite3.connect(self.pfad_datenbank) cursor = con.cursor() liste_varianzkomponenten = cursor.execute(f"SELECT varianzkomponenteID, instrumenteID, beobachtungsgruppe, varianz_varianzkomponentenschaetzung FROM Varianzkomponentenschaetzung").fetchall() cursor.close() con.close() return liste_varianzkomponenten def tabelle_instrumente_aus_db(self) -> None: """Stellt die in der Datenbank gespeicherten Instrumente tabellarisch dar. Die Methode liest alle Datensätze aus der Tabelle Instrumente über die zugehörige Datenbankzugriffsmethode und erzeugt daraus einen pandas-DataFrame zur Anzeige im Notebook. Sind keine Instrumente vorhanden, wird ein Hinweistext ausgegeben, dass die Instrumente zuerst anzulegen sind. :return: None :rtype: None """ liste_instrumente_in_db = self.get_alle_instrumente_liste() # Prüfen, ob Datensätze in der Tabelle Instrumente enthalten sind if isinstance(liste_instrumente_in_db, list) and len(liste_instrumente_in_db) > 0: df_instrumente = pd.DataFrame(liste_instrumente_in_db, columns=['InstrumenteID', 'Typ', 'Bezeichnung']) display(df_instrumente.style.hide(axis='index')) else: print( "Es wurden noch keine Instrumente angelegt. Bitte in der folgenden Zelle nachholen und diese Zelle erneut ausführen!") def tabelle_genauigkeiten_aus_db(self) -> None: """Stellt die a-priori Genauigkeiten der Beobachtungsgruppen tabellarisch dar. Die Methode liest alle Einträge aus der Tabelle Genauigkeiten über die zugehörige Datenbankzugriffsmethode und erstellt eine übersichtliche Anzeige im Notebook. Liegen keine Genauigkeitsangaben vor, wird ein Hinweistext ausgegeben, dass die a-priori Genauigkeiten zunächst zu erfassen sind. :return: None :rtype: None """ genauigkeiten_dict = self.get_genauigkeiten_dict() # Prüfen, ob Datensätze in der Tabelle Instrumente enthalten sind if genauigkeiten_dict == {}: print( "Es wurden noch keine apriori Genauigkeiten zu den Beobachtungsgruppen erfasst. Bitte in der folgenden Zelle nachholen und diese Zelle erneut ausführen.") else: formatierte_daten = list(genauigkeiten_dict.values()) spalten = [ 'instrumenteID', 'beobachtungsart', 'stabw_apriori_konstant', 'stabw_apriori_streckenprop' ] df = pd.DataFrame(formatierte_daten, columns=spalten) display(df.style.hide(axis='index'))