001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.nbio.survival.cox; 022 023import java.text.DecimalFormat; 024import java.util.ArrayList; 025import java.util.LinkedHashMap; 026 027/** 028 * Information needed to represent a survival curve 029 * 030 * @author Scooter Willis <willishf at gmail dot com> 031 */ 032public class StrataInfo { 033 034 private ArrayList<Double> time = new ArrayList<Double>(); 035 private ArrayList<Integer> status = new ArrayList<Integer>(); 036 private ArrayList<Double> nevent = new ArrayList<Double>(); 037 private ArrayList<Double> ncens = new ArrayList<Double>(); 038 private ArrayList<Double> nrisk = new ArrayList<Double>(); 039 private ArrayList<Double> weight = new ArrayList<Double>(); 040 private ArrayList<Double> surv = new ArrayList<Double>(); 041 private ArrayList<Double> varhaz = new ArrayList<Double>(); 042 private ArrayList<Double> stderr = new ArrayList<Double>(); 043 private ArrayList<Double> stdlow = new ArrayList<Double>(); 044 private ArrayList<Double> upper = new ArrayList<Double>(); 045 private ArrayList<Double> lower = new ArrayList<Double>(); 046 private LinkedHashMap<Double, Integer> ndead = new LinkedHashMap<Double, Integer>(); 047 DecimalFormat df = new DecimalFormat("#.######"); 048 DecimalFormat dfe = new DecimalFormat("0.000000E0"); 049 050 /** 051 * Need to find the actual time for the nearest time represented as a 052 * percentage Would be used to then look up the number at risk at that 053 * particular time 054 * 055 * @param timePercentage 056 * @return 057 */ 058 public Double getNearestTime(double timePercentage) { 059 //the arrays should be sorted by time so this step is probably not needed 060 Double minTime = null; 061 Double maxTime = null; 062 for (Double t : time) { 063 if (minTime == null || t < minTime) { 064 minTime = t; 065 } 066 if (maxTime == null || t > maxTime) { 067 maxTime = t; 068 } 069 } 070 Double timeRange = maxTime - minTime; 071 Double targetTime = minTime + timePercentage * timeRange; 072 Double previousTime = null; 073 for (Double t : time) { 074 if (previousTime == null || t <= targetTime) { 075 previousTime = t; 076 } else { 077 return previousTime; 078 } 079 } 080 return previousTime; 081 } 082 083 /** 084 * Selection of number of risk will depend on the precision and rounding of 085 * time in the survival table. If you are asking for 12 and entry exists for 086 * 11.9999999 then 12 is greater than 11.99999 unless you round. 087 * 088 * @param t 089 * @return 090 */ 091 public Double getNearestAtRisk(double t) { 092 Integer index = 0; 093/* String timeValue = t + ""; 094 String format = "#"; 095 int numDecimals = 0; 096 int decimalIndex = timeValue.indexOf("."); 097 if (decimalIndex > 0) { 098 for (int i = timeValue.length() - 1; i > decimalIndex; i--) { 099 if (timeValue.charAt(i) == '0' && numDecimals == 0) { 100 continue; 101 } 102 if (i == decimalIndex - 1) { 103 format = format + ".#"; 104 } else { 105 format = format + "#"; 106 } 107 } 108 } 109 */ 110 DecimalFormat newFormat = new DecimalFormat("#.#"); //used to round on expected precision of time. Not correct but trying to match the other packages 111 112 for (int i = 0; i < time.size(); i++) { 113 Double compareTime = time.get(i); 114 // compareTime = new Double(Math.round(compareTime)); //this is rounding up so that we stop on the first match trying to get this to match another report. Not correct or the other report is wrong 115 compareTime = Double.valueOf(newFormat.format(compareTime)); 116 if (compareTime < t) { 117 index = i + 1 ; 118 } else if(compareTime == t){ 119 index = i; 120 break; 121 }else { 122 break; 123 } 124 } 125 126 //http://www.inside-r.org/packages/cran/rms/docs/survplot 127 //per validation using survplot from RMS package and ggkm they select the next 128 //time in the future which doesn't seem to be correct as the next time represents 129 //knowledge about the future but maybe nrisk at that point in time is defined 130 //as the nrisk prior to that time. This appears to be the case where at time 0 131 //you would expect that everyone is at risk and you should report that time which 132 //is the case in survplot. Added in index = 0 or if the time you are requesting has 133 //an exact match 134 //survplot(kma,n.risk=TRUE,time.inc=1090) 135 //ggkm(kma,timeby=1090) 136 // if(index != 0 && time.get(index) != t){ 137 // index++; 138 // } 139 if (index >= nrisk.size()) { 140 return null; 141 } else { 142 return nrisk.get(index); 143 } 144 } 145 146 /** 147 * 148 * @param d 149 * @return 150 */ 151 public String f(Double d) { 152 String v = df.format(d); 153 int l = 10 - v.length(); 154 for (int i = 0; i < l; i++) { 155 v = v + " "; 156 } 157 return v; 158 } 159 160 @Override 161 public String toString() { 162 String o = ""; 163 o = o + "n=" + nevent.size() + "\r\n"; 164 o = o + " time nevent ncens nrisk weight surv varhaz stderr stdlow lower upper\r\n"; 165 for (int i = 0; i < nevent.size(); i++) { 166 // if(nevent.get(i) == 0) 167 // continue; 168 o = o + (i + 1) + " " + f(time.get(i)) + " " + f(nevent.get(i)) + " " + f(ncens.get(i)) + " " + f(nrisk.get(i)) + " " + f(weight.get(i)) + " " + f(surv.get(i)) + " " + (varhaz.get(i)) + " " + stderr.get(i) + " " + stdlow.get(i) + " " + lower.get(i) + " " + upper.get(i) + "\r\n"; 169 170 } 171 o = o + "\r\n"; 172 // for(Integer i : ndead.values()){ 173 // o = o + i + "\r\n"; 174 // } 175 176 return o; 177 } 178 179 /** 180 * @return the time 181 */ 182 public ArrayList<Double> getTime() { 183 return time; 184 } 185 186 /** 187 * @return the surv 188 */ 189 public ArrayList<Double> getSurv() { 190 return surv; 191 } 192 193 /** 194 * @return the stderr 195 */ 196 public ArrayList<Double> getStderr() { 197 return stderr; 198 } 199 200 /** 201 * @return the upper 202 */ 203 public ArrayList<Double> getUpper() { 204 return upper; 205 } 206 207 /** 208 * @return the lower 209 */ 210 public ArrayList<Double> getLower() { 211 return lower; 212 } 213 214 /** 215 * @return the status 216 */ 217 public ArrayList<Integer> getStatus() { 218 return status; 219 } 220 221 /** 222 * @return the nevent 223 */ 224 public ArrayList<Double> getNevent() { 225 return nevent; 226 } 227 228 /** 229 * @return the ncens 230 */ 231 public ArrayList<Double> getNcens() { 232 return ncens; 233 } 234 235 /** 236 * @return the nrisk 237 */ 238 public ArrayList<Double> getNrisk() { 239 return nrisk; 240 } 241 242 /** 243 * @return the weight 244 */ 245 public ArrayList<Double> getWeight() { 246 return weight; 247 } 248 249 /** 250 * @return the ndead 251 */ 252 public LinkedHashMap<Double, Integer> getNdead() { 253 return ndead; 254 } 255 256 /** 257 * @return the varhaz 258 */ 259 public ArrayList<Double> getVarhaz() { 260 return varhaz; 261 } 262 263 /** 264 * @return the stdlow 265 */ 266 public ArrayList<Double> getStdlow() { 267 return stdlow; 268 } 269 270 /** 271 * @param stdlow the stdlow to set 272 */ 273 public void setStdlow(ArrayList<Double> stdlow) { 274 this.stdlow = stdlow; 275 } 276}