Exemple #1
0
  /**
   * @param method
   * @param survivalInfoList
   * @param useStrata
   * @return
   */
  public static double[] process(
      CoxMethod method, ArrayList<SurvivalInfo> survivalInfoList, boolean useStrata) {
    int i, j;
    int lastone;
    int n = survivalInfoList.size();
    double deaths, denom = 0, e_denom = 0;
    double hazard;
    double temp, wtsum;
    double downwt;
    double[] time = new double[n];
    double[] status = new double[n];
    double[] strata = new double[n];
    double[] wt = new double[n];
    double[] score = new double[n];

    double[] expect = new double[survivalInfoList.size()];

    for (int p = 0; p < n; p++) {
      SurvivalInfo si = survivalInfoList.get(p);
      time[p] = si.getTime();
      status[p] = si.getStatus();
      if (useStrata) {
        strata[p] = si.getStrata();
      } else {
        strata[p] = 0;
      }
      wt[p] = si.getWeight();
      score[p] = si.getScore();
    }

    strata[n - 1] = 1; /*failsafe */
    /* Pass 1-- store the risk denominator in 'expect' */
    for (i = n - 1;
        i >= 0;
        i--) { // Error because of no bounds checking in C it is an error on the get i - 1
      //   SurvivalInfo si = survivalInfoList.get(i);

      if (strata[i] == 1) {
        denom = 0; // strata[i]
      }
      denom += score[i] * wt[i]; // score[i]*wt[i];
      if (i == 0
          || strata[i - 1] == 1
          || time[i - 1] != time[i]) // strata[i-1]==1 ||  time[i-1]!=time[i]
      {
        //   si.setResidual(denom);
        expect[i] = denom;
      } else {
        //   si.setResidual(0); //expect[i] =0;
        expect[i] = 0;
      }
    }

    /* Pass 2-- now do the work */
    deaths = 0;
    wtsum = 0;
    e_denom = 0;
    hazard = 0;
    lastone = 0;
    for (i = 0; i < n; i++) {
      //         SurvivalInfo si = survivalInfoList.get(i);
      //         SurvivalInfo sip1 = null;
      //         if (i + 1 < n) {
      //             sip1 = survivalInfoList.get(i + 1);
      //         }
      //         if (si.getResidual() != 0) {
      //             denom = si.getResidual();
      //         }
      if (expect[i] != 0) denom = expect[i];
      //         si.setResidual(status[i]);//expect[i] = status[i];
      expect[i] = status[i];

      deaths += status[i]; // status[i];
      wtsum += status[i] * wt[i]; // status[i]*wt[i];
      e_denom += score[i] * status[i] * wt[i]; // score[i]*status[i] *wt[i];
      if (strata[i] == 1 || time[i + 1] != time[i]) { // strata[i]==1 ||  time[i+1]!=time[i]
        /*last subject of a set of tied times */
        if (deaths < 2 || method == CoxMethod.Breslow) { // *method==0
          hazard += wtsum / denom;
          for (j = lastone; j <= i; j++) {
            //     SurvivalInfo sj = survivalInfoList.get(j);
            //     double res =  sj.getResidual() - score[j] * hazard;
            expect[j] -= score[j] * hazard;
            //     sj.setResidual(res); //expect[j] -= score[j]*hazard;

          }
        } else {
          temp = hazard;
          wtsum /= deaths;
          for (j = 0; j < deaths; j++) {
            downwt = j / deaths;
            hazard += wtsum / (denom - e_denom * downwt);
            temp += wtsum * (1 - downwt) / (denom - e_denom * downwt);
          }
          for (j = lastone; j <= i; j++) {
            //   SurvivalInfo sj = survivalInfoList.get(j);
            if (status[j] == 0) {
              // this appears to be an error for = - versus -=
              //   double res = -score[j] * hazard;
              expect[j] = -score[j] * hazard;
              //   sj.setResidual(res);//expect[j] = -score[j]*hazard; This appears to be an error
              // of -score vs -=
            } else {
              // double res = sj.getResidual() - score[j] * temp;
              expect[j] -= score[j] * temp;
              // expect[j] -=  score[j]* temp;
            }
          }
        }
        lastone = i + 1;
        deaths = 0;
        wtsum = 0;
        e_denom = 0;
      }
      if (strata[i] == 1) {
        hazard = 0;
      }
    }

    for (j = lastone; j < n; j++) {
      expect[j] -= score[j] * hazard;
    }

    return expect;
  }
Exemple #2
0
  /**
   * @param ci
   * @param useWeighted
   * @param robust
   * @param cluster
   * @throws Exception
   */
  public void coxphfitSCleanup(
      CoxInfo ci, boolean useWeighted, boolean robust, ArrayList<String> cluster) throws Exception {
    // Do cleanup found after coxfit6 is called in coxph.fit.S
    // infs <- abs(coxfit$u %*% var)
    // [ a1 b1] * [a1 b1]
    //           [a2 b2]
    double[][] du = new double[1][ci.u.length];
    du[0] = ci.u;
    double[] infs = Matrix.abs(Matrix.multiply(ci.u, ci.getVariance()));
    //        StdArrayIO.print(infs);

    ArrayList<CoxCoefficient> coxCoefficients =
        new ArrayList<CoxCoefficient>(ci.getCoefficientsList().values());

    for (int i = 0; i < infs.length; i++) {
      double inf = infs[i];
      double coe = coxCoefficients.get(i).getCoeff();
      if (inf > ci.eps && inf > (ci.toler * Math.abs(coe))) {
        ci.message = "Loglik converged before variable ";
      }
    }

    // sum(coef*coxfit$means)
    double sumcoefmeans = 0;
    for (CoxCoefficient cc : coxCoefficients) {
      sumcoefmeans = sumcoefmeans + cc.getCoeff() * cc.getMean();
    }

    // coxph.fit.S line 107
    // lp <- c(x %*% coef) + offset - sum(coef*coxfit$means)
    for (SurvivalInfo si : ci.survivalInfoList) {
      double offset = si.getOffset();
      double lp = 0;
      for (CoxCoefficient cc : coxCoefficients) {
        String name = cc.getName();
        double coef = cc.getCoeff();
        double value = si.getVariable(name);
        lp = lp + value * coef;
      }
      lp = lp + offset - sumcoefmeans;
      si.setLinearPredictor(lp);
      si.setScore(Math.exp(lp));

      //           System.out.println("lp score " + si.order + " " + si.time + " " + si.getWeight()
      // + " " + si.getClusterValue() + " " + lp + " " + Math.exp(lp));
    }
    //       ci.dump();
    // begin code after call to coxfit6 in coxph.fit.S
    // Compute the martingale residual for a Cox model
    // appears to be C syntax error for = - vs -=
    // (if (nullmodel) in coxph.fit
    double[] res = CoxMart.process(ci.method, ci.survivalInfoList, false);

    for (int i = 0; i < ci.survivalInfoList.size(); i++) {
      SurvivalInfo si = ci.survivalInfoList.get(i);
      si.setResidual(res[i]);
    }

    // this represents the end of coxph.fit.S code and we pickup
    // after call to fit <- fitter(X, Y, strats ....) in coxph.R

    if (robust) {
      ci.setNaiveVariance(ci.getVariance());
      double[][] temp;
      double[][] temp0;

      if (cluster != null) {

        temp = ResidualsCoxph.process(ci, ResidualsCoxph.Type.dfbeta, useWeighted, cluster);
        // # get score for null model
        //    if (is.null(init))
        //          fit2$linear.predictors <- 0*fit$linear.predictors
        //    else
        //          fit2$linear.predictors <- c(X %*% init)
        // Set score to 1

        double[] templp = new double[ci.survivalInfoList.size()];
        double[] tempscore = new double[ci.survivalInfoList.size()];
        int i = 0;
        for (SurvivalInfo si : ci.survivalInfoList) {
          templp[i] = si.getLinearPredictor();
          tempscore[i] = si.getScore();
          si.setLinearPredictor(0);
          si.setScore(1.0); // this erases stored value which isn't how the R code does it
          i++;
        }

        temp0 = ResidualsCoxph.process(ci, ResidualsCoxph.Type.score, useWeighted, cluster);

        i = 0;
        for (SurvivalInfo si : ci.survivalInfoList) {
          si.setLinearPredictor(templp[i]);
          si.setScore(tempscore[i]); // this erases stored value which isn't how the R code does it
          i++;
        }

      } else {
        temp = ResidualsCoxph.process(ci, ResidualsCoxph.Type.dfbeta, useWeighted, null);
        //     fit2$linear.predictors <- 0*fit$linear.predictors
        double[] templp = new double[ci.survivalInfoList.size()];
        double[] tempscore = new double[ci.survivalInfoList.size()];
        int i = 0;
        for (SurvivalInfo si : ci.survivalInfoList) {
          templp[i] = si.getLinearPredictor();
          tempscore[i] = si.getScore();
          si.setLinearPredictor(0);
          si.setScore(1.0);
        }
        temp0 = ResidualsCoxph.process(ci, ResidualsCoxph.Type.score, useWeighted, null);

        i = 0;
        for (SurvivalInfo si : ci.survivalInfoList) {
          si.setLinearPredictor(templp[i]);
          si.setScore(tempscore[i]); // this erases stored value which isn't how the R code does it
          i++;
        }
      }
      // fit$var<- t(temp) % * % temp
      double[][] ttemp = Matrix.transpose(temp);
      double[][] var = Matrix.multiply(ttemp, temp);
      ci.setVariance(var);
      // u<- apply(as.matrix(temp0), 2, sum)
      double[] u = new double[temp0[0].length];
      for (int i = 0; i < temp0[0].length; i++) {
        for (int j = 0; j < temp0.length; j++) {
          u[i] = u[i] + temp0[j][i];
        }
      }
      // fit$rscore <- coxph.wtest(t(temp0)%*%temp0, u, control$toler.chol)$test
      double[][] wtemp = Matrix.multiply(Matrix.transpose(temp0), temp0);
      double toler_chol = 1.818989e-12;
      //  toler_chol = ci.toler;
      WaldTestInfo wti = WaldTest.process(wtemp, u, toler_chol);
      // not giving the correct value
      ci.setRscore(wti.getTest());
    }

    if (ci.getNumberCoefficients() > 0) {
      double toler_chol = 1.818989e-12;
      //  toler_chol = ci.toler;
      double[][] b = new double[1][ci.getNumberCoefficients()];
      int i = 0;
      for (CoxCoefficient coe : ci.getCoefficientsList().values()) {
        b[0][i] = coe.getCoeff();
        i++;
      }
      ci.setWaldTestInfo(WaldTest.process(ci.getVariance(), b, toler_chol));
    }
  }
Exemple #3
0
  /** @param args the command line arguments */
  public static void main(String[] args) {
    // TODO code application logic here
    CoxR coxr = new CoxR();

    if (true) {
      try {
        InputStream is = coxr.getClass().getClassLoader().getResourceAsStream("uis-complete.txt");

        WorkSheet worksheet = WorkSheet.readCSV(is, '\t');
        ArrayList<SurvivalInfo> survivalInfoList = new ArrayList<SurvivalInfo>();
        int i = 0;
        for (String row : worksheet.getRows()) {
          double time = worksheet.getCellDouble(row, "TIME");
          double age = worksheet.getCellDouble(row, "AGE");
          double treat = worksheet.getCellDouble(row, "TREAT");
          double c = worksheet.getCellDouble(row, "CENSOR");
          int censor = (int) c;

          SurvivalInfo si = new SurvivalInfo(time, censor);
          si.setOrder(i);
          si.addContinuousVariable("AGE", age);
          si.addContinuousVariable("TREAT", treat);

          survivalInfoList.add(si);
          i++;
        }

        CoxR cox = new CoxR();
        ArrayList<String> variables = new ArrayList<String>();
        //               variables.add("AGE");

        variables.add("AGE");
        variables.add("TREAT");

        //       variables.add("TREAT:AGE");
        //  ArrayList<Integer> cluster = new ArrayList<Integer>();
        CoxInfo ci = cox.process(variables, survivalInfoList, false, true, false, false);
        System.out.println(ci);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    if (false) {

      try {

        WorkSheet worksheet =
            WorkSheet.readCSV(
                "/Users/Scooter/NetBeansProjects/AssayWorkbench/src/edu/scripps/assayworkbench/cox/uis-complete.txt",
                '\t');
        ArrayList<String> rows = worksheet.getRows();
        ArrayList<String> variables = new ArrayList<String>();
        variables.add("AGE");
        variables.add("TREAT");
        double[] time2 = new double[rows.size()];
        int[] status2 = new int[rows.size()];
        double[][] covar2 = new double[variables.size()][rows.size()];
        double[] offset2 = new double[rows.size()];
        double[] weights2 = new double[rows.size()];
        int[] strata2 = new int[rows.size()];

        for (int i = 0; i < rows.size(); i++) {
          String row = rows.get(i);
          double time = worksheet.getCellDouble(row, "TIME");
          //      double age = worksheet.getCellDouble(row, "AGE");
          //      double treat = worksheet.getCellDouble(row, "TREAT");
          double c = worksheet.getCellDouble(row, "CENSOR");
          int censor = (int) c;

          time2[i] = time;
          status2[i] = censor;
          offset2[i] = 0;
          weights2[i] = 1;
          strata2[i] = 0;

          for (int j = 0; j < variables.size(); j++) {
            String variable = variables.get(j);
            double v = worksheet.getCellDouble(row, variable);
            covar2[j][i] = v;
          }
        }
        // from coxph.control.S
        int maxiter2 = 20;
        double eps2 = 1e-9;
        double toler2 = Math.pow(eps2, .75);
        int doscale2 = 1;
        int method2 = 0;
        // toler.chol = eps ^ .75
        // toler.inf=sqrt(eps)
        // outer.max=10

        CoxR cox = new CoxR();
        //        cox.coxfit6(maxiter2, time2, status2, covar2, offset2, weights2, strata2, method2,
        // eps2, toler2, time2, doscale2);

      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
Exemple #4
0
  /**
   * @param variables
   * @param data
   * @param maxiter
   * @param method
   * @param eps
   * @param toler
   * @param beta
   * @param doscale
   * @param useStrata
   * @param useWeighted
   * @param robust
   * @param cluster
   * @return
   * @throws Exception
   */
  public CoxInfo process(
      ArrayList<String> variables,
      ArrayList<SurvivalInfo> data,
      int maxiter,
      CoxMethod method,
      double eps,
      double toler,
      double[] beta,
      int doscale,
      boolean useStrata,
      boolean useWeighted,
      boolean robust,
      boolean cluster)
      throws Exception {
    // make sure data is converted to numbers if labels are used
    SurvivalInfoHelper.categorizeData(data);
    // create variables if testing for interaction
    for (String variable : variables) {
      if (variable.indexOf(":") != -1) {
        String[] d = variable.split(":");
        SurvivalInfoHelper.addInteraction(d[0], d[1], data);
      }
    }

    Collections.sort(data);
    // Collections.reverse(data);
    CoxInfo coxInfo = new CoxInfo();
    coxInfo.setSurvivalInfoList(data);

    int i, j, k, person;
    boolean gotofinish = false;
    double cmat[][], imat[][]; /*ragged arrays covar[][], */
    double wtave;
    double a[], newbeta[];
    double a2[], cmat2[][];
    double scale[];
    double denom = 0, zbeta, risk;
    double temp, temp2;
    int ndead; /* actually, the sum of their weights */
    double newlk = 0;
    double dtime, d2;
    double deadwt; /*sum of case weights for the deaths*/
    double efronwt; /* sum of weighted risk scores for the deaths*/
    int halving; /*are we doing step halving at the moment? */
    int nrisk = 0; /* number of subjects in the current risk set */

    /* copies of scalar input arguments */
    int nused, nvar;

    /* vector inputs */
    //  double *time, *weights, *offset;
    //  int *status, *strata;

    /* returned objects */
    // double imat2[][];
    double u[], loglik[], means[];

    double sctest;
    int flag = 0;
    int iter = 0;
    // SEXP rlist, rlistnames;
    //  int nprotect;  /* number of protect calls I have issued */

    /* get local copies of some input args */
    nused = data.size(); // LENGTH(offset2);
    nvar = variables.size(); // ncols(covar2);

    //       imat2 = new double[nvar][nvar];
    //        nprotect++;
    imat = new double[nvar][nvar]; // dmatrix(REAL(imat2),  nvar, nvar);
    a = new double[nvar]; // (double *) R_alloc(2*nvar*nvar + 4*nvar, sizeof(double));
    newbeta = new double[nvar]; // a + nvar;
    a2 = new double[nvar]; // newbeta + nvar;
    scale = new double[nvar]; // a2 + nvar;
    cmat = new double[nvar][nvar]; // dmatrix(scale + nvar,   nvar, nvar);
    cmat2 = new double[nvar][nvar]; // dmatrix(scale + nvar +nvar*nvar, nvar, nvar);

    /*
     ** create output variables
     */
    //    PROTECT(beta2 = duplicate(ibeta));
    //    beta = REAL(beta2);
    //  beta = new double[nvar];
    // beta = beta2;
    //  PROTECT(means2 = allocVector(REALSXP, nvar));
    //  means = REAL(means2);
    means = new double[nvar];
    double[] sd = new double[nvar];
    double[] se = new double[nvar];

    //   means = means2;
    //   PROTECT(u2 = allocVector(REALSXP, nvar));
    //   u = REAL(u2);
    u = new double[nvar];
    //   u = u2;
    //    PROTECT(loglik2 = allocVector(REALSXP, 2));
    //    loglik = REAL(loglik2);
    loglik = new double[2];
    //   loglik = loglik2;
    //    PROTECT(sctest2 = allocVector(REALSXP, 1));
    //    sctest = REAL(sctest2);
    //        sctest = new double[1];
    //   sctest = sctest2;
    //    PROTECT(flag2 = allocVector(INTSXP, 1));
    //    flag = INTEGER(flag2);
    //        flag = new int[1];
    //     flag = flag2;
    //    PROTECT(iter2 = allocVector(INTSXP, 1));
    //    iterations = INTEGER(iter2);
    //        iterations = new int[1];
    //        iterations = iter2;
    //       nprotect += 7;

    /*
     ** Subtract the mean from each covar, as this makes the regression
     **  much more stable.
     */
    double[] time = new double[nused];
    int[] status = new int[nused];
    double[] offset = new double[nused];
    double[] weights = new double[nused];
    int[] strata = new int[nused];

    double[][] covar = new double[nvar][nused];
    ArrayList<String> clusterList = null;

    if (cluster) {
      clusterList = new ArrayList<String>();
    }
    // copy data over to local arrays to minimuze changing code
    for (person = 0; person < nused; person++) {
      SurvivalInfo si = data.get(person);
      time[person] = si.getTime();
      status[person] = si.getStatus();
      offset[person] = si.getOffset();
      if (cluster) {
        if (si.getClusterValue() == null && si.getClusterValue().length() == 0) {
          throw new Exception("Cluster value is not valid for " + si.toString());
        }
        clusterList.add(si.getClusterValue());
      }
      if (useWeighted) {
        weights[person] = si.getWeight();
      } else {
        weights[person] = 1.0;
      }
      if (useStrata) {
        strata[person] = si.getStrata();
      } else {
        strata[person] = 0;
      }
      for (i = 0; i < variables.size(); i++) {
        String variable = variables.get(i);
        covar[i][person] = si.getVariable(variable);
      }
    }

    double tempsd = 0;
    i = 0;
    for (i = 0; i < nvar; i++) {

      temp = 0;
      tempsd = 0;
      // calculate the mean sd

      for (person = 0; person < nused; person++) {

        temp += covar[i][person]; // * weights[person];
        tempsd += (covar[i][person]) * (covar[i][person]); // *weights[person] * weights[person]
      }
      temp /= nused;
      //   temp /= weightCount;
      means[i] = temp;
      tempsd /= nused;
      //  tempsd /= weightCount;
      tempsd = Math.sqrt(tempsd - temp * temp);
      sd[i] = tempsd; // standard deviation
      // subtract the mean
      for (person = 0; person < nused; person++) {
        covar[i][person] -= temp;
      }
      if (doscale == 1) {
          /* and also scale it */
        temp = 0;
        for (person = 0; person < nused; person++) {
          temp += Math.abs(covar[i][person]); // fabs
        }
        if (temp > 0) {
          temp = nused / temp; /* scaling */
        } else {
          temp = 1.0; /* rare case of a constant covariate */
        }
        scale[i] = temp;
        for (person = 0; person < nused; person++) {
          covar[i][person] *= temp;
        }
      }
    }
    if (doscale == 1) {
      for (i = 0; i < nvar; i++) {
        beta[i] /= scale[i]; /*rescale initial betas */
      }
    } else {
      for (i = 0; i < nvar; i++) {
        scale[i] = 1.0;
      }
    }

    /*
     ** do the initial iteration step
     */
    strata[nused - 1] = 1;
    loglik[1] = 0;
    for (i = 0; i < nvar; i++) {
      u[i] = 0; // u = s1
      a2[i] = 0; // a2 = a
      for (j = 0; j < nvar; j++) {
        imat[i][j] = 0; // s2
        cmat2[i][j] = 0; // a
      }
    }

    for (person = nused - 1; person >= 0; ) {
      if (strata[person] == 1) {
        nrisk = 0;
        denom = 0;
        for (i = 0; i < nvar; i++) {
          a[i] = 0;
          for (j = 0; j < nvar; j++) {
            cmat[i][j] = 0;
          }
        }
      }

      dtime = time[person];
      ndead = 0; /*number of deaths at this time point */
      deadwt = 0; /* sum of weights for the deaths */
      efronwt = 0; /* sum of weighted risks for the deaths */
      while (person >= 0 && time[person] == dtime) {
        /* walk through the this set of tied times */
        nrisk++;
        zbeta = offset[person]; /* form the term beta*z (vector mult) */
        for (i = 0; i < nvar; i++) {
          zbeta += beta[i] * covar[i][person]; // x
        }
        zbeta = coxsafe(zbeta);

        risk = Math.exp(zbeta) * weights[person]; // risk = v
        denom += risk;

        /* a is the vector of weighted sums of x, cmat sums of squares */
        for (i = 0; i < nvar; i++) {
          a[i] += risk * covar[i][person]; // a = s1
          for (j = 0; j <= i; j++) {
            cmat[i][j] += risk * covar[i][person] * covar[j][person]; // cmat = s2;
          }
        }

        if (status[person] == 1) {
          ndead++;
          deadwt += weights[person];
          efronwt += risk;
          loglik[1] += weights[person] * zbeta;

          for (i = 0; i < nvar; i++) {
            u[i] += weights[person] * covar[i][person];
          }
          if (method == CoxMethod.Efron) {
              /* Efron */
            for (i = 0; i < nvar; i++) {
              a2[i] += risk * covar[i][person];
              for (j = 0; j <= i; j++) {
                cmat2[i][j] += risk * covar[i][person] * covar[j][person];
              }
            }
          }
        }

        person--;
        if (person >= 0 && strata[person] == 1) { // added catch of person = 0 and person-- = -1
          break; /*ties don't cross strata */
        }
      }

      if (ndead > 0) {
          /* we need to add to the main terms */
        if (method == CoxMethod.Breslow) {
            /* Breslow */
          loglik[1] -= deadwt * Math.log(denom);

          for (i = 0; i < nvar; i++) {
            temp2 = a[i] / denom; /* mean */
            u[i] -= deadwt * temp2;
            for (j = 0; j <= i; j++) {
              imat[j][i] += deadwt * (cmat[i][j] - temp2 * a[j]) / denom;
            }
          }
        } else {
            /* Efron */
          /*
           ** If there are 3 deaths we have 3 terms: in the first the
           **  three deaths are all in, in the second they are 2/3
           **  in the sums, and in the last 1/3 in the sum.  Let k go
           **  from 0 to (ndead -1), then we will sequentially use
           **     denom - (k/ndead)*efronwt as the denominator
           **     a - (k/ndead)*a2 as the "a" term
           **     cmat - (k/ndead)*cmat2 as the "cmat" term
           **  and reprise the equations just above.
           */
          for (k = 0; k < ndead; k++) {
            temp = (double) k / ndead;
            wtave = deadwt / ndead;
            d2 = denom - temp * efronwt;
            loglik[1] -= wtave * Math.log(d2);
            for (i = 0; i < nvar; i++) {
              temp2 = (a[i] - temp * a2[i]) / d2;
              u[i] -= wtave * temp2;
              for (j = 0; j <= i; j++) {
                imat[j][i] +=
                    (wtave / d2)
                        * ((cmat[i][j] - temp * cmat2[i][j]) - temp2 * (a[j] - temp * a2[j]));
              }
            }
          }

          for (i = 0; i < nvar; i++) {
            a2[i] = 0;
            for (j = 0; j < nvar; j++) {
              cmat2[i][j] = 0;
            }
          }
        }
      }
    } /* end  of accumulation loop */
    loglik[0] = loglik[1]; /* save the loglik for iterations 0 */

    /* am I done?
     **   update the betas and test for convergence
     */
    for (i = 0; i < nvar; i++) /*use 'a' as a temp to save u0, for the score test*/ {
      a[i] = u[i];
    }

    flag = Cholesky2.process(imat, nvar, toler);
    chsolve2(imat, nvar, a); /* a replaced by  a *inverse(i) */

    temp = 0;
    for (i = 0; i < nvar; i++) {
      temp += u[i] * a[i];
    }
    sctest = temp; /* score test */

    /*
     **  Never, never complain about convergence on the first step.  That way,
     **  if someone HAS to they can force one iterations at a time.
     */
    for (i = 0; i < nvar; i++) {
      newbeta[i] = beta[i] + a[i];
    }
    if (maxiter == 0) {
      chinv2(imat, nvar);
      for (i = 0; i < nvar; i++) {
        beta[i] *= scale[i]; /*return to original scale */
        u[i] /= scale[i];
        imat[i][i] *= scale[i] * scale[i];
        for (j = 0; j < i; j++) {
          imat[j][i] *= scale[i] * scale[j];
          imat[i][j] = imat[j][i];
        }
      }
      // goto finish;
      gotofinish = true;
    }

    /*
     ** here is the main loop
     */
    if (gotofinish == false) {
      halving = 0; /* =1 when in the midst of "step halving" */
      for (iter = 1; iter <= maxiter; iter++) {
        newlk = 0;
        for (i = 0; i < nvar; i++) {
          u[i] = 0;
          for (j = 0; j < nvar; j++) {
            imat[i][j] = 0;
          }
        }

        /*
         ** The data is sorted from smallest time to largest
         ** Start at the largest time, accumulating the risk set 1 by 1
         */
        for (person = nused - 1; person >= 0; ) {
          if (strata[person] == 1) {
              /* rezero temps for each strata */
            denom = 0;
            nrisk = 0;
            for (i = 0; i < nvar; i++) {
              a[i] = 0;
              for (j = 0; j < nvar; j++) {
                cmat[i][j] = 0;
              }
            }
          }

          dtime = time[person];
          deadwt = 0;
          ndead = 0;
          efronwt = 0;
          while (person >= 0 && time[person] == dtime) {
            nrisk++;
            zbeta = offset[person];
            for (i = 0; i < nvar; i++) {
              zbeta += newbeta[i] * covar[i][person];
            }
            zbeta = coxsafe(zbeta);

            risk = Math.exp(zbeta) * weights[person];
            denom += risk;

            for (i = 0; i < nvar; i++) {
              a[i] += risk * covar[i][person];
              for (j = 0; j <= i; j++) {
                cmat[i][j] += risk * covar[i][person] * covar[j][person];
              }
            }

            if (status[person] == 1) {
              ndead++;
              deadwt += weights[person];
              newlk += weights[person] * zbeta;
              for (i = 0; i < nvar; i++) {
                u[i] += weights[person] * covar[i][person];
              }
              if (method == CoxMethod.Efron) {
                  /* Efron */
                efronwt += risk;
                for (i = 0; i < nvar; i++) {
                  a2[i] += risk * covar[i][person];
                  for (j = 0; j <= i; j++) {
                    cmat2[i][j] += risk * covar[i][person] * covar[j][person];
                  }
                }
              }
            }

            person--;
            if (person >= 0 && strata[person] == 1) { // added catch of person = 0 and person-- = -1
              break; /*ties don't cross strata */
            }
          }

          if (ndead > 0) {
              /* add up terms*/
            if (method == CoxMethod.Breslow) {
                /* Breslow */
              newlk -= deadwt * Math.log(denom);
              for (i = 0; i < nvar; i++) {
                temp2 = a[i] / denom; /* mean */
                u[i] -= deadwt * temp2;
                for (j = 0; j <= i; j++) {
                  imat[j][i] += (deadwt / denom) * (cmat[i][j] - temp2 * a[j]);
                }
              }
            } else {
                /* Efron */
              for (k = 0; k < ndead; k++) {
                temp = (double) k / ndead;
                wtave = deadwt / ndead;
                d2 = denom - temp * efronwt;
                newlk -= wtave * Math.log(d2);
                for (i = 0; i < nvar; i++) {
                  temp2 = (a[i] - temp * a2[i]) / d2;
                  u[i] -= wtave * temp2;
                  for (j = 0; j <= i; j++) {
                    imat[j][i] +=
                        (wtave / d2)
                            * ((cmat[i][j] - temp * cmat2[i][j]) - temp2 * (a[j] - temp * a2[j]));
                  }
                }
              }

              for (i = 0; i < nvar; i++) {
                  /*in anticipation */
                a2[i] = 0;
                for (j = 0; j < nvar; j++) {
                  cmat2[i][j] = 0;
                }
              }
            }
          }
        } /* end  of accumulation loop  */

        /* am I done?
         **   update the betas and test for convergence
         */
        flag = Cholesky2.process(imat, nvar, toler);

        if (Math.abs(1 - (loglik[1] / newlk)) <= eps && halving == 0) {
            /* all done */
          loglik[1] = newlk;
          chinv2(imat, nvar); /* invert the information matrix */
          for (i = 0; i < nvar; i++) {
            beta[i] = newbeta[i] * scale[i];
            u[i] /= scale[i];
            imat[i][i] *= scale[i] * scale[i];
            for (j = 0; j < i; j++) {
              imat[j][i] *= scale[i] * scale[j];
              imat[i][j] = imat[j][i];
            }
          }
          //  goto finish;
          gotofinish = true;
          break;
        }

        if (iter == maxiter) {
          break; /*skip the step halving calc*/
        }

        if (newlk < loglik[1]) {
            /*it is not converging ! */
          halving = 1;
          for (i = 0; i < nvar; i++) {
            newbeta[i] = (newbeta[i] + beta[i]) / 2; /*half of old increment */
          }
        } else {
          halving = 0;
          loglik[1] = newlk;
          chsolve2(imat, nvar, u);
          j = 0;
          for (i = 0; i < nvar; i++) {
            beta[i] = newbeta[i];
            newbeta[i] = newbeta[i] + u[i];
          }
        }
      } /* return for another iteration */
    }

    if (gotofinish == false) {
      /*
       ** We end up here only if we ran out of iterations
       */
      loglik[1] = newlk;
      chinv2(imat, nvar);
      for (i = 0; i < nvar; i++) {
        beta[i] = newbeta[i] * scale[i];
        u[i] /= scale[i];
        imat[i][i] *= scale[i] * scale[i];
        for (j = 0; j < i; j++) {
          imat[j][i] *= scale[i] * scale[j];
          imat[i][j] = imat[j][i];
        }
      }
      flag = 1000;
    }

    // finish:
    /*
    for (j = 0; j < numCovariates; j++) {
    b[j] = b[j] / SD[j];
    * ix = j * (numCovariates + 1) + j
    SE[j] = Math.sqrt(a[ix(j, j, numCovariates + 1)]) / SD[j];
    //            o = o + ("   " + variables.get(j) + "    " + Fmt(b[j]) + Fmt(SE[j]) + Fmt(Math.exp(b[j])) + Fmt(Norm(Math.abs(b[j] / SE[j]))) + Fmt(Math.exp(b[j] - 1.95 * SE[j])) + Fmt(Math.exp(b[j] + 1.95 * SE[j])) + NL);
    CoxCoefficient coe = coxInfo.getCoefficient(variables.get(j));
    coe.coeff = b[j];
    coe.stdError = SE[j];
    coe.hazardRatio = Math.exp(b[j]);
    coe.pvalue = Norm(Math.abs(b[j] / SE[j]));
    coe.hazardRatioLoCI = Math.exp(b[j] - 1.95 * SE[j]);
    coe.hazardRatioHiCI = Math.exp(b[j] + 1.95 * SE[j]);
    }

    */

    coxInfo.setScoreLogrankTest(sctest);
    coxInfo.setDegreeFreedom(beta.length);
    coxInfo.setScoreLogrankTestpvalue(ChiSq.chiSq(coxInfo.getScoreLogrankTest(), beta.length));
    coxInfo.setVariance(imat);
    coxInfo.u = u;

    //     for (int n = 0; n < beta.length; n++) {
    //         se[n] = Math.sqrt(imat[n][n]); // / sd[n];
    //     }

    //       System.out.println("coef,se, means,u");
    for (int n = 0; n < beta.length; n++) {
      CoxCoefficient coe = new CoxCoefficient();
      coe.name = variables.get(n);
      coe.mean = means[n];
      coe.standardDeviation = sd[n];
      coe.coeff = beta[n];
      coe.stdError = Math.sqrt(imat[n][n]);
      coe.hazardRatio = Math.exp(coe.getCoeff());
      coe.z = coe.getCoeff() / coe.getStdError();
      coe.pvalue = ChiSq.norm(Math.abs(coe.getCoeff() / coe.getStdError()));
      double z = 1.959964;
      coe.hazardRatioLoCI = Math.exp(coe.getCoeff() - z * coe.getStdError());
      coe.hazardRatioHiCI = Math.exp(coe.getCoeff() + z * coe.getStdError());

      coxInfo.setCoefficient(coe.getName(), coe);
      // System.out.println(beta[n] + "," + se[n] + "," + means[n] + "," + sd[n] + "," + u[n]); //+
      // "," + imat[n] "," + loglik[n] + "," + sctest[n] + "," + iterations[n] + "," + flag[n]

    }

    coxInfo.maxIterations = maxiter;
    coxInfo.eps = eps;
    coxInfo.toler = toler;

    coxInfo.iterations = iter;
    coxInfo.flag = flag;
    coxInfo.loglikInit = loglik[0];
    coxInfo.loglikFinal = loglik[1];
    coxInfo.method = method;

    //    System.out.println("loglik[0]=" + loglik[0]);
    //    System.out.println("loglik[1]=" + loglik[1]);

    //    System.out.println("chisq? sctest[0]=" + sctest[0]);
    //    System.out.println("?overall model p-value=" + chiSq(sctest[0], beta.length));

    //      System.out.println();
    //       for (int n = 0; n < covar[0].length; n++) {
    //           System.out.print(n);
    //           for (int variable = 0; variable < covar.length; variable++) {
    //               System.out.print("\t" + covar[variable][n]);

    //           }
    //           System.out.println();
    //       }
    //      for (SurvivalInfo si : data) {
    //          System.out.println(si.order + " " + si.getScore());
    //      }
    //        coxInfo.dump();

    coxphfitSCleanup(coxInfo, useWeighted, robust, clusterList);
    return coxInfo;
  }