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 import edu.psu.geovista.data.StatisticsVectors; 20 import javax.swing.border.*; 21 import javax.swing.BorderFactory; 22 23 public class MultiClassDistributions extends JPanel implements MouseListener, ComponentListener 24 { 25 private static double AXISSPACEPORTION = 1.0/6.0; 26 private static int DEFAULT_HIST_NUM = 20; 27 private static double DELTA = 1; 28 private Color background; 29 private Color foreground; 30 private boolean axisOn = true; 31 private int plotOriginX; 32 private int plotOriginY; 33 private int plotEndX; 34 private int plotEndY; 35 private Vector[] dataVector; 36 private int classNumber; 37 private Vector oneVarData = new Vector(); 38 private Vector dataXVector = new Vector(); 39 private int displayVarIdx; 40 private double xAxisMin; 41 private double xAxisMax; 42 private double yAxisMin; 43 private double yAxisMax; 44 private double delta; 45 private Vector dataDistributions = new Vector(); 46 private Vector exsIntVector = new Vector(); 47 private Vector whyIntVector = new Vector(); 48 private int nonsamplenum=100; 49 private double[] continuousData; 50 private boolean gauss; 51 private Vector dataGaussians = new Vector(); 52 private Vector dataGaussiansInt = new Vector(); 53 private JPopupMenu popup; 54 private JCheckBoxMenuItem[] classCheckBox; 55 private int currentCheckBox; 56 //private EventListenerList listenerListAction = new EventListenerList(); 57 58 public MultiClassDistributions(){ 59 this.setBorder(BorderFactory.createLineBorder(Color.gray)); 60 popup = new JPopupMenu(); 61 } 62 63 public void setDisplayVariableIndex(int index){ 64 this.displayVarIdx = index; 65 this.initialize(); 66 this.repaint(); 67 } 68 69 public int getDisplayVariableIndex(){ 70 return this.displayVarIdx; 71 } 72 73 public void setDataVector(Vector[] dataVector){ 74 this.dataVector = dataVector; 75 this.classNumber = this.dataVector.length; 76 77 this.exsIntVector.setSize(this.classNumber); 78 79 this.classCheckBox = new JCheckBoxMenuItem[this.classNumber]; 80 for(int i = 0; i < this.classNumber; i ++){ 81 this.classCheckBox[i] = new JCheckBoxMenuItem("class" + new Integer(i).toString()); 82 this.classCheckBox[i].setName(new Integer(i).toString()); 83 this.classCheckBox[i].setSelected(true); 84 this.popup.add(this.classCheckBox[i], i); 85 this.currentCheckBox = i; 86 classCheckBox[i].addActionListener(new ActionListener() { 87 88 /*** 89 * put your documentation comment here 90 * @param e 91 */ 92 public void actionPerformed (ActionEvent e) { 93 boolean isSelected = classCheckBox[currentCheckBox].isSelected(); 94 classCheckBox[currentCheckBox].setSelected(!isSelected); 95 repaint(); 96 } 97 }); 98 } 99 addMouseListener(this); 100 101 initialize(); 102 103 } 104 105 public Vector[] getDataVector(){ 106 return this.dataVector; 107 } 108 109 public void setAxisOn (boolean axisOn){ 110 this.axisOn = axisOn; 111 } 112 113 public boolean getAxisOn (){ 114 return this.axisOn; 115 } 116 117 public void setGaussOn (boolean gauss){ 118 this.gauss = gauss; 119 } 120 121 public boolean getGaussOn (){ 122 return this.gauss; 123 } 124 125 /*** 126 * put your documentation comment here 127 * @param c 128 */ 129 public void setBackground (Color c) { 130 if (c == null) 131 return; 132 this.background = c; 133 int colorTotal = c.getRed() + c.getGreen() + c.getBlue(); 134 int greyColor = 128 * 3; 135 if (colorTotal < greyColor) 136 this.foreground = Color.white; 137 else 138 this.foreground = Color.black; 139 this.repaint(); 140 } 141 142 /*private double[] calculatePDF(double[] data){ 143 double[] pdfArray; 144 double[][] dataWithIndex = new double[data.length][2]; 145 int len = data.length; 146 pdfArray = new double[len]; 147 148 for (int i = 0; i < len; i++) { 149 dataWithIndex[i][0] = data[i]; 150 dataWithIndex[i][1] = i; 151 } 152 //now sort 153 ArraySort2D.sortDouble(dataWithIndex,0); 154 //this.pdfArray[0] = dataWithIndex[0][0]; 155 //this.pdfArray[len-1] = dataWithIndex[len-1][0]; 156 for (int i = 0; i < len; i ++){ 157 int numberInDelta = 1; 158 int j = 1; 159 double mean = dataWithIndex[i][0]; 160 while ((i != 0)&&(dataWithIndex[i-j][0] > dataWithIndex[i][0] - this.delta)){ 161 mean += dataWithIndex[i-j][0]; 162 j ++; 163 if (j > i){ 164 break; 165 } 166 } 167 numberInDelta += j-1; 168 j = 1; 169 while ((i != len-1)&&(dataWithIndex[i+j][0] < dataWithIndex[i][0] + this.delta)){ 170 mean += dataWithIndex[i+j][0]; 171 j ++; 172 if ((i+j) == len){ 173 break; 174 } 175 } 176 numberInDelta += j-1; 177 if (numberInDelta ==0){ 178 pdfArray[i] = 0; 179 }else{ 180 mean /= numberInDelta; 181 pdfArray[i] = numberInDelta/this.delta/2/len; 182 } 183 } 184 185 DataArray pdfDataArray = new DataArray(pdfArray); 186 double yMin = ((double[])pdfDataArray.getExtent().clone())[0]; 187 double yMax = ((double[])pdfDataArray.getExtent().clone())[1]; 188 this.yAxisMin = (this.yAxisMin <= yMin) ? yAxisMin : yMin; 189 this.yAxisMax = (this.yAxisMax >= yMax) ? yAxisMax : yMax; 190 return pdfArray; 191 }*/ 192 193 private double[] nonsamplepdf(double[] data, int cl) { 194 int len = data.length; 195 double[][] dataWithIndex = new double[len][2]; 196 double[] pdfArray; 197 198 //add index 199 if (dataWithIndex == null || dataWithIndex.length != data.length || dataWithIndex[0].length != 2) { 200 dataWithIndex = new double[data.length][2]; 201 } 202 for (int i = 0; i < len; i++) { 203 dataWithIndex[i][0] = data[i]; 204 dataWithIndex[i][1] = i; 205 } 206 //now sort 207 ArraySort2D.sortDouble(dataWithIndex,0); 208 //this.pdfArray[0] = dataWithIndex[0][0]; 209 //this.pdfArray[len-1] = dataWithIndex[len-1][0]; 210 211 double xMin; 212 double xMax; 213 DataArray dataArray; 214 215 dataArray = new DataArray(data); 216 xMin = ((double[])dataArray.getExtent().clone())[0]; 217 xMax = ((double[])dataArray.getExtent().clone())[1]; 218 this.delta = (xMax - xMin)/20.0; 219 220 int minindex, maxindex; 221 minindex=maxindex=0; 222 double interval=(xMax-xMin)/nonsamplenum; 223 pdfArray=new double[nonsamplenum]; // y 224 double[] continuousData = new double[nonsamplenum]; // x 225 for (int i = 0; i < nonsamplenum; i ++){ 226 continuousData[i]=(i+0.5)*interval+xMin; 227 // find minimum 228 while ((dataWithIndex[minindex][0]<continuousData[i]-this.delta)&&minindex<len-1) { 229 minindex+=1; 230 } 231 // find maximum 232 while ((dataWithIndex[maxindex][0]<continuousData[i]+this.delta)&&maxindex<len-1) { 233 maxindex+=1; 234 } 235 if (this.delta != 0){ 236 pdfArray[i]=(maxindex-minindex)/(len*this.delta*2.0); 237 }else{ 238 pdfArray[i] = 0; 239 } 240 } 241 242 this.dataXVector.add(cl, continuousData.clone()); 243 244 DataArray pdfDataArray = new DataArray(pdfArray); 245 double yMin = ((double[])pdfDataArray.getExtent().clone())[0]; 246 double yMax = ((double[])pdfDataArray.getExtent().clone())[1]; 247 this.yAxisMin = (this.yAxisMin <= yMin) ? yAxisMin : yMin; 248 this.yAxisMax = (this.yAxisMax >= yMax) ? yAxisMax : yMax; 249 250 this.xAxisMin = (this.xAxisMin <= xMin) ? xAxisMin : xMin; 251 this.xAxisMax = (this.xAxisMax >= xMax) ? xAxisMax : xMax; 252 253 if (this.gauss == true){ 254 255 double[] dataGaussian = new double[len]; 256 double mean = StatisticsVectors.mean(data); 257 //System.out.println("mean " + mean); 258 double variance = 0; 259 if(this.delta != 0){ 260 variance = StatisticsVectors.variance(data); 261 } 262 //System.out.println("variance " + variance); 263 for(int i = 0; i < continuousData.length; i ++){ 264 if (this.delta != 0){ 265 dataGaussian[i] = 1/Math.sqrt(2*Math.PI*variance) * Math.exp(-Math.pow(continuousData[i]-mean, 2)/2/variance); 266 }else{ 267 dataGaussian[i] = 0; 268 } 269 } 270 this.dataGaussians.add(cl, dataGaussian.clone()); 271 } 272 273 return pdfArray; 274 } 275 276 private void initialize(){ 277 this.oneVarData.clear(); 278 this.dataDistributions.clear(); 279 this.dataXVector.clear(); 280 281 for(int i = 0; i < this.classNumber; i ++){ 282 int len = this.dataVector[i].size(); 283 double[] oneClassData = new double[len]; 284 for(int j = 0; j < len; j ++){ 285 if (((double[])(this.dataVector[i].get(j))).length <= this.displayVarIdx){ 286 return; 287 } 288 oneClassData[j] = ((double[])(this.dataVector[i].get(j)))[this.displayVarIdx]; 289 } 290 this.oneVarData.add(oneClassData.clone()); 291 } 292 293 this.xAxisMin = 0; 294 this.xAxisMax = 0; 295 296 this.addComponentListener(this); 297 298 this.setBackground(Color.white); 299 300 this.yAxisMin = 0; 301 this.yAxisMax = 0; 302 for (int i = 0; i < this.classNumber; i ++){ 303 dataDistributions.add(i, this.nonsamplepdf((double[])this.oneVarData.get(i), i).clone()); 304 } 305 306 setupDataforDisplay(); 307 this.validate(); 308 } 309 310 private void setupDataforDisplay(){ 311 312 if (axisOn){ 313 plotOriginX = (int)(this.getWidth()*AXISSPACEPORTION); 314 plotOriginY = (int)(this.getHeight()*(1 - AXISSPACEPORTION)); 315 plotEndX = (int)(this.getWidth()) - (int)(this.getWidth()*AXISSPACEPORTION/2); 316 plotEndY = (int)(this.getHeight()*AXISSPACEPORTION/2); 317 }else { 318 plotOriginX = 0; 319 plotOriginY = (int)(this.getSize().getHeight() - 2); 320 plotEndX = (int)(this.getSize().getWidth()) - 3; 321 plotEndY = 3; 322 } 323 324 //get positions on screen 325 double scaleX, scaleY; 326 scaleX = getScale(plotOriginX, plotEndX, xAxisMin, xAxisMax); 327 scaleY = getScale(plotOriginY, plotEndY, yAxisMin, yAxisMax); 328 329 this.exsIntVector.clear(); 330 this.whyIntVector.clear(); 331 this.dataGaussiansInt.clear(); 332 //double[] dataX = new double[nonsamplenum]; 333 for(int cl = 0; cl < this.classNumber; cl ++){ 334 int[] exsInt = new int[nonsamplenum]; 335 int[] whyInt = new int[nonsamplenum]; 336 exsInt = getValueScreen((double[])dataXVector.get(cl), scaleX, plotOriginX, xAxisMin); 337 whyInt = getValueScreen((double[])this.dataDistributions.get(cl), scaleY, plotOriginY, yAxisMin); 338 this.exsIntVector.add(cl, exsInt.clone()); 339 this.whyIntVector.add(cl, whyInt.clone()); 340 } 341 342 if (gauss == true){ 343 for(int cl = 0; cl < this.classNumber; cl ++){ 344 int[] gaussianInt = new int[nonsamplenum]; 345 gaussianInt = getValueScreen((double[])this.dataGaussians.get(cl), scaleY, plotOriginY, yAxisMin); 346 this.dataGaussiansInt.add(cl, gaussianInt.clone()); 347 } 348 } 349 } 350 351 public void paintComponent (Graphics g) { 352 g.setColor(background); 353 g.fillRect(0, 0, getSize().width, getSize().height); 354 g.setColor(foreground); 355 if (this.axisOn == true){ 356 drawAxis(g); 357 } 358 drawPlot(g); 359 } 360 361 private void drawPlot (Graphics g) { 362 for(int cl = 0; cl < this.classNumber; cl ++){ 363 //int[] exsInt = (int[])this.exsIntVector.get(cl); 364 //int[] whyInt = (int[])this.whyIntVector.get(cl); 365 if(cl == 0){ 366 g.setColor(Color.red); 367 }else if(cl == 1){ 368 g.setColor(Color.BLUE); 369 }else if(cl == 2){ 370 g.setColor(Color.green); 371 }else if(cl == 3){ 372 g.setColor(Color.orange); 373 }else if(cl == 4){ 374 g.setColor(Color.darkGray); 375 } 376 if (this.classCheckBox[cl].isSelected() == true){ 377 for (int i = 0; i < nonsamplenum; i ++){ 378 g.drawOval(((int[])this.exsIntVector.get(cl))[i], ((int[])this.whyIntVector.get(cl))[i], 2, 2); 379 } 380 381 if(gauss == true){ 382 int[] gy = (int[])this.dataGaussiansInt.get(cl); 383 for (int i = 0; i < nonsamplenum; i ++){ 384 //g.drawOval(((int[])this.exsIntVector.get(cl))[i], gy[i], 2, 2); 385 g.drawPolyline(((int[])this.exsIntVector.get(cl)), gy, this.nonsamplenum); 386 } 387 } 388 g.setColor(foreground); 389 } 390 } 391 } 392 393 394 private void drawAxis (Graphics g) { 395 int plotWidth, plotHeight; 396 plotWidth = (int)this.getSize().getWidth(); 397 plotHeight = (int)this.getSize().getHeight(); 398 g.setColor(foreground); 399 g.drawLine(plotOriginX, plotEndY, plotOriginX, plotOriginY); 400 g.drawLine(plotOriginX, plotOriginY, plotEndX, plotOriginY); 401 // draw tick bars for scales on Y coordinate 402 int fontSize; 403 if (plotWidth < plotHeight){ 404 if (plotWidth < 300){ 405 fontSize = 9; 406 } else { 407 fontSize = (int)(plotWidth/32); 408 } 409 }else { 410 if (plotHeight < 300){ 411 fontSize = 9; 412 } else { 413 fontSize = (int)(plotHeight/32); 414 } 415 } 416 Font font = new Font("", Font.PLAIN, fontSize); 417 g.setFont(font); 418 //draw the labels on y axis (frequency). 419 /*String scaleStringY; 420 double barNumber = this.pdfDataArray.getTickNumber(); 421 double yBarDistance = ((plotOriginY - plotEndY)/barNumber); 422 //System.out.println("drawaxis: "+plotOriginY+" "+plotEndY+" "+yBarDistance+" "+barNumber); 423 for (int i = 0; i <= barNumber; i++) { 424 g.drawLine(plotOriginX - 3, plotEndY + (int)(i*yBarDistance), plotOriginX, 425 plotEndY + (int)(i*yBarDistance)); 426 if (Math.abs(this.pdfDataArray.getMajorTick()) <= 1) { 427 scaleStringY = Float.toString((float)(yAxisMax - i*this.pdfDataArray.getMajorTick())); 428 } 429 else { 430 scaleStringY = Integer.toString((int)(yAxisMax - i*this.pdfDataArray.getMajorTick())); 431 } 432 g.drawString(scaleStringY, plotOriginX - (int)(plotWidth*AXISSPACEPORTION/2), 433 plotEndY + (int)(i*yBarDistance + yBarDistance*1/6)); 434 }*/ 435 //draw the labels on x axis. 436 //First tick. 437 String scaleStringX; 438 g.drawLine(plotOriginX, plotOriginY, plotOriginX, plotOriginY + 3); 439 if (Math.abs(xAxisMin) <= 1) { 440 scaleStringX = Float.toString((float)xAxisMin); 441 } else { 442 scaleStringX = Integer.toString((int)xAxisMin); 443 } 444 g.drawString(scaleStringX, plotOriginX - 3, plotOriginY + (int)(plotHeight*AXISSPACEPORTION/4)); 445 //Last tick. 446 g.drawLine(plotEndX, plotOriginY, plotEndX, plotOriginY + 3); 447 if (Math.abs(xAxisMax) <= 1) { 448 scaleStringX = Float.toString((float)xAxisMax); 449 } else { 450 scaleStringX = Integer.toString((int)xAxisMax); 451 } 452 g.drawString(scaleStringX, plotEndX - 8, plotOriginY + (int)(plotHeight*AXISSPACEPORTION/4)); 453 font = new Font("", Font.PLAIN, fontSize + 3); 454 g.setFont(font); 455 //draw X axis attribute string 456 //g.drawString(this.variableName, plotOriginX + (plotEndX - plotOriginX)/2 - plotWidth/12, 457 // plotOriginY + plotHeight/6 - 5); 458 //draw Y axis attribute string. Need rotation for drawing the string vertically. 459 Graphics2D g2d = (Graphics2D)g; 460 g2d.rotate(-Math.PI/2, plotOriginX - plotWidth/9, plotOriginY - (plotOriginY 461 - plotEndY)/3); 462 g2d.drawString("Density", plotOriginX - plotWidth/9, plotOriginY - (plotOriginY 463 - plotEndY)/3); 464 g2d.rotate(+Math.PI/2, plotOriginX - plotWidth/9, plotOriginY - (plotOriginY 465 - plotEndY)/3); 466 } 467 468 /*** 469 * Calculate scale between real data and integer data for showing up on screen. 470 * @param min 471 * @param max 472 * @param dataMin 473 * @param dataMax 474 * @return scale 475 */ 476 private double getScale (int min, int max, double dataMin, double dataMax) { 477 double scale; 478 scale = (max - min)/(dataMax - dataMin); 479 return scale; 480 } 481 /*** 482 * Convert the single value to integer value worked on screen. 483 * @param data 484 * @param scale 485 * @param min 486 * @param dataMin 487 * @return valueScreen 488 */ 489 private int getValueScreen (double data, double scale, int min, double dataMin) { 490 int valueScreen; 491 if (Double.isNaN(data)) { 492 valueScreen = Integer.MIN_VALUE; 493 } 494 else { 495 valueScreen = (int)((data - dataMin)*scale + min); 496 } 497 return valueScreen; 498 } 499 /*** 500 * Convert the numeric values of observations to integer value worked on screen. 501 * @param dataArray 502 * @param scale 503 * @param min 504 * @param dataMin 505 * @return valueScreen 506 */ 507 private int[] getValueScreen (double[] dataArray, double scale, int min, double dataMin) { 508 int[] valueScreen = new int[dataArray.length]; 509 for (int i = 0; i < dataArray.length; i++) { 510 if (Double.isNaN(dataArray[i])) { 511 valueScreen[i] = Integer.MIN_VALUE; 512 } 513 else { 514 valueScreen[i] = (int)((dataArray[i] - dataMin)*scale + min); 515 } 516 } 517 return valueScreen; 518 } 519 520 public void componentHidden(ComponentEvent e) { 521 522 } 523 524 public void componentMoved(ComponentEvent e) { 525 526 } 527 528 public void componentResized(ComponentEvent e) { 529 this.setupDataforDisplay(); 530 this.repaint(); 531 } 532 533 public void componentShown(ComponentEvent e) { 534 } 535 536 /*** 537 * put your documentation comment here 538 * @param e 539 */ 540 private void maybeShowPopup (MouseEvent e) { 541 if (e.isPopupTrigger()) { 542 popup.show(e.getComponent(), e.getX(), e.getY()); 543 } 544 } 545 546 public void mouseClicked(MouseEvent e){ 547 int count = e.getClickCount(); 548 //double click, pop up a detail scatter plot. 549 if (count == 2){ // This is a double-click or triple... 550 MultiClassDistributions detailSP = new MultiClassDistributions(); 551 detailSP.setAxisOn(true); 552 detailSP.setBackground(background); 553 detailSP.setGaussOn(true); 554 detailSP.setDisplayVariableIndex(this.displayVarIdx); 555 detailSP.setDataVector(this.dataVector); 556 //detailSP.setElementPosition(dataIndices); 557 //detailSP.setColorArrayForObs(this.colorArrayForObs); 558 //detailSP.setSelectedObservations(selRecords); 559 //detailSP.setSelections(this.selections); 560 JFrame dlgSP = new JFrame("Detailed Distributions"); 561 //JDialog dlgSP = new JDialog(dummyFrame, "Detailed Distributions", true); 562 dlgSP.setLocation(300, 300); 563 dlgSP.setSize(300, 300); 564 dlgSP.getContentPane().setLayout(new BorderLayout()); 565 dlgSP.getContentPane().add(detailSP, BorderLayout.CENTER); 566 /*detailSP.addActionListener(new ActionListener() { 567 568 /** 569 * put your documentation comment here 570 * @param e 571 */ 572 /*public void actionPerformed (ActionEvent e) { 573 //System.out.println("something came from detailed one."); 574 ScatterPlot detailSP = (ScatterPlot)e.getSource(); 575 String command = e.getActionCommand(); 576 if (command.compareTo(ScatterPlot.COMMAND_POINT_SELECTED) == 0) { 577 //System.out.println("SPMC.plotUnitPanel.actionPerformed(), point selected"); 578 //Vector selRecords = detailSP.getSelectedObservations(); 579 int[] selections = detailSP.getSelections(); 580 // Don't recall the scatterplot which generated the original event 581 //ScatterPlot.this.setSelectedObservations(selRecords); 582 ScatterPlot.this.setSelections(selections); 583 ScatterPlot.this.fireActionPerformed(COMMAND_POINT_SELECTED); 584 } 585 else if(command.compareTo(ScatterPlot.COMMAND_DATARANGE_SET)==0){ 586 double[] dataArrayX = detailSP.getXAxisExtents(); 587 double[] dataArrayY = detailSP.getYAxisExtents(); 588 ScatterPlot.this.setXAxisExtents(dataArrayX); 589 ScatterPlot.this.setYAxisExtents(dataArrayY); 590 fireActionPerformed(COMMAND_DATARANGE_SET); 591 } 592 //System.err.println("Unknown command! = " + command); 593 } 594 });*/ 595 dlgSP.show(); 596 } 597 } 598 599 public void mousePressed(MouseEvent e){ 600 if (e.isPopupTrigger()) 601 maybeShowPopup(e); 602 } 603 604 public void mouseReleased(MouseEvent e){ 605 if (e.isPopupTrigger()){ 606 maybeShowPopup(e); 607 } 608 } 609 610 public void mouseEntered(MouseEvent e){ 611 } 612 613 public void mouseExited(MouseEvent e){ 614 } 615 616 }

This page was automatically generated by Maven