class_docstr: This class implements fitting Cox's time-varying proportional hazard model:
  
      .. math::  h(t|x(t)) = h_0(t)\exp((x(t)-\overline{x})'\beta)
  
  Parameters
  ----------
  alpha: float, optional (default=0.05)
     the level in the confidence intervals.
  penalizer: float, optional
      the coefficient of an L2 penalizer in the regression
  
  Attributes
  ----------
  params_ : Series
      The estimated coefficients. Changed in version 0.22.0: use to be ``.hazards_``
  hazard_ratios_ : Series
      The exp(coefficients)
  confidence_intervals_ : DataFrame
      The lower and upper confidence intervals for the hazard coefficients
  event_observed: Series
      The event_observed variable provided
  weights: Series
      The event_observed variable provided
  variance_matrix_ : DataFrame
      The variance matrix of the coefficients
  strata: list | str
      the strata provided
  standard_errors_: Series
      the standard errors of the estimates
  baseline_cumulative_hazard_: DataFrame
  baseline_survival_: DataFrame
class_docstr_tok: ["This","class","implements","fitting","Cox","'s","time-varying","proportional","hazard","model",":","..","math",":",":","h","(","t|x","(","t",")",")","=","h_0","(","t",")","\\exp","(","(","x","(","t",")","-\\overline","{","x","}",")","'\\beta",")","Parameters","--","--","--","--","--","alpha",":","float",",","optional","(","default=0.05",")","the","level","in","the","confidence","intervals",".","penalizer",":","float",",","optional","the","coefficient","of","an","L2","penalizer","in","the","regression","Attributes","--","--","--","--","--","params_",":","Series","The","estimated","coefficients",".","Changed","in","version","0.22.0",":","use","to","be","``",".hazards_","``","hazard_ratios_",":","Series","The","exp","(","coefficients",")","confidence_intervals_",":","DataFrame","The","lower","and","upper","confidence","intervals","for","the","hazard","coefficients","event_observed",":","Series","The","event_observed","variable","provided","weights",":","Series","The","event_observed","variable","provided","variance_matrix_",":","DataFrame","The","variance","matrix","of","the","coefficients","strata",":","list","|","str","the","strata","provided","standard_errors_",":","Series","the","standard","errors","of","the","estimates","baseline_cumulative_hazard_",":","DataFrame","baseline_survival_",":","DataFrame"]
docstr: Calculates the first and second order vector differentials, with respect to beta.
  
  Returns
  -------
  hessian: (d, d) numpy array,
  gradient: (1, d) numpy array
  log_likelihood: float
docstr_tok: ["Calculates","the","first","and","second","order","vector","differentials",",","with","respect","to","beta",".","Returns","--","--","--","-","hessian",":","(","d",",","d",")","numpy","array",",","gradient",":","(","1",",","d",")","numpy","array","log_likelihood",":","float"]
code: def _get_gradients(
      X, events, start, stop, weights, beta
  ):  # pylint: disable=too-many-locals
      """
      Calculates the first and second order vector differentials, with respect to beta.
  
      Returns
      -------
      hessian: (d, d) numpy array,
      gradient: (1, d) numpy array
      log_likelihood: float
      """
  
      _, d = X.shape
      hessian = np.zeros((d, d))
      gradient = np.zeros(d)
      log_lik = 0
      unique_death_times = np.unique(stop[events])
  
      for t in unique_death_times:
          # I feel like this can be made into some tree-like structure
          ix = (start < t) & (t <= stop)
  
          X_at_t = X[ix]
          weights_at_t = weights[ix]
          stops_events_at_t = stop[ix]
          events_at_t = events[ix]
  
          phi_i = weights_at_t * np.exp(np.dot(X_at_t, beta))
          phi_x_i = phi_i[:, None] * X_at_t
          phi_x_x_i = np.dot(X_at_t.T, phi_x_i)
  
          # Calculate sums of Risk set
          risk_phi = array_sum_to_scalar(phi_i)
          risk_phi_x = matrix_axis_0_sum_to_1d_array(phi_x_i)
          risk_phi_x_x = phi_x_x_i
  
          # Calculate the sums of Tie set
          deaths = events_at_t & (stops_events_at_t == t)
  
          tied_death_counts = array_sum_to_scalar(
              deaths.astype(int)
          )  # should always at least 1. Why? TODO
  
          xi_deaths = X_at_t[deaths]
  
          x_death_sum = matrix_axis_0_sum_to_1d_array(
              weights_at_t[deaths, None] * xi_deaths
          )
  
          weight_count = array_sum_to_scalar(weights_at_t[deaths])
          weighted_average = weight_count / tied_death_counts
  
          #
          # This code is near identical to the _batch algorithm in CoxPHFitter. In fact, see _batch for comments.
          #
  
          if tied_death_counts > 1:
              # A good explanation for how Efron handles ties. Consider three of five subjects who fail at the time.
              # As it is not known a priori that who is the first to fail, so one-third of
              # (φ1 + φ2 + φ3) is adjusted from sum_j^{5} φj after one fails. Similarly two-third
              # of (φ1 + φ2 + φ3) is adjusted after first two individuals fail, etc.
  
              # a lot of this is now in Einstein notation for performance, but see original "expanded" code here
              # https://github.com/CamDavidsonPilon/lifelines/blob/e7056e7817272eb5dff5983556954f56c33301b1/lifelines/fitters/cox_time_varying_fitter.py#L458-L490
  
              tie_phi = array_sum_to_scalar(phi_i[deaths])
              tie_phi_x = matrix_axis_0_sum_to_1d_array(phi_x_i[deaths])
              tie_phi_x_x = np.dot(
                  xi_deaths.T, phi_i[deaths, None] * xi_deaths
              )
  
              increasing_proportion = (
                  np.arange(tied_death_counts) / tied_death_counts
              )
              denom = 1.0 / (risk_phi - increasing_proportion * tie_phi)
              numer = risk_phi_x - np.outer(
                  increasing_proportion, tie_phi_x
              )
  
              a1 = np.einsum(
                  "ab, i->ab", risk_phi_x_x, denom
              ) - np.einsum(
                  "ab, i->ab",
                  tie_phi_x_x,
                  increasing_proportion * denom,
              )
          else:
              # no tensors here, but do some casting to make it easier in the converging step next.
              denom = 1.0 / np.array([risk_phi])
              numer = risk_phi_x
              a1 = risk_phi_x_x * denom
  
          summand = numer * denom[:, None]
          a2 = summand.T.dot(summand)
  
          gradient = (
              gradient + x_death_sum - weighted_average * summand.sum(0)
          )
          log_lik = (
              log_lik
              + np.dot(x_death_sum, beta)
              + weighted_average * np.log(denom).sum()
          )
          hessian = hessian + weighted_average * (a2 - a1)
  
      return hessian, gradient, log_lik
  
imports: from datetime import datetime
  import warnings
  import time
  from typing import Optional
  import numpy
  import pandas
  from scipy import stats
  from numpy.linalg import norm, inv
  from numpy import sum
  from scipy.linalg import solve, LinAlgError
  from autograd import elementwise_grad
  from autograd import numpy
  from lifelines.fitters import SemiParametricRegressionFitter
  from lifelines.fitters.mixins import ProportionalHazardMixin
  from lifelines.utils.printer import Printer
  from lifelines.statistics import _chisq_test_p_value, StatisticalResult
  from lifelines.exceptions import ConvergenceError, ConvergenceWarning
  from lifelines.utils import _get_index, _to_list, check_for_numeric_dtypes_or_raise, check_low_var, check_complete_separation_low_variance, check_for_immediate_deaths, check_for_instantaneous_events_at_time_zero, check_for_instantaneous_events_at_death_time, check_for_nonnegative_intervals, pass_for_numeric_dtypes_or_raise_array, inv_normal_cdf, normalize, StepSizer, check_nans_or_infs, string_rjustify, coalesce
  from lifelines import utils
label_desc: Use image node_id 11 for calling the CoxTimeVaryingFitter obj's underlying member method code with example usage: obj._get_gradients(X, events, start, stop, weights, beta) and returns: hessian,  gradient,  log_lik