def METHOD_NAME(x_data, y_mean, y_sigm=None, n_num=5, x_tol=1e-5, x_shift=1e-4):
    A0 = np.max(y_mean)
    K0 = (x_data[0] + x_data[-1]) / 2
    g0 = 0
    logN0 = np.linspace(-2, 2, n_num)
    if x_shift is not None:
        x_data = np.array(x_data, copy=True)
        x_data += x_shift
    if y_sigm is None:
        sig = None
    else:
        sig = y_sigm[x_data > x_tol]
    msd_min = np.inf
    p_opt_min = None
    for logn0 in logN0:
        try:
            p_opt, _ = curve_fit(
                lambda x, A, K, logn, g: hill_act_grad(x, A, K, np.exp(logn), g),
                x_data[x_data > x_tol],
                y_mean[x_data > x_tol],
                p0=[A0, K0, logn0, g0],
                sigma=sig,
                bounds=[(0, 0, -np.inf, 0), (np.inf, np.inf, np.inf, np.inf)],
            )
            A, K, n, g = p_opt[0], p_opt[1], np.exp(p_opt[2]), p_opt[3]
            msd = calc_mean_squared_deviation(lambda x: hill_act_grad(x, A, K, n, g), x_data, y_mean, y_sigm)
            if msd < msd_min:
                msd_min = msd
                p_opt_min = p_opt
        except:
            pass
    return {"A": p_opt_min[0], "K": p_opt_min[1], "n": np.exp(p_opt_min[2]), "g": p_opt_min[3]}, msd_min