1 | package vishnu.util;
|
---|
2 |
|
---|
3 | import java.awt.*;
|
---|
4 | import java.awt.event.*;
|
---|
5 | import javax.swing.*;
|
---|
6 | import javax.imageio.*;
|
---|
7 | import javax.imageio.stream.*;
|
---|
8 | import java.io.*;
|
---|
9 | import java.util.*;
|
---|
10 | import java.awt.image.*;
|
---|
11 |
|
---|
12 | public class Hgram extends JFrame
|
---|
13 | {
|
---|
14 | public static int TOP = 0;
|
---|
15 | public static int LARGEST = 1;
|
---|
16 |
|
---|
17 | // data is an array with each entry being the frequency of a bin
|
---|
18 | public static int BIN_DATA = 0;
|
---|
19 |
|
---|
20 | // data comes in raw format and needs to be allocated to bins
|
---|
21 | public static int RAW_DATA = 1;
|
---|
22 |
|
---|
23 | double[] data;
|
---|
24 |
|
---|
25 | // default size of frame
|
---|
26 | int width = 400;
|
---|
27 | int height = 400;
|
---|
28 |
|
---|
29 | // axis limits of histogram
|
---|
30 | double xmin;
|
---|
31 | double xmax;
|
---|
32 |
|
---|
33 | // number of bins, bin frequencies and width
|
---|
34 | int noBins;
|
---|
35 | double bins[];
|
---|
36 | double binWidth;
|
---|
37 |
|
---|
38 | BufferedImage offScreen=null;
|
---|
39 | Dimension offScreenSize;
|
---|
40 | Graphics2D offGraphics;
|
---|
41 |
|
---|
42 | String label = null;
|
---|
43 |
|
---|
44 | double median = -1;
|
---|
45 | int med_bin = -1;
|
---|
46 | int mode = -1;
|
---|
47 |
|
---|
48 |
|
---|
49 | public Hgram()
|
---|
50 | {
|
---|
51 | init();
|
---|
52 | }
|
---|
53 |
|
---|
54 |
|
---|
55 | public void setData(double[] d, int m){
|
---|
56 | data = d;
|
---|
57 | mode = m;
|
---|
58 | xmin = getMinimum(data);
|
---|
59 | xmax = getMaximum(data);
|
---|
60 | createBins(data,noBins,xmin, xmax);
|
---|
61 | }
|
---|
62 |
|
---|
63 |
|
---|
64 | public void setBins(double[] b){ bins = b; }
|
---|
65 |
|
---|
66 |
|
---|
67 | public void setBinNumber(int i){ noBins = i; }
|
---|
68 |
|
---|
69 |
|
---|
70 | public void setMaximum(double i){ xmax = i; }
|
---|
71 |
|
---|
72 |
|
---|
73 | public void setMinimum(double i){ xmin = i; }
|
---|
74 |
|
---|
75 |
|
---|
76 | public void setBinWidth(double i){ binWidth = i; }
|
---|
77 |
|
---|
78 |
|
---|
79 | public void setLabel(String l){ label = l; }
|
---|
80 |
|
---|
81 |
|
---|
82 | public void init()
|
---|
83 | {
|
---|
84 | this.setDefaultLookAndFeelDecorated(true);
|
---|
85 | this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
---|
86 | this.setSize(width,height);
|
---|
87 | this.setLocation(0,0);
|
---|
88 | this.setVisible(true);
|
---|
89 |
|
---|
90 | this.addComponentListener( new ComponentAdapter(){
|
---|
91 | public void componentResized(ComponentEvent evt){
|
---|
92 | update();
|
---|
93 | }
|
---|
94 | });
|
---|
95 |
|
---|
96 |
|
---|
97 | this.addMouseListener(new MouseAdapter(){
|
---|
98 | public void mousePressed(MouseEvent evt)
|
---|
99 | {
|
---|
100 | int intX = evt.getX();
|
---|
101 | int intY = evt.getY();
|
---|
102 | }
|
---|
103 |
|
---|
104 | public void mouseClicked(MouseEvent event)
|
---|
105 | {
|
---|
106 | int x = event.getX();
|
---|
107 | int y = event.getY();
|
---|
108 |
|
---|
109 | if( event.getClickCount() == 1 )
|
---|
110 | {
|
---|
111 | }
|
---|
112 | }
|
---|
113 | });
|
---|
114 |
|
---|
115 |
|
---|
116 | this.addMouseMotionListener(new MouseMotionAdapter()
|
---|
117 | {
|
---|
118 | public void mouseMoved(MouseEvent event)
|
---|
119 | {
|
---|
120 | int x = event.getX();
|
---|
121 | int y = event.getY();
|
---|
122 | getBin(x,y);
|
---|
123 | }
|
---|
124 | });
|
---|
125 | }
|
---|
126 |
|
---|
127 |
|
---|
128 | public int getBin(int x, int y){ return -1; }
|
---|
129 |
|
---|
130 |
|
---|
131 | private int getMaxBin()
|
---|
132 | {
|
---|
133 | int maxIndex = -1;
|
---|
134 | double max = 0;
|
---|
135 |
|
---|
136 | for( int i = 0; i < bins.length; i++ ){
|
---|
137 | if( bins[i] > max ){
|
---|
138 | max = bins[i];
|
---|
139 | maxIndex = i;
|
---|
140 | }
|
---|
141 | }
|
---|
142 |
|
---|
143 | return maxIndex;
|
---|
144 | }
|
---|
145 |
|
---|
146 |
|
---|
147 | public void plot()
|
---|
148 | {
|
---|
149 | update();
|
---|
150 | }
|
---|
151 |
|
---|
152 |
|
---|
153 | public double getMaximum(double[] d)
|
---|
154 | {
|
---|
155 | double max = 0;
|
---|
156 |
|
---|
157 | for( int i = 0; i < d.length; i++ ){
|
---|
158 | if( d[i] > max ) max = d[i];
|
---|
159 | }
|
---|
160 | return max;
|
---|
161 | }
|
---|
162 |
|
---|
163 |
|
---|
164 |
|
---|
165 | public double getMinimum(double[] d)
|
---|
166 | {
|
---|
167 | double min = d[0]*d[0]*1000;
|
---|
168 |
|
---|
169 | for( int i = 0; i < d.length; i++ )
|
---|
170 | {
|
---|
171 | if( d[i] < min ) min = d[i];
|
---|
172 | }
|
---|
173 | return min;
|
---|
174 | }
|
---|
175 |
|
---|
176 |
|
---|
177 | public double getFirstMaximum(double[] d)
|
---|
178 | {
|
---|
179 | double max = 0;
|
---|
180 | for( int i = 0; i < bins.length; i++ )
|
---|
181 | {
|
---|
182 | if( bins[i] > max )
|
---|
183 | {
|
---|
184 | max = bins[i];
|
---|
185 | }
|
---|
186 | }
|
---|
187 | return max;
|
---|
188 | }
|
---|
189 |
|
---|
190 |
|
---|
191 | public double getSecondMaximum(double[] d)
|
---|
192 | {
|
---|
193 | double max_1 = 0;
|
---|
194 | double max_2 = 0;
|
---|
195 | for( int i = 0; i < d.length; i++ ){
|
---|
196 | if( d[i] > max_1 ){
|
---|
197 | max_2 = max_1;
|
---|
198 | max_1 = d[i];
|
---|
199 | }
|
---|
200 | else if( d[i] > max_2 ){
|
---|
201 | max_2 = d[i];
|
---|
202 | }
|
---|
203 | }
|
---|
204 | return max_2;
|
---|
205 | }
|
---|
206 |
|
---|
207 |
|
---|
208 | public void createBins(double[] data, int noBins, double xmin, double xmax)
|
---|
209 | {
|
---|
210 | bins = new double[noBins];
|
---|
211 | binWidth = (double)(xmax-xmin)/noBins;
|
---|
212 |
|
---|
213 | for( int i = 0; i < data.length; i++ ){
|
---|
214 | int bin = (int)Math.round((double)(data[i]-xmin)/binWidth);
|
---|
215 | if( bin >= noBins ) bin = noBins-1;
|
---|
216 | bins[bin]++;
|
---|
217 | }
|
---|
218 |
|
---|
219 | for( int i = 0; i < noBins; i++ ){
|
---|
220 | bins[i] = (double)bins[i]/data.length;
|
---|
221 | }
|
---|
222 | }
|
---|
223 |
|
---|
224 |
|
---|
225 | public void update()
|
---|
226 | {
|
---|
227 | if( bins == null ) return;
|
---|
228 |
|
---|
229 | Dimension d = this.getSize();
|
---|
230 | width = d.width;
|
---|
231 | height = d.height;
|
---|
232 | offScreen = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB );
|
---|
233 | offGraphics = (Graphics2D)offScreen.getGraphics();
|
---|
234 | offGraphics.setColor(Color.white);
|
---|
235 | offGraphics.fillRect(0,0,width,height);
|
---|
236 | BasicStroke myStroke = new BasicStroke(2,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER);
|
---|
237 | offGraphics.setStroke(myStroke);
|
---|
238 |
|
---|
239 | int xaxis = (int)(0.8 * width);
|
---|
240 | int xBuffer = (int)(0.1 * width);
|
---|
241 |
|
---|
242 | int yaxis = (int)(0.8 * d.height);
|
---|
243 | int yBuffer = (int)(0.1 * d.height);
|
---|
244 |
|
---|
245 | double maxBinLength = (double)xaxis/bins.length;
|
---|
246 | int effBinLength = (int)(0.8 * maxBinLength);
|
---|
247 | int binBuffer = (int)(0.1 * effBinLength);
|
---|
248 |
|
---|
249 | double max_1 = getFirstMaximum(bins);
|
---|
250 | double max_2 = getSecondMaximum(bins);
|
---|
251 | double max = max_1;
|
---|
252 | boolean cut = false;
|
---|
253 |
|
---|
254 | if( max_1 > 1.5 * max_2 ){
|
---|
255 | cut = true;
|
---|
256 | max = max_2;
|
---|
257 | }
|
---|
258 |
|
---|
259 | double pixelPerUnit = (double)yaxis/max;
|
---|
260 |
|
---|
261 |
|
---|
262 | /**** draw the bins ****/
|
---|
263 |
|
---|
264 | for( int i = 0; i < bins.length; i++ ){
|
---|
265 | int level = (int)(bins[i]* pixelPerUnit);
|
---|
266 | double bound = (double)((int)(100 * (i * (double)(xmax-xmin)/bins.length + xmin)))/100;
|
---|
267 | offGraphics.setColor(Color.blue);
|
---|
268 | offGraphics.fillRect(xBuffer + (int)(i*maxBinLength)+binBuffer,height-yBuffer-level,effBinLength,level);
|
---|
269 | }
|
---|
270 |
|
---|
271 | if( label != null ){
|
---|
272 | FontMetrics fm = offGraphics.getFontMetrics(offGraphics.getFont());
|
---|
273 | int x = width/2 - fm.stringWidth(label)/2;
|
---|
274 | offGraphics.drawString(label,x,yBuffer);
|
---|
275 | }
|
---|
276 |
|
---|
277 |
|
---|
278 | /**** draw axes and ticks ****/
|
---|
279 |
|
---|
280 | offGraphics.setColor(Color.blue);
|
---|
281 |
|
---|
282 | int x = xBuffer + binBuffer;
|
---|
283 | int y = height-yBuffer;
|
---|
284 | offGraphics.drawLine(x, y+5, x, y-5);
|
---|
285 |
|
---|
286 | String tickStr = String.valueOf(xmin);
|
---|
287 | offGraphics.drawString(tickStr,x-5,y+20);
|
---|
288 |
|
---|
289 | x = xBuffer + binBuffer+(int)(bins.length*maxBinLength)+binBuffer;
|
---|
290 | y = height-yBuffer;
|
---|
291 | offGraphics.drawLine(x, y+5, x, y-5);
|
---|
292 | tickStr = String.valueOf(xmax);
|
---|
293 | offGraphics.drawString(tickStr,x-5,y+20);
|
---|
294 |
|
---|
295 | repaint();
|
---|
296 | }
|
---|
297 |
|
---|
298 |
|
---|
299 | public void paint(Graphics g)
|
---|
300 | {
|
---|
301 | Graphics2D g2 = (Graphics2D)g;
|
---|
302 |
|
---|
303 | if( offScreen!=null )
|
---|
304 | g2.drawImage(offScreen, 0, 0, null);
|
---|
305 | }
|
---|
306 |
|
---|
307 |
|
---|
308 | public void printBins()
|
---|
309 | {
|
---|
310 | for( int i = 0; i < bins.length; i++ ){
|
---|
311 | double low = i*binWidth;
|
---|
312 | double up = (i+1)*binWidth;
|
---|
313 | System.out.println("Bin.." + i + " " + low + " " + up + " " + bins[i]);
|
---|
314 | }
|
---|
315 | }
|
---|
316 |
|
---|
317 |
|
---|
318 | public void save(String name, String type)
|
---|
319 | {
|
---|
320 |
|
---|
321 | try{
|
---|
322 | Iterator imageWriters =
|
---|
323 | ImageIO.getImageWritersByFormatName(type);
|
---|
324 | ImageWriter imageWriter = (ImageWriter)imageWriters.next();
|
---|
325 | File file = new File( name + "." + type );
|
---|
326 | ImageOutputStream ios =
|
---|
327 | ImageIO.createImageOutputStream( file );
|
---|
328 | imageWriter.setOutput( ios );
|
---|
329 | imageWriter.write( offScreen );
|
---|
330 | } catch( IOException ie ) {
|
---|
331 | ie.printStackTrace();
|
---|
332 | }
|
---|
333 | }
|
---|
334 |
|
---|
335 | }
|
---|
336 |
|
---|
337 | // accepts raw data
|
---|
338 | /*public Hgram(double[] data, int noBins, double min, double max)
|
---|
339 | {
|
---|
340 | super("JHistogram");
|
---|
341 | init();
|
---|
342 | createBins(data,noBins,min,max);
|
---|
343 | update();
|
---|
344 | }*/
|
---|
345 |
|
---|
346 |
|
---|
347 | // accepts both raw and binned data
|
---|
348 | /*public Hgram(double[] data, int noBins, int mode)
|
---|
349 | {
|
---|
350 | super("JHistogram");
|
---|
351 | this.mode = mode;
|
---|
352 | init();
|
---|
353 | createBins(data,noBins,getMinimum(data),getMaximum(data));
|
---|
354 | update();
|
---|
355 | }*/
|
---|
356 |
|
---|
357 |
|
---|
358 |
|
---|
359 | /*
|
---|
360 | int level = (int)(bins[med_bin]* pixelPerUnit);
|
---|
361 | offGraphics.fillRect(xBuffer + (int)(med_bin*maxBinLength)+binBuffer,height-yBuffer-level,effBinLength,level);
|
---|
362 | String med_string = String.valueOf(median);
|
---|
363 | med_string = med_string.substring(0,med_string.indexOf('.')+3);
|
---|
364 | offGraphics.drawString(med_string, xBuffer + (int)(med_bin*maxBinLength)+binBuffer-10,height-yBuffer-level-10);
|
---|
365 |
|
---|
366 | //saveHistogram(offScreen);
|
---|
367 |
|
---|
368 | repaint();
|
---|
369 | }
|
---|
370 | }*/
|
---|
371 |
|
---|
372 | /*
|
---|
373 | public Hgram(double[] data, int noBins)
|
---|
374 | {
|
---|
375 | init();
|
---|
376 | createBins(data,noBins,getMinimum(data),getFirstMaximum(data));
|
---|
377 | update();
|
---|
378 | }*/
|
---|