def minimize_t0s(means, weights, combs):
    """Varies t0s to minimize the deviation of the gaussian means from zero.

    Parameters
    ----------
    means: numpy array of means of all PMT combinations
    weights: numpy array of weights for the squared sum
    combs: pmt combinations to use for minimization

    Returns
    -------
    opt_t0s: optimal t0 values for all PMTs

    """

    def make_quality_function(means, weights, combs):
        def quality_function(t0s):
            sq_sum = 0
            for mean, comb, weight in zip(means, combs, weights):
                sq_sum += ((mean - (t0s[comb[1]] - t0s[comb[0]])) * weight)**2
            return sq_sum

        return quality_function

    qfunc = make_quality_function(means, weights, combs)
    # t0s = np.zeros(31)
    t0s = np.random.rand(31)
    bounds = [(0, 0)] + [(-10., 10.)] * 30
    opt_t0s = optimize.minimize(qfunc, t0s, bounds=bounds)
    return opt_t0s
Varies t0s to minimize the deviation of the gaussian means from zero.

    Parameters
    ----------
    means: numpy array of means of all PMT combinations
    weights: numpy array of weights for the squared sum
    combs: pmt combinations to use for minimization

    Returns
    -------
    opt_t0s: optimal t0 values for all PMTs