001 /* 002 * $Id: ScatterDisplay.java,v 1.61 2012/04/10 19:34:07 rink Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2012 007 * Space Science and Engineering Center (SSEC) 008 * University of Wisconsin - Madison 009 * 1225 W. Dayton Street, Madison, WI 53706, USA 010 * https://www.ssec.wisc.edu/mcidas 011 * 012 * All Rights Reserved 013 * 014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 015 * some McIDAS-V source code is based on IDV and VisAD source code. 016 * 017 * McIDAS-V is free software; you can redistribute it and/or modify 018 * it under the terms of the GNU Lesser Public License as published by 019 * the Free Software Foundation; either version 3 of the License, or 020 * (at your option) any later version. 021 * 022 * McIDAS-V is distributed in the hope that it will be useful, 023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 025 * GNU Lesser Public License for more details. 026 * 027 * You should have received a copy of the GNU Lesser Public License 028 * along with this program. If not, see http://www.gnu.org/licenses. 029 */ 030 031 032 package edu.wisc.ssec.mcidasv.control; 033 034 import java.awt.BorderLayout; 035 import java.awt.Color; 036 import java.awt.Component; 037 import java.awt.Container; 038 import java.awt.Dimension; 039 import java.awt.FlowLayout; 040 import java.awt.GridLayout; 041 import java.awt.event.ActionEvent; 042 import java.awt.event.ActionListener; 043 import java.awt.event.WindowEvent; 044 import java.awt.event.WindowAdapter; 045 import java.awt.geom.Rectangle2D; 046 import java.net.URL; 047 import java.rmi.RemoteException; 048 import java.util.ArrayList; 049 import java.util.List; 050 import java.io.PrintWriter; 051 import java.io.File; 052 053 import javax.swing.JFrame; 054 import javax.swing.ButtonGroup; 055 import javax.swing.ImageIcon; 056 import javax.swing.JComponent; 057 import javax.swing.JPanel; 058 import javax.swing.JRadioButton; 059 import javax.swing.JToggleButton; 060 import javax.swing.JButton; 061 import javax.swing.JScrollPane; 062 import javax.swing.JTable; 063 import javax.swing.JFileChooser; 064 import javax.swing.filechooser.FileFilter; 065 import javax.swing.filechooser.FileNameExtensionFilter; 066 import javax.swing.table.AbstractTableModel; 067 import javax.swing.table.TableCellRenderer; 068 import javax.swing.border.CompoundBorder; 069 import javax.swing.border.EmptyBorder; 070 import javax.swing.border.LineBorder; 071 072 import org.slf4j.Logger; 073 import org.slf4j.LoggerFactory; 074 075 import visad.AxisScale; 076 import visad.BaseColorControl; 077 import visad.CellImpl; 078 import visad.CoordinateSystem; 079 import visad.Data; 080 import visad.DelaunayCustom; 081 import visad.DisplayEvent; 082 import visad.DisplayListener; 083 import visad.Real; 084 import visad.FieldImpl; 085 import visad.FlatField; 086 import visad.FunctionType; 087 import visad.Gridded2DSet; 088 import visad.Gridded3DSet; 089 import visad.Integer1DSet; 090 import visad.Linear2DSet; 091 import visad.LinearLatLonSet; 092 import visad.RealTupleType; 093 import visad.MathType; 094 import visad.RealType; 095 import visad.SampledSet; 096 import visad.ScalarMap; 097 import visad.Set; 098 import visad.SetType; 099 import visad.UnionSet; 100 import visad.VisADException; 101 import visad.data.mcidas.BaseMapAdapter; 102 import visad.georef.MapProjection; 103 import visad.georef.TrivialMapProjection; 104 import visad.python.JPythonMethods; 105 106 import ucar.unidata.data.DataAlias; 107 import ucar.unidata.data.DataChoice; 108 import ucar.unidata.data.DataSelection; 109 import ucar.unidata.data.grid.GridUtil; 110 import ucar.unidata.idv.DisplayConventions; 111 import ucar.unidata.idv.control.ColorTableWidget; 112 import ucar.unidata.idv.control.DisplayControlImpl; 113 import ucar.unidata.ui.colortable.ColorTableManager; 114 import ucar.unidata.util.ColorTable; 115 import ucar.unidata.util.LogUtil; 116 import ucar.unidata.util.Range; 117 import ucar.unidata.view.geoloc.MapProjectionDisplay; 118 import ucar.unidata.view.geoloc.MapProjectionDisplayJ3D; 119 import ucar.visad.display.DisplayMaster; 120 import ucar.visad.display.LineDrawing; 121 import ucar.visad.display.MapLines; 122 import ucar.visad.display.RGBDisplayable; 123 import ucar.visad.display.RubberBandBox; 124 import ucar.visad.display.XYDisplay; 125 126 import edu.wisc.ssec.mcidasv.data.hydra.CurveDrawer; 127 import edu.wisc.ssec.mcidasv.data.hydra.HistogramField; 128 import edu.wisc.ssec.mcidasv.data.hydra.HydraRGBDisplayable; 129 import edu.wisc.ssec.mcidasv.data.hydra.MultiSpectralData; 130 import edu.wisc.ssec.mcidasv.data.hydra.SubsetRubberBandBox; 131 import edu.wisc.ssec.mcidasv.data.hydra.LongitudeLatitudeCoordinateSystem; 132 import edu.wisc.ssec.mcidasv.data.hydra.Statistics; 133 134 public class ScatterDisplay extends DisplayControlImpl { 135 136 private static final Logger logger = LoggerFactory.getLogger(ScatterDisplay.class); 137 138 private Container container; 139 private FlatField X_field; 140 private FlatField Y_field; 141 private FlatField Area_field; 142 private double total_area; 143 private DisplayMaster scatterMaster = null; 144 145 private DisplayMaster dspMasterX; 146 private DisplayMaster dspMasterY; 147 148 private HistogramField histoField; 149 150 private FlatField mask_field; 151 private float[][] mask_range; 152 private float[][] scatterFieldRange; 153 private Data X_data; 154 private Data Y_data; 155 private String X_name; 156 private String Y_name; 157 158 private boolean cancel = false; 159 160 private ScatterDisplayable scatterMarkDsp; 161 162 private BoxCurveSwitch boxCurveSwitch; 163 164 public DataChoice dataChoiceX = null; 165 166 public DataChoice dataChoiceY = null; 167 168 public DataSelection dataSelectionX = null; 169 170 public DataSelection dataSelectionY = null; 171 172 JComponent ctwCompX; 173 174 JComponent ctwCompY; 175 176 ColorTableWidget ctw; 177 178 int n_selectors = 3; 179 180 List<ScatterBoxSelector> scatterBoxSelectors = new ArrayList<ScatterBoxSelector>(); 181 182 List<ScatterCurveSelector> scatterCurveSelectors = new ArrayList<ScatterCurveSelector>(); 183 184 List<ImageBoxSelector> imageXBoxSelectors = new ArrayList<ImageBoxSelector>(); 185 186 List<ImageBoxSelector> imageYBoxSelectors = new ArrayList<ImageBoxSelector>(); 187 188 List<ImageCurveSelector> imageXCurveSelectors = new ArrayList<ImageCurveSelector>(); 189 190 List<ImageCurveSelector> imageYCurveSelectors = new ArrayList<ImageCurveSelector>(); 191 192 JToggleButton[] selectorToggleButtons = new JToggleButton[n_selectors]; 193 Color[] selectorColors = new Color[] {Color.magenta, Color.green, Color.blue}; 194 float[][] maskColorPalette = new float[][] {{0.8f,0f,0f},{0f,0.8f,0f},{0.8f,0f,0.8f}}; 195 float[][] markColorPalette = new float[][] {{1f,0.8f,0f,0f},{1f,0f,0.8f,0f},{1f,0.8f,0f,0.8f}}; 196 197 JButton computeStatsButton; 198 MyStatsTable statsTable; 199 200 boolean selectByCurve = false; 201 202 public ScatterDisplay() { 203 super(); 204 setHelpUrl("idv.controls.misc.scatteranalysiscontrol"); 205 } 206 207 208 @Override public boolean init(List choices) throws VisADException, RemoteException { 209 if ((dataChoiceX != null) && (dataChoiceY != null)) { 210 setupFromUnpersistence(); 211 } 212 else { 213 try { 214 setup(); 215 } catch (VisADException vade) { 216 return false; 217 } 218 } 219 220 mask_field = new FlatField( 221 new FunctionType(((FunctionType)X_field.getType()).getDomain(), RealType.Generic), 222 X_field.getDomainSet()); 223 224 int len = X_field.getDomainSet().getLength(); 225 mask_range = new float[1][len]; 226 for (int t=0; t<len; t++) { 227 mask_range[0][t] = Float.NaN; 228 } 229 mask_range[0][0] = 0; //- field should not be all missing 230 mask_field.setSamples(mask_range, false); 231 232 try { 233 histoField = new HistogramField(X_field, Y_field, mask_field, 100, 10); 234 } 235 catch (Exception e) { 236 e.printStackTrace(); 237 } 238 239 Range rangeX = getImageRange(X_field); 240 Range rangeY = getImageRange(Y_field); 241 ColorTable clrTableX = getColorTable(X_field); 242 ColorTable clrTableY = getColorTable(Y_field); 243 244 dspMasterX = makeImageDisplay(getDataProjection(X_field), X_field, mask_field, 245 rangeX, clrTableX); 246 247 dspMasterY = makeImageDisplay(getDataProjection(Y_field), Y_field, mask_field, 248 rangeY, clrTableY); 249 250 dspMasterX.addDisplayListener(new DisplayListener() { 251 @Override public void displayChanged(final DisplayEvent e) { 252 double[] xProjection = dspMasterX.getProjectionMatrix(); 253 double[] yProjection = dspMasterY.getProjectionMatrix(); 254 if (xProjection.equals(yProjection)) 255 return; 256 257 try { 258 dspMasterY.setProjectionMatrix(xProjection); 259 } catch (Exception ex) { 260 LogUtil.logException("dspMasterX.displayChanged", ex); 261 } 262 } 263 }); 264 265 dspMasterY.addDisplayListener(new DisplayListener() { 266 @Override public void displayChanged(final DisplayEvent e) { 267 double[] xProjection = dspMasterX.getProjectionMatrix(); 268 double[] yProjection = dspMasterY.getProjectionMatrix(); 269 if (yProjection.equals(xProjection)) 270 return; 271 272 try { 273 dspMasterX.setProjectionMatrix(yProjection); 274 } catch (Exception ex) { 275 LogUtil.logException("dspMasterX.displayChanged", ex); 276 } 277 } 278 }); 279 280 X_name = ((((FunctionType)X_field.getType()).getFlatRange().getRealComponents())[0]).getName(); 281 Y_name = ((((FunctionType)Y_field.getType()).getFlatRange().getRealComponents())[0]).getName(); 282 283 if (statsTable != null) statsTable.setNames(X_name, Y_name); 284 285 Grid2DReadoutProbe probeX = new Grid2DReadoutProbe(X_field, dspMasterX); 286 Grid2DReadoutProbe probeY = new Grid2DReadoutProbe(Y_field, dspMasterY); 287 probeX.doMakeProbe(Color.red, dspMasterX); 288 probeY.doMakeProbe(Color.red, dspMasterY); 289 290 ImageControl dCntrl = new ImageControl((HydraRGBDisplayable)dspMasterX.getDisplayables(0), getDisplayConventions()); 291 ctw = new ColorTableWidget(dCntrl, ColorTableManager.getManager(), clrTableX, rangeX); 292 ctwCompX = ctw.getLegendPanel(BOTTOM_LEGEND); 293 dCntrl.ctw = ctw; 294 295 dCntrl = new ImageControl((HydraRGBDisplayable)dspMasterY.getDisplayables(0), getDisplayConventions()); 296 ctw = new ColorTableWidget(dCntrl, ColorTableManager.getManager(), clrTableY, rangeY); 297 ctwCompY = ctw.getLegendPanel(BOTTOM_LEGEND); 298 dCntrl.ctw = ctw; 299 300 return true; 301 } 302 303 public void setup() throws VisADException, RemoteException { 304 dataSelectionX = getDataSelection(); 305 dataChoiceX = getDataChoice(); 306 X_data = dataChoiceX.getData(dataSelectionX); 307 308 if (X_data instanceof FlatField) { 309 X_field = (FlatField) X_data; 310 } else if (X_data instanceof FieldImpl) { 311 X_field = (FlatField) ((FieldImpl)X_data).getSample(0); 312 } 313 314 popupDataDialog("select Y Axis field", container, false, null); 315 316 // if user canceled the popup, popupDataDialog will set the cancel flag 317 if (cancel) throw new VisADException("Scatter Display Canceled"); 318 319 dataSelectionY = getDataSelection(); 320 dataChoiceY = getDataChoice(); 321 322 dataSelectionY.setGeoSelection(dataSelectionX.getGeoSelection()); 323 324 Y_data = dataChoiceY.getData(dataSelectionY); 325 326 if (Y_data instanceof FlatField) { 327 Y_field = (FlatField) Y_data; 328 } else if (Y_data instanceof FieldImpl) { 329 Y_field = (FlatField) ((FieldImpl)Y_data).getSample(0); 330 } 331 332 if (!( X_field.getDomainSet().equals(Y_field.getDomainSet()))) 333 { 334 Y_field = resample(X_field, Y_field); 335 } 336 337 Area_field = JPythonMethods.createAreaField(X_field); 338 statsTable = new MyStatsTable(); 339 340 } 341 342 public void setupFromUnpersistence() throws VisADException, RemoteException { 343 X_data = dataChoiceX.getData(dataSelectionX); 344 if (X_data instanceof FlatField) { 345 X_field = (FlatField) X_data; 346 } else if (X_data instanceof FieldImpl) { 347 X_field = (FlatField) ((FieldImpl)X_data).getSample(0); 348 } 349 350 Y_data = dataChoiceY.getData(dataSelectionY); 351 if (Y_data instanceof FlatField) { 352 Y_field = (FlatField) Y_data; 353 } else if (X_data instanceof FieldImpl) { 354 Y_field = (FlatField) ((FieldImpl)Y_data).getSample(0); 355 } 356 } 357 358 @Override protected void popupDataDialog(final String dialogMessage, 359 Component from, boolean multiples, 360 List categories) { 361 362 List<DataChoice> choices = selectDataChoices(dialogMessage, from, 363 multiples, categories); 364 if ((choices == null) || (choices.size() == 0)) { 365 logger.debug("popupDataDialog, no data choice, user canceled"); 366 cancel = true; 367 return; 368 } 369 final List clonedList = 370 DataChoice.cloneDataChoices((List)choices.get(0)); 371 dataSelection = ((DataChoice) clonedList.get(0)).getDataSelection(); 372 //- don't do this in a separate thread like the IDV does. 373 //- We want the dataChoice list updated before return. 374 try { 375 addNewData(clonedList); 376 } catch (Exception exc) { 377 logException("Selecting new data", exc); 378 } 379 } 380 381 382 @Override public void initDone() { 383 try { 384 DisplayMaster master = makeScatterDisplay(); 385 for (int k=0; k<n_selectors; k++) { 386 scatterBoxSelectors.add(new ScatterBoxSelector(master, selectorColors[k], (float)k)); 387 scatterCurveSelectors.add(new ScatterCurveSelector(master, selectorColors[k], (float)k)); 388 } 389 master.draw(); 390 391 for (int k=0; k<n_selectors; k++) { 392 SubsetRubberBandBox X_subsetBox = 393 new SubsetRubberBandBox(getIsLatLon(X_field), X_field, 394 ((MapProjectionDisplayJ3D)dspMasterX).getDisplayCoordinateSystem(), 1, false); 395 X_subsetBox.setColor(selectorColors[k]); 396 397 ImageBoxSelector markX = new ImageBoxSelector(X_subsetBox, X_field.getDomainSet(), dspMasterX, selectorColors[k], (float)k+1, statsTable); 398 399 SubsetRubberBandBox Y_subsetBox = 400 new SubsetRubberBandBox(getIsLatLon(Y_field), Y_field, 401 ((MapProjectionDisplayJ3D)dspMasterY).getDisplayCoordinateSystem(), 1, false); 402 Y_subsetBox.setColor(selectorColors[k]); 403 ImageBoxSelector markY = new ImageBoxSelector(Y_subsetBox, Y_field.getDomainSet(), dspMasterY, selectorColors[k], (float)k+1, statsTable); 404 405 markX.setOther(markY); 406 markY.setOther(markX); 407 imageXBoxSelectors.add(markX); 408 imageYBoxSelectors.add(markY); 409 } 410 411 for (int k=0; k<n_selectors; k++) { 412 CurveDrawer curveDraw = new CurveDrawer(RealType.Longitude, RealType.Latitude, 1); 413 curveDraw.setColor(selectorColors[k]); 414 curveDraw.setLineWidth(2); 415 ImageCurveSelector curveX = new ImageCurveSelector(curveDraw, X_field, dspMasterX, selectorColors[k], (float) k+1, statsTable); 416 curveX.setActive(false); 417 curveDraw.addAction(curveX); 418 curveX.setVisible(false); 419 dspMasterX.addDisplayable(curveDraw); 420 421 curveDraw = new CurveDrawer(RealType.Longitude, RealType.Latitude, 1); 422 curveDraw.setColor(selectorColors[k]); 423 curveDraw.setLineWidth(2); 424 ImageCurveSelector curveY = new ImageCurveSelector(curveDraw, Y_field, dspMasterY, selectorColors[k], (float) k+1, statsTable); 425 curveY.setActive(false); 426 curveDraw.addAction(curveY); 427 curveY.setVisible(false); 428 dspMasterY.addDisplayable(curveDraw); 429 430 curveX.setOther(curveY); 431 curveY.setOther(curveX); 432 imageXCurveSelectors.add(curveX); 433 imageYCurveSelectors.add(curveY); 434 } 435 436 for (int k=0; k<n_selectors; k++) { 437 JToggleButton jtog = selectorToggleButtons[k]; 438 439 jtog.addActionListener(new ActionListener() { 440 @Override public void actionPerformed(ActionEvent e) { 441 int idx = Integer.valueOf(e.getActionCommand()); 442 try { 443 for (int i=0; i<n_selectors; i++) { 444 ScatterBoxSelector boxSel = (ScatterBoxSelector) scatterBoxSelectors.get(i); 445 ImageBoxSelector imageXbox = (ImageBoxSelector) imageXBoxSelectors.get(i); 446 ImageBoxSelector imageYbox = (ImageBoxSelector) imageYBoxSelectors.get(i); 447 ScatterCurveSelector curveSel = (ScatterCurveSelector) scatterCurveSelectors.get(i); 448 ImageCurveSelector imageXcurve = (ImageCurveSelector) imageXCurveSelectors.get(i); 449 ImageCurveSelector imageYcurve = (ImageCurveSelector) imageYCurveSelectors.get(i); 450 451 if (i == idx) { 452 if (!selectorToggleButtons[i].isSelected()) { 453 454 if (statsTable != null) statsTable.resetValues(i); 455 456 boxSel.setActive(false); 457 boxSel.setVisible(false); 458 boxSel.reset(); 459 imageXbox.setActive(false); 460 imageXbox.setVisible(false); 461 imageXbox.reset(); 462 imageYbox.setActive(false); 463 imageYbox.setVisible(false); 464 imageYbox.reset(); 465 466 curveSel.setActive(false); 467 curveSel.setVisible(false); 468 curveSel.reset(); 469 imageXcurve.setActive(false); 470 imageXcurve.setVisible(false); 471 imageXcurve.reset(); 472 imageYcurve.setActive(false); 473 imageYcurve.setVisible(false); 474 imageYcurve.reset(); 475 476 477 } 478 boxSel.setActive(!getSelectByCurve()); 479 boxSel.setVisible(!getSelectByCurve()); 480 imageXbox.setActive(!getSelectByCurve()); 481 imageXbox.setVisible(!getSelectByCurve()); 482 imageYbox.setActive(!getSelectByCurve()); 483 imageYbox.setVisible(!getSelectByCurve()); 484 485 curveSel.setActive(getSelectByCurve()); 486 curveSel.setVisible(getSelectByCurve()); 487 imageXcurve.setActive(getSelectByCurve()); 488 imageXcurve.setVisible(getSelectByCurve()); 489 imageYcurve.setActive(getSelectByCurve()); 490 imageYcurve.setVisible(getSelectByCurve()); 491 } 492 else { 493 selectorToggleButtons[i].setSelected(false); 494 boxSel.setActive(false); 495 boxSel.setVisible(false); 496 imageXbox.setActive(false); 497 imageXbox.setVisible(false); 498 imageYbox.setActive(false); 499 imageYbox.setVisible(false); 500 curveSel.setActive(false); 501 curveSel.setVisible(false); 502 imageXcurve.setActive(false); 503 imageXcurve.setVisible(false); 504 imageYcurve.setActive(false); 505 imageYcurve.setVisible(false); 506 } 507 } 508 } 509 catch (Exception exc) { 510 System.out.println(exc); 511 } 512 }}); 513 514 ScatterBoxSelector boxSel = (ScatterBoxSelector) scatterBoxSelectors.get(k); 515 ImageBoxSelector imageXbox = (ImageBoxSelector) imageXBoxSelectors.get(k); 516 ImageBoxSelector imageYbox = (ImageBoxSelector) imageYBoxSelectors.get(k); 517 ScatterCurveSelector curveSel = (ScatterCurveSelector) scatterCurveSelectors.get(k); 518 ImageCurveSelector imageXcurve = (ImageCurveSelector) imageXCurveSelectors.get(k); 519 ImageCurveSelector imageYcurve = (ImageCurveSelector) imageYCurveSelectors.get(k); 520 521 if (k == 0) { 522 jtog.setSelected(true); 523 boxSel.setActive(!getSelectByCurve()); 524 boxSel.setVisible(!getSelectByCurve()); 525 imageXbox.setActive(!getSelectByCurve()); 526 imageXbox.setVisible(!getSelectByCurve()); 527 imageYbox.setActive(!getSelectByCurve()); 528 imageYbox.setVisible(!getSelectByCurve()); 529 530 curveSel.setActive(getSelectByCurve()); 531 curveSel.setVisible(getSelectByCurve()); 532 imageXcurve.setActive(getSelectByCurve()); 533 imageXcurve.setVisible(getSelectByCurve()); 534 imageYcurve.setActive(getSelectByCurve()); 535 imageYcurve.setVisible(getSelectByCurve()); 536 } 537 else { 538 boxSel.setActive(false); 539 boxSel.setVisible(false); 540 imageXbox.setActive(false); 541 imageXbox.setVisible(false); 542 imageYbox.setActive(false); 543 imageYbox.setVisible(false); 544 curveSel.setActive(false); 545 curveSel.setVisible(false); 546 imageXcurve.setActive(false); 547 imageXcurve.setVisible(false); 548 imageYcurve.setActive(false); 549 imageYcurve.setVisible(false); 550 } 551 } 552 } 553 catch (Exception e) { 554 e.printStackTrace(); 555 } 556 } 557 558 public DisplayMaster makeScatterDisplay() throws VisADException, RemoteException { 559 560 ScatterDisplayable scatterDsp = new ScatterDisplayable("scatter", 561 RealType.getRealType("mask"), markColorPalette, false); 562 float[] valsX = X_field.getFloats(false)[0]; 563 float[] valsY = Y_field.getFloats(false)[0]; 564 Integer1DSet set = new Integer1DSet(valsX.length); 565 FlatField scatter = new FlatField( 566 new FunctionType(RealType.Generic, 567 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), set); 568 float[] mask = new float[valsX.length]; 569 for (int k=0; k<mask.length; k++) mask[k] = 0; 570 scatterFieldRange = new float[][] {valsX, valsY, mask}; 571 scatter.setSamples(scatterFieldRange); 572 scatterDsp.setPointSize(2f); 573 scatterDsp.setRangeForColor(0,n_selectors); 574 575 float[] xRange = minmax(valsX); 576 float[] yRange = minmax(valsY); 577 578 scatterDsp.setData(scatter); 579 580 scatterMarkDsp = new ScatterDisplayable("scatter", 581 RealType.getRealType("mask"), markColorPalette, false); 582 set = new Integer1DSet(2); 583 scatter = new FlatField( 584 new FunctionType(RealType.Generic, 585 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), set); 586 scatterMarkDsp.setData(scatter); 587 scatterMarkDsp.setPointSize(2f); 588 scatterMarkDsp.setRangeForColor(0,n_selectors); 589 590 DisplayMaster master = scatterMaster; 591 ((XYDisplay)master).showAxisScales(true); 592 AxisScale scaleX = ((XYDisplay)master).getXAxisScale(); 593 scaleX.setTitle(X_name); 594 AxisScale scaleY = ((XYDisplay)master).getYAxisScale(); 595 scaleY.setTitle(Y_name); 596 597 ((XYDisplay)master).setXRange((double)xRange[0], (double)xRange[1]); 598 ((XYDisplay)master).setYRange((double)yRange[0], (double)yRange[1]); 599 master.addDisplayable(scatterDsp); 600 master.addDisplayable(scatterMarkDsp); 601 602 return master; 603 } 604 605 606 @Override public Container doMakeContents() { 607 JPanel pane = new JPanel(new GridLayout(1,3)); 608 609 Component[] comps = new Component[] {null, null, null}; 610 comps[0] = dspMasterX.getComponent(); 611 comps[1] = dspMasterY.getComponent(); 612 comps[2] = getScatterTabComponent(); 613 614 JPanel panelX = new JPanel(new BorderLayout()); 615 panelX.setBorder(new EmptyBorder(4,4,4,4)); 616 panelX.add(comps[0], BorderLayout.CENTER); 617 panelX.add(ctwCompX, BorderLayout.SOUTH); 618 619 JPanel panelY = new JPanel(new BorderLayout()); 620 panelY.setBorder(new EmptyBorder(4,4,4,4)); 621 panelY.add(comps[1], BorderLayout.CENTER); 622 panelY.add(ctwCompY, BorderLayout.SOUTH); 623 624 JPanel panelS = new JPanel(new BorderLayout()); 625 panelS.setBorder(new EmptyBorder(4,4,4,4)); 626 panelS.add(comps[2], BorderLayout.CENTER); 627 628 pane.add(panelX); 629 pane.add(panelY); 630 pane.add(panelS); 631 632 633 JPanel buttonPanel = new JPanel(); 634 buttonPanel.setLayout(new FlowLayout()); 635 JRadioButton boxSelect = new JRadioButton("Box"); 636 boxSelect.setSelected(true); 637 JRadioButton curveSelect = new JRadioButton("Curve"); 638 ButtonGroup buttonGroup = new ButtonGroup(); 639 buttonGroup.add(boxSelect); 640 buttonGroup.add(curveSelect); 641 buttonPanel.add(boxSelect); 642 buttonPanel.add(curveSelect); 643 644 boxCurveSwitch = new BoxCurveSwitch(); 645 boxSelect.addActionListener(boxCurveSwitch); 646 curveSelect.addActionListener(boxCurveSwitch); 647 648 649 JPanel toggleButtonPanel = new JPanel(new FlowLayout()); 650 for (int k=0; k<n_selectors; k++) { 651 JToggleButton jtog = 652 new JToggleButton( 653 new ImageIcon(getClass().getResource("/edu/wisc/ssec/mcidasv/resources/icons/buttons/subset12.jpg"))); 654 jtog.setBorder(new CompoundBorder(new LineBorder(selectorColors[k],2), new EmptyBorder(4,4,4,4))); 655 jtog.setActionCommand(String.valueOf(k)); 656 toggleButtonPanel.add(jtog); 657 selectorToggleButtons[k] = jtog; 658 } 659 660 buttonPanel.add(toggleButtonPanel); 661 662 JButton computeStatsButton = new JButton("compute statistics"); 663 664 computeStatsButton.addActionListener(new ActionListener() { 665 public void actionPerformed(final ActionEvent e) { 666 667 if (statsTable == null) { 668 statsTable = new MyStatsTable(); 669 } 670 671 statsTable.setIsShowing(); 672 statsTable.setFields(X_field, Y_field,0); 673 } 674 }); 675 676 buttonPanel.add(computeStatsButton); 677 678 //-container = pane; 679 JPanel new_pane = new JPanel(new BorderLayout()); 680 new_pane.add(pane, BorderLayout.CENTER); 681 new_pane.add(buttonPanel, BorderLayout.SOUTH); 682 container = new_pane; 683 return container; 684 } 685 686 687 protected Component getScatterTabComponent() { 688 try { 689 scatterMaster = new XYDisplay("Scatter", RealType.XAxis, RealType.YAxis); 690 } catch (Exception e) { 691 e.printStackTrace(); 692 } 693 return scatterMaster.getComponent(); 694 } 695 696 public DisplayMaster makeImageDisplay(MapProjection mapProj, FlatField image, 697 FlatField mask_image, Range imageRange, ColorTable colorTable) 698 throws VisADException, RemoteException { 699 MapProjectionDisplayJ3D mapProjDsp; 700 DisplayMaster dspMaster; 701 702 mapProjDsp = new MapProjectionDisplayJ3D(MapProjectionDisplay.MODE_2Din3D); 703 mapProjDsp.enableRubberBanding(false); 704 dspMaster = mapProjDsp; 705 mapProjDsp.setMapProjection(mapProj); 706 707 RealType imageRangeType = 708 (((FunctionType)image.getType()).getFlatRange().getRealComponents())[0]; 709 710 boolean alphaflag = false; 711 HydraRGBDisplayable imageDsp = new HydraRGBDisplayable("image", imageRangeType, null, alphaflag, null); 712 713 imageDsp.setData(image); 714 dspMaster.addDisplayable(imageDsp); 715 addMapDisplayables(mapProjDsp); 716 717 if (mask_image != null) { 718 RGBDisplayable maskDsp = 719 new ScatterDisplayable("mask", RealType.Generic, maskColorPalette, false); 720 maskDsp.setData(mask_image); 721 maskDsp.setRangeForColor(0, n_selectors-1); 722 dspMaster.addDisplayable(maskDsp); 723 } 724 725 dspMaster.draw(); 726 727 ScalarMap colorMap = imageDsp.getColorMap(); 728 colorMap.setRange(imageRange.getMin(), imageRange.getMax()); 729 BaseColorControl clrCntrl = (BaseColorControl) colorMap.getControl(); 730 float[][] ct = colorTable.getColorTable(); 731 732 if ( !(alphaflag) && (ct.length == 4) ) { 733 float[][] new_ct = new float[3][]; 734 new_ct[0] = ct[0]; 735 new_ct[1] = ct[1]; 736 new_ct[2] = ct[2]; 737 ct = new_ct; 738 } 739 740 clrCntrl.setTable(ct); 741 742 return dspMaster; 743 } 744 745 public Range getImageRange(FlatField image) 746 throws VisADException, RemoteException { 747 DisplayConventions dc = getDisplayConventions(); 748 Range[] range = GridUtil.fieldMinMax(image); 749 Range imageRange = range[0]; 750 RealType imageRangeType = 751 (((FunctionType)image.getType()).getFlatRange().getRealComponents())[0]; 752 String canonicalName = DataAlias.aliasToCanonical(imageRangeType.getName()); 753 Range dfltRange = dc.getParamRange(canonicalName, null); 754 755 if (dfltRange == null) { 756 imageRange = range[0]; 757 } 758 else if ((imageRange.getMax() - imageRange.getMin()) < (dfltRange.getMax() - dfltRange.getMin())) { 759 } 760 else { 761 imageRange = dfltRange; 762 } 763 return imageRange; 764 } 765 766 public ColorTable getColorTable(FlatField image) 767 throws VisADException, RemoteException { 768 RealType imageRangeType = 769 (((FunctionType)image.getType()).getFlatRange().getRealComponents())[0]; 770 DisplayConventions dc = getDisplayConventions(); 771 return dc.getParamColorTable(imageRangeType.getName()); 772 } 773 774 775 public MapProjection getDataProjection(FlatField image) 776 throws VisADException, RemoteException { 777 MapProjection mp = null; 778 //- get MapProjection from incoming image. If none, use default method 779 FunctionType fnc_type = (FunctionType) image.getType(); 780 RealTupleType rtt = fnc_type.getDomain(); 781 CoordinateSystem cs = rtt.getCoordinateSystem(); 782 Set domainSet = image.getDomainSet(); 783 784 if (cs instanceof visad.CachingCoordinateSystem) { 785 cs = ((visad.CachingCoordinateSystem)cs).getCachedCoordinateSystem(); 786 } 787 788 if (cs instanceof MapProjection) { 789 return (MapProjection) cs; 790 } 791 else if (cs instanceof LongitudeLatitudeCoordinateSystem) { 792 Rectangle2D rect = MultiSpectralData.getLonLatBoundingBox(image); 793 try { 794 mp = new LambertAEA(rect); 795 } catch (Exception e) { 796 System.out.println(" getDataProjection"+e); 797 } 798 return mp; 799 } 800 801 float minLon = Float.NaN; 802 float minLat = Float.NaN; 803 float delLon = Float.NaN; 804 float delLat = Float.NaN; 805 806 if (domainSet instanceof LinearLatLonSet) { 807 MathType type0 = ((SetType)domainSet.getType()).getDomain().getComponent(0); 808 int latI = RealType.Latitude.equals(type0) ? 0 : 1; 809 int lonI = (latI == 1) ? 0 : 1; 810 811 float[] min = ((LinearLatLonSet)domainSet).getLow(); 812 float[] max = ((LinearLatLonSet)domainSet).getHi(); 813 minLon = min[lonI]; 814 minLat = min[latI]; 815 delLon = max[lonI] - min[lonI]; 816 delLat = max[latI] - min[latI]; 817 818 try { 819 mp = new TrivialMapProjection(RealTupleType.SpatialEarth2DTuple, 820 new Rectangle2D.Float(minLon, minLat, delLon, delLat)); 821 } catch (Exception e) { 822 logException("MultiSpectralControl.getDataProjection", e); 823 } 824 825 return mp; 826 } 827 else if (domainSet instanceof Gridded2DSet) { 828 rtt = ((SetType)domainSet.getType()).getDomain(); 829 rtt = RealTupleType.SpatialEarth2DTuple; 830 if (!(rtt.equals(RealTupleType.SpatialEarth2DTuple) || rtt.equals(RealTupleType.LatitudeLongitudeTuple))) { 831 minLon = -180f; 832 minLat = -90f; 833 delLon = 360f; 834 delLat = 180f; 835 } 836 else { 837 int latI = rtt.equals(RealTupleType.SpatialEarth2DTuple) ? 1 : 0; 838 int lonI = (latI == 1) ? 0 : 1; 839 840 float[] min = ((Gridded2DSet)domainSet).getLow(); 841 float[] max = ((Gridded2DSet)domainSet).getHi(); 842 minLon = min[lonI]; 843 minLat = min[latI]; 844 delLon = max[lonI] - min[lonI]; 845 delLat = max[latI] - min[latI]; 846 } 847 } 848 849 try { 850 mp = new TrivialMapProjection(RealTupleType.SpatialEarth2DTuple, 851 new Rectangle2D.Float(minLon, minLat, delLon, delLat)); 852 } catch (Exception e) { 853 logException("MultiSpectralControl.getDataProjection", e); 854 } 855 856 return mp; 857 } 858 859 public void addMapDisplayables(MapProjectionDisplayJ3D mapProjDsp) 860 throws VisADException, RemoteException { 861 MapLines mapLines = new MapLines("maplines"); 862 URL mapSource = 863 mapProjDsp.getClass().getResource("/auxdata/maps/OUTLSUPU"); 864 try { 865 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 866 mapLines.setMapLines(mapAdapter.getData()); 867 mapLines.setColor(java.awt.Color.cyan); 868 mapProjDsp.addDisplayable(mapLines); 869 } catch (Exception excp) { 870 System.out.println("Can't open map file " + mapSource); 871 System.out.println(excp); 872 } 873 874 mapLines = new MapLines("maplines"); 875 mapSource = 876 mapProjDsp.getClass().getResource("/auxdata/maps/OUTLSUPW"); 877 try { 878 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 879 mapLines.setMapLines(mapAdapter.getData()); 880 mapLines.setColor(java.awt.Color.cyan); 881 mapProjDsp.addDisplayable(mapLines); 882 } catch (Exception excp) { 883 System.out.println("Can't open map file " + mapSource); 884 System.out.println(excp); 885 } 886 887 mapLines = new MapLines("maplines"); 888 mapSource = 889 mapProjDsp.getClass().getResource("/auxdata/maps/OUTLHPOL"); 890 try { 891 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 892 mapLines.setMapLines(mapAdapter.getData()); 893 mapLines.setColor(java.awt.Color.cyan); 894 mapProjDsp.addDisplayable(mapLines); 895 } catch (Exception excp) { 896 System.out.println("Can't open map file " + mapSource); 897 System.out.println(excp); 898 } 899 } 900 901 public boolean getSelectByCurve() { 902 return selectByCurve; 903 } 904 905 private FlatField resample(FlatField X_field, FlatField Y_field) throws VisADException, RemoteException { 906 907 RealTupleType X_domainRef = null; 908 RealTupleType Y_domainRef = null; 909 float[][] coords = null; 910 int[] indexes = null; 911 float[][] Yvalues = Y_field.getFloats(false); 912 float[][] Xsamples = ((SampledSet)X_field.getDomainSet()).getSamples(false); 913 914 CoordinateSystem X_cs = X_field.getDomainCoordinateSystem(); 915 if (X_cs == null) { 916 RealTupleType X_domain = ((FunctionType)X_field.getType()).getDomain(); 917 } 918 else { 919 X_domainRef = X_cs.getReference(); 920 } 921 922 CoordinateSystem Y_cs = Y_field.getDomainCoordinateSystem(); 923 if (Y_cs == null) { 924 RealTupleType Y_domain = ((FunctionType)Y_field.getType()).getDomain(); 925 } 926 else { 927 Y_domainRef = Y_cs.getReference(); 928 } 929 930 if ( X_domainRef != null && Y_domainRef != null) { 931 Xsamples = X_cs.toReference(Xsamples); 932 coords = Y_cs.fromReference(Xsamples); 933 indexes = ((SampledSet)Y_field.getDomainSet()).valueToIndex(coords); 934 } 935 else if ( X_domainRef == null && Y_domainRef != null ) { 936 Xsamples = Y_cs.fromReference(Xsamples); 937 indexes = ((SampledSet)Y_field.getDomainSet()).valueToIndex(Xsamples); 938 } 939 else if ( X_domainRef != null && Y_domainRef == null) { 940 Xsamples = X_cs.toReference(Xsamples); 941 Gridded2DSet domSet = (Gridded2DSet) Y_field.getDomainSet(); 942 943 // TODO this is a hack for the longitude range problem 944 float[] hi = domSet.getHi(); 945 if (hi[0] <= 180f) { 946 for (int t=0; t<Xsamples[0].length; t++) { 947 if (Xsamples[0][t] > 180f) Xsamples[0][t] -=360; 948 } 949 } 950 951 indexes = ((SampledSet)Y_field.getDomainSet()).valueToIndex(Xsamples); 952 } 953 else if (X_domainRef == null && Y_domainRef == null) { 954 Gridded2DSet domSet = (Gridded2DSet) Y_field.getDomainSet(); 955 indexes = domSet.valueToIndex(Xsamples); 956 } 957 958 float[][] new_values = new float[1][indexes.length]; 959 for (int k=0; k<indexes.length; k++) { 960 new_values[0][k] = Float.NaN; 961 if (indexes[k] >= 0) { 962 new_values[0][k] = Yvalues[0][indexes[k]]; 963 } 964 } 965 966 FunctionType ftype = new FunctionType(((FunctionType)X_field.getType()).getDomain(), 967 ((FunctionType)Y_field.getType()).getRange()); 968 Y_field = new FlatField(ftype, X_field.getDomainSet()); 969 Y_field.setSamples(new_values); 970 971 return Y_field; 972 } 973 974 975 //For creating a non-editable JTable 976 private class MyStatsTable extends AbstractTableModel { 977 String [][] data; 978 JTable table; 979 JFrame statsWindow; 980 int numCols; 981 boolean isShowing = false; 982 Color[] coltab = {new Color(0xf0f0f0), new Color(0xffd0ff), 983 new Color(0xd0ffd0), new Color(0xc0d0ff)}; 984 985 final int maxCols = 9; 986 String[] colNames = {"Stats Parameter","Whole Field X","Whole Field Y", 987 "Magenta X","Magenta Y", "Green X","Green Y","Blue X","Blue Y"}; 988 989 final int maxRows = 13; 990 final String[] rowNames = {"Maximum","Minimum", 991 "Number of points","Mean","Median","Variance","Kurtosis", 992 "Std Dev","Correlation","Difference Maximum", 993 "Difference Minimum","Difference Mean","Area [km^2]"}; 994 995 MyStatsTable() { super(); 996 data = new String[maxRows][maxCols]; 997 numCols = 1; 998 999 for (int i=0; i<maxRows; i++) { 1000 data[i][0] = rowNames[i]; 1001 for (int j=1; j<maxCols; j++) { 1002 data[i][j] = " "; 1003 } 1004 } 1005 1006 1007 table = new JTable(this) { 1008 public Component prepareRenderer( 1009 TableCellRenderer renderer, int row, int col) { 1010 Component comp = super.prepareRenderer(renderer, row, col); 1011 Color c = Color.white; 1012 if (col == 0) c = coltab[0]; 1013 if (col == 3 || col == 4) c = coltab[1]; 1014 if (col == 5 || col == 6) c = coltab[2]; 1015 if (col == 7 || col == 8) c = coltab[3]; 1016 comp.setBackground(c); 1017 return comp; 1018 } 1019 1020 }; 1021 table.setFillsViewportHeight(true); 1022 table.setPreferredScrollableViewportSize(new Dimension(620,220)); 1023 table.setRowSelectionAllowed(true); 1024 table.setColumnSelectionAllowed(false); 1025 1026 JButton saveStatsButt = new JButton("Save As CSV"); 1027 JScrollPane sp = new JScrollPane(table); 1028 statsWindow = new JFrame("Scatter Statistics"); 1029 statsWindow.setLayout(new BorderLayout()); 1030 statsWindow.getContentPane().add(sp,BorderLayout.NORTH); 1031 JPanel bpan = new JPanel(new FlowLayout()); 1032 bpan.add(saveStatsButt); 1033 statsWindow.getContentPane().add(bpan,BorderLayout.SOUTH); 1034 statsWindow.setSize(650,340); 1035 statsWindow.pack(); 1036 statsWindow.addWindowListener(new WindowAdapter() { 1037 public void windowClosing(WindowEvent e) { 1038 isShowing = false; 1039 } 1040 }); 1041 1042 saveStatsButt.addActionListener(new ActionListener() { 1043 public void actionPerformed(final ActionEvent e) { 1044 JFileChooser chzr = new JFileChooser(); 1045 FileFilter filt = new FileNameExtensionFilter("csv","txt"); 1046 chzr.addChoosableFileFilter(filt); 1047 int rv = chzr.showSaveDialog(statsWindow); 1048 if (rv == JFileChooser.APPROVE_OPTION) { 1049 try { 1050 File fpw = chzr.getSelectedFile(); 1051 statsWindow.setTitle("Scatter Statistics saved to "+fpw.toString()); 1052 PrintWriter pw = new PrintWriter(fpw); 1053 String line = ""; 1054 for (int k=0; k<colNames.length; k++) { 1055 if (k != 0) line = line + ","; 1056 line = line + colNames[k]; 1057 } 1058 pw.println(line); 1059 1060 for (int i=0; i<data.length; i++) { 1061 line = ""; 1062 for (int j=0; j<data[i].length; j++) { 1063 if (j != 0) line = line+","; 1064 line = line+data[i][j]; 1065 } 1066 pw.println(line); 1067 } 1068 pw.flush(); 1069 pw.close(); 1070 } catch (Exception epw) { 1071 statsWindow.setTitle("Scatter Statistics: File not saved"); 1072 } 1073 1074 } 1075 1076 } 1077 }); 1078 1079 isShowing = false; 1080 statsWindow.setVisible(false); 1081 } 1082 1083 public void setIsShowing() { 1084 isShowing = true; 1085 } 1086 1087 public void resetValues(int col) { 1088 for (int i=0; i<maxRows; i++) { 1089 int c = 2*col + 3; 1090 data[i][c] = " "; 1091 data[i][c+1] = " "; 1092 } 1093 fireTableStructureChanged(); 1094 } 1095 1096 public void setNames(String xn, String yn) { 1097 colNames[1] = colNames[3] = colNames[5] = colNames[7] =xn; 1098 colNames[2] = colNames[4] = colNames[6] = colNames[8] =yn; 1099 } 1100 1101 // fx, fy are Fields, col = 0,1,2,3 (all, red, green, blue) 1102 public void setFields(FlatField fx, FlatField fy, int col) { 1103 statsWindow.setTitle("Scatter Statistics"); 1104 try { 1105 Statistics sx = new Statistics(fx); 1106 Statistics sy = new Statistics(fy); 1107 Statistics diff = new Statistics((FlatField)fx.subtract(fy)); 1108 1109 int c = 2*col + 1; 1110 data[0][c] = fmtMe(((Real)sx.max()).getValue()); 1111 data[0][c+1] = fmtMe(((Real)sy.max()).getValue()); 1112 1113 data[1][c] = fmtMe(((Real)sx.min()).getValue()); 1114 data[1][c+1] = fmtMe(((Real)sy.min()).getValue()); 1115 1116 data[2][c] = String.format("%d",sx.numPoints()); 1117 data[2][c+1] = String.format("%d",sy.numPoints()); 1118 1119 data[3][c] = fmtMe(((Real)sx.mean()).getValue()); 1120 data[3][c+1] = fmtMe(((Real)sy.mean()).getValue()); 1121 1122 data[4][c] = fmtMe(((Real)sx.median()).getValue()); 1123 data[4][c+1] = fmtMe(((Real)sy.median()).getValue()); 1124 1125 data[5][c] = fmtMe(((Real)sx.variance()).getValue()); 1126 data[5][c+1] = fmtMe(((Real)sy.variance()).getValue()); 1127 1128 data[6][c] = fmtMe(((Real)sx.kurtosis()).getValue()); 1129 data[6][c+1] = fmtMe(((Real)sy.kurtosis()).getValue()); 1130 1131 data[7][c] = fmtMe(((Real)sx.standardDeviation()).getValue()); 1132 data[7][c+1] = fmtMe(((Real)sy.standardDeviation()).getValue()); 1133 1134 data[8][c] = fmtMe(((Real)sx.correlation(fy)).getValue()); 1135 data[8][c+1] = " "; 1136 1137 data[9][c] = fmtMe(((Real)diff.max()).getValue()); 1138 data[9][c+1] = " "; 1139 1140 data[10][c] = fmtMe(((Real)diff.min()).getValue()); 1141 data[10][c+1] = " "; 1142 1143 data[11][c] = fmtMe(((Real)diff.mean()).getValue()); 1144 data[11][c+1] = " "; 1145 1146 if (c == 1) { 1147 data[12][c] = " "; 1148 } else { 1149 data[12][c] = fmtMe(total_area); 1150 } 1151 data[12][c+1] = " "; 1152 1153 if (c+2 > numCols) numCols = c+2; 1154 fireTableStructureChanged(); 1155 1156 } catch (VisADException exc) { 1157 System.out.println(exc.getMessage()); 1158 } catch (Exception exc) { 1159 exc.printStackTrace(); 1160 } 1161 1162 if (isShowing) statsWindow.setVisible(true); 1163 } 1164 1165 private String fmtMe(double val) { 1166 1167 if (Math.abs(val) == 0.0) { 1168 return "0.00"; 1169 1170 } else if (Math.abs(val) > 9999.9 || Math.abs(val) < .0010) { 1171 return String.format("%.6e", val); 1172 1173 } else if (Math.abs(val) < 1.0) { 1174 return String.format("%.5f", val); 1175 1176 } else if (Math.abs(val) < 10.0) { 1177 return String.format("%.3f", val); 1178 1179 } else { 1180 return String.format("%.2f", val); 1181 } 1182 } 1183 1184 public void setPoints(float[][] markScatter, int len, int indx) { 1185 try { 1186 Integer1DSet sdset = new Integer1DSet(len); 1187 FlatField scattX = new FlatField( 1188 new FunctionType(RealType.Generic, RealType.Generic), sdset); 1189 1190 float[][] scattValsX = new float[1][len]; 1191 System.arraycopy(markScatter[0],0,scattValsX[0],0,len); 1192 scattX.setSamples(scattValsX, false); 1193 1194 FlatField scattY = new FlatField( 1195 new FunctionType(RealType.Generic, RealType.Generic), sdset); 1196 float[][] scattValsY = new float[1][len]; 1197 System.arraycopy(markScatter[1],0,scattValsY[0],0,len); 1198 scattY.setSamples(scattValsY, false); 1199 1200 setFields(scattX, scattY, indx); 1201 1202 } catch (Exception esd) { 1203 esd.printStackTrace(); 1204 } 1205 } 1206 1207 public int getRowCount() { 1208 return maxRows; 1209 } 1210 public int getColumnCount() { 1211 return numCols; 1212 } 1213 public String getValueAt(int row, int col) { 1214 return data[row][col]; 1215 } 1216 public String getColumnName(int col) { 1217 return colNames[col]; 1218 } 1219 } 1220 1221 1222 private class ScatterDisplayable extends RGBDisplayable { 1223 ScatterDisplayable(String name, RealType rgbRealType, float[][] colorPalette, boolean alphaflag) 1224 throws VisADException, RemoteException { 1225 super(name, rgbRealType, colorPalette, alphaflag); 1226 } 1227 } 1228 1229 private class ImageControl extends DisplayControlImpl { 1230 HydraRGBDisplayable rgbDisp; 1231 DisplayConventions dc; 1232 ColorTableWidget ctw; 1233 1234 ImageControl(HydraRGBDisplayable rgbDisp, DisplayConventions dc) { 1235 super(); 1236 this.rgbDisp = rgbDisp; 1237 this.dc = dc; 1238 } 1239 1240 @Override public void setRange(Range r) throws VisADException, RemoteException { 1241 if (r != null) { 1242 rgbDisp.setRangeForColor(r.getMin(), r.getMax()); 1243 } 1244 } 1245 1246 @Override public DisplayConventions getDisplayConventions() { 1247 return dc; 1248 } 1249 1250 @Override public void setColorTable(ColorTable ct) { 1251 try { 1252 ctw.setColorTable(ct); 1253 ScalarMap colorMap = rgbDisp.getColorMap(); 1254 BaseColorControl clrCntrl = (BaseColorControl) colorMap.getControl(); 1255 1256 // Force incoming color dimension to that of the colorMap 1257 // 1258 int numComps = clrCntrl.getNumberOfComponents(); 1259 float[][] clrTable = ct.getColorTable(); 1260 float[][] newTable = null; 1261 if (numComps != clrTable.length) { 1262 if (numComps < clrTable.length) { 1263 newTable = new float[numComps][clrTable[0].length]; 1264 for (int k=0; k<numComps; k++) { 1265 System.arraycopy(clrTable[k], 0, newTable[k], 0, newTable[0].length); 1266 } 1267 } 1268 else if (numComps > clrTable.length) { 1269 newTable = new float[numComps][clrTable[0].length]; 1270 for (int k=0; k<clrTable.length; k++) { 1271 System.arraycopy(clrTable[k], 0, newTable[k], 0, newTable[0].length); 1272 } 1273 newTable[3] = new float[clrTable[0].length]; 1274 } 1275 } else { 1276 newTable = new float[numComps][clrTable[0].length]; 1277 for (int k = 0; k < clrTable.length; k++) { 1278 System.arraycopy(clrTable[k], 0, newTable[k], 0, newTable[0].length); 1279 } 1280 } 1281 clrCntrl.setTable(newTable); 1282 } 1283 catch (Exception e) { 1284 LogUtil.logException("Problem changing color table", e); 1285 } 1286 } 1287 } 1288 1289 private class ImageCurveSelector extends CellImpl implements DisplayListener { 1290 boolean init = false; 1291 CurveDrawer curveDraw; 1292 DisplayMaster dspMaster; 1293 Gridded2DSet domainSet; 1294 CoordinateSystem cs; 1295 int domainLen_0; 1296 int domainLen_1; 1297 ImageCurveSelector other; 1298 UnionSet last_uSet = null; 1299 boolean imageLatLon = false; 1300 boolean active = true; 1301 float maskVal; 1302 LineDrawing lastCurve; 1303 MyStatsTable myTable = null; 1304 int myTableIndex = 0; 1305 1306 ImageCurveSelector(CurveDrawer curveDraw, FlatField image, DisplayMaster master, Color color, float maskVal, MyStatsTable mst) 1307 throws VisADException, RemoteException { 1308 this.curveDraw = curveDraw; 1309 this.maskVal = maskVal; 1310 this.myTable = mst; 1311 myTableIndex = 0; 1312 if (color == Color.magenta) myTableIndex = 1; 1313 if (color == Color.green) myTableIndex = 2; 1314 if (color == Color.blue) myTableIndex = 3; 1315 dspMaster = master; 1316 dspMaster.addDisplayListener(this); 1317 domainSet = (Gridded2DSet) image.getDomainSet(); 1318 int[] lens = domainSet.getLengths(); 1319 domainLen_0 = lens[0]; 1320 domainLen_1 = lens[1]; 1321 cs = ((FunctionType)image.getType()).getDomain().getCoordinateSystem(); 1322 RealTupleType reference = null; 1323 if (cs != null) { 1324 reference = cs.getReference(); 1325 } 1326 else { 1327 reference = ((SetType)domainSet.getType()).getDomain(); 1328 } 1329 RealType[] rtypes = reference.getRealComponents(); 1330 if (rtypes[0].equals(RealType.Latitude)) imageLatLon = true; 1331 lastCurve = new LineDrawing("lastCurve"); 1332 lastCurve.setColor(color); 1333 lastCurve.setLineWidth(2); 1334 master.addDisplayable(lastCurve); 1335 } 1336 1337 @Override public void displayChanged(DisplayEvent de) 1338 throws VisADException, RemoteException { 1339 if ((de.getId() == DisplayEvent.MOUSE_RELEASED) && (active)) { 1340 UnionSet uSet = curveDraw.getCurves(); 1341 if (uSet == last_uSet) return; 1342 SampledSet[] sets = uSet.getSets(); 1343 int s_idx = sets.length-1; 1344 float[][] crv; 1345 1346 if (cs != null) { 1347 crv = sets[s_idx].getSamples(); 1348 if (imageLatLon) { 1349 float[] tmp = crv[0]; 1350 crv[0] = crv[1]; 1351 crv[1] = tmp; 1352 } 1353 crv = cs.fromReference(crv); 1354 crv = domainSet.valueToGrid(crv); 1355 } 1356 else { 1357 crv = sets[s_idx].getSamples(); 1358 crv = domainSet.valueToGrid(crv); 1359 } 1360 1361 float[][] onImage = new float[2][crv[0].length]; 1362 int cnt = 0; 1363 for (int i=0; i<crv[0].length; i++) { 1364 if ( ((crv[0][i] >= 0)&&(crv[0][i] <= domainLen_0)) && 1365 ((crv[1][i] >= 0)&&(crv[1][i] <= domainLen_1)) ) { 1366 onImage[0][cnt] = crv[0][i]; 1367 onImage[1][cnt] = crv[1][i]; 1368 cnt++; 1369 } 1370 } 1371 uSet = new UnionSet(new SampledSet[] {sets[s_idx]}); 1372 last_uSet = uSet; 1373 lastCurve.setData(last_uSet); 1374 curveDraw.setCurves(uSet); 1375 other.updateCurve(sets[s_idx]); 1376 1377 if (cnt == 0) { 1378 return; 1379 } 1380 1381 float[][] tmp = new float[2][cnt]; 1382 System.arraycopy(onImage[0], 0, tmp[0], 0, cnt); 1383 System.arraycopy(onImage[1], 0, tmp[1], 0, cnt); 1384 onImage = tmp; 1385 1386 float[] minmaxvals = minmax(onImage[0]); 1387 int low_0 = Math.round(minmaxvals[0]); 1388 int hi_0 = Math.round(minmaxvals[1]); 1389 minmaxvals = minmax(onImage[1]); 1390 int low_1 = Math.round(minmaxvals[0]); 1391 int hi_1 = Math.round(minmaxvals[1]); 1392 1393 int len_0 = (hi_0 - low_0) + 1; 1394 int len_1 = (hi_1 - low_1) + 1; 1395 int len = len_0*len_1; 1396 1397 tmp = new float[3][len]; 1398 int[] tmpsel = new int[len]; 1399 1400 int num_inside = 0; 1401 for (int j=0; j<len_1; j++) { 1402 for (int i=0; i<len_0; i++) { 1403 int idx = (j+low_1)*domainLen_0 + (i+low_0); 1404 float x = (float) (i + low_0); 1405 float y = (float) (j + low_1); 1406 if (DelaunayCustom.inside(crv, x, y)) { 1407 tmp[0][num_inside] = scatterFieldRange[0][idx]; 1408 tmp[1][num_inside] = scatterFieldRange[1][idx]; 1409 tmp[2][num_inside] = maskVal; 1410 tmpsel[num_inside] = idx; 1411 num_inside++; 1412 } 1413 } 1414 } 1415 len = num_inside; 1416 float[][] markScatter = new float[3][len]; 1417 System.arraycopy(tmp[0], 0, markScatter[0], 0, len); 1418 System.arraycopy(tmp[1], 0, markScatter[1], 0, len); 1419 System.arraycopy(tmp[2], 0, markScatter[2], 0, len); 1420 1421 1422 int last_len = 0; 1423 float[][] lastMark = ((FlatField)scatterMarkDsp.getData()).getFloats(false); 1424 tmp = new float[3][lastMark[0].length]; 1425 for (int k=0; k<lastMark[0].length; k++) { 1426 if (lastMark[2][k] != maskVal) { 1427 tmp[0][last_len] = lastMark[0][k]; 1428 tmp[1][last_len] = lastMark[1][k]; 1429 tmp[2][last_len] = lastMark[2][k]; 1430 last_len++; 1431 } 1432 } 1433 1434 float[][] newMarkScatter = new float[3][len+last_len]; 1435 System.arraycopy(tmp[0], 0, newMarkScatter[0], 0, last_len); 1436 System.arraycopy(tmp[1], 0, newMarkScatter[1], 0, last_len); 1437 System.arraycopy(tmp[2], 0, newMarkScatter[2], 0, last_len); 1438 System.arraycopy(markScatter[0], 0, newMarkScatter[0], last_len, len); 1439 System.arraycopy(markScatter[1], 0, newMarkScatter[1], last_len, len); 1440 System.arraycopy(markScatter[2], 0, newMarkScatter[2], last_len, len); 1441 1442 Integer1DSet dset = new Integer1DSet(len+last_len); 1443 FlatField scatterFieldMark = new FlatField( 1444 new FunctionType(RealType.Generic, 1445 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1446 1447 scatterFieldMark.setSamples(newMarkScatter, false); 1448 scatterMarkDsp.setData(scatterFieldMark); 1449 1450 if (myTable != null) { 1451 int[] selected = new int[len]; 1452 System.arraycopy(tmpsel, 0, selected, 0, len); 1453 total_area = JPythonMethods.computeSum(Area_field, selected); 1454 myTable.setPoints(markScatter, len, myTableIndex); 1455 } 1456 1457 } 1458 } 1459 1460 public void setActive(boolean active) { 1461 this.active = active; 1462 } 1463 1464 public void reset() throws VisADException, RemoteException { 1465 1466 float[][] lastMark = ((FlatField)scatterMarkDsp.getData()).getFloats(false); 1467 float[][] tmp = new float[3][lastMark[0].length]; 1468 int cnt = 0; 1469 for (int k=0; k<lastMark[0].length; k++) { 1470 if (lastMark[2][k] != maskVal) { 1471 tmp[0][cnt] = lastMark[0][k]; 1472 tmp[1][cnt] = lastMark[1][k]; 1473 tmp[2][cnt] = lastMark[2][k]; 1474 cnt++; 1475 } 1476 } 1477 1478 RealTupleType type = ((SetType)curveDraw.getCurves().getType()).getDomain(); 1479 curveDraw.setCurves(new UnionSet(new Gridded2DSet[]{ 1480 new Gridded2DSet(type, new float[][] { 1481 { 0.0f }, { 0.0f }}, 1) })); 1482 1483 lastCurve.setData(new UnionSet(new Gridded2DSet[]{ 1484 new Gridded2DSet(type, new float[][] { 1485 { 0.0f }, { 0.0f }}, 1) })); 1486 1487 FlatField scatterFieldMark = null; 1488 if (cnt == 0) { 1489 Integer1DSet dset = new Integer1DSet(2); 1490 scatterFieldMark = new FlatField( 1491 new FunctionType(RealType.Generic, 1492 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1493 float[][] markScatter = new float[3][2]; 1494 for (int k=0; k<2; k++) { 1495 markScatter[0][k] = scatterFieldRange[0][k]; 1496 markScatter[1][k] = scatterFieldRange[1][k]; 1497 markScatter[2][k] = 0; 1498 } 1499 scatterFieldMark.setSamples(markScatter, false); 1500 } 1501 else { 1502 Integer1DSet dset = new Integer1DSet(cnt); 1503 scatterFieldMark = new FlatField( 1504 new FunctionType(RealType.Generic, 1505 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1506 float[][] markScatter = new float[3][cnt]; 1507 for (int k=0; k<cnt; k++) { 1508 markScatter[0][k] = tmp[0][k]; 1509 markScatter[1][k] = tmp[1][k]; 1510 markScatter[2][k] = tmp[2][k]; 1511 } 1512 scatterFieldMark.setSamples(markScatter, false); 1513 } 1514 1515 scatterMarkDsp.setData(scatterFieldMark); 1516 } 1517 1518 public void updateCurve(SampledSet set) throws VisADException, RemoteException { 1519 last_uSet = new UnionSet(new SampledSet[] {set}); 1520 curveDraw.setCurves(last_uSet); 1521 lastCurve.setData(last_uSet); 1522 } 1523 1524 public void setOther(ImageCurveSelector other) { 1525 this.other = other; 1526 } 1527 1528 @Override public void doAction() 1529 throws VisADException, RemoteException { 1530 if (!init) { 1531 init = true; 1532 return; 1533 } 1534 } 1535 1536 public void setVisible(boolean visible) throws VisADException, RemoteException { 1537 curveDraw.setVisible(visible); 1538 } 1539 1540 } 1541 1542 private class ImageBoxSelector extends CellImpl { 1543 boolean init = false; 1544 boolean active = true; 1545 SubsetRubberBandBox subsetBox; 1546 Set imageDomain; 1547 int domainLen_0; 1548 LineDrawing lastBox; 1549 ImageBoxSelector other; 1550 float maskVal; 1551 boolean earthCoordDomain = false; 1552 MyStatsTable myTable = null; 1553 int myTableIndex = 0; 1554 1555 ImageBoxSelector(SubsetRubberBandBox subsetBox, Set imageDomain, DisplayMaster master, Color color, float maskVal, MyStatsTable mst) 1556 throws VisADException, RemoteException { 1557 super(); 1558 this.myTable = mst; 1559 myTableIndex = 0; 1560 if (color == Color.magenta) myTableIndex = 1; 1561 if (color == Color.green) myTableIndex = 2; 1562 if (color == Color.blue) myTableIndex = 3; 1563 this.subsetBox = subsetBox; 1564 this.imageDomain = imageDomain; 1565 int[] lens = ((Gridded2DSet)imageDomain).getLengths(); 1566 this.maskVal = maskVal; 1567 domainLen_0 = lens[0]; 1568 lastBox = new LineDrawing("last_box"); 1569 lastBox.setColor(color); 1570 master.addDisplayable(lastBox); 1571 subsetBox.addAction(this); 1572 master.addDisplayable(subsetBox); 1573 RealTupleType rtt = ((SetType)imageDomain.getType()).getDomain(); 1574 if (rtt.equals(RealTupleType.SpatialEarth2DTuple) || 1575 rtt.equals(RealTupleType.LatitudeLongitudeTuple)) { 1576 earthCoordDomain = true; 1577 } 1578 } 1579 1580 @Override public void doAction() 1581 throws VisADException, RemoteException 1582 { 1583 if (!init) { 1584 init = true; 1585 return; 1586 } 1587 1588 if (!active) { 1589 return; 1590 } 1591 1592 Gridded2DSet set = subsetBox.getBounds(); 1593 float[][] corners = set.getSamples(false); 1594 float[][] coords = corners; 1595 1596 if ((imageDomain instanceof Linear2DSet) || !earthCoordDomain) { 1597 coords = ((Gridded2DSet)imageDomain).valueToGrid(corners); 1598 } 1599 1600 float[] coords_0 = coords[0]; 1601 float[] coords_1 = coords[1]; 1602 1603 int low_0 = Math.round(Math.min(coords_0[0], coords_0[1])); 1604 int low_1 = Math.round(Math.min(coords_1[0], coords_1[1])); 1605 int hi_0 = Math.round(Math.max(coords_0[0], coords_0[1])); 1606 int hi_1 = Math.round(Math.max(coords_1[0], coords_1[1])); 1607 1608 int len_0 = (hi_0 - low_0) + 1; 1609 int len_1 = (hi_1 - low_1) + 1; 1610 int len = len_0*len_1; 1611 1612 float[][] markScatter = new float[3][len]; 1613 int[] selected = new int[len]; 1614 1615 for (int j=0; j<len_1; j++) { 1616 for (int i=0; i<len_0; i++) { 1617 int idx = (j+low_1)*domainLen_0 + (i+low_0); 1618 int k = j*len_0 + i; 1619 markScatter[0][k] = scatterFieldRange[0][idx]; 1620 markScatter[1][k] = scatterFieldRange[1][idx]; 1621 markScatter[2][k] = maskVal; 1622 selected[k] = idx; 1623 } 1624 } 1625 1626 int last_len = 0; 1627 float[][] lastMark = ((FlatField)scatterMarkDsp.getData()).getFloats(false); 1628 float[][] tmp = new float[3][lastMark[0].length]; 1629 for (int k=0; k<lastMark[0].length; k++) { 1630 if (lastMark[2][k] != maskVal) { 1631 tmp[0][last_len] = lastMark[0][k]; 1632 tmp[1][last_len] = lastMark[1][k]; 1633 tmp[2][last_len] = lastMark[2][k]; 1634 last_len++; 1635 } 1636 } 1637 1638 float[][] newMarkScatter = new float[3][len+last_len]; 1639 System.arraycopy(tmp[0], 0, newMarkScatter[0], 0, last_len); 1640 System.arraycopy(tmp[1], 0, newMarkScatter[1], 0, last_len); 1641 System.arraycopy(tmp[2], 0, newMarkScatter[2], 0, last_len); 1642 System.arraycopy(markScatter[0], 0, newMarkScatter[0], last_len, len); 1643 System.arraycopy(markScatter[1], 0, newMarkScatter[1], last_len, len); 1644 System.arraycopy(markScatter[2], 0, newMarkScatter[2], last_len, len); 1645 1646 Integer1DSet dset = new Integer1DSet(len+last_len); 1647 FlatField scatterFieldMark = new FlatField( 1648 new FunctionType(RealType.Generic, 1649 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1650 1651 scatterFieldMark.setSamples(newMarkScatter, false); 1652 scatterMarkDsp.setData(scatterFieldMark); 1653 1654 if (myTable != null) { 1655 total_area = JPythonMethods.computeSum(Area_field, selected); 1656 myTable.setPoints(markScatter, len, myTableIndex); 1657 } 1658 1659 updateBox(); 1660 } 1661 1662 public void setActive(boolean active) { 1663 this.active = active; 1664 } 1665 1666 public void setVisible(boolean visible) throws VisADException, RemoteException { 1667 subsetBox.setVisible(visible); 1668 if (visible) { 1669 lastBox.setVisible(visible); 1670 } 1671 } 1672 1673 public void reset() throws VisADException, RemoteException { 1674 Gridded2DSet set2D = 1675 new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, 1676 new float[][] {{0},{0}}, 1); 1677 lastBox.setVisible(false); 1678 lastBox.setData(set2D); 1679 1680 float[][] lastMark = ((FlatField)scatterMarkDsp.getData()).getFloats(false); 1681 float[][] tmp = new float[3][lastMark[0].length]; 1682 int cnt = 0; 1683 for (int k=0; k<lastMark[0].length; k++) { 1684 if (lastMark[2][k] != maskVal) { 1685 tmp[0][cnt] = lastMark[0][k]; 1686 tmp[1][cnt] = lastMark[1][k]; 1687 tmp[2][cnt] = lastMark[2][k]; 1688 cnt++; 1689 } 1690 } 1691 1692 FlatField scatterFieldMark; 1693 if (cnt == 2) { 1694 Integer1DSet dset = new Integer1DSet(2); 1695 scatterFieldMark = new FlatField( 1696 new FunctionType(RealType.Generic, 1697 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1698 float[][] markScatter = new float[3][2]; 1699 for (int k=0; k<2; k++) { 1700 markScatter[0][k] = scatterFieldRange[0][k]; 1701 markScatter[1][k] = scatterFieldRange[1][k]; 1702 markScatter[2][k] = 0; 1703 } 1704 scatterFieldMark.setSamples(markScatter, false); 1705 } 1706 else { 1707 Integer1DSet dset = new Integer1DSet(cnt); 1708 scatterFieldMark = new FlatField( 1709 new FunctionType(RealType.Generic, 1710 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1711 float[][] markScatter = new float[3][cnt]; 1712 for (int k=0; k<cnt; k++) { 1713 markScatter[0][k] = tmp[0][k]; 1714 markScatter[1][k] = tmp[1][k]; 1715 markScatter[2][k] = tmp[2][k]; 1716 } 1717 scatterFieldMark.setSamples(markScatter, false); 1718 } 1719 1720 scatterMarkDsp.setData(scatterFieldMark); 1721 } 1722 1723 public void setOther(ImageBoxSelector other) { 1724 this.other = other; 1725 } 1726 1727 public void updateBox() throws VisADException, RemoteException { 1728 Gridded3DSet set3D = subsetBox.getLastBox(); 1729 float[][] samples = set3D.getSamples(false); 1730 Gridded2DSet set2D = 1731 new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, 1732 new float[][] {samples[0], samples[1]}, samples[0].length); 1733 lastBox.setData(set2D); 1734 other.updateBox(set2D); 1735 } 1736 1737 public void updateBox(Gridded2DSet set2D) throws VisADException, RemoteException { 1738 lastBox.setData(set2D); 1739 } 1740 1741 } 1742 1743 private class ScatterBoxSelector extends CellImpl { 1744 boolean init = false; 1745 double[] x_coords = new double[2]; 1746 double[] y_coords = new double[2]; 1747 RubberBandBox rbb; 1748 LineDrawing selectBox; 1749 boolean active = true; 1750 float maskVal = 0; 1751 1752 ScatterBoxSelector(DisplayMaster master, Color color, float maskVal) throws VisADException, RemoteException { 1753 selectBox = new LineDrawing("select"); 1754 selectBox.setColor(color); 1755 1756 rbb = new RubberBandBox(RealType.XAxis, RealType.YAxis, 1); 1757 rbb.setColor(color); 1758 rbb.addAction(this); 1759 1760 master.addDisplayable(rbb); 1761 master.addDisplayable(selectBox); 1762 this.maskVal = maskVal; 1763 } 1764 1765 1766 @Override public void doAction() throws VisADException, RemoteException { 1767 if (!init) { 1768 init = true; 1769 return; 1770 } 1771 1772 if (!active) { 1773 return; 1774 } 1775 1776 Gridded2DSet set = rbb.getBounds(); 1777 float[] low = set.getLow(); 1778 float[] hi = set.getHi(); 1779 x_coords[0] = low[0]; 1780 x_coords[1] = hi[0]; 1781 y_coords[0] = low[1]; 1782 y_coords[1] = hi[1]; 1783 1784 SampledSet[] sets = new SampledSet[4]; 1785 sets[0] = new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] {{low[0], hi[0]}, {low[1], low[1]}}, 2); 1786 sets[1] = new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] {{hi[0], hi[0]}, {low[1], hi[1]}}, 2); 1787 sets[2] = new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] {{hi[0], low[0]}, {hi[1], hi[1]}}, 2); 1788 sets[3] = new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] {{low[0], low[0]}, {hi[1], low[1]}}, 2); 1789 UnionSet uset = new UnionSet(sets); 1790 selectBox.setData(uset); 1791 1792 try { 1793 histoField.markMaskFieldByRange(x_coords, y_coords, maskVal); 1794 } catch (Exception e) { 1795 e.printStackTrace(); 1796 } 1797 } 1798 1799 public void setVisible(boolean visible) throws VisADException, RemoteException { 1800 rbb.setVisible(visible); 1801 if (visible) { 1802 selectBox.setVisible(visible); 1803 } 1804 } 1805 1806 public void setActive(boolean active) { 1807 this.active = active; 1808 } 1809 1810 public void reset() throws Exception { 1811 selectBox.setVisible(false); 1812 selectBox.setData(new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] {{0f, 0f}, {0f, 0f}}, 2)); 1813 histoField.resetMaskField(maskVal); 1814 } 1815 } 1816 1817 private class ScatterCurveSelector extends CellImpl implements DisplayListener { 1818 CurveDrawer curveDraw; 1819 boolean init = false; 1820 UnionSet last_uSet = null; 1821 boolean active = true; 1822 float maskVal = 0; 1823 LineDrawing selectCurve; 1824 1825 ScatterCurveSelector(DisplayMaster master, Color color, float maskVal) throws VisADException, RemoteException { 1826 curveDraw = new CurveDrawer(RealType.XAxis, RealType.YAxis, 1); 1827 curveDraw.setColor(color); 1828 curveDraw.setLineWidth(2); 1829 curveDraw.setData(new UnionSet(new Gridded2DSet[]{ 1830 new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] { 1831 { scatterFieldRange[0][0] }, { scatterFieldRange[1][0]} 1832 }, 1) })); 1833 1834 selectCurve = new LineDrawing("select"); 1835 selectCurve.setColor(color); 1836 selectCurve.setLineWidth(2); 1837 master.addDisplayable(curveDraw); 1838 master.addDisplayable(selectCurve); 1839 this.maskVal = maskVal; 1840 1841 curveDraw.addAction(this); 1842 master.addDisplayListener(this); 1843 } 1844 1845 @Override public void displayChanged(DisplayEvent de) 1846 throws VisADException, RemoteException { 1847 if ((de.getId() == DisplayEvent.MOUSE_RELEASED) && (active)) { 1848 UnionSet uSet = curveDraw.getCurves(); 1849 if (uSet == last_uSet) return; 1850 SampledSet[] sets = uSet.getSets(); 1851 int s_idx = sets.length-1; 1852 float[][] crv; 1853 1854 crv = sets[s_idx].getSamples(); 1855 last_uSet = new UnionSet(new SampledSet[] {sets[s_idx]}); 1856 curveDraw.setCurves(last_uSet); 1857 selectCurve.setData(last_uSet); 1858 1859 try { 1860 histoField.clearMaskField(maskVal); 1861 histoField.markMaskFieldByCurve(crv, maskVal); 1862 } catch (Exception e) { 1863 e.printStackTrace(); 1864 } 1865 } 1866 } 1867 1868 @Override public void doAction() throws VisADException, RemoteException { 1869 if (!init) { 1870 init = true; 1871 return; 1872 } 1873 } 1874 1875 public void setVisible(boolean visible) throws VisADException, RemoteException { 1876 curveDraw.setVisible(visible); 1877 } 1878 1879 public void setActive(boolean active) { 1880 this.active = active; 1881 } 1882 1883 public void reset() throws Exception { 1884 curveDraw.setData(new UnionSet(new Gridded2DSet[]{ 1885 new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] { 1886 { scatterFieldRange[0][0] }, { scatterFieldRange[1][0]} 1887 }, 1) })); 1888 selectCurve.setData(new UnionSet(new Gridded2DSet[]{ 1889 new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] { 1890 { scatterFieldRange[0][0] }, { scatterFieldRange[1][0]} 1891 }, 1) })); 1892 histoField.resetMaskField(maskVal); 1893 } 1894 } 1895 1896 private class BoxCurveSwitch implements ActionListener { 1897 1898 public BoxCurveSwitch() { 1899 } 1900 1901 @Override public void actionPerformed(ActionEvent ae) { 1902 String cmd = ae.getActionCommand(); 1903 try { 1904 if (cmd.equals("Box")) { 1905 selectByCurve = false; 1906 } else if (cmd.equals("Curve")) { 1907 selectByCurve = true; 1908 } 1909 } 1910 catch (Exception e) { 1911 e.printStackTrace(); 1912 } 1913 } 1914 } 1915 1916 public static float[] minmax(float[] values) { 1917 float min = Float.MAX_VALUE; 1918 float max = -Float.MAX_VALUE; 1919 for (int k = 0; k < values.length; k++) { 1920 float val = values[k]; 1921 if ((val == val) && (val < Float.POSITIVE_INFINITY) && (val > Float.NEGATIVE_INFINITY)) { 1922 if (val < min) min = val; 1923 if (val > max) max = val; 1924 } 1925 } 1926 return new float[] {min, max}; 1927 } 1928 1929 public boolean getIsLatLon(FlatField field) throws VisADException, RemoteException { 1930 boolean isLL = false; 1931 FunctionType fnc_type = (FunctionType) field.getType(); 1932 RealTupleType rtt = fnc_type.getDomain(); 1933 if (rtt.equals(RealTupleType.LatitudeLongitudeTuple)) { 1934 isLL = true; 1935 } 1936 else if (!rtt.equals(RealTupleType.SpatialEarth2DTuple)) { 1937 rtt = fnc_type.getDomain().getCoordinateSystem().getReference(); 1938 if ( rtt.equals(RealTupleType.LatitudeLongitudeTuple)) { 1939 isLL = true; 1940 } 1941 } 1942 return isLL; 1943 } 1944 }