Perform a 2D fit on 2D points then return parameters

   :param zxq: A list where each element is (z, transverse, charge)

def Fit(self, zxq):
        """Perform a 2D fit on 2D points then return parameters

   :param zxq: A list where each element is (z, transverse, charge)
   """
        z, trans, Q = zip(*zxq)

        assert len(trans) == len(z)
        ndf = len(z) - 3

        z = np.array(z)
        trans = np.array(trans)

        def dbexpl(t, p):
            return(p[0] - p[1] * t + p[2] * t ** 2)

        def residuals(p, data, t):
            err = data - dbexpl(t, p)
            return err

        doc = {}

        try:
            assert ndf > 0

            p0 = [1, 0, 0]  # initial guesses
            pbest = leastsq(residuals, p0, args=(trans, z), full_output=1)
            bestparams = pbest[0]
            good_of_fit = sum(pbest[2]['fvec'] ** 2)
            good_of_fit = float(good_of_fit / ndf)
            doc['params'] = list(bestparams)
            doc['gof'] = good_of_fit
        except:
            doc['gof'] = 'FAIL'
            doc['params'] = [0, 0, 0]

        return doc