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