This commit is contained in:
2026-01-14 14:04:33 +01:00
parent 678e5763c0
commit d2b6f604f0
6 changed files with 50774 additions and 37077 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,11 @@ from Berechnungen import Berechnungen
import numpy as np import numpy as np
import importlib import importlib
from Koordinatentransformationen import Transformationen from Koordinatentransformationen import Transformationen
from pathlib import Path
import pandas as pd
import numpy as np
import sympy as sp
@@ -28,9 +33,8 @@ class FunktionalesModell:
def jacobi_matrix_symbolisch(self, datumsfestlegung = None, liste_unbekannte_datumsfestlegung = None): def jacobi_matrix_symbolisch(self, datumsfestlegung = None, liste_unbekannte_datumsfestlegung = None):
#liste_beobachtungsarten = ["tachymeter_distanz", "tachymeter_richtung", "tachymeter_zenitwinkel"] #liste_beobachtungsarten = ["tachymeter_distanz", "tachymeter_richtung", "tachymeter_zenitwinkel"]
liste_beobachtungsarten = ["tachymeter_distanz", "tachymeter_richtung", "tachymeter_zenitwinkel", "gnss_basislinien", "geometrisches_nivellement"] #liste_beobachtungsarten = ["tachymeter_distanz", "tachymeter_richtung", "tachymeter_zenitwinkel", "gnss_basislinien", "geometrisches_nivellement"]
#liste_beobachtungsarten = ["tachymeter_distanz", "tachymeter_richtung", "tachymeter_zenitwinkel", liste_beobachtungsarten = ["tachymeter_distanz", "tachymeter_richtung", "tachymeter_zenitwinkel", "gnss_basislinien"]
# "gnss_basislinien"]
db_zugriff = Datenbankzugriff(self.pfad_datenbank) db_zugriff = Datenbankzugriff(self.pfad_datenbank)
liste_beobachtungen_rohdaten_gnssbasislinien = [] liste_beobachtungen_rohdaten_gnssbasislinien = []
@@ -371,7 +375,7 @@ class FunktionalesModell:
return A_gesamt, liste_unbekannte, liste_zeilenbeschriftungen_gesamt return A_gesamt, liste_unbekannte, liste_zeilenbeschriftungen_gesamt
def jacobi_matrix_zahlen_iteration_0(self, A_symbolisch, koordinatenart, liste_unbekannte = None, liste_zeilenbeschriftungen_gesamt = None): def jacobi_matrix_zahlen_iteration_0(self, A_symbolisch, koordinatenart, liste_unbekannte = None, liste_zeilenbeschriftungen_gesamt = None, iterationsnummer = 0):
self.liste_beobachtungsvektor_symbolisch = [str(x) for x in liste_zeilenbeschriftungen_gesamt] self.liste_beobachtungsvektor_symbolisch = [str(x) for x in liste_zeilenbeschriftungen_gesamt]
if koordinatenart == "naeherung_us": if koordinatenart == "naeherung_us":
@@ -385,13 +389,34 @@ class FunktionalesModell:
cse=True cse=True
) )
fehlend = [s for s in self.liste_symbole_lambdify if s not in self.substitutionen_dict]
if fehlend:
Export.matrix_to_csv(
r"Zwischenergebnisse\fehlende_substitutionen_A.csv",
[""],
[str(s) for s in fehlend],
sp.Matrix([[str(s)] for s in fehlend]),
"fehlend"
)
raise ValueError(f"Fehlende Substitutionen in A: {[str(s) for s in fehlend[:30]]}")
liste_werte = [self.substitutionen_dict[s] for s in self.liste_symbole_lambdify] liste_werte = [self.substitutionen_dict[s] for s in self.liste_symbole_lambdify]
#A_numerisch = sp.Matrix(self.func_A0(*liste_werte)) #A_numerisch = sp.Matrix(self.func_A0(*liste_werte))
A_numerisch = np.asarray(self.func_A0(*liste_werte), dtype=float) A_numerisch = np.asarray(self.func_A0(*liste_werte), dtype=float)
Export.matrix_to_csv(r"Zwischenergebnisse\Jacobi_Matrix_Numerisch_Iteration0.csv", liste_unbekannte, Export.matrix_to_csv(fr"Zwischenergebnisse\{iterationsnummer}Jacobi_Matrix_Numerisch_Iteration0.csv", liste_unbekannte,
liste_zeilenbeschriftungen_gesamt, A_numerisch, "Beobachtung") liste_zeilenbeschriftungen_gesamt, A_numerisch, "Beobachtung")
condA = float(np.linalg.cond(A_numerisch))
rankA = int(np.linalg.matrix_rank(A_numerisch))
Export.matrix_to_csv(
fr"Zwischenergebnisse\{iterationsnummer}_Jacobi_Matrix_Stats.csv",
[""],
["condA", "rankA"],
np.array([[condA], [rankA]], dtype=float),
"Wert"
)
return A_numerisch return A_numerisch
else: else:
print("Koordinaten noch nicht implementiert!") print("Koordinaten noch nicht implementiert!")
@@ -543,7 +568,7 @@ class FunktionalesModell:
return beobachtungsvektor_naeherung_symbolisch return beobachtungsvektor_naeherung_symbolisch
def beobachtungsvektor_naeherung_numerisch_iteration0(self, liste_beobachtungsvektor_symbolisch, beobachtungsvektor_naeherung_symbolisch): def beobachtungsvektor_naeherung_numerisch_iteration0(self, liste_beobachtungsvektor_symbolisch, beobachtungsvektor_naeherung_symbolisch, iterationsnummer=0):
#beobachtungsvektor_naeherung_numerisch_iteration0 = beobachtungsvektor_naeherung_symbolisch.xreplace(self.substitutionen_dict) #beobachtungsvektor_naeherung_numerisch_iteration0 = beobachtungsvektor_naeherung_symbolisch.xreplace(self.substitutionen_dict)
if self.func_beob0 is None: if self.func_beob0 is None:
#self.liste_symbole_lambdify = sorted(self.substitutionen_dict.keys(), key=lambda s: str(s)) #self.liste_symbole_lambdify = sorted(self.substitutionen_dict.keys(), key=lambda s: str(s))
@@ -559,7 +584,7 @@ class FunktionalesModell:
beobachtungsvektor_naeherung_numerisch_iteration0 = np.asarray(self.func_beob0(*liste_werte), beobachtungsvektor_naeherung_numerisch_iteration0 = np.asarray(self.func_beob0(*liste_werte),
dtype=float).reshape(-1, 1) dtype=float).reshape(-1, 1)
Export.matrix_to_csv(r"Zwischenergebnisse\Beobachtungsvektor_Näherung_Numerisch_Iteration0.csv", [""], Export.matrix_to_csv(fr"Zwischenergebnisse\{iterationsnummer}_Beobachtungsvektor_Näherung_Numerisch_Iteration0.csv", [""],
liste_beobachtungsvektor_symbolisch, beobachtungsvektor_naeherung_numerisch_iteration0, liste_beobachtungsvektor_symbolisch, beobachtungsvektor_naeherung_numerisch_iteration0,
"Beobachtungsvektor") "Beobachtungsvektor")
@@ -571,23 +596,29 @@ class FunktionalesModell:
"Unbekanntenvektor") "Unbekanntenvektor")
return(unbekanntenvektor_symbolisch) return(unbekanntenvektor_symbolisch)
def unbekanntenvektor_numerisch(self, liste_unbekanntenvektor_symbolisch, unbekanntenvektor_symbolisch, dX_Vektor = None, unbekanntenvektor_neumerisch_vorherige_Iteration = None): def unbekanntenvektor_numerisch(self, liste_unbekanntenvektor_symbolisch, unbekanntenvektor_symbolisch, dX_Vektor = None, unbekanntenvektor_neumerisch_vorherige_Iteration = None, iterationsnummer=0):
if not hasattr(self, "liste_unbekanntenvektor_symbolisch"): self.liste_unbekanntenvektor_symbolisch = liste_unbekanntenvektor_symbolisch
self.liste_unbekanntenvektor_symbolisch = liste_unbekanntenvektor_symbolisch
#if not hasattr(self, "liste_unbekanntenvektor_symbolisch"):
# self.liste_unbekanntenvektor_symbolisch = liste_unbekanntenvektor_symbolisch
if dX_Vektor is None and unbekanntenvektor_neumerisch_vorherige_Iteration is None: if dX_Vektor is None and unbekanntenvektor_neumerisch_vorherige_Iteration is None:
#unbekanntenvektor_numerisch = unbekanntenvektor_symbolisch.xreplace(self.substitutionen_dict) #unbekanntenvektor_numerisch = unbekanntenvektor_symbolisch.xreplace(self.substitutionen_dict)
if self.func_u0 is None: #if self.func_u0 is None:
self.func_u0 = sp.lambdify( # self.func_u0 = sp.lambdify(
self.liste_symbole_lambdify, # self.liste_symbole_lambdify,
unbekanntenvektor_symbolisch, # unbekanntenvektor_symbolisch,
modules="numpy", # modules="numpy",
cse=True # cse=True
) # )
unbekanntenvektor_numerisch = np.asarray(
[[float(self.substitutionen_dict[sym])] for sym in self.liste_unbekanntenvektor_symbolisch],
dtype=float
).reshape(-1, 1)
liste_werte = [self.substitutionen_dict[s] for s in self.liste_symbole_lambdify] #liste_werte = [self.substitutionen_dict[s] for s in self.liste_symbole_lambdify]
#unbekanntenvektor_numerisch = sp.Matrix(self.func_u0(*liste_werte)) #unbekanntenvektor_numerisch = sp.Matrix(self.func_u0(*liste_werte))
unbekanntenvektor_numerisch = np.asarray(self.func_u0(*liste_werte), dtype=float).reshape(-1, 1) #unbekanntenvektor_numerisch = np.asarray(self.func_u0(*liste_werte), dtype=float).reshape(-1, 1)
else: else:
@@ -595,38 +626,57 @@ class FunktionalesModell:
unbekanntenvektor_neumerisch_vorherige_Iteration = np.asarray( unbekanntenvektor_neumerisch_vorherige_Iteration = np.asarray(
unbekanntenvektor_neumerisch_vorherige_Iteration, dtype=float).reshape(-1, 1) unbekanntenvektor_neumerisch_vorherige_Iteration, dtype=float).reshape(-1, 1)
dX_Vektor = np.asarray(dX_Vektor, dtype=float).reshape(-1, 1) dX_Vektor = np.asarray(dX_Vektor, dtype=float).reshape(-1, 1)
unbekanntenvektor_numerisch = unbekanntenvektor_neumerisch_vorherige_Iteration + dX_Vektor unbekanntenvektor_numerisch = unbekanntenvektor_neumerisch_vorherige_Iteration + dX_Vektor
self.substitutionen_dict = self.dict_substitutionen_uebergeordnetes_system(unbekanntenvektor_numerisch) self.substitutionen_dict = self.dict_substitutionen_uebergeordnetes_system(unbekanntenvektor_numerisch)
Export.matrix_to_csv(r"Zwischenergebnisse\Unbekanntenvektor_Numerisch_Iteration0.csv", [""], Export.matrix_to_csv(fr"Zwischenergebnisse\{iterationsnummer}_Unbekanntenvektor_Numerisch_Iteration0.csv", [""],
liste_unbekanntenvektor_symbolisch, unbekanntenvektor_numerisch, liste_unbekanntenvektor_symbolisch, unbekanntenvektor_numerisch,
"Unbekanntenvektor") "Unbekanntenvektor")
return unbekanntenvektor_numerisch return unbekanntenvektor_numerisch
def unbekanntenvektor_numerisch_to_dict_unbekanntenvektor(self, liste_unbekanntenvektor_symbolisch, unbekanntenvektor_numerisch): def unbekanntenvektor_numerisch_to_dict_unbekanntenvektor(self, liste_unbekanntenvektor_symbolisch, unbekanntenvektor_numerisch):
dict_unbekanntenvektor_numerisch = {} dict_unbekanntenvektor_numerisch = {}
index = 0 #index = 0
unbekanntenvektor_numerisch = np.asarray(unbekanntenvektor_numerisch, dtype=float).reshape(-1, 1) unbekanntenvektor_numerisch = np.asarray(unbekanntenvektor_numerisch, dtype=float).reshape(-1, 1)
for symbol in liste_unbekanntenvektor_symbolisch: idx = {str(sym): i for i, sym in enumerate(liste_unbekanntenvektor_symbolisch)}
name = str(symbol)
if not name.startswith("X"): punktnummern = []
for sym in liste_unbekanntenvektor_symbolisch:
name = str(sym)
if name.startswith("X"):
pn = name[1:]
if pn not in punktnummern:
punktnummern.append(pn)
dict_koordinaten = {}
for pn in punktnummern:
iX = idx.get(f"X{pn}", None)
iY = idx.get(f"Y{pn}", None)
iZ = idx.get(f"Z{pn}", None)
if iX is None or iY is None or iZ is None:
continue continue
punktnummer = str(name[1:]) dict_koordinaten[pn] = sp.Matrix([
float(unbekanntenvektor_numerisch[iX, 0]),
dict_unbekanntenvektor_numerisch[punktnummer] = sp.Matrix([ float(unbekanntenvektor_numerisch[iY, 0]),
float(unbekanntenvektor_numerisch[index, 0]), float(unbekanntenvektor_numerisch[iZ, 0]),
float(unbekanntenvektor_numerisch[index + 1, 0]),
float(unbekanntenvektor_numerisch[index + 2, 0])
]) ])
index += 3
return dict_unbekanntenvektor_numerisch #dict_unbekanntenvektor_numerisch[punktnummer] = sp.Matrix([
# float(unbekanntenvektor_numerisch[index, 0]),
# float(unbekanntenvektor_numerisch[index + 1, 0]),
# float(unbekanntenvektor_numerisch[index + 2, 0])
#])
#index += 3
return dict_koordinaten
def berechnung_dl(self, beobachtungsvektor_numerisch, beobachtungsvektor_naeherung_numerisch, def berechnung_dl(self, beobachtungsvektor_numerisch, beobachtungsvektor_naeherung_numerisch,
liste_beobachtungsvektor_symbolisch=None): liste_beobachtungsvektor_symbolisch=None, iterationsnummer=0):
dl = beobachtungsvektor_numerisch - beobachtungsvektor_naeherung_numerisch dl = beobachtungsvektor_numerisch - beobachtungsvektor_naeherung_numerisch
dl = np.asarray(dl, dtype=float) dl = np.asarray(dl, dtype=float)
@@ -637,6 +687,14 @@ class FunktionalesModell:
if "_R_" in str(name): if "_R_" in str(name):
dl[i] = np.arctan2(np.sin(dl[i]), np.cos(dl[i])) dl[i] = np.arctan2(np.sin(dl[i]), np.cos(dl[i]))
Export.matrix_to_csv(
fr"Zwischenergebnisse\{iterationsnummer}_dl.csv",
[""],
liste_beobachtungsvektor_symbolisch,
dl.reshape(-1, 1),
"dl"
)
return dl return dl
def dict_substitutionen_uebergeordnetes_system(self, unbekanntenvektor_aus_iteration = None): def dict_substitutionen_uebergeordnetes_system(self, unbekanntenvektor_aus_iteration = None):
@@ -661,8 +719,18 @@ class FunktionalesModell:
dict_koordinaten_xyz_kopie = {pn: [v[0], v[1], v[2]] for pn, v in dict_koordinaten.items()} dict_koordinaten_xyz_kopie = {pn: [v[0], v[1], v[2]] for pn, v in dict_koordinaten.items()}
dict_koordinaten_B_L = berechnungen.geometrische_breite_laenge(dict_koordinaten_xyz_kopie) dict_koordinaten_B_L = berechnungen.geometrische_breite_laenge(dict_koordinaten_xyz_kopie)
punktnummern_niv = set()
for beobachtungenID, pn_sp, pn_zp, niv_dh, niv_strecke, niv_anz_standpkte in liste_beobachtungen_nivellemente:
punktnummern_niv.add(str(pn_sp).strip())
punktnummern_niv.add(str(pn_zp).strip())
dict_koordinaten_niv = {}
for pn in punktnummern_niv:
if pn in dict_koordinaten:
dict_koordinaten_niv[pn] = dict_koordinaten[pn]
dict_koordinaten_utm = self.trafos.ecef_to_utm( dict_koordinaten_utm = self.trafos.ecef_to_utm(
dict_koordinaten, dict_koordinaten_niv,
self.pfad_tif_quasigeoidundolation) self.pfad_tif_quasigeoidundolation)
substitutionen = {} substitutionen = {}

View File

@@ -6,6 +6,8 @@ from pathlib import Path
import shutil import shutil
from pyproj import CRS, Transformer, datadir from pyproj import CRS, Transformer, datadir
import numpy as np import numpy as np
from pyproj.exceptions import ProjError
from pyproj import CRS, Transformer
class Transformationen: class Transformationen:
@@ -359,6 +361,8 @@ class Transformationen:
allow_ballpark=False, allow_ballpark=False,
) )
tr_geo = Transformer.from_crs(CRS.from_epsg(4936), CRS.from_epsg(4979), always_xy=True)
dict_koordinaten_utm = {} dict_koordinaten_utm = {}
for punktnummer, koordinate in dict_koordinaten.items(): for punktnummer, koordinate in dict_koordinaten.items():
werte = [] werte = []
@@ -398,7 +402,16 @@ class Transformationen:
X, Y, Z = werte[0], werte[1], werte[2] X, Y, Z = werte[0], werte[1], werte[2]
E, N, H = tr.transform(X, Y, Z) try:
E, N, H = tr.transform(X, Y, Z, errcheck=True)
except ProjError as e:
lon, lat, h_ell = tr_geo.transform(X, Y, Z, errcheck=True)
raise ProjError(
f"transform error (outside grid) | pn={punktnummer} | "
f"X,Y,Z={X},{Y},{Z} | lon/lat={lon},{lat} | h_ell={h_ell} | {e}"
)
E, N, H = tr.transform(X, Y, Z, errcheck=True)
# Runden, weil ansonsten aufgrund begrenzter Rechenkapazität falsche Werte Resultieren # Runden, weil ansonsten aufgrund begrenzter Rechenkapazität falsche Werte Resultieren
dict_koordinaten_utm[punktnummer] = (round(E, 8), round(N, 8), round(H, 8)) dict_koordinaten_utm[punktnummer] = (round(E, 8), round(N, 8), round(H, 8))
return dict_koordinaten_utm return dict_koordinaten_utm

View File

@@ -39,7 +39,7 @@ class Zuverlaessigkeit:
def globaltest(r_gesamt, sigma0_apost, sigma0_apriori, alpha): def globaltest(r_gesamt, sigma0_apost, sigma0_apriori, alpha):
T_G = (sigma0_apost ** 2) / (sigma0_apriori ** 2) T_G = (sigma0_apost ** 2) / (sigma0_apriori ** 2)
F_krit = stats.f.ppf(1 - alpha, r_gesamt, 10 ** 9) F_krit = stats.f.ppf(1 - alpha, r_gesamt, 10 ** 9)
H0 = T_G <= F_krit H0 = T_G < F_krit
if H0: if H0:
interpretation = ( interpretation = (
@@ -72,10 +72,17 @@ class Zuverlaessigkeit:
ri = np.asarray(ri, float).reshape(-1) ri = np.asarray(ri, float).reshape(-1)
labels = list(labels) labels = list(labels)
# Grobfehlerabschätzung:
ri_ = np.where(ri == 0, np.nan, ri)
GF = -v / ri_
# 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(s0_apost) * np.sqrt(qv)
# Normierte Verbesserung NV
NV = np.abs(v) / s_vi
# Quantile k und kA (zweiseitig), # Quantile k und kA (zweiseitig),
k = float(norm.ppf(1 - alpha / 2)) k = float(norm.ppf(1 - alpha / 2))
kA = float(norm.ppf(1 - beta)) # (Testmacht 1-β) kA = float(norm.ppf(1 - beta)) # (Testmacht 1-β)
@@ -83,22 +90,10 @@ class Zuverlaessigkeit:
# Nichtzentralitätsparameter δ0 # Nichtzentralitätsparameter δ0
nzp = k + kA nzp = k + kA
# Normierte Verbesserung NV
NV = np.abs(v) / s_vi
# Grenzen für v_i
v_grenz = k * s_vi
v_min = -v_grenz
v_max = v_grenz
# Grobfehlerabschätzung:
ri_safe = np.where(ri == 0, np.nan, ri)
GF = -v / ri_safe
# Grenzwert für die Aufdeckbarkeit eines GF (GRZW) # Grenzwert für die Aufdeckbarkeit eines GF (GRZW)
GRZW_i = (s_vi / ri_safe) * k GRZW_i = (s_vi / ri_) * nzp
auffaellig = NV > k auffaellig = NV > nzp
Lokaltest_innere_Zuv = pd.DataFrame({ Lokaltest_innere_Zuv = pd.DataFrame({
"Beobachtung": labels, "Beobachtung": labels,
@@ -108,59 +103,11 @@ class Zuverlaessigkeit:
"k": k, "k": k,
"NV_i": NV, "NV_i": NV,
"auffaellig": auffaellig, "auffaellig": auffaellig,
"v_min": v_min,
"v_max": v_max,
"GF_i": GF, "GF_i": GF,
"GRZW_v": v_grenz, # = k*s_vi "GRZW_i": GRZW_i,
"GRZW_i": GRZW_i, # = (s_vi/r_i)*k
"alpha": alpha, "alpha": alpha,
"beta": beta, "beta": beta,
"kA": kA, "kA": kA,
"δ0": nzp, "δ0": nzp,
}) })
return Lokaltest_innere_Zuv return Lokaltest_innere_Zuv
def EinflussPunktlage(df_lokaltest):
df = df_lokaltest.copy()
r = df["r_i"].astype(float).to_numpy()
GF = df["GF_i"].astype(float).to_numpy()
nzp = df["δ0"].astype(float).to_numpy()
EF = np.sqrt((1 - r) / r) * nzp
EP = (1 - r) * GF
df["δ0"] = nzp
df["EF_i"] = EF
df["EP_i"] = EP
EinflussPunktlage = df[["Beobachtung", "r_i", "GF_i", "EF_i", "EP_i", "δ0", "alpha", "beta"]]
return EinflussPunktlage
def aeussere_zuverlaessigkeit_EF(Qxx, A, P, s0_apost, GRZW, labels):
Qxx = np.asarray(Qxx, float)
A = np.asarray(A, float)
P = np.asarray(P, float)
GRZW = np.asarray(GRZW, float).reshape(-1)
labels = list(labels)
B = Qxx @ (A.T @ P)
EF = np.empty_like(GRZW, dtype=float)
# Für jede Beobachtung i: ∇x_i = B[:,i] * GRZW_i
# EF_i^2 = (GRZW_i^2 * B_i^T Qxx^{-1} B_i) / s0^2
for i in range(len(GRZW)):
bi = B[:, i] # (u,)
y = np.linalg.solve(Qxx, bi) # = Qxx^{-1} bi
EF2 = (GRZW[i] ** 2) * float(bi @ y) / (float(s0_apost) ** 2)
EF[i] = np.sqrt(EF2)
df = pd.DataFrame({
"Beobachtung": labels,
"GRZW_i": GRZW,
"EF_i": EF
})
return df

View File

@@ -19,7 +19,7 @@ def ausgleichung_global(A, dl, Q_ext):
n = A.T @ P @ dl n = A.T @ P @ dl
# 3) Zuschlagsvektor dx und Unbekanntenvektor x # 3) Zuschlagsvektor dx und Unbekanntenvektor x
dx = np.linalg.inv(N) @ n dx = np.linalg.solve(N, n)
# 4) Residuenvektor v # 4) Residuenvektor v
v = A @ dx - dl v = A @ dx - dl

View File

@@ -241,7 +241,16 @@ class StochastischesModell:
if stabw_apriori_konstant is not None: if stabw_apriori_konstant is not None:
substitutionen[sp.Symbol(f"stabw_apriori_konstant_{beobachtungsart_kurz}_{instrumenteID}")] = float(stabw_apriori_konstant) substitutionen[sp.Symbol(f"stabw_apriori_konstant_{beobachtungsart_kurz}_{instrumenteID}")] = float(stabw_apriori_konstant)
if stabw_apriori_streckenprop is not None: if stabw_apriori_streckenprop is not None:
substitutionen[sp.Symbol(f"stabw_apriori_streckenprop_{beobachtungsart_kurz}_{instrumenteID}")] = float(stabw_apriori_streckenprop) wert = float(stabw_apriori_streckenprop)
if beobachtungsart_kurz == "niv":
wert = wert / 1000.0
substitutionen[sp.Symbol(f"stabw_apriori_streckenprop_{beobachtungsart_kurz}_{instrumenteID}")] = wert
# --- DEBUG NIV Genauigkeiten (einmalig) ---
for k, v in substitutionen.items():
ks = str(k)
if "stabw_apriori_streckenprop_niv_" in ks or "stabw_apriori_konstant_niv_" in ks:
print("DEBUG", ks, "=", v)
for instrumenteID, wert in dict_konstante_sd.items(): for instrumenteID, wert in dict_konstante_sd.items():
substitutionen[sp.Symbol(f"stabw_apriori_konstant_SD_{instrumenteID}")] = float(wert) substitutionen[sp.Symbol(f"stabw_apriori_konstant_SD_{instrumenteID}")] = float(wert)