View Javadoc
1 package edu.psu.geovista.category; 2 3 /*** 4 * <p>Title: Studio applications</p> 5 * <p>Description: </p> 6 * <p>Copyright: Copyright (c) 2002</p> 7 * <p>Company: GeoVSITA Center</p> 8 * @author Xiping Dai 9 * @version 1.0 10 */ 11 12 import java.lang.*; 13 import java.awt.*; 14 import javax.swing.*; 15 import java.awt.event.*; 16 import java.util.Vector; 17 import edu.psu.geovista.app.scatterplot.*; 18 import edu.psu.geovista.data.ArraySort2D; 19 20 public class DistributionGraph extends JPanel implements ComponentListener 21 { 22 23 private static double AXISSPACEPORTION = 1.0/6.0; 24 private static int DEFAULT_HIST_NUM = 20; 25 private static double DELTA = 1; 26 private int pdf_method =0; 27 transient private double[] data; 28 transient private double[] continuousData; 29 transient private double[][] dataWithIndex; 30 transient private String variableName; 31 transient private DataArray dataArray; 32 transient private DataArray pdfDataArray; 33 transient private double[] pdfArray; 34 private double delta=DELTA; 35 private boolean axisOn = true; 36 private int plotOriginX; 37 private int plotOriginY; 38 private int plotEndX; 39 private int plotEndY; 40 private double[] xAxisExtents; 41 private double[] yAxisExtents; 42 private int[] exsInt; 43 private int[] whyInt; 44 private int[] accumulativeInt; 45 private int[] selectionInt; 46 private int exsStep; 47 private Vector selRecords = new Vector(); 48 private Vector[] histRecords; 49 private Rectangle[] histRecs; 50 private double[] selectionArray; //the count of seleced observation in each histogram bin. 51 private Color background; 52 private Color foreground; 53 private int nonsamplenum=100; 54 55 private double[] gaussianPDF; 56 private boolean gauss = false; 57 private int[] gx; 58 private int[] gy; 59 60 public DistributionGraph() 61 { 62 this.setPreferredSize(new Dimension(300,300)); 63 this.setMinimumSize(new Dimension(100, 100)); 64 } 65 66 public void setData (double[] data){ 67 this.data = data; 68 this.dataArray = new DataArray(data); 69 this.xAxisExtents = (double[])dataArray.getExtent().clone(); 70 this.delta = (this.xAxisExtents[1] - this.xAxisExtents[0])/20; 71 this.addComponentListener(this); 72 this.setBackground(Color.white); 73 if (pdf_method == 0){ 74 calculatePDF(); 75 } else{ 76 this.nonsamplepdf(); 77 } 78 setupDataforDisplay(); 79 this.validate(); 80 } 81 82 public double[] getData (){ 83 return this.data; 84 } 85 86 public void setGaussianPDF(double[] gauss){ 87 this.gauss = true; 88 this.gaussianPDF = gauss; 89 } 90 91 public void setVariableName (String name){ 92 this.variableName = name; 93 } 94 95 public String getVariableName (){ 96 return this.variableName; 97 } 98 99 100 public void setAxisOn (boolean axisOn){ 101 this.axisOn = axisOn; 102 } 103 104 public boolean getAxisOn (){ 105 return this.axisOn; 106 } 107 108 /*** 109 * Minimum and maximum values for xAxis. xAxisExtents[0] = min, xAxisExtents[1] = max. 110 * @param double[] xAxisExtents 111 */ 112 public void setXAxisExtents (double[] xAxisExtents) { 113 //System.out.println("set up axis ..." + xAxisExtents[0]); 114 this.xAxisExtents = (double[])xAxisExtents.clone(); 115 //System.out.println("set up axis ..." + xAxisExtents[0]); 116 //this.histogramCalculation(); 117 //this.setupDataforDisplay(); 118 repaint(); 119 } 120 121 /*** 122 * put your documentation comment here 123 * @return 124 */ 125 public double[] getXAxisExtents () { 126 return this.xAxisExtents; 127 } 128 129 /*** 130 * put your documentation comment here 131 * @param c 132 */ 133 public void setBackground (Color c) { 134 if (c == null) 135 return; 136 this.background = c; 137 int colorTotal = c.getRed() + c.getGreen() + c.getBlue(); 138 int greyColor = 128 * 3; 139 if (colorTotal < greyColor) 140 this.foreground = Color.white; 141 else 142 this.foreground = Color.black; 143 this.repaint(); 144 } 145 146 private void calculatePDF(){ 147 int len = data.length; 148 this.pdfArray = new double[len]; 149 //add index 150 if (dataWithIndex == null || dataWithIndex.length != data.length || dataWithIndex[0].length != 2) { 151 dataWithIndex = new double[data.length][2]; 152 } 153 for (int i = 0; i < len; i++) { 154 dataWithIndex[i][0] = data[i]; 155 dataWithIndex[i][1] = i; 156 } 157 //now sort 158 ArraySort2D.sortDouble(dataWithIndex,0); 159 //this.pdfArray[0] = dataWithIndex[0][0]; 160 //this.pdfArray[len-1] = dataWithIndex[len-1][0]; 161 for (int i = 0; i < len; i ++){ 162 int numberInDelta = 1; 163 int j = 1; 164 double mean = dataWithIndex[i][0]; 165 while ((i != 0)&&(dataWithIndex[i-j][0] > dataWithIndex[i][0] - this.delta)){ 166 mean += dataWithIndex[i-j][0]; 167 j ++; 168 if (j > i){ 169 break; 170 } 171 } 172 numberInDelta += j-1; 173 j = 1; 174 while ((i != len-1)&&(dataWithIndex[i+j][0] < dataWithIndex[i][0] + this.delta)){ 175 mean += dataWithIndex[i+j][0]; 176 j ++; 177 if ((i+j) == len){ 178 break; 179 } 180 } 181 numberInDelta += j-1; 182 if (numberInDelta ==0){ 183 this.pdfArray[i] = 0; 184 }else{ 185 mean /= numberInDelta; 186 this.pdfArray[i] = numberInDelta/this.delta/2/len; 187 } 188 } 189 this.pdfDataArray = new DataArray(pdfArray); 190 this.yAxisExtents = (double[])this.pdfDataArray.getExtent().clone(); 191 } 192 193 private void setupDataforDisplay(){ 194 195 if (axisOn){ 196 plotOriginX = (int)(this.getWidth()*AXISSPACEPORTION); 197 plotOriginY = (int)(this.getHeight()*(1 - AXISSPACEPORTION)); 198 plotEndX = (int)(this.getWidth()) - (int)(this.getWidth()*AXISSPACEPORTION/2); 199 plotEndY = (int)(this.getHeight()*AXISSPACEPORTION/2); 200 }else { 201 plotOriginX = 0; 202 plotOriginY = (int)(this.getSize().getHeight() - 2); 203 plotEndX = (int)(this.getSize().getWidth()) - 3; 204 plotEndY = 3; 205 } 206 double[] dataX; 207 if (pdf_method==0) { // sample 208 int len = this.data.length; 209 exsInt = new int[len]; 210 whyInt = new int[len]; 211 dataX = new double[len]; 212 for(int i = 0; i < len; i ++) { 213 dataX[i] = this.dataWithIndex[i][0]; 214 } 215 } 216 else { //nonsample 217 exsInt = new int[nonsamplenum]; 218 whyInt = new int[nonsamplenum]; 219 dataX = new double[nonsamplenum]; 220 for (int i=0;i<nonsamplenum;i++) { 221 dataX[i] = this.continuousData[i]; 222 } 223 } 224 225 //get positions on screen 226 double scaleX, scaleY; 227 scaleX = getScale(plotOriginX, plotEndX, xAxisExtents[0], xAxisExtents[1]); 228 exsInt = getValueScreen(dataX, scaleX, plotOriginX, xAxisExtents[0]); 229 exsStep = exsInt[1]-exsInt[0]; 230 scaleY = getScale(plotOriginY, plotEndY, yAxisExtents[0], yAxisExtents[1]); 231 whyInt = getValueScreen(this.pdfArray, scaleY, plotOriginY, yAxisExtents[0]); 232 233 if (gauss == true){ 234 int len = this.data.length; 235 gx = new int[len]; 236 gy = new int[len]; 237 gx = getValueScreen(data, scaleX, plotOriginX, xAxisExtents[0]); 238 gy = getValueScreen(this.gaussianPDF, scaleY, plotOriginY, yAxisExtents[0]); 239 } 240 } 241 242 public void paintComponent (Graphics g) { 243 g.setColor(background); 244 g.fillRect(0, 0, getSize().width, getSize().height); 245 g.setColor(foreground); 246 if (this.axisOn == true){ 247 drawAxis(g); 248 } 249 drawPlot(g); 250 } 251 252 private void drawPlot (Graphics g) { 253 int len = this.data.length; 254 if (pdf_method == 0){ 255 for (int i = 0; i < len; i ++){ 256 g.drawOval(exsInt[i], whyInt[i], 1, 1); 257 } 258 }else{ 259 for (int i = 0; i < nonsamplenum; i ++){ 260 g.drawOval(exsInt[i], whyInt[i], 1, 1); 261 } 262 } 263 264 g.setColor(Color.red); 265 if(gauss == true){ 266 for (int i = 0; i < len; i ++){ 267 g.drawOval(gx[i], gy[i], 1, 1); 268 } 269 } 270 g.setColor(Color.black); 271 } 272 273 274 private void drawAxis (Graphics g) { 275 int plotWidth, plotHeight; 276 plotWidth = (int)this.getSize().getWidth(); 277 plotHeight = (int)this.getSize().getHeight(); 278 g.setColor(foreground); 279 g.drawLine(plotOriginX, plotEndY, plotOriginX, plotOriginY); 280 g.drawLine(plotOriginX, plotOriginY, plotEndX, plotOriginY); 281 // draw tick bars for scales on Y coordinate 282 int fontSize; 283 if (plotWidth < plotHeight){ 284 if (plotWidth < 300){ 285 fontSize = 9; 286 } else { 287 fontSize = (int)(plotWidth/32); 288 } 289 }else { 290 if (plotHeight < 300){ 291 fontSize = 9; 292 } else { 293 fontSize = (int)(plotHeight/32); 294 } 295 } 296 Font font = new Font("", Font.PLAIN, fontSize); 297 g.setFont(font); 298 //draw the labels on y axis (frequency). 299 String scaleStringY; 300 double barNumber = this.pdfDataArray.getTickNumber(); 301 double yBarDistance = ((plotOriginY - plotEndY)/barNumber); 302 //System.out.println("drawaxis: "+plotOriginY+" "+plotEndY+" "+yBarDistance+" "+barNumber); 303 for (int i = 0; i <= barNumber; i++) { 304 g.drawLine(plotOriginX - 3, plotEndY + (int)(i*yBarDistance), plotOriginX, 305 plotEndY + (int)(i*yBarDistance)); 306 if (Math.abs(this.pdfDataArray.getMajorTick()) <= 1) { 307 scaleStringY = Float.toString((float)(yAxisExtents[1] - i*this.pdfDataArray.getMajorTick())); 308 } 309 else { 310 scaleStringY = Integer.toString((int)(yAxisExtents[1] - i*this.pdfDataArray.getMajorTick())); 311 } 312 g.drawString(scaleStringY, plotOriginX - (int)(plotWidth*AXISSPACEPORTION/2), 313 plotEndY + (int)(i*yBarDistance + yBarDistance*1/6)); 314 } 315 //draw the labels on x axis. 316 //First tick. 317 String scaleStringX; 318 g.drawLine(plotOriginX, plotOriginY, plotOriginX, plotOriginY + 3); 319 if (Math.abs(xAxisExtents[0]) <= 1) { 320 scaleStringX = Float.toString((float)xAxisExtents[0]); 321 } else { 322 scaleStringX = Integer.toString((int)xAxisExtents[0]); 323 } 324 g.drawString(scaleStringX, plotOriginX - 3, plotOriginY + (int)(plotHeight*AXISSPACEPORTION/4)); 325 //Last tick. 326 g.drawLine(plotEndX, plotOriginY, plotEndX, plotOriginY + 3); 327 if (Math.abs(xAxisExtents[1]) <= 1) { 328 scaleStringX = Float.toString((float)xAxisExtents[1]); 329 } else { 330 scaleStringX = Integer.toString((int)xAxisExtents[1]); 331 } 332 g.drawString(scaleStringX, plotEndX - 8, plotOriginY + (int)(plotHeight*AXISSPACEPORTION/4)); 333 font = new Font("", Font.PLAIN, fontSize + 3); 334 g.setFont(font); 335 //draw X axis attribute string 336 //g.drawString(this.variableName, plotOriginX + (plotEndX - plotOriginX)/2 - plotWidth/12, 337 // plotOriginY + plotHeight/6 - 5); 338 //draw Y axis attribute string. Need rotation for drawing the string vertically. 339 Graphics2D g2d = (Graphics2D)g; 340 g2d.rotate(-Math.PI/2, plotOriginX - plotWidth/9, plotOriginY - (plotOriginY 341 - plotEndY)/3); 342 g2d.drawString("Density", plotOriginX - plotWidth/9, plotOriginY - (plotOriginY 343 - plotEndY)/3); 344 g2d.rotate(+Math.PI/2, plotOriginX - plotWidth/9, plotOriginY - (plotOriginY 345 - plotEndY)/3); 346 } 347 348 /*** 349 * Calculate scale between real data and integer data for showing up on screen. 350 * @param min 351 * @param max 352 * @param dataMin 353 * @param dataMax 354 * @return scale 355 */ 356 private double getScale (int min, int max, double dataMin, double dataMax) { 357 double scale; 358 scale = (max - min)/(dataMax - dataMin); 359 return scale; 360 } 361 /*** 362 * Convert the single value to integer value worked on screen. 363 * @param data 364 * @param scale 365 * @param min 366 * @param dataMin 367 * @return valueScreen 368 */ 369 private int getValueScreen (double data, double scale, int min, double dataMin) { 370 int valueScreen; 371 if (Double.isNaN(data)) { 372 valueScreen = Integer.MIN_VALUE; 373 } 374 else { 375 valueScreen = (int)((data - dataMin)*scale + min); 376 } 377 return valueScreen; 378 } 379 /*** 380 * Convert the numeric values of observations to integer value worked on screen. 381 * @param dataArray 382 * @param scale 383 * @param min 384 * @param dataMin 385 * @return valueScreen 386 */ 387 private int[] getValueScreen (double[] dataArray, double scale, int min, double dataMin) { 388 int[] valueScreen = new int[dataArray.length]; 389 for (int i = 0; i < dataArray.length; i++) { 390 if (Double.isNaN(dataArray[i])) { 391 valueScreen[i] = Integer.MIN_VALUE; 392 } 393 else { 394 valueScreen[i] = (int)((dataArray[i] - dataMin)*scale + min); 395 } 396 } 397 return valueScreen; 398 } 399 400 401 public void componentHidden(ComponentEvent e) { 402 403 } 404 405 public void componentMoved(ComponentEvent e) { 406 407 } 408 409 public void componentResized(ComponentEvent e) { 410 //System.out.println("in component resized"); 411 this.setupDataforDisplay(); 412 //this.setAccumulativeFrequency(); 413 this.repaint(); 414 } 415 416 public void componentShown(ComponentEvent e) { 417 } 418 419 private void nonsamplepdf() { 420 int len = data.length; 421 //add index 422 if (dataWithIndex == null || dataWithIndex.length != data.length || dataWithIndex[0].length != 2) { 423 dataWithIndex = new double[data.length][2]; 424 } 425 for (int i = 0; i < len; i++) { 426 dataWithIndex[i][0] = data[i]; 427 dataWithIndex[i][1] = i; 428 } 429 //now sort 430 ArraySort2D.sortDouble(dataWithIndex,0); 431 //this.pdfArray[0] = dataWithIndex[0][0]; 432 //this.pdfArray[len-1] = dataWithIndex[len-1][0]; 433 int minindex, maxindex; 434 minindex=maxindex=0; 435 double interval=(this.xAxisExtents[1]-this.xAxisExtents[0])/nonsamplenum; 436 this.pdfArray=new double[nonsamplenum]; // y 437 this.continuousData = new double[nonsamplenum]; // x 438 for (int i = 0; i < nonsamplenum; i ++){ 439 this.continuousData[i]=(i+0.5)*interval+this.xAxisExtents[0]; 440 // find minimum 441 while ((this.dataWithIndex[minindex][0]<this.continuousData[i]-this.delta)&&minindex<len-1) { 442 minindex+=1; 443 } 444 // find maximum 445 while ((this.dataWithIndex[maxindex][0]<this.continuousData[i]+this.delta)&&maxindex<len-1) { 446 maxindex+=1; 447 } 448 pdfArray[i]=(maxindex-minindex)/(len*this.delta*2.0); 449 } 450 this.pdfDataArray = new DataArray(pdfArray); 451 this.yAxisExtents = (double[])this.pdfDataArray.getExtent().clone(); 452 } 453 454 }

This page was automatically generated by Maven