This commit is contained in:
2026-01-23 21:19:23 +01:00
parent 7c1b335b1c
commit 1561eb242e
8 changed files with 36417 additions and 35865 deletions

View File

@@ -1,6 +1,6 @@
import numpy as np
import plotly.graph_objects as go
from scipy.stats import f as f_dist
from scipy.stats import f
import pandas as pd
@@ -57,99 +57,143 @@ class Genauigkeitsmaße:
def standardellipse(Qxx, s0_apost, unbekannten_liste, dim_labels=3):
@staticmethod
def standardellipse(Qxx, s0_apost, unbekannten_liste):
Qxx = np.asarray(Qxx, float)
data = []
daten = []
namen_str = [str(sym) for sym in unbekannten_liste]
n_punkte = len(unbekannten_liste) // dim_labels
punkt_ids = []
for n in namen_str:
if n.upper().startswith('X'):
punkt_ids.append(n[1:])
for i in range(n_punkte):
sym_x = str(unbekannten_liste[dim_labels * i]) # z.B. "X10009"
punkt = sym_x[1:] # -> "10009"
for pid in punkt_ids:
try:
idx_x = next(i for i, n in enumerate(namen_str) if n.upper() == f"X{pid}".upper())
idx_y = next(i for i, n in enumerate(namen_str) if n.upper() == f"Y{pid}".upper())
ix = dim_labels * i
iy = dim_labels * i + 1
qxx = Qxx[idx_x, idx_x]
qyy = Qxx[idx_y, idx_y]
qyx = Qxx[idx_y, idx_x]
# 2x2-Kofaktorblock
Qxx_ = Qxx[ix, ix]
Qyy_ = Qxx[iy, iy]
Qyx_ = Qxx[iy, ix]
# Standardabweichungen
sx = s0_apost * np.sqrt(qxx)
sy = s0_apost * np.sqrt(qyy)
sxy = (s0_apost ** 2) * qyx
# Standardabweichungen der Koordinatenkomponenten
sx = s0_apost * np.sqrt(Qxx_)
sy = s0_apost * np.sqrt(Qyy_)
sxy = (s0_apost ** 2) * Qyx_
k = np.sqrt((qxx - qyy) ** 2 + 4 * (qyx ** 2))
# k und Eigenwerte (Q_dmax, Q_dmin)
k = np.sqrt((Qxx_ - Qyy_) ** 2 + 4 * (Qyx_ ** 2))
Q_dmax = 0.5 * (Qxx_ + Qyy_ + k)
Q_dmin = 0.5 * (Qxx_ + Qyy_ - k)
# Q_dmax/min = 0.5 * (Qyy + Qxx +/- k)
q_dmax = 0.5 * (qyy + qxx + k)
q_dmin = 0.5 * (qyy + qxx - k)
# Halbachsen (Standardabweichungen entlang Hauptachsen)
s_max = s0_apost * np.sqrt(Q_dmax)
s_min = s0_apost * np.sqrt(Q_dmin)
# Halbachsen
s_max = s0_apost * np.sqrt(q_dmax)
s_min = s0_apost * np.sqrt(q_dmin)
# Richtungswinkel theta (Hauptachse) in rad:
theta_rad = 0.5 * np.arctan2(2 * Qyx_, (Qxx_ - Qyy_))
# Richtungswinkel theta in gon:
zaehler = 2 * qyx
nenner = qxx - qyy
t_grund = 0.5 * np.arctan(abs(zaehler) / abs(nenner)) * (200 / np.pi)
# in gon
theta_gon = theta_rad * (200 / np.pi)
if theta_gon < 0:
theta_gon += 200.0
# Quadrantenabfrage
if nenner > 0 and qyx > 0: # Qxx - Qyy > 0 und Qyx > 0
t_gon = t_grund # 0 - 50 gon
elif nenner < 0 and qyx > 0: # Qxx - Qyy < 0 und Qyx > 0
t_gon = 100 - t_grund # 50 - 100 gon
elif nenner < 0 and qyx < 0: # Qxx - Qyy < 0 und Qyx < 0
t_gon = 100 + t_grund # 100 - 150 gon
elif nenner > 0 and qyx < 0: # Qxx - Qyy > 0 und Qyx < 0
t_gon = 200 - t_grund # 150 - 200 gon
else:
t_gon = 0.0
data.append([
punkt,
float(sx), float(sy), float(sxy),
float(s_max), float(s_min),
float(theta_gon)
])
daten.append([
pid,
float(sx), float(sy), float(sxy),
float(s_max), float(s_min),
float(t_gon)
])
standardellipse = pd.DataFrame(data, columns=["Punkt", "σx", "σy", "σxy", "s_max", "s_min", "θ [gon]"])
except:
continue
standardellipse = pd.DataFrame(daten, columns=["Punkt", "σx", "σy", "σxy", "s_max", "s_min", "θ [gon]"])
return standardellipse
def konfidenzellipse(Qxx, s0_apost, unbekannten_liste, R, alpha=0.05):
@staticmethod
def konfidenzellipse(Qxx, s0_apost, unbekannten_liste, R, alpha):
Qxx = np.asarray(Qxx, float)
daten = []
namen_str = [str(sym) for sym in unbekannten_liste]
data = []
n_punkte = len(unbekannten_liste) // 3 # X,Y,Z je Punkt angenommen
punkt_ids = [n[1:] for n in namen_str if n.upper().startswith('X')]
k = float(np.sqrt(2.0 * f_dist.ppf(1.0 - alpha, 2, R)))
# Faktor für Konfidenzellipse (F-Verteilung)
kk = float(np.sqrt(2.0 * f.ppf(1.0 - alpha, 2, R)))
for i in range(n_punkte):
punkt = str(unbekannten_liste[3 * i])[1:] # "X10009" -> "10009"
for pid in punkt_ids:
try:
idx_x = next(i for i, n in enumerate(namen_str) if n.upper() == f"X{pid}".upper())
idx_y = next(i for i, n in enumerate(namen_str) if n.upper() == f"Y{pid}".upper())
ix = 3 * i
iy = 3 * i + 1
qxx = Qxx[idx_x, idx_x]
qyy = Qxx[idx_y, idx_y]
qyx = Qxx[idx_y, idx_x]
Qxx_ = Qxx[ix, ix]
Qyy_ = Qxx[iy, iy]
Qxy_ = Qxx[iy, ix] # = Qyx
# Standardabweichungen
sx = s0_apost * np.sqrt(qxx)
sy = s0_apost * np.sqrt(qyy)
sxy = (s0_apost ** 2) * qyx
# k für Eigenwerte
kk = np.sqrt((Qxx_ - Qyy_) ** 2 + 4 * (Qxy_ ** 2))
Q_dmax = 0.5 * (Qxx_ + Qyy_ + kk)
Q_dmin = 0.5 * (Qxx_ + Qyy_ - kk)
k = np.sqrt((qxx - qyy) ** 2 + 4 * (qyx ** 2))
# Standard-Halbachsen (1-sigma)
s_max = s0_apost * np.sqrt(Q_dmax)
s_min = s0_apost * np.sqrt(Q_dmin)
# Q_dmax/min = 0.5 * (Qyy + Qxx +/- k)
q_dmax = 0.5 * (qyy + qxx + k)
q_dmin = 0.5 * (qyy + qxx - k)
# Orientierung (Hauptachse) in gon
theta_rad = 0.5 * np.arctan2(2 * Qxy_, (Qxx_ - Qyy_))
theta_gon = theta_rad * (200 / np.pi)
if theta_gon < 0:
theta_gon += 200.0
# Halbachsen der Standardellipse
s_max = s0_apost * np.sqrt(q_dmax)
s_min = s0_apost * np.sqrt(q_dmin)
# Konfidenz-Halbachsen
a_K = k * s_max
b_K = k * s_min
# Halbachsen der Konfidenzellipse
A_K = kk * s_max
B_K = kk * s_min
data.append([punkt, float(a_K), float(b_K), float(theta_gon)])
# Richtungswinkel theta in gon:
zaehler = 2 * qyx
nenner = qxx - qyy
t_grund = 0.5 * np.arctan(abs(zaehler) / abs(nenner)) * (200 / np.pi)
# Quadrantenabfrage
if nenner > 0 and qyx > 0:
t_gon = t_grund # 0 - 50 gon
elif nenner < 0 and qyx > 0:
t_gon = 100 - t_grund # 50 - 100 gon
elif nenner < 0 and qyx < 0:
t_gon = 100 + t_grund # 100 - 150 gon
elif nenner > 0 and qyx < 0:
t_gon = 200 - t_grund # 150 - 200 gon
else:
t_gon = 0.0
daten.append([
pid,
float(sx), float(sy), float(sxy),
float(A_K), float(B_K),
float(t_gon)
])
except:
continue
konfidenzellipse = pd.DataFrame(daten, columns= ["Punkt", "σx", "σy", "σxy", "a_K", "b_K","θ [gon]"])
return konfidenzellipse
konfidenzellipsen = pd.DataFrame(data, columns=["Punkt", "a_K", "b_K", "θ [gon]"])
return konfidenzellipsen
def plot_netz_komplett_final(x_vektor, unbekannten_labels, beobachtungs_labels, Qxx, sigma0_apost,