001 /* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2013 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see http://www.gnu.org/licenses. 027 */ 028 029 package edu.wisc.ssec.mcidasv.data; 030 031 import java.awt.BorderLayout; 032 import java.awt.Color; 033 import java.awt.Component; 034 import java.awt.Container; 035 import java.awt.Dimension; 036 import java.awt.FlowLayout; 037 import java.awt.GridLayout; 038 import java.awt.event.ActionEvent; 039 import java.awt.event.ActionListener; 040 import java.awt.event.WindowEvent; 041 import java.awt.event.WindowAdapter; 042 import java.awt.geom.Rectangle2D; 043 import java.net.URL; 044 import java.rmi.RemoteException; 045 import java.util.ArrayList; 046 import java.util.List; 047 import java.io.PrintWriter; 048 import java.io.File; 049 050 import javax.swing.JFrame; 051 import javax.swing.ButtonGroup; 052 import javax.swing.ImageIcon; 053 import javax.swing.JComponent; 054 import javax.swing.JPanel; 055 import javax.swing.JRadioButton; 056 import javax.swing.JToggleButton; 057 import javax.swing.JButton; 058 import javax.swing.JScrollPane; 059 import javax.swing.JTable; 060 import javax.swing.JFileChooser; 061 import javax.swing.filechooser.FileFilter; 062 import javax.swing.filechooser.FileNameExtensionFilter; 063 import javax.swing.table.AbstractTableModel; 064 import javax.swing.table.TableCellRenderer; 065 import javax.swing.border.CompoundBorder; 066 import javax.swing.border.EmptyBorder; 067 import javax.swing.border.LineBorder; 068 069 import org.slf4j.Logger; 070 import org.slf4j.LoggerFactory; 071 072 import visad.AxisScale; 073 import visad.BaseColorControl; 074 import visad.CellImpl; 075 import visad.CoordinateSystem; 076 import visad.Data; 077 import visad.DelaunayCustom; 078 import visad.DisplayEvent; 079 import visad.DisplayListener; 080 import visad.Real; 081 import visad.FieldImpl; 082 import visad.FlatField; 083 import visad.FunctionType; 084 import visad.Gridded2DSet; 085 import visad.Gridded3DSet; 086 import visad.Integer1DSet; 087 import visad.Linear2DSet; 088 import visad.LinearLatLonSet; 089 import visad.RealTupleType; 090 import visad.MathType; 091 import visad.RealType; 092 import visad.SampledSet; 093 import visad.ScalarMap; 094 import visad.Set; 095 import visad.SetType; 096 import visad.UnionSet; 097 import visad.VisADException; 098 import visad.data.mcidas.BaseMapAdapter; 099 import visad.georef.MapProjection; 100 import visad.georef.TrivialMapProjection; 101 import visad.python.JPythonMethods; 102 103 import edu.wisc.ssec.mcidasv.data.hydra.Statistics; 104 105 public class StatsTable extends AbstractTableModel { 106 107 String [][] data; 108 JTable table; 109 JFrame statsWindow; 110 double total_area = 0.0; 111 int numCols; 112 boolean isShowing = false; 113 Color[] coltab = {new Color(0xf0f0f0), new Color(0xffd0ff), 114 new Color(0xd0ffd0), new Color(0xc0d0ff)}; 115 116 final int maxCols = 9; 117 String[] colNames = {"Stats Parameter","Whole Field X","Whole Field Y", 118 "Magenta X","Magenta Y", "Green X","Green Y","Blue X","Blue Y"}; 119 120 final int maxRows = 13; 121 final String[] rowNames = {"Maximum","Minimum", 122 "Number of points","Mean","Median","Variance","Kurtosis", 123 "Std Dev","Correlation","Difference Maximum", 124 "Difference Minimum","Difference Mean","Area [km^2]"}; 125 126 boolean saveStats = true; 127 128 129 public StatsTable() { 130 this(true); 131 } 132 133 public StatsTable(boolean saveStats) { super(); 134 this.saveStats = saveStats; 135 136 data = new String[maxRows][maxCols]; 137 numCols = 1; 138 139 for (int i=0; i<maxRows; i++) { 140 data[i][0] = rowNames[i]; 141 for (int j=1; j<maxCols; j++) { 142 data[i][j] = " "; 143 } 144 } 145 146 147 table = new JTable(this) { 148 public Component prepareRenderer( 149 TableCellRenderer renderer, int row, int col) { 150 Component comp = super.prepareRenderer(renderer, row, col); 151 Color c = Color.white; 152 if (col == 0) c = coltab[0]; 153 if (col == 3 || col == 4) c = coltab[1]; 154 if (col == 5 || col == 6) c = coltab[2]; 155 if (col == 7 || col == 8) c = coltab[3]; 156 comp.setBackground(c); 157 return comp; 158 } 159 160 }; 161 table.setFillsViewportHeight(true); 162 table.setPreferredScrollableViewportSize(new Dimension(620,220)); 163 table.setRowSelectionAllowed(true); 164 table.setColumnSelectionAllowed(false); 165 166 JButton saveStatsButt = new JButton("Save As CSV"); 167 JScrollPane sp = new JScrollPane(table); 168 statsWindow = new JFrame("Scatter Statistics"); 169 statsWindow.setLayout(new BorderLayout()); 170 statsWindow.getContentPane().add(sp,BorderLayout.NORTH); 171 JPanel bpan = new JPanel(new FlowLayout()); 172 bpan.add(saveStatsButt); 173 if (saveStats) { 174 statsWindow.getContentPane().add(bpan,BorderLayout.SOUTH); 175 } 176 statsWindow.setSize(650,340); 177 statsWindow.pack(); 178 statsWindow.addWindowListener(new WindowAdapter() { 179 public void windowClosing(WindowEvent e) { 180 isShowing = false; 181 } 182 }); 183 184 saveStatsButt.addActionListener(new ActionListener() { 185 public void actionPerformed(final ActionEvent e) { 186 JFileChooser chzr = new JFileChooser(); 187 FileFilter filt = new FileNameExtensionFilter("csv","txt"); 188 chzr.addChoosableFileFilter(filt); 189 int rv = chzr.showSaveDialog(statsWindow); 190 if (rv == JFileChooser.APPROVE_OPTION) { 191 try { 192 File fpw = chzr.getSelectedFile(); 193 statsWindow.setTitle("Scatter Statistics saved to "+fpw.toString()); 194 PrintWriter pw = new PrintWriter(fpw); 195 String line = ""; 196 for (int k=0; k<colNames.length; k++) { 197 if (k != 0) line = line + ","; 198 line = line + colNames[k]; 199 } 200 pw.println(line); 201 202 for (int i=0; i<data.length; i++) { 203 line = ""; 204 for (int j=0; j<data[i].length; j++) { 205 if (j != 0) line = line+","; 206 line = line+data[i][j]; 207 } 208 pw.println(line); 209 } 210 pw.flush(); 211 pw.close(); 212 } catch (Exception epw) { 213 statsWindow.setTitle("Scatter Statistics: File not saved"); 214 } 215 216 } 217 218 } 219 }); 220 221 isShowing = false; 222 statsWindow.setVisible(false); 223 } 224 225 public void setIsShowing() { 226 isShowing = true; 227 } 228 229 public void resetValues(int col) { 230 for (int i=0; i<maxRows; i++) { 231 int c = 2*col + 3; 232 data[i][c] = " "; 233 data[i][c+1] = " "; 234 } 235 fireTableStructureChanged(); 236 } 237 238 public void setNames(String xn, String yn) { 239 colNames[1] = colNames[3] = colNames[5] = colNames[7] =xn; 240 colNames[2] = colNames[4] = colNames[6] = colNames[8] =yn; 241 } 242 243 // fx, fy are Fields, col = 0,1,2,3 (all, red, green, blue) 244 public void setFields(FlatField fx, FlatField fy, int col) { 245 statsWindow.setTitle("Scatter Statistics"); 246 try { 247 Statistics sx = new Statistics(fx); 248 Statistics sy = new Statistics(fy); 249 Statistics diff = new Statistics((FlatField)fx.subtract(fy)); 250 251 int c = 2*col + 1; 252 data[0][c] = fmtMe(((Real)sx.max()).getValue()); 253 data[0][c+1] = fmtMe(((Real)sy.max()).getValue()); 254 255 data[1][c] = fmtMe(((Real)sx.min()).getValue()); 256 data[1][c+1] = fmtMe(((Real)sy.min()).getValue()); 257 258 data[2][c] = String.format("%d",sx.numPoints()); 259 data[2][c+1] = String.format("%d",sy.numPoints()); 260 261 data[3][c] = fmtMe(((Real)sx.mean()).getValue()); 262 data[3][c+1] = fmtMe(((Real)sy.mean()).getValue()); 263 264 data[4][c] = fmtMe(((Real)sx.median()).getValue()); 265 data[4][c+1] = fmtMe(((Real)sy.median()).getValue()); 266 267 data[5][c] = fmtMe(((Real)sx.variance()).getValue()); 268 data[5][c+1] = fmtMe(((Real)sy.variance()).getValue()); 269 270 data[6][c] = fmtMe(((Real)sx.kurtosis()).getValue()); 271 data[6][c+1] = fmtMe(((Real)sy.kurtosis()).getValue()); 272 273 data[7][c] = fmtMe(((Real)sx.standardDeviation()).getValue()); 274 data[7][c+1] = fmtMe(((Real)sy.standardDeviation()).getValue()); 275 276 data[8][c] = fmtMe(((Real)sx.correlation(fy)).getValue()); 277 data[8][c+1] = " "; 278 279 data[9][c] = fmtMe(((Real)diff.max()).getValue()); 280 data[9][c+1] = " "; 281 282 data[10][c] = fmtMe(((Real)diff.min()).getValue()); 283 data[10][c+1] = " "; 284 285 data[11][c] = fmtMe(((Real)diff.mean()).getValue()); 286 data[11][c+1] = " "; 287 288 if (c == 1) { 289 data[12][c] = " "; 290 } else { 291 data[12][c] = fmtMe(total_area); 292 } 293 data[12][c+1] = " "; 294 295 if (c+2 > numCols) numCols = c+2; 296 fireTableStructureChanged(); 297 298 } catch (VisADException exc) { 299 System.out.println(exc.getMessage()); 300 } catch (Exception exc) { 301 exc.printStackTrace(); 302 } 303 304 if (isShowing) statsWindow.setVisible(true); 305 } 306 307 private String fmtMe(double val) { 308 309 if (Math.abs(val) == 0.0) { 310 return "0.00"; 311 312 } else if (Math.abs(val) > 9999.9 || Math.abs(val) < .0010) { 313 return String.format("%.6e", val); 314 315 } else if (Math.abs(val) < 1.0) { 316 return String.format("%.5f", val); 317 318 } else if (Math.abs(val) < 10.0) { 319 return String.format("%.3f", val); 320 321 } else { 322 return String.format("%.2f", val); 323 } 324 } 325 326 public void setPoints(float[][] markScatter, int len, int indx, double area) { 327 try { 328 total_area = area; 329 Integer1DSet sdset = new Integer1DSet(len); 330 FlatField scattX = new FlatField( 331 new FunctionType(RealType.Generic, RealType.Generic), sdset); 332 333 float[][] scattValsX = new float[1][len]; 334 System.arraycopy(markScatter[0],0,scattValsX[0],0,len); 335 scattX.setSamples(scattValsX, false); 336 337 FlatField scattY = new FlatField( 338 new FunctionType(RealType.Generic, RealType.Generic), sdset); 339 float[][] scattValsY = new float[1][len]; 340 System.arraycopy(markScatter[1],0,scattValsY[0],0,len); 341 scattY.setSamples(scattValsY, false); 342 343 setFields(scattX, scattY, indx); 344 345 } catch (Exception esd) { 346 esd.printStackTrace(); 347 } 348 } 349 350 public int getRowCount() { 351 return maxRows; 352 } 353 public int getColumnCount() { 354 return numCols; 355 } 356 public String getValueAt(int row, int col) { 357 return data[row][col]; 358 } 359 public String getColumnName(int col) { 360 return colNames[col]; 361 } 362 }