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