code: def generate_data(n=1000):
      from scipy.optimize import root_scalar
  
      p = 0.8
      gamma2 = 1.6
      lambda2 = 0.1
      gamma1 = 3
      lambda1 = 0.1
      beta = 0.5
      X = np.random.binomial(1, 0.5, size=n)
  
      # confirm that S(5).mean() == 0.106 ✅
      # h(t) looks like graph ✅
      def S(t, x):
          return p * np.exp(
              -lambda1 * (t**gamma1) * np.exp(-x * beta * gamma1)
          ) + (1 - p) * np.exp(
              -lambda2 * (t**gamma2) * np.exp(-x * beta * gamma2)
          )
  
      T_actual = np.empty(n)
  
      for i in range(n):
          u = np.random.random()
          x = X[i]
          sol = root_scalar(lambda t: S(t, x) - u, x0=1, x1=3)
          assert sol.converged
          T_actual[i] = sol.root
  
      MAX_TIME = 5
      T_observed = np.minimum(MAX_TIME, T_actual)
      E = T_actual < MAX_TIME
      return pd.DataFrame({"E": E, "T": T_observed, "X": X})
  
file_path: lifelines/examples/crowther_royston_clements_splines.py
imports: import pandas
  from autograd import numpy
  from lifelines.fitters import ParametricRegressionFitter
  from lifelines import WeibullAFTFitter
  from lifelines.fitters.mixins import SplineFitterMixin
  from lifelines.utils.safe_exp import safe_exp
label_desc: Use image node_id 2 for calling a global function with example usage: generate_data(n) and returns: pd, unknown