def __calc_tau__(self, beta, gamma, theta, data, verbose=False):
        # using a nonlinear solver (fsolve)
        # ToDo(1): Add derivative of gap (fprime)
        # ToDo(2): Check if it is better to use args instead of lambda functions
        # ToDo(3): Check if it is better to use equation (4) of Gilardoni2007 instead of special function G

        kappa = data.CPM / data.CMR
        G1223 = lambda z: mp.meijerg([[0, 1 - 1 / gamma], []], [[0], [1, -1 / gamma]], (z ** gamma) / theta)
        gap = lambda tau: kappa + beta * tau[0] * G1223(tau[0])
        x0 = [5.84]  # from ModelPLP
        tau = opt.fsolve(gap, x0, args=(), fprime=None)

        if verbose:
            (tau, info, flag, msg) = opt.fsolve(gap, x0, args=(), fprime=None, full_output=True)
            print('> calc tau')
            print('  message: %s after %d iterations.' % (msg[:-1], info['nfev']))
            print('  x0  = %f' % x0[0])
            print('  tau = %f' % tau[0])
            print('  gap = %e' % gap(tau))

        return tau[0]
    def __gap_params__(self, data, beta, gamma, theta, verbose=False):
        G1112A = lambda z: mp.meijerg([[1 - 1 / gamma], []], [[0], [-1 / gamma]], (z ** gamma) / theta)
        G1112B = lambda z: mp.meijerg([[0], []], [[0], [1]], (z ** gamma) / theta)
        G1223 = lambda z: mp.meijerg([[0, 1 - 1 / gamma], []], [[0], [-1 / gamma, 1]], (z ** gamma) / theta)
        G1001 = lambda z: mp.meijerg([[], []], [[0], []], (z ** gamma) / theta)
        G1334 = lambda z: mp.meijerg([[0, 1 - 1 / gamma, 1 - 1 / gamma], []], [[0], [-1 / gamma, -1 / gamma, 1]], (z ** gamma) / theta)
        G1445 = lambda z: mp.meijerg([[0, 1 - 1 / gamma, 1 - 1 / gamma, 1 - 1 / gamma], []], [[0], [-1 / gamma, -1 / gamma, -1 / gamma, 1]], (z ** gamma) / theta)

        # gap beta
        si = 0
        for Ti in data.censorTimes:
            si += Ti * (1 - G1112A(Ti) / gamma)
        gap_beta = -si + len(data.allFailures) / beta

        # gap gamma
        si = 0
        for Ti in data.censorTimes:
            si += Ti * (mp.ln(Ti) * G1334(Ti) - G1445(Ti) / gamma)
        sij = 0
        for tij in data.allFailures:
            sij += (mp.ln(tij) * G1112B(tij)) / (1 - G1001(tij))
        gap_gamma = (beta / gamma) * si - sij

        # gap theta
        si = 0
        for Ti in data.censorTimes:
            si += Ti * G1223(Ti)
        sij = 0
        for tij in data.allFailures:
            sij += G1112B(tij) / (1 - G1001(tij))
        gap_theta = (beta * theta / gamma) * si - theta * sij

        if verbose:
            print('  gap beta  = %g' % gap_beta)
            print('  gap gamma = %g' % gap_gamma)
            print('  gap theta = %g' % gap_theta)

        return np.array([gap_beta, gap_gamma, gap_theta], dtype=float)
        def G1555(z): return mp.meijerg([[0,1-1/gamma,1-1/gamma,1-1/gamma,0], []], [[0], [-1/gamma,-1/gamma,-1/gamma,1]], (z ** gamma) / theta)

        Tij = data.allFailures
 def G1444(z): return mp.meijerg([[0,1-1/gamma,1-1/gamma,0], []], [[0], [-1/gamma,-1/gamma,1]], (z ** gamma) / theta)
 def G1555(z): return mp.meijerg([[0,1-1/gamma,1-1/gamma,1-1/gamma,0], []], [[0], [-1/gamma,-1/gamma,-1/gamma,1]], (z ** gamma) / theta)
 def G1112B(z): return mp.meijerg([[0, 0], []], [[0], [1]], (z ** gamma) / theta)
 def G1111(z): return mp.meijerg([[0], []], [[0], []], (z ** gamma) / theta)
 def G1333(z): return mp.meijerg([[0,1-1/gamma,0], []], [[0], [-1/gamma,1]], (z ** gamma) / theta)
 def G1112B(z): return mp.meijerg([[0, 0], []], [[0], [1]], (z ** gamma) / theta)
 def G1333(z): return mp.meijerg([[0,1-1/gamma,0], []], [[0], [1,-1/gamma]], (z**gamma) / theta)
 def gap(tau): return kappa + beta * tau[0] * G1333(tau[0])