I'm trying to fit a dynamic n-modal Gaussian function to some test data, but I'm having some difficulty in getting the scipy.optimize.curve_fit method to interpret my arguments properly.
from scipy.optimize import curve_fit
import numpy as np
def gaussian(x_g, mu, sigma, a):
return a * np.exp((-1 * (x_g-mu) ** 2) / (2 * sigma)**2)
def n_modal(x_n, mu_n, sigma_n, a_n):
mu_n = np.array(mu_n)
sigma_n = np.array(sigma_n)
a_n = np.array(a_n)
result = 0
for i in range(mu_n.shape[0]):
result += gaussian(x_n, mu_n[i], sigma_n[i], a_n[i])
return result
xes = np.linspace(-2*np.pi, 2*np.pi, 1000)
ys = np.sin(2*xes)
mus = np.array([-6, -4, -2, -1, 1, 2, 4, 6]).reshape((1, 8))
sigmas = np.array([1, 1, 1, 1, 1, 1, 1, 1]).reshape((1, 8))
asz = np.array([1, -1, -1, 1, -1, 1, -1, 1]).reshape((1, 8))
params = np.concatenate((mus, sigmas, asz), axis=0)
param_opt, param_cov = curve_fit(n_modal, xes, ys, p0=params)
The terminal just tells me that I'm feeding in the wrong amount of parameters, as expected, because the method probably can't figure out that the function takes a dynamic amount of parameters for mu_n, sigma_n, and a_n.
I know that I can just remake the functions with an explicit amount of variables (see below), but I want something a bit more general. What are my options?
def bimodal(x_bi, mu1, sigma1, a1, mu2, sigma2, a2):
return (gaussian(x_bi, mu1, sigma1, a1) +
gaussian(x_bi, mu2, sigma2, a2))
def trimodal(x_tri, mu1, sigma1, a1, mu2, sigma2, a2, mu3, sigma3, a3):
return (gaussian(x_tri, mu1, sigma1, a1) +
gaussian(x_tri, mu2, sigma2, a2) +
gaussian(x_tri, mu3, sigma3, a3))
def tetramodal(x_tet, mu1, sigma1, a1, mu2, sigma2, a2, mu3, sigma3, a3, mu4, sigma4, a4):
return (gaussian(x_tet, mu1, sigma1, a1) +
gaussian(x_tet, mu2, sigma2, a2) +
gaussian(x_tet, mu3, sigma3, a3) +
gaussian(x_tet, mu4, sigma4, a4))