Files
guadaloop_lev_control/sensor/analogFitter-Logistic5Parameters.py
2025-11-15 13:13:07 -06:00

70 lines
2.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
# --- Load CSV ---
data = pd.read_csv(r'C:\Users\k28ad\OneDrive\Documents\sensor\Sensor3DataNew.csv')
x = data["x"].values
# Stack them into a 2D array (shape: 5 × 100)
# stacked = np.column_stack((data["y"].values, data["y2"].values, data["y3"].values, data["y4"].values, data["y5"].values))
# Take the average across the 5 columns for each row
# y = np.mean(data["y"], axis=1)
# print(y)
y = data["y"].values
# --- Define 5-parameter logistic function ---
def logistic_5pl(x, A, K, B, C, nu):
# Clip to avoid overflow in exp for large values
z = -B * (x - C)
z = np.clip(z, -500, 500)
return A + (K - A) / (1.0 + np.exp(z))**(1/nu)
# --- Initial parameter guesses ---
A0 = np.min(y) # lower asymptote
K0 = np.max(y) # upper asymptote
B0 = 1.0 # slope
C0 = np.median(x) # inflection point
nu0 = 1.0 # asymmetry (1 = symmetric, same as 4PL)
p0 = [A0, K0, B0, C0, nu0]
# --- Fit the curve ---
params, covariance = curve_fit(
logistic_5pl, x, y, p0=p0, maxfev=20000,
bounds=([-np.inf, -np.inf, 0, -np.inf, 0.1], [np.inf, np.inf, np.inf, np.inf, 10])
)
A_fit, K_fit, B_fit, C_fit, nu_fit = params
print("Fitted parameters:")
print(f"A = {A_fit}")
print(f"K = {K_fit}")
print(f"B = {B_fit}")
print(f"C = {C_fit}")
print(f"nu = {nu_fit}")
# --- Predicted values ---
y_pred = logistic_5pl(x, *params)
# --- Goodness of fit (R²) ---
residuals = y - y_pred
ss_res = np.sum(residuals**2)
ss_tot = np.sum((y - np.mean(y))**2)
r_squared = 1 - (ss_res / ss_tot)
print(f"\nGoodness of fit: R² = {r_squared:.6f}")
# --- Plot ---
x_fit = np.linspace(min(x), max(x), 400)
y_fit = logistic_5pl(x_fit, *params)
y_pred = logistic_5pl(x, *params)
plt.figure(figsize=(8, 5))
plt.scatter(x, y, label="Data", color="blue")
plt.plot(x_fit, y_fit, 'r-', label="5PL Fit")
plt.title("5-Parameter Logistic Fit")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
plt.grid(True, linestyle="--", alpha=0.5)
plt.show()