code: def sample_size_necessary_under_cph(
      power,
      ratio_of_participants,
      p_exp,
      p_con,
      postulated_hazard_ratio,
      alpha=0.05,
  ):
      """
      This computes the sample size for needed power to compare two groups under a Cox
      Proportional Hazard model.
  
      Parameters
      ----------
  
      power : float
          power to detect the magnitude of the hazard ratio as small as that specified by postulated_hazard_ratio.
      ratio_of_participants: ratio of participants in experimental group over control group.
  
      p_exp : float
          probability of failure in experimental group over period of study.
  
      p_con : float
          probability of failure in control group over period of study
  
      postulated_hazard_ratio : float
          the postulated hazard ratio
  
      alpha : float, optional (default=0.05)
          type I error rate
  
  
      Returns
      -------
  
      n_exp : integer
          the samples sizes need for the experiment to achieve desired power
  
      n_con : integer
          the samples sizes need for the control group to achieve desired power
  
  
      Examples
      --------
      .. code:: python
  
          from lifelines.statistics import sample_size_necessary_under_cph
  
          desired_power = 0.8
          ratio_of_participants = 1.
          p_exp = 0.25
          p_con = 0.35
          postulated_hazard_ratio = 0.7
          n_exp, n_con = sample_size_necessary_under_cph(desired_power, ratio_of_participants, p_exp, p_con, postulated_hazard_ratio)
          # (421, 421)
  
      References
      -----------
      https://cran.r-project.org/web/packages/powerSurvEpi/powerSurvEpi.pdf
  
      See Also
      --------
      power_under_cph
      """
  
      def z(p):
          return stats.norm.ppf(p)
  
      m = (
          1.0
          / ratio_of_participants
          * (
              (ratio_of_participants * postulated_hazard_ratio + 1.0)
              / (postulated_hazard_ratio - 1.0)
          )
          ** 2
          * (z(1.0 - alpha / 2.0) + z(power)) ** 2
      )
  
      n_exp = (
          m
          * ratio_of_participants
          / (ratio_of_participants * p_exp + p_con)
      )
      n_con = m / (ratio_of_participants * p_exp + p_con)
  
      return int(np.ceil(n_exp)), int(np.ceil(n_con))
  
imports: from itertools import combinations
  import warnings
  import numpy
  from scipy import stats
  import pandas
  from lifelines import utils
  from lifelines.utils import group_survival_table_from_events, string_rjustify, format_p_value, format_floats, interpolate_at_times_and_return_pandas, _expected_value_of_survival_up_to_t, _expected_value_of_survival_squared_up_to_t
  from lifelines import KaplanMeierFitter
label_desc: Use image node_id 1 for calling a global function with example usage: sample_size_necessary_under_cph(power, ratio_of_participants, p_exp, p_con, postulated_hazard_ratio, alpha) and returns: int,  int, stats