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