001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2025 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 */ 028package edu.wisc.ssec.mcidasv.control; 029 030import edu.wisc.ssec.mcidasv.data.hydra.ImageRGBDisplayable; 031 032import net.miginfocom.swing.MigLayout; 033 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036import ucar.unidata.data.DataChoice; 037import ucar.unidata.data.DataSelection; 038import ucar.unidata.idv.ViewManager; 039import ucar.unidata.idv.control.DisplayControlImpl; 040import ucar.unidata.util.ColorTable; 041import ucar.unidata.util.LogUtil; 042import ucar.visad.display.DisplayMaster; 043 044import visad.*; 045import visad.georef.MapProjection; 046 047import javax.swing.Box; 048import javax.swing.JButton; 049import javax.swing.JCheckBox; 050import javax.swing.JLabel; 051import javax.swing.JPanel; 052import javax.swing.JTextField; 053 054import java.awt.Container; 055import java.awt.FlowLayout; 056import java.rmi.RemoteException; 057import java.util.Hashtable; 058import java.util.Iterator; 059 060public class RGBCompositeControl extends DisplayControlImpl { 061 062 public final static String FORMULA_IN_PROGRESS_FLAG = "Formula_Active"; 063 private static final Logger logger = LoggerFactory.getLogger(RGBCompositeControl.class); 064 /** Displayable for the data */ 065 private ImageRGBDisplayable imageDisplay; 066 067 private DisplayMaster displayMaster; 068 069 private ScalarMap redMap = null; 070 private ScalarMap grnMap = null; 071 private ScalarMap bluMap = null; 072 073 float[][] redTable = null; 074 float[][] grnTable = null; 075 float[][] bluTable = null; 076 077 final private double[] redRange = { Double.NaN, Double.NaN }; 078 final private double[] grnRange = { Double.NaN, Double.NaN }; 079 final private double[] bluRange = { Double.NaN, Double.NaN }; 080 081 final double[] initRedRange = { Double.NaN, Double.NaN }; 082 final double[] initGrnRange = { Double.NaN, Double.NaN }; 083 final double[] initBluRange = { Double.NaN, Double.NaN }; 084 085 private FieldImpl imageField = null; 086 private MapProjection mapProjection = null; 087 088 private static final double DEFAULT_GAMMA = 1.0d; 089 private double gamma = DEFAULT_GAMMA; 090 091 private double redGamma = DEFAULT_GAMMA; 092 private double grnGamma = DEFAULT_GAMMA; 093 private double bluGamma = DEFAULT_GAMMA; 094 095 private JCheckBox matchFieldsCbox = null; 096 097 private final JTextField gammaTxtFld = 098 new JTextField(Double.toString(gamma), 4); 099 private final JTextField redGammaTxtFld = 100 new JTextField(Double.toString(redGamma), 4); 101 private final JTextField grnGammaTxtFld = 102 new JTextField(Double.toString(grnGamma), 4); 103 private final JTextField bluGammaTxtFld = 104 new JTextField(Double.toString(bluGamma), 4); 105 106 private final JTextField redLowTxtFld = 107 new JTextField(Float.toString(1.0f), 10); 108 private final JTextField redHighTxtFld = 109 new JTextField(Float.toString(1.0f), 10); 110 private final JTextField grnLowTxtFld = 111 new JTextField(Float.toString(1.0f), 10); 112 private final JTextField grnHighTxtFld = 113 new JTextField(Float.toString(1.0f), 10); 114 private final JTextField bluLowTxtFld = 115 new JTextField(Float.toString(1.0f), 10); 116 private final JTextField bluHighTxtFld = 117 new JTextField(Float.toString(1.0f), 10); 118 119 public boolean init(DataChoice dataChoice) throws VisADException, RemoteException { 120 121 displayMaster = getViewManager().getMaster(); 122 DataSelection dataSelection = getDataSelection(); 123 124 // TJJ Jul 2014 125 // by sharing a property via the active View Manager, we can signal all three 126 // preview windows they are part of an in-progress RGB Composite. If so, it 127 // appears we need to use a shared HydraContext so our geographic coverage 128 // subset applies across channels. 129 130 Hashtable ht = getIdv().getViewManager().getProperties(); 131 ht.put(FORMULA_IN_PROGRESS_FLAG, true); 132 133 imageField = (FieldImpl) dataChoice.getData(dataSelection); 134 135 imageDisplay = new ImageRGBDisplayable("rgb composite", null, false, imageField); 136 137 ht.put(FORMULA_IN_PROGRESS_FLAG, false); 138 139 Iterator iter = imageDisplay.getScalarMapSet().iterator(); 140 while (iter.hasNext()) { 141 ScalarMap map = (ScalarMap) iter.next(); 142 if (map.getScalarName().startsWith("redimage")) { 143 redMap = map; 144 } 145 if (map.getScalarName().startsWith("greenimage")) { 146 grnMap = map; 147 } 148 if (map.getScalarName().startsWith("blueimage")) { 149 bluMap = map; 150 } 151 } 152 153 if (checkRange()) { //- from unpersistence if true, initialize gui, ScalarMaps 154 double[] redRange = getRedRange(); 155 double[] grnRange = getGrnRange(); 156 double[] bluRange = getBluRange(); 157 158 initRedRange[0] = redRange[0]; 159 initRedRange[1] = redRange[1]; 160 initGrnRange[0] = grnRange[0]; 161 initGrnRange[1] = grnRange[1]; 162 initBluRange[0] = bluRange[0]; 163 initBluRange[1] = bluRange[1]; 164 165 redLowTxtFld.setText(Float.toString((float)redRange[0])); 166 redHighTxtFld.setText(Float.toString((float)redRange[1])); 167 grnLowTxtFld.setText(Float.toString((float)grnRange[0])); 168 grnHighTxtFld.setText(Float.toString((float)grnRange[1])); 169 bluLowTxtFld.setText(Float.toString((float)bluRange[0])); 170 bluHighTxtFld.setText(Float.toString((float)bluRange[1])); 171 172 gammaTxtFld.setText(Float.toString((float)gamma)); 173 redGammaTxtFld.setText(Float.toString((float)redGamma)); 174 grnGammaTxtFld.setText(Float.toString((float)grnGamma)); 175 bluGammaTxtFld.setText(Float.toString((float)bluGamma)); 176 177 redMap.setRange(redRange[0], redRange[1]); 178 grnMap.setRange(grnRange[0], grnRange[1]); 179 bluMap.setRange(bluRange[0], bluRange[1]); 180 } else { 181 redMap.resetAutoScale(); 182 grnMap.resetAutoScale(); 183 bluMap.resetAutoScale(); 184 185 redMap.addScalarMapListener(new ColorMapListener(redMap, initRedRange, redRange, redLowTxtFld, redHighTxtFld)); 186 grnMap.addScalarMapListener(new ColorMapListener(grnMap, initGrnRange, grnRange, grnLowTxtFld, grnHighTxtFld)); 187 bluMap.addScalarMapListener(new ColorMapListener(bluMap, initBluRange, bluRange, bluLowTxtFld, bluHighTxtFld)); 188 } 189 190 setShowInDisplayList(true); 191 192 addDisplayable(imageDisplay, FLAG_COLORTABLE | FLAG_ZPOSITION); 193 194 return true; 195 } 196 197 public void initDone() { 198 while (true) { 199 if (null != redMap.getControl()) { 200 redTable = ((BaseColorControl) redMap.getControl()).getTable(); 201 break; 202 } 203 } 204 while (true) { 205 if (null != grnMap.getControl()) { 206 grnTable = ((BaseColorControl) grnMap.getControl()).getTable(); 207 break; 208 } 209 } 210 211 while (true) { 212 if (null != bluMap.getControl()) { 213 bluTable = ((BaseColorControl) bluMap.getControl()).getTable(); 214 break; 215 } 216 } 217 218 float[][] newRedTbl = getZeroOutArray(redTable); 219 float[][] newGrnTbl = getZeroOutArray(grnTable); 220 float[][] newBluTbl = getZeroOutArray(bluTable); 221 222 for (int k=0; k<redTable[0].length; k++) { 223 newRedTbl[0][k] = (float) Math.pow(redTable[0][k], redGamma); 224 newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], grnGamma); 225 newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], bluGamma); 226 } 227 228 try { 229 displayMaster.setDisplayInactive(); 230 ((BaseColorControl)redMap.getControl()).setTable(newRedTbl); 231 ((BaseColorControl)grnMap.getControl()).setTable(newGrnTbl); 232 ((BaseColorControl)bluMap.getControl()).setTable(newBluTbl); 233 imageDisplay.loadData(imageField); 234 displayMaster.setDisplayActive(); 235 } catch (Exception ex) { 236 LogUtil.logException("setDisplayInactive", ex); 237 } 238 } 239 240 public MapProjection getDataProjection() { 241 CoordinateSystem cs = null; 242 try { 243 if (imageField instanceof FlatField) { 244 cs = ((FunctionType)imageField.getType()).getDomain().getCoordinateSystem(); 245 } 246 else if (imageField instanceof FieldImpl) { 247 Data dat = imageField.getSample(0, false); 248 if (dat instanceof FlatField) { 249 FlatField img = (FlatField) dat; 250 cs = ((FunctionType)img.getType()).getDomain().getCoordinateSystem(); 251 } 252 } 253 } 254 catch (Exception ex) { 255 LogUtil.logException("problem accessing data", ex); 256 } 257 258 if (cs instanceof MapProjection) { 259 mapProjection = (MapProjection)cs; 260 } 261 262 return mapProjection; 263 } 264 265 boolean checkRange() { 266 return !(Double.isNaN(redRange[0]) || Double.isNaN(grnRange[0]) || Double.isNaN(bluRange[0])); 267 } 268 269 private void updateRedRange(double lo, double hi) { 270 redRange[0] = lo; 271 redRange[1] = hi; 272 redHighTxtFld.setText(Float.toString((float)hi)); 273 redLowTxtFld.setText(Float.toString((float)lo)); 274 try { 275 redMap.setRange(lo, hi); 276 } catch (VisADException | RemoteException ex) { 277 LogUtil.logException("redMap.setRange", ex); 278 } 279 } 280 281 public void setRedRange(double[] range) { 282 redRange[0] = range[0]; 283 redRange[1] = range[1]; 284 } 285 286 public double[] getRedRange() { 287 return new double[] {redRange[0], redRange[1]}; 288 } 289 290 private void updateGrnRange(double lo, double hi) { 291 grnRange[0] = lo; 292 grnRange[1] = hi; 293 grnHighTxtFld.setText(Float.toString((float)hi)); 294 grnLowTxtFld.setText(Float.toString((float)lo)); 295 try { 296 grnMap.setRange(lo, hi); 297 } catch (VisADException | RemoteException ex) { 298 LogUtil.logException("grnMap.setRange", ex); 299 } 300 } 301 302 public void setGrnRange(double[] range) { 303 grnRange[0] = range[0]; 304 grnRange[1] = range[1]; 305 } 306 307 public double[] getGrnRange() { 308 return new double[] {grnRange[0], grnRange[1]}; 309 } 310 311 private void updateBluRange(double lo, double hi) { 312 bluRange[0] = lo; 313 bluRange[1] = hi; 314 bluHighTxtFld.setText(Float.toString((float)hi)); 315 bluLowTxtFld.setText(Float.toString((float)lo)); 316 try { 317 bluMap.setRange(lo, hi); 318 } catch (VisADException | RemoteException ex) { 319 LogUtil.logException("bluMap.setRange", ex); 320 } 321 } 322 323 public void setBluRange(double[] range) { 324 bluRange[0] = range[0]; 325 bluRange[1] = range[1]; 326 } 327 328 public double[] getBluRange() { 329 return new double[] {bluRange[0], bluRange[1]}; 330 } 331 332 public void setRedGamma(double gamma) { 333 redGamma = gamma; 334 } 335 336 public double getRedGamma() { 337 return redGamma; 338 } 339 340 public void setGrnGamma(double gamma) { 341 grnGamma = gamma; 342 } 343 344 public double getGrnGamma() { 345 return grnGamma; 346 } 347 348 public void setBluGamma(double gamma) { 349 bluGamma = gamma; 350 } 351 352 public double getBluGamma() { 353 return bluGamma; 354 } 355 356 public void setGamma(double gamma) { 357 this.gamma = gamma; 358 } 359 360 public double getGamma() { 361 return gamma; 362 } 363 364 public void reapplyAllGammaSettings() { 365 updateRedGamma(getRedGamma()); 366 updateGrnGamma(getGrnGamma()); 367 updateBluGamma(getBluGamma()); 368 } 369 370 /** 371 * TJJ - quick hack, just do something visually jarring to test path 372 */ 373 374 /** 375 * Computes a Rayleigh scattering corrected 2D grid for visible range data. 376 * 377 * @param visibleDataGrid 2D grid of remote sensing data in the visible range 378 * (assuming it represents top-of-atmosphere radiance or reflectance). 379 * @param satelliteZenithGrid 2D grid of satellite zenith angles (in degrees). 380 * @param solarZenithGrid 2D grid of solar zenith angles (in degrees). 381 * @param satelliteAzimuthGrid 2D grid of satellite azimuth angles (in degrees). 382 * @param solarAzimuthGrid 2D grid of solar azimuth angles (in degrees). 383 * @param wavelengthVisible Wavelength of the visible band (in micrometers). 384 * @param atmosphericPressure Atmospheric pressure at the surface (in hPa). 385 * @return A 2D grid representing the Rayleigh scattering corrected data. 386 * @throws IllegalArgumentException if input grid dimensions are inconsistent. 387 */ 388 389 public static FieldImpl correctRayleighVisible(FieldImpl visibleField, 390 FieldImpl satelliteZenithField, 391 FieldImpl solarZenithField, 392 FieldImpl satelliteAzimuthField, 393 FieldImpl solarAzimuthField, 394 double wavelengthVisible, 395 double atmosphericPressure) 396 throws VisADException, RemoteException { 397 398 double[][] visibleDataGrid = visibleField.getValues(); 399 double[][] satelliteZenithGrid = satelliteZenithField.getValues(); 400 double[][] solarZenithGrid = solarZenithField.getValues(); 401 double[][] satelliteAzimuthGrid = satelliteAzimuthField.getValues(); 402 double[][] solarAzimuthGrid = solarAzimuthField.getValues(); 403 404 int rows = visibleDataGrid.length; 405 int cols = visibleDataGrid[0].length; 406 407 // float[][] correctedDataGrid = new float[rows][cols]; 408 409 for (int i = 0; i < rows; i++) { 410 for (int j = 0; j < cols; j++) { 411 float thetaV = (float) Math.toRadians(satelliteZenithGrid[i][j]); 412 float thetaS = (float) Math.toRadians(solarZenithGrid[i][j]); 413 float phiV = (float) Math.toRadians(satelliteAzimuthGrid[i][j]); 414 float phiS = (float) Math.toRadians(solarAzimuthGrid[i][j]); 415 416 double rhoRayleigh = calculateRayleighReflectance(wavelengthVisible, thetaS, thetaV, phiS, phiV, atmosphericPressure); 417 visibleDataGrid[i][j] = (float) (visibleDataGrid[i][j] - rhoRayleigh); 418 } 419 } 420 visibleField.setSamples(visibleDataGrid); 421 422 logger.info("3141 - made it out"); 423 return visibleField; 424 } 425 426 // Calculate Rayleigh reflectance - McIDAS Inquiry #3055-3141 427 private static double calculateRayleighReflectance( 428 double wavelength, double solarZenithRad, double satelliteZenithRad, 429 double solarAzimuthRad, double satelliteAzimuthRad, double pressureHPa) { 430 431 double tau_ro = (0.008569 / Math.pow(wavelength, 4)) 432 * (1 + (0.0113 / Math.pow(wavelength, 2)) + (0.00013 / Math.pow(wavelength, 4))); 433 434 // \tau_{ro} = \frac{0.008569}{\lambda^4} \cdot (1 + \frac{0.0113}{\lambda^2} + \frac{0.00013}{\lambda^4}) 435 436 double pressure_rat = pressureHPa / 1013.25; 437 // P = \frac{pHPa}{atmP} 438 439 double tau = pressure_rat * tau_ro; // this is the only thing matters next 440 // \tau = P \cdot \tau_{ro} 441 442 double scattering_angle_cos = Math.cos(solarZenithRad) * Math.cos(satelliteZenithRad) 443 + Math.sin(solarZenithRad) * Math.sin(satelliteZenithRad) 444 * Math.cos(satelliteAzimuthRad - solarAzimuthRad); 445 446 // \cos (\Theta) = \cos (\theta_{sun})\cos (\theta_{sat}) + \sin (\theta_{sun})\sin (\theta_{sat}) \cdot \cos(\phi_{sat} - \phi_{sun}) 447 448 double P_big_theta = 0.75 * (1 + Math.pow(scattering_angle_cos, 2)); // another important value 449 // P(\Theta) = 0.75 * (1 + (\cos(\Theta))^2) 450 451 double mu_1 = Math.cos(solarZenithRad); 452 double mu_2 = Math.cos(satelliteZenithRad); 453 454 return tau * P_big_theta * (1 / (4 * mu_1 * mu_2)); 455 // \tau \cdot P(\Theta) \cdot (\frac{1}{4 \cdot \mu_1 \cdot \mu_2}) 456 } 457 458 private void applyRayleighCorrection() { 459 float[][] newRedTbl = getZeroOutArray(redTable); 460 float[][] newGrnTbl = getZeroOutArray(grnTable); 461 float[][] newBluTbl = getZeroOutArray(bluTable); 462 463 for (int k = 0; k < redTable[0].length; k++) { 464 newRedTbl[0][k] = (float) Math.pow(redTable[0][k], 0.2); 465 newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], 0.2); 466 newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], 0.2); 467 } 468 try { 469 displayMaster.setDisplayInactive(); 470 ((BaseColorControl) redMap.getControl()).setTable(newRedTbl); 471 ((BaseColorControl) grnMap.getControl()).setTable(newGrnTbl); 472 ((BaseColorControl) bluMap.getControl()).setTable(newBluTbl); 473 displayMaster.setDisplayActive(); 474 } catch (Exception e) { 475 LogUtil.logException("setDisplayInactive", e); 476 } 477 } 478 479 private void updateGamma(double gamma) { 480 setGamma(gamma); 481 setRedGamma(gamma); 482 setGrnGamma(gamma); 483 setBluGamma(gamma); 484 redGammaTxtFld.setText(Float.toString((float)gamma)); 485 grnGammaTxtFld.setText(Float.toString((float)gamma)); 486 bluGammaTxtFld.setText(Float.toString((float)gamma)); 487 488 float[][] newRedTbl = getZeroOutArray(redTable); 489 float[][] newGrnTbl = getZeroOutArray(grnTable); 490 float[][] newBluTbl = getZeroOutArray(bluTable); 491 492 for (int k=0; k<redTable[0].length; k++) { 493 newRedTbl[0][k] = (float) Math.pow(redTable[0][k], gamma); 494 newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], gamma); 495 newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], gamma); 496 } 497 try { 498 displayMaster.setDisplayInactive(); 499 ((BaseColorControl)redMap.getControl()).setTable(newRedTbl); 500 ((BaseColorControl)grnMap.getControl()).setTable(newGrnTbl); 501 ((BaseColorControl)bluMap.getControl()).setTable(newBluTbl); 502 displayMaster.setDisplayActive(); 503 } catch (Exception ex) { 504 LogUtil.logException("setDisplayInactive", ex); 505 } 506 } 507 508 private void updateRedGamma(double gamma) { 509 setRedGamma(gamma); 510 511 float[][] newRedTbl = getZeroOutArray(redTable); 512 513 for (int k=0; k<redTable[0].length; k++) { 514 newRedTbl[0][k] = (float) Math.pow(redTable[0][k], gamma); 515 } 516 517 try { 518 displayMaster.setDisplayInactive(); 519 ((BaseColorControl)redMap.getControl()).setTable(newRedTbl); 520 displayMaster.setDisplayActive(); 521 } catch (Exception ex) { 522 LogUtil.logException("setDisplayInactive", ex); 523 } 524 } 525 526 private void updateGrnGamma(double gamma) { 527 setGrnGamma(gamma); 528 529 float[][] newGrnTbl = getZeroOutArray(grnTable); 530 for (int k=0; k<grnTable[0].length; k++) { 531 newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], gamma); 532 } 533 534 try { 535 displayMaster.setDisplayInactive(); 536 ((BaseColorControl)grnMap.getControl()).setTable(newGrnTbl); 537 displayMaster.setDisplayActive(); 538 } catch (Exception ex) { 539 LogUtil.logException("setDisplayInactive", ex); 540 } 541 } 542 543 private void updateBluGamma(double gamma) { 544 setBluGamma(gamma); 545 546 float[][] newBluTbl = getZeroOutArray(bluTable); 547 for (int k=0; k<bluTable[0].length; k++) { 548 newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], gamma); 549 } 550 551 try { 552 displayMaster.setDisplayInactive(); 553 ((BaseColorControl)bluMap.getControl()).setTable(newBluTbl); 554 displayMaster.setDisplayActive(); 555 } catch (Exception ex) { 556 LogUtil.logException("setDisplayInactive", ex); 557 } 558 } 559 560 public float[][] getZeroOutArray(float[][] array) { 561 float[][] newArray = new float[array.length][array[0].length]; 562 for (int i=0; i<newArray.length; i++) { 563 for (int j=0; j<newArray[0].length; j++) { 564 newArray[i][j] = 0.0f; 565 } 566 } 567 return newArray; 568 } 569 570 protected ColorTable getInitialColorTable() { 571 return getDisplayConventions().getParamColorTable("image"); 572 } 573 574 void setAllFields(String txtl1, String txtl2) { 575 Double l1 = Double.valueOf(txtl1.trim()); 576 Double l2 = Double.valueOf(txtl2.trim()); 577 bluRange[0] = l1; 578 bluRange[1] = l2; 579 redRange[0] = l1; 580 redRange[1] = l2; 581 grnRange[0] = l1; 582 grnRange[1] = l2; 583 updateRedRange(redRange[0], redRange[1]); 584 updateBluRange(redRange[0], redRange[1]); 585 updateGrnRange(redRange[0], redRange[1]); 586 587 redLowTxtFld.setText(txtl1); 588 grnLowTxtFld.setText(txtl1); 589 bluLowTxtFld.setText(txtl1); 590 591 redHighTxtFld.setText(txtl2); 592 bluHighTxtFld.setText(txtl2); 593 grnHighTxtFld.setText(txtl2); 594 } 595 596 public Container doMakeContents() { 597 598 JButton allGammaButton = new JButton("Apply to All Gamma Fields"); 599 allGammaButton.addActionListener(e -> { 600 String tmp = gammaTxtFld.getText().trim(); 601 updateGamma(Double.valueOf(tmp)); 602 }); 603 604 gammaTxtFld.addActionListener(e -> { 605 String tmp = gammaTxtFld.getText().trim(); 606 updateGamma(Double.valueOf(tmp)); 607 }); 608 609 // McIDAS Inquiry #3193-3141 610 redLowTxtFld.addActionListener(e -> { 611 if (matchFieldsCbox.isSelected()) 612 setAllFields(redLowTxtFld.getText(),redHighTxtFld.getText()); 613 614 Double l1 = Double.valueOf(redLowTxtFld.getText().trim()); 615 Double l2 = Double.valueOf(redHighTxtFld.getText().trim()); 616 redRange[0] = l1; 617 redRange[1] = l2; 618 updateRedRange(redRange[0], redRange[1]); 619 620 }); 621 622 redHighTxtFld.addActionListener(e -> { 623 if (matchFieldsCbox.isSelected()) 624 setAllFields(redLowTxtFld.getText(),redHighTxtFld.getText()); 625 626 Double l1 = Double.valueOf(redLowTxtFld.getText().trim()); 627 Double l2 = Double.valueOf(redHighTxtFld.getText().trim()); 628 redRange[0] = l1; 629 redRange[1] = l2; 630 updateRedRange(redRange[0], redRange[1]); 631 }); 632 633 redGammaTxtFld.addActionListener(e -> { 634 String tmp = redGammaTxtFld.getText().trim(); 635 updateRedGamma(Double.valueOf(tmp)); 636 637 if (matchFieldsCbox.isSelected()) { 638 grnGammaTxtFld.setText(tmp); 639 bluGammaTxtFld.setText(tmp); 640 updateBluGamma(Double.valueOf(tmp)); 641 updateGrnGamma(Double.valueOf(tmp)); 642 } 643 }); 644 645 JButton redReset = new JButton("Reset"); 646 redReset.addActionListener(e -> { 647 updateRedRange(initRedRange[0], initRedRange[1]); 648 redRange[0] = initRedRange[0]; 649 redRange[1] = initRedRange[1]; 650 redLowTxtFld.setText(Float.toString((float)redRange[0])); 651 redHighTxtFld.setText(Float.toString((float)redRange[1])); 652 updateRedGamma(1.0); 653 redGammaTxtFld.setText("1.0"); 654 }); 655 656 grnLowTxtFld.addActionListener(e -> { 657 if (matchFieldsCbox.isSelected()) 658 setAllFields(grnLowTxtFld.getText(),grnHighTxtFld.getText()); 659 660 Double l1 = Double.valueOf(grnLowTxtFld.getText().trim()); 661 Double l2 = Double.valueOf(grnHighTxtFld.getText().trim()); 662 grnRange[0] = l1; 663 grnRange[1] = l2; 664 updateGrnRange(grnRange[0], grnRange[1]); 665 }); 666 667 grnHighTxtFld.addActionListener(e -> { 668 if (matchFieldsCbox.isSelected()) 669 setAllFields(grnLowTxtFld.getText(),grnHighTxtFld.getText()); 670 671 Double l1 = Double.valueOf(grnLowTxtFld.getText().trim()); 672 Double l2 = Double.valueOf(grnHighTxtFld.getText().trim()); 673 grnRange[0] = l1; 674 grnRange[1] = l2; 675 updateGrnRange(grnRange[0], grnRange[1]); 676 }); 677 678 grnGammaTxtFld.addActionListener(e -> { 679 String tmp = grnGammaTxtFld.getText().trim(); 680 updateGrnGamma(Double.valueOf(tmp)); 681 682 if (matchFieldsCbox.isSelected()) { 683 redGammaTxtFld.setText(tmp); 684 bluGammaTxtFld.setText(tmp); 685 updateRedGamma(Double.valueOf(tmp)); 686 updateGrnGamma(Double.valueOf(tmp)); 687 } 688 }); 689 690 JButton grnReset = new JButton("Reset"); 691 grnReset.addActionListener(e -> { 692 updateGrnRange(initGrnRange[0], initGrnRange[1]); 693 grnRange[0] = initGrnRange[0]; 694 grnRange[1] = initGrnRange[1]; 695 grnLowTxtFld.setText(Float.toString((float)grnRange[0])); 696 grnHighTxtFld.setText(Float.toString((float)grnRange[1])); 697 updateGrnGamma(1.0); 698 grnGammaTxtFld.setText("1.0"); 699 }); 700 701 bluLowTxtFld.addActionListener(e -> { 702 if (matchFieldsCbox.isSelected()) 703 setAllFields(bluLowTxtFld.getText(),bluHighTxtFld.getText()); 704 705 Double l1 = Double.valueOf(bluLowTxtFld.getText().trim()); 706 Double l2 = Double.valueOf(bluHighTxtFld.getText().trim()); 707 bluRange[0] = l1; 708 bluRange[1] = l2; 709 updateBluRange(bluRange[0], bluRange[1]); 710 }); 711 712 bluHighTxtFld.addActionListener(e -> { 713 if (matchFieldsCbox.isSelected()) 714 setAllFields(bluLowTxtFld.getText(),bluHighTxtFld.getText()); 715 716 Double l1 = Double.valueOf(bluLowTxtFld.getText().trim()); 717 Double l2 = Double.valueOf(bluHighTxtFld.getText().trim()); 718 bluRange[0] = l1; 719 bluRange[1] = l2; 720 updateBluRange(bluRange[0], bluRange[1]); 721 }); 722 723 bluGammaTxtFld.addActionListener(e -> { 724 String tmp = bluGammaTxtFld.getText().trim(); 725 updateBluGamma(Double.valueOf(tmp)); 726 727 if (matchFieldsCbox.isSelected()) { 728 grnGammaTxtFld.setText(tmp); 729 redGammaTxtFld.setText(tmp); 730 updateGrnGamma(Double.valueOf(tmp)); 731 updateRedGamma(Double.valueOf(tmp)); 732 } 733 }); 734 735 JButton bluReset = new JButton("Reset"); 736 bluReset.addActionListener(e -> { 737 updateBluRange(initBluRange[0], initBluRange[1]); 738 bluRange[0] = initBluRange[0]; 739 bluRange[1] = initBluRange[1]; 740 bluLowTxtFld.setText(Float.toString((float)bluRange[0])); 741 bluHighTxtFld.setText(Float.toString((float)bluRange[1])); 742 updateBluGamma(1.0); 743 bluGammaTxtFld.setText("1.0"); 744 }); 745 746 JButton applyButton = new JButton("Apply"); 747 applyButton.addActionListener(e -> { 748 String redLow = redLowTxtFld.getText().trim(); 749 String redHigh = redHighTxtFld.getText().trim(); 750 updateRedRange(Double.valueOf(redLow), Double.valueOf(redHigh)); 751 String grnLow = grnLowTxtFld.getText().trim(); 752 String grnHigh = grnHighTxtFld.getText().trim(); 753 updateGrnRange(Double.valueOf(grnLow), Double.valueOf(grnHigh)); 754 String bluLow = bluLowTxtFld.getText().trim(); 755 String bluHigh = bluHighTxtFld.getText().trim(); 756 updateBluRange(Double.valueOf(bluLow), Double.valueOf(bluHigh)); 757 758 String tmp1 = redGammaTxtFld.getText().trim(); 759 updateRedGamma(Double.valueOf(tmp1)); 760 String tmp2 = grnGammaTxtFld.getText().trim(); 761 updateGrnGamma(Double.valueOf(tmp2)); 762 String tmp3 = bluGammaTxtFld.getText().trim(); 763 updateBluGamma(Double.valueOf(tmp3)); 764 }); 765 766 // McIDAS Inquiry #3193-3141 767 matchFieldsCbox = new JCheckBox(); 768 matchFieldsCbox.setToolTipText("When enabled, changing a setting for one color changes the setting for all colors."); 769 JPanel topPanel = new JPanel(new MigLayout()); 770 topPanel.add(new JLabel("Match fields: ")); 771 topPanel.add(matchFieldsCbox, "wrap"); 772 topPanel.add(new JLabel("Red Range: ")); 773 topPanel.add(redLowTxtFld); 774 topPanel.add(redHighTxtFld); 775 topPanel.add(new JLabel("Red Gamma: ")); 776 topPanel.add(redGammaTxtFld); 777 topPanel.add(redReset, "wrap"); 778 779 topPanel.add(new JLabel("Green Range: ")); 780 topPanel.add(grnLowTxtFld); 781 topPanel.add(grnHighTxtFld); 782 topPanel.add(new JLabel("Green Gamma: ")); 783 topPanel.add(grnGammaTxtFld); 784 topPanel.add(grnReset, "wrap"); 785 786 topPanel.add(new JLabel("Blue Range: ")); 787 topPanel.add(bluLowTxtFld); 788 topPanel.add(bluHighTxtFld); 789 topPanel.add(new JLabel("Blue Gamma: ")); 790 topPanel.add(bluGammaTxtFld); 791 topPanel.add(bluReset, "wrap"); 792 793 topPanel.add(Box.createHorizontalStrut(2), "span 5"); 794 topPanel.add(applyButton, "wrap"); 795 796 JPanel bottomPanel = new JPanel(new MigLayout()); 797 bottomPanel.add(new JLabel("Common Gamma: ")); 798 bottomPanel.add(gammaTxtFld); 799 bottomPanel.add(allGammaButton, "wrap"); 800 bottomPanel.add(new JLabel("Vertical Position: ")); 801 bottomPanel.add(doMakeZPositionSlider()); 802 803 JPanel mainPanel = new JPanel(new MigLayout("wrap 1", "[grow]", "")); 804 mainPanel.add(topPanel, "growx"); 805 mainPanel.add(bottomPanel, "growx"); 806 807 return mainPanel; 808 } 809 810 private class ColorMapListener implements ScalarMapListener { 811 ScalarMap clrMap; 812 813 double[] range = null; 814 double[] initRange = null; 815 816 JTextField lowTxtFld; 817 JTextField highTxtFld; 818 819 ColorMapListener(ScalarMap clrMap, double[] initRange, double[] range, JTextField lowTxtFld, JTextField highTxtFld) { 820 this.clrMap = clrMap; 821 this.lowTxtFld = lowTxtFld; 822 this.highTxtFld = highTxtFld; 823 this.range = range; 824 this.initRange = initRange; 825 } 826 827 public void controlChanged(ScalarMapControlEvent event) throws RemoteException, VisADException { 828 } 829 830 @Override 831 public void mapChanged(ScalarMapEvent event) throws RemoteException, VisADException { 832 if (event.getId() == ScalarMapEvent.AUTO_SCALE) { 833 double[] rng = clrMap.getRange(); 834 boolean shouldRemove = false; 835 //Ghansham: decide whether it is first time. The cleaner way 836 if (!Double.isNaN(rng[0]) && !Double.isNaN(rng[1]) && Double.isNaN(initRange[0]) && Double.isNaN(initRange[1])) { 837 shouldRemove = true; 838 } 839 range[0] = rng[0]; 840 range[1] = rng[1]; 841 initRange[0] = rng[0]; 842 initRange[1] = rng[1]; 843 lowTxtFld.setText(Float.toString((float)rng[0])); 844 highTxtFld.setText(Float.toString((float)rng[1])); 845 //Ghansham:If its first time remove the scalarmaplistener and setRange manually to disable autscaling of the scalarmap 846 if (shouldRemove) { 847 clrMap.removeScalarMapListener(this); 848 //-Lock out auto-scaling 849 clrMap.disableAutoScale(); 850 } 851 } else if (event.getId() == ScalarMapEvent.MANUAL) { 852 double[] rng = clrMap.getRange(); 853 range[0] = rng[0]; 854 range[1] = rng[1]; 855 } 856 } 857 } 858}